Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci Change DMA physical address in wm_flush_desc_rin...



details:   https://anonhg.NetBSD.org/src/rev/bc8cae101de9
branches:  trunk
changeset: 989922:bc8cae101de9
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Wed Oct 20 08:02:07 2021 +0000

description:
Change DMA physical address in wm_flush_desc_rings() to match other OSes.

 - Even without this change, the workaround works with my machines.
 - Add comment.

diffstat:

 sys/dev/pci/if_wm.c |  31 ++++++++++++++++++++++++-------
 1 files changed, 24 insertions(+), 7 deletions(-)

diffs (73 lines):

diff -r 777e7749bd08 -r bc8cae101de9 sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Wed Oct 20 07:04:28 2021 +0000
+++ b/sys/dev/pci/if_wm.c       Wed Oct 20 08:02:07 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.712 2021/10/20 07:04:28 knakahara Exp $    */
+/*     $NetBSD: if_wm.c,v 1.713 2021/10/20 08:02:07 msaitoh Exp $      */
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -82,7 +82,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.712 2021/10/20 07:04:28 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.713 2021/10/20 08:02:07 msaitoh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -4852,8 +4852,15 @@
 }
 
 /*
- * Only used by WM_T_PCH_SPT which does not use multiqueue,
- * so it is enough to check sc->sc_queue[0] only.
+ * wm_flush_desc_rings - remove all descriptors from the descriptor rings.
+ *
+ * In i219, the descriptor rings must be emptied before resetting the HW
+ * or before changing the device state to D3 during runtime (runtime PM).
+ *
+ * Failure to do this will cause the HW to enter a unit hang state which can
+ * only be released by PCI reset on the device.
+ *
+ * I219 does not use multiqueue, so it is enough to check sc->sc_queue[0] only.
  */
 static void
 wm_flush_desc_rings(struct wm_softc *sc)
@@ -4875,7 +4882,14 @@
        if (((preg & DESCRING_STATUS_FLUSH_REQ) == 0) || (reg == 0))
                return;
 
-       /* TX */
+       /*
+        * Remove all descriptors from the tx_ring.
+        *
+        * We want to clear all pending descriptors from the TX ring. Zeroing
+        * happens when the HW reads the regs. We  assign the ring itself as
+        * the data of the next descriptor. We don't care about the data we are
+        * about to reset the HW.
+        */
        device_printf(sc->sc_dev, "Need TX flush (reg = %08x, len = %u)\n",
            preg, reg);
        reg = CSR_READ(sc, WMREG_TCTL);
@@ -4884,7 +4898,7 @@
        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));
+       wm_set_dma_addr(&txd->wtx_addr, txq->txq_desc_dma);
        txd->wtx_cmdlen = htole32(WTX_CMD_IFCS | 512);
        txd->wtx_fields.wtxu_status = 0;
        txd->wtx_fields.wtxu_options = 0;
@@ -4903,7 +4917,10 @@
        if ((preg & DESCRING_STATUS_FLUSH_REQ) == 0)
                return;
 
-       /* RX */
+       /*
+        * Mark all descriptors in the RX ring as consumed and disable the
+        * rx ring.
+        */
        device_printf(sc->sc_dev, "Need RX flush (reg = %08x)\n", preg);
        rctl = CSR_READ(sc, WMREG_RCTL);
        CSR_WRITE(sc, WMREG_RCTL, rctl & ~RCTL_EN);



Home | Main Index | Thread Index | Old Index