diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2017-04-04 09:36:57 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2017-04-04 14:46:23 +0200 |
commit | de8a76da2f374792594ce03a203b3f30e4889f6f (patch) | |
tree | 12b5e1e59358005c3c522955c08aee4795e4829c /freebsd/sys/dev/tsec | |
parent | Enable bridging by default (diff) | |
download | rtems-libbsd-de8a76da2f374792594ce03a203b3f30e4889f6f.tar.bz2 |
Update to FreeBSD head 2017-04-04
Git mirror commit 642b174daddbd0efd9bb5f242c43f4ab4db6869f.
Diffstat (limited to 'freebsd/sys/dev/tsec')
-rw-r--r-- | freebsd/sys/dev/tsec/if_tsec.c | 311 | ||||
-rw-r--r-- | freebsd/sys/dev/tsec/if_tsec.h | 118 |
2 files changed, 174 insertions, 255 deletions
diff --git a/freebsd/sys/dev/tsec/if_tsec.c b/freebsd/sys/dev/tsec/if_tsec.c index 5b94af9c..25802db0 100644 --- a/freebsd/sys/dev/tsec/if_tsec.c +++ b/freebsd/sys/dev/tsec/if_tsec.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include <rtems/bsd/sys/param.h> #include <sys/systm.h> #include <sys/bus.h> +#include <sys/bus_dma.h> #include <sys/endian.h> #include <sys/mbuf.h> #include <sys/kernel.h> @@ -73,8 +74,8 @@ static int tsec_alloc_dma_desc(device_t dev, bus_dma_tag_t *dtag, bus_dmamap_t *dmap, bus_size_t dsize, void **vaddr, void *raddr, const char *dname); static void tsec_dma_ctl(struct tsec_softc *sc, int state); -static int tsec_encap(struct tsec_softc *sc, struct mbuf *m_head, - int fcb_inserted); +static void tsec_encap(struct ifnet *ifp, struct tsec_softc *sc, + struct mbuf *m0, uint16_t fcb_flags, int *start_tx); static void tsec_free_dma(struct tsec_softc *sc); static void tsec_free_dma_desc(bus_dma_tag_t dtag, bus_dmamap_t dmap, void *vaddr); static int tsec_ifmedia_upd(struct ifnet *ifp); @@ -123,8 +124,6 @@ tsec_attach(struct tsec_softc *sc) { uint8_t hwaddr[ETHER_ADDR_LEN]; struct ifnet *ifp; - bus_dmamap_t *map_ptr; - bus_dmamap_t **map_pptr; int error = 0; int i; @@ -181,7 +180,7 @@ tsec_attach(struct tsec_softc *sc) BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filtfunc, filtfuncarg */ MCLBYTES * (TSEC_TX_NUM_DESC - 1), /* maxsize */ - TSEC_TX_NUM_DESC - 1, /* nsegments */ + TSEC_TX_MAX_DMA_SEGS, /* nsegments */ MCLBYTES, 0, /* maxsegsz, flags */ NULL, NULL, /* lockfunc, lockfuncarg */ &sc->tsec_tx_mtag); /* dmat */ @@ -211,17 +210,15 @@ tsec_attach(struct tsec_softc *sc) } /* Create TX busdma maps */ - map_ptr = sc->tx_map_data; - map_pptr = sc->tx_map_unused_data; - for (i = 0; i < TSEC_TX_NUM_DESC; i++) { - map_pptr[i] = &map_ptr[i]; - error = bus_dmamap_create(sc->tsec_tx_mtag, 0, map_pptr[i]); + error = bus_dmamap_create(sc->tsec_tx_mtag, 0, + &sc->tx_bufmap[i].map); if (error) { device_printf(sc->dev, "failed to init TX ring\n"); tsec_detach(sc); return (ENXIO); } + sc->tx_bufmap[i].map_initialized = 1; } /* Create RX busdma maps and zero mbuf handlers */ @@ -370,13 +367,33 @@ tsec_init(void *xsc) TSEC_GLOBAL_UNLOCK(sc); } +static int +tsec_mii_wait(struct tsec_softc *sc, uint32_t flags) +{ + int timeout; + + /* + * The status indicators are not set immediatly after a command. + * Discard the first value. + */ + TSEC_PHY_READ(sc, TSEC_REG_MIIMIND); + + timeout = TSEC_READ_RETRY; + while ((TSEC_PHY_READ(sc, TSEC_REG_MIIMIND) & flags) && --timeout) + DELAY(TSEC_READ_DELAY); + + return (timeout == 0); +} + + static void tsec_init_locked(struct tsec_softc *sc) { struct tsec_desc *tx_desc = sc->tsec_tx_vaddr; struct tsec_desc *rx_desc = sc->tsec_rx_vaddr; struct ifnet *ifp = sc->tsec_ifp; - uint32_t timeout, val, i; + uint32_t val, i; + int timeout; if (ifp->if_drv_flags & IFF_DRV_RUNNING) return; @@ -435,15 +452,13 @@ tsec_init_locked(struct tsec_softc *sc) TSEC_PHY_WRITE(sc, TSEC_REG_MIIMCFG, TSEC_MIIMCFG_CLKDIV28); /* Step 8: Read MII Mgmt indicator register and check for Busy = 0 */ - timeout = TSEC_READ_RETRY; - while (--timeout && (TSEC_PHY_READ(sc, TSEC_REG_MIIMIND) & - TSEC_MIIMIND_BUSY)) - DELAY(TSEC_READ_DELAY); - if (timeout == 0) { + timeout = tsec_mii_wait(sc, TSEC_MIIMIND_BUSY); + + TSEC_PHY_UNLOCK(sc); + if (timeout) { if_printf(ifp, "tsec_init_locked(): Mgmt busy timeout\n"); return; } - TSEC_PHY_UNLOCK(sc); /* Step 9: Setup the MII Mgmt */ #ifdef __rtems__ @@ -724,124 +739,135 @@ static void tsec_start_locked(struct ifnet *ifp) { struct tsec_softc *sc; - struct mbuf *m0, *mtmp; + struct mbuf *m0; struct tsec_tx_fcb *tx_fcb; - unsigned int queued = 0; - int csum_flags, fcb_inserted = 0; + int csum_flags; + int start_tx; + uint16_t fcb_flags; sc = ifp->if_softc; + start_tx = 0; TSEC_TRANSMIT_LOCK_ASSERT(sc); - if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != - IFF_DRV_RUNNING) - return; - if (sc->tsec_link == 0) return; bus_dmamap_sync(sc->tsec_tx_dtag, sc->tsec_tx_dmap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { + for (;;) { + + if (TSEC_FREE_TX_DESC(sc) < TSEC_TX_MAX_DMA_SEGS) { + /* No free descriptors */ + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + break; + } + /* Get packet from the queue */ IFQ_DRV_DEQUEUE(&ifp->if_snd, m0); if (m0 == NULL) break; /* Insert TCP/IP Off-load frame control block */ + fcb_flags = 0; csum_flags = m0->m_pkthdr.csum_flags; if (csum_flags) { - M_PREPEND(m0, sizeof(struct tsec_tx_fcb), M_NOWAIT); if (m0 == NULL) break; - tx_fcb = mtod(m0, struct tsec_tx_fcb *); - tx_fcb->flags = 0; - tx_fcb->l3_offset = ETHER_HDR_LEN; - tx_fcb->l4_offset = sizeof(struct ip); - if (csum_flags & CSUM_IP) - tx_fcb->flags |= TSEC_TX_FCB_IP4 | + fcb_flags |= TSEC_TX_FCB_IP4 | TSEC_TX_FCB_CSUM_IP; if (csum_flags & CSUM_TCP) - tx_fcb->flags |= TSEC_TX_FCB_TCP | + fcb_flags |= TSEC_TX_FCB_TCP | TSEC_TX_FCB_CSUM_TCP_UDP; if (csum_flags & CSUM_UDP) - tx_fcb->flags |= TSEC_TX_FCB_UDP | + fcb_flags |= TSEC_TX_FCB_UDP | TSEC_TX_FCB_CSUM_TCP_UDP; - fcb_inserted = 1; + tx_fcb = mtod(m0, struct tsec_tx_fcb *); + tx_fcb->flags = fcb_flags; + tx_fcb->l3_offset = ETHER_HDR_LEN; + tx_fcb->l4_offset = sizeof(struct ip); } - mtmp = m_defrag(m0, M_NOWAIT); - if (mtmp) - m0 = mtmp; - - if (tsec_encap(sc, m0, fcb_inserted)) { - IFQ_DRV_PREPEND(&ifp->if_snd, m0); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - break; - } - queued++; - BPF_MTAP(ifp, m0); + tsec_encap(ifp, sc, m0, fcb_flags, &start_tx); } bus_dmamap_sync(sc->tsec_tx_dtag, sc->tsec_tx_dmap, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - if (queued) { + if (start_tx) { /* Enable transmitter and watchdog timer */ TSEC_WRITE(sc, TSEC_REG_TSTAT, TSEC_TSTAT_THLT); sc->tsec_watchdog = 5; } } -static int -tsec_encap(struct tsec_softc *sc, struct mbuf *m0, int fcb_inserted) +static void +tsec_encap(struct ifnet *ifp, struct tsec_softc *sc, struct mbuf *m0, + uint16_t fcb_flags, int *start_tx) { - struct tsec_desc *tx_desc = NULL; - struct ifnet *ifp; - bus_dma_segment_t segs[TSEC_TX_NUM_DESC]; - bus_dmamap_t *mapp; - int csum_flag = 0, error, seg, nsegs; + bus_dma_segment_t segs[TSEC_TX_MAX_DMA_SEGS]; + int error, i, nsegs; + struct tsec_bufmap *tx_bufmap; + uint32_t tx_idx; + uint16_t flags; TSEC_TRANSMIT_LOCK_ASSERT(sc); - ifp = sc->tsec_ifp; - - if (TSEC_FREE_TX_DESC(sc) == 0) { - /* No free descriptors */ - return (-1); - } - - /* Fetch unused map */ - mapp = TSEC_ALLOC_TX_MAP(sc); - + tx_idx = sc->tx_idx_head; + tx_bufmap = &sc->tx_bufmap[tx_idx]; + /* Create mapping in DMA memory */ - error = bus_dmamap_load_mbuf_sg(sc->tsec_tx_mtag, - *mapp, m0, segs, &nsegs, BUS_DMA_NOWAIT); - if (error != 0 || nsegs > TSEC_FREE_TX_DESC(sc) || nsegs <= 0) { - bus_dmamap_unload(sc->tsec_tx_mtag, *mapp); - TSEC_FREE_TX_MAP(sc, mapp); - return ((error != 0) ? error : -1); + error = bus_dmamap_load_mbuf_sg(sc->tsec_tx_mtag, tx_bufmap->map, m0, + segs, &nsegs, BUS_DMA_NOWAIT); + if (error == EFBIG) { + /* Too many segments! Defrag and try again. */ + struct mbuf *m = m_defrag(m0, M_NOWAIT); + + if (m == NULL) { + m_freem(m0); + return; + } + m0 = m; + error = bus_dmamap_load_mbuf_sg(sc->tsec_tx_mtag, + tx_bufmap->map, m0, segs, &nsegs, BUS_DMA_NOWAIT); + } + if (error != 0) { + /* Give up. */ + m_freem(m0); + return; } - bus_dmamap_sync(sc->tsec_tx_mtag, *mapp, BUS_DMASYNC_PREWRITE); - - if ((ifp->if_flags & IFF_DEBUG) && (nsegs > 1)) - if_printf(ifp, "TX buffer has %d segments\n", nsegs); - - if (fcb_inserted) - csum_flag = TSEC_TXBD_TOE; - - /* Everything is ok, now we can send buffers */ - for (seg = 0; seg < nsegs; seg++) { - tx_desc = TSEC_GET_CUR_TX_DESC(sc); - tx_desc->length = segs[seg].ds_len; - tx_desc->bufptr = segs[seg].ds_addr; + bus_dmamap_sync(sc->tsec_tx_mtag, tx_bufmap->map, + BUS_DMASYNC_PREWRITE); + tx_bufmap->mbuf = m0; + + /* + * Fill in the TX descriptors back to front so that READY bit in first + * descriptor is set last. + */ + tx_idx = (tx_idx + (uint32_t)nsegs) & (TSEC_TX_NUM_DESC - 1); + sc->tx_idx_head = tx_idx; + flags = TSEC_TXBD_L | TSEC_TXBD_I | TSEC_TXBD_R | TSEC_TXBD_TC; + for (i = nsegs - 1; i >= 0; i--) { + struct tsec_desc *tx_desc; + + tx_idx = (tx_idx - 1) & (TSEC_TX_NUM_DESC - 1); + tx_desc = &sc->tsec_tx_vaddr[tx_idx]; + tx_desc->length = segs[i].ds_len; + tx_desc->bufptr = segs[i].ds_addr; + + if (i == 0) { + wmb(); + + if (fcb_flags != 0) + flags |= TSEC_TXBD_TOE; + } /* * Set flags: @@ -851,17 +877,14 @@ tsec_encap(struct tsec_softc *sc, struct mbuf *m0, int fcb_inserted) * - transmit the CRC sequence after the last data byte * - interrupt after the last buffer */ - tx_desc->flags = - (tx_desc->flags & TSEC_TXBD_W) | - ((seg == 0) ? csum_flag : 0) | TSEC_TXBD_R | TSEC_TXBD_TC | - ((seg == nsegs - 1) ? TSEC_TXBD_L | TSEC_TXBD_I : 0); - } + tx_desc->flags = (tx_idx == (TSEC_TX_NUM_DESC - 1) ? + TSEC_TXBD_W : 0) | flags; - /* Save mbuf and DMA mapping for release at later stage */ - TSEC_PUT_TX_MBUF(sc, m0); - TSEC_PUT_TX_MAP(sc, mapp); + flags &= ~(TSEC_TXBD_L | TSEC_TXBD_I); + } - return (0); + BPF_MTAP(ifp, m0); + *start_tx = 1; } static void @@ -925,11 +948,8 @@ tsec_ioctl(struct ifnet *ifp, u_long command, caddr_t data) { struct tsec_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *)data; - device_t dev; int mask, error = 0; - dev = sc->dev; - switch (command) { case SIOCSIFMTU: TSEC_GLOBAL_LOCK(sc); @@ -1188,9 +1208,9 @@ tsec_free_dma(struct tsec_softc *sc) /* Free TX maps */ for (i = 0; i < TSEC_TX_NUM_DESC; i++) - if (sc->tx_map_data[i] != NULL) + if (sc->tx_bufmap[i].map_initialized) bus_dmamap_destroy(sc->tsec_tx_mtag, - sc->tx_map_data[i]); + sc->tx_bufmap[i].map); /* Destroy tag for TX mbufs */ bus_dma_tag_destroy(sc->tsec_tx_mtag); @@ -1225,8 +1245,6 @@ static void tsec_stop(struct tsec_softc *sc) { struct ifnet *ifp; - struct mbuf *m0; - bus_dmamap_t *mapp; uint32_t tmpval; TSEC_GLOBAL_LOCK_ASSERT(sc); @@ -1243,16 +1261,15 @@ tsec_stop(struct tsec_softc *sc) tsec_dma_ctl(sc, 0); /* Remove pending data from TX queue */ - while (!TSEC_EMPTYQ_TX_MBUF(sc)) { - m0 = TSEC_GET_TX_MBUF(sc); - mapp = TSEC_GET_TX_MAP(sc); - - bus_dmamap_sync(sc->tsec_tx_mtag, *mapp, + while (sc->tx_idx_tail != sc->tx_idx_head) { + bus_dmamap_sync(sc->tsec_tx_mtag, + sc->tx_bufmap[sc->tx_idx_tail].map, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->tsec_tx_mtag, *mapp); - - TSEC_FREE_TX_MAP(sc, mapp); - m_freem(m0); + bus_dmamap_unload(sc->tsec_tx_mtag, + sc->tx_bufmap[sc->tx_idx_tail].map); + m_freem(sc->tx_bufmap[sc->tx_idx_tail].mbuf); + sc->tx_idx_tail = (sc->tx_idx_tail + 1) + & (TSEC_TX_NUM_DESC - 1); } /* Disable RX and TX */ @@ -1304,7 +1321,6 @@ tsec_receive_intr_locked(struct tsec_softc *sc, int count) struct ifnet *ifp; struct rx_data_type *rx_data; struct mbuf *m; - device_t dev; uint32_t i; int c, rx_npkts; uint16_t flags; @@ -1313,7 +1329,6 @@ tsec_receive_intr_locked(struct tsec_softc *sc, int count) ifp = sc->tsec_ifp; rx_data = sc->rx_data; - dev = sc->dev; rx_npkts = 0; bus_dmamap_sync(sc->tsec_rx_dtag, sc->tsec_rx_dmap, @@ -1381,7 +1396,7 @@ tsec_receive_intr_locked(struct tsec_softc *sc, int count) if (tsec_new_rxbuf(sc->tsec_rx_mtag, rx_data[i].map, &rx_data[i].mbuf, &rx_data[i].paddr)) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); /* * We ran out of mbufs; didn't consume current * descriptor and have to return it to the queue. @@ -1451,11 +1466,8 @@ tsec_receive_intr(void *arg) static void tsec_transmit_intr_locked(struct tsec_softc *sc) { - struct tsec_desc *tx_desc; struct ifnet *ifp; - struct mbuf *m0; - bus_dmamap_t *mapp; - int send = 0; + uint32_t tx_idx; TSEC_TRANSMIT_LOCK_ASSERT(sc); @@ -1474,44 +1486,41 @@ tsec_transmit_intr_locked(struct tsec_softc *sc) bus_dmamap_sync(sc->tsec_tx_dtag, sc->tsec_tx_dmap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - while (TSEC_CUR_DIFF_DIRTY_TX_DESC(sc)) { - tx_desc = TSEC_GET_DIRTY_TX_DESC(sc); + tx_idx = sc->tx_idx_tail; + while (tx_idx != sc->tx_idx_head) { + struct tsec_desc *tx_desc; + struct tsec_bufmap *tx_bufmap; + + tx_desc = &sc->tsec_tx_vaddr[tx_idx]; if (tx_desc->flags & TSEC_TXBD_R) { - TSEC_BACK_DIRTY_TX_DESC(sc); break; } - if ((tx_desc->flags & TSEC_TXBD_L) == 0) + tx_bufmap = &sc->tx_bufmap[tx_idx]; + tx_idx = (tx_idx + 1) & (TSEC_TX_NUM_DESC - 1); + if (tx_bufmap->mbuf == NULL) continue; /* * This is the last buf in this packet, so unmap and free it. */ - m0 = TSEC_GET_TX_MBUF(sc); - mapp = TSEC_GET_TX_MAP(sc); - - bus_dmamap_sync(sc->tsec_tx_mtag, *mapp, + bus_dmamap_sync(sc->tsec_tx_mtag, tx_bufmap->map, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->tsec_tx_mtag, *mapp); - - TSEC_FREE_TX_MAP(sc, mapp); - m_freem(m0); + bus_dmamap_unload(sc->tsec_tx_mtag, tx_bufmap->map); + m_freem(tx_bufmap->mbuf); + tx_bufmap->mbuf = NULL; if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); - send = 1; } + sc->tx_idx_tail = tx_idx; bus_dmamap_sync(sc->tsec_tx_dtag, sc->tsec_tx_dmap, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - if (send) { - /* Now send anything that was pending */ - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - tsec_start_locked(ifp); + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + tsec_start_locked(ifp); - /* Stop wathdog if all sent */ - if (TSEC_EMPTYQ_TX_MBUF(sc)) - sc->tsec_watchdog = 0; - } + if (sc->tx_idx_tail == sc->tx_idx_head) + sc->tsec_watchdog = 0; } void @@ -1562,13 +1571,9 @@ tsec_error_intr_locked(struct tsec_softc *sc, int count) TSEC_WRITE(sc, TSEC_REG_TSTAT, TSEC_TSTAT_THLT); } - /* Check receiver errors */ + /* Check for discarded frame due to a lack of buffers */ if (eflags & TSEC_IEVENT_BSY) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); - - /* Get data from RX buffers */ - tsec_receive_intr_locked(sc, count); } if (ifp->if_flags & IFF_DEBUG) @@ -1602,7 +1607,7 @@ int tsec_miibus_readreg(device_t dev, int phy, int reg) { struct tsec_softc *sc; - uint32_t timeout; + int timeout; int rv; sc = device_get_softc(dev); @@ -1612,17 +1617,13 @@ tsec_miibus_readreg(device_t dev, int phy, int reg) TSEC_PHY_WRITE(sc, TSEC_REG_MIIMCOM, 0); TSEC_PHY_WRITE(sc, TSEC_REG_MIIMCOM, TSEC_MIIMCOM_READCYCLE); - timeout = TSEC_READ_RETRY; - while (--timeout && TSEC_PHY_READ(sc, TSEC_REG_MIIMIND) & - (TSEC_MIIMIND_NOTVALID | TSEC_MIIMIND_BUSY)) - DELAY(TSEC_READ_DELAY); - - if (timeout == 0) - device_printf(dev, "Timeout while reading from PHY!\n"); - + timeout = tsec_mii_wait(sc, TSEC_MIIMIND_NOTVALID | TSEC_MIIMIND_BUSY); rv = TSEC_PHY_READ(sc, TSEC_REG_MIIMSTAT); TSEC_PHY_UNLOCK(); + if (timeout) + device_printf(dev, "Timeout while reading from PHY!\n"); + return (rv); } @@ -1630,21 +1631,17 @@ int tsec_miibus_writereg(device_t dev, int phy, int reg, int value) { struct tsec_softc *sc; - uint32_t timeout; + int timeout; sc = device_get_softc(dev); TSEC_PHY_LOCK(); TSEC_PHY_WRITE(sc, TSEC_REG_MIIMADD, (phy << 8) | reg); TSEC_PHY_WRITE(sc, TSEC_REG_MIIMCON, value); - - timeout = TSEC_READ_RETRY; - while (--timeout && (TSEC_READ(sc, TSEC_REG_MIIMIND) & - TSEC_MIIMIND_BUSY)) - DELAY(TSEC_READ_DELAY); + timeout = tsec_mii_wait(sc, TSEC_MIIMIND_BUSY); TSEC_PHY_UNLOCK(); - if (timeout == 0) + if (timeout) device_printf(dev, "Timeout while writing to PHY!\n"); return (0); diff --git a/freebsd/sys/dev/tsec/if_tsec.h b/freebsd/sys/dev/tsec/if_tsec.h index d13f4639..c8dca3bf 100644 --- a/freebsd/sys/dev/tsec/if_tsec.h +++ b/freebsd/sys/dev/tsec/if_tsec.h @@ -32,6 +32,7 @@ #define TSEC_RX_NUM_DESC 256 #define TSEC_TX_NUM_DESC 256 +#define TSEC_TX_MAX_DMA_SEGS 8 /* Interrupt Coalescing types */ #define TSEC_IC_RX 0 @@ -44,6 +45,12 @@ #define TSEC_MIN_FRAME_SIZE 64 #define TSEC_MAX_FRAME_SIZE 9600 +struct tsec_bufmap { + bus_dmamap_t map; + int map_initialized; + struct mbuf *mbuf; +}; + struct tsec_softc { /* XXX MII bus requires that struct ifnet is first!!! */ struct ifnet *tsec_ifp; @@ -59,16 +66,16 @@ struct tsec_softc { bus_dma_tag_t tsec_tx_dtag; /* TX descriptors tag */ bus_dmamap_t tsec_tx_dmap; /* TX descriptors map */ - struct tsec_desc *tsec_tx_vaddr;/* vadress of TX descriptors */ - uint32_t tsec_tx_raddr; /* real address of TX descriptors */ + bus_dma_tag_t tsec_tx_mtag; /* TX mbufs tag */ + uint32_t tx_idx_head; /* TX head descriptor/bufmap index */ + uint32_t tx_idx_tail; /* TX tail descriptor/bufmap index */ + struct tsec_desc *tsec_tx_vaddr;/* virtual address of TX descriptors */ + struct tsec_bufmap tx_bufmap[TSEC_TX_NUM_DESC]; + bus_dma_tag_t tsec_rx_mtag; /* TX mbufs tag */ bus_dma_tag_t tsec_rx_dtag; /* RX descriptors tag */ bus_dmamap_t tsec_rx_dmap; /* RX descriptors map */ struct tsec_desc *tsec_rx_vaddr; /* vadress of RX descriptors */ - uint32_t tsec_rx_raddr; /* real address of RX descriptors */ - - bus_dma_tag_t tsec_tx_mtag; /* TX mbufs tag */ - bus_dma_tag_t tsec_rx_mtag; /* TX mbufs tag */ struct rx_data_type { bus_dmamap_t map; /* mbuf map */ @@ -76,8 +83,6 @@ struct tsec_softc { uint32_t paddr; /* DMA address of buffer */ } rx_data[TSEC_RX_NUM_DESC]; - uint32_t tx_cur_desc_cnt; - uint32_t tx_dirty_desc_cnt; uint32_t rx_cur_desc_cnt; struct resource *sc_rres; /* register resource */ @@ -104,24 +109,6 @@ struct tsec_softc { struct callout tsec_callout; int tsec_watchdog; - /* TX maps */ - bus_dmamap_t tx_map_data[TSEC_TX_NUM_DESC]; - - /* unused TX maps data */ - uint32_t tx_map_unused_get_cnt; - uint32_t tx_map_unused_put_cnt; - bus_dmamap_t *tx_map_unused_data[TSEC_TX_NUM_DESC]; - - /* used TX maps data */ - uint32_t tx_map_used_get_cnt; - uint32_t tx_map_used_put_cnt; - bus_dmamap_t *tx_map_used_data[TSEC_TX_NUM_DESC]; - - /* mbufs in TX queue */ - uint32_t tx_mbuf_used_get_cnt; - uint32_t tx_mbuf_used_put_cnt; - struct mbuf *tx_mbuf_used_data[TSEC_TX_NUM_DESC]; - /* interrupt coalescing */ struct mtx ic_lock; uint32_t rx_ic_time; /* RW, valid values 0..65535 */ @@ -136,6 +123,9 @@ struct tsec_softc { bus_space_tag_t phy_bst; bus_space_handle_t phy_bsh; int phy_regoff; + + uint32_t tsec_rx_raddr; /* real address of RX descriptors */ + uint32_t tsec_tx_raddr; /* real address of TX descriptors */ }; /* interface to get/put generic objects */ @@ -156,75 +146,8 @@ struct tsec_softc { (sc)->count = (wrap) - 1; \ } while (0) -/* TX maps interface */ -#define TSEC_TX_MAP_CNT_INIT(sc) do { \ - TSEC_CNT_INIT((sc)->tx_map_unused_get_cnt, TSEC_TX_NUM_DESC); \ - TSEC_CNT_INIT((sc)->tx_map_unused_put_cnt, TSEC_TX_NUM_DESC); \ - TSEC_CNT_INIT((sc)->tx_map_used_get_cnt, TSEC_TX_NUM_DESC); \ - TSEC_CNT_INIT((sc)->tx_map_used_put_cnt, TSEC_TX_NUM_DESC); \ -} while (0) - -/* interface to get/put unused TX maps */ -#define TSEC_ALLOC_TX_MAP(sc) \ - TSEC_GET_GENERIC(sc, tx_map_unused_data, tx_map_unused_get_cnt, \ - TSEC_TX_NUM_DESC) - -#define TSEC_FREE_TX_MAP(sc, val) \ - TSEC_PUT_GENERIC(sc, tx_map_unused_data, tx_map_unused_put_cnt, \ - TSEC_TX_NUM_DESC, val) - -/* interface to get/put used TX maps */ -#define TSEC_GET_TX_MAP(sc) \ - TSEC_GET_GENERIC(sc, tx_map_used_data, tx_map_used_get_cnt, \ - TSEC_TX_NUM_DESC) - -#define TSEC_PUT_TX_MAP(sc, val) \ - TSEC_PUT_GENERIC(sc, tx_map_used_data, tx_map_used_put_cnt, \ - TSEC_TX_NUM_DESC, val) - -/* interface to get/put TX mbufs in send queue */ -#define TSEC_TX_MBUF_CNT_INIT(sc) do { \ - TSEC_CNT_INIT((sc)->tx_mbuf_used_get_cnt, TSEC_TX_NUM_DESC); \ - TSEC_CNT_INIT((sc)->tx_mbuf_used_put_cnt, TSEC_TX_NUM_DESC); \ -} while (0) - -#define TSEC_GET_TX_MBUF(sc) \ - TSEC_GET_GENERIC(sc, tx_mbuf_used_data, tx_mbuf_used_get_cnt, \ - TSEC_TX_NUM_DESC) - -#define TSEC_PUT_TX_MBUF(sc, val) \ - TSEC_PUT_GENERIC(sc, tx_mbuf_used_data, tx_mbuf_used_put_cnt, \ - TSEC_TX_NUM_DESC, val) - -#define TSEC_EMPTYQ_TX_MBUF(sc) \ - ((sc)->tx_mbuf_used_get_cnt == (sc)->tx_mbuf_used_put_cnt) - -/* interface for manage tx tsec_desc */ -#define TSEC_TX_DESC_CNT_INIT(sc) do { \ - TSEC_CNT_INIT((sc)->tx_cur_desc_cnt, TSEC_TX_NUM_DESC); \ - TSEC_CNT_INIT((sc)->tx_dirty_desc_cnt, TSEC_TX_NUM_DESC); \ -} while (0) - -#define TSEC_GET_CUR_TX_DESC(sc) \ - &TSEC_GET_GENERIC(sc, tsec_tx_vaddr, tx_cur_desc_cnt, \ - TSEC_TX_NUM_DESC) - -#define TSEC_GET_DIRTY_TX_DESC(sc) \ - &TSEC_GET_GENERIC(sc, tsec_tx_vaddr, tx_dirty_desc_cnt, \ - TSEC_TX_NUM_DESC) - -#define TSEC_BACK_DIRTY_TX_DESC(sc) \ - TSEC_BACK_GENERIC(sc, tx_dirty_desc_cnt, TSEC_TX_NUM_DESC) - -#define TSEC_CUR_DIFF_DIRTY_TX_DESC(sc) \ - ((sc)->tx_cur_desc_cnt != (sc)->tx_dirty_desc_cnt) - -#define TSEC_FREE_TX_DESC(sc) \ - (((sc)->tx_cur_desc_cnt < (sc)->tx_dirty_desc_cnt) ? \ - ((sc)->tx_dirty_desc_cnt - (sc)->tx_cur_desc_cnt - 1) \ - : \ - (TSEC_TX_NUM_DESC - (sc)->tx_cur_desc_cnt \ - + (sc)->tx_dirty_desc_cnt - 1)) +#define TSEC_FREE_TX_DESC(sc) \ + (((sc)->tx_idx_tail - (sc)->tx_idx_head - 1) & (TSEC_TX_NUM_DESC - 1)) /* interface for manage rx tsec_desc */ #define TSEC_RX_DESC_CNT_INIT(sc) do { \ @@ -243,9 +166,8 @@ struct tsec_softc { /* init all counters (for init only!) */ #define TSEC_TX_RX_COUNTERS_INIT(sc) do { \ - TSEC_TX_MAP_CNT_INIT(sc); \ - TSEC_TX_MBUF_CNT_INIT(sc); \ - TSEC_TX_DESC_CNT_INIT(sc); \ + sc->tx_idx_head = 0; \ + sc->tx_idx_tail = 0; \ TSEC_RX_DESC_CNT_INIT(sc); \ } while (0) |