Author: yongari
Date: Wed Nov 23 22:07:13 2011
New Revision: 227914
URL: http://svn.freebsd.org/changeset/base/227914

Log:
  Make sure to stop TX MAC before freeing queued TX frames.
  For RTL8111DP, check if the TX MAC is active by reading RL_GTXSTART
  register.  For RTL8402/8168E-VL/8168F/8411, wait until TX queue is
  empty.

Modified:
  head/sys/dev/re/if_re.c
  head/sys/pci/if_rlreg.h

Modified: head/sys/dev/re/if_re.c
==============================================================================
--- head/sys/dev/re/if_re.c     Wed Nov 23 22:05:44 2011        (r227913)
+++ head/sys/dev/re/if_re.c     Wed Nov 23 22:07:13 2011        (r227914)
@@ -1401,13 +1401,18 @@ re_attach(device_t dev)
                    RL_FLAG_AUTOPAD | RL_FLAG_MACSLEEP;
                break;
        case RL_HWREV_8401E:
-       case RL_HWREV_8402:
        case RL_HWREV_8105E:
        case RL_HWREV_8105E_SPIN1:
                sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PHYWAKE_PM |
                    RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT |
                    RL_FLAG_FASTETHER | RL_FLAG_CMDSTOP | RL_FLAG_AUTOPAD;
                break;
+       case RL_HWREV_8402:
+               sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PHYWAKE_PM |
+                   RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT |
+                   RL_FLAG_FASTETHER | RL_FLAG_CMDSTOP | RL_FLAG_AUTOPAD |
+                   RL_FLAG_CMDSTOP_WAIT_TXQ;
+               break;
        case RL_HWREV_8168B_SPIN1:
        case RL_HWREV_8168B_SPIN2:
                sc->rl_flags |= RL_FLAG_WOLRXENB;
@@ -1424,11 +1429,15 @@ re_attach(device_t dev)
                /* FALLTHROUGH */
        case RL_HWREV_8168CP:
        case RL_HWREV_8168D:
-       case RL_HWREV_8168DP:
                sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR |
                    RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_CMDSTOP |
                    RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2;
                break;
+       case RL_HWREV_8168DP:
+               sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR |
+                   RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_AUTOPAD |
+                   RL_FLAG_JUMBOV2 | RL_FLAG_WAIT_TXPOLL;
+               break;
        case RL_HWREV_8168E:
                sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PHYWAKE_PM |
                    RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT |
@@ -1439,7 +1448,8 @@ re_attach(device_t dev)
        case RL_HWREV_8411:
                sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR |
                    RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_CMDSTOP |
-                   RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2;
+                   RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2 |
+                   RL_FLAG_CMDSTOP_WAIT_TXQ;
                break;
        case RL_HWREV_8169_8110SB:
        case RL_HWREV_8169_8110SBL:
@@ -3466,10 +3476,32 @@ re_stop(struct rl_softc *sc)
            ~(RL_RXCFG_RX_ALLPHYS | RL_RXCFG_RX_INDIV | RL_RXCFG_RX_MULTI |
            RL_RXCFG_RX_BROAD));
 
-       if ((sc->rl_flags & RL_FLAG_CMDSTOP) != 0)
+       if ((sc->rl_flags & RL_FLAG_WAIT_TXPOLL) != 0) {
+               for (i = RL_TIMEOUT; i > 0; i--) {
+                       if ((CSR_READ_1(sc, sc->rl_txstart) &
+                           RL_TXSTART_START) == 0)
+                               break;
+                       DELAY(20);
+               }
+               if (i == 0)
+                       device_printf(sc->rl_dev,
+                           "stopping TX poll timed out!\n");
+               CSR_WRITE_1(sc, RL_COMMAND, 0x00);
+       } else if ((sc->rl_flags & RL_FLAG_CMDSTOP) != 0) {
                CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_STOPREQ | RL_CMD_TX_ENB |
                    RL_CMD_RX_ENB);
-       else
+               if ((sc->rl_flags & RL_FLAG_CMDSTOP_WAIT_TXQ) != 0) {
+                       for (i = RL_TIMEOUT; i > 0; i--) {
+                               if ((CSR_READ_4(sc, RL_TXCFG) &
+                                   RL_TXCFG_QUEUE_EMPTY) != 0)
+                                       break;
+                               DELAY(100);
+                       }
+                       if (i == 0)
+                               device_printf(sc->rl_dev,
+                                  "stopping TXQ timed out!\n");
+               }
+       } else
                CSR_WRITE_1(sc, RL_COMMAND, 0x00);
        DELAY(1000);
        CSR_WRITE_2(sc, RL_IMR, 0x0000);

Modified: head/sys/pci/if_rlreg.h
==============================================================================
--- head/sys/pci/if_rlreg.h     Wed Nov 23 22:05:44 2011        (r227913)
+++ head/sys/pci/if_rlreg.h     Wed Nov 23 22:07:13 2011        (r227914)
@@ -143,6 +143,7 @@
  */
 #define        RL_TXCFG_CLRABRT        0x00000001      /* retransmit aborted 
pkt */
 #define        RL_TXCFG_MAXDMA         0x00000700      /* max DMA burst size */
+#define        RL_TXCFG_QUEUE_EMPTY    0x00000800      /* 8168E-VL or higher */
 #define        RL_TXCFG_CRCAPPEND      0x00010000      /* CRC append (0 = yes) 
*/
 #define        RL_TXCFG_LOOPBKTST      0x00060000      /* loopback test */
 #define        RL_TXCFG_IFG2           0x00080000      /* 8169 only */
@@ -897,22 +898,24 @@ struct rl_softc {
        int                     rl_int_rx_act;
        int                     rl_int_rx_mod;
        uint32_t                rl_flags;
-#define        RL_FLAG_MSI             0x0001
-#define        RL_FLAG_AUTOPAD         0x0002
-#define        RL_FLAG_PHYWAKE_PM      0x0004
-#define        RL_FLAG_PHYWAKE         0x0008
-#define        RL_FLAG_JUMBOV2         0x0010
-#define        RL_FLAG_PAR             0x0020
-#define        RL_FLAG_DESCV2          0x0040
-#define        RL_FLAG_MACSTAT         0x0080
-#define        RL_FLAG_FASTETHER       0x0100
-#define        RL_FLAG_CMDSTOP         0x0200
-#define        RL_FLAG_MACRESET        0x0400
-#define        RL_FLAG_MSIX            0x0800
-#define        RL_FLAG_WOLRXENB        0x1000
-#define        RL_FLAG_MACSLEEP        0x2000
-#define        RL_FLAG_PCIE            0x4000
-#define        RL_FLAG_LINK            0x8000
+#define        RL_FLAG_MSI             0x00000001
+#define        RL_FLAG_AUTOPAD         0x00000002
+#define        RL_FLAG_PHYWAKE_PM      0x00000004
+#define        RL_FLAG_PHYWAKE         0x00000008
+#define        RL_FLAG_JUMBOV2         0x00000010
+#define        RL_FLAG_PAR             0x00000020
+#define        RL_FLAG_DESCV2          0x00000040
+#define        RL_FLAG_MACSTAT         0x00000080
+#define        RL_FLAG_FASTETHER       0x00000100
+#define        RL_FLAG_CMDSTOP         0x00000200
+#define        RL_FLAG_MACRESET        0x00000400
+#define        RL_FLAG_MSIX            0x00000800
+#define        RL_FLAG_WOLRXENB        0x00001000
+#define        RL_FLAG_MACSLEEP        0x00002000
+#define        RL_FLAG_WAIT_TXPOLL     0x00004000
+#define        RL_FLAG_CMDSTOP_WAIT_TXQ        0x00008000
+#define        RL_FLAG_PCIE            0x40000000
+#define        RL_FLAG_LINK            0x80000000
 };
 
 #define        RL_LOCK(_sc)            mtx_lock(&(_sc)->rl_mtx)
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to