Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci support {extended, advanced} receive descriptor ...



details:   https://anonhg.NetBSD.org/src/rev/4e23895e3b56
branches:  trunk
changeset: 820922:4e23895e3b56
user:      knakahara <knakahara%NetBSD.org@localhost>
date:      Mon Jan 16 00:09:06 2017 +0000

description:
support {extended, advanced} receive descriptor for wm(4).

support below two receive descriptors.
    - extended descriptor (used by 82574 only)
    - advanced descriptor (used by 82575 and newer)

SPH(split header buffer) is not supported yet.

ok by msaitoh@n.o.

diffstat:

 sys/dev/pci/if_wm.c    |  414 ++++++++++++++++++++++++++++++++++++++----------
 sys/dev/pci/if_wmreg.h |  213 +++++++++++++++++++++++++-
 2 files changed, 540 insertions(+), 87 deletions(-)

diffs (truncated from 892 to 300 lines):

diff -r d954c1a7c96d -r 4e23895e3b56 sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Sun Jan 15 22:18:11 2017 +0000
+++ b/sys/dev/pci/if_wm.c       Mon Jan 16 00:09:06 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.465 2017/01/10 08:57:39 msaitoh Exp $      */
+/*     $NetBSD: if_wm.c,v 1.466 2017/01/16 00:09:06 knakahara Exp $    */
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -84,7 +84,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.465 2017/01/10 08:57:39 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.466 2017/01/16 00:09:06 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -215,8 +215,14 @@
        nq_txdesc_t      sctxu_nq_txdescs[WM_NTXDESC_82544];
 } txdescs_t;
 
+typedef union rxdescs {
+       wiseman_rxdesc_t sctxu_rxdescs[WM_NRXDESC];
+       ext_rxdesc_t      sctxu_ext_rxdescs[WM_NRXDESC]; /* 82574 only */
+       nq_rxdesc_t      sctxu_nq_rxdescs[WM_NRXDESC]; /* 82575 and newer */
+} rxdescs_t;
+
 #define        WM_CDTXOFF(txq, x)      ((txq)->txq_descsize * (x))
-#define        WM_CDRXOFF(x)   (sizeof(wiseman_rxdesc_t) * x)
+#define        WM_CDRXOFF(rxq, x)      ((rxq)->rxq_descsize * (x))
 
 /*
  * Software state for transmit jobs.
@@ -356,15 +362,19 @@
        struct wm_softc *rxq_sc;        /* shortcut (skip struct wm_queue) */
 
        /* Software state for the receive descriptors. */
-       wiseman_rxdesc_t *rxq_descs;
+       struct wm_rxsoft rxq_soft[WM_NRXDESC];
 
        /* RX control data structures. */
-       struct wm_rxsoft rxq_soft[WM_NRXDESC];
+       int rxq_ndesc;                  /* must be a power of two */
+       size_t rxq_descsize;            /* a rx descriptor size */
+       rxdescs_t *rxq_descs_u;
        bus_dmamap_t rxq_desc_dmamap;   /* control data DMA map */
        bus_dma_segment_t rxq_desc_seg; /* control data segment */
        int rxq_desc_rseg;              /* real number of control segment */
-       size_t rxq_desc_size;           /* control data size */
 #define        rxq_desc_dma    rxq_desc_dmamap->dm_segs[0].ds_addr
+#define        rxq_descs       rxq_descs_u->sctxu_rxdescs
+#define        rxq_ext_descs   rxq_descs_u->sctxu_ext_rxdescs
+#define        rxq_nq_descs    rxq_descs_u->sctxu_nq_rxdescs
 
        bus_addr_t rxq_rdt_reg;         /* offset of RDT register */
 
@@ -578,7 +588,7 @@
            (reg) + sc->sc_flashreg_offset, (data))
 
 #define        WM_CDTXADDR(txq, x)     ((txq)->txq_desc_dma + WM_CDTXOFF((txq), (x)))
-#define        WM_CDRXADDR(rxq, x)     ((rxq)->rxq_desc_dma + WM_CDRXOFF((x)))
+#define        WM_CDRXADDR(rxq, x)     ((rxq)->rxq_desc_dma + WM_CDRXOFF((rxq), (x)))
 
 #define        WM_CDTXADDR_LO(txq, x)  (WM_CDTXADDR((txq), (x)) & 0xffffffffU)
 #define        WM_CDTXADDR_HI(txq, x)                                          \
@@ -1516,7 +1526,7 @@
        struct wm_softc *sc = rxq->rxq_sc;
 
        bus_dmamap_sync(sc->sc_dmat, rxq->rxq_desc_dmamap,
-           WM_CDRXOFF(start), sizeof(wiseman_rxdesc_t), ops);
+           WM_CDRXOFF(rxq, start), rxq->rxq_descsize, ops);
 }
 
 static inline void
@@ -1524,7 +1534,6 @@
 {
        struct wm_softc *sc = rxq->rxq_sc;
        struct wm_rxsoft *rxs = &rxq->rxq_soft[start];
-       wiseman_rxdesc_t *rxd = &rxq->rxq_descs[start];
        struct mbuf *m = rxs->rxs_mbuf;
 
        /*
@@ -1543,13 +1552,29 @@
         */
        m->m_data = m->m_ext.ext_buf + sc->sc_align_tweak;
 
-       wm_set_dma_addr(&rxd->wrx_addr,
-           rxs->rxs_dmamap->dm_segs[0].ds_addr + sc->sc_align_tweak);
-       rxd->wrx_len = 0;
-       rxd->wrx_cksum = 0;
-       rxd->wrx_status = 0;
-       rxd->wrx_errors = 0;
-       rxd->wrx_special = 0;
+       if (sc->sc_type == WM_T_82574) {
+               ext_rxdesc_t *rxd = &rxq->rxq_ext_descs[start];
+               rxd->erx_data.erxd_addr =
+                       htole64(rxs->rxs_dmamap->dm_segs[0].ds_addr + sc->sc_align_tweak);
+               rxd->erx_data.erxd_dd = 0;
+       } else if ((sc->sc_flags & WM_F_NEWQUEUE) != 0) {
+               nq_rxdesc_t *rxd = &rxq->rxq_nq_descs[start];
+
+               rxd->nqrx_data.nrxd_paddr =
+                       htole64(rxs->rxs_dmamap->dm_segs[0].ds_addr + sc->sc_align_tweak);
+               /* Currently, split header is not supported. */
+               rxd->nqrx_data.nrxd_haddr = 0;
+       } else {
+               wiseman_rxdesc_t *rxd = &rxq->rxq_descs[start];
+
+               wm_set_dma_addr(&rxd->wrx_addr,
+                   rxs->rxs_dmamap->dm_segs[0].ds_addr + sc->sc_align_tweak);
+               rxd->wrx_len = 0;
+               rxd->wrx_cksum = 0;
+               rxd->wrx_status = 0;
+               rxd->wrx_errors = 0;
+               rxd->wrx_special = 0;
+       }
        wm_cdrxsync(rxq, start, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 
        CSR_WRITE(sc, rxq->rxq_rdt_reg, start);
@@ -3721,6 +3746,12 @@
                        reg |= WMREG_RFCTL_NEWIPV6EXDIS |WMREG_RFCTL_IPV6EXDIS;
                        CSR_WRITE(sc, WMREG_RFCTL, reg);
                        break;
+               case WM_T_82574:
+                       /* use extened Rx descriptor. */
+                       reg = CSR_READ(sc, WMREG_RFCTL);
+                       reg |= WMREG_RFCTL_EXSTEN;
+                       CSR_WRITE(sc, WMREG_RFCTL, reg);
+                       break;
                default:
                        break;
                }
@@ -5173,6 +5204,12 @@
            | RCTL_MO(sc->sc_mchash_type);
 
        /*
+        * 82574 use one buffer extended Rx descriptor.
+        */
+       if (sc->sc_type == WM_T_82574)
+               sc->sc_rctl |= RCTL_DTYP_ONEBUF;
+
+       /*
         * The I350 has a bug where it always strips the CRC whether
         * asked to or not. So ask for stripped CRC here and cope in rxeof
         */
@@ -5558,6 +5595,7 @@
 wm_alloc_rx_descs(struct wm_softc *sc, struct wm_rxqueue *rxq)
 {
        int error;
+       size_t rxq_descs_size;
 
        /*
         * Allocate the control data structures, and create and load the
@@ -5567,8 +5605,16 @@
         * memory.  So must Rx descriptors.  We simplify by allocating
         * both sets within the same 4G segment.
         */
-       rxq->rxq_desc_size = sizeof(wiseman_rxdesc_t) * WM_NRXDESC;
-       if ((error = bus_dmamem_alloc(sc->sc_dmat, rxq->rxq_desc_size,
+       rxq->rxq_ndesc = WM_NRXDESC;
+       if (sc->sc_type == WM_T_82574)
+               rxq->rxq_descsize = sizeof(ext_rxdesc_t);
+       else if ((sc->sc_flags & WM_F_NEWQUEUE) != 0)
+               rxq->rxq_descsize = sizeof(nq_rxdesc_t);
+       else
+               rxq->rxq_descsize = sizeof(wiseman_rxdesc_t);
+       rxq_descs_size = rxq->rxq_descsize * rxq->rxq_ndesc;
+
+       if ((error = bus_dmamem_alloc(sc->sc_dmat, rxq_descs_size,
                    PAGE_SIZE, (bus_size_t) 0x100000000ULL, &rxq->rxq_desc_seg,
                    1, &rxq->rxq_desc_rseg, 0)) != 0) {
                aprint_error_dev(sc->sc_dev,
@@ -5578,15 +5624,15 @@
        }
 
        if ((error = bus_dmamem_map(sc->sc_dmat, &rxq->rxq_desc_seg,
-                   rxq->rxq_desc_rseg, rxq->rxq_desc_size,
-                   (void **)&rxq->rxq_descs, BUS_DMA_COHERENT)) != 0) {
+                   rxq->rxq_desc_rseg, rxq_descs_size,
+                   (void **)&rxq->rxq_descs_u, BUS_DMA_COHERENT)) != 0) {
                aprint_error_dev(sc->sc_dev,
                    "unable to map RX control data, error = %d\n", error);
                goto fail_1;
        }
 
-       if ((error = bus_dmamap_create(sc->sc_dmat, rxq->rxq_desc_size, 1,
-                   rxq->rxq_desc_size, 0, 0, &rxq->rxq_desc_dmamap)) != 0) {
+       if ((error = bus_dmamap_create(sc->sc_dmat, rxq_descs_size, 1,
+                   rxq_descs_size, 0, 0, &rxq->rxq_desc_dmamap)) != 0) {
                aprint_error_dev(sc->sc_dev,
                    "unable to create RX control data DMA map, error = %d\n",
                    error);
@@ -5594,7 +5640,7 @@
        }
 
        if ((error = bus_dmamap_load(sc->sc_dmat, rxq->rxq_desc_dmamap,
-                   rxq->rxq_descs, rxq->rxq_desc_size, NULL, 0)) != 0) {
+                   rxq->rxq_descs_u, rxq_descs_size, NULL, 0)) != 0) {
                aprint_error_dev(sc->sc_dev,
                    "unable to load RX control data DMA map, error = %d\n",
                    error);
@@ -5606,8 +5652,8 @@
  fail_3:
        bus_dmamap_destroy(sc->sc_dmat, rxq->rxq_desc_dmamap);
  fail_2:
-       bus_dmamem_unmap(sc->sc_dmat, (void *)rxq->rxq_descs,
-           rxq->rxq_desc_size);
+       bus_dmamem_unmap(sc->sc_dmat, (void *)rxq->rxq_descs_u,
+           rxq_descs_size);
  fail_1:
        bus_dmamem_free(sc->sc_dmat, &rxq->rxq_desc_seg, rxq->rxq_desc_rseg);
  fail_0:
@@ -5620,8 +5666,8 @@
 
        bus_dmamap_unload(sc->sc_dmat, rxq->rxq_desc_dmamap);
        bus_dmamap_destroy(sc->sc_dmat, rxq->rxq_desc_dmamap);
-       bus_dmamem_unmap(sc->sc_dmat, (void *)rxq->rxq_descs,
-           rxq->rxq_desc_size);
+       bus_dmamem_unmap(sc->sc_dmat, (void *)rxq->rxq_descs_u,
+           rxq->rxq_descsize * rxq->rxq_ndesc);
        bus_dmamem_free(sc->sc_dmat, &rxq->rxq_desc_seg, rxq->rxq_desc_rseg);
 }
 
@@ -5675,7 +5721,7 @@
        int i, error;
 
        /* Create the receive buffer DMA maps. */
-       for (i = 0; i < WM_NRXDESC; i++) {
+       for (i = 0; i < rxq->rxq_ndesc; i++) {
                if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
                            MCLBYTES, 0, 0,
                            &rxq->rxq_soft[i].rxs_dmamap)) != 0) {
@@ -5690,7 +5736,7 @@
        return 0;
 
  fail:
-       for (i = 0; i < WM_NRXDESC; i++) {
+       for (i = 0; i < rxq->rxq_ndesc; i++) {
                if (rxq->rxq_soft[i].rxs_dmamap != NULL)
                        bus_dmamap_destroy(sc->sc_dmat,
                            rxq->rxq_soft[i].rxs_dmamap);
@@ -5703,7 +5749,7 @@
 {
        int i;
 
-       for (i = 0; i < WM_NRXDESC; i++) {
+       for (i = 0; i < rxq->rxq_ndesc; i++) {
                if (rxq->rxq_soft[i].rxs_dmamap != NULL)
                        bus_dmamap_destroy(sc->sc_dmat,
                            rxq->rxq_soft[i].rxs_dmamap);
@@ -5993,7 +6039,7 @@
                CSR_WRITE(sc, WMREG_OLD_RDBAH0, WM_CDRXADDR_HI(rxq, 0));
                CSR_WRITE(sc, WMREG_OLD_RDBAL0, WM_CDRXADDR_LO(rxq, 0));
                CSR_WRITE(sc, WMREG_OLD_RDLEN0,
-                   sizeof(wiseman_rxdesc_t) * WM_NRXDESC);
+                   rxq->rxq_descsize * rxq->rxq_ndesc);
                CSR_WRITE(sc, WMREG_OLD_RDH0, 0);
                CSR_WRITE(sc, WMREG_OLD_RDT0, 0);
                CSR_WRITE(sc, WMREG_OLD_RDTR0, 28 | RDTR_FPD);
@@ -6009,12 +6055,14 @@
 
                CSR_WRITE(sc, WMREG_RDBAH(qid), WM_CDRXADDR_HI(rxq, 0));
                CSR_WRITE(sc, WMREG_RDBAL(qid), WM_CDRXADDR_LO(rxq, 0));
-               CSR_WRITE(sc, WMREG_RDLEN(qid), rxq->rxq_desc_size);
+               CSR_WRITE(sc, WMREG_RDLEN(qid), rxq->rxq_descsize * rxq->rxq_ndesc);
 
                if ((sc->sc_flags & WM_F_NEWQUEUE) != 0) {
                        if (MCLBYTES & ((1 << SRRCTL_BSIZEPKT_SHIFT) - 1))
                                panic("%s: MCLBYTES %d unsupported for i2575 or higher\n", __func__, MCLBYTES);
-                       CSR_WRITE(sc, WMREG_SRRCTL(qid), SRRCTL_DESCTYPE_LEGACY
+
+                       /* Currently, support SRRCTL_DESCTYPE_ADV_ONEBUF only. */
+                       CSR_WRITE(sc, WMREG_SRRCTL(qid), SRRCTL_DESCTYPE_ADV_ONEBUF
                            | (MCLBYTES >> SRRCTL_BSIZEPKT_SHIFT));
                        CSR_WRITE(sc, WMREG_RXDCTL(qid), RXDCTL_QUEUE_ENABLE
                            | RXDCTL_PTHRESH(16) | RXDCTL_HTHRESH(8)
@@ -6042,7 +6090,7 @@
 
        KASSERT(mutex_owned(rxq->rxq_lock));
 
-       for (i = 0; i < WM_NRXDESC; i++) {
+       for (i = 0; i < rxq->rxq_ndesc; i++) {
                rxs = &rxq->rxq_soft[i];
                if (rxs->rxs_mbuf == NULL) {
                        if ((error = wm_add_rxbuf(rxq, i)) != 0) {
@@ -7411,6 +7459,224 @@
        return processed;
 }
 
+static inline uint32_t
+wm_rxdesc_get_status(struct wm_rxqueue *rxq, int idx)
+{
+       struct wm_softc *sc = rxq->rxq_sc;
+
+       if (sc->sc_type == WM_T_82574)
+               return EXTRXC_STATUS(rxq->rxq_ext_descs[idx].erx_ctx.erxc_err_stat);
+       else if ((sc->sc_flags & WM_F_NEWQUEUE) != 0)
+               return NQRXC_STATUS(rxq->rxq_nq_descs[idx].nqrx_ctx.nrxc_err_stat);
+       else



Home | Main Index | Thread Index | Old Index