Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci Some MP improvements
details: https://anonhg.NetBSD.org/src/rev/527ec044c03c
branches: trunk
changeset: 370080:527ec044c03c
user: skrll <skrll%NetBSD.org@localhost>
date: Fri Sep 16 03:55:53 2022 +0000
description:
Some MP improvements
- Remove use of IFF_OACTIVE
- Remove use of if_timer and provide an MP safe multiqueue watchdog
- Sprinkle some lock assertions.
Tested by ryo@. Thanks.
diffstat:
sys/dev/pci/if_aq.c | 318 ++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 247 insertions(+), 71 deletions(-)
diffs (truncated from 591 to 300 lines):
diff -r 1a5a336379fd -r 527ec044c03c sys/dev/pci/if_aq.c
--- a/sys/dev/pci/if_aq.c Fri Sep 16 03:12:03 2022 +0000
+++ b/sys/dev/pci/if_aq.c Fri Sep 16 03:55:53 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_aq.c,v 1.32 2022/09/08 07:05:42 skrll Exp $ */
+/* $NetBSD: if_aq.c,v 1.33 2022/09/16 03:55:53 skrll Exp $ */
/**
* aQuantia Corporation Network Driver
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.32 2022/09/08 07:05:42 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_aq.c,v 1.33 2022/09/16 03:55:53 skrll Exp $");
#ifdef _KERNEL_OPT
#include "opt_if_aq.h"
@@ -854,6 +854,9 @@
int txr_index;
kmutex_t txr_mutex;
bool txr_active;
+ bool txr_stopping;
+ bool txr_sending;
+ time_t txr_lastsent;
pcq_t *txr_pcq;
void *txr_softint;
@@ -878,6 +881,7 @@
kmutex_t rxr_mutex;
bool rxr_active;
bool rxr_discarding;
+ bool rxr_stopping;
struct mbuf *rxr_receiving_m; /* receiving jumboframe */
struct mbuf *rxr_receiving_m_last; /* last mbuf of jumboframe */
@@ -934,10 +938,12 @@
#define AQ_LOCK(sc) mutex_enter(&(sc)->sc_mutex);
#define AQ_UNLOCK(sc) mutex_exit(&(sc)->sc_mutex);
+#define AQ_LOCKED(sc) KASSERT(mutex_owned(&(sc)->sc_mutex));
/* lock for FW2X_MPI_{CONTROL,STATE]_REG read-modify-write */
#define AQ_MPI_LOCK(sc) mutex_enter(&(sc)->sc_mpi_mutex);
#define AQ_MPI_UNLOCK(sc) mutex_exit(&(sc)->sc_mpi_mutex);
+#define AQ_MPI_LOCKED(sc) KASSERT(mutex_owned(&(sc)->sc_mpi_mutex));
struct aq_softc {
@@ -1018,6 +1024,15 @@
int sc_ec_capenable; /* last ec_capenable */
unsigned short sc_if_flags; /* last if_flags */
+ bool sc_tx_sending;
+ bool sc_stopping;
+
+ struct workqueue *sc_reset_wq;
+ struct work sc_reset_work;
+ volatile unsigned sc_reset_pending;
+
+ bool sc_trigger_reset;
+
#ifdef AQ_EVENT_COUNTERS
aq_hw_stats_s_t sc_statistics[2];
int sc_statistics_idx;
@@ -1059,13 +1074,14 @@
static int aq_vlan_cb(struct ethercom *ec, uint16_t vid, bool set);
static int aq_ifflags_cb(struct ethercom *);
static int aq_init(struct ifnet *);
+static int aq_init_locked(struct ifnet *);
static void aq_send_common_locked(struct ifnet *, struct aq_softc *,
struct aq_txring *, bool);
static int aq_transmit(struct ifnet *, struct mbuf *);
static void aq_deferred_transmit(void *);
static void aq_start(struct ifnet *);
static void aq_stop(struct ifnet *, int);
-static void aq_watchdog(struct ifnet *);
+static void aq_stop_locked(struct ifnet *, bool);
static int aq_ioctl(struct ifnet *, unsigned long, void *);
static int aq_txrx_rings_alloc(struct aq_softc *);
@@ -1076,6 +1092,10 @@
static void aq_initmedia(struct aq_softc *);
static void aq_enable_intr(struct aq_softc *, bool, bool);
+static void aq_handle_reset_work(struct work *, void *);
+static void aq_unset_stopping_flags(struct aq_softc *);
+static void aq_set_stopping_flags(struct aq_softc *);
+
#if NSYSMON_ENVSYS > 0
static void aq_temp_refresh(struct sysmon_envsys *, envsys_data_t *);
#endif
@@ -1119,6 +1139,12 @@
static int fw2x_get_temperature(struct aq_softc *, uint32_t *);
#endif
+#ifndef AQ_WATCHDOG_TIMEOUT
+#define AQ_WATCHDOG_TIMEOUT 5
+#endif
+static int aq_watchdog_timeout = AQ_WATCHDOG_TIMEOUT;
+
+
static const struct aq_firmware_ops aq_fw1x_ops = {
.reset = fw1x_reset,
.set_mode = fw1x_set_mode,
@@ -1370,9 +1396,20 @@
if (error != 0)
goto attach_failure;
- callout_init(&sc->sc_tick_ch, 0);
+ callout_init(&sc->sc_tick_ch, CALLOUT_MPSAFE);
callout_setfunc(&sc->sc_tick_ch, aq_tick, sc);
+ char wqname[MAXCOMLEN];
+ snprintf(wqname, sizeof(wqname), "%sReset", device_xname(sc->sc_dev));
+ error = workqueue_create(&sc->sc_reset_wq, wqname,
+ aq_handle_reset_work, sc, PRI_SOFTNET, IPL_SOFTCLOCK,
+ WQ_MPSAFE);
+ if (error) {
+ aprint_error_dev(sc->sc_dev,
+ "unable to create reset workqueue\n");
+ goto attach_failure;
+ }
+
sc->sc_intr_moderation_enable = CONFIG_INTR_MODERATION_ENABLE;
if (sc->sc_msix && (sc->sc_nqueues > 1))
@@ -1423,7 +1460,7 @@
ifp->if_transmit = aq_transmit;
ifp->if_start = aq_start;
ifp->if_stop = aq_stop;
- ifp->if_watchdog = aq_watchdog;
+ ifp->if_watchdog = NULL;
IFQ_SET_READY(&ifp->if_snd);
/* initialize capabilities */
@@ -1551,9 +1588,7 @@
if (sc->sc_iosize != 0) {
if (ifp->if_softc != NULL) {
- const int s = splnet();
aq_stop(ifp, 0);
- splx(s);
}
for (i = 0; i < AQ_NINTR_MAX; i++) {
@@ -2753,6 +2788,7 @@
aq_ifmedia_change(struct ifnet * const ifp)
{
struct aq_softc * const sc = ifp->if_softc;
+
aq_link_speed_t rate = AQ_LINK_NONE;
aq_link_fc_t fc = AQ_FC_NONE;
aq_link_eee_t eee = AQ_EEE_DISABLE;
@@ -3828,10 +3864,67 @@
}
#endif
+
+
+static bool
+aq_watchdog_check(struct aq_softc * const sc)
+{
+
+ AQ_LOCKED(sc);
+
+ bool ok = true;
+ for (u_int n = 0; n < sc->sc_nqueues; n++) {
+ struct aq_txring *txring = &sc->sc_queue[n].txring;
+
+ mutex_enter(&txring->txr_mutex);
+ if (txring->txr_sending &&
+ time_uptime - txring->txr_lastsent > aq_watchdog_timeout)
+ ok = false;
+
+ mutex_exit(&txring->txr_mutex);
+
+ if (!ok)
+ return false;
+ }
+
+ if (sc->sc_trigger_reset) {
+ /* debug operation, no need for atomicity or reliability */
+ sc->sc_trigger_reset = 0;
+ return false;
+ }
+
+ return true;
+}
+
+
+
+static bool
+aq_watchdog_tick(struct ifnet *ifp)
+{
+ struct aq_softc * const sc = ifp->if_softc;
+
+ AQ_LOCKED(sc);
+
+ if (!sc->sc_trigger_reset && aq_watchdog_check(sc))
+ return true;
+
+ if (atomic_swap_uint(&sc->sc_reset_pending, 1) == 0) {
+ workqueue_enqueue(sc->sc_reset_wq, &sc->sc_reset_work, NULL);
+ }
+
+ return false;
+}
+
static void
aq_tick(void *arg)
{
- struct aq_softc *sc = arg;
+ struct aq_softc * const sc = arg;
+
+ AQ_LOCK(sc);
+ if (sc->sc_stopping) {
+ AQ_UNLOCK(sc);
+ return;
+ }
if (sc->sc_poll_linkstat || sc->sc_detect_linkstat) {
sc->sc_detect_linkstat = false;
@@ -3843,13 +3936,12 @@
aq_update_statistics(sc);
#endif
- if (sc->sc_poll_linkstat
-#ifdef AQ_EVENT_COUNTERS
- || sc->sc_poll_statistics
-#endif
- ) {
+ struct ifnet * const ifp = &sc->sc_ethercom.ec_if;
+ const bool ok = aq_watchdog_tick(ifp);
+ if (ok)
callout_schedule(&sc->sc_tick_ch, hz);
- }
+
+ AQ_UNLOCK(sc);
}
/* interrupt enable/disable */
@@ -3931,7 +4023,7 @@
static int
aq_link_intr(void *arg)
{
- struct aq_softc *sc = arg;
+ struct aq_softc * const sc = arg;
uint32_t status;
int nintr = 0;
@@ -4229,6 +4321,7 @@
hw_head = AQ_READ_REG_BIT(sc, TX_DMA_DESC_HEAD_PTR_REG(ringidx),
TX_DMA_DESC_HEAD_PTR);
if (hw_head == txring->txr_considx) {
+ txring->txr_sending = false;
goto tx_intr_done;
}
@@ -4256,12 +4349,9 @@
IF_STAT_PUTREF(ifp);
- if (ringidx == 0 && txring->txr_nfree >= AQ_TXD_MIN)
- ifp->if_flags &= ~IFF_OACTIVE;
-
/* no more pending TX packet, cancel watchdog */
if (txring->txr_nfree >= AQ_TXD_NUM)
- ifp->if_timer = 0;
+ txring->txr_sending = false;
tx_intr_done:
mutex_exit(&txring->txr_mutex);
@@ -4536,16 +4626,32 @@
return error;
}
+
static int
aq_init(struct ifnet *ifp)
{
struct aq_softc * const sc = ifp->if_softc;
- int i, error = 0;
-
- aq_stop(ifp, false);
AQ_LOCK(sc);
+ int ret = aq_init_locked(ifp);
+
+ AQ_UNLOCK(sc);
+
+ return ret;
+}
+
+static int
+aq_init_locked(struct ifnet *ifp)
+{
+ struct aq_softc * const sc = ifp->if_softc;
+ int i, error = 0;
Home |
Main Index |
Thread Index |
Old Index