Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-8]: src/sys/dev/pci/ixgbe Pull up following revision(s) (requeste...



details:   https://anonhg.NetBSD.org/src/rev/c1b61cecf94b
branches:  netbsd-8
changeset: 851288:c1b61cecf94b
user:      snj <snj%NetBSD.org@localhost>
date:      Sat Jan 13 21:40:01 2018 +0000

description:
Pull up following revision(s) (requested by msaitoh in ticket #490):
        sys/dev/pci/ixgbe/ixgbe.c: revision 1.116-1.119
        sys/dev/pci/ixgbe/ixv.c: revision 1.76-1.77
Don't panic when resource shortage occured. Fixes PR#52820 reported by
kardel@:
 - Don't use if_free() because ixgbe(4) don't use if_alloc().
 - Move location of {ixgbe,ixv}_setup_interface() call at a position that
   any error don't occur. One of the reason is that it should be. Another
   reason is that it's hard to call ether_ifdetach() and if_detach() when
   cold == 1 (because of pserialize_perform, xc_wait, timing of domaininit
   and maybe more).
--
Don't panic when resource shortage occured. Like ixgbe.c rev. 1.116.
 - Move location of {ixgbe,ixv}_setup_interface() call at a position that
   any error don't occur. One of the reason is that it should be. Another
   reason is that it's hard to call ether_ifdetach() and if_detach() when
   cold == 1 (because of pserialize_perform, xc_wait, timing of domaininit
   and maybe more).
--
Fix panic when only link interrupt can't be established.
--
- If MSI can't be used on some environment, fallback to INTx correctly.
- Use single vector MSI when number of CPU is 1 to save interrupt slot.
--
Fallback from MSI-X to MSI or INTx if MSI-X setup failed.

diffstat:

 sys/dev/pci/ixgbe/ixgbe.c |  267 +++++++++++++++++++++++++++++++--------------
 sys/dev/pci/ixgbe/ixv.c   |   16 +-
 2 files changed, 189 insertions(+), 94 deletions(-)

diffs (truncated from 538 to 300 lines):

diff -r 5e3773f674f3 -r c1b61cecf94b sys/dev/pci/ixgbe/ixgbe.c
--- a/sys/dev/pci/ixgbe/ixgbe.c Sat Jan 13 21:35:29 2018 +0000
+++ b/sys/dev/pci/ixgbe/ixgbe.c Sat Jan 13 21:40:01 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe.c,v 1.88.2.7 2018/01/02 10:20:33 snj Exp $ */
+/* $NetBSD: ixgbe.c,v 1.88.2.8 2018/01/13 21:40:01 snj Exp $ */
 
 /******************************************************************************
 
@@ -172,12 +172,14 @@
 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_get_slot_info(struct adapter *);
 static int      ixgbe_allocate_msix(struct adapter *,
                    const struct pci_attach_args *);
 static int      ixgbe_allocate_legacy(struct adapter *,
                    const struct pci_attach_args *);
 static int      ixgbe_configure_interrupts(struct adapter *);
+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 *);
@@ -1043,17 +1045,54 @@
        hw->eeprom.ops.read(hw, IXGBE_ETRACKID_L, &low);
        aprint_normal(" ETrackID %08x\n", ((uint32_t)high << 16) | low);
 
-       /* Setup OS specific network interface */
-       if (ixgbe_setup_interface(dev, adapter) != 0)
-               goto err_late;
-
-       if (adapter->feat_en & IXGBE_FEATURE_MSIX)
+       if (adapter->feat_en & IXGBE_FEATURE_MSIX) {
                error = ixgbe_allocate_msix(adapter, pa);
-       else
+               if (error) {
+                       /* Free allocated queue structures first */
+                       ixgbe_free_transmit_structures(adapter);
+                       ixgbe_free_receive_structures(adapter);
+                       free(adapter->queues, M_DEVBUF);
+
+                       /* Fallback to legacy interrupt */
+                       adapter->feat_en &= ~IXGBE_FEATURE_MSIX;
+                       if (adapter->feat_cap & IXGBE_FEATURE_MSI)
+                               adapter->feat_en |= IXGBE_FEATURE_MSI;
+                       adapter->num_queues = 1;
+
+                       /* Allocate our TX/RX Queues again */
+                       if (ixgbe_allocate_queues(adapter)) {
+                               error = ENOMEM;
+                               goto err_out;
+                       }
+               }
+       }
+       if ((adapter->feat_en & IXGBE_FEATURE_MSIX) == 0)
                error = ixgbe_allocate_legacy(adapter, pa);
        if (error) 
                goto err_late;
 
+       /* Tasklets for Link, SFP, Multispeed Fiber and Flow Director */
+       adapter->link_si = softint_establish(SOFTINT_NET |IXGBE_SOFTINFT_FLAGS,
+           ixgbe_handle_link, adapter);
+       adapter->mod_si = softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
+           ixgbe_handle_mod, adapter);
+       adapter->msf_si = softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
+           ixgbe_handle_msf, adapter);
+       adapter->phy_si = softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
+           ixgbe_handle_phy, adapter);
+       if (adapter->feat_en & IXGBE_FEATURE_FDIR)
+               adapter->fdir_si =
+                   softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
+                       ixgbe_reinit_fdir, adapter);
+       if ((adapter->link_si == NULL) || (adapter->mod_si == NULL)
+           || (adapter->msf_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;
+       }
+
        error = ixgbe_start_hw(hw);
        switch (error) {
        case IXGBE_ERR_EEPROM_VERSION:
@@ -1074,6 +1113,10 @@
                break;
        }
 
+       /* Setup OS specific network interface */
+       if (ixgbe_setup_interface(dev, adapter) != 0)
+               goto err_late;
+
        /*
         *  Print PHY ID only for copper PHY. On device which has SFP(+) cage
         * and a module is inserted, phy.id is not MII PHY id but SFF 8024 ID.
@@ -1155,11 +1198,10 @@
        ixgbe_free_receive_structures(adapter);
        free(adapter->queues, M_DEVBUF);
 err_out:
-       if (adapter->ifp != NULL)
-               if_free(adapter->ifp);
        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_pci_resources(adapter);
        if (adapter->mta != NULL)
                free(adapter->mta, M_DEVBUF);
@@ -3115,6 +3157,53 @@
        return (0);
 } /* ixgbe_allocate_pci_resources */
 
+static void
+ixgbe_free_softint(struct adapter *adapter)
+{
+       struct ix_queue *que = adapter->queues;
+       struct tx_ring *txr = adapter->tx_rings;
+       int i;
+
+       for (i = 0; i < adapter->num_queues; i++, que++, txr++) {
+               if (!(adapter->feat_en & IXGBE_FEATURE_LEGACY_TX)) {
+                       if (txr->txr_si != NULL)
+                               softint_disestablish(txr->txr_si);
+               }
+               if (que->que_si != NULL)
+                       softint_disestablish(que->que_si);
+       }
+
+       /* Drain the Link queue */
+       if (adapter->link_si != NULL) {
+               softint_disestablish(adapter->link_si);
+               adapter->link_si = NULL;
+       }
+       if (adapter->mod_si != NULL) {
+               softint_disestablish(adapter->mod_si);
+               adapter->mod_si = NULL;
+       }
+       if (adapter->msf_si != NULL) {
+               softint_disestablish(adapter->msf_si);
+               adapter->msf_si = NULL;
+       }
+       if (adapter->phy_si != NULL) {
+               softint_disestablish(adapter->phy_si);
+               adapter->phy_si = NULL;
+       }
+       if (adapter->feat_en & IXGBE_FEATURE_FDIR) {
+               if (adapter->fdir_si != NULL) {
+                       softint_disestablish(adapter->fdir_si);
+                       adapter->fdir_si = NULL;
+               }
+       }
+       if (adapter->feat_cap & IXGBE_FEATURE_SRIOV) {
+               if (adapter->mbx_si != NULL) {
+                       softint_disestablish(adapter->mbx_si);
+                       adapter->mbx_si = NULL;
+               }
+       }
+} /* ixgbe_free_softint */
+
 /************************************************************************
  * ixgbe_detach - Device removal routine
  *
@@ -3128,7 +3217,6 @@
 ixgbe_detach(device_t dev, int flags)
 {
        struct adapter *adapter = device_private(dev);
-       struct ix_queue *que = adapter->queues;
        struct rx_ring *rxr = adapter->rx_rings;
        struct tx_ring *txr = adapter->tx_rings;
        struct ixgbe_hw *hw = &adapter->hw;
@@ -3166,22 +3254,8 @@
        ixgbe_setup_low_power_mode(adapter);
        IXGBE_CORE_UNLOCK(adapter);
 
-       for (int i = 0; i < adapter->num_queues; i++, que++, txr++) {
-               if (!(adapter->feat_en & IXGBE_FEATURE_LEGACY_TX))
-                       softint_disestablish(txr->txr_si);
-               softint_disestablish(que->que_si);
-       }
-
-       /* Drain the Link queue */
-       softint_disestablish(adapter->link_si);
-       softint_disestablish(adapter->mod_si);
-       softint_disestablish(adapter->msf_si);
-       if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
-               softint_disestablish(adapter->mbx_si);
-       softint_disestablish(adapter->phy_si);
-       if (adapter->feat_en & IXGBE_FEATURE_FDIR)
-               softint_disestablish(adapter->fdir_si);
-
+       ixgbe_free_softint(adapter);
+       
        /* let hardware know driver is unloading */
        ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
        ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
@@ -4548,10 +4622,10 @@
 } /* ixgbe_legacy_irq */
 
 /************************************************************************
- * ixgbe_free_pci_resources
+ * ixgbe_free_pciintr_resources
  ************************************************************************/
 static void
-ixgbe_free_pci_resources(struct adapter *adapter)
+ixgbe_free_pciintr_resources(struct adapter *adapter)
 {
        struct ix_queue *que = adapter->queues;
        int             rid;
@@ -4560,9 +4634,11 @@
         * Release all msix queue resources:
         */
        for (int i = 0; i < adapter->num_queues; i++, que++) {
-               if (que->res != NULL)
+               if (que->res != NULL) {
                        pci_intr_disestablish(adapter->osdep.pc,
                            adapter->osdep.ihs[i]);
+                       adapter->osdep.ihs[i] = NULL;
+               }
        }
 
        /* Clean the Legacy or Link interrupt last */
@@ -4577,8 +4653,23 @@
                adapter->osdep.ihs[rid] = NULL;
        }
 
-       pci_intr_release(adapter->osdep.pc, adapter->osdep.intrs,
-           adapter->osdep.nintrs);
+       if (adapter->osdep.intrs != NULL) {
+               pci_intr_release(adapter->osdep.pc, adapter->osdep.intrs,
+                   adapter->osdep.nintrs);
+               adapter->osdep.intrs = NULL;
+       }
+
+       return;
+} /* ixgbe_free_pciintr_resources */
+
+/************************************************************************
+ * ixgbe_free_pci_resources
+ ************************************************************************/
+static void
+ixgbe_free_pci_resources(struct adapter *adapter)
+{
+
+       ixgbe_free_pciintr_resources(adapter);
 
        if (adapter->osdep.mem_size != 0) {
                bus_space_unmap(adapter->osdep.mem_bus_space_tag,
@@ -5668,8 +5759,9 @@
        counts[PCI_INTR_TYPE_MSIX] = 0;
        counts[PCI_INTR_TYPE_MSI] =
            (adapter->feat_en & IXGBE_FEATURE_MSI) ? 1 : 0;
+       /* Check not feat_en but feat_cap to fallback to INTx */
        counts[PCI_INTR_TYPE_INTX] =
-           (adapter->feat_en & IXGBE_FEATURE_LEGACY_IRQ) ? 1 : 0;
+           (adapter->feat_cap & IXGBE_FEATURE_LEGACY_IRQ) ? 1 : 0;
 
 alloc_retry:
        if (pci_intr_alloc(pa, &adapter->osdep.intrs, counts, max_type) != 0) {
@@ -5682,29 +5774,39 @@
        adapter->osdep.ihs[0] = pci_intr_establish_xname(adapter->osdep.pc,
            adapter->osdep.intrs[0], IPL_NET, ixgbe_legacy_irq, que,
            device_xname(dev));
+       intr_type = pci_intr_type(adapter->osdep.pc, adapter->osdep.intrs[0]);
        if (adapter->osdep.ihs[0] == NULL) {
-               intr_type = pci_intr_type(adapter->osdep.pc,
-                   adapter->osdep.intrs[0]);
                aprint_error_dev(dev,"unable to establish %s\n",
                    (intr_type == PCI_INTR_TYPE_MSI) ? "MSI" : "INTx");
                pci_intr_release(adapter->osdep.pc, adapter->osdep.intrs, 1);
+               adapter->osdep.intrs = NULL;
                switch (intr_type) {
                case PCI_INTR_TYPE_MSI:
                        /* The next try is for INTx: Disable MSI */
                        max_type = PCI_INTR_TYPE_INTX;
                        counts[PCI_INTR_TYPE_INTX] = 1;
-                       goto alloc_retry;
+                       adapter->feat_en &= ~IXGBE_FEATURE_MSI;
+                       if (adapter->feat_cap & IXGBE_FEATURE_LEGACY_IRQ) {
+                               adapter->feat_en |= IXGBE_FEATURE_LEGACY_IRQ;
+                               goto alloc_retry;
+                       } else
+                               break;
                case PCI_INTR_TYPE_INTX:
                default:
                        /* See below */
                        break;
                }
        }
+       if (intr_type == PCI_INTR_TYPE_INTX) {
+               adapter->feat_en &= ~IXGBE_FEATURE_MSI;
+               adapter->feat_en |= IXGBE_FEATURE_LEGACY_IRQ;
+       }
        if (adapter->osdep.ihs[0] == NULL) {
                aprint_error_dev(dev,
                    "couldn't establish interrupt%s%s\n",
                    intrstr ? " at " : "", intrstr ? intrstr : "");
                pci_intr_release(adapter->osdep.pc, adapter->osdep.intrs, 1);
+               adapter->osdep.intrs = NULL;
                return ENXIO;



Home | Main Index | Thread Index | Old Index