Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci - Move I219 DMA workaround into wm_flush_desc_ri...



details:   https://anonhg.NetBSD.org/src/rev/a54a52a0ba6e
branches:  trunk
changeset: 818965:a54a52a0ba6e
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Thu Nov 10 08:35:24 2016 +0000

description:
- Move I219 DMA workaround into wm_flush_desc_rings() and call it before
  wm_reset().
- Rewite I219 TX DMA workaround based on OpenBSD's one.
- Add I219 RX DMA workaroud from OpenBSD.

diffstat:

 sys/dev/pci/if_wm.c |  128 +++++++++++++++++++++++++++++++++------------------
 1 files changed, 83 insertions(+), 45 deletions(-)

diffs (170 lines):

diff -r 0e355d144199 -r a54a52a0ba6e sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Thu Nov 10 06:57:15 2016 +0000
+++ b/sys/dev/pci/if_wm.c       Thu Nov 10 08:35:24 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.442 2016/11/10 06:57:15 msaitoh Exp $      */
+/*     $NetBSD: if_wm.c,v 1.443 2016/11/10 08:35:24 msaitoh 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.442 2016/11/10 06:57:15 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.443 2016/11/10 08:35:24 msaitoh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -637,6 +637,7 @@
 static void    wm_get_cfg_done(struct wm_softc *);
 static void    wm_initialize_hardware_bits(struct wm_softc *);
 static uint32_t        wm_rxpbs_adjust_82580(uint32_t);
+static void    wm_flush_desc_rings(struct wm_softc *);
 static void    wm_reset(struct wm_softc *);
 static int     wm_add_rxbuf(struct wm_rxqueue *, int);
 static void    wm_rxdrain(struct wm_rxqueue *);
@@ -3742,6 +3743,82 @@
        return rv;
 }
 
+static void
+wm_flush_desc_rings(struct wm_softc *sc)
+{
+       pcireg_t preg;
+       uint32_t reg;
+       int nexttx;
+
+       /* First, disable MULR fix in FEXTNVM11 */
+       reg = CSR_READ(sc, WMREG_FEXTNVM11);
+       reg |= FEXTNVM11_DIS_MULRFIX;
+       CSR_WRITE(sc, WMREG_FEXTNVM11, reg);
+
+       preg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, WM_PCI_DESCRING_STATUS);
+       reg = CSR_READ(sc, WMREG_TDLEN(0));
+       if (((preg & DESCRING_STATUS_FLUSH_REQ) != 0) && (reg != 0)) {
+               struct wm_txqueue *txq;
+               wiseman_txdesc_t *txd;
+
+               /* TX */
+               printf("%s: Need TX flush (reg = %08x, len = %u)\n",
+                   device_xname(sc->sc_dev), preg, reg);
+               reg = CSR_READ(sc, WMREG_TCTL);
+               CSR_WRITE(sc, WMREG_TCTL, reg | TCTL_EN);
+
+               txq = &sc->sc_queue[0].wmq_txq;
+               nexttx = txq->txq_next;
+               txd = &txq->txq_descs[nexttx];
+               wm_set_dma_addr(&txd->wtx_addr, WM_CDTXADDR(txq, nexttx));
+               txd->wtx_cmdlen = htole32(WTX_CMD_IFCS| 512);
+               txd->wtx_fields.wtxu_status = 0;
+               txd->wtx_fields.wtxu_options = 0;
+               txd->wtx_fields.wtxu_vlan = 0;
+
+               bus_space_barrier(sc->sc_st, sc->sc_sh, 0, 0,
+                       BUS_SPACE_BARRIER_WRITE);
+               
+               txq->txq_next = WM_NEXTTX(txq, txq->txq_next);
+               CSR_WRITE(sc, WMREG_TDT(0), txq->txq_next);
+               bus_space_barrier(sc->sc_st, sc->sc_sh, 0, 0,
+                       BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
+               delay(250);
+       }
+       preg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, WM_PCI_DESCRING_STATUS);
+       if (preg & DESCRING_STATUS_FLUSH_REQ) {
+               uint32_t rctl;
+
+               /* RX */
+               printf("%s: Need RX flush (reg = %08x)\n",
+                   device_xname(sc->sc_dev), preg);
+               rctl = CSR_READ(sc, WMREG_RCTL);
+               CSR_WRITE(sc, WMREG_RCTL, rctl & ~RCTL_EN);
+               CSR_WRITE_FLUSH(sc);
+               delay(150);
+
+               reg = CSR_READ(sc, WMREG_RXDCTL(0));
+               /* zero the lower 14 bits (prefetch and host thresholds) */
+               reg &= 0xffffc000;
+               /*
+                * update thresholds: prefetch threshold to 31, host threshold
+                * to 1 and make sure the granularity is "descriptors" and not
+                * "cache lines"
+                */
+               reg |= (0x1f | (1 << 8) | RXDCTL_GRAN);
+               CSR_WRITE(sc, WMREG_RXDCTL(0), reg);
+
+               /*
+                * momentarily enable the RX ring for the changes to take
+                * effect
+                */
+               CSR_WRITE(sc, WMREG_RCTL, rctl | RCTL_EN);
+               CSR_WRITE_FLUSH(sc);
+               delay(150);
+               CSR_WRITE(sc, WMREG_RCTL, rctl & ~RCTL_EN);
+       }
+}
+
 /*
  * wm_reset:
  *
@@ -4663,6 +4740,10 @@
        ifp->if_collisions += CSR_READ(sc, WMREG_COLC);
        ifp->if_ierrors += CSR_READ(sc, WMREG_RXERRC);
 
+       /* PCH_SPT hardware workaround */
+       if (sc->sc_type == WM_T_PCH_SPT)
+               wm_flush_desc_rings(sc);
+
        /* Reset the chip to a known state. */
        wm_reset(sc);
 
@@ -5237,49 +5318,6 @@
                                txs->txs_mbuf = NULL;
                        }
                }
-               if (sc->sc_type == WM_T_PCH_SPT) {
-                       pcireg_t preg;
-                       uint32_t reg;
-                       int nexttx;
-
-                       /* First, disable MULR fix in FEXTNVM11 */
-                       reg = CSR_READ(sc, WMREG_FEXTNVM11);
-                       reg |= FEXTNVM11_DIS_MULRFIX;
-                       CSR_WRITE(sc, WMREG_FEXTNVM11, reg);
-
-                       preg = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
-                           WM_PCI_DESCRING_STATUS);
-                       reg = CSR_READ(sc, WMREG_TDLEN(0));
-                       printf("XXX RST: FLUSH = %08x, len = %u\n",
-                           (uint32_t)(preg & DESCRING_STATUS_FLUSH_REQ), reg);
-                       if (((preg & DESCRING_STATUS_FLUSH_REQ) != 0)
-                           && (reg != 0)) {
-                               /* TX */
-                               printf("XXX need TX flush (reg = %08x)\n",
-                                   preg);
-                               wm_init_tx_descs(sc, txq);
-                               wm_init_tx_regs(sc, wmq, txq);
-                               nexttx = txq->txq_next;
-                               wm_set_dma_addr(
-                                       &txq->txq_descs[nexttx].wtx_addr,
-                                       WM_CDTXADDR(txq, nexttx));
-                               txq->txq_descs[nexttx].wtx_cmdlen
-                                   = htole32(WTX_CMD_IFCS | 512);
-                               wm_cdtxsync(txq, nexttx, 1,
-                                   BUS_DMASYNC_PREREAD |BUS_DMASYNC_PREWRITE);
-                               CSR_WRITE(sc, WMREG_TCTL, TCTL_EN);
-                               CSR_WRITE(sc, WMREG_TDT(0), nexttx);
-                               CSR_WRITE_FLUSH(sc);
-                               delay(250);
-                               CSR_WRITE(sc, WMREG_TCTL, 0);
-                       }
-                       preg = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
-                           WM_PCI_DESCRING_STATUS);
-                       if (preg & DESCRING_STATUS_FLUSH_REQ) {
-                               /* RX */
-                               printf("XXX need RX flush\n");
-                       }
-               }
                mutex_exit(txq->txq_lock);
        }
 



Home | Main Index | Thread Index | Old Index