Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci/ixgbe Reduce ixgbe's busy loop using with workqu...
details: https://anonhg.NetBSD.org/src/rev/e2f2126ea0b1
branches: trunk
changeset: 935116:e2f2126ea0b1
user: msaitoh <msaitoh%NetBSD.org@localhost>
date: Thu Jun 25 07:53:01 2020 +0000
description:
Reduce ixgbe's busy loop using with workqueue and kpause.
- Use workqueue instead of softint to make some functions sleepable.
- Use new workqueue and enqueue it in ixgbe_local_timer() and
ixgbe_recovery_mode_timer() to make them sleepable.
- Make new ixgbe_delay() and use it. This functions sleeps if the time is
more than equals 1 tick. If it's not, do delay().
diffstat:
sys/dev/pci/ixgbe/if_sriov.c | 2 -
sys/dev/pci/ixgbe/ixgbe.c | 414 ++++++++++++++++++++++----------------
sys/dev/pci/ixgbe/ixgbe.h | 42 ++-
sys/dev/pci/ixgbe/ixgbe_netbsd.c | 18 +-
sys/dev/pci/ixgbe/ixgbe_osdep.h | 8 +-
sys/dev/pci/ixgbe/ixv.c | 184 +++++++++++++----
6 files changed, 425 insertions(+), 243 deletions(-)
diffs (truncated from 1372 to 300 lines):
diff -r 1ae12002e1dd -r e2f2126ea0b1 sys/dev/pci/ixgbe/if_sriov.c
--- a/sys/dev/pci/ixgbe/if_sriov.c Thu Jun 25 06:45:10 2020 +0000
+++ b/sys/dev/pci/ixgbe/if_sriov.c Thu Jun 25 07:53:01 2020 +0000
@@ -645,7 +645,6 @@
hw = &adapter->hw;
- IXGBE_CORE_LOCK(adapter);
for (i = 0; i < adapter->num_vfs; i++) {
vf = &adapter->vfs[i];
@@ -660,7 +659,6 @@
ixgbe_process_vf_ack(adapter, vf);
}
}
- IXGBE_CORE_UNLOCK(adapter);
} /* ixgbe_handle_mbx */
int
diff -r 1ae12002e1dd -r e2f2126ea0b1 sys/dev/pci/ixgbe/ixgbe.c
--- a/sys/dev/pci/ixgbe/ixgbe.c Thu Jun 25 06:45:10 2020 +0000
+++ b/sys/dev/pci/ixgbe/ixgbe.c Thu Jun 25 07:53:01 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe.c,v 1.232 2020/06/18 09:00:11 msaitoh Exp $ */
+/* $NetBSD: ixgbe.c,v 1.233 2020/06/25 07:53:01 msaitoh Exp $ */
/******************************************************************************
@@ -179,7 +179,7 @@
static int ixgbe_media_change(struct ifnet *);
static int ixgbe_allocate_pci_resources(struct adapter *,
const struct pci_attach_args *);
-static void ixgbe_free_softint(struct adapter *);
+static void ixgbe_free_workqueue(struct adapter *);
static void ixgbe_get_slot_info(struct adapter *);
static int ixgbe_allocate_msix(struct adapter *,
const struct pci_attach_args *);
@@ -189,12 +189,14 @@
static void ixgbe_free_pciintr_resources(struct adapter *);
static void ixgbe_free_pci_resources(struct adapter *);
static void ixgbe_local_timer(void *);
-static void ixgbe_local_timer1(void *);
+static void ixgbe_handle_timer(struct work *, void *);
static void ixgbe_recovery_mode_timer(void *);
+static void ixgbe_handle_recovery_mode_timer(struct work *, void *);
static int ixgbe_setup_interface(device_t, struct adapter *);
static void ixgbe_config_gpie(struct adapter *);
static void ixgbe_config_dmac(struct adapter *);
static void ixgbe_config_delay_values(struct adapter *);
+static void ixgbe_schedule_admin_tasklet(struct adapter *);
static void ixgbe_config_link(struct adapter *);
static void ixgbe_check_wol_support(struct adapter *);
static int ixgbe_setup_low_power_mode(struct adapter *);
@@ -262,17 +264,17 @@
/* The MSI/MSI-X Interrupt handlers */
static int ixgbe_msix_que(void *);
-static int ixgbe_msix_link(void *);
-
-/* Software interrupts for deferred work */
+static int ixgbe_msix_admin(void *);
+
+/* Event handlers running on workqueue */
static void ixgbe_handle_que(void *);
static void ixgbe_handle_link(void *);
+static void ixgbe_handle_msf(void *);
static void ixgbe_handle_mod(void *);
static void ixgbe_handle_phy(void *);
-static void ixgbe_handle_msf(struct work *, void *);
-
-/* Workqueue handler for deferred work */
+/* Deferred workqueue handlers */
+static void ixgbe_handle_admin(struct work *, void *);
static void ixgbe_handle_que_work(struct work *, void *);
static const ixgbe_vendor_info_t *ixgbe_lookup(const struct pci_attach_args *);
@@ -783,6 +785,7 @@
struct pci_attach_args *pa = aux;
bool unsupported_sfp = false;
const char *str;
+ char wqname[MAXCOMLEN];
char buf[256];
INIT_DEBUGOUT("ixgbe_attach: begin");
@@ -807,11 +810,20 @@
aprint_normal(": %s, Version - %s\n",
ixgbe_strings[ent->index], ixgbe_driver_version);
- /* Core Lock Init*/
+ /* Core Lock Init */
IXGBE_CORE_LOCK_INIT(adapter, device_xname(dev));
- /* Set up the timer callout */
+ /* Set up the timer callout and workqueue */
callout_init(&adapter->timer, IXGBE_CALLOUT_FLAGS);
+ snprintf(wqname, sizeof(wqname), "%s-timer", device_xname(dev));
+ error = workqueue_create(&adapter->timer_wq, wqname,
+ ixgbe_handle_timer, adapter, IXGBE_WORKQUEUE_PRI, IPL_NET,
+ IXGBE_TASKLET_WQ_FLAGS);
+ if (error) {
+ aprint_error_dev(dev,
+ "could not create timer workqueue (%d)\n", error);
+ goto err_out;
+ }
/* Determine hardware revision */
id = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG);
@@ -1100,32 +1112,13 @@
goto err_late;
/* Tasklets for Link, SFP, Multispeed Fiber and Flow Director */
- adapter->link_si = softint_establish(SOFTINT_NET |IXGBE_SOFTINT_FLAGS,
- ixgbe_handle_link, adapter);
- adapter->mod_si = softint_establish(SOFTINT_NET | IXGBE_SOFTINT_FLAGS,
- ixgbe_handle_mod, adapter);
- adapter->phy_si = softint_establish(SOFTINT_NET | IXGBE_SOFTINT_FLAGS,
- ixgbe_handle_phy, adapter);
- if (adapter->feat_en & IXGBE_FEATURE_FDIR)
- adapter->fdir_si =
- softint_establish(SOFTINT_NET | IXGBE_SOFTINT_FLAGS,
- ixgbe_reinit_fdir, adapter);
- if ((adapter->link_si == NULL) || (adapter->mod_si == NULL)
- || (adapter->phy_si == NULL)
- || ((adapter->feat_en & IXGBE_FEATURE_FDIR)
- && (adapter->fdir_si == NULL))) {
- aprint_error_dev(dev,
- "could not establish software interrupts ()\n");
- goto err_out;
- }
- char wqname[MAXCOMLEN];
- snprintf(wqname, sizeof(wqname), "%s-msf", device_xname(dev));
- error = workqueue_create(&adapter->msf_wq, wqname,
- ixgbe_handle_msf, adapter, IXGBE_WORKQUEUE_PRI, IPL_NET,
+ snprintf(wqname, sizeof(wqname), "%s-admin", device_xname(dev));
+ error = workqueue_create(&adapter->admin_wq, wqname,
+ ixgbe_handle_admin, adapter, IXGBE_WORKQUEUE_PRI, IPL_NET,
IXGBE_TASKLET_WQ_FLAGS);
if (error) {
aprint_error_dev(dev,
- "could not create MSF workqueue (%d)\n", error);
+ "could not create admin workqueue (%d)\n", error);
goto err_out;
}
@@ -1235,6 +1228,14 @@
/* Set up the timer callout */
callout_init(&adapter->recovery_mode_timer,
IXGBE_CALLOUT_FLAGS);
+ error = workqueue_create(&adapter->recovery_mode_timer_wq,
+ wqname, ixgbe_handle_recovery_mode_timer, adapter,
+ IXGBE_WORKQUEUE_PRI, IPL_NET, IXGBE_TASKLET_WQ_FLAGS);
+ if (error) {
+ aprint_error_dev(dev, "could not create "
+ "recovery_mode_timer workqueue (%d)\n", error);
+ goto err_out;
+ }
/* Start the task */
callout_reset(&adapter->recovery_mode_timer, hz,
@@ -1252,7 +1253,7 @@
ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext);
- ixgbe_free_softint(adapter);
+ ixgbe_free_workqueue(adapter);
ixgbe_free_pci_resources(adapter);
if (adapter->mta != NULL)
free(adapter->mta, M_DEVBUF);
@@ -1508,13 +1509,13 @@
} /* ixgbe_is_sfp */
static void
-ixgbe_schedule_msf_tasklet(struct adapter *adapter)
+ixgbe_schedule_admin_tasklet(struct adapter *adapter)
{
if (adapter->schedule_wqs_ok) {
- if (!adapter->msf_pending) {
- adapter->msf_pending = true;
- workqueue_enqueue(adapter->msf_wq,
- &adapter->msf_wc, NULL);
+ if (!adapter->admin_pending) {
+ atomic_or_uint(&adapter->admin_pending, 1);
+ workqueue_enqueue(adapter->admin_wq,
+ &adapter->admin_wc, NULL);
}
}
}
@@ -1527,6 +1528,7 @@
{
struct ixgbe_hw *hw = &adapter->hw;
u32 autoneg, err = 0;
+ u32 task_requests = 0;
bool sfp, negotiate = false;
sfp = ixgbe_is_sfp(hw);
@@ -1534,11 +1536,11 @@
if (sfp) {
if (hw->phy.multispeed_fiber) {
ixgbe_enable_tx_laser(hw);
- kpreempt_disable();
- ixgbe_schedule_msf_tasklet(adapter);
- kpreempt_enable();
+ task_requests |= IXGBE_REQUEST_TASK_MSF;
}
- softint_schedule(adapter->mod_si);
+ task_requests |= IXGBE_REQUEST_TASK_MOD;
+ atomic_or_32(&adapter->task_requests, task_requests);
+ ixgbe_schedule_admin_tasklet(adapter);
} else {
struct ifmedia *ifm = &adapter->media;
@@ -1766,16 +1768,16 @@
NULL, xname, "Watchdog timeouts");
evcnt_attach_dynamic(&adapter->tso_err, EVCNT_TYPE_MISC,
NULL, xname, "TSO errors");
- evcnt_attach_dynamic(&adapter->link_irq, EVCNT_TYPE_INTR,
- NULL, xname, "Link MSI-X IRQ Handled");
- evcnt_attach_dynamic(&adapter->link_sicount, EVCNT_TYPE_INTR,
- NULL, xname, "Link softint");
- evcnt_attach_dynamic(&adapter->mod_sicount, EVCNT_TYPE_INTR,
- NULL, xname, "module softint");
- evcnt_attach_dynamic(&adapter->msf_sicount, EVCNT_TYPE_INTR,
- NULL, xname, "multimode softint");
- evcnt_attach_dynamic(&adapter->phy_sicount, EVCNT_TYPE_INTR,
- NULL, xname, "external PHY softint");
+ evcnt_attach_dynamic(&adapter->admin_irqev, EVCNT_TYPE_INTR,
+ NULL, xname, "Admin MSI-X IRQ Handled");
+ evcnt_attach_dynamic(&adapter->link_workev, EVCNT_TYPE_INTR,
+ NULL, xname, "Link event");
+ evcnt_attach_dynamic(&adapter->mod_workev, EVCNT_TYPE_INTR,
+ NULL, xname, "SFP+ module event");
+ evcnt_attach_dynamic(&adapter->msf_workev, EVCNT_TYPE_INTR,
+ NULL, xname, "Multispeed event");
+ evcnt_attach_dynamic(&adapter->phy_workev, EVCNT_TYPE_INTR,
+ NULL, xname, "External PHY event");
/* Max number of traffic class is 8 */
KASSERT(IXGBE_DCB_MAX_TRAFFIC_CLASS == 8);
@@ -2072,11 +2074,11 @@
adapter->enomem_tx_dma_setup.ev_count = 0;
adapter->tso_err.ev_count = 0;
adapter->watchdog_events.ev_count = 0;
- adapter->link_irq.ev_count = 0;
- adapter->link_sicount.ev_count = 0;
- adapter->mod_sicount.ev_count = 0;
- adapter->msf_sicount.ev_count = 0;
- adapter->phy_sicount.ev_count = 0;
+ adapter->admin_irqev.ev_count = 0;
+ adapter->link_workev.ev_count = 0;
+ adapter->mod_workev.ev_count = 0;
+ adapter->msf_workev.ev_count = 0;
+ adapter->phy_workev.ev_count = 0;
for (i = 0; i < IXGBE_TC_COUNTER_NUM; i++) {
if (i < __arraycount(stats->mpc)) {
@@ -3047,17 +3049,18 @@
} /* ixgbe_media_change */
/************************************************************************
- * ixgbe_msix_link - Link status change ISR (MSI/MSI-X)
+ * ixgbe_msix_admin - Link status change ISR (MSI/MSI-X)
************************************************************************/
static int
-ixgbe_msix_link(void *arg)
+ixgbe_msix_admin(void *arg)
{
struct adapter *adapter = arg;
struct ixgbe_hw *hw = &adapter->hw;
u32 eicr, eicr_mask;
+ u32 task_requests = 0;
s32 retval;
- ++adapter->link_irq.ev_count;
+ ++adapter->admin_irqev.ev_count;
/* Pause other interrupts */
IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER);
@@ -3092,21 +3095,21 @@
|| ((hw->phy.sfp_type == ixgbe_sfp_type_not_present)
&& (eicr & IXGBE_EICR_LSC))) {
IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask);
- softint_schedule(adapter->mod_si);
+ task_requests |= IXGBE_REQUEST_TASK_MOD;
}
if ((hw->mac.type == ixgbe_mac_82599EB) &&
(eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) {
IXGBE_WRITE_REG(hw, IXGBE_EICR,
IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
- ixgbe_schedule_msf_tasklet(adapter);
+ task_requests |= IXGBE_REQUEST_TASK_MSF;
}
}
/* Link status change */
if (eicr & IXGBE_EICR_LSC) {
IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC);
- softint_schedule(adapter->link_si);
+ task_requests |= IXGBE_REQUEST_TASK_LSC;
Home |
Main Index |
Thread Index |
Old Index