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