svn commit: r199667 - head/sys/dev/bge
Pyun YongHyeon
yongari at FreeBSD.org
Sun Nov 22 20:02:13 UTC 2009
Author: yongari
Date: Sun Nov 22 20:02:13 2009
New Revision: 199667
URL: http://svn.freebsd.org/changeset/base/199667
Log:
Cache Rx producer/Tx consumer index as soon as we know status block
update and then clear status block. Previously it used to access
these index without synchronization which may cause problems when
bounce buffers are used. Also add missing bus_dmamap_sync(9) in
polling handler. Since we now update status block in driver, adjust
bus_dmamap_sync(9) for status block.
Modified:
head/sys/dev/bge/if_bge.c
Modified: head/sys/dev/bge/if_bge.c
==============================================================================
--- head/sys/dev/bge/if_bge.c Sun Nov 22 19:44:11 2009 (r199666)
+++ head/sys/dev/bge/if_bge.c Sun Nov 22 20:02:13 2009 (r199667)
@@ -361,8 +361,8 @@ static int bge_get_eaddr_nvram(struct bg
static int bge_get_eaddr_eeprom(struct bge_softc *, uint8_t[]);
static int bge_get_eaddr(struct bge_softc *, uint8_t[]);
-static void bge_txeof(struct bge_softc *);
-static int bge_rxeof(struct bge_softc *);
+static void bge_txeof(struct bge_softc *, uint16_t);
+static int bge_rxeof(struct bge_softc *, uint16_t);
static void bge_asf_driver_up (struct bge_softc *);
static void bge_tick(void *);
@@ -3135,15 +3135,14 @@ bge_reset(struct bge_softc *sc)
*/
static int
-bge_rxeof(struct bge_softc *sc)
+bge_rxeof(struct bge_softc *sc, uint16_t rx_prod)
{
struct ifnet *ifp;
int rx_npkts = 0, stdcnt = 0, jumbocnt = 0;
- uint16_t rx_prod, rx_cons;
+ uint16_t rx_cons;
BGE_LOCK_ASSERT(sc);
rx_cons = sc->bge_rx_saved_considx;
- rx_prod = sc->bge_ldata.bge_status_block->bge_idx[0].bge_rx_prod_idx;
/* Nothing to do. */
if (rx_cons == rx_prod)
@@ -3296,7 +3295,7 @@ bge_rxeof(struct bge_softc *sc)
}
static void
-bge_txeof(struct bge_softc *sc)
+bge_txeof(struct bge_softc *sc, uint16_t tx_cons)
{
struct bge_tx_bd *cur_tx = NULL;
struct ifnet *ifp;
@@ -3304,8 +3303,7 @@ bge_txeof(struct bge_softc *sc)
BGE_LOCK_ASSERT(sc);
/* Nothing to do. */
- if (sc->bge_tx_saved_considx ==
- sc->bge_ldata.bge_status_block->bge_idx[0].bge_tx_cons_idx)
+ if (sc->bge_tx_saved_considx == tx_cons)
return;
ifp = sc->bge_ifp;
@@ -3316,8 +3314,7 @@ bge_txeof(struct bge_softc *sc)
* Go through our tx ring and free mbufs for those
* frames that have been sent.
*/
- while (sc->bge_tx_saved_considx !=
- sc->bge_ldata.bge_status_block->bge_idx[0].bge_tx_cons_idx) {
+ while (sc->bge_tx_saved_considx != tx_cons) {
uint32_t idx = 0;
idx = sc->bge_tx_saved_considx;
@@ -3348,6 +3345,7 @@ static int
bge_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
{
struct bge_softc *sc = ifp->if_softc;
+ uint16_t rx_prod, tx_cons;
uint32_t statusword;
int rx_npkts = 0;
@@ -3358,13 +3356,17 @@ bge_poll(struct ifnet *ifp, enum poll_cm
}
bus_dmamap_sync(sc->bge_cdata.bge_status_tag,
- sc->bge_cdata.bge_status_map, BUS_DMASYNC_POSTREAD);
+ sc->bge_cdata.bge_status_map,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ rx_prod = sc->bge_ldata.bge_status_block->bge_idx[0].bge_rx_prod_idx;
+ tx_cons = sc->bge_ldata.bge_status_block->bge_idx[0].bge_tx_cons_idx;
statusword = atomic_readandclear_32(
&sc->bge_ldata.bge_status_block->bge_status);
bus_dmamap_sync(sc->bge_cdata.bge_status_tag,
- sc->bge_cdata.bge_status_map, BUS_DMASYNC_PREREAD);
+ sc->bge_cdata.bge_status_map,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
/* Note link event. It will be processed by POLL_AND_CHECK_STATUS. */
if (statusword & BGE_STATFLAG_LINKSTATE_CHANGED)
@@ -3377,12 +3379,12 @@ bge_poll(struct ifnet *ifp, enum poll_cm
bge_link_upd(sc);
sc->rxcycles = count;
- rx_npkts = bge_rxeof(sc);
+ rx_npkts = bge_rxeof(sc, rx_prod);
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
BGE_UNLOCK(sc);
return (rx_npkts);
}
- bge_txeof(sc);
+ bge_txeof(sc, tx_cons);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
bge_start_locked(ifp);
@@ -3397,6 +3399,7 @@ bge_intr(void *xsc)
struct bge_softc *sc;
struct ifnet *ifp;
uint32_t statusword;
+ uint16_t rx_prod, tx_cons;
sc = xsc;
@@ -3440,7 +3443,14 @@ bge_intr(void *xsc)
/* Make sure the descriptor ring indexes are coherent. */
bus_dmamap_sync(sc->bge_cdata.bge_status_tag,
- sc->bge_cdata.bge_status_map, BUS_DMASYNC_POSTREAD);
+ sc->bge_cdata.bge_status_map,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ rx_prod = sc->bge_ldata.bge_status_block->bge_idx[0].bge_rx_prod_idx;
+ tx_cons = sc->bge_ldata.bge_status_block->bge_idx[0].bge_tx_cons_idx;
+ sc->bge_ldata.bge_status_block->bge_status = 0;
+ bus_dmamap_sync(sc->bge_cdata.bge_status_tag,
+ sc->bge_cdata.bge_status_map,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
if ((sc->bge_asicrev == BGE_ASICREV_BCM5700 &&
sc->bge_chipid != BGE_CHIPID_BCM5700_B2) ||
@@ -3449,21 +3459,18 @@ bge_intr(void *xsc)
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
/* Check RX return ring producer/consumer. */
- bge_rxeof(sc);
+ bge_rxeof(sc, rx_prod);
}
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
/* Check TX ring producer/consumer. */
- bge_txeof(sc);
+ bge_txeof(sc, tx_cons);
}
if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
bge_start_locked(ifp);
- bus_dmamap_sync(sc->bge_cdata.bge_status_tag,
- sc->bge_cdata.bge_status_map, BUS_DMASYNC_PREREAD);
-
BGE_UNLOCK(sc);
}
More information about the svn-src-head
mailing list