Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci Fix a bug that RX and TX may stall on heavy load...



details:   https://anonhg.NetBSD.org/src/rev/8da4aff4b0d8
branches:  trunk
changeset: 829840:8da4aff4b0d8
user:      knakahara <knakahara%NetBSD.org@localhost>
date:      Wed Feb 14 12:56:00 2018 +0000

description:
Fix a bug that RX and TX may stall on heavy load on wm(4) like ixgbe.c:r1.121.

wm_rxeof() and wm_txeof() have loop limit and the function returns true
if a packet still exists.

XXX need pullup-8

diffstat:

 sys/dev/pci/if_wm.c |  55 +++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 39 insertions(+), 16 deletions(-)

diffs (182 lines):

diff -r 3a126a4818cc -r 8da4aff4b0d8 sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Wed Feb 14 12:47:43 2018 +0000
+++ b/sys/dev/pci/if_wm.c       Wed Feb 14 12:56:00 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.562 2018/01/30 08:15:47 knakahara Exp $    */
+/*     $NetBSD: if_wm.c,v 1.563 2018/02/14 12:56:00 knakahara Exp $    */
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -83,7 +83,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.562 2018/01/30 08:15:47 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.563 2018/02/14 12:56:00 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -775,8 +775,8 @@
 static void    wm_deferred_start_locked(struct wm_txqueue *);
 static void    wm_handle_queue(void *);
 /* Interrupt */
-static int     wm_txeof(struct wm_txqueue *, u_int);
-static void    wm_rxeof(struct wm_rxqueue *, u_int);
+static bool    wm_txeof(struct wm_txqueue *, u_int);
+static bool    wm_rxeof(struct wm_rxqueue *, u_int);
 static void    wm_linkintr_gmii(struct wm_softc *, uint32_t);
 static void    wm_linkintr_tbi(struct wm_softc *, uint32_t);
 static void    wm_linkintr_serdes(struct wm_softc *, uint32_t);
@@ -8066,7 +8066,7 @@
  *
  *     Helper; handle transmit interrupts.
  */
-static int
+static bool
 wm_txeof(struct wm_txqueue *txq, u_int limit)
 {
        struct wm_softc *sc = txq->txq_sc;
@@ -8076,11 +8076,12 @@
        int i;
        uint8_t status;
        struct wm_queue *wmq = container_of(txq, struct wm_queue, wmq_txq);
+       bool more = false;
 
        KASSERT(mutex_owned(txq->txq_lock));
 
        if (txq->txq_stopping)
-               return 0;
+               return false;
 
        txq->txq_flags &= ~WM_TXQ_NO_SPACE;
        /* for ALTQ and legacy(not use multiqueue) ethernet controller */
@@ -8093,8 +8094,13 @@
         */
        for (i = txq->txq_sdirty; txq->txq_sfree != WM_TXQUEUELEN(txq);
             i = WM_NEXTTXS(txq, i), txq->txq_sfree++) {
-               if (limit-- == 0)
-                       break;
+               if (limit-- == 0) {
+                       more = true;
+                       DPRINTF(WM_DEBUG_TX,
+                           ("%s: TX: loop limited, job %d is not processed\n",
+                               device_xname(sc->sc_dev), i));
+                       break;
+               }
 
                txs = &txq->txq_soft[i];
 
@@ -8168,7 +8174,7 @@
        if (txq->txq_sfree == WM_TXQUEUELEN(txq))
                txq->txq_watchdog = false;
 
-       return count;
+       return more;
 }
 
 static inline uint32_t
@@ -8381,7 +8387,7 @@
  *
  *     Helper; handle receive interrupts.
  */
-static void
+static bool
 wm_rxeof(struct wm_rxqueue *rxq, u_int limit)
 {
        struct wm_softc *sc = rxq->rxq_sc;
@@ -8392,12 +8398,17 @@
        int count = 0;
        uint32_t status, errors;
        uint16_t vlantag;
+       bool more = false;
 
        KASSERT(mutex_owned(rxq->rxq_lock));
 
        for (i = rxq->rxq_ptr;; i = WM_NEXTRX(i)) {
                if (limit-- == 0) {
                        rxq->rxq_ptr = i;
+                       more = true;
+                       DPRINTF(WM_DEBUG_RX,
+                           ("%s: RX: loop limited, descriptor %d is not processed\n",
+                               device_xname(sc->sc_dev), i));
                        break;
                }
 
@@ -8571,6 +8582,8 @@
 
        DPRINTF(WM_DEBUG_RX,
            ("%s: RX: rxptr -> %d\n", device_xname(sc->sc_dev), i));
+
+       return more;
 }
 
 /*
@@ -9009,6 +9022,8 @@
        struct wm_softc *sc = txq->txq_sc;
        u_int txlimit = sc->sc_tx_intr_process_limit;
        u_int rxlimit = sc->sc_rx_intr_process_limit;
+       bool txmore;
+       bool rxmore;
 
        KASSERT(wmq->wmq_intr_idx == wmq->wmq_id);
 
@@ -9025,7 +9040,7 @@
        }
 
        WM_Q_EVCNT_INCR(txq, txdw);
-       wm_txeof(txq, txlimit);
+       txmore = wm_txeof(txq, txlimit);
        /* wm_deferred start() is done in wm_handle_queue(). */
        mutex_exit(txq->txq_lock);
 
@@ -9039,12 +9054,15 @@
        }
 
        WM_Q_EVCNT_INCR(rxq, rxintr);
-       wm_rxeof(rxq, rxlimit);
+       rxmore = wm_rxeof(rxq, rxlimit);
        mutex_exit(rxq->rxq_lock);
 
        wm_itrs_writereg(sc, wmq);
 
-       softint_schedule(wmq->wmq_si);
+       if (txmore || rxmore)
+               softint_schedule(wmq->wmq_si);
+       else
+               wm_txrxintr_enable(wmq);
 
        return 1;
 }
@@ -9058,13 +9076,15 @@
        struct wm_softc *sc = txq->txq_sc;
        u_int txlimit = sc->sc_tx_process_limit;
        u_int rxlimit = sc->sc_rx_process_limit;
+       bool txmore;
+       bool rxmore;
 
        mutex_enter(txq->txq_lock);
        if (txq->txq_stopping) {
                mutex_exit(txq->txq_lock);
                return;
        }
-       wm_txeof(txq, txlimit);
+       txmore = wm_txeof(txq, txlimit);
        wm_deferred_start_locked(txq);
        mutex_exit(txq->txq_lock);
 
@@ -9074,10 +9094,13 @@
                return;
        }
        WM_Q_EVCNT_INCR(rxq, rxdefer);
-       wm_rxeof(rxq, rxlimit);
+       rxmore = wm_rxeof(rxq, rxlimit);
        mutex_exit(rxq->rxq_lock);
 
-       wm_txrxintr_enable(wmq);
+       if (txmore || rxmore)
+               softint_schedule(wmq->wmq_si);
+       else
+               wm_txrxintr_enable(wmq);
 }
 
 /*



Home | Main Index | Thread Index | Old Index