summaryrefslogtreecommitdiffstats
path: root/sys/dev/ixl
diff options
context:
space:
mode:
authorerj <erj@FreeBSD.org>2016-05-12 18:20:36 +0000
committererj <erj@FreeBSD.org>2016-05-12 18:20:36 +0000
commitd659ce99761d64a57d1f0efc13b67d2d2d0c3e29 (patch)
treea3bb384123113a9a6a64b22a87e50b40fee4e6d8 /sys/dev/ixl
parent8341d0e8b90129736b4d9a6f8677395269845708 (diff)
downloadFreeBSD-src-d659ce99761d64a57d1f0efc13b67d2d2d0c3e29.zip
FreeBSD-src-d659ce99761d64a57d1f0efc13b67d2d2d0c3e29.tar.gz
ixl: Update to 1.4.12-k.
Changes by author: Eric Joyner ixl: Remove substitution of EACCES for EPERM when perrno is set on an nvmupdate command return. Eric Joyner ixl: Print message when hardware sends GRST interrupt. Eric Joyner ixl: Fix kernel panic when driver fails to initialize admin queue. Eric Joyner ixl: Print out messages when a non-handled other interrupt occurs. Eric Joyner ixl: Fix spaces in a couple messages. Eric Joyner ixl: Add lock around nvmupd command entry point and reconvert EPERM errors to EACCES. Anjali Singhai Jain i40e-shared: Make some changes in the nvm read code Shannon Nelson i40e-shared: AQ Add Run PHY Activity struct Shannon Nelson i40e-shared: AQ Add Geneve cloud tunnel type Shannon Nelson i40e-shared: AQ Add external power class to get link status response struct Shannon Nelson i40e-shared: AQ Add shared resource flags for macvlan filters Shannon Nelson i40e-shared: AQ Add set_switch_config Shannon Nelson i40e-shared: AQ Add VXLAN-GPE tunnel type for cloud filter and tunnel commands Shannon Nelson i40e-shared: AQ thermal sensor control struct Shannon Nelson i40e-shared: Bump AQ minor version to 1.5 for FVL5 features Shannon Nelson i40e-shared: add a little more to an NVM update debug message Carolyn Wyborny i40e-shared: Fix for PHY NVM interaction problem Eric Joyner i40e-shared: Add prototypes for private NVM write functions Eric Joyner ixl/ixlv: Remove unused define from ixl.h. Eric Joyner ixl: Add handling of EMP reset for nvm update purposes. Eric Joyner ixl: Move addition of device sysctls to separate function. Eric Joyner ixl: Fix up a couple error messages in ixl_attach(). Eric Joyner ixl: Update the hardware resource allocation debug sysctl. Differential Revision: https://reviews.freebsd.org/D6211 Reviewed by: sbruno, kmacy, jeffrey.e.pieper@intel.com MFC after: 2 weeks Sponsored by: Intel Corporation
Diffstat (limited to 'sys/dev/ixl')
-rw-r--r--sys/dev/ixl/i40e_adminq_cmd.h66
-rw-r--r--sys/dev/ixl/i40e_common.c15
-rw-r--r--sys/dev/ixl/i40e_nvm.c89
-rw-r--r--sys/dev/ixl/i40e_prototype.h8
-rw-r--r--sys/dev/ixl/if_ixl.c467
-rw-r--r--sys/dev/ixl/ixl.h1
-rw-r--r--sys/dev/ixl/ixl_pf.h3
7 files changed, 462 insertions, 187 deletions
diff --git a/sys/dev/ixl/i40e_adminq_cmd.h b/sys/dev/ixl/i40e_adminq_cmd.h
index 62af939..8402c93 100644
--- a/sys/dev/ixl/i40e_adminq_cmd.h
+++ b/sys/dev/ixl/i40e_adminq_cmd.h
@@ -42,7 +42,7 @@
*/
#define I40E_FW_API_VERSION_MAJOR 0x0001
-#define I40E_FW_API_VERSION_MINOR 0x0004
+#define I40E_FW_API_VERSION_MINOR 0x0005
struct i40e_aq_desc {
__le16 flags;
@@ -153,6 +153,7 @@ enum i40e_admin_queue_opc {
i40e_aqc_opc_remove_statistics = 0x0202,
i40e_aqc_opc_set_port_parameters = 0x0203,
i40e_aqc_opc_get_switch_resource_alloc = 0x0204,
+ i40e_aqc_opc_set_switch_config = 0x0205,
i40e_aqc_opc_add_vsi = 0x0210,
i40e_aqc_opc_update_vsi_parameters = 0x0211,
@@ -228,6 +229,7 @@ enum i40e_admin_queue_opc {
i40e_aqc_opc_get_phy_wol_caps = 0x0621,
i40e_aqc_opc_set_phy_debug = 0x0622,
i40e_aqc_opc_upload_ext_phy_fm = 0x0625,
+ i40e_aqc_opc_run_phy_activity = 0x0626,
/* NVM commands */
i40e_aqc_opc_nvm_read = 0x0701,
@@ -236,6 +238,7 @@ enum i40e_admin_queue_opc {
i40e_aqc_opc_nvm_config_read = 0x0704,
i40e_aqc_opc_nvm_config_write = 0x0705,
i40e_aqc_opc_oem_post_update = 0x0720,
+ i40e_aqc_opc_thermal_sensor = 0x0721,
/* virtualization commands */
i40e_aqc_opc_send_msg_to_pf = 0x0801,
@@ -686,6 +689,17 @@ struct i40e_aqc_switch_resource_alloc_element_resp {
I40E_CHECK_STRUCT_LEN(0x10, i40e_aqc_switch_resource_alloc_element_resp);
+/* Set Switch Configuration (direct 0x0205) */
+struct i40e_aqc_set_switch_config {
+ __le16 flags;
+#define I40E_AQ_SET_SWITCH_CFG_PROMISC 0x0001
+#define I40E_AQ_SET_SWITCH_CFG_L2_FILTER 0x0002
+ __le16 valid_flags;
+ u8 reserved[12];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_set_switch_config);
+
/* Add VSI (indirect 0x0210)
* this indirect command uses struct i40e_aqc_vsi_properties_data
* as the indirect buffer (128 bytes)
@@ -908,7 +922,8 @@ struct i40e_aqc_add_veb {
I40E_AQC_ADD_VEB_PORT_TYPE_SHIFT)
#define I40E_AQC_ADD_VEB_PORT_TYPE_DEFAULT 0x2
#define I40E_AQC_ADD_VEB_PORT_TYPE_DATA 0x4
-#define I40E_AQC_ADD_VEB_ENABLE_L2_FILTER 0x8
+#define I40E_AQC_ADD_VEB_ENABLE_L2_FILTER 0x8 /* deprecated */
+#define I40E_AQC_ADD_VEB_ENABLE_DISABLE_STATS 0x10
u8 enable_tcs;
u8 reserved[9];
};
@@ -975,6 +990,7 @@ struct i40e_aqc_add_macvlan_element_data {
#define I40E_AQC_MACVLAN_ADD_HASH_MATCH 0x0002
#define I40E_AQC_MACVLAN_ADD_IGNORE_VLAN 0x0004
#define I40E_AQC_MACVLAN_ADD_TO_QUEUE 0x0008
+#define I40E_AQC_MACVLAN_ADD_USE_SHARED_MAC 0x0010
__le16 queue_number;
#define I40E_AQC_MACVLAN_CMD_QUEUE_SHIFT 0
#define I40E_AQC_MACVLAN_CMD_QUEUE_MASK (0x7FF << \
@@ -1259,10 +1275,16 @@ struct i40e_aqc_add_remove_cloud_filters_element_data {
#define I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT 9
#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK 0x1E00
-#define I40E_AQC_ADD_CLOUD_TNL_TYPE_XVLAN 0
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_VXLAN 0
#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NVGRE_OMAC 1
-#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NGE 2
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_GENEVE 2
#define I40E_AQC_ADD_CLOUD_TNL_TYPE_IP 3
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_RESERVED 4
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_VXLAN_GPE 5
+
+#define I40E_AQC_ADD_CLOUD_FLAGS_SHARED_OUTER_MAC 0x2000
+#define I40E_AQC_ADD_CLOUD_FLAGS_SHARED_INNER_MAC 0x4000
+#define I40E_AQC_ADD_CLOUD_FLAGS_SHARED_OUTER_IP 0x8000
__le32 tenant_id;
u8 reserved[4];
@@ -1756,7 +1778,12 @@ struct i40e_aqc_get_link_status {
u8 config;
#define I40E_AQ_CONFIG_CRC_ENA 0x04
#define I40E_AQ_CONFIG_PACING_MASK 0x78
- u8 reserved[5];
+ u8 external_power_ability;
+#define I40E_AQ_LINK_POWER_CLASS_1 0x00
+#define I40E_AQ_LINK_POWER_CLASS_2 0x01
+#define I40E_AQ_LINK_POWER_CLASS_3 0x02
+#define I40E_AQ_LINK_POWER_CLASS_4 0x03
+ u8 reserved[4];
};
I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status);
@@ -1824,6 +1851,18 @@ enum i40e_aq_phy_reg_type {
I40E_AQC_PHY_REG_EXERNAL_MODULE = 0x3
};
+/* Run PHY Activity (0x0626) */
+struct i40e_aqc_run_phy_activity {
+ __le16 activity_id;
+ u8 flags;
+ u8 reserved1;
+ __le32 control;
+ __le32 data;
+ u8 reserved2[4];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_run_phy_activity);
+
/* NVM Read command (indirect 0x0701)
* NVM Erase commands (direct 0x0702)
* NVM Update commands (indirect 0x0703)
@@ -1912,6 +1951,22 @@ struct i40e_aqc_nvm_oem_post_update_buffer {
I40E_CHECK_STRUCT_LEN(0x28, i40e_aqc_nvm_oem_post_update_buffer);
+/* Thermal Sensor (indirect 0x0721)
+ * read or set thermal sensor configs and values
+ * takes a sensor and command specific data buffer, not detailed here
+ */
+struct i40e_aqc_thermal_sensor {
+ u8 sensor_action;
+#define I40E_AQ_THERMAL_SENSOR_READ_CONFIG 0
+#define I40E_AQ_THERMAL_SENSOR_SET_CONFIG 1
+#define I40E_AQ_THERMAL_SENSOR_READ_TEMP 2
+ u8 reserved[7];
+ __le32 addr_high;
+ __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_thermal_sensor);
+
/* Send to PF command (indirect 0x0801) id is only used by PF
* Send to VF command (indirect 0x0802) id is only used by PF
* Send to Peer PF command (indirect 0x0803)
@@ -2184,6 +2239,7 @@ struct i40e_aqc_add_udp_tunnel {
#define I40E_AQC_TUNNEL_TYPE_VXLAN 0x00
#define I40E_AQC_TUNNEL_TYPE_NGE 0x01
#define I40E_AQC_TUNNEL_TYPE_TEREDO 0x10
+#define I40E_AQC_TUNNEL_TYPE_VXLAN_GPE 0x11
u8 reserved1[10];
};
diff --git a/sys/dev/ixl/i40e_common.c b/sys/dev/ixl/i40e_common.c
index c0c8f1e..5538450 100644
--- a/sys/dev/ixl/i40e_common.c
+++ b/sys/dev/ixl/i40e_common.c
@@ -2393,14 +2393,15 @@ enum i40e_status_code i40e_update_link_info(struct i40e_hw *hw)
if (status)
return status;
- status = i40e_aq_get_phy_capabilities(hw, FALSE, false, &abilities,
- NULL);
- if (status)
- return status;
-
- memcpy(hw->phy.link_info.module_type, &abilities.module_type,
- sizeof(hw->phy.link_info.module_type));
+ if (hw->phy.link_info.link_info & I40E_AQ_MEDIA_AVAILABLE) {
+ status = i40e_aq_get_phy_capabilities(hw, FALSE, false,
+ &abilities, NULL);
+ if (status)
+ return status;
+ memcpy(hw->phy.link_info.module_type, &abilities.module_type,
+ sizeof(hw->phy.link_info.module_type));
+ }
return status;
}
diff --git a/sys/dev/ixl/i40e_nvm.c b/sys/dev/ixl/i40e_nvm.c
index bd8a45a..5d3f6a3 100644
--- a/sys/dev/ixl/i40e_nvm.c
+++ b/sys/dev/ixl/i40e_nvm.c
@@ -208,7 +208,7 @@ static enum i40e_status_code i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw)
}
/**
- * i40e_read_nvm_word - Reads Shadow RAM
+ * i40e_read_nvm_word - Reads nvm word and acquire lock if necessary
* @hw: pointer to the HW structure
* @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
* @data: word read from the Shadow RAM
@@ -225,6 +225,24 @@ enum i40e_status_code i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
}
/**
+ * __i40e_read_nvm_word - Reads nvm word, assumes caller does the locking
+ * @hw: pointer to the HW structure
+ * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
+ * @data: word read from the Shadow RAM
+ *
+ * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.
+ **/
+enum i40e_status_code __i40e_read_nvm_word(struct i40e_hw *hw,
+ u16 offset,
+ u16 *data)
+{
+ enum i40e_status_code ret_code = I40E_SUCCESS;
+
+ ret_code = i40e_read_nvm_word_srctl(hw, offset, data);
+ return ret_code;
+}
+
+/**
* i40e_read_nvm_word_srctl - Reads Shadow RAM via SRCTL register
* @hw: pointer to the HW structure
* @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
@@ -296,7 +314,28 @@ enum i40e_status_code i40e_read_nvm_word_aq(struct i40e_hw *hw, u16 offset,
}
/**
- * i40e_read_nvm_buffer - Reads Shadow RAM buffer
+ * __i40e_read_nvm_buffer - Reads nvm buffer, caller must acquire lock
+ * @hw: pointer to the HW structure
+ * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
+ * @words: (in) number of words to read; (out) number of words actually read
+ * @data: words read from the Shadow RAM
+ *
+ * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()
+ * method. The buffer read is preceded by the NVM ownership take
+ * and followed by the release.
+ **/
+enum i40e_status_code __i40e_read_nvm_buffer(struct i40e_hw *hw,
+ u16 offset,
+ u16 *words, u16 *data)
+{
+ enum i40e_status_code ret_code = I40E_SUCCESS;
+
+ ret_code = i40e_read_nvm_buffer_srctl(hw, offset, words, data);
+ return ret_code;
+}
+
+/**
+ * i40e_read_nvm_buffer - Reads Shadow RAM buffer and acuire lock if necessary
* @hw: pointer to the HW structure
* @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
* @words: (in) number of words to read; (out) number of words actually read
@@ -506,7 +545,7 @@ enum i40e_status_code i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
}
/**
- * i40e_write_nvm_word - Writes Shadow RAM word
+ * __i40e_write_nvm_word - Writes Shadow RAM word
* @hw: pointer to the HW structure
* @offset: offset of the Shadow RAM word to write
* @data: word to write to the Shadow RAM
@@ -516,8 +555,8 @@ enum i40e_status_code i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
* reception) by caller. To commit SR to NVM update checksum function
* should be called.
**/
-enum i40e_status_code i40e_write_nvm_word(struct i40e_hw *hw, u32 offset,
- void *data)
+enum i40e_status_code __i40e_write_nvm_word(struct i40e_hw *hw, u32 offset,
+ void *data)
{
DEBUGFUNC("i40e_write_nvm_word");
@@ -528,7 +567,7 @@ enum i40e_status_code i40e_write_nvm_word(struct i40e_hw *hw, u32 offset,
}
/**
- * i40e_write_nvm_buffer - Writes Shadow RAM buffer
+ * __i40e_write_nvm_buffer - Writes Shadow RAM buffer
* @hw: pointer to the HW structure
* @module_pointer: module pointer location in words from the NVM beginning
* @offset: offset of the Shadow RAM buffer to write
@@ -540,9 +579,9 @@ enum i40e_status_code i40e_write_nvm_word(struct i40e_hw *hw, u32 offset,
* on ARQ completion event reception by caller. To commit SR to NVM update
* checksum function should be called.
**/
-enum i40e_status_code i40e_write_nvm_buffer(struct i40e_hw *hw,
- u8 module_pointer, u32 offset,
- u16 words, void *data)
+enum i40e_status_code __i40e_write_nvm_buffer(struct i40e_hw *hw,
+ u8 module_pointer, u32 offset,
+ u16 words, void *data)
{
__le16 *le_word_ptr = (__le16 *)data;
u16 *word_ptr = (u16 *)data;
@@ -589,15 +628,17 @@ enum i40e_status_code i40e_calc_nvm_checksum(struct i40e_hw *hw, u16 *checksum)
data = (u16 *)vmem.va;
/* read pointer to VPD area */
- ret_code = i40e_read_nvm_word(hw, I40E_SR_VPD_PTR, &vpd_module);
+ ret_code = __i40e_read_nvm_word(hw, I40E_SR_VPD_PTR,
+ &vpd_module);
if (ret_code != I40E_SUCCESS) {
ret_code = I40E_ERR_NVM_CHECKSUM;
goto i40e_calc_nvm_checksum_exit;
}
/* read pointer to PCIe Alt Auto-load module */
- ret_code = i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR,
- &pcie_alt_module);
+ ret_code = __i40e_read_nvm_word(hw,
+ I40E_SR_PCIE_ALT_AUTO_LOAD_PTR,
+ &pcie_alt_module);
if (ret_code != I40E_SUCCESS) {
ret_code = I40E_ERR_NVM_CHECKSUM;
goto i40e_calc_nvm_checksum_exit;
@@ -611,7 +652,7 @@ enum i40e_status_code i40e_calc_nvm_checksum(struct i40e_hw *hw, u16 *checksum)
if ((i % I40E_SR_SECTOR_SIZE_IN_WORDS) == 0) {
u16 words = I40E_SR_SECTOR_SIZE_IN_WORDS;
- ret_code = i40e_read_nvm_buffer(hw, i, &words, data);
+ ret_code = __i40e_read_nvm_buffer(hw, i, &words, data);
if (ret_code != I40E_SUCCESS) {
ret_code = I40E_ERR_NVM_CHECKSUM;
goto i40e_calc_nvm_checksum_exit;
@@ -686,13 +727,18 @@ enum i40e_status_code i40e_validate_nvm_checksum(struct i40e_hw *hw,
DEBUGFUNC("i40e_validate_nvm_checksum");
- ret_code = i40e_calc_nvm_checksum(hw, &checksum_local);
- if (ret_code != I40E_SUCCESS)
+ if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE)
+ ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
+ if (!ret_code) {
+ ret_code = i40e_calc_nvm_checksum(hw, &checksum_local);
+ if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE)
+ i40e_release_nvm(hw);
+ if (ret_code != I40E_SUCCESS)
+ goto i40e_validate_nvm_checksum_exit;
+ } else {
goto i40e_validate_nvm_checksum_exit;
+ }
- /* Do not use i40e_read_nvm_word() because we do not want to take
- * the synchronization semaphores twice here.
- */
i40e_read_nvm_word(hw, I40E_SR_SW_CHECKSUM_WORD, &checksum_sr);
/* Verify read checksum from EEPROM is the same as
@@ -788,10 +834,11 @@ enum i40e_status_code i40e_nvmupd_command(struct i40e_hw *hw,
/* early check for status command and debug msgs */
upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
- i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d\n",
+ i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d cmd 0x%08x config 0x%08x offset 0x%08x data_size 0x%08x\n",
i40e_nvm_update_state_str[upd_cmd],
hw->nvmupd_state,
- hw->aq.nvm_release_on_done);
+ hw->aq.nvm_release_on_done,
+ cmd->command, cmd->config, cmd->offset, cmd->data_size);
if (upd_cmd == I40E_NVMUPD_INVALID) {
*perrno = -EFAULT;
@@ -1059,6 +1106,7 @@ retry:
break;
case I40E_NVMUPD_CSUM_CON:
+ /* Assumes the caller has acquired the nvm */
status = i40e_update_nvm_checksum(hw);
if (status) {
*perrno = hw->aq.asq_last_status ?
@@ -1072,6 +1120,7 @@ retry:
break;
case I40E_NVMUPD_CSUM_LCB:
+ /* Assumes the caller has acquired the nvm */
status = i40e_update_nvm_checksum(hw);
if (status) {
*perrno = hw->aq.asq_last_status ?
diff --git a/sys/dev/ixl/i40e_prototype.h b/sys/dev/ixl/i40e_prototype.h
index cfecacb..e7e6aa2 100644
--- a/sys/dev/ixl/i40e_prototype.h
+++ b/sys/dev/ixl/i40e_prototype.h
@@ -413,9 +413,13 @@ enum i40e_status_code i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
enum i40e_status_code i40e_write_nvm_aq(struct i40e_hw *hw, u8 module,
u32 offset, u16 words, void *data,
bool last_command);
-enum i40e_status_code i40e_write_nvm_word(struct i40e_hw *hw, u32 offset,
+enum i40e_status_code __i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
+ u16 *data);
+enum i40e_status_code __i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
+ u16 *words, u16 *data);
+enum i40e_status_code __i40e_write_nvm_word(struct i40e_hw *hw, u32 offset,
void *data);
-enum i40e_status_code i40e_write_nvm_buffer(struct i40e_hw *hw, u8 module,
+enum i40e_status_code __i40e_write_nvm_buffer(struct i40e_hw *hw, u8 module,
u32 offset, u16 words, void *data);
enum i40e_status_code i40e_calc_nvm_checksum(struct i40e_hw *hw, u16 *checksum);
enum i40e_status_code i40e_update_nvm_checksum(struct i40e_hw *hw);
diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c
index ca1eb9c..2ae906c 100644
--- a/sys/dev/ixl/if_ixl.c
+++ b/sys/dev/ixl/if_ixl.c
@@ -48,7 +48,7 @@
/*********************************************************************
* Driver version
*********************************************************************/
-char ixl_driver_version[] = "1.4.9-k";
+char ixl_driver_version[] = "1.4.12-k";
/*********************************************************************
* PCI Device ID Table
@@ -154,11 +154,25 @@ static struct ixl_mac_filter *
static void ixl_add_mc_filter(struct ixl_vsi *, u8 *);
static void ixl_free_mac_filters(struct ixl_vsi *vsi);
+/* Sysctls*/
+static void ixl_add_device_sysctls(struct ixl_pf *);
-/* Sysctl debug interface */
static int ixl_debug_info(SYSCTL_HANDLER_ARGS);
static void ixl_print_debug_info(struct ixl_pf *);
+static int ixl_set_flowcntl(SYSCTL_HANDLER_ARGS);
+static int ixl_set_advertise(SYSCTL_HANDLER_ARGS);
+static int ixl_current_speed(SYSCTL_HANDLER_ARGS);
+static int ixl_sysctl_show_fw(SYSCTL_HANDLER_ARGS);
+
+#ifdef IXL_DEBUG_SYSCTL
+static int ixl_sysctl_link_status(SYSCTL_HANDLER_ARGS);
+static int ixl_sysctl_phy_abilities(SYSCTL_HANDLER_ARGS);
+static int ixl_sysctl_sw_filter_list(SYSCTL_HANDLER_ARGS);
+static int ixl_sysctl_hw_res_alloc(SYSCTL_HANDLER_ARGS);
+static int ixl_sysctl_switch_config(SYSCTL_HANDLER_ARGS);
+#endif
+
/* The MSI/X Interrupt handlers */
static void ixl_intr(void *);
static void ixl_msix_que(void *);
@@ -168,12 +182,6 @@ static void ixl_handle_mdd_event(struct ixl_pf *);
/* Deferred interrupt tasklets */
static void ixl_do_adminq(void *, int);
-/* Sysctl handlers */
-static int ixl_set_flowcntl(SYSCTL_HANDLER_ARGS);
-static int ixl_set_advertise(SYSCTL_HANDLER_ARGS);
-static int ixl_current_speed(SYSCTL_HANDLER_ARGS);
-static int ixl_sysctl_show_fw(SYSCTL_HANDLER_ARGS);
-
/* Statistics */
static void ixl_add_hw_stats(struct ixl_pf *);
static void ixl_add_sysctls_mac_stats(struct sysctl_ctx_list *,
@@ -193,14 +201,6 @@ static void ixl_stat_update32(struct i40e_hw *, u32, bool,
/* NVM update */
static int ixl_handle_nvmupd_cmd(struct ixl_pf *, struct ifdrv *);
-#ifdef IXL_DEBUG_SYSCTL
-static int ixl_sysctl_link_status(SYSCTL_HANDLER_ARGS);
-static int ixl_sysctl_phy_abilities(SYSCTL_HANDLER_ARGS);
-static int ixl_sysctl_sw_filter_list(SYSCTL_HANDLER_ARGS);
-static int ixl_sysctl_hw_res_alloc(SYSCTL_HANDLER_ARGS);
-static int ixl_sysctl_switch_config(SYSCTL_HANDLER_ARGS);
-#endif
-
#ifdef PCI_IOV
static int ixl_adminq_err_to_errno(enum i40e_admin_queue_err err);
@@ -440,90 +440,6 @@ ixl_attach(device_t dev)
/* Set up the timer callout */
callout_init_mtx(&pf->timer, &pf->pf_mtx, 0);
- /* Set up sysctls */
- SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "fc", CTLTYPE_INT | CTLFLAG_RW,
- pf, 0, ixl_set_flowcntl, "I", "Flow Control");
-
- SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "advertise_speed", CTLTYPE_INT | CTLFLAG_RW,
- pf, 0, ixl_set_advertise, "I", "Advertised Speed");
-
- SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "current_speed", CTLTYPE_STRING | CTLFLAG_RD,
- pf, 0, ixl_current_speed, "A", "Current Port Speed");
-
- SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "fw_version", CTLTYPE_STRING | CTLFLAG_RD,
- pf, 0, ixl_sysctl_show_fw, "A", "Firmware version");
-
- SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "rx_itr", CTLFLAG_RW,
- &ixl_rx_itr, IXL_ITR_8K, "RX ITR");
-
- SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "dynamic_rx_itr", CTLFLAG_RW,
- &ixl_dynamic_rx_itr, 0, "Dynamic RX ITR");
-
- SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "tx_itr", CTLFLAG_RW,
- &ixl_tx_itr, IXL_ITR_4K, "TX ITR");
-
- SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "dynamic_tx_itr", CTLFLAG_RW,
- &ixl_dynamic_tx_itr, 0, "Dynamic TX ITR");
-
-#ifdef IXL_DEBUG_SYSCTL
- SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "debug", CTLTYPE_INT|CTLFLAG_RW, pf, 0,
- ixl_debug_info, "I", "Debug Information");
-
- /* Debug shared-code message level */
- SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "debug_mask", CTLFLAG_RW,
- &pf->hw.debug_mask, 0, "Debug Message Level");
-
- SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "vc_debug_level", CTLFLAG_RW, &pf->vc_debug_lvl,
- 0, "PF/VF Virtual Channel debug level");
-
- SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "link_status", CTLTYPE_STRING | CTLFLAG_RD,
- pf, 0, ixl_sysctl_link_status, "A", "Current Link Status");
-
- SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "phy_abilities", CTLTYPE_STRING | CTLFLAG_RD,
- pf, 0, ixl_sysctl_phy_abilities, "A", "PHY Abilities");
-
- SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "filter_list", CTLTYPE_STRING | CTLFLAG_RD,
- pf, 0, ixl_sysctl_sw_filter_list, "A", "SW Filter List");
-
- SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "hw_res_alloc", CTLTYPE_STRING | CTLFLAG_RD,
- pf, 0, ixl_sysctl_hw_res_alloc, "A", "HW Resource Allocation");
-
- SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "switch_config", CTLTYPE_STRING | CTLFLAG_RD,
- pf, 0, ixl_sysctl_switch_config, "A", "HW Switch Configuration");
-#endif
-
/* Save off the PCI information */
hw->vendor_id = pci_get_vendor(dev);
hw->device_id = pci_get_device(dev);
@@ -549,7 +465,7 @@ ixl_attach(device_t dev)
i40e_clear_hw(hw);
error = i40e_pf_reset(hw);
if (error) {
- device_printf(dev, "PF reset failure %x\n", error);
+ device_printf(dev, "PF reset failure %d\n", error);
error = EIO;
goto err_out;
}
@@ -560,24 +476,35 @@ ixl_attach(device_t dev)
hw->aq.arq_buf_size = IXL_AQ_BUFSZ;
hw->aq.asq_buf_size = IXL_AQ_BUFSZ;
+ /* Initialize mac filter list for VSI */
+ SLIST_INIT(&vsi->ftl);
+
/* Initialize the shared code */
error = i40e_init_shared_code(hw);
if (error) {
- device_printf(dev, "Unable to initialize the shared code\n");
+ device_printf(dev, "Unable to initialize shared code, error %d\n",
+ error);
error = EIO;
goto err_out;
}
/* Set up the admin queue */
error = i40e_init_adminq(hw);
- if (error) {
+ if (error != 0 && error != I40E_ERR_FIRMWARE_API_VERSION) {
+ device_printf(dev, "Unable to initialize Admin Queue, error %d\n",
+ error);
+ error = EIO;
+ goto err_out;
+ }
+ device_printf(dev, "%s\n", ixl_fw_version_str(hw));
+ if (error == I40E_ERR_FIRMWARE_API_VERSION) {
device_printf(dev, "The driver for the device stopped "
"because the NVM image is newer than expected.\n"
"You must install the most recent version of "
- " the network driver.\n");
+ "the network driver.\n");
+ error = EIO;
goto err_out;
}
- device_printf(dev, "%s\n", ixl_fw_version_str(hw));
if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
hw->aq.api_min_ver > I40E_FW_API_VERSION_MINOR)
@@ -633,9 +560,6 @@ ixl_attach(device_t dev)
goto err_mac_hmc;
}
- /* Initialize mac filter list for VSI */
- SLIST_INIT(&vsi->ftl);
-
if (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) ||
(hw->aq.fw_maj_ver < 4)) {
i40e_msec_delay(75);
@@ -680,7 +604,9 @@ ixl_attach(device_t dev)
/* Initialize taskqueues */
ixl_init_taskqueues(pf);
- /* Initialize statistics */
+ /* Initialize statistics & add sysctls */
+ ixl_add_device_sysctls(pf);
+
ixl_pf_reset_stats(pf);
ixl_update_stats_counters(pf);
ixl_add_hw_stats(pf);
@@ -1558,7 +1484,8 @@ ixl_msix_adminq(void *arg)
{
struct ixl_pf *pf = arg;
struct i40e_hw *hw = &pf->hw;
- u32 reg, mask;
+ u32 reg, mask, rstat_reg;
+ bool do_task = FALSE;
++pf->admin_irq;
@@ -1566,12 +1493,52 @@ ixl_msix_adminq(void *arg)
mask = rd32(hw, I40E_PFINT_ICR0_ENA);
/* Check on the cause */
- if (reg & I40E_PFINT_ICR0_ADMINQ_MASK)
- mask &= ~I40E_PFINT_ICR0_ENA_ADMINQ_MASK;
+ if (reg & I40E_PFINT_ICR0_ADMINQ_MASK) {
+ mask &= ~I40E_PFINT_ICR0_ADMINQ_MASK;
+ do_task = TRUE;
+ }
if (reg & I40E_PFINT_ICR0_MAL_DETECT_MASK) {
ixl_handle_mdd_event(pf);
- mask &= ~I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK;
+ mask &= ~I40E_PFINT_ICR0_MAL_DETECT_MASK;
+ }
+
+ if (reg & I40E_PFINT_ICR0_GRST_MASK) {
+ device_printf(pf->dev, "Reset Requested!\n");
+ rstat_reg = rd32(hw, I40E_GLGEN_RSTAT);
+ rstat_reg = (rstat_reg & I40E_GLGEN_RSTAT_RESET_TYPE_MASK)
+ >> I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT;
+ device_printf(pf->dev, "Reset type: ");
+ switch (rstat_reg) {
+ /* These others might be handled similarly to an EMPR reset */
+ case I40E_RESET_CORER:
+ printf("CORER\n");
+ break;
+ case I40E_RESET_GLOBR:
+ printf("GLOBR\n");
+ break;
+ case I40E_RESET_EMPR:
+ printf("EMPR\n");
+ atomic_set_int(&pf->state, IXL_PF_STATE_EMPR_RESETTING);
+ break;
+ default:
+ printf("?\n");
+ break;
+ }
+ // overload admin queue task to check reset progress?
+ do_task = TRUE;
+ }
+
+ if (reg & I40E_PFINT_ICR0_ECC_ERR_MASK) {
+ device_printf(pf->dev, "ECC Error detected!\n");
+ }
+
+ if (reg & I40E_PFINT_ICR0_HMC_ERR_MASK) {
+ device_printf(pf->dev, "HMC Error detected!\n");
+ }
+
+ if (reg & I40E_PFINT_ICR0_PCI_EXCEPTION_MASK) {
+ device_printf(pf->dev, "PCI Exception detected!\n");
}
#ifdef PCI_IOV
@@ -1585,8 +1552,8 @@ ixl_msix_adminq(void *arg)
reg = reg | I40E_PFINT_DYN_CTL0_CLEARPBA_MASK;
wr32(hw, I40E_PFINT_DYN_CTL0, reg);
- taskqueue_enqueue(pf->tq, &pf->adminq);
- return;
+ if (do_task)
+ taskqueue_enqueue(pf->tq, &pf->adminq);
}
/*********************************************************************
@@ -2330,7 +2297,7 @@ ixl_init_msix(struct ixl_pf *pf)
if (!pf->msix_mem) {
/* May not be enabled */
device_printf(pf->dev,
- "Unable to map MSIX table \n");
+ "Unable to map MSIX table\n");
goto msi;
}
@@ -2435,7 +2402,7 @@ ixl_configure_msix(struct ixl_pf *pf)
reg = I40E_PFINT_ICR0_ENA_ECC_ERR_MASK |
I40E_PFINT_ICR0_ENA_GRST_MASK |
- I40E_PFINT_ICR0_HMC_ERR_MASK |
+ I40E_PFINT_ICR0_ENA_HMC_ERR_MASK |
I40E_PFINT_ICR0_ENA_ADMINQ_MASK |
I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK |
I40E_PFINT_ICR0_ENA_VFLR_MASK |
@@ -2583,7 +2550,7 @@ ixl_allocate_pci_resources(struct ixl_pf *pf)
&rid, RF_ACTIVE);
if (!(pf->pci_mem)) {
- device_printf(dev,"Unable to allocate bus resource: memory\n");
+ device_printf(dev, "Unable to allocate bus resource: memory\n");
return (ENXIO);
}
@@ -3128,6 +3095,9 @@ ixl_free_vsi(struct ixl_vsi *vsi)
struct ixl_queue *que = vsi->queues;
/* Free station queues */
+ if (!vsi->queues)
+ goto free_filters;
+
for (int i = 0; i < vsi->num_queues; i++, que++) {
struct tx_ring *txr = &que->txr;
struct rx_ring *rxr = &que->rxr;
@@ -3153,6 +3123,7 @@ ixl_free_vsi(struct ixl_vsi *vsi)
}
free(vsi->queues, M_DEVBUF);
+free_filters:
/* Free VSI filter list */
ixl_free_mac_filters(vsi);
}
@@ -4538,9 +4509,34 @@ ixl_do_adminq(void *context, int pending)
struct i40e_arq_event_info event;
i40e_status ret;
device_t dev = pf->dev;
- u32 loop = 0;
+ u32 reg, loop = 0;
u16 opcode, result;
+ // XXX: Possibly inappropriate overload
+ if (pf->state & IXL_PF_STATE_EMPR_RESETTING) {
+ int count = 0;
+ // ERJ: Typically finishes within 3-4 seconds
+ while (count++ < 100) {
+ reg = rd32(hw, I40E_GLGEN_RSTAT);
+ reg = reg & I40E_GLGEN_RSTAT_DEVSTATE_MASK;
+ if (reg) {
+ i40e_msec_delay(100);
+ } else {
+ break;
+ }
+ }
+ device_printf(dev, "EMPR reset wait count: %d\n", count);
+
+ device_printf(dev, "Rebuilding HW structs...\n");
+ // XXX: I feel like this could cause a kernel panic some time in the future
+ ixl_stop(pf);
+ ixl_init(pf);
+
+ atomic_clear_int(&pf->state, IXL_PF_STATE_EMPR_RESETTING);
+ return;
+ }
+
+ // Actually do Admin Queue handling
event.buf_len = IXL_AQ_BUF_SZ;
event.msg_buf = malloc(event.buf_len,
M_DEVBUF, M_NOWAIT | M_ZERO);
@@ -4830,6 +4826,96 @@ ixl_stat_update32(struct i40e_hw *hw, u32 reg,
*stat = (u32)((new_data + ((u64)1 << 32)) - *offset);
}
+static void
+ixl_add_device_sysctls(struct ixl_pf *pf)
+{
+ device_t dev = pf->dev;
+
+ /* Set up sysctls */
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "fc", CTLTYPE_INT | CTLFLAG_RW,
+ pf, 0, ixl_set_flowcntl, "I", "Flow Control");
+
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "advertise_speed", CTLTYPE_INT | CTLFLAG_RW,
+ pf, 0, ixl_set_advertise, "I", "Advertised Speed");
+
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "current_speed", CTLTYPE_STRING | CTLFLAG_RD,
+ pf, 0, ixl_current_speed, "A", "Current Port Speed");
+
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "fw_version", CTLTYPE_STRING | CTLFLAG_RD,
+ pf, 0, ixl_sysctl_show_fw, "A", "Firmware version");
+
+ SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "rx_itr", CTLFLAG_RW,
+ &ixl_rx_itr, IXL_ITR_8K, "RX ITR");
+
+ SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "dynamic_rx_itr", CTLFLAG_RW,
+ &ixl_dynamic_rx_itr, 0, "Dynamic RX ITR");
+
+ SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "tx_itr", CTLFLAG_RW,
+ &ixl_tx_itr, IXL_ITR_4K, "TX ITR");
+
+ SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "dynamic_tx_itr", CTLFLAG_RW,
+ &ixl_dynamic_tx_itr, 0, "Dynamic TX ITR");
+
+#ifdef IXL_DEBUG_SYSCTL
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "debug", CTLTYPE_INT|CTLFLAG_RW, pf, 0,
+ ixl_debug_info, "I", "Debug Information");
+
+ /* Debug shared-code message level */
+ SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "debug_mask", CTLFLAG_RW,
+ &pf->hw.debug_mask, 0, "Debug Message Level");
+
+ SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "vc_debug_level", CTLFLAG_RW, &pf->vc_debug_lvl,
+ 0, "PF/VF Virtual Channel debug level");
+
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "link_status", CTLTYPE_STRING | CTLFLAG_RD,
+ pf, 0, ixl_sysctl_link_status, "A", "Current Link Status");
+
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "phy_abilities", CTLTYPE_STRING | CTLFLAG_RD,
+ pf, 0, ixl_sysctl_phy_abilities, "A", "PHY Abilities");
+
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "filter_list", CTLTYPE_STRING | CTLFLAG_RD,
+ pf, 0, ixl_sysctl_sw_filter_list, "A", "SW Filter List");
+
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "hw_res_alloc", CTLTYPE_STRING | CTLFLAG_RD,
+ pf, 0, ixl_sysctl_hw_res_alloc, "A", "HW Resource Allocation");
+
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "switch_config", CTLTYPE_STRING | CTLFLAG_RD,
+ pf, 0, ixl_sysctl_switch_config, "A", "HW Switch Configuration");
+#endif
+}
+
/*
** Set flow control using sysctl:
** 0 - off
@@ -5185,12 +5271,32 @@ ixl_handle_nvmupd_cmd(struct ixl_pf *pf, struct ifdrv *ifd)
nvma = (struct i40e_nvm_access *)ifd->ifd_data;
- status = i40e_nvmupd_command(hw, nvma, nvma->data, &perrno);
+ if (pf->state & IXL_PF_STATE_EMPR_RESETTING) {
+ int count = 0;
+ while (count++ < 100) {
+ i40e_msec_delay(100);
+ if (!(pf->state & IXL_PF_STATE_EMPR_RESETTING))
+ break;
+ }
+ // device_printf(dev, "ioctl EMPR reset wait count %d\n", count);
+ }
+
+ if (!(pf->state & IXL_PF_STATE_EMPR_RESETTING)) {
+ IXL_PF_LOCK(pf);
+ status = i40e_nvmupd_command(hw, nvma, nvma->data, &perrno);
+ IXL_PF_UNLOCK(pf);
+ } else {
+ perrno = -EBUSY;
+ }
+
if (status)
device_printf(dev, "i40e_nvmupd_command status %d, perrno %d\n",
status, perrno);
- /* Convert EPERM error code for tools */
+ /*
+ * -EPERM is actually ERESTART, which the kernel interprets as it needing
+ * to run this ioctl again. So use -EACCES for -EPERM instead.
+ */
if (perrno == -EPERM)
return (-EACCES);
else
@@ -5315,6 +5421,41 @@ ixl_res_alloc_cmp(const void *a, const void *b)
return ((int)one->resource_type - (int)two->resource_type);
}
+/*
+ * Longest string length: 25
+ */
+static char *
+ixl_switch_res_type_string(u8 type)
+{
+ static char * ixl_switch_res_type_strings[0x14] = {
+ "VEB",
+ "VSI",
+ "Perfect Match MAC address",
+ "S-tag",
+ "(Reserved)",
+ "Multicast hash entry",
+ "Unicast hash entry",
+ "VLAN",
+ "VSI List entry",
+ "(Reserved)",
+ "VLAN Statistic Pool",
+ "Mirror Rule",
+ "Queue Set",
+ "Inner VLAN Forward filter",
+ "(Reserved)",
+ "Inner MAC",
+ "IP",
+ "GRE/VN1 Key",
+ "VN2 Key",
+ "Tunneling Port"
+ };
+
+ if (type < 0x14)
+ return ixl_switch_res_type_strings[type];
+ else
+ return "(Reserved)";
+}
+
static int
ixl_sysctl_hw_res_alloc(SYSCTL_HANDLER_ARGS)
{
@@ -5354,12 +5495,20 @@ ixl_sysctl_hw_res_alloc(SYSCTL_HANDLER_ARGS)
sbuf_cat(buf, "\n");
sbuf_printf(buf, "# of entries: %d\n", num_entries);
sbuf_printf(buf,
+#if 0
"Type | Guaranteed | Total | Used | Un-allocated\n"
" | (this) | (all) | (this) | (all) \n");
+#endif
+ " Type | Guaranteed | Total | Used | Un-allocated\n"
+ " | (this) | (all) | (this) | (all) \n");
for (int i = 0; i < num_entries; i++) {
sbuf_printf(buf,
+#if 0
"%#4x | %10d %5d %6d %12d",
resp[i].resource_type,
+#endif
+ "%25s | %10d %5d %6d %12d",
+ ixl_switch_res_type_string(resp[i].resource_type),
resp[i].guaranteed,
resp[i].total,
resp[i].used,
@@ -5379,36 +5528,48 @@ ixl_sysctl_hw_res_alloc(SYSCTL_HANDLER_ARGS)
/*
** Caller must init and delete sbuf; this function will clear and
** finish it for caller.
+**
+** XXX: Cannot use the SEID for this, since there is no longer a
+** fixed mapping between SEID and element type.
*/
static char *
-ixl_switch_element_string(struct sbuf *s, u16 seid, bool uplink)
+ixl_switch_element_string(struct sbuf *s,
+ struct i40e_aqc_switch_config_element_resp *element)
{
sbuf_clear(s);
- if (seid == 0 && uplink)
- sbuf_cat(s, "Network");
- else if (seid == 0)
- sbuf_cat(s, "Host");
- else if (seid == 1)
+ switch (element->element_type) {
+ case I40E_AQ_SW_ELEM_TYPE_MAC:
+ sbuf_printf(s, "MAC %3d", element->element_info);
+ break;
+ case I40E_AQ_SW_ELEM_TYPE_PF:
+ sbuf_printf(s, "PF %3d", element->element_info);
+ break;
+ case I40E_AQ_SW_ELEM_TYPE_VF:
+ sbuf_printf(s, "VF %3d", element->element_info);
+ break;
+ case I40E_AQ_SW_ELEM_TYPE_EMP:
sbuf_cat(s, "EMP");
- else if (seid <= 5)
- sbuf_printf(s, "MAC %d", seid - 2);
- else if (seid <= 15)
- sbuf_cat(s, "Reserved");
- else if (seid <= 31)
- sbuf_printf(s, "PF %d", seid - 16);
- else if (seid <= 159)
- sbuf_printf(s, "VF %d", seid - 32);
- else if (seid <= 287)
- sbuf_cat(s, "Reserved");
- else if (seid <= 511)
- sbuf_cat(s, "Other"); // for other structures
- else if (seid <= 895)
- sbuf_printf(s, "VSI %d", seid - 512);
- else if (seid <= 1023)
- sbuf_printf(s, "Reserved");
- else
- sbuf_cat(s, "Invalid");
+ break;
+ case I40E_AQ_SW_ELEM_TYPE_BMC:
+ sbuf_cat(s, "BMC");
+ break;
+ case I40E_AQ_SW_ELEM_TYPE_PV:
+ sbuf_cat(s, "PV");
+ break;
+ case I40E_AQ_SW_ELEM_TYPE_VEB:
+ sbuf_cat(s, "VEB");
+ break;
+ case I40E_AQ_SW_ELEM_TYPE_PA:
+ sbuf_cat(s, "PA");
+ break;
+ case I40E_AQ_SW_ELEM_TYPE_VSI:
+ sbuf_printf(s, "VSI %3d", element->element_info);
+ break;
+ default:
+ sbuf_cat(s, "?");
+ break;
+ }
sbuf_finish(s);
return sbuf_data(s);
@@ -5423,9 +5584,9 @@ ixl_sysctl_switch_config(SYSCTL_HANDLER_ARGS)
struct sbuf *buf;
struct sbuf *nmbuf;
int error = 0;
+ u16 next = 0;
u8 aq_buf[I40E_AQ_LARGE_BUF];
- u16 next = 0;
struct i40e_aqc_get_switch_config_resp *sw_config;
sw_config = (struct i40e_aqc_get_switch_config_resp *)aq_buf;
@@ -5444,6 +5605,9 @@ ixl_sysctl_switch_config(SYSCTL_HANDLER_ARGS)
sbuf_delete(buf);
return error;
}
+ if (next)
+ device_printf(dev, "%s: TODO: get more config with SEID %d\n",
+ __func__, next);
nmbuf = sbuf_new_auto();
if (!nmbuf) {
@@ -5454,7 +5618,8 @@ ixl_sysctl_switch_config(SYSCTL_HANDLER_ARGS)
sbuf_cat(buf, "\n");
// Assuming <= 255 elements in switch
- sbuf_printf(buf, "# of elements: %d\n", sw_config->header.num_reported);
+ sbuf_printf(buf, "# of reported elements: %d\n", sw_config->header.num_reported);
+ sbuf_printf(buf, "total # of elements: %d\n", sw_config->header.num_total);
/* Exclude:
** Revision -- all elements are revision 1 for now
*/
@@ -5466,13 +5631,11 @@ ixl_sysctl_switch_config(SYSCTL_HANDLER_ARGS)
sbuf_printf(buf, "%4d", sw_config->element[i].seid);
sbuf_cat(buf, " ");
sbuf_printf(buf, "(%8s)", ixl_switch_element_string(nmbuf,
- sw_config->element[i].seid, false));
+ &sw_config->element[i]));
sbuf_cat(buf, " | ");
- sbuf_printf(buf, "%8s", ixl_switch_element_string(nmbuf,
- sw_config->element[i].uplink_seid, true));
+ sbuf_printf(buf, "%8d", sw_config->element[i].uplink_seid);
sbuf_cat(buf, " ");
- sbuf_printf(buf, "%8s", ixl_switch_element_string(nmbuf,
- sw_config->element[i].downlink_seid, false));
+ sbuf_printf(buf, "%8d", sw_config->element[i].downlink_seid);
sbuf_cat(buf, " ");
sbuf_printf(buf, "%#8x", sw_config->element[i].connection_type);
if (i < sw_config->header.num_reported - 1)
diff --git a/sys/dev/ixl/ixl.h b/sys/dev/ixl/ixl.h
index 3bf3fe7..b28c852 100644
--- a/sys/dev/ixl/ixl.h
+++ b/sys/dev/ixl/ixl.h
@@ -205,7 +205,6 @@
#define IXL_BAR 3
#define IXL_ADM_LIMIT 2
#define IXL_TSO_SIZE 65535
-#define IXL_TX_BUF_SZ ((u32) 1514)
#define IXL_AQ_BUF_SZ ((u32) 4096)
#define IXL_RX_HDR 128
/* Controls the length of the Admin Queue */
diff --git a/sys/dev/ixl/ixl_pf.h b/sys/dev/ixl/ixl_pf.h
index 5780f7c..3859d90 100644
--- a/sys/dev/ixl/ixl_pf.h
+++ b/sys/dev/ixl/ixl_pf.h
@@ -42,6 +42,8 @@
#define VF_FLAG_PROMISC_CAP 0x08
#define VF_FLAG_MAC_ANTI_SPOOF 0x10
+#define IXL_PF_STATE_EMPR_RESETTING (1 << 0)
+
struct ixl_vf {
struct ixl_vsi vsi;
uint32_t vf_flags;
@@ -72,6 +74,7 @@ struct ixl_pf {
struct callout timer;
int msix;
int if_flags;
+ int state;
struct mtx pf_mtx;
OpenPOWER on IntegriCloud