Changeset 0cb4075 in rtems-libbsd


Ignore:
Timestamp:
Oct 24, 2017, 10:17:00 AM (20 months ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
eeb3fd5d9b07ac9a2e280cff60a1b762bd273a8d, 1e989998de954bef51e6c19cc3d64d39f32100aa
Children:
fd5ee57
Parents:
798d308
git-author:
Sebastian Huber <sebastian.huber@…> (10/24/17 10:17:00)
git-committer:
Sebastian Huber <sebastian.huber@…> (10/25/17 12:29:55)
Message:

ffec: Defragment transmit mbuf only if necessary

Use structure similar to TSEC (if_tsec) driver.

The use of bus_dmamap_sync() differs these network interface drivers.
This should not be the case.

Update #3090.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • freebsd/sys/dev/ffec/if_ffec.c

    r798d308 r0cb4075  
    126126
    127127/*
    128  * Driver data and defines.
     128 * Driver data and defines.  The descriptor counts must be a power of two.
    129129 */
    130130#define RX_DESC_COUNT   64
     
    132132#define TX_DESC_COUNT   64
    133133#define TX_DESC_SIZE    (sizeof(struct ffec_hwdesc) * TX_DESC_COUNT)
     134#define TX_MAX_DMA_SEGS 8
    134135
    135136#define WATCHDOG_TIMEOUT_SECS   5
     
    188189        uint32_t                tx_idx_head;
    189190        uint32_t                tx_idx_tail;
    190         int                     txcount;
    191191};
    192192
     
    201201static void ffec_init_locked(struct ffec_softc *sc);
    202202static void ffec_stop_locked(struct ffec_softc *sc);
     203static void ffec_encap(struct ifnet *ifp, struct ffec_softc *sc,
     204    struct mbuf *m0, int *start_tx);
    203205static void ffec_txstart_locked(struct ffec_softc *sc);
    204206static void ffec_txfinish_locked(struct ffec_softc *sc);
     
    233235
    234236static inline uint32_t
    235 next_rxidx(struct ffec_softc *sc, uint32_t curidx)
    236 {
    237 
    238         return ((curidx == RX_DESC_COUNT - 1) ? 0 : curidx + 1);
     237next_rxidx(uint32_t curidx)
     238{
     239
     240        return ((curidx + 1) & (RX_DESC_COUNT - 1));
    239241}
    240242
    241243static inline uint32_t
    242 next_txidx(struct ffec_softc *sc, uint32_t curidx)
    243 {
    244 
    245         return ((curidx == TX_DESC_COUNT - 1) ? 0 : curidx + 1);
     244next_txidx(uint32_t curidx)
     245{
     246
     247        return ((curidx + 1) & (TX_DESC_COUNT - 1));
     248}
     249
     250static inline uint32_t
     251prev_txidx(uint32_t curidx)
     252{
     253
     254        return ((curidx - 1) & (TX_DESC_COUNT - 1));
     255}
     256
     257static inline uint32_t
     258inc_txidx(uint32_t curidx, uint32_t inc)
     259{
     260
     261        return ((curidx + inc) & (TX_DESC_COUNT - 1));
     262}
     263
     264static inline uint32_t
     265free_txdesc(struct ffec_softc *sc)
     266{
     267
     268        return (((sc)->tx_idx_tail - (sc)->tx_idx_head - 1) &
     269            (TX_DESC_COUNT - 1));
    246270}
    247271
     
    570594}
    571595
    572 inline static uint32_t
    573 ffec_setup_txdesc(struct ffec_softc *sc, int idx, bus_addr_t paddr,
    574     uint32_t len)
    575 {
    576         uint32_t nidx;
     596static void
     597ffec_encap(struct ifnet *ifp, struct ffec_softc *sc, struct mbuf *m0,
     598    int *start_tx)
     599{
     600        bus_dma_segment_t segs[TX_MAX_DMA_SEGS];
     601        int error, i, nsegs;
     602        struct ffec_bufmap *bmap;
     603        uint32_t tx_idx;
    577604        uint32_t flags;
    578605
    579         nidx = next_txidx(sc, idx);
    580 
    581         /* Addr/len 0 means we're clearing the descriptor after xmit done. */
    582         if (paddr == 0 || len == 0) {
    583                 flags = 0;
    584                 --sc->txcount;
    585         } else {
    586                 flags = FEC_TXDESC_READY | FEC_TXDESC_L | FEC_TXDESC_TC;
    587                 ++sc->txcount;
    588         }
    589         if (nidx == 0)
    590                 flags |= FEC_TXDESC_WRAP;
    591 
    592         /*
    593          * The hardware requires 32-bit physical addresses.  We set up the dma
    594          * tag to indicate that, so the cast to uint32_t should never lose
    595          * significant bits.
    596          */
    597         sc->txdesc_ring[idx].buf_paddr = (uint32_t)paddr;
    598         wmb();
    599         sc->txdesc_ring[idx].flags_len = flags | len; /* Must be set last! */
    600 
    601         return (nidx);
    602 }
    603 
    604 static int
    605 ffec_setup_txbuf(struct ffec_softc *sc, int idx, struct mbuf **mp)
    606 {
    607         struct mbuf * m;
    608         int error, nsegs;
    609         struct bus_dma_segment seg;
    610 
    611         if ((m = m_defrag(*mp, M_NOWAIT)) == NULL)
    612                 return (ENOMEM);
    613         *mp = m;
    614 
    615         error = bus_dmamap_load_mbuf_sg(sc->txbuf_tag, sc->txbuf_map[idx].map,
    616             m, &seg, &nsegs, 0);
     606        FFEC_ASSERT_LOCKED(sc);
     607
     608        tx_idx = sc->tx_idx_head;
     609        bmap = &sc->txbuf_map[tx_idx];
     610
     611        /* Create mapping in DMA memory */
     612        error = bus_dmamap_load_mbuf_sg(sc->txbuf_tag, bmap->map, m0,
     613            segs, &nsegs, BUS_DMA_NOWAIT);
     614        if (error == EFBIG) {
     615                /* Too many segments!  Defrag and try again. */
     616                struct mbuf *m = m_defrag(m0, M_NOWAIT);
     617
     618                if (m == NULL) {
     619                        m_freem(m0);
     620                        return;
     621                }
     622                m0 = m;
     623                error = bus_dmamap_load_mbuf_sg(sc->txbuf_tag,
     624                    bmap->map, m0, segs, &nsegs, BUS_DMA_NOWAIT);
     625        }
    617626        if (error != 0) {
    618                 return (ENOMEM);
    619         }
     627                /* Give up. */
     628                m_freem(m0);
     629                return;
     630        }
     631
    620632#ifndef __rtems__
    621         bus_dmamap_sync(sc->txbuf_tag, sc->txbuf_map[idx].map,
    622             BUS_DMASYNC_PREWRITE);
    623 #else /* __rtems__ */
    624         rtems_cache_flush_multiple_data_lines((void *)seg.ds_addr, seg.ds_len);
     633        bus_dmamap_sync(sc->txbuf_tag, bmap->map, BUS_DMASYNC_PREWRITE);
    625634#endif /* __rtems__ */
    626 
    627         sc->txbuf_map[idx].mbuf = m;
    628         ffec_setup_txdesc(sc, idx, seg.ds_addr, seg.ds_len);
    629 
    630         return (0);
    631 
     635        bmap->mbuf = m0;
     636
     637        /*
     638         * Fill in the TX descriptors back to front so that READY bit in first
     639         * descriptor is set last.
     640         */
     641        tx_idx = inc_txidx(tx_idx, (uint32_t)nsegs);
     642        sc->tx_idx_head = tx_idx;
     643        flags = FEC_TXDESC_L | FEC_TXDESC_READY | FEC_TXDESC_TC;
     644        for (i = nsegs - 1; i >= 0; i--) {
     645                struct ffec_hwdesc *tx_desc;
     646
     647                tx_idx = prev_txidx(tx_idx);;
     648                tx_desc = &sc->txdesc_ring[tx_idx];
     649                tx_desc->buf_paddr = segs[i].ds_addr;
     650#ifdef __rtems__
     651                rtems_cache_flush_multiple_data_lines((void *)segs[i].ds_addr,
     652                    segs[i].ds_len);
     653#endif /* __rtems__ */
     654
     655                if (i == 0) {
     656                        wmb();
     657                }
     658
     659                tx_desc->flags_len = (tx_idx == (TX_DESC_COUNT - 1) ?
     660                    FEC_TXDESC_WRAP : 0) | flags | segs[i].ds_len;
     661
     662                flags &= ~FEC_TXDESC_L;
     663        }
     664
     665        BPF_MTAP(ifp, m0);
     666        *start_tx = 1;
    632667}
    633668
     
    636671{
    637672        struct ifnet *ifp;
    638         struct mbuf *m;
    639         int enqueued;
     673        struct mbuf *m0;
     674        int start_tx;
    640675
    641676        FFEC_ASSERT_LOCKED(sc);
     677
     678        ifp = sc->ifp;
     679        start_tx = 0;
    642680
    643681        if (!sc->link_is_up)
    644682                return;
    645683
    646         ifp = sc->ifp;
    647 
    648         if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
    649                 return;
    650 
    651         enqueued = 0;
    652 
    653684        for (;;) {
    654                 if (sc->txcount == (TX_DESC_COUNT-1)) {
     685                if (free_txdesc(sc) < TX_MAX_DMA_SEGS) {
     686                        /* No free descriptors */
    655687                        ifp->if_drv_flags |= IFF_DRV_OACTIVE;
    656688                        break;
    657689                }
    658                 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
    659                 if (m == NULL)
     690
     691                /* Get packet from the queue */
     692                IFQ_DRV_DEQUEUE(&ifp->if_snd, m0);
     693                if (m0 == NULL)
    660694                        break;
    661                 if (ffec_setup_txbuf(sc, sc->tx_idx_head, &m) != 0) {
    662                         IFQ_DRV_PREPEND(&ifp->if_snd, m);
    663                         break;
    664                 }
    665                 BPF_MTAP(ifp, m);
    666                 sc->tx_idx_head = next_txidx(sc, sc->tx_idx_head);
    667                 ++enqueued;
    668         }
    669 
    670         if (enqueued != 0) {
     695
     696                ffec_encap(ifp, sc, m0, &start_tx);
     697        }
     698
     699        if (start_tx ) {
    671700                bus_dmamap_sync(sc->txdesc_tag, sc->txdesc_map, BUS_DMASYNC_PREWRITE);
    672701                WR4(sc, FEC_TDAR_REG, FEC_TDAR_TDAR);
     
    690719{
    691720        struct ifnet *ifp;
    692         struct ffec_hwdesc *desc;
    693         struct ffec_bufmap *bmap;
    694         boolean_t retired_buffer;
     721        uint32_t tx_idx;
    695722
    696723        FFEC_ASSERT_LOCKED(sc);
     724
     725        ifp = sc->ifp;
    697726
    698727        /* XXX Can't set PRE|POST right now, but we need both. */
    699728        bus_dmamap_sync(sc->txdesc_tag, sc->txdesc_map, BUS_DMASYNC_PREREAD);
    700729        bus_dmamap_sync(sc->txdesc_tag, sc->txdesc_map, BUS_DMASYNC_POSTREAD);
    701         ifp = sc->ifp;
    702         retired_buffer = false;
    703         while (sc->tx_idx_tail != sc->tx_idx_head) {
    704                 desc = &sc->txdesc_ring[sc->tx_idx_tail];
     730
     731        tx_idx = sc->tx_idx_tail;
     732        while (tx_idx != sc->tx_idx_head) {
     733                struct ffec_hwdesc *desc;
     734                struct ffec_bufmap *bmap;
     735
     736                desc = &sc->txdesc_ring[tx_idx];
    705737                if (desc->flags_len & FEC_TXDESC_READY)
    706738                        break;
    707                 retired_buffer = true;
    708                 bmap = &sc->txbuf_map[sc->tx_idx_tail];
    709                 bus_dmamap_sync(sc->txbuf_tag, bmap->map,
     739
     740                bmap = &sc->txbuf_map[tx_idx];
     741                tx_idx = next_txidx(tx_idx);
     742                if (bmap->mbuf == NULL)
     743                        continue;
     744
     745                /*
     746                 * This is the last buf in this packet, so unmap and free it.
     747                 */
     748                bus_dmamap_sync(sc->txbuf_tag, bmap->map,
    710749                    BUS_DMASYNC_POSTWRITE);
    711750                bus_dmamap_unload(sc->txbuf_tag, bmap->map);
    712751                m_freem(bmap->mbuf);
    713752                bmap->mbuf = NULL;
    714                 ffec_setup_txdesc(sc, sc->tx_idx_tail, 0, 0);
    715                 sc->tx_idx_tail = next_txidx(sc, sc->tx_idx_tail);
    716         }
    717 
    718         /*
    719          * If we retired any buffers, there will be open tx slots available in
    720          * the descriptor ring, go try to start some new output.
    721          */
    722         if (retired_buffer) {
    723                 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
    724                 ffec_txstart_locked(sc);
    725         }
     753        }
     754        sc->tx_idx_tail = tx_idx;
     755
     756        ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
     757        ffec_txstart_locked(sc);
    726758
    727759        /* If there are no buffers outstanding, muzzle the watchdog. */
     
    741773         * significant bits.
    742774         */
    743         nidx = next_rxidx(sc, idx);
     775        nidx = next_rxidx(idx);
    744776        sc->rxdesc_ring[idx].buf_paddr = (uint32_t)paddr;
    745777        wmb();
     
    925957                        ffec_rxfinish_onebuf(sc, len);
    926958                }
    927                 sc->rx_idx = next_rxidx(sc, sc->rx_idx);
     959                sc->rx_idx = next_rxidx(sc->rx_idx);
    928960        }
    929961
     
    10771109                desc = &sc->txdesc_ring[idx];
    10781110                bmap = &sc->txbuf_map[idx];
    1079                 if (desc->buf_paddr != 0) {
    1080                         bus_dmamap_unload(sc->txbuf_tag, bmap->map);
    1081                         m_freem(bmap->mbuf);
    1082                         bmap->mbuf = NULL;
    1083                         ffec_setup_txdesc(sc, idx, 0, 0);
    1084                 }
    1085                 idx = next_txidx(sc, idx);
     1111                idx = next_txidx(idx);
     1112                if (bmap->mbuf == NULL)
     1113                        continue;
     1114
     1115                bus_dmamap_sync(sc->txbuf_tag, bmap->map,
     1116                    BUS_DMASYNC_POSTWRITE);
     1117                bus_dmamap_unload(sc->txbuf_tag, bmap->map);
     1118                m_freem(bmap->mbuf);
     1119                bmap->mbuf = NULL;
    10861120        }
    10871121
     
    12111245        sc->rx_idx = 0;
    12121246        sc->tx_idx_head = sc->tx_idx_tail = 0;
    1213         sc->txcount = 0;
    12141247        WR4(sc, FEC_RDSR_REG, sc->rxdesc_ring_paddr);
    12151248        WR4(sc, FEC_TDSR_REG, sc->txdesc_ring_paddr);
     
    15941627            BUS_SPACE_MAXADDR,          /* highaddr */
    15951628            NULL, NULL,                 /* filter, filterarg */
    1596             MCLBYTES, 1,                /* maxsize, nsegments */
     1629            MCLBYTES, TX_MAX_DMA_SEGS, /* maxsize, nsegments */
    15971630            MCLBYTES,                   /* maxsegsize */
    15981631            0,                          /* flags */
     
    16131646                        goto out;
    16141647                }
    1615                 ffec_setup_txdesc(sc, idx, 0, 0);
     1648                sc->txdesc_ring[idx].buf_paddr = 0;
     1649                sc->txdesc_ring[idx].flags_len =
     1650                    ((idx == TX_DESC_COUNT - 1) ?  FEC_TXDESC_WRAP : 0);
    16161651        }
    16171652
Note: See TracChangeset for help on using the changeset viewer.