Wed Oct 28 07:08:08 2020 UTC ()
 Add missing drain for pcq in wm_stop_locked(). OK'd by knakahara.

This change fixes two problems:
 1. If the pcq is full and watchdog timer is fired, the full state of the
    pcq is kept and wm_transmit() returns with ENOBUFS.
 2. ifconfig down doesn't free mbufs in the pcq.


(msaitoh)
diff -r1.691 -r1.692 src/sys/dev/pci/if_wm.c

cvs diff -r1.691 -r1.692 src/sys/dev/pci/if_wm.c (expand / switch to unified diff)

--- src/sys/dev/pci/if_wm.c 2020/10/16 05:53:39 1.691
+++ src/sys/dev/pci/if_wm.c 2020/10/28 07:08:08 1.692
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: if_wm.c,v 1.691 2020/10/16 05:53:39 msaitoh Exp $ */ 1/* $NetBSD: if_wm.c,v 1.692 2020/10/28 07:08:08 msaitoh Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. 4 * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -72,27 +72,27 @@ @@ -72,27 +72,27 @@
72 * 72 *
73 * TODO (in order of importance): 73 * TODO (in order of importance):
74 * 74 *
75 * - Check XXX'ed comments 75 * - Check XXX'ed comments
76 * - TX Multi queue improvement (refine queue selection logic) 76 * - TX Multi queue improvement (refine queue selection logic)
77 * - Split header buffer for newer descriptors 77 * - Split header buffer for newer descriptors
78 * - EEE (Energy Efficiency Ethernet) for I354 78 * - EEE (Energy Efficiency Ethernet) for I354
79 * - Virtual Function 79 * - Virtual Function
80 * - Set LED correctly (based on contents in EEPROM) 80 * - Set LED correctly (based on contents in EEPROM)
81 * - Rework how parameters are loaded from the EEPROM. 81 * - Rework how parameters are loaded from the EEPROM.
82 */ 82 */
83 83
84#include <sys/cdefs.h> 84#include <sys/cdefs.h>
85__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.691 2020/10/16 05:53:39 msaitoh Exp $"); 85__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.692 2020/10/28 07:08:08 msaitoh Exp $");
86 86
87#ifdef _KERNEL_OPT 87#ifdef _KERNEL_OPT
88#include "opt_net_mpsafe.h" 88#include "opt_net_mpsafe.h"
89#include "opt_if_wm.h" 89#include "opt_if_wm.h"
90#endif 90#endif
91 91
92#include <sys/param.h> 92#include <sys/param.h>
93#include <sys/systm.h> 93#include <sys/systm.h>
94#include <sys/callout.h> 94#include <sys/callout.h>
95#include <sys/mbuf.h> 95#include <sys/mbuf.h>
96#include <sys/malloc.h> 96#include <sys/malloc.h>
97#include <sys/kmem.h> 97#include <sys/kmem.h>
98#include <sys/kernel.h> 98#include <sys/kernel.h>
@@ -6513,36 +6513,41 @@ wm_stop_locked(struct ifnet *ifp, bool d @@ -6513,36 +6513,41 @@ wm_stop_locked(struct ifnet *ifp, bool d
6513 6513
6514 /* Stop the 82547 Tx FIFO stall check timer. */ 6514 /* Stop the 82547 Tx FIFO stall check timer. */
6515 if (sc->sc_type == WM_T_82547) { 6515 if (sc->sc_type == WM_T_82547) {
6516 if (wait) 6516 if (wait)
6517 callout_halt(&sc->sc_txfifo_ch, sc->sc_core_lock); 6517 callout_halt(&sc->sc_txfifo_ch, sc->sc_core_lock);
6518 else 6518 else
6519 callout_stop(&sc->sc_txfifo_ch); 6519 callout_stop(&sc->sc_txfifo_ch);
6520 } 6520 }
6521 6521
6522 /* Release any queued transmit buffers. */ 6522 /* Release any queued transmit buffers. */
6523 for (qidx = 0; qidx < sc->sc_nqueues; qidx++) { 6523 for (qidx = 0; qidx < sc->sc_nqueues; qidx++) {
6524 struct wm_queue *wmq = &sc->sc_queue[qidx]; 6524 struct wm_queue *wmq = &sc->sc_queue[qidx];
6525 struct wm_txqueue *txq = &wmq->wmq_txq; 6525 struct wm_txqueue *txq = &wmq->wmq_txq;
 6526 struct mbuf *m;
 6527
6526 mutex_enter(txq->txq_lock); 6528 mutex_enter(txq->txq_lock);
6527 txq->txq_sending = false; /* Ensure watchdog disabled */ 6529 txq->txq_sending = false; /* Ensure watchdog disabled */
6528 for (i = 0; i < WM_TXQUEUELEN(txq); i++) { 6530 for (i = 0; i < WM_TXQUEUELEN(txq); i++) {
6529 txs = &txq->txq_soft[i]; 6531 txs = &txq->txq_soft[i];
6530 if (txs->txs_mbuf != NULL) { 6532 if (txs->txs_mbuf != NULL) {
6531 bus_dmamap_unload(sc->sc_dmat,txs->txs_dmamap); 6533 bus_dmamap_unload(sc->sc_dmat,txs->txs_dmamap);
6532 m_freem(txs->txs_mbuf); 6534 m_freem(txs->txs_mbuf);
6533 txs->txs_mbuf = NULL; 6535 txs->txs_mbuf = NULL;
6534 } 6536 }
6535 } 6537 }
 6538 /* Drain txq_interq */
 6539 while ((m = pcq_get(txq->txq_interq)) != NULL)
 6540 m_freem(m);
6536 mutex_exit(txq->txq_lock); 6541 mutex_exit(txq->txq_lock);
6537 } 6542 }
6538 6543
6539 /* Mark the interface as down and cancel the watchdog timer. */ 6544 /* Mark the interface as down and cancel the watchdog timer. */
6540 ifp->if_flags &= ~IFF_RUNNING; 6545 ifp->if_flags &= ~IFF_RUNNING;
6541 6546
6542 if (disable) { 6547 if (disable) {
6543 for (i = 0; i < sc->sc_nqueues; i++) { 6548 for (i = 0; i < sc->sc_nqueues; i++) {
6544 struct wm_rxqueue *rxq = &sc->sc_queue[i].wmq_rxq; 6549 struct wm_rxqueue *rxq = &sc->sc_queue[i].wmq_rxq;
6545 mutex_enter(rxq->rxq_lock); 6550 mutex_enter(rxq->rxq_lock);
6546 wm_rxdrain(rxq); 6551 wm_rxdrain(rxq);
6547 mutex_exit(rxq->rxq_lock); 6552 mutex_exit(rxq->rxq_lock);
6548 } 6553 }