Module Name: src Committed By: knakahara Date: Thu Feb 16 05:36:41 UTC 2017
Modified Files: src/sys/dev/pci: if_wm.c Log Message: fix about IFF_OACTIVE. It is required manipulate IFF_OACTIVE for old ethernet controllers and ALTQ to use if_start. To avoid race, txq_lock of 0th txq is needed to write IFF_OACTIVE. TODO: read side refactor To generate a diff of this commit: cvs rdiff -u -r1.478 -r1.479 src/sys/dev/pci/if_wm.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/if_wm.c diff -u src/sys/dev/pci/if_wm.c:1.478 src/sys/dev/pci/if_wm.c:1.479 --- src/sys/dev/pci/if_wm.c:1.478 Mon Feb 13 05:02:21 2017 +++ src/sys/dev/pci/if_wm.c Thu Feb 16 05:36:41 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wm.c,v 1.478 2017/02/13 05:02:21 knakahara Exp $ */ +/* $NetBSD: if_wm.c,v 1.479 2017/02/16 05:36:41 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.478 2017/02/13 05:02:21 knakahara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.479 2017/02/16 05:36:41 knakahara Exp $"); #ifdef _KERNEL_OPT #include "opt_net_mpsafe.h" @@ -6522,11 +6522,15 @@ wm_send_common_locked(struct ifnet *ifp, bus_size_t seglen, curlen; uint32_t cksumcmd; uint8_t cksumfields; + struct wm_queue *wmq = container_of(txq, struct wm_queue, wmq_txq); + int qid = wmq->wmq_id; KASSERT(mutex_owned(txq->txq_lock)); if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) return; + if ((txq->txq_flags & WM_TXQ_NO_SPACE) != 0) + return; /* Remember the previous number of free descriptors. */ ofree = txq->txq_free; @@ -6635,7 +6639,9 @@ wm_send_common_locked(struct ifnet *ifp, ("%s: TX: need %d (%d) descriptors, have %d\n", device_xname(sc->sc_dev), dmamap->dm_nsegs, segs_needed, txq->txq_free - 1)); - ifp->if_flags |= IFF_OACTIVE; + if (qid == 0) + ifp->if_flags |= IFF_OACTIVE; + txq->txq_flags |= WM_TXQ_NO_SPACE; bus_dmamap_unload(sc->sc_dmat, dmamap); WM_Q_EVCNT_INCR(txq, txdstall); break; @@ -6651,7 +6657,9 @@ wm_send_common_locked(struct ifnet *ifp, DPRINTF(WM_DEBUG_TX, ("%s: TX: 82547 Tx FIFO bug detected\n", device_xname(sc->sc_dev))); - ifp->if_flags |= IFF_OACTIVE; + if (qid == 0) + ifp->if_flags |= IFF_OACTIVE; + txq->txq_flags |= WM_TXQ_NO_SPACE; bus_dmamap_unload(sc->sc_dmat, dmamap); WM_Q_EVCNT_INCR(txq, txfifo_stall); break; @@ -6795,7 +6803,9 @@ wm_send_common_locked(struct ifnet *ifp, } if (m0 != NULL) { - ifp->if_flags |= IFF_OACTIVE; + if (qid == 0) + ifp->if_flags |= IFF_OACTIVE; + txq->txq_flags |= WM_TXQ_NO_SPACE; WM_Q_EVCNT_INCR(txq, txdrop); DPRINTF(WM_DEBUG_TX, ("%s: TX: error after IFQ_DEQUEUE\n", __func__)); @@ -6804,7 +6814,9 @@ wm_send_common_locked(struct ifnet *ifp, if (txq->txq_sfree == 0 || txq->txq_free <= 2) { /* No more slots; notify upper layer. */ - ifp->if_flags |= IFF_OACTIVE; + if (qid == 0) + ifp->if_flags |= IFF_OACTIVE; + txq->txq_flags |= WM_TXQ_NO_SPACE; } if (txq->txq_free != ofree) { @@ -7103,6 +7115,8 @@ wm_nq_send_common_locked(struct ifnet *i bus_dmamap_t dmamap; int error, nexttx, lasttx = -1, seg, segs_needed; bool do_csum, sent; + struct wm_queue *wmq = container_of(txq, struct wm_queue, wmq_txq); + int qid = wmq->wmq_id; KASSERT(mutex_owned(txq->txq_lock)); @@ -7196,6 +7210,8 @@ wm_nq_send_common_locked(struct ifnet *i ("%s: TX: need %d (%d) descriptors, have %d\n", device_xname(sc->sc_dev), dmamap->dm_nsegs, segs_needed, txq->txq_free - 1)); + if (qid == 0) + ifp->if_flags |= IFF_OACTIVE; txq->txq_flags |= WM_TXQ_NO_SPACE; bus_dmamap_unload(sc->sc_dmat, dmamap); WM_Q_EVCNT_INCR(txq, txdstall); @@ -7353,6 +7369,8 @@ wm_nq_send_common_locked(struct ifnet *i } if (m0 != NULL) { + if (qid == 0) + ifp->if_flags |= IFF_OACTIVE; txq->txq_flags |= WM_TXQ_NO_SPACE; WM_Q_EVCNT_INCR(txq, txdrop); DPRINTF(WM_DEBUG_TX, ("%s: TX: error after IFQ_DEQUEUE\n", @@ -7362,6 +7380,8 @@ wm_nq_send_common_locked(struct ifnet *i if (txq->txq_sfree == 0 || txq->txq_free <= 2) { /* No more slots; notify upper layer. */ + if (qid == 0) + ifp->if_flags |= IFF_OACTIVE; txq->txq_flags |= WM_TXQ_NO_SPACE; } @@ -7430,15 +7450,16 @@ wm_txeof(struct wm_softc *sc, struct wm_ int count = 0; int i; uint8_t status; + struct wm_queue *wmq = container_of(txq, struct wm_queue, wmq_txq); KASSERT(mutex_owned(txq->txq_lock)); if (txq->txq_stopping) return 0; - if ((sc->sc_flags & WM_F_NEWQUEUE) != 0) - txq->txq_flags &= ~WM_TXQ_NO_SPACE; - else + txq->txq_flags &= ~WM_TXQ_NO_SPACE; + /* for ALTQ and legacy(not use multiqueue) ethernet controller */ + if (wmq->wmq_id == 0) ifp->if_flags &= ~IFF_OACTIVE; /*