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