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