if_cgem: Use explicit cache operations

This commit is contained in:
Sebastian Huber 2014-11-25 12:54:35 +01:00
parent cd179c472b
commit 911f517d2d

View File

@ -126,7 +126,9 @@ struct cgem_softc {
struct cgem_rx_desc volatile *rxring; struct cgem_rx_desc volatile *rxring;
bus_addr_t rxring_physaddr; bus_addr_t rxring_physaddr;
struct mbuf *rxring_m[CGEM_NUM_RX_DESCS]; struct mbuf *rxring_m[CGEM_NUM_RX_DESCS];
#ifndef __rtems__
bus_dmamap_t rxring_m_dmamap[CGEM_NUM_RX_DESCS]; bus_dmamap_t rxring_m_dmamap[CGEM_NUM_RX_DESCS];
#endif /* __rtems__ */
int rxring_hd_ptr; /* where to put rcv bufs */ int rxring_hd_ptr; /* where to put rcv bufs */
int rxring_tl_ptr; /* where to get receives */ int rxring_tl_ptr; /* where to get receives */
int rxring_queued; /* how many rcv bufs queued */ int rxring_queued; /* how many rcv bufs queued */
@ -142,7 +144,9 @@ struct cgem_softc {
struct cgem_tx_desc volatile *txring; struct cgem_tx_desc volatile *txring;
bus_addr_t txring_physaddr; bus_addr_t txring_physaddr;
struct mbuf *txring_m[CGEM_NUM_TX_DESCS]; struct mbuf *txring_m[CGEM_NUM_TX_DESCS];
#ifndef __rtems__
bus_dmamap_t txring_m_dmamap[CGEM_NUM_TX_DESCS]; bus_dmamap_t txring_m_dmamap[CGEM_NUM_TX_DESCS];
#endif /* __rtems__ */
int txring_hd_ptr; /* where to put next xmits */ int txring_hd_ptr; /* where to put next xmits */
int txring_tl_ptr; /* next xmit mbuf to free */ int txring_tl_ptr; /* next xmit mbuf to free */
int txring_queued; /* num xmits segs queued */ int txring_queued; /* num xmits segs queued */
@ -425,10 +429,12 @@ cgem_setup_descs(struct cgem_softc *sc)
sc->rxring[i].addr = CGEM_RXDESC_OWN; sc->rxring[i].addr = CGEM_RXDESC_OWN;
sc->rxring[i].ctl = 0; sc->rxring[i].ctl = 0;
sc->rxring_m[i] = NULL; sc->rxring_m[i] = NULL;
#ifndef __rtems__
err = bus_dmamap_create(sc->mbuf_dma_tag, 0, err = bus_dmamap_create(sc->mbuf_dma_tag, 0,
&sc->rxring_m_dmamap[i]); &sc->rxring_m_dmamap[i]);
if (err) if (err)
return (err); return (err);
#endif /* __rtems__ */
} }
sc->rxring[CGEM_NUM_RX_DESCS - 1].addr |= CGEM_RXDESC_WRAP; sc->rxring[CGEM_NUM_RX_DESCS - 1].addr |= CGEM_RXDESC_WRAP;
@ -458,10 +464,12 @@ cgem_setup_descs(struct cgem_softc *sc)
sc->txring[i].addr = 0; sc->txring[i].addr = 0;
sc->txring[i].ctl = CGEM_TXDESC_USED; sc->txring[i].ctl = CGEM_TXDESC_USED;
sc->txring_m[i] = NULL; sc->txring_m[i] = NULL;
#ifndef __rtems__
err = bus_dmamap_create(sc->mbuf_dma_tag, 0, err = bus_dmamap_create(sc->mbuf_dma_tag, 0,
&sc->txring_m_dmamap[i]); &sc->txring_m_dmamap[i]);
if (err) if (err)
return (err); return (err);
#endif /* __rtems__ */
} }
sc->txring[CGEM_NUM_TX_DESCS - 1].ctl |= CGEM_TXDESC_WRAP; sc->txring[CGEM_NUM_TX_DESCS - 1].ctl |= CGEM_TXDESC_WRAP;
@ -477,8 +485,12 @@ static void
cgem_fill_rqueue(struct cgem_softc *sc) cgem_fill_rqueue(struct cgem_softc *sc)
{ {
struct mbuf *m = NULL; struct mbuf *m = NULL;
#ifndef __rtems__
bus_dma_segment_t segs[TX_MAX_DMA_SEGS]; bus_dma_segment_t segs[TX_MAX_DMA_SEGS];
int nsegs; int nsegs;
#else /* __rtems__ */
bus_dma_segment_t segs[1];
#endif /* __rtems__ */
CGEM_ASSERT_LOCKED(sc); CGEM_ASSERT_LOCKED(sc);
@ -492,6 +504,7 @@ cgem_fill_rqueue(struct cgem_softc *sc)
m->m_pkthdr.len = MCLBYTES; m->m_pkthdr.len = MCLBYTES;
m->m_pkthdr.rcvif = sc->ifp; m->m_pkthdr.rcvif = sc->ifp;
#ifndef __rtems__
/* Load map and plug in physical address. */ /* Load map and plug in physical address. */
if (bus_dmamap_load_mbuf_sg(sc->mbuf_dma_tag, if (bus_dmamap_load_mbuf_sg(sc->mbuf_dma_tag,
sc->rxring_m_dmamap[sc->rxring_hd_ptr], m, sc->rxring_m_dmamap[sc->rxring_hd_ptr], m,
@ -500,12 +513,18 @@ cgem_fill_rqueue(struct cgem_softc *sc)
m_free(m); m_free(m);
break; break;
} }
#endif /* __rtems__ */
sc->rxring_m[sc->rxring_hd_ptr] = m; sc->rxring_m[sc->rxring_hd_ptr] = m;
#ifndef __rtems__
/* Sync cache with receive buffer. */ /* Sync cache with receive buffer. */
bus_dmamap_sync(sc->mbuf_dma_tag, bus_dmamap_sync(sc->mbuf_dma_tag,
sc->rxring_m_dmamap[sc->rxring_hd_ptr], sc->rxring_m_dmamap[sc->rxring_hd_ptr],
BUS_DMASYNC_PREREAD); BUS_DMASYNC_PREREAD);
#else /* __rtems__ */
rtems_cache_invalidate_multiple_data_lines(m->m_data, m->m_len);
segs[0].ds_addr = mtod(m, bus_addr_t);
#endif /* __rtems__ */
/* Write rx descriptor and increment head pointer. */ /* Write rx descriptor and increment head pointer. */
sc->rxring[sc->rxring_hd_ptr].ctl = 0; sc->rxring[sc->rxring_hd_ptr].ctl = 0;
@ -542,6 +561,7 @@ cgem_recv(struct cgem_softc *sc)
m = sc->rxring_m[sc->rxring_tl_ptr]; m = sc->rxring_m[sc->rxring_tl_ptr];
sc->rxring_m[sc->rxring_tl_ptr] = NULL; sc->rxring_m[sc->rxring_tl_ptr] = NULL;
#ifndef __rtems__
/* Sync cache with receive buffer. */ /* Sync cache with receive buffer. */
bus_dmamap_sync(sc->mbuf_dma_tag, bus_dmamap_sync(sc->mbuf_dma_tag,
sc->rxring_m_dmamap[sc->rxring_tl_ptr], sc->rxring_m_dmamap[sc->rxring_tl_ptr],
@ -550,6 +570,9 @@ cgem_recv(struct cgem_softc *sc)
/* Unload dmamap. */ /* Unload dmamap. */
bus_dmamap_unload(sc->mbuf_dma_tag, bus_dmamap_unload(sc->mbuf_dma_tag,
sc->rxring_m_dmamap[sc->rxring_tl_ptr]); sc->rxring_m_dmamap[sc->rxring_tl_ptr]);
#else /* __rtems__ */
rtems_cache_invalidate_multiple_data_lines(m->m_data, m->m_len);
#endif /* __rtems__ */
/* Increment tail pointer. */ /* Increment tail pointer. */
if (++sc->rxring_tl_ptr == CGEM_NUM_RX_DESCS) if (++sc->rxring_tl_ptr == CGEM_NUM_RX_DESCS)
@ -639,6 +662,7 @@ cgem_clean_tx(struct cgem_softc *sc)
((ctl = sc->txring[sc->txring_tl_ptr].ctl) & ((ctl = sc->txring[sc->txring_tl_ptr].ctl) &
CGEM_TXDESC_USED) != 0) { CGEM_TXDESC_USED) != 0) {
#ifndef __rtems__
/* Sync cache. nop? */ /* Sync cache. nop? */
bus_dmamap_sync(sc->mbuf_dma_tag, bus_dmamap_sync(sc->mbuf_dma_tag,
sc->txring_m_dmamap[sc->txring_tl_ptr], sc->txring_m_dmamap[sc->txring_tl_ptr],
@ -647,6 +671,7 @@ cgem_clean_tx(struct cgem_softc *sc)
/* Unload DMA map. */ /* Unload DMA map. */
bus_dmamap_unload(sc->mbuf_dma_tag, bus_dmamap_unload(sc->mbuf_dma_tag,
sc->txring_m_dmamap[sc->txring_tl_ptr]); sc->txring_m_dmamap[sc->txring_tl_ptr]);
#endif /* __rtems__ */
/* Free up the mbuf. */ /* Free up the mbuf. */
m = sc->txring_m[sc->txring_tl_ptr]; m = sc->txring_m[sc->txring_tl_ptr];
@ -701,6 +726,33 @@ cgem_clean_tx(struct cgem_softc *sc)
} }
} }
#ifdef __rtems__
static int
cgem_get_segs_for_tx(struct mbuf *m, bus_dma_segment_t segs[TX_MAX_DMA_SEGS],
int *nsegs)
{
int i = 0;
do {
if (m->m_len > 0) {
segs[i].ds_addr = mtod(m, bus_addr_t);
segs[i].ds_len = m->m_len;
rtems_cache_flush_multiple_data_lines(m->m_data, m->m_len);
++i;
}
m = m->m_next;
if (m == NULL) {
*nsegs = i;
return (0);
}
} while (i < TX_MAX_DMA_SEGS);
return (EFBIG);
}
#endif /* __rtems__ */
/* Start transmits. */ /* Start transmits. */
static void static void
cgem_start_locked(struct ifnet *ifp) cgem_start_locked(struct ifnet *ifp)
@ -738,10 +790,14 @@ cgem_start_locked(struct ifnet *ifp)
if (m == NULL) if (m == NULL)
break; break;
#ifndef __rtems__
/* Load DMA map. */ /* Load DMA map. */
err = bus_dmamap_load_mbuf_sg(sc->mbuf_dma_tag, err = bus_dmamap_load_mbuf_sg(sc->mbuf_dma_tag,
sc->txring_m_dmamap[sc->txring_hd_ptr], sc->txring_m_dmamap[sc->txring_hd_ptr],
m, segs, &nsegs, BUS_DMA_NOWAIT); m, segs, &nsegs, BUS_DMA_NOWAIT);
#else /* __rtems__ */
err = cgem_get_segs_for_tx(m, segs, &nsegs);
#endif /* __rtems__ */
if (err == EFBIG) { if (err == EFBIG) {
/* Too many segments! defrag and try again. */ /* Too many segments! defrag and try again. */
struct mbuf *m2 = m_defrag(m, M_NOWAIT); struct mbuf *m2 = m_defrag(m, M_NOWAIT);
@ -752,9 +808,13 @@ cgem_start_locked(struct ifnet *ifp)
continue; continue;
} }
m = m2; m = m2;
#ifndef __rtems__
err = bus_dmamap_load_mbuf_sg(sc->mbuf_dma_tag, err = bus_dmamap_load_mbuf_sg(sc->mbuf_dma_tag,
sc->txring_m_dmamap[sc->txring_hd_ptr], sc->txring_m_dmamap[sc->txring_hd_ptr],
m, segs, &nsegs, BUS_DMA_NOWAIT); m, segs, &nsegs, BUS_DMA_NOWAIT);
#else /* __rtems__ */
err = cgem_get_segs_for_tx(m, segs, &nsegs);
#endif /* __rtems__ */
sc->txdefrags++; sc->txdefrags++;
} }
if (err) { if (err) {
@ -765,10 +825,12 @@ cgem_start_locked(struct ifnet *ifp)
} }
sc->txring_m[sc->txring_hd_ptr] = m; sc->txring_m[sc->txring_hd_ptr] = m;
#ifndef __rtems__
/* Sync tx buffer with cache. */ /* Sync tx buffer with cache. */
bus_dmamap_sync(sc->mbuf_dma_tag, bus_dmamap_sync(sc->mbuf_dma_tag,
sc->txring_m_dmamap[sc->txring_hd_ptr], sc->txring_m_dmamap[sc->txring_hd_ptr],
BUS_DMASYNC_PREWRITE); BUS_DMASYNC_PREWRITE);
#endif /* __rtems__ */
/* Set wrap flag if next packet might run off end of ring. */ /* Set wrap flag if next packet might run off end of ring. */
wrap = sc->txring_hd_ptr + nsegs + TX_MAX_DMA_SEGS >= wrap = sc->txring_hd_ptr + nsegs + TX_MAX_DMA_SEGS >=
@ -1127,8 +1189,10 @@ cgem_stop(struct cgem_softc *sc)
sc->txring[i].ctl = CGEM_TXDESC_USED; sc->txring[i].ctl = CGEM_TXDESC_USED;
sc->txring[i].addr = 0; sc->txring[i].addr = 0;
if (sc->txring_m[i]) { if (sc->txring_m[i]) {
#ifndef __rtems__
bus_dmamap_unload(sc->mbuf_dma_tag, bus_dmamap_unload(sc->mbuf_dma_tag,
sc->txring_m_dmamap[i]); sc->txring_m_dmamap[i]);
#endif /* __rtems__ */
m_freem(sc->txring_m[i]); m_freem(sc->txring_m[i]);
sc->txring_m[i] = NULL; sc->txring_m[i] = NULL;
} }
@ -1144,9 +1208,11 @@ cgem_stop(struct cgem_softc *sc)
sc->rxring[i].addr = CGEM_RXDESC_OWN; sc->rxring[i].addr = CGEM_RXDESC_OWN;
sc->rxring[i].ctl = 0; sc->rxring[i].ctl = 0;
if (sc->rxring_m[i]) { if (sc->rxring_m[i]) {
#ifndef __rtems__
/* Unload dmamap. */ /* Unload dmamap. */
bus_dmamap_unload(sc->mbuf_dma_tag, bus_dmamap_unload(sc->mbuf_dma_tag,
sc->rxring_m_dmamap[sc->rxring_tl_ptr]); sc->rxring_m_dmamap[sc->rxring_tl_ptr]);
#endif /* __rtems__ */
m_freem(sc->rxring_m[i]); m_freem(sc->rxring_m[i]);
sc->rxring_m[i] = NULL; sc->rxring_m[i] = NULL;
@ -1765,7 +1831,9 @@ static int
cgem_detach(device_t dev) cgem_detach(device_t dev)
{ {
struct cgem_softc *sc = device_get_softc(dev); struct cgem_softc *sc = device_get_softc(dev);
#ifndef __rtems__
int i; int i;
#endif /* __rtems__ */
if (sc == NULL) if (sc == NULL)
return (ENODEV); return (ENODEV);
@ -1807,12 +1875,14 @@ cgem_detach(device_t dev)
bus_dmamem_free(sc->desc_dma_tag, __DEVOLATILE(void *, sc->rxring), bus_dmamem_free(sc->desc_dma_tag, __DEVOLATILE(void *, sc->rxring),
sc->rxring_dma_map); sc->rxring_dma_map);
sc->rxring = NULL; sc->rxring = NULL;
#ifndef __rtems__
for (i = 0; i < CGEM_NUM_RX_DESCS; i++) for (i = 0; i < CGEM_NUM_RX_DESCS; i++)
if (sc->rxring_m_dmamap[i] != NULL) { if (sc->rxring_m_dmamap[i] != NULL) {
bus_dmamap_destroy(sc->mbuf_dma_tag, bus_dmamap_destroy(sc->mbuf_dma_tag,
sc->rxring_m_dmamap[i]); sc->rxring_m_dmamap[i]);
sc->rxring_m_dmamap[i] = NULL; sc->rxring_m_dmamap[i] = NULL;
} }
#endif /* __rtems__ */
} }
if (sc->txring != NULL) { if (sc->txring != NULL) {
if (sc->txring_physaddr != 0) { if (sc->txring_physaddr != 0) {
@ -1822,12 +1892,14 @@ cgem_detach(device_t dev)
bus_dmamem_free(sc->desc_dma_tag, __DEVOLATILE(void *, sc->txring), bus_dmamem_free(sc->desc_dma_tag, __DEVOLATILE(void *, sc->txring),
sc->txring_dma_map); sc->txring_dma_map);
sc->txring = NULL; sc->txring = NULL;
#ifndef __rtems__
for (i = 0; i < CGEM_NUM_TX_DESCS; i++) for (i = 0; i < CGEM_NUM_TX_DESCS; i++)
if (sc->txring_m_dmamap[i] != NULL) { if (sc->txring_m_dmamap[i] != NULL) {
bus_dmamap_destroy(sc->mbuf_dma_tag, bus_dmamap_destroy(sc->mbuf_dma_tag,
sc->txring_m_dmamap[i]); sc->txring_m_dmamap[i]);
sc->txring_m_dmamap[i] = NULL; sc->txring_m_dmamap[i] = NULL;
} }
#endif /* __rtems__ */
} }
if (sc->desc_dma_tag != NULL) { if (sc->desc_dma_tag != NULL) {
bus_dma_tag_destroy(sc->desc_dma_tag); bus_dma_tag_destroy(sc->desc_dma_tag);