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 Apply FreeBSD ix-3.3.6.tar.gz's change to ...



details:   https://anonhg.NetBSD.org/src/rev/cb54255838bd
branches:  trunk
changeset: 446455:cb54255838bd
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Thu Dec 06 13:25:02 2018 +0000

description:
Apply FreeBSD ix-3.3.6.tar.gz's change to NetBSD. Tested on C3000 and X550-T1,
but not tested on Xeon D:
- Add firmware recovery mode for X550, X550A(Xeon D) and X550EM (C3000):
  - FreeBSD always set IXGBE_FEATURE_RECOVERY_MODE without checking the
    NVM image version. We compare it against 2.0 to not to make new callout and
    not to call extra atomic operations.
  - In some FreeBSD's sysctl functions, atomic_load_acq_int() is called
    before a null pointer check. We call it after null pointer check.
  - Before calling atomic_load_acq_uint(), check adapter->feat_en flags
    to save atomic operation call.
  - We don't check recovery_mode in ixgbe_set_sysctl_value() because this
    function doesn't touch any hardware register.
  - NetBSD don't have FreeBSD's atomic_load_acq_int()-like function, so do it
    with membar_sync(). Thanks riastradh@ for the advice.
- FreeBSD's ix-3.3.6 changed ixgbe_enable_aim from TRUE to FALSE, but we will
  keep it as TRUE because we have already fixed some bugs.
- Remove IXGBE_DEV_ID_82599_LS(0x154f) support again. I don't know why. This
  was added in ix-3.2.18.tar.gz(NetBSD: ixgbe_82599.c rev. 1.20) and removed in
  ix-3.3.6.tar.gz.
- On X550EMU, use ixgbe_identify_sfp_module_X550em() instead of
  ixgbe_identify_module_generic(). ixgbe_identify_sfp_module_X550em() has
  extra check (e.g. exclude 1G copper).
- if_sriov.c's change doesn't affect to NetBSD because we don't support
  SR-IOV PF function.

diffstat:

 sys/dev/pci/ixgbe/if_sriov.c       |   60 +++++++++++++
 sys/dev/pci/ixgbe/ixgbe.c          |  167 +++++++++++++++++++++++++++++++++++-
 sys/dev/pci/ixgbe/ixgbe.h          |   18 +++-
 sys/dev/pci/ixgbe/ixgbe_82599.c    |    5 +-
 sys/dev/pci/ixgbe/ixgbe_api.c      |   15 ++-
 sys/dev/pci/ixgbe/ixgbe_api.h      |    3 +-
 sys/dev/pci/ixgbe/ixgbe_features.h |    3 +-
 sys/dev/pci/ixgbe/ixgbe_netbsd.c   |   18 +++-
 sys/dev/pci/ixgbe/ixgbe_netbsd.h   |    4 +-
 sys/dev/pci/ixgbe/ixgbe_phy.c      |    3 +-
 sys/dev/pci/ixgbe/ixgbe_type.h     |   10 +-
 sys/dev/pci/ixgbe/ixgbe_x550.c     |   21 ++++-
 sys/dev/pci/ixgbe/ixgbe_x550.h     |    1 +
 13 files changed, 302 insertions(+), 26 deletions(-)

diffs (truncated from 810 to 300 lines):

diff -r 24930f0610e3 -r cb54255838bd sys/dev/pci/ixgbe/if_sriov.c
--- a/sys/dev/pci/ixgbe/if_sriov.c      Thu Dec 06 10:00:40 2018 +0000
+++ b/sys/dev/pci/ixgbe/if_sriov.c      Thu Dec 06 13:25:02 2018 +0000
@@ -250,6 +250,64 @@
 } /* ixgbe_vf_set_default_vlan */
 
 
+static void
+ixgbe_clear_vfmbmem(struct ixgbe_hw *hw, struct ixgbe_vf *vf)
+{
+       uint32_t vf_index = IXGBE_VF_INDEX(vf->pool);
+       uint16_t mbx_size = hw->mbx.size;
+       uint16_t i;
+
+       IXGBE_CORE_LOCK_ASSERT(adapter);
+
+       for (i = 0; i < mbx_size; ++i)
+               IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_index), i, 0x0);
+} /* ixgbe_clear_vfmbmem */
+
+
+static void
+ixgbe_toggle_txdctl(struct ixgbe_hw *hw, struct ixgbe_vf *vf)
+{
+       uint32_t vf_index, offset, reg;
+       uint8_t  queue_count, i;
+
+       IXGBE_CORE_LOCK_ASSERT(adapter);
+
+       vf_index = IXGBE_VF_INDEX(vf->pool);
+
+       /* Determine number of queues by checking
+        * number of virtual functions */
+       reg = IXGBE_READ_REG(hw, IXGBE_GCR_EXT);
+       switch (reg & IXGBE_GCR_EXT_VT_MODE_MASK) {
+       case IXGBE_GCR_EXT_VT_MODE_64:
+               queue_count = 2;
+               break;
+       case IXGBE_GCR_EXT_VT_MODE_32:
+               queue_count = 4;
+               break;
+       default:
+               return;
+       }
+
+       /* Toggle queues */
+       for (i = 0; i < queue_count; ++i) {
+               /* Calculate offset of current queue */
+               offset = queue_count * vf_index + i;
+
+               /* Enable queue */
+               reg = IXGBE_READ_REG(hw, IXGBE_PVFTXDCTL(offset));
+               reg |= IXGBE_TXDCTL_ENABLE;
+               IXGBE_WRITE_REG(hw, IXGBE_PVFTXDCTL(offset), reg);
+               IXGBE_WRITE_FLUSH(hw);
+
+               /* Disable queue */
+               reg = IXGBE_READ_REG(hw, IXGBE_PVFTXDCTL(offset));
+               reg &= ~IXGBE_TXDCTL_ENABLE;
+               IXGBE_WRITE_REG(hw, IXGBE_PVFTXDCTL(offset), reg);
+               IXGBE_WRITE_FLUSH(hw);
+       }
+} /* ixgbe_toggle_txdctl */
+
+
 static boolean_t
 ixgbe_vf_frame_size_compatible(struct adapter *adapter, struct ixgbe_vf *vf)
 {
@@ -305,6 +363,8 @@
        // XXX clear multicast addresses
 
        ixgbe_clear_rar(&adapter->hw, vf->rar_index);
+       ixgbe_clear_vfmbmem(&adapter->hw, vf);
+       ixgbe_toggle_txdctl(&adapter->hw, vf);
 
        vf->api_ver = IXGBE_API_VER_UNKNOWN;
 } /* ixgbe_process_vf_reset */
diff -r 24930f0610e3 -r cb54255838bd sys/dev/pci/ixgbe/ixgbe.c
--- a/sys/dev/pci/ixgbe/ixgbe.c Thu Dec 06 10:00:40 2018 +0000
+++ b/sys/dev/pci/ixgbe/ixgbe.c Thu Dec 06 13:25:02 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe.c,v 1.168 2018/12/03 04:39:44 msaitoh Exp $ */
+/* $NetBSD: ixgbe.c,v 1.169 2018/12/06 13:25:02 msaitoh Exp $ */
 
 /******************************************************************************
 
@@ -81,7 +81,7 @@
  * Driver version
  ************************************************************************/
 static const char ixgbe_driver_version[] = "4.0.1-k";
-
+/* XXX NetBSD: + 3.3.6 */
 
 /************************************************************************
  * PCI Device ID Table
@@ -184,6 +184,7 @@
 static void    ixgbe_free_pci_resources(struct adapter *);
 static void    ixgbe_local_timer(void *);
 static void    ixgbe_local_timer1(void *);
+static void     ixgbe_recovery_mode_timer(void *);
 static int     ixgbe_setup_interface(device_t, struct adapter *);
 static void    ixgbe_config_gpie(struct adapter *);
 static void    ixgbe_config_dmac(struct adapter *);
@@ -971,6 +972,7 @@
 
        aprint_normal("%s:", device_xname(dev));
        /* NVM Image Version */
+       high = low = 0;
        switch (hw->mac.type) {
        case ixgbe_mac_X540:
        case ixgbe_mac_X550EM_a:
@@ -1000,6 +1002,8 @@
        default:
                break;
        }
+       hw->eeprom.nvm_image_ver_high = high;
+       hw->eeprom.nvm_image_ver_low = low;
 
        /* PHY firmware revision */
        switch (hw->mac.type) {
@@ -1072,6 +1076,21 @@
                        }
                }
        }
+       /* Recovery mode */
+       switch (adapter->hw.mac.type) {
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
+       case ixgbe_mac_X550EM_a:
+               /* >= 2.00 */
+               if (hw->eeprom.nvm_image_ver_high >= 2) {
+                       adapter->feat_cap |= IXGBE_FEATURE_RECOVERY_MODE;
+                       adapter->feat_en |= IXGBE_FEATURE_RECOVERY_MODE;
+               }
+               break;
+       default:
+               break;
+       }
+
        if ((adapter->feat_en & IXGBE_FEATURE_MSIX) == 0)
                error = ixgbe_allocate_legacy(adapter, pa);
        if (error) 
@@ -1194,6 +1213,19 @@
        else
                aprint_error_dev(dev, "couldn't establish power handler\n");
 
+       /* Init recovery mode timer and state variable */
+       if (adapter->feat_en & IXGBE_FEATURE_RECOVERY_MODE) {
+               adapter->recovery_mode = 0;
+
+               /* Set up the timer callout */
+               callout_init(&adapter->recovery_mode_timer,
+                   IXGBE_CALLOUT_FLAGS);
+
+               /* Start the task */
+               callout_reset(&adapter->recovery_mode_timer, hz,
+                   ixgbe_recovery_mode_timer, adapter);
+       }
+
        INIT_DEBUGOUT("ixgbe_attach: end");
        adapter->osdep.attached = true;
 
@@ -2156,12 +2188,17 @@
 {
        struct sysctlnode node = *rnode;
        struct tx_ring *txr = (struct tx_ring *)node.sysctl_data;
+       struct adapter *adapter;
        uint32_t val;
 
        if (!txr)
                return (0);
 
-       val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDH(txr->me));
+       adapter = txr->adapter;
+       if (ixgbe_fw_recovery_mode_swflag(adapter))
+               return (EPERM);
+
+       val = IXGBE_READ_REG(&adapter->hw, IXGBE_TDH(txr->me));
        node.sysctl_data = &val;
        return sysctl_lookup(SYSCTLFN_CALL(&node));
 } /* ixgbe_sysctl_tdh_handler */
@@ -2176,12 +2213,17 @@
 {
        struct sysctlnode node = *rnode;
        struct tx_ring *txr = (struct tx_ring *)node.sysctl_data;
+       struct adapter *adapter;
        uint32_t val;
 
        if (!txr)
                return (0);
 
-       val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDT(txr->me));
+       adapter = txr->adapter;
+       if (ixgbe_fw_recovery_mode_swflag(adapter))
+               return (EPERM);
+
+       val = IXGBE_READ_REG(&adapter->hw, IXGBE_TDT(txr->me));
        node.sysctl_data = &val;
        return sysctl_lookup(SYSCTLFN_CALL(&node));
 } /* ixgbe_sysctl_tdt_handler */
@@ -2197,11 +2239,16 @@
 {
        struct sysctlnode node = *rnode;
        struct rx_ring *rxr = (struct rx_ring *)node.sysctl_data;
+       struct adapter *adapter;
        uint32_t val;
 
        if (!rxr)
                return (0);
 
+       adapter = rxr->adapter;
+       if (ixgbe_fw_recovery_mode_swflag(adapter))
+               return (EPERM);
+
        val = rxr->next_to_check;
        node.sysctl_data = &val;
        return sysctl_lookup(SYSCTLFN_CALL(&node));
@@ -2217,12 +2264,17 @@
 {
        struct sysctlnode node = *rnode;
        struct rx_ring *rxr = (struct rx_ring *)node.sysctl_data;
+       struct adapter *adapter;
        uint32_t val;
 
        if (!rxr)
                return (0);
 
-       val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDH(rxr->me));
+       adapter = rxr->adapter;
+       if (ixgbe_fw_recovery_mode_swflag(adapter))
+               return (EPERM);
+
+       val = IXGBE_READ_REG(&adapter->hw, IXGBE_RDH(rxr->me));
        node.sysctl_data = &val;
        return sysctl_lookup(SYSCTLFN_CALL(&node));
 } /* ixgbe_sysctl_rdh_handler */
@@ -2237,12 +2289,17 @@
 {
        struct sysctlnode node = *rnode;
        struct rx_ring *rxr = (struct rx_ring *)node.sysctl_data;
+       struct adapter *adapter;
        uint32_t val;
 
        if (!rxr)
                return (0);
 
-       val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDT(rxr->me));
+       adapter = rxr->adapter;
+       if (ixgbe_fw_recovery_mode_swflag(adapter))
+               return (EPERM);
+
+       val = IXGBE_READ_REG(&adapter->hw, IXGBE_RDT(rxr->me));
        node.sysctl_data = &val;
        return sysctl_lookup(SYSCTLFN_CALL(&node));
 } /* ixgbe_sysctl_rdt_handler */
@@ -3127,13 +3184,18 @@
 {
        struct sysctlnode node = *rnode;
        struct ix_queue *que = (struct ix_queue *)node.sysctl_data;
-       struct adapter  *adapter = que->adapter;
+       struct adapter  *adapter;
        uint32_t reg, usec, rate;
        int error;
 
        if (que == NULL)
                return 0;
-       reg = IXGBE_READ_REG(&que->adapter->hw, IXGBE_EITR(que->msix));
+
+       adapter = que->adapter;
+       if (ixgbe_fw_recovery_mode_swflag(adapter))
+               return (EPERM);
+
+       reg = IXGBE_READ_REG(&adapter->hw, IXGBE_EITR(que->msix));
        usec = ((reg & 0x0FF8) >> 3);
        if (usec > 0)
                rate = 500000 / usec;
@@ -3504,6 +3566,7 @@
        IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext);
 
        callout_halt(&adapter->timer, NULL);
+       callout_halt(&adapter->recovery_mode_timer, NULL);
 
        if (adapter->feat_en & IXGBE_FEATURE_NETMAP)
                netmap_detach(adapter->ifp);
@@ -4448,6 +4511,32 @@
 } /* ixgbe_local_timer */
 
 /************************************************************************
+ * ixgbe_recovery_mode_timer - Recovery mode timer routine
+ ************************************************************************/
+static void
+ixgbe_recovery_mode_timer(void *arg)
+{
+       struct adapter *adapter = arg;
+       struct ixgbe_hw *hw = &adapter->hw;
+
+       IXGBE_CORE_LOCK(adapter);
+       if (ixgbe_fw_recovery_mode(hw)) {
+               if (atomic_cas_uint(&adapter->recovery_mode, 0, 1)) {
+                       /* Firmware error detected, entering recovery mode */



Home | Main Index | Thread Index | Old Index