aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Joyner <erj@FreeBSD.org>2022-03-04 18:25:25 +0000
committerEric Joyner <erj@FreeBSD.org>2022-03-08 00:11:46 +0000
commita0cdf45ea1d17453a8724cfe630dc838e71cb64e (patch)
tree8ea358fa8bc94a478d110b1d56f2d584a50d2f9b
parentc185d44f1c5fb1305a560a90c75d186886d0687e (diff)
downloadsrc-a0cdf45ea1d1.tar.gz
src-a0cdf45ea1d1.zip
ice(4): Update to 1.34.2-k
- Adds FW logging support - Once enabled, this lets the firmware print event and error messages to the log, increasing the visibility into what the hardware is doing; this is useful for debugging - General bug fixes - Adds inital DCB support to the driver - Notably, this adds support for DCBX to the driver; now with the fw_lldp sysctl set to 1, the driver and adapter will adopt a DCBX configuration sent from a link partner - Adds statistcs sysctls for priority flow control frames - Adds new configuration sysctls for DCB-related features: (VLAN) user priority to TC mapping; ETS bandwidth allocation; priority flow control - Remove unused SR-IOV files (until support gets added) Signed-off-by: Eric Joyner <erj@FreeBSD.org> Tested by: jeffrey.e.pieper@intel.com MFC after: 3 days MFC with: 213e91399b, e438f0a975 Relnotes: yes Sponsored by: Intel Corporation Differential Revision: https://reviews.freebsd.org/D34024 (cherry picked from commit 56429daea255fa719169bb23ded66f8edb6f5408) (cherry picked from commit 61d83041ab111fe491409f2eca2b528108b9ec29)
-rw-r--r--sys/conf/files.amd646
-rw-r--r--sys/conf/files.arm648
-rw-r--r--sys/conf/files.powerpc6
-rw-r--r--sys/dev/ice/ice_adminq_cmd.h175
-rw-r--r--sys/dev/ice/ice_common.c723
-rw-r--r--sys/dev/ice/ice_common.h47
-rw-r--r--sys/dev/ice/ice_dcb.c212
-rw-r--r--sys/dev/ice/ice_dcb.h21
-rw-r--r--sys/dev/ice/ice_devids.h12
-rw-r--r--sys/dev/ice/ice_drv_info.h25
-rw-r--r--sys/dev/ice/ice_features.h2
-rw-r--r--sys/dev/ice/ice_flex_pipe.c14
-rw-r--r--sys/dev/ice/ice_flex_type.h4
-rw-r--r--sys/dev/ice/ice_flow.c46
-rw-r--r--sys/dev/ice/ice_flow.h9
-rw-r--r--sys/dev/ice/ice_fw_logging.c425
-rw-r--r--sys/dev/ice/ice_fwlog.c505
-rw-r--r--sys/dev/ice/ice_fwlog.h91
-rw-r--r--sys/dev/ice/ice_hw_autogen.h148
-rw-r--r--sys/dev/ice/ice_iflib.h6
-rw-r--r--sys/dev/ice/ice_iflib_txrx.c82
-rw-r--r--sys/dev/ice/ice_lan_tx_rx.h27
-rw-r--r--sys/dev/ice/ice_lib.c1662
-rw-r--r--sys/dev/ice/ice_lib.h39
-rw-r--r--sys/dev/ice/ice_nvm.c69
-rw-r--r--sys/dev/ice/ice_nvm.h13
-rw-r--r--sys/dev/ice/ice_osdep.c36
-rw-r--r--sys/dev/ice/ice_osdep.h2
-rw-r--r--sys/dev/ice/ice_protocol_type.h14
-rw-r--r--sys/dev/ice/ice_sched.c63
-rw-r--r--sys/dev/ice/ice_sriov.c596
-rw-r--r--sys/dev/ice/ice_sriov.h65
-rw-r--r--sys/dev/ice/ice_strings.c130
-rw-r--r--sys/dev/ice/ice_switch.c73
-rw-r--r--sys/dev/ice/ice_switch.h12
-rw-r--r--sys/dev/ice/ice_type.h83
-rw-r--r--sys/dev/ice/ice_vlan_mode.c74
-rw-r--r--sys/dev/ice/ice_vlan_mode.h2
-rw-r--r--sys/dev/ice/if_ice_iflib.c42
-rw-r--r--sys/dev/ice/virtchnl.h613
-rw-r--r--sys/dev/ice/virtchnl_inline_ipsec.h36
-rw-r--r--sys/dev/ice/virtchnl_lan_desc.h293
-rw-r--r--sys/modules/ice/Makefile3
43 files changed, 5082 insertions, 1432 deletions
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index 36ed2bb88737..9c3c8e855bde 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -215,12 +215,14 @@ dev/ice/ice_nvm.c optional ice pci \
compile-with "${NORMAL_C} -I$S/dev/ice"
dev/ice/ice_sched.c optional ice pci \
compile-with "${NORMAL_C} -I$S/dev/ice"
-dev/ice/ice_sriov.c optional ice pci \
- compile-with "${NORMAL_C} -I$S/dev/ice"
dev/ice/ice_switch.c optional ice pci \
compile-with "${NORMAL_C} -I$S/dev/ice"
dev/ice/ice_vlan_mode.c optional ice pci \
compile-with "${NORMAL_C} -I$S/dev/ice"
+dev/ice/ice_fw_logging.c optional ice pci \
+ compile-with "${NORMAL_C} -I$S/dev/ice"
+dev/ice/ice_fwlog.c optional ice pci \
+ compile-with "${NORMAL_C} -I$S/dev/ice"
ice_ddp.c optional ice_ddp \
compile-with "${AWK} -f $S/tools/fw_stub.awk ice_ddp.fw:ice_ddp:0x01031b00 -mice_ddp -c${.TARGET}" \
no-ctfconvert no-implicit-rule before-depend local \
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
index ba43f2647cfd..b694ed091d88 100644
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -203,11 +203,13 @@ dev/ice/ice_nvm.c optional ice pci \
compile-with "${NORMAL_C} -I$S/dev/ice"
dev/ice/ice_sched.c optional ice pci \
compile-with "${NORMAL_C} -I$S/dev/ice"
-dev/ice/ice_sriov.c optional ice pci \
- compile-with "${NORMAL_C} -I$S/dev/ice"
dev/ice/ice_switch.c optional ice pci \
compile-with "${NORMAL_C} -I$S/dev/ice"
-dev/ice/ice_vlan_mode.c optional ice pci \
+dev/ice/ice_vlan_mode.c optional ice pci \
+ compile-with "${NORMAL_C} -I$S/dev/ice"
+dev/ice/ice_fw_logging.c optional ice pci \
+ compile-with "${NORMAL_C} -I$S/dev/ice"
+dev/ice/ice_fwlog.c optional ice pci \
compile-with "${NORMAL_C} -I$S/dev/ice"
ice_ddp.c optional ice_ddp \
compile-with "${AWK} -f $S/tools/fw_stub.awk ice_ddp.fw:ice_ddp:0x01031b00 -mice_ddp -c${.TARGET}" \
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
index 233ee5f89743..6491c8ae3d9a 100644
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -66,12 +66,14 @@ dev/ice/ice_nvm.c optional ice pci powerpc64 \
compile-with "${NORMAL_C} -I$S/dev/ice"
dev/ice/ice_sched.c optional ice pci powerpc64 \
compile-with "${NORMAL_C} -I$S/dev/ice"
-dev/ice/ice_sriov.c optional ice pci powerpc64 \
- compile-with "${NORMAL_C} -I$S/dev/ice"
dev/ice/ice_switch.c optional ice pci powerpc64 \
compile-with "${NORMAL_C} -I$S/dev/ice"
dev/ice/ice_vlan_mode.c optional ice pci powerpc64 \
compile-with "${NORMAL_C} -I$S/dev/ice"
+dev/ice/ice_fw_logging.c optional ice pci powerpc64 \
+ compile-with "${NORMAL_C} -I$S/dev/ice"
+dev/ice/ice_fwlog.c optional ice pci powerpc64 \
+ compile-with "${NORMAL_C} -I$S/dev/ice"
ice_ddp.c optional ice_ddp powerpc64 \
compile-with "${AWK} -f $S/tools/fw_stub.awk ice_ddp.fw:ice_ddp:0x01031b00 -mice_ddp -c${.TARGET}" \
no-ctfconvert no-implicit-rule before-depend local \
diff --git a/sys/dev/ice/ice_adminq_cmd.h b/sys/dev/ice/ice_adminq_cmd.h
index 5e8560dccb1e..eae8a412d1cc 100644
--- a/sys/dev/ice/ice_adminq_cmd.h
+++ b/sys/dev/ice/ice_adminq_cmd.h
@@ -169,6 +169,10 @@ struct ice_aqc_list_caps_elem {
#define ICE_AQC_CAPS_PCIE_RESET_AVOIDANCE 0x0076
#define ICE_AQC_CAPS_POST_UPDATE_RESET_RESTRICT 0x0077
#define ICE_AQC_CAPS_NVM_MGMT 0x0080
+#define ICE_AQC_CAPS_EXT_TOPO_DEV_IMG0 0x0081
+#define ICE_AQC_CAPS_EXT_TOPO_DEV_IMG1 0x0082
+#define ICE_AQC_CAPS_EXT_TOPO_DEV_IMG2 0x0083
+#define ICE_AQC_CAPS_EXT_TOPO_DEV_IMG3 0x0084
u8 major_ver;
u8 minor_ver;
@@ -1240,10 +1244,11 @@ struct ice_aqc_get_phy_caps {
/* 18.0 - Report qualified modules */
#define ICE_AQC_GET_PHY_RQM BIT(0)
/* 18.1 - 18.3 : Report mode
- * 000b - Report NVM capabilities
- * 001b - Report topology capabilities
- * 010b - Report SW configured
- * 100b - Report default capabilities
+ * 000b - Report topology capabilities, without media
+ * 001b - Report topology capabilities, with media
+ * 010b - Report Active configuration
+ * 011b - Report PHY Type and FEC mode capabilities
+ * 100b - Report Default capabilities
*/
#define ICE_AQC_REPORT_MODE_S 1
#define ICE_AQC_REPORT_MODE_M (7 << ICE_AQC_REPORT_MODE_S)
@@ -1586,6 +1591,7 @@ struct ice_aqc_set_event_mask {
#define ICE_AQ_LINK_EVENT_PORT_TX_SUSPENDED BIT(9)
#define ICE_AQ_LINK_EVENT_TOPO_CONFLICT BIT(10)
#define ICE_AQ_LINK_EVENT_MEDIA_CONFLICT BIT(11)
+#define ICE_AQ_LINK_EVENT_PHY_FW_LOAD_FAIL BIT(12)
u8 reserved1[6];
};
@@ -1774,7 +1780,7 @@ struct ice_aqc_dnl_read_log_response {
};
-struct ice_aqc_link_topo_addr {
+struct ice_aqc_link_topo_params {
u8 lport_num;
u8 lport_num_valid;
#define ICE_AQC_LINK_TOPO_PORT_NUM_VALID BIT(0)
@@ -1800,6 +1806,10 @@ struct ice_aqc_link_topo_addr {
#define ICE_AQC_LINK_TOPO_NODE_CTX_PROVIDED 4
#define ICE_AQC_LINK_TOPO_NODE_CTX_OVERRIDE 5
u8 index;
+};
+
+struct ice_aqc_link_topo_addr {
+ struct ice_aqc_link_topo_params topo_params;
__le16 handle;
#define ICE_AQC_LINK_TOPO_HANDLE_S 0
#define ICE_AQC_LINK_TOPO_HANDLE_M (0x3FF << ICE_AQC_LINK_TOPO_HANDLE_S)
@@ -1822,59 +1832,10 @@ struct ice_aqc_link_topo_addr {
struct ice_aqc_get_link_topo {
struct ice_aqc_link_topo_addr addr;
u8 node_part_num;
+#define ICE_ACQ_GET_LINK_TOPO_NODE_NR_PCA9575 0x21
u8 rsvd[9];
};
-/* Get Link Topology Pin (direct, 0x06E1) */
-struct ice_aqc_get_link_topo_pin {
- struct ice_aqc_link_topo_addr addr;
- u8 input_io_params;
-#define ICE_AQC_LINK_TOPO_INPUT_IO_FUNC_S 0
-#define ICE_AQC_LINK_TOPO_INPUT_IO_FUNC_M \
- (0x1F << ICE_AQC_LINK_TOPO_INPUT_IO_FUNC_S)
-#define ICE_AQC_LINK_TOPO_IO_FUNC_GPIO 0
-#define ICE_AQC_LINK_TOPO_IO_FUNC_RESET_N 1
-#define ICE_AQC_LINK_TOPO_IO_FUNC_INT_N 2
-#define ICE_AQC_LINK_TOPO_IO_FUNC_PRESENT_N 3
-#define ICE_AQC_LINK_TOPO_IO_FUNC_TX_DIS 4
-#define ICE_AQC_LINK_TOPO_IO_FUNC_MODSEL_N 5
-#define ICE_AQC_LINK_TOPO_IO_FUNC_LPMODE 6
-#define ICE_AQC_LINK_TOPO_IO_FUNC_TX_FAULT 7
-#define ICE_AQC_LINK_TOPO_IO_FUNC_RX_LOSS 8
-#define ICE_AQC_LINK_TOPO_IO_FUNC_RS0 9
-#define ICE_AQC_LINK_TOPO_IO_FUNC_RS1 10
-#define ICE_AQC_LINK_TOPO_IO_FUNC_EEPROM_WP 11
-/* 12 repeats intentionally due to two different uses depending on context */
-#define ICE_AQC_LINK_TOPO_IO_FUNC_LED 12
-#define ICE_AQC_LINK_TOPO_IO_FUNC_RED_LED 12
-#define ICE_AQC_LINK_TOPO_IO_FUNC_GREEN_LED 13
-#define ICE_AQC_LINK_TOPO_IO_FUNC_BLUE_LED 14
-#define ICE_AQC_LINK_TOPO_INPUT_IO_TYPE_S 5
-#define ICE_AQC_LINK_TOPO_INPUT_IO_TYPE_M \
- (0x7 << ICE_AQC_LINK_TOPO_INPUT_IO_TYPE_S)
-/* Use ICE_AQC_LINK_TOPO_NODE_TYPE_* for the type values */
- u8 output_io_params;
-#define ICE_AQC_LINK_TOPO_OUTPUT_IO_FUNC_S 0
-#define ICE_AQC_LINK_TOPO_OUTPUT_IO_FUNC_M \
- (0x1F << \ ICE_AQC_LINK_TOPO_INPUT_IO_FUNC_NUM_S)
-/* Use ICE_AQC_LINK_TOPO_IO_FUNC_* for the non-numerical options */
-#define ICE_AQC_LINK_TOPO_OUTPUT_IO_TYPE_S 5
-#define ICE_AQC_LINK_TOPO_OUTPUT_IO_TYPE_M \
- (0x7 << ICE_AQC_LINK_TOPO_INPUT_IO_TYPE_S)
-/* Use ICE_AQC_LINK_TOPO_NODE_TYPE_* for the type values */
- u8 output_io_flags;
-#define ICE_AQC_LINK_TOPO_OUTPUT_SPEED_S 0
-#define ICE_AQC_LINK_TOPO_OUTPUT_SPEED_M \
- (0x7 << ICE_AQC_LINK_TOPO_OUTPUT_SPEED_S)
-#define ICE_AQC_LINK_TOPO_OUTPUT_INT_S 3
-#define ICE_AQC_LINK_TOPO_OUTPUT_INT_M \
- (0x3 << ICE_AQC_LINK_TOPO_OUTPUT_INT_S)
-#define ICE_AQC_LINK_TOPO_OUTPUT_POLARITY BIT(5)
-#define ICE_AQC_LINK_TOPO_OUTPUT_VALUE BIT(6)
-#define ICE_AQC_LINK_TOPO_OUTPUT_DRIVEN BIT(7)
- u8 rsvd[7];
-};
-
/* Read/Write I2C (direct, 0x06E2/0x06E3) */
struct ice_aqc_i2c {
struct ice_aqc_link_topo_addr topo_addr;
@@ -2072,23 +2033,18 @@ struct ice_aqc_sw_gpio {
u8 rsvd[12];
};
-/* Program topology device NVM (direct, 0x06F2) */
-struct ice_aqc_program_topology_device_nvm {
- u8 lport_num;
- u8 lport_num_valid;
- u8 node_type_ctx;
- u8 index;
+/* Program Topology Device NVM (direct, 0x06F2) */
+struct ice_aqc_prog_topo_dev_nvm {
+ struct ice_aqc_link_topo_params topo_params;
u8 rsvd[12];
};
-/* Read topology device NVM (indirect, 0x06F3) */
-struct ice_aqc_read_topology_device_nvm {
- u8 lport_num;
- u8 lport_num_valid;
- u8 node_type_ctx;
- u8 index;
+/* Read Topology Device NVM (direct, 0x06F3) */
+struct ice_aqc_read_topo_dev_nvm {
+ struct ice_aqc_link_topo_params topo_params;
__le32 start_address;
- u8 data_read[8];
+#define ICE_AQC_READ_TOPO_DEV_NVM_DATA_READ_SIZE 8
+ u8 data_read[ICE_AQC_READ_TOPO_DEV_NVM_DATA_READ_SIZE];
};
/* NVM Read command (indirect 0x0701)
@@ -2117,10 +2073,11 @@ struct ice_aqc_nvm {
#define ICE_AQC_NVM_REVERT_LAST_ACTIV BIT(6) /* Write Activate only */
#define ICE_AQC_NVM_ACTIV_SEL_MASK MAKEMASK(0x7, 3)
#define ICE_AQC_NVM_FLASH_ONLY BIT(7)
-#define ICE_AQC_NVM_POR_FLAG 0 /* Used by NVM Write completion on ARQ */
-#define ICE_AQC_NVM_PERST_FLAG 1
-#define ICE_AQC_NVM_EMPR_FLAG 2
-#define ICE_AQC_NVM_EMPR_ENA BIT(0)
+#define ICE_AQC_NVM_RESET_LVL_M MAKEMASK(0x3, 0) /* Write reply only */
+#define ICE_AQC_NVM_POR_FLAG 0
+#define ICE_AQC_NVM_PERST_FLAG 1
+#define ICE_AQC_NVM_EMPR_FLAG 2
+#define ICE_AQC_NVM_EMPR_ENA BIT(0) /* Write Activate reply only */
__le16 module_typeid;
__le16 length;
#define ICE_AQC_NVM_ERASE_LEN 0xFFFF
@@ -2665,6 +2622,63 @@ struct ice_aqc_event_lan_overflow {
u8 reserved[8];
};
+/* Debug Dump Internal Data (indirect 0xFF08) */
+struct ice_aqc_debug_dump_internals {
+ u8 cluster_id;
+#define ICE_AQC_DBG_DUMP_CLUSTER_ID_SW 0
+#define ICE_AQC_DBG_DUMP_CLUSTER_ID_TXSCHED 2
+#define ICE_AQC_DBG_DUMP_CLUSTER_ID_PROFILES 3
+/* EMP_DRAM only dumpable in device debug mode */
+#define ICE_AQC_DBG_DUMP_CLUSTER_ID_EMP_DRAM 4
+#define ICE_AQC_DBG_DUMP_CLUSTER_ID_LINK 5
+/* AUX_REGS only dumpable in device debug mode */
+#define ICE_AQC_DBG_DUMP_CLUSTER_ID_AUX_REGS 6
+#define ICE_AQC_DBG_DUMP_CLUSTER_ID_DCB 7
+#define ICE_AQC_DBG_DUMP_CLUSTER_ID_L2P 8
+ u8 reserved;
+ __le16 table_id; /* Used only for non-memory clusters */
+ __le32 idx; /* In table entries for tables, in bytes for memory */
+ __le32 addr_high;
+ __le32 addr_low;
+};
+
+enum ice_aqc_fw_logging_mod {
+ ICE_AQC_FW_LOG_ID_GENERAL = 0,
+ ICE_AQC_FW_LOG_ID_CTRL,
+ ICE_AQC_FW_LOG_ID_LINK,
+ ICE_AQC_FW_LOG_ID_LINK_TOPO,
+ ICE_AQC_FW_LOG_ID_DNL,
+ ICE_AQC_FW_LOG_ID_I2C,
+ ICE_AQC_FW_LOG_ID_SDP,
+ ICE_AQC_FW_LOG_ID_MDIO,
+ ICE_AQC_FW_LOG_ID_ADMINQ,
+ ICE_AQC_FW_LOG_ID_HDMA,
+ ICE_AQC_FW_LOG_ID_LLDP,
+ ICE_AQC_FW_LOG_ID_DCBX,
+ ICE_AQC_FW_LOG_ID_DCB,
+ ICE_AQC_FW_LOG_ID_XLR,
+ ICE_AQC_FW_LOG_ID_NVM,
+ ICE_AQC_FW_LOG_ID_AUTH,
+ ICE_AQC_FW_LOG_ID_VPD,
+ ICE_AQC_FW_LOG_ID_IOSF,
+ ICE_AQC_FW_LOG_ID_PARSER,
+ ICE_AQC_FW_LOG_ID_SW,
+ ICE_AQC_FW_LOG_ID_SCHEDULER,
+ ICE_AQC_FW_LOG_ID_TXQ,
+ ICE_AQC_FW_LOG_ID_RSVD,
+ ICE_AQC_FW_LOG_ID_POST,
+ ICE_AQC_FW_LOG_ID_WATCHDOG,
+ ICE_AQC_FW_LOG_ID_TASK_DISPATCH,
+ ICE_AQC_FW_LOG_ID_MNG,
+ ICE_AQC_FW_LOG_ID_SYNCE,
+ ICE_AQC_FW_LOG_ID_HEALTH,
+ ICE_AQC_FW_LOG_ID_TSDRV,
+ ICE_AQC_FW_LOG_ID_PFREG,
+ ICE_AQC_FW_LOG_ID_MDLVER,
+ ICE_AQC_FW_LOG_ID_MAX,
+};
+
+
/* Set Health Status (direct 0xFF20) */
struct ice_aqc_set_health_status_config {
u8 event_source;
@@ -2694,6 +2708,8 @@ struct ice_aqc_set_health_status_config {
#define ICE_AQC_HEALTH_STATUS_ERR_LINK_HW_ACCESS 0x115
#define ICE_AQC_HEALTH_STATUS_ERR_LINK_RUNTIME 0x116
#define ICE_AQC_HEALTH_STATUS_ERR_DNL_INIT 0x117
+#define ICE_AQC_HEALTH_STATUS_ERR_PHY_NVM_PROG 0x120
+#define ICE_AQC_HEALTH_STATUS_ERR_PHY_FW_LOAD 0x121
#define ICE_AQC_HEALTH_STATUS_INFO_RECOVERY 0x500
#define ICE_AQC_HEALTH_STATUS_ERR_FLASH_ACCESS 0x501
#define ICE_AQC_HEALTH_STATUS_ERR_NVM_AUTH 0x502
@@ -2745,11 +2761,11 @@ struct ice_aqc_clear_health_status {
* Get FW Log (indirect 0xFF34)
* Clear FW Log (indirect 0xFF35)
*/
-
struct ice_aqc_fw_log {
u8 cmd_flags;
#define ICE_AQC_FW_LOG_CONF_UART_EN BIT(0)
#define ICE_AQC_FW_LOG_CONF_AQ_EN BIT(1)
+#define ICE_AQC_FW_LOG_QUERY_REGISTERED BIT(2)
#define ICE_AQC_FW_LOG_CONF_SET_VALID BIT(3)
#define ICE_AQC_FW_LOG_AQ_REGISTER BIT(0)
#define ICE_AQC_FW_LOG_AQ_QUERY BIT(2)
@@ -2837,6 +2853,7 @@ struct ice_aq_desc {
struct ice_aqc_mdio read_write_mdio;
struct ice_aqc_gpio_by_func read_write_gpio_by_func;
struct ice_aqc_gpio read_write_gpio;
+ struct ice_aqc_sw_gpio sw_read_write_gpio;
struct ice_aqc_set_led set_led;
struct ice_aqc_mdio read_mdio;
struct ice_aqc_mdio write_mdio;
@@ -2887,6 +2904,8 @@ struct ice_aq_desc {
struct ice_aqc_download_pkg download_pkg;
struct ice_aqc_get_pkg_info_list get_pkg_info_list;
struct ice_aqc_driver_shared_params drv_shared_params;
+ struct ice_aqc_fw_log fw_log;
+ struct ice_aqc_debug_dump_internals debug_dump;
struct ice_aqc_set_mac_lb set_mac_lb;
struct ice_aqc_alloc_free_res_cmd sw_res_ctrl;
struct ice_aqc_get_res_alloc get_res;
@@ -2902,6 +2921,8 @@ struct ice_aq_desc {
get_supported_health_status_codes;
struct ice_aqc_get_health_status get_health_status;
struct ice_aqc_clear_health_status clear_health_status;
+ struct ice_aqc_prog_topo_dev_nvm prog_topo_dev_nvm;
+ struct ice_aqc_read_topo_dev_nvm read_topo_dev_nvm;
} params;
};
@@ -3069,7 +3090,6 @@ enum ice_adminq_opc {
ice_aqc_opc_dnl_set_breakpoints = 0x0686,
ice_aqc_opc_dnl_read_log = 0x0687,
ice_aqc_opc_get_link_topo = 0x06E0,
- ice_aqc_opc_get_link_topo_pin = 0x06E1,
ice_aqc_opc_read_i2c = 0x06E2,
ice_aqc_opc_write_i2c = 0x06E3,
ice_aqc_opc_read_mdio = 0x06E4,
@@ -3085,8 +3105,8 @@ enum ice_adminq_opc {
ice_aqc_opc_sff_eeprom = 0x06EE,
ice_aqc_opc_sw_set_gpio = 0x06EF,
ice_aqc_opc_sw_get_gpio = 0x06F0,
- ice_aqc_opc_program_topology_device_nvm = 0x06F2,
- ice_aqc_opc_read_topology_device_nvm = 0x06F3,
+ ice_aqc_opc_prog_topo_dev_nvm = 0x06F2,
+ ice_aqc_opc_read_topo_dev_nvm = 0x06F3,
/* NVM commands */
ice_aqc_opc_nvm_read = 0x0701,
@@ -3148,6 +3168,9 @@ enum ice_adminq_opc {
/* Standalone Commands/Events */
ice_aqc_opc_event_lan_overflow = 0x1001,
+ /* debug commands */
+ ice_aqc_opc_debug_dump_internals = 0xFF08,
+
/* SystemDiagnostic commands */
ice_aqc_opc_set_health_status_config = 0xFF20,
ice_aqc_opc_get_supported_health_status_codes = 0xFF21,
diff --git a/sys/dev/ice/ice_common.c b/sys/dev/ice/ice_common.c
index 1e5d6dcb7d30..80aa3557bf75 100644
--- a/sys/dev/ice/ice_common.c
+++ b/sys/dev/ice/ice_common.c
@@ -40,6 +40,120 @@
#define ICE_PF_RESET_WAIT_COUNT 300
/**
+ * dump_phy_type - helper function that prints PHY type strings
+ * @hw: pointer to the HW structure
+ * @phy: 64 bit PHY type to decipher
+ * @i: bit index within phy
+ * @phy_string: string corresponding to bit i in phy
+ * @prefix: prefix string to differentiate multiple dumps
+ */
+static void
+dump_phy_type(struct ice_hw *hw, u64 phy, u8 i, const char *phy_string,
+ const char *prefix)
+{
+ if (phy & BIT_ULL(i))
+ ice_debug(hw, ICE_DBG_PHY, "%s: bit(%d): %s\n", prefix, i,
+ phy_string);
+}
+
+/**
+ * ice_dump_phy_type_low - helper function to dump phy_type_low
+ * @hw: pointer to the HW structure
+ * @low: 64 bit value for phy_type_low
+ * @prefix: prefix string to differentiate multiple dumps
+ */
+static void
+ice_dump_phy_type_low(struct ice_hw *hw, u64 low, const char *prefix)
+{
+ ice_debug(hw, ICE_DBG_PHY, "%s: phy_type_low: 0x%016llx\n", prefix,
+ (unsigned long long)low);
+
+ dump_phy_type(hw, low, 0, "100BASE_TX", prefix);
+ dump_phy_type(hw, low, 1, "100M_SGMII", prefix);
+ dump_phy_type(hw, low, 2, "1000BASE_T", prefix);
+ dump_phy_type(hw, low, 3, "1000BASE_SX", prefix);
+ dump_phy_type(hw, low, 4, "1000BASE_LX", prefix);
+ dump_phy_type(hw, low, 5, "1000BASE_KX", prefix);
+ dump_phy_type(hw, low, 6, "1G_SGMII", prefix);
+ dump_phy_type(hw, low, 7, "2500BASE_T", prefix);
+ dump_phy_type(hw, low, 8, "2500BASE_X", prefix);
+ dump_phy_type(hw, low, 9, "2500BASE_KX", prefix);
+ dump_phy_type(hw, low, 10, "5GBASE_T", prefix);
+ dump_phy_type(hw, low, 11, "5GBASE_KR", prefix);
+ dump_phy_type(hw, low, 12, "10GBASE_T", prefix);
+ dump_phy_type(hw, low, 13, "10G_SFI_DA", prefix);
+ dump_phy_type(hw, low, 14, "10GBASE_SR", prefix);
+ dump_phy_type(hw, low, 15, "10GBASE_LR", prefix);
+ dump_phy_type(hw, low, 16, "10GBASE_KR_CR1", prefix);
+ dump_phy_type(hw, low, 17, "10G_SFI_AOC_ACC", prefix);
+ dump_phy_type(hw, low, 18, "10G_SFI_C2C", prefix);
+ dump_phy_type(hw, low, 19, "25GBASE_T", prefix);
+ dump_phy_type(hw, low, 20, "25GBASE_CR", prefix);
+ dump_phy_type(hw, low, 21, "25GBASE_CR_S", prefix);
+ dump_phy_type(hw, low, 22, "25GBASE_CR1", prefix);
+ dump_phy_type(hw, low, 23, "25GBASE_SR", prefix);
+ dump_phy_type(hw, low, 24, "25GBASE_LR", prefix);
+ dump_phy_type(hw, low, 25, "25GBASE_KR", prefix);
+ dump_phy_type(hw, low, 26, "25GBASE_KR_S", prefix);
+ dump_phy_type(hw, low, 27, "25GBASE_KR1", prefix);
+ dump_phy_type(hw, low, 28, "25G_AUI_AOC_ACC", prefix);
+ dump_phy_type(hw, low, 29, "25G_AUI_C2C", prefix);
+ dump_phy_type(hw, low, 30, "40GBASE_CR4", prefix);
+ dump_phy_type(hw, low, 31, "40GBASE_SR4", prefix);
+ dump_phy_type(hw, low, 32, "40GBASE_LR4", prefix);
+ dump_phy_type(hw, low, 33, "40GBASE_KR4", prefix);
+ dump_phy_type(hw, low, 34, "40G_XLAUI_AOC_ACC", prefix);
+ dump_phy_type(hw, low, 35, "40G_XLAUI", prefix);
+ dump_phy_type(hw, low, 36, "50GBASE_CR2", prefix);
+ dump_phy_type(hw, low, 37, "50GBASE_SR2", prefix);
+ dump_phy_type(hw, low, 38, "50GBASE_LR2", prefix);
+ dump_phy_type(hw, low, 39, "50GBASE_KR2", prefix);
+ dump_phy_type(hw, low, 40, "50G_LAUI2_AOC_ACC", prefix);
+ dump_phy_type(hw, low, 41, "50G_LAUI2", prefix);
+ dump_phy_type(hw, low, 42, "50G_AUI2_AOC_ACC", prefix);
+ dump_phy_type(hw, low, 43, "50G_AUI2", prefix);
+ dump_phy_type(hw, low, 44, "50GBASE_CP", prefix);
+ dump_phy_type(hw, low, 45, "50GBASE_SR", prefix);
+ dump_phy_type(hw, low, 46, "50GBASE_FR", prefix);
+ dump_phy_type(hw, low, 47, "50GBASE_LR", prefix);
+ dump_phy_type(hw, low, 48, "50GBASE_KR_PAM4", prefix);
+ dump_phy_type(hw, low, 49, "50G_AUI1_AOC_ACC", prefix);
+ dump_phy_type(hw, low, 50, "50G_AUI1", prefix);
+ dump_phy_type(hw, low, 51, "100GBASE_CR4", prefix);
+ dump_phy_type(hw, low, 52, "100GBASE_SR4", prefix);
+ dump_phy_type(hw, low, 53, "100GBASE_LR4", prefix);
+ dump_phy_type(hw, low, 54, "100GBASE_KR4", prefix);
+ dump_phy_type(hw, low, 55, "100G_CAUI4_AOC_ACC", prefix);
+ dump_phy_type(hw, low, 56, "100G_CAUI4", prefix);
+ dump_phy_type(hw, low, 57, "100G_AUI4_AOC_ACC", prefix);
+ dump_phy_type(hw, low, 58, "100G_AUI4", prefix);
+ dump_phy_type(hw, low, 59, "100GBASE_CR_PAM4", prefix);
+ dump_phy_type(hw, low, 60, "100GBASE_KR_PAM4", prefix);
+ dump_phy_type(hw, low, 61, "100GBASE_CP2", prefix);
+ dump_phy_type(hw, low, 62, "100GBASE_SR2", prefix);
+ dump_phy_type(hw, low, 63, "100GBASE_DR", prefix);
+}
+
+/**
+ * ice_dump_phy_type_high - helper function to dump phy_type_high
+ * @hw: pointer to the HW structure
+ * @high: 64 bit value for phy_type_high
+ * @prefix: prefix string to differentiate multiple dumps
+ */
+static void
+ice_dump_phy_type_high(struct ice_hw *hw, u64 high, const char *prefix)
+{
+ ice_debug(hw, ICE_DBG_PHY, "%s: phy_type_high: 0x%016llx\n", prefix,
+ (unsigned long long)high);
+
+ dump_phy_type(hw, high, 0, "100GBASE_KR2_PAM4", prefix);
+ dump_phy_type(hw, high, 1, "100G_CAUI2_AOC_ACC", prefix);
+ dump_phy_type(hw, high, 2, "100G_CAUI2", prefix);
+ dump_phy_type(hw, high, 3, "100G_AUI2_AOC_ACC", prefix);
+ dump_phy_type(hw, high, 4, "100G_AUI2", prefix);
+}
+
+/**
* ice_set_mac_type - Sets MAC type
* @hw: pointer to the HW structure
*
@@ -76,6 +190,11 @@ enum ice_status ice_set_mac_type(struct ice_hw *hw)
case ICE_DEV_ID_E823L_BACKPLANE:
case ICE_DEV_ID_E823L_QSFP:
case ICE_DEV_ID_E823L_SFP:
+ case ICE_DEV_ID_E823C_10G_BASE_T:
+ case ICE_DEV_ID_E823C_BACKPLANE:
+ case ICE_DEV_ID_E823C_QSFP:
+ case ICE_DEV_ID_E823C_SFP:
+ case ICE_DEV_ID_E823C_SGMII:
hw->mac_type = ICE_MAC_GENERIC;
break;
default:
@@ -88,6 +207,42 @@ enum ice_status ice_set_mac_type(struct ice_hw *hw)
}
/**
+ * ice_is_e810
+ * @hw: pointer to the hardware structure
+ *
+ * returns true if the device is E810 based, false if not.
+ */
+bool ice_is_e810(struct ice_hw *hw)
+{
+ return hw->mac_type == ICE_MAC_E810;
+}
+
+/**
+ * ice_is_e810t
+ * @hw: pointer to the hardware structure
+ *
+ * returns true if the device is E810T based, false if not.
+ */
+bool ice_is_e810t(struct ice_hw *hw)
+{
+ switch (hw->device_id) {
+ case ICE_DEV_ID_E810C_SFP:
+ if (hw->subsystem_device_id == ICE_SUBDEV_ID_E810T ||
+ hw->subsystem_device_id == ICE_SUBDEV_ID_E810T2)
+ return true;
+ break;
+ case ICE_DEV_ID_E810C_QSFP:
+ if (hw->subsystem_device_id == ICE_SUBDEV_ID_E810T2)
+ return true;
+ break;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+/**
* ice_clear_pf_cfg - Clear PF configuration
* @hw: pointer to the hardware structure
*
@@ -181,6 +336,7 @@ ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
u16 pcaps_size = sizeof(*pcaps);
struct ice_aq_desc desc;
enum ice_status status;
+ const char *prefix;
struct ice_hw *hw;
cmd = &desc.params.get_phy;
@@ -201,29 +357,42 @@ ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
cmd->param0 |= CPU_TO_LE16(report_mode);
status = ice_aq_send_cmd(hw, &desc, pcaps, pcaps_size, cd);
- ice_debug(hw, ICE_DBG_LINK, "get phy caps - report_mode = 0x%x\n",
- report_mode);
- ice_debug(hw, ICE_DBG_LINK, " phy_type_low = 0x%llx\n",
- (unsigned long long)LE64_TO_CPU(pcaps->phy_type_low));
- ice_debug(hw, ICE_DBG_LINK, " phy_type_high = 0x%llx\n",
- (unsigned long long)LE64_TO_CPU(pcaps->phy_type_high));
- ice_debug(hw, ICE_DBG_LINK, " caps = 0x%x\n", pcaps->caps);
- ice_debug(hw, ICE_DBG_LINK, " low_power_ctrl_an = 0x%x\n",
+ ice_debug(hw, ICE_DBG_LINK, "get phy caps dump\n");
+
+ if (report_mode == ICE_AQC_REPORT_TOPO_CAP_MEDIA)
+ prefix = "phy_caps_media";
+ else if (report_mode == ICE_AQC_REPORT_TOPO_CAP_NO_MEDIA)
+ prefix = "phy_caps_no_media";
+ else if (report_mode == ICE_AQC_REPORT_ACTIVE_CFG)
+ prefix = "phy_caps_active";
+ else if (report_mode == ICE_AQC_REPORT_DFLT_CFG)
+ prefix = "phy_caps_default";
+ else
+ prefix = "phy_caps_invalid";
+
+ ice_dump_phy_type_low(hw, LE64_TO_CPU(pcaps->phy_type_low), prefix);
+ ice_dump_phy_type_high(hw, LE64_TO_CPU(pcaps->phy_type_high), prefix);
+
+ ice_debug(hw, ICE_DBG_LINK, "%s: report_mode = 0x%x\n",
+ prefix, report_mode);
+ ice_debug(hw, ICE_DBG_LINK, "%s: caps = 0x%x\n", prefix, pcaps->caps);
+ ice_debug(hw, ICE_DBG_LINK, "%s: low_power_ctrl_an = 0x%x\n", prefix,
pcaps->low_power_ctrl_an);
- ice_debug(hw, ICE_DBG_LINK, " eee_cap = 0x%x\n", pcaps->eee_cap);
- ice_debug(hw, ICE_DBG_LINK, " eeer_value = 0x%x\n",
+ ice_debug(hw, ICE_DBG_LINK, "%s: eee_cap = 0x%x\n", prefix,
+ pcaps->eee_cap);
+ ice_debug(hw, ICE_DBG_LINK, "%s: eeer_value = 0x%x\n", prefix,
pcaps->eeer_value);
- ice_debug(hw, ICE_DBG_LINK, " link_fec_options = 0x%x\n",
+ ice_debug(hw, ICE_DBG_LINK, "%s: link_fec_options = 0x%x\n", prefix,
pcaps->link_fec_options);
- ice_debug(hw, ICE_DBG_LINK, " module_compliance_enforcement = 0x%x\n",
- pcaps->module_compliance_enforcement);
- ice_debug(hw, ICE_DBG_LINK, " extended_compliance_code = 0x%x\n",
- pcaps->extended_compliance_code);
- ice_debug(hw, ICE_DBG_LINK, " module_type[0] = 0x%x\n",
+ ice_debug(hw, ICE_DBG_LINK, "%s: module_compliance_enforcement = 0x%x\n",
+ prefix, pcaps->module_compliance_enforcement);
+ ice_debug(hw, ICE_DBG_LINK, "%s: extended_compliance_code = 0x%x\n",
+ prefix, pcaps->extended_compliance_code);
+ ice_debug(hw, ICE_DBG_LINK, "%s: module_type[0] = 0x%x\n", prefix,
pcaps->module_type[0]);
- ice_debug(hw, ICE_DBG_LINK, " module_type[1] = 0x%x\n",
+ ice_debug(hw, ICE_DBG_LINK, "%s: module_type[1] = 0x%x\n", prefix,
pcaps->module_type[1]);
- ice_debug(hw, ICE_DBG_LINK, " module_type[2] = 0x%x\n",
+ ice_debug(hw, ICE_DBG_LINK, "%s: module_type[2] = 0x%x\n", prefix,
pcaps->module_type[2]);
if (status == ICE_SUCCESS && report_mode == ICE_AQC_REPORT_TOPO_CAP_MEDIA) {
@@ -238,35 +407,76 @@ ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
}
/**
- * ice_aq_get_link_topo_handle - get link topology node return status
- * @pi: port information structure
- * @node_type: requested node type
- * @cd: pointer to command details structure or NULL
- *
- * Get link topology node return status for specified node type (0x06E0)
- *
- * Node type cage can be used to determine if cage is present. If AQC
- * returns error (ENOENT), then no cage present. If no cage present, then
- * connection type is backplane or BASE-T.
+ * ice_aq_get_netlist_node
+ * @hw: pointer to the hw struct
+ * @cmd: get_link_topo AQ structure
+ * @node_part_number: output node part number if node found
+ * @node_handle: output node handle parameter if node found
*/
-static enum ice_status
-ice_aq_get_link_topo_handle(struct ice_port_info *pi, u8 node_type,
- struct ice_sq_cd *cd)
+enum ice_status
+ice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd,
+ u8 *node_part_number, u16 *node_handle)
{
- struct ice_aqc_get_link_topo *cmd;
struct ice_aq_desc desc;
- cmd = &desc.params.get_link_topo;
-
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo);
+ desc.params.get_link_topo = *cmd;
- cmd->addr.node_type_ctx = (ICE_AQC_LINK_TOPO_NODE_CTX_PORT <<
- ICE_AQC_LINK_TOPO_NODE_CTX_S);
+ if (ice_aq_send_cmd(hw, &desc, NULL, 0, NULL))
+ return ICE_ERR_NOT_SUPPORTED;
- /* set node type */
- cmd->addr.node_type_ctx |= (ICE_AQC_LINK_TOPO_NODE_TYPE_M & node_type);
+ if (node_handle)
+ *node_handle =
+ LE16_TO_CPU(desc.params.get_link_topo.addr.handle);
+ if (node_part_number)
+ *node_part_number = desc.params.get_link_topo.node_part_num;
- return ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd);
+ return ICE_SUCCESS;
+}
+
+#define MAX_NETLIST_SIZE 10
+/**
+ * ice_find_netlist_node
+ * @hw: pointer to the hw struct
+ * @node_type_ctx: type of netlist node to look for
+ * @node_part_number: node part number to look for
+ * @node_handle: output parameter if node found - optional
+ *
+ * Find and return the node handle for a given node type and part number in the
+ * netlist. When found ICE_SUCCESS is returned, ICE_ERR_DOES_NOT_EXIST
+ * otherwise. If @node_handle provided, it would be set to found node handle.
+ */
+enum ice_status
+ice_find_netlist_node(struct ice_hw *hw, u8 node_type_ctx, u8 node_part_number,
+ u16 *node_handle)
+{
+ struct ice_aqc_get_link_topo cmd;
+ u8 rec_node_part_number;
+ enum ice_status status;
+ u16 rec_node_handle;
+ u8 idx;
+
+ for (idx = 0; idx < MAX_NETLIST_SIZE; idx++) {
+ memset(&cmd, 0, sizeof(cmd));
+
+ cmd.addr.topo_params.node_type_ctx =
+ (node_type_ctx << ICE_AQC_LINK_TOPO_NODE_TYPE_S);
+ cmd.addr.topo_params.index = idx;
+
+ status = ice_aq_get_netlist_node(hw, &cmd,
+ &rec_node_part_number,
+ &rec_node_handle);
+ if (status)
+ return status;
+
+ if (rec_node_part_number == node_part_number) {
+ if (node_handle)
+ *node_handle = rec_node_handle;
+ return ICE_SUCCESS;
+ }
+ }
+
+ return ICE_ERR_DOES_NOT_EXIST;
}
/**
@@ -278,13 +488,27 @@ ice_aq_get_link_topo_handle(struct ice_port_info *pi, u8 node_type,
*/
static bool ice_is_media_cage_present(struct ice_port_info *pi)
{
+ struct ice_aqc_get_link_topo *cmd;
+ struct ice_aq_desc desc;
+
+ cmd = &desc.params.get_link_topo;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo);
+
+ cmd->addr.topo_params.node_type_ctx =
+ (ICE_AQC_LINK_TOPO_NODE_CTX_PORT <<
+ ICE_AQC_LINK_TOPO_NODE_CTX_S);
+
+ /* set node type */
+ cmd->addr.topo_params.node_type_ctx |=
+ (ICE_AQC_LINK_TOPO_NODE_TYPE_M &
+ ICE_AQC_LINK_TOPO_NODE_TYPE_CAGE);
+
/* Node type cage can be used to determine if cage is present. If AQC
* returns error (ENOENT), then no cage present. If no cage present then
* connection type is backplane or BASE-T.
*/
- return !ice_aq_get_link_topo_handle(pi,
- ICE_AQC_LINK_TOPO_NODE_TYPE_CAGE,
- NULL);
+ return ice_aq_get_netlist_node(pi->hw, cmd, NULL, NULL);
}
/**
@@ -489,6 +713,7 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
(unsigned long long)li->phy_type_high);
ice_debug(hw, ICE_DBG_LINK, " media_type = 0x%x\n", *hw_media_type);
ice_debug(hw, ICE_DBG_LINK, " link_info = 0x%x\n", li->link_info);
+ ice_debug(hw, ICE_DBG_LINK, " link_cfg_err = 0x%x\n", li->link_cfg_err);
ice_debug(hw, ICE_DBG_LINK, " an_info = 0x%x\n", li->an_info);
ice_debug(hw, ICE_DBG_LINK, " ext_info = 0x%x\n", li->ext_info);
ice_debug(hw, ICE_DBG_LINK, " fec_info = 0x%x\n", li->fec_info);
@@ -526,7 +751,7 @@ ice_fill_tx_timer_and_fc_thresh(struct ice_hw *hw,
* LFC. Thus, we will use index =
* PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX.
*
- * Also, because we are opearating on transmit timer and fc
+ * Also, because we are operating on transmit timer and fc
* threshold of LFC, we don't turn on any bit in tx_tmr_priority
*/
#define IDX_OF_LFC PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX
@@ -548,12 +773,14 @@ ice_fill_tx_timer_and_fc_thresh(struct ice_hw *hw,
* ice_aq_set_mac_cfg
* @hw: pointer to the HW struct
* @max_frame_size: Maximum Frame Size to be supported
+ * @auto_drop: Tell HW to drop packets if TC queue is blocked
* @cd: pointer to command details structure or NULL
*
* Set MAC configuration (0x0603)
*/
enum ice_status
-ice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, struct ice_sq_cd *cd)
+ice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, bool auto_drop,
+ struct ice_sq_cd *cd)
{
struct ice_aqc_set_mac_cfg *cmd;
struct ice_aq_desc desc;
@@ -567,6 +794,8 @@ ice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, struct ice_sq_cd *cd)
cmd->max_frame_size = CPU_TO_LE16(max_frame_size);
+ if (ice_is_fw_auto_drop_supported(hw) && auto_drop)
+ cmd->drop_opts |= ICE_AQ_SET_MAC_AUTO_DROP_BLOCKING_PKTS;
ice_fill_tx_timer_and_fc_thresh(hw, cmd);
return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
@@ -667,7 +896,7 @@ ice_cleanup_fltr_mgmt_single(struct ice_hw *hw, struct ice_switch_info *sw)
}
/**
- * ice_cleanup_all_fltr_mgmt - cleanup filter management list and locks
+ * ice_cleanup_fltr_mgmt_struct - cleanup filter management list and locks
* @hw: pointer to the HW struct
*/
static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw)
@@ -724,6 +953,17 @@ void ice_print_rollback_msg(struct ice_hw *hw)
}
/**
+ * ice_set_umac_shared
+ * @hw: pointer to the hw struct
+ *
+ * Set boolean flag to allow unicast MAC sharing
+ */
+void ice_set_umac_shared(struct ice_hw *hw)
+{
+ hw->umac_shared = true;
+}
+
+/**
* ice_init_hw - main hardware initialization routine
* @hw: pointer to the hardware structure
*/
@@ -754,6 +994,25 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
if (status)
goto err_unroll_cqinit;
+ ice_fwlog_set_support_ena(hw);
+ status = ice_fwlog_set(hw, &hw->fwlog_cfg);
+ if (status) {
+ ice_debug(hw, ICE_DBG_INIT, "Failed to enable FW logging, status %d.\n",
+ status);
+ } else {
+ if (hw->fwlog_cfg.options & ICE_FWLOG_OPTION_REGISTER_ON_INIT) {
+ status = ice_fwlog_register(hw);
+ if (status)
+ ice_debug(hw, ICE_DBG_INIT, "Failed to register for FW logging events, status %d.\n",
+ status);
+ } else {
+ status = ice_fwlog_unregister(hw);
+ if (status)
+ ice_debug(hw, ICE_DBG_INIT, "Failed to unregister for FW logging events, status %d.\n",
+ status);
+ }
+ }
+
status = ice_init_nvm(hw);
if (status)
goto err_unroll_cqinit;
@@ -833,6 +1092,7 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
goto err_unroll_sched;
/* Get MAC information */
+
/* A single port can report up to two (LAN and WoL) addresses */
mac_buf = ice_calloc(hw, 2,
sizeof(struct ice_aqc_manage_mac_read_resp));
@@ -848,10 +1108,13 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
if (status)
goto err_unroll_fltr_mgmt_struct;
+
/* enable jumbo frame support at MAC level */
- status = ice_aq_set_mac_cfg(hw, ICE_AQ_SET_MAC_FRAME_SIZE_MAX, NULL);
+ status = ice_aq_set_mac_cfg(hw, ICE_AQ_SET_MAC_FRAME_SIZE_MAX, false,
+ NULL);
if (status)
goto err_unroll_fltr_mgmt_struct;
+
status = ice_init_hw_tbls(hw);
if (status)
goto err_unroll_fltr_mgmt_struct;
@@ -2132,12 +2395,64 @@ ice_parse_common_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,
caps->num_wol_proxy_fltr);
ice_debug(hw, ICE_DBG_INIT, "%s: wol_proxy_vsi_seid = %d\n", prefix,
caps->wol_proxy_vsi_seid);
+ ice_debug(hw, ICE_DBG_INIT, "%s: apm_wol_support = %d\n",
+ prefix, caps->apm_wol_support);
break;
case ICE_AQC_CAPS_MAX_MTU:
caps->max_mtu = number;
ice_debug(hw, ICE_DBG_INIT, "%s: max_mtu = %d\n",
prefix, caps->max_mtu);
break;
+ case ICE_AQC_CAPS_PCIE_RESET_AVOIDANCE:
+ caps->pcie_reset_avoidance = (number > 0);
+ ice_debug(hw, ICE_DBG_INIT,
+ "%s: pcie_reset_avoidance = %d\n", prefix,
+ caps->pcie_reset_avoidance);
+ break;
+ case ICE_AQC_CAPS_POST_UPDATE_RESET_RESTRICT:
+ caps->reset_restrict_support = (number == 1);
+ ice_debug(hw, ICE_DBG_INIT,
+ "%s: reset_restrict_support = %d\n", prefix,
+ caps->reset_restrict_support);
+ break;
+ case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG0:
+ case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG1:
+ case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG2:
+ case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG3:
+ {
+ u8 index = cap - ICE_AQC_CAPS_EXT_TOPO_DEV_IMG0;
+
+ caps->ext_topo_dev_img_ver_high[index] = number;
+ caps->ext_topo_dev_img_ver_low[index] = logical_id;
+ caps->ext_topo_dev_img_part_num[index] =
+ (phys_id & ICE_EXT_TOPO_DEV_IMG_PART_NUM_M) >>
+ ICE_EXT_TOPO_DEV_IMG_PART_NUM_S;
+ caps->ext_topo_dev_img_load_en[index] =
+ (phys_id & ICE_EXT_TOPO_DEV_IMG_LOAD_EN) != 0;
+ caps->ext_topo_dev_img_prog_en[index] =
+ (phys_id & ICE_EXT_TOPO_DEV_IMG_PROG_EN) != 0;
+ ice_debug(hw, ICE_DBG_INIT,
+ "%s: ext_topo_dev_img_ver_high[%d] = %d\n",
+ prefix, index,
+ caps->ext_topo_dev_img_ver_high[index]);
+ ice_debug(hw, ICE_DBG_INIT,
+ "%s: ext_topo_dev_img_ver_low[%d] = %d\n",
+ prefix, index,
+ caps->ext_topo_dev_img_ver_low[index]);
+ ice_debug(hw, ICE_DBG_INIT,
+ "%s: ext_topo_dev_img_part_num[%d] = %d\n",
+ prefix, index,
+ caps->ext_topo_dev_img_part_num[index]);
+ ice_debug(hw, ICE_DBG_INIT,
+ "%s: ext_topo_dev_img_load_en[%d] = %d\n",
+ prefix, index,
+ caps->ext_topo_dev_img_load_en[index]);
+ ice_debug(hw, ICE_DBG_INIT,
+ "%s: ext_topo_dev_img_prog_en[%d] = %d\n",
+ prefix, index,
+ caps->ext_topo_dev_img_prog_en[index]);
+ break;
+ }
default:
/* Not one of the recognized common capabilities */
found = false;
@@ -2282,6 +2597,7 @@ ice_parse_valid_functions_cap(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
dev_p->num_funcs = ice_hweight32(number);
ice_debug(hw, ICE_DBG_INIT, "dev caps: num_funcs = %d\n",
dev_p->num_funcs);
+
}
/**
@@ -2659,6 +2975,28 @@ ice_aq_set_port_params(struct ice_port_info *pi, u16 bad_frame_vsi,
}
/**
+ * ice_is_100m_speed_supported
+ * @hw: pointer to the HW struct
+ *
+ * returns true if 100M speeds are supported by the device,
+ * false otherwise.
+ */
+bool ice_is_100m_speed_supported(struct ice_hw *hw)
+{
+ switch (hw->device_id) {
+ case ICE_DEV_ID_E822C_10G_BASE_T:
+ case ICE_DEV_ID_E822C_SGMII:
+ case ICE_DEV_ID_E822L_10G_BASE_T:
+ case ICE_DEV_ID_E822L_SGMII:
+ case ICE_DEV_ID_E823L_10G_BASE_T:
+ case ICE_DEV_ID_E823L_1GBE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/**
* ice_get_link_speed_based_on_phy_type - returns link speed
* @phy_type_low: lower part of phy_type
* @phy_type_high: higher part of phy_type
@@ -3205,7 +3543,7 @@ ice_phy_caps_equals_cfg(struct ice_aqc_get_phy_caps_data *phy_caps,
/**
* ice_copy_phy_caps_to_cfg - Copy PHY ability data to configuration data
* @pi: port information structure
- * @caps: PHY ability structure to copy date from
+ * @caps: PHY ability structure to copy data from
* @cfg: PHY configuration structure to copy data to
*
* Helper function to copy AQC PHY get ability data to PHY set configuration
@@ -3501,6 +3839,76 @@ ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr,
}
/**
+ * ice_aq_prog_topo_dev_nvm
+ * @hw: pointer to the hardware structure
+ * @topo_params: pointer to structure storing topology parameters for a device
+ * @cd: pointer to command details structure or NULL
+ *
+ * Program Topology Device NVM (0x06F2)
+ *
+ */
+enum ice_status
+ice_aq_prog_topo_dev_nvm(struct ice_hw *hw,
+ struct ice_aqc_link_topo_params *topo_params,
+ struct ice_sq_cd *cd)
+{
+ struct ice_aqc_prog_topo_dev_nvm *cmd;
+ struct ice_aq_desc desc;
+
+ cmd = &desc.params.prog_topo_dev_nvm;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_prog_topo_dev_nvm);
+
+ ice_memcpy(&cmd->topo_params, topo_params, sizeof(*topo_params),
+ ICE_NONDMA_TO_NONDMA);
+
+ return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+}
+
+/**
+ * ice_aq_read_topo_dev_nvm
+ * @hw: pointer to the hardware structure
+ * @topo_params: pointer to structure storing topology parameters for a device
+ * @start_address: byte offset in the topology device NVM
+ * @data: pointer to data buffer
+ * @data_size: number of bytes to be read from the topology device NVM
+ * @cd: pointer to command details structure or NULL
+ * Read Topology Device NVM (0x06F3)
+ *
+ */
+enum ice_status
+ice_aq_read_topo_dev_nvm(struct ice_hw *hw,
+ struct ice_aqc_link_topo_params *topo_params,
+ u32 start_address, u8 *data, u8 data_size,
+ struct ice_sq_cd *cd)
+{
+ struct ice_aqc_read_topo_dev_nvm *cmd;
+ struct ice_aq_desc desc;
+ enum ice_status status;
+
+ if (!data || data_size == 0 ||
+ data_size > ICE_AQC_READ_TOPO_DEV_NVM_DATA_READ_SIZE)
+ return ICE_ERR_PARAM;
+
+ cmd = &desc.params.read_topo_dev_nvm;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_topo_dev_nvm);
+
+ desc.datalen = data_size;
+ ice_memcpy(&cmd->topo_params, topo_params, sizeof(*topo_params),
+ ICE_NONDMA_TO_NONDMA);
+ cmd->start_address = CPU_TO_LE32(start_address);
+
+ status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+ if (status)
+ return status;
+
+ ice_memcpy(data, cmd->data_read, data_size, ICE_NONDMA_TO_NONDMA);
+
+ return ICE_SUCCESS;
+}
+
+/**
* __ice_aq_get_set_rss_lut
* @hw: pointer to the hardware structure
* @params: RSS LUT parameters
@@ -4161,6 +4569,56 @@ ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx,
}
/**
+ * ice_aq_get_internal_data
+ * @hw: pointer to the hardware structure
+ * @cluster_id: specific cluster to dump
+ * @table_id: table ID within cluster
+ * @start: index of line in the block to read
+ * @buf: dump buffer
+ * @buf_size: dump buffer size
+ * @ret_buf_size: return buffer size (returned by FW)
+ * @ret_next_table: next block to read (returned by FW)
+ * @ret_next_index: next index to read (returned by FW)
+ * @cd: pointer to command details structure
+ *
+ * Get internal FW/HW data (0xFF08) for debug purposes.
+ */
+enum ice_status
+ice_aq_get_internal_data(struct ice_hw *hw, u8 cluster_id, u16 table_id,
+ u32 start, void *buf, u16 buf_size, u16 *ret_buf_size,
+ u16 *ret_next_table, u32 *ret_next_index,
+ struct ice_sq_cd *cd)
+{
+ struct ice_aqc_debug_dump_internals *cmd;
+ struct ice_aq_desc desc;
+ enum ice_status status;
+
+ cmd = &desc.params.debug_dump;
+
+ if (buf_size == 0 || !buf)
+ return ICE_ERR_PARAM;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_debug_dump_internals);
+
+ cmd->cluster_id = cluster_id;
+ cmd->table_id = CPU_TO_LE16(table_id);
+ cmd->idx = CPU_TO_LE32(start);
+
+ status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
+
+ if (!status) {
+ if (ret_buf_size)
+ *ret_buf_size = LE16_TO_CPU(desc.datalen);
+ if (ret_next_table)
+ *ret_next_table = LE16_TO_CPU(cmd->table_id);
+ if (ret_next_index)
+ *ret_next_index = LE32_TO_CPU(cmd->idx);
+ }
+
+ return status;
+}
+
+/**
* ice_read_byte - read context byte into struct
* @src_ctx: the context structure to read from
* @dest_ctx: the context to be written to
@@ -4662,7 +5120,7 @@ static bool ice_is_main_vsi(struct ice_hw *hw, u16 vsi_handle)
*
* Initializes required config data for VSI, FD, ACL, and RSS before replay.
*/
-static enum ice_status
+enum ice_status
ice_replay_pre_init(struct ice_hw *hw, struct ice_switch_info *sw)
{
enum ice_status status;
@@ -5021,7 +5479,6 @@ enum ice_fw_modes ice_get_fw_mode(struct ice_hw *hw)
/* check the current FW mode */
fw_mode = rd32(hw, GL_MNG_FWSM) & GL_MNG_FWSM_FW_MODES_M;
-
if (fw_mode & ICE_FW_MODE_DBG_M)
return ICE_FW_MODE_DBG;
else if (fw_mode & ICE_FW_MODE_REC_M)
@@ -5146,6 +5603,158 @@ exit:
}
/**
+ * ice_aq_read_i2c
+ * @hw: pointer to the hw struct
+ * @topo_addr: topology address for a device to communicate with
+ * @bus_addr: 7-bit I2C bus address
+ * @addr: I2C memory address (I2C offset) with up to 16 bits
+ * @params: I2C parameters: bit [7] - Repeated start, bits [6:5] data offset size,
+ * bit [4] - I2C address type, bits [3:0] - data size to read (0-16 bytes)
+ * @data: pointer to data (0 to 16 bytes) to be read from the I2C device
+ * @cd: pointer to command details structure or NULL
+ *
+ * Read I2C (0x06E2)
+ */
+enum ice_status
+ice_aq_read_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,
+ u16 bus_addr, __le16 addr, u8 params, u8 *data,
+ struct ice_sq_cd *cd)
+{
+ struct ice_aq_desc desc = { 0 };
+ struct ice_aqc_i2c *cmd;
+ enum ice_status status;
+ u8 data_size;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_i2c);
+ cmd = &desc.params.read_write_i2c;
+
+ if (!data)
+ return ICE_ERR_PARAM;
+
+ data_size = (params & ICE_AQC_I2C_DATA_SIZE_M) >> ICE_AQC_I2C_DATA_SIZE_S;
+
+ cmd->i2c_bus_addr = CPU_TO_LE16(bus_addr);
+ cmd->topo_addr = topo_addr;
+ cmd->i2c_params = params;
+ cmd->i2c_addr = addr;
+
+ status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+ if (!status) {
+ struct ice_aqc_read_i2c_resp *resp;
+ u8 i;
+
+ resp = &desc.params.read_i2c_resp;
+ for (i = 0; i < data_size; i++) {
+ *data = resp->i2c_data[i];
+ data++;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * ice_aq_write_i2c
+ * @hw: pointer to the hw struct
+ * @topo_addr: topology address for a device to communicate with
+ * @bus_addr: 7-bit I2C bus address
+ * @addr: I2C memory address (I2C offset) with up to 16 bits
+ * @params: I2C parameters: bit [4] - I2C address type, bits [3:0] - data size to write (0-7 bytes)
+ * @data: pointer to data (0 to 4 bytes) to be written to the I2C device
+ * @cd: pointer to command details structure or NULL
+ *
+ * Write I2C (0x06E3)
+ */
+enum ice_status
+ice_aq_write_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,
+ u16 bus_addr, __le16 addr, u8 params, u8 *data,
+ struct ice_sq_cd *cd)
+{
+ struct ice_aq_desc desc = { 0 };
+ struct ice_aqc_i2c *cmd;
+ u8 i, data_size;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_write_i2c);
+ cmd = &desc.params.read_write_i2c;
+
+ data_size = (params & ICE_AQC_I2C_DATA_SIZE_M) >> ICE_AQC_I2C_DATA_SIZE_S;
+
+ /* data_size limited to 4 */
+ if (data_size > 4)
+ return ICE_ERR_PARAM;
+
+ cmd->i2c_bus_addr = CPU_TO_LE16(bus_addr);
+ cmd->topo_addr = topo_addr;
+ cmd->i2c_params = params;
+ cmd->i2c_addr = addr;
+
+ for (i = 0; i < data_size; i++) {
+ cmd->i2c_data[i] = *data;
+ data++;
+ }
+
+ return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+}
+
+/**
+ * ice_aq_set_gpio
+ * @hw: pointer to the hw struct
+ * @gpio_ctrl_handle: GPIO controller node handle
+ * @pin_idx: IO Number of the GPIO that needs to be set
+ * @value: SW provide IO value to set in the LSB
+ * @cd: pointer to command details structure or NULL
+ *
+ * Sends 0x06EC AQ command to set the GPIO pin state that's part of the topology
+ */
+enum ice_status
+ice_aq_set_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx, bool value,
+ struct ice_sq_cd *cd)
+{
+ struct ice_aqc_gpio *cmd;
+ struct ice_aq_desc desc;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_gpio);
+ cmd = &desc.params.read_write_gpio;
+ cmd->gpio_ctrl_handle = gpio_ctrl_handle;
+ cmd->gpio_num = pin_idx;
+ cmd->gpio_val = value ? 1 : 0;
+
+ return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+}
+
+/**
+ * ice_aq_get_gpio
+ * @hw: pointer to the hw struct
+ * @gpio_ctrl_handle: GPIO controller node handle
+ * @pin_idx: IO Number of the GPIO that needs to be set
+ * @value: IO value read
+ * @cd: pointer to command details structure or NULL
+ *
+ * Sends 0x06ED AQ command to get the value of a GPIO signal which is part of
+ * the topology
+ */
+enum ice_status
+ice_aq_get_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx,
+ bool *value, struct ice_sq_cd *cd)
+{
+ struct ice_aqc_gpio *cmd;
+ struct ice_aq_desc desc;
+ enum ice_status status;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_gpio);
+ cmd = &desc.params.read_write_gpio;
+ cmd->gpio_ctrl_handle = gpio_ctrl_handle;
+ cmd->gpio_num = pin_idx;
+
+ status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+ if (status)
+ return status;
+
+ *value = !!cmd->gpio_val;
+ return ICE_SUCCESS;
+}
+
+/**
* ice_fw_supports_link_override
* @hw: pointer to the hardware structure
*
@@ -5423,7 +6032,7 @@ ice_aq_set_lldp_mib(struct ice_hw *hw, u8 mib_type, void *buf, u16 buf_size,
}
/**
- * ice_fw_supports_lldp_fltr - check NVM version supports lldp_fltr_ctrl
+ * ice_fw_supports_lldp_fltr_ctrl - check NVM version supports lldp_fltr_ctrl
* @hw: pointer to HW struct
*/
bool ice_fw_supports_lldp_fltr_ctrl(struct ice_hw *hw)
@@ -5488,3 +6097,17 @@ bool ice_fw_supports_report_dflt_cfg(struct ice_hw *hw)
}
return false;
}
+
+/**
+ * ice_is_fw_auto_drop_supported
+ * @hw: pointer to the hardware structure
+ *
+ * Checks if the firmware supports auto drop feature
+ */
+bool ice_is_fw_auto_drop_supported(struct ice_hw *hw)
+{
+ if (hw->api_maj_ver >= ICE_FW_API_AUTO_DROP_MAJ &&
+ hw->api_min_ver >= ICE_FW_API_AUTO_DROP_MIN)
+ return true;
+ return false;
+}
diff --git a/sys/dev/ice/ice_common.h b/sys/dev/ice/ice_common.h
index 3f5cb9c7e901..48fd52cb2484 100644
--- a/sys/dev/ice/ice_common.h
+++ b/sys/dev/ice/ice_common.h
@@ -52,6 +52,7 @@ enum ice_fw_modes {
void ice_idle_aq(struct ice_hw *hw, struct ice_ctl_q_info *cq);
bool ice_sq_done(struct ice_hw *hw, struct ice_ctl_q_info *cq);
+void ice_set_umac_shared(struct ice_hw *hw);
enum ice_status ice_init_hw(struct ice_hw *hw);
void ice_deinit_hw(struct ice_hw *hw);
enum ice_status ice_check_reset(struct ice_hw *hw);
@@ -89,6 +90,12 @@ enum ice_status ice_get_caps(struct ice_hw *hw);
void ice_set_safe_mode_caps(struct ice_hw *hw);
+enum ice_status
+ice_aq_get_internal_data(struct ice_hw *hw, u8 cluster_id, u16 table_id,
+ u32 start, void *buf, u16 buf_size, u16 *ret_buf_size,
+ u16 *ret_next_table, u32 *ret_next_index,
+ struct ice_sq_cd *cd);
+
enum ice_status ice_set_mac_type(struct ice_hw *hw);
/* Define a macro that will align a pointer to point to the next memory address
@@ -164,6 +171,12 @@ enum ice_status
ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
struct ice_aqc_get_phy_caps_data *caps,
struct ice_sq_cd *cd);
+enum ice_status
+ice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd,
+ u8 *node_part_number, u16 *node_handle);
+enum ice_status
+ice_find_netlist_node(struct ice_hw *hw, u8 node_type_ctx, u8 node_part_number,
+ u16 *node_handle);
void
ice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high,
u16 link_speeds_bitmap);
@@ -203,7 +216,8 @@ enum ice_status
ice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link,
struct ice_sq_cd *cd);
enum ice_status
-ice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, struct ice_sq_cd *cd);
+ice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, bool auto_drop,
+ struct ice_sq_cd *cd);
enum ice_status
ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
struct ice_link_status *link, struct ice_sq_cd *cd);
@@ -222,6 +236,16 @@ ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr,
bool write, struct ice_sq_cd *cd);
enum ice_status
+ice_aq_prog_topo_dev_nvm(struct ice_hw *hw,
+ struct ice_aqc_link_topo_params *topo_params,
+ struct ice_sq_cd *cd);
+enum ice_status
+ice_aq_read_topo_dev_nvm(struct ice_hw *hw,
+ struct ice_aqc_link_topo_params *topo_params,
+ u32 start_address, u8 *buf, u8 buf_size,
+ struct ice_sq_cd *cd);
+
+enum ice_status
ice_aq_get_port_options(struct ice_hw *hw,
struct ice_aqc_get_port_options_elem *options,
u8 *option_count, u8 lport, bool lport_valid,
@@ -244,6 +268,8 @@ enum ice_status
ice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u16 q_handle,
u8 num_qgrps, struct ice_aqc_add_tx_qgrp *buf, u16 buf_size,
struct ice_sq_cd *cd);
+enum ice_status
+ice_replay_pre_init(struct ice_hw *hw, struct ice_switch_info *sw);
enum ice_status ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle);
void ice_replay_post(struct ice_hw *hw);
struct ice_q_ctx *
@@ -259,6 +285,8 @@ ice_stat_update_repc(struct ice_hw *hw, u16 vsi_handle, bool prev_stat_loaded,
struct ice_eth_stats *cur_stats);
enum ice_fw_modes ice_get_fw_mode(struct ice_hw *hw);
void ice_print_rollback_msg(struct ice_hw *hw);
+bool ice_is_e810(struct ice_hw *hw);
+bool ice_is_e810t(struct ice_hw *hw);
enum ice_status
ice_aq_alternate_write(struct ice_hw *hw, u32 reg_addr0, u32 reg_val0,
u32 reg_addr1, u32 reg_val1);
@@ -276,6 +304,13 @@ enum ice_status
ice_get_cur_lldp_persist_status(struct ice_hw *hw, u32 *lldp_status);
enum ice_status
ice_get_dflt_lldp_persist_status(struct ice_hw *hw, u32 *lldp_status);
+enum ice_status
+ice_aq_set_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx, bool value,
+ struct ice_sq_cd *cd);
+enum ice_status
+ice_aq_get_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx,
+ bool *value, struct ice_sq_cd *cd);
+bool ice_is_100m_speed_supported(struct ice_hw *hw);
enum ice_status ice_get_netlist_ver_info(struct ice_hw *hw, struct ice_netlist_info *netlist);
enum ice_status
ice_aq_set_lldp_mib(struct ice_hw *hw, u8 mib_type, void *buf, u16 buf_size,
@@ -284,8 +319,18 @@ bool ice_fw_supports_lldp_fltr_ctrl(struct ice_hw *hw);
enum ice_status
ice_lldp_fltr_add_remove(struct ice_hw *hw, u16 vsi_num, bool add);
enum ice_status
+ice_aq_read_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,
+ u16 bus_addr, __le16 addr, u8 params, u8 *data,
+ struct ice_sq_cd *cd);
+enum ice_status
+ice_aq_write_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,
+ u16 bus_addr, __le16 addr, u8 params, u8 *data,
+ struct ice_sq_cd *cd);
+enum ice_status
ice_aq_set_health_status_config(struct ice_hw *hw, u8 event_source,
struct ice_sq_cd *cd);
bool ice_is_fw_health_report_supported(struct ice_hw *hw);
bool ice_fw_supports_report_dflt_cfg(struct ice_hw *hw);
+/* AQ API version for FW auto drop reports */
+bool ice_is_fw_auto_drop_supported(struct ice_hw *hw);
#endif /* _ICE_COMMON_H_ */
diff --git a/sys/dev/ice/ice_dcb.c b/sys/dev/ice/ice_dcb.c
index abe0237eb88f..137ffad92935 100644
--- a/sys/dev/ice/ice_dcb.c
+++ b/sys/dev/ice/ice_dcb.c
@@ -932,36 +932,41 @@ ice_aq_query_pfc_mode(struct ice_hw *hw, u8 *pfcmode_ret, struct ice_sq_cd *cd)
/**
* ice_aq_set_pfc_mode - Set PFC mode
* @hw: pointer to the HW struct
- * @pfcmode_set: set-value of PFC mode
- * @pfcmode_ret: return value of PFC mode, written by FW
+ * @pfc_mode: value of PFC mode to set
* @cd: pointer to command details structure or NULL
*
* This AQ call configures the PFC mdoe to DSCP-based PFC mode or VLAN
* -based PFC (0x0303)
*/
enum ice_status
-ice_aq_set_pfc_mode(struct ice_hw *hw, u8 pfcmode_set, u8 *pfcmode_ret,
- struct ice_sq_cd *cd)
+ice_aq_set_pfc_mode(struct ice_hw *hw, u8 pfc_mode, struct ice_sq_cd *cd)
{
struct ice_aqc_set_query_pfc_mode *cmd;
struct ice_aq_desc desc;
enum ice_status status;
- if (pfcmode_set > ICE_AQC_PFC_DSCP_BASED_PFC)
+ if (pfc_mode > ICE_AQC_PFC_DSCP_BASED_PFC)
return ICE_ERR_PARAM;
cmd = &desc.params.set_query_pfc_mode;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_pfc_mode);
- cmd->pfc_mode = pfcmode_set;
+ cmd->pfc_mode = pfc_mode;
status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+ if (status)
+ return status;
- if (!status)
- *pfcmode_ret = cmd->pfc_mode;
+ /* FW will write the PFC mode set back into cmd->pfc_mode, but if DCB is
+ * disabled, FW will write back 0 to cmd->pfc_mode. After the AQ has
+ * been executed, check if cmd->pfc_mode is what was requested. If not,
+ * return an error.
+ */
+ if (cmd->pfc_mode != pfc_mode)
+ return ICE_ERR_NOT_SUPPORTED;
- return status;
+ return ICE_SUCCESS;
}
/**
@@ -1113,7 +1118,7 @@ ice_cee_to_dcb_cfg(struct ice_aqc_get_cee_dcb_cfg_resp *cee_cfg,
}
/**
- * ice_get_ieee_dcb_cfg
+ * ice_get_ieee_or_cee_dcb_cfg
* @pi: port information structure
* @dcbx_mode: mode of DCBX (IEEE or CEE)
*
@@ -1463,7 +1468,140 @@ ice_add_ieee_app_pri_tlv(struct ice_lldp_org_tlv *tlv,
}
/**
- * ice_add_dcb_tlv - Add all IEEE TLVs
+ * ice_add_dscp_up_tlv - Prepare DSCP to UP TLV
+ * @tlv: location to build the TLV data
+ * @dcbcfg: location of data to convert to TLV
+ */
+static void
+ice_add_dscp_up_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
+{
+ u8 *buf = tlv->tlvinfo;
+ u32 ouisubtype;
+ u16 typelen;
+ int i;
+
+ typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
+ ICE_DSCP_UP_TLV_LEN);
+ tlv->typelen = HTONS(typelen);
+
+ ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
+ ICE_DSCP_SUBTYPE_DSCP2UP);
+ tlv->ouisubtype = HTONL(ouisubtype);
+
+ /* bytes 0 - 63 - IPv4 DSCP2UP LUT */
+ for (i = 0; i < ICE_DSCP_NUM_VAL; i++) {
+ /* IPv4 mapping */
+ buf[i] = dcbcfg->dscp_map[i];
+ /* IPv6 mapping */
+ buf[i + ICE_DSCP_IPV6_OFFSET] = dcbcfg->dscp_map[i];
+ }
+
+ /* byte 64 - IPv4 untagged traffic */
+ buf[i] = 0;
+
+ /* byte 144 - IPv6 untagged traffic */
+ buf[i + ICE_DSCP_IPV6_OFFSET] = 0;
+}
+
+#define ICE_BYTES_PER_TC 8
+/**
+ * ice_add_dscp_enf_tlv - Prepare DSCP Enforcement TLV
+ * @tlv: location to build the TLV data
+ */
+static void
+ice_add_dscp_enf_tlv(struct ice_lldp_org_tlv *tlv)
+{
+ u8 *buf = tlv->tlvinfo;
+ u32 ouisubtype;
+ u16 typelen;
+
+ typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
+ ICE_DSCP_ENF_TLV_LEN);
+ tlv->typelen = HTONS(typelen);
+
+ ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
+ ICE_DSCP_SUBTYPE_ENFORCE);
+ tlv->ouisubtype = HTONL(ouisubtype);
+
+ /* Allow all DSCP values to be valid for all TC's (IPv4 and IPv6) */
+ memset(buf, 0, 2 * (ICE_MAX_TRAFFIC_CLASS * ICE_BYTES_PER_TC));
+}
+
+/**
+ * ice_add_dscp_tc_bw_tlv - Prepare DSCP BW for TC TLV
+ * @tlv: location to build the TLV data
+ * @dcbcfg: location of the data to convert to TLV
+ */
+static void
+ice_add_dscp_tc_bw_tlv(struct ice_lldp_org_tlv *tlv,
+ struct ice_dcbx_cfg *dcbcfg)
+{
+ struct ice_dcb_ets_cfg *etscfg;
+ u8 *buf = tlv->tlvinfo;
+ u32 ouisubtype;
+ u8 offset = 0;
+ u16 typelen;
+ int i;
+
+ typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
+ ICE_DSCP_TC_BW_TLV_LEN);
+ tlv->typelen = HTONS(typelen);
+
+ ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
+ ICE_DSCP_SUBTYPE_TCBW);
+ tlv->ouisubtype = HTONL(ouisubtype);
+
+ /* First Octect after subtype
+ * ----------------------------
+ * | RSV | CBS | RSV | Max TCs |
+ * | 1b | 1b | 3b | 3b |
+ * ----------------------------
+ */
+ etscfg = &dcbcfg->etscfg;
+ buf[0] = etscfg->maxtcs & ICE_IEEE_ETS_MAXTC_M;
+
+ /* bytes 1 - 4 reserved */
+ offset = 5;
+
+ /* TC BW table
+ * bytes 0 - 7 for TC 0 - 7
+ *
+ * TSA Assignment table
+ * bytes 8 - 15 for TC 0 - 7
+ */
+ for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
+ buf[offset] = etscfg->tcbwtable[i];
+ buf[offset + ICE_MAX_TRAFFIC_CLASS] = etscfg->tsatable[i];
+ offset++;
+ }
+}
+
+/**
+ * ice_add_dscp_pfc_tlv - Prepare DSCP PFC TLV
+ * @tlv: Fill PFC TLV in IEEE format
+ * @dcbcfg: Local store which holds the PFC CFG data
+ */
+static void
+ice_add_dscp_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
+{
+ u8 *buf = tlv->tlvinfo;
+ u32 ouisubtype;
+ u16 typelen;
+
+ typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
+ ICE_DSCP_PFC_TLV_LEN);
+ tlv->typelen = HTONS(typelen);
+
+ ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
+ ICE_DSCP_SUBTYPE_PFC);
+ tlv->ouisubtype = HTONL(ouisubtype);
+
+ buf[0] = dcbcfg->pfc.pfccap & 0xF;
+ buf[1] = dcbcfg->pfc.pfcena & 0xF;
+}
+
+/**
+ * ice_add_dcb_tlv - Add all IEEE or DSCP TLVs
* @tlv: Fill TLV data in IEEE format
* @dcbcfg: Local store which holds the DCB Config
* @tlvid: Type of IEEE TLV
@@ -1474,21 +1612,41 @@ static void
ice_add_dcb_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg,
u16 tlvid)
{
- switch (tlvid) {
- case ICE_IEEE_TLV_ID_ETS_CFG:
- ice_add_ieee_ets_tlv(tlv, dcbcfg);
- break;
- case ICE_IEEE_TLV_ID_ETS_REC:
- ice_add_ieee_etsrec_tlv(tlv, dcbcfg);
- break;
- case ICE_IEEE_TLV_ID_PFC_CFG:
- ice_add_ieee_pfc_tlv(tlv, dcbcfg);
- break;
- case ICE_IEEE_TLV_ID_APP_PRI:
- ice_add_ieee_app_pri_tlv(tlv, dcbcfg);
- break;
- default:
- break;
+ if (dcbcfg->pfc_mode == ICE_QOS_MODE_VLAN) {
+ switch (tlvid) {
+ case ICE_IEEE_TLV_ID_ETS_CFG:
+ ice_add_ieee_ets_tlv(tlv, dcbcfg);
+ break;
+ case ICE_IEEE_TLV_ID_ETS_REC:
+ ice_add_ieee_etsrec_tlv(tlv, dcbcfg);
+ break;
+ case ICE_IEEE_TLV_ID_PFC_CFG:
+ ice_add_ieee_pfc_tlv(tlv, dcbcfg);
+ break;
+ case ICE_IEEE_TLV_ID_APP_PRI:
+ ice_add_ieee_app_pri_tlv(tlv, dcbcfg);
+ break;
+ default:
+ break;
+ }
+ } else {
+ /* pfc_mode == ICE_QOS_MODE_DSCP */
+ switch (tlvid) {
+ case ICE_TLV_ID_DSCP_UP:
+ ice_add_dscp_up_tlv(tlv, dcbcfg);
+ break;
+ case ICE_TLV_ID_DSCP_ENF:
+ ice_add_dscp_enf_tlv(tlv);
+ break;
+ case ICE_TLV_ID_DSCP_TC_BW:
+ ice_add_dscp_tc_bw_tlv(tlv, dcbcfg);
+ break;
+ case ICE_TLV_ID_DSCP_TO_PFC:
+ ice_add_dscp_pfc_tlv(tlv, dcbcfg);
+ break;
+ default:
+ break;
+ }
}
}
@@ -1582,7 +1740,7 @@ ice_aq_query_port_ets(struct ice_port_info *pi,
struct ice_aq_desc desc;
enum ice_status status;
- if (!pi)
+ if (!pi || !pi->root)
return ICE_ERR_PARAM;
cmd = &desc.params.port_ets;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_query_port_ets);
diff --git a/sys/dev/ice/ice_dcb.h b/sys/dev/ice/ice_dcb.h
index 85d6b399cf11..6d624268bb74 100644
--- a/sys/dev/ice/ice_dcb.h
+++ b/sys/dev/ice/ice_dcb.h
@@ -57,6 +57,13 @@
#define ICE_CEE_DCBX_OUI 0x001B21
#define ICE_CEE_DCBX_TYPE 2
+#define ICE_DSCP_OUI 0xFFFFFF
+#define ICE_DSCP_SUBTYPE_DSCP2UP 0x41
+#define ICE_DSCP_SUBTYPE_ENFORCE 0x42
+#define ICE_DSCP_SUBTYPE_TCBW 0x43
+#define ICE_DSCP_SUBTYPE_PFC 0x44
+#define ICE_DSCP_IPV6_OFFSET 80
+
#define ICE_CEE_SUBTYPE_CTRL 1
#define ICE_CEE_SUBTYPE_PG_CFG 2
#define ICE_CEE_SUBTYPE_PFC_CFG 3
@@ -125,11 +132,20 @@
#define ICE_IEEE_TLV_ID_APP_PRI 6
#define ICE_TLV_ID_END_OF_LLDPPDU 7
#define ICE_TLV_ID_START ICE_IEEE_TLV_ID_ETS_CFG
+#define ICE_TLV_ID_DSCP_UP 3
+#define ICE_TLV_ID_DSCP_ENF 4
+#define ICE_TLV_ID_DSCP_TC_BW 5
+#define ICE_TLV_ID_DSCP_TO_PFC 6
#define ICE_IEEE_ETS_TLV_LEN 25
#define ICE_IEEE_PFC_TLV_LEN 6
#define ICE_IEEE_APP_TLV_LEN 11
+#define ICE_DSCP_UP_TLV_LEN 148
+#define ICE_DSCP_ENF_TLV_LEN 132
+#define ICE_DSCP_TC_BW_TLV_LEN 25
+#define ICE_DSCP_PFC_TLV_LEN 6
+
#pragma pack(1)
/* IEEE 802.1AB LLDP Organization specific TLV */
struct ice_lldp_org_tlv {
@@ -222,11 +238,10 @@ ice_aq_get_cee_dcb_cfg(struct ice_hw *hw,
enum ice_status
ice_aq_query_pfc_mode(struct ice_hw *hw, u8 *pfcmode_ret, struct ice_sq_cd *cd);
enum ice_status
-ice_aq_set_pfc_mode(struct ice_hw *hw, u8 pfcmode_set, u8 *pfcmode_ret,
- struct ice_sq_cd *cd);
-enum ice_status
ice_aq_set_dcb_parameters(struct ice_hw *hw, bool dcb_enable,
struct ice_sq_cd *cd);
+enum ice_status
+ice_aq_set_pfc_mode(struct ice_hw *hw, u8 pfc_mode, struct ice_sq_cd *cd);
enum ice_status ice_lldp_to_dcb_cfg(u8 *lldpmib, struct ice_dcbx_cfg *dcbcfg);
u8 ice_get_dcbx_status(struct ice_hw *hw);
enum ice_status
diff --git a/sys/dev/ice/ice_devids.h b/sys/dev/ice/ice_devids.h
index 8611fc170816..2d092c6037c4 100644
--- a/sys/dev/ice/ice_devids.h
+++ b/sys/dev/ice/ice_devids.h
@@ -50,12 +50,24 @@
#define ICE_DEV_ID_E810C_QSFP 0x1592
/* Intel(R) Ethernet Controller E810-C for SFP */
#define ICE_DEV_ID_E810C_SFP 0x1593
+#define ICE_SUBDEV_ID_E810T 0x000E
+#define ICE_SUBDEV_ID_E810T2 0x000F
/* Intel(R) Ethernet Controller E810-XXV for backplane */
#define ICE_DEV_ID_E810_XXV_BACKPLANE 0x1599
/* Intel(R) Ethernet Controller E810-XXV for QSFP */
#define ICE_DEV_ID_E810_XXV_QSFP 0x159A
/* Intel(R) Ethernet Controller E810-XXV for SFP */
#define ICE_DEV_ID_E810_XXV_SFP 0x159B
+/* Intel(R) Ethernet Connection E823-C for backplane */
+#define ICE_DEV_ID_E823C_BACKPLANE 0x188A
+/* Intel(R) Ethernet Connection E823-C for QSFP */
+#define ICE_DEV_ID_E823C_QSFP 0x188B
+/* Intel(R) Ethernet Connection E823-C for SFP */
+#define ICE_DEV_ID_E823C_SFP 0x188C
+/* Intel(R) Ethernet Connection E823-C/X557-AT 10GBASE-T */
+#define ICE_DEV_ID_E823C_10G_BASE_T 0x188D
+/* Intel(R) Ethernet Connection E823-C 1GbE */
+#define ICE_DEV_ID_E823C_SGMII 0x188E
/* Intel(R) Ethernet Connection E822-C for backplane */
#define ICE_DEV_ID_E822C_BACKPLANE 0x1890
/* Intel(R) Ethernet Connection E822-C for QSFP */
diff --git a/sys/dev/ice/ice_drv_info.h b/sys/dev/ice/ice_drv_info.h
index b344c010a35f..19d633554463 100644
--- a/sys/dev/ice/ice_drv_info.h
+++ b/sys/dev/ice/ice_drv_info.h
@@ -63,16 +63,16 @@
* @var ice_rc_version
* @brief driver release candidate version number
*/
-const char ice_driver_version[] = "0.29.4-k";
-const uint8_t ice_major_version = 0;
-const uint8_t ice_minor_version = 29;
-const uint8_t ice_patch_version = 4;
+const char ice_driver_version[] = "1.34.2-k";
+const uint8_t ice_major_version = 1;
+const uint8_t ice_minor_version = 34;
+const uint8_t ice_patch_version = 2;
const uint8_t ice_rc_version = 0;
#define PVIDV(vendor, devid, name) \
- PVID(vendor, devid, name " - 0.29.4-k")
+ PVID(vendor, devid, name " - 1.34.2-k")
#define PVIDV_OEM(vendor, devid, svid, sdevid, revid, name) \
- PVID_OEM(vendor, devid, svid, sdevid, revid, name " - 0.29.4-k")
+ PVID_OEM(vendor, devid, svid, sdevid, revid, name " - 1.34.2-k")
/**
* @var ice_vendor_info_array
@@ -134,9 +134,6 @@ static pci_vendor_info_t ice_vendor_info_array[] = {
ICE_INTEL_VENDOR_ID, 0x0008, 0,
"Intel(R) Ethernet Network Adapter E810-XXV-2"),
PVIDV_OEM(ICE_INTEL_VENDOR_ID, ICE_DEV_ID_E810C_SFP,
- ICE_INTEL_VENDOR_ID, 0x0009, 0,
- "Intel(R) Ethernet Network Adapter E810-XXV-2 for OCP 2.0"),
- PVIDV_OEM(ICE_INTEL_VENDOR_ID, ICE_DEV_ID_E810C_SFP,
ICE_INTEL_VENDOR_ID, 0x000C, 0,
"Intel(R) Ethernet Network Adapter E810-XXV-4 for OCP 3.0"),
PVIDV(ICE_INTEL_VENDOR_ID, ICE_DEV_ID_E810C_SFP,
@@ -169,6 +166,16 @@ static pci_vendor_info_t ice_vendor_info_array[] = {
"Intel(R) Ethernet Connection E823-L/X557-AT 10GBASE-T"),
PVIDV(ICE_INTEL_VENDOR_ID, ICE_DEV_ID_E823L_1GBE,
"Intel(R) Ethernet Connection E823-L 1GbE"),
+ PVIDV(ICE_INTEL_VENDOR_ID, ICE_DEV_ID_E823C_BACKPLANE,
+ "Intel(R) Ethernet Connection E823-C for backplane"),
+ PVIDV(ICE_INTEL_VENDOR_ID, ICE_DEV_ID_E823C_QSFP,
+ "Intel(R) Ethernet Connection E823-C for QSFP"),
+ PVIDV(ICE_INTEL_VENDOR_ID, ICE_DEV_ID_E823C_SFP,
+ "Intel(R) Ethernet Connection E823-C for SFP"),
+ PVIDV(ICE_INTEL_VENDOR_ID, ICE_DEV_ID_E823C_10G_BASE_T,
+ "Intel(R) Ethernet Connection E823-C/X557-AT 10GBASE-T"),
+ PVIDV(ICE_INTEL_VENDOR_ID, ICE_DEV_ID_E823C_SGMII,
+ "Intel(R) Ethernet Connection E823-C 1GbE"),
PVIDV(ICE_INTEL_VENDOR_ID, ICE_DEV_ID_E810_XXV_BACKPLANE,
"Intel(R) Ethernet Controller E810-XXV for backplane"),
PVIDV(ICE_INTEL_VENDOR_ID, ICE_DEV_ID_E810_XXV_QSFP,
diff --git a/sys/dev/ice/ice_features.h b/sys/dev/ice/ice_features.h
index 93f57b23170d..51c60b0dfeea 100644
--- a/sys/dev/ice/ice_features.h
+++ b/sys/dev/ice/ice_features.h
@@ -66,6 +66,8 @@ enum feat_list {
ICE_FEATURE_LINK_MGMT_VER_1,
ICE_FEATURE_LINK_MGMT_VER_2,
ICE_FEATURE_HEALTH_STATUS,
+ ICE_FEATURE_FW_LOGGING,
+ ICE_FEATURE_HAS_PBA,
/* Must be last entry */
ICE_FEATURE_COUNT
};
diff --git a/sys/dev/ice/ice_flex_pipe.c b/sys/dev/ice/ice_flex_pipe.c
index 0d0dc3c8c80d..0c956f720a92 100644
--- a/sys/dev/ice/ice_flex_pipe.c
+++ b/sys/dev/ice/ice_flex_pipe.c
@@ -365,7 +365,6 @@ ice_boost_tcam_handler(u32 sect_type, void *section, u32 index, u32 *offset)
if (sect_type != ICE_SID_RXPARSER_BOOST_TCAM)
return NULL;
- /* cppcheck-suppress nullPointer */
if (index > ICE_MAX_BST_TCAMS_IN_BUF)
return NULL;
@@ -437,7 +436,6 @@ ice_label_enum_handler(u32 __ALWAYS_UNUSED sect_type, void *section, u32 index,
if (!section)
return NULL;
- /* cppcheck-suppress nullPointer */
if (index > ICE_MAX_LABELS_IN_BUF)
return NULL;
@@ -1160,7 +1158,7 @@ ice_download_pkg(struct ice_hw *hw, struct ice_seg *ice_seg)
status = ice_dwnld_cfg_bufs(hw, ice_buf_tbl->buf_array,
LE32_TO_CPU(ice_buf_tbl->buf_count));
- ice_cache_vlan_mode(hw);
+ ice_post_pkg_dwnld_vlan_mode_cfg(hw);
return status;
}
@@ -1181,8 +1179,13 @@ ice_init_pkg_info(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr)
if (!pkg_hdr)
return ICE_ERR_PARAM;
+ hw->pkg_seg_id = SEGMENT_TYPE_ICE_E810;
+
+ ice_debug(hw, ICE_DBG_INIT, "Pkg using segment id: 0x%08X\n",
+ hw->pkg_seg_id);
+
seg_hdr = (struct ice_generic_seg_hdr *)
- ice_find_seg_in_pkg(hw, SEGMENT_TYPE_ICE, pkg_hdr);
+ ice_find_seg_in_pkg(hw, hw->pkg_seg_id, pkg_hdr);
if (seg_hdr) {
struct ice_meta_sect *meta;
struct ice_pkg_enum state;
@@ -1449,7 +1452,7 @@ ice_chk_pkg_compat(struct ice_hw *hw, struct ice_pkg_hdr *ospkg,
}
/* find ICE segment in given package */
- *seg = (struct ice_seg *)ice_find_seg_in_pkg(hw, SEGMENT_TYPE_ICE,
+ *seg = (struct ice_seg *)ice_find_seg_in_pkg(hw, hw->pkg_seg_id,
ospkg);
if (!*seg) {
ice_debug(hw, ICE_DBG_INIT, "no ice segment in package.\n");
@@ -2811,7 +2814,6 @@ ice_match_prop_lst(struct LIST_HEAD_TYPE *list1, struct LIST_HEAD_TYPE *list2)
count++;
LIST_FOR_EACH_ENTRY(tmp2, list2, ice_vsig_prof, list)
chk_count++;
- /* cppcheck-suppress knownConditionTrueFalse */
if (!count || count != chk_count)
return false;
diff --git a/sys/dev/ice/ice_flex_type.h b/sys/dev/ice/ice_flex_type.h
index 31a7135f7e22..bd3b6ddeaf7b 100644
--- a/sys/dev/ice/ice_flex_type.h
+++ b/sys/dev/ice/ice_flex_type.h
@@ -61,7 +61,7 @@ struct ice_pkg_hdr {
/* generic segment */
struct ice_generic_seg_hdr {
#define SEGMENT_TYPE_METADATA 0x00000001
-#define SEGMENT_TYPE_ICE 0x00000010
+#define SEGMENT_TYPE_ICE_E810 0x00000010
__le32 seg_type;
struct ice_pkg_ver seg_format_ver;
__le32 seg_size;
@@ -226,6 +226,8 @@ struct ice_buf_hdr {
#define ICE_SID_CDID_KEY_BUILDER_PE 87
#define ICE_SID_CDID_REDIR_PE 88
+#define ICE_SID_RXPARSER_FLAG_REDIR 97
+
/* Label Metadata section IDs */
#define ICE_SID_LBL_FIRST 0x80000010
#define ICE_SID_LBL_RXPARSER_IMEM 0x80000010
diff --git a/sys/dev/ice/ice_flow.c b/sys/dev/ice/ice_flow.c
index 7d792e749e3d..387882bfe903 100644
--- a/sys/dev/ice/ice_flow.c
+++ b/sys/dev/ice/ice_flow.c
@@ -159,11 +159,11 @@ static const u32 ice_ptypes_macvlan_il[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
-/* Packet types for packets with an Outer/First/Single IPv4 header, does NOT
- * include IPV4 other PTYPEs
+/* Packet types for packets with an Outer/First/Single non-frag IPv4 header,
+ * does NOT include IPV4 other PTYPEs
*/
static const u32 ice_ptypes_ipv4_ofos[] = {
- 0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
+ 0x1D800000, 0x04000800, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -173,11 +173,11 @@ static const u32 ice_ptypes_ipv4_ofos[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
-/* Packet types for packets with an Outer/First/Single IPv4 header, includes
- * IPV4 other PTYPEs
+/* Packet types for packets with an Outer/First/Single non-frag IPv4 header,
+ * includes IPV4 other PTYPEs
*/
static const u32 ice_ptypes_ipv4_ofos_all[] = {
- 0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
+ 0x1D800000, 0x04000800, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -199,11 +199,11 @@ static const u32 ice_ptypes_ipv4_il[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
-/* Packet types for packets with an Outer/First/Single IPv6 header, does NOT
- * include IVP6 other PTYPEs
+/* Packet types for packets with an Outer/First/Single non-frag IPv6 header,
+ * does NOT include IVP6 other PTYPEs
*/
static const u32 ice_ptypes_ipv6_ofos[] = {
- 0x00000000, 0x00000000, 0x77000000, 0x10002000,
+ 0x00000000, 0x00000000, 0x76000000, 0x10002000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -213,11 +213,11 @@ static const u32 ice_ptypes_ipv6_ofos[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
-/* Packet types for packets with an Outer/First/Single IPv6 header, includes
- * IPV6 other PTYPEs
+/* Packet types for packets with an Outer/First/Single non-frag IPv6 header,
+ * includes IPV6 other PTYPEs
*/
static const u32 ice_ptypes_ipv6_ofos_all[] = {
- 0x00000000, 0x00000000, 0x77000000, 0x10002000,
+ 0x00000000, 0x00000000, 0x76000000, 0x10002000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -239,9 +239,11 @@ static const u32 ice_ptypes_ipv6_il[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
-/* Packet types for packets with an Outer/First/Single IPv4 header - no L4 */
+/* Packet types for packets with an Outer/First/Single
+ * non-frag IPv4 header - no L4
+ */
static const u32 ice_ptypes_ipv4_ofos_no_l4[] = {
- 0x10C00000, 0x04000800, 0x00000000, 0x00000000,
+ 0x10800000, 0x04000800, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -263,9 +265,11 @@ static const u32 ice_ptypes_ipv4_il_no_l4[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
-/* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */
+/* Packet types for packets with an Outer/First/Single
+ * non-frag IPv6 header - no L4
+ */
static const u32 ice_ptypes_ipv6_ofos_no_l4[] = {
- 0x00000000, 0x00000000, 0x43000000, 0x10002000,
+ 0x00000000, 0x00000000, 0x42000000, 0x10002000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -1298,9 +1302,19 @@ ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt,
/* set outer most header */
if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4)
segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
+ ICE_FLOW_SEG_HDR_IPV_FRAG |
ICE_FLOW_SEG_HDR_IPV_OTHER;
else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6)
segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
+ ICE_FLOW_SEG_HDR_IPV_FRAG |
+ ICE_FLOW_SEG_HDR_IPV_OTHER;
+ else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4_GRE)
+ segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
+ ICE_FLOW_SEG_HDR_GRE |
+ ICE_FLOW_SEG_HDR_IPV_OTHER;
+ else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6_GRE)
+ segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
+ ICE_FLOW_SEG_HDR_GRE |
ICE_FLOW_SEG_HDR_IPV_OTHER;
if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
diff --git a/sys/dev/ice/ice_flow.h b/sys/dev/ice/ice_flow.h
index 66e50cff6eed..a66c773b8d77 100644
--- a/sys/dev/ice/ice_flow.h
+++ b/sys/dev/ice/ice_flow.h
@@ -87,9 +87,10 @@ enum ice_flow_seg_hdr {
ICE_FLOW_SEG_HDR_SCTP = 0x00000100,
ICE_FLOW_SEG_HDR_GRE = 0x00000200,
/* The following is an additive bit for ICE_FLOW_SEG_HDR_IPV4 and
- * ICE_FLOW_SEG_HDR_IPV6 which include the IPV4 other PTYPEs
+ * ICE_FLOW_SEG_HDR_IPV6.
*/
- ICE_FLOW_SEG_HDR_IPV_OTHER = 0x20000000,
+ ICE_FLOW_SEG_HDR_IPV_FRAG = 0x40000000,
+ ICE_FLOW_SEG_HDR_IPV_OTHER = 0x80000000,
};
enum ice_flow_field {
@@ -193,6 +194,10 @@ enum ice_rss_cfg_hdr_type {
/* take inner headers as inputset for packet with outer ipv6. */
ICE_RSS_INNER_HEADERS_W_OUTER_IPV6,
/* take outer headers first then inner headers as inputset */
+ /* take inner as inputset for GTPoGRE with outer ipv4 + gre. */
+ ICE_RSS_INNER_HEADERS_W_OUTER_IPV4_GRE,
+ /* take inner as inputset for GTPoGRE with outer ipv6 + gre. */
+ ICE_RSS_INNER_HEADERS_W_OUTER_IPV6_GRE,
ICE_RSS_ANY_HEADERS
};
diff --git a/sys/dev/ice/ice_fw_logging.c b/sys/dev/ice/ice_fw_logging.c
new file mode 100644
index 000000000000..fb97df5f5797
--- /dev/null
+++ b/sys/dev/ice/ice_fw_logging.c
@@ -0,0 +1,425 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/* Copyright (c) 2021, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*$FreeBSD$*/
+
+/**
+ * @file ice_fw_logging.c
+ * @brief firmware logging sysctls
+ *
+ * Contains sysctls to enable and configure firmware logging debug support.
+ */
+
+#include "ice_lib.h"
+#include "ice_iflib.h"
+#include <sys/queue.h>
+#include <sys/sdt.h>
+
+/*
+ * SDT provider for DTrace probes related to firmware logging events
+ */
+SDT_PROVIDER_DEFINE(ice_fwlog);
+
+/*
+ * SDT DTrace probe fired when a firmware log message is received over the
+ * AdminQ. It passes the buffer of the firwmare log message along with its
+ * length in bytes to the DTrace framework.
+ */
+SDT_PROBE_DEFINE2(ice_fwlog, , , message, "uint8_t *", "int");
+
+/*
+ * Helper function prototypes
+ */
+static int ice_reconfig_fw_log(struct ice_softc *sc, struct ice_fwlog_cfg *cfg);
+
+/*
+ * dynamic sysctl handlers
+ */
+static int ice_sysctl_fwlog_set_cfg_options(SYSCTL_HANDLER_ARGS);
+static int ice_sysctl_fwlog_log_resolution(SYSCTL_HANDLER_ARGS);
+static int ice_sysctl_fwlog_register(SYSCTL_HANDLER_ARGS);
+static int ice_sysctl_fwlog_module_log_severity(SYSCTL_HANDLER_ARGS);
+
+/**
+ * ice_reconfig_fw_log - Re-program firmware logging configuration
+ * @sc: private softc structure
+ * @cfg: firmware log configuration to latch
+ *
+ * If the adminq is currently active, ask firmware to update the logging
+ * configuration. If the adminq is currently down, then do nothing. In this
+ * case, ice_init_hw() will re-configure firmware logging as soon as it brings
+ * up the adminq.
+ */
+static int
+ice_reconfig_fw_log(struct ice_softc *sc, struct ice_fwlog_cfg *cfg)
+{
+ enum ice_status status;
+
+ ice_fwlog_init(&sc->hw, cfg);
+
+ if (!ice_check_sq_alive(&sc->hw, &sc->hw.adminq))
+ return (0);
+
+ if (!ice_fwlog_supported(&sc->hw))
+ return (0);
+
+ status = ice_fwlog_set(&sc->hw, cfg);
+ if (status) {
+ device_printf(sc->dev,
+ "Failed to reconfigure firmware logging, err %s aq_err %s\n",
+ ice_status_str(status),
+ ice_aq_str(sc->hw.adminq.sq_last_status));
+ return (ENODEV);
+ }
+
+ return (0);
+}
+
+#define ICE_SYSCTL_HELP_FWLOG_LOG_RESOLUTION \
+"\nControl firmware message limit to send per ARQ event" \
+"\t\nMin: 1" \
+"\t\nMax: 128"
+
+#define ICE_SYSCTL_HELP_FWLOG_ARQ_ENA \
+"\nControl whether to enable/disable reporing to admin Rx queue" \
+"\n0 - Enable firmware reporting via ARQ" \
+"\n1 - Disable firmware reporting via ARQ"
+
+#define ICE_SYSCTL_HELP_FWLOG_UART_ENA \
+"\nControl whether to enable/disable reporing to UART" \
+"\n0 - Enable firmware reporting via UART" \
+"\n1 - Disable firmware reporting via UART"
+
+#define ICE_SYSCTL_HELP_FWLOG_ENABLE_ON_LOAD \
+"\nControl whether to enable logging during the attach phase" \
+"\n0 - Enable firmware logging during attach phase" \
+"\n1 - Disable firmware logging during attach phase"
+
+#define ICE_SYSCTL_HELP_FWLOG_REGISTER \
+"\nControl whether to enable/disable firmware logging" \
+"\n0 - Enable firmware logging" \
+"\n1 - Disable firmware logging"
+
+#define ICE_SYSCTL_HELP_FWLOG_MODULE_SEVERITY \
+"\nControl the level of log output messages for this module" \
+"\n\tverbose <4> - Verbose messages + (Error|Warning|Normal)" \
+"\n\tnormal <3> - Normal messages + (Error|Warning)" \
+"\n\twarning <2> - Warning messages + (Error)" \
+"\n\terror <1> - Error messages" \
+"\n\tnone <0> - Disables all logging for this module"
+
+/**
+ * ice_sysctl_fwlog_set_cfg_options - Sysctl for setting fwlog cfg options
+ * @oidp: sysctl oid structure
+ * @arg1: private softc structure
+ * @arg2: option to adjust
+ * @req: sysctl request pointer
+ *
+ * On read: displays whether firmware logging was reported during attachment
+ * On write: enables/disables firmware logging during attach phase
+ *
+ * This has no effect on the legacy (V1) version of firmware logging.
+ */
+static int
+ice_sysctl_fwlog_set_cfg_options(SYSCTL_HANDLER_ARGS)
+{
+ struct ice_softc *sc = (struct ice_softc *)arg1;
+ struct ice_fwlog_cfg *cfg = &sc->hw.fwlog_cfg;
+ int error;
+ u16 option = (u16)arg2;
+ bool enabled;
+
+ enabled = !!(cfg->options & option);
+
+ error = sysctl_handle_bool(oidp, &enabled, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ if (enabled)
+ cfg->options |= option;
+ else
+ cfg->options &= ~option;
+
+ return ice_reconfig_fw_log(sc, cfg);
+}
+
+/**
+ * ice_sysctl_fwlog_log_resolution - Sysctl for setting log message resolution
+ * @oidp: sysctl oid structure
+ * @arg1: private softc structure
+ * @arg2: __unused__
+ * @req: sysctl request pointer
+ *
+ * On read: displays message queue limit before posting
+ * On write: sets message queue limit before posting
+ *
+ * This has no effect on the legacy (V1) version of firmware logging.
+ */
+static int
+ice_sysctl_fwlog_log_resolution(SYSCTL_HANDLER_ARGS)
+{
+ struct ice_softc *sc = (struct ice_softc *)arg1;
+ struct ice_fwlog_cfg *cfg = &sc->hw.fwlog_cfg;
+ int error;
+ u8 resolution;
+
+ UNREFERENCED_PARAMETER(arg2);
+
+ resolution = cfg->log_resolution;
+
+ error = sysctl_handle_8(oidp, &resolution, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ if ((resolution < ICE_AQC_FW_LOG_MIN_RESOLUTION) ||
+ (resolution > ICE_AQC_FW_LOG_MAX_RESOLUTION)) {
+ device_printf(sc->dev, "Log resolution out-of-bounds\n");
+ return (EINVAL);
+ }
+
+ cfg->log_resolution = resolution;
+
+ return ice_reconfig_fw_log(sc, cfg);
+}
+
+/**
+ * ice_sysctl_fwlog_register - Sysctl for (de)registering firmware logs
+ * @oidp: sysctl oid structure
+ * @arg1: private softc structure
+ * @arg2: __unused__
+ * @req: sysctl request pointer
+ *
+ * On read: displays whether firmware logging is registered
+ * On write: (de)registers firmware logging.
+ */
+static int
+ice_sysctl_fwlog_register(SYSCTL_HANDLER_ARGS)
+{
+ struct ice_softc *sc = (struct ice_softc *)arg1;
+ struct ice_fwlog_cfg *cfg = &sc->hw.fwlog_cfg;
+ enum ice_status status;
+ int error;
+ u8 enabled;
+
+ UNREFERENCED_PARAMETER(arg2);
+
+ if (ice_test_state(&sc->state, ICE_STATE_ATTACHING)) {
+ device_printf(sc->dev, "Registering FW Logging via kenv is supported with the on_load option\n");
+ return (EIO);
+ }
+
+ if (cfg->options & ICE_FWLOG_OPTION_IS_REGISTERED)
+ enabled = true;
+ else
+ enabled = false;
+
+ error = sysctl_handle_bool(oidp, &enabled, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ if (!ice_check_sq_alive(&sc->hw, &sc->hw.adminq))
+ return (0);
+
+ if (enabled) {
+ status = ice_fwlog_register(&sc->hw);
+ if (!status)
+ ice_set_bit(ICE_FEATURE_FW_LOGGING, sc->feat_en);
+ } else {
+ status = ice_fwlog_unregister(&sc->hw);
+ if (!status)
+ ice_clear_bit(ICE_FEATURE_FW_LOGGING, sc->feat_en);
+ }
+
+ if (status)
+ return (EIO);
+
+ return (0);
+}
+
+/**
+ * ice_sysctl_fwlog_module_log_severity - Add tunables for a FW logging module
+ * @oidp: sysctl oid structure
+ * @arg1: private softc structure
+ * @arg2: index to logging module
+ * @req: sysctl request pointer
+ */
+static int
+ice_sysctl_fwlog_module_log_severity(SYSCTL_HANDLER_ARGS)
+{
+ struct ice_softc *sc = (struct ice_softc *)arg1;
+ struct ice_fwlog_cfg *cfg = &sc->hw.fwlog_cfg;
+ struct sbuf *sbuf;
+ char *sev_str_end;
+ enum ice_aqc_fw_logging_mod module = (enum ice_aqc_fw_logging_mod)arg2;
+ int error, ll_num;
+ u8 log_level;
+ char sev_str[16];
+ bool sev_set = false;
+
+ log_level = cfg->module_entries[module].log_level;
+ sbuf = sbuf_new(NULL, sev_str, sizeof(sev_str), SBUF_FIXEDLEN);
+ sbuf_printf(sbuf, "%d<%s>", log_level, ice_log_sev_str(log_level));
+ sbuf_finish(sbuf);
+ sbuf_delete(sbuf);
+
+ error = sysctl_handle_string(oidp, sev_str, sizeof(sev_str), req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ if (strcasecmp(ice_log_sev_str(ICE_FWLOG_LEVEL_VERBOSE), sev_str) == 0) {
+ log_level = ICE_FWLOG_LEVEL_VERBOSE;
+ sev_set = true;
+ } else if (strcasecmp(ice_log_sev_str(ICE_FWLOG_LEVEL_NORMAL), sev_str) == 0) {
+ log_level = ICE_FWLOG_LEVEL_NORMAL;
+ sev_set = true;
+ } else if (strcasecmp(ice_log_sev_str(ICE_FWLOG_LEVEL_WARNING), sev_str) == 0) {
+ log_level = ICE_FWLOG_LEVEL_WARNING;
+ sev_set = true;
+ } else if (strcasecmp(ice_log_sev_str(ICE_FWLOG_LEVEL_ERROR), sev_str) == 0) {
+ log_level = ICE_FWLOG_LEVEL_ERROR;
+ sev_set = true;
+ } else if (strcasecmp(ice_log_sev_str(ICE_FWLOG_LEVEL_NONE), sev_str) == 0) {
+ log_level = ICE_FWLOG_LEVEL_NONE;
+ sev_set = true;
+ }
+
+ if (!sev_set) {
+ ll_num = strtol(sev_str, &sev_str_end, 0);
+ if (sev_str_end == sev_str)
+ ll_num = -1;
+ if ((ll_num >= ICE_FWLOG_LEVEL_NONE) &&
+ (ll_num < ICE_FWLOG_LEVEL_INVALID))
+ log_level = ll_num;
+ else {
+ device_printf(sc->dev,
+ "%s: \"%s\" is not a valid log level\n",
+ __func__, sev_str);
+ return (EINVAL);
+ }
+ }
+
+ cfg->module_entries[module].log_level = log_level;
+
+ return ice_reconfig_fw_log(sc, cfg);
+}
+
+/**
+ * ice_add_fw_logging_tunables - Add tunables to configure FW logging events
+ * @sc: private softc structure
+ * @parent: parent node to add the tunables under
+ *
+ * Add tunables for configuring the firmware logging support. This includes
+ * a control to enable the logging, and controls for each module to configure
+ * which events to receive.
+ */
+void
+ice_add_fw_logging_tunables(struct ice_softc *sc, struct sysctl_oid *parent)
+{
+ struct sysctl_oid_list *parent_list, *fwlog_list, *module_list;
+ struct sysctl_oid *fwlog_node, *module_node;
+ struct sysctl_ctx_list *ctx;
+ struct ice_hw *hw = &sc->hw;
+ struct ice_fwlog_cfg *cfg;
+ device_t dev = sc->dev;
+ enum ice_aqc_fw_logging_mod module;
+ u16 i;
+
+ cfg = &hw->fwlog_cfg;
+ ctx = device_get_sysctl_ctx(dev);
+ parent_list = SYSCTL_CHILDREN(parent);
+
+ fwlog_node = SYSCTL_ADD_NODE(ctx, parent_list, OID_AUTO, "fw_log",
+ ICE_CTLFLAG_DEBUG | CTLFLAG_RD, NULL,
+ "Firmware Logging");
+ fwlog_list = SYSCTL_CHILDREN(fwlog_node);
+
+ cfg->log_resolution = 10;
+ SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "log_resolution",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_U8 | CTLFLAG_RWTUN, sc,
+ 0, ice_sysctl_fwlog_log_resolution,
+ "CU", ICE_SYSCTL_HELP_FWLOG_LOG_RESOLUTION);
+
+ cfg->options |= ICE_FWLOG_OPTION_ARQ_ENA;
+ SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "arq_en",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_U8 | CTLFLAG_RWTUN, sc,
+ ICE_FWLOG_OPTION_ARQ_ENA, ice_sysctl_fwlog_set_cfg_options,
+ "CU", ICE_SYSCTL_HELP_FWLOG_ARQ_ENA);
+
+ SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "uart_en",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_U8 | CTLFLAG_RWTUN, sc,
+ ICE_FWLOG_OPTION_UART_ENA, ice_sysctl_fwlog_set_cfg_options,
+ "CU", ICE_SYSCTL_HELP_FWLOG_UART_ENA);
+
+ SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "on_load",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_U8 | CTLFLAG_RWTUN, sc,
+ ICE_FWLOG_OPTION_REGISTER_ON_INIT, ice_sysctl_fwlog_set_cfg_options,
+ "CU", ICE_SYSCTL_HELP_FWLOG_ENABLE_ON_LOAD);
+
+ SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "register",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_U8 | CTLFLAG_RWTUN, sc,
+ 0, ice_sysctl_fwlog_register,
+ "CU", ICE_SYSCTL_HELP_FWLOG_REGISTER);
+
+ module_node = SYSCTL_ADD_NODE(ctx, fwlog_list, OID_AUTO, "severity",
+ ICE_CTLFLAG_DEBUG | CTLFLAG_RD, NULL,
+ "Level of log output");
+
+ module_list = SYSCTL_CHILDREN(module_node);
+
+ for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) {
+ /* Setup some defaults */
+ cfg->module_entries[i].module_id = i;
+ cfg->module_entries[i].log_level = ICE_FWLOG_LEVEL_NONE;
+ module = (enum ice_aqc_fw_logging_mod)i;
+
+ SYSCTL_ADD_PROC(ctx, module_list,
+ OID_AUTO, ice_fw_module_str(module),
+ ICE_CTLFLAG_DEBUG | CTLTYPE_STRING | CTLFLAG_RWTUN, sc,
+ module, ice_sysctl_fwlog_module_log_severity,
+ "A", ICE_SYSCTL_HELP_FWLOG_MODULE_SEVERITY);
+ }
+}
+
+/**
+ * ice_handle_fw_log_event - Handle a firmware logging event from the AdminQ
+ * @sc: pointer to private softc structure
+ * @desc: the AdminQ descriptor for this firmware event
+ * @buf: pointer to the buffer accompanying the AQ message
+ */
+void
+ice_handle_fw_log_event(struct ice_softc *sc, struct ice_aq_desc *desc,
+ void *buf)
+{
+ /* Trigger a DTrace probe event for this firmware message */
+ SDT_PROBE2(ice_fwlog, , , message, (const u8 *)buf, desc->datalen);
+
+ /* Possibly dump the firmware message to the console, if enabled */
+ ice_fwlog_event_dump(&sc->hw, desc, buf);
+}
diff --git a/sys/dev/ice/ice_fwlog.c b/sys/dev/ice/ice_fwlog.c
new file mode 100644
index 000000000000..375b80647e1a
--- /dev/null
+++ b/sys/dev/ice/ice_fwlog.c
@@ -0,0 +1,505 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/* Copyright (c) 2021, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*$FreeBSD$*/
+
+#include "ice_common.h"
+#include "ice_fwlog.h"
+
+/**
+ * cache_cfg - Cache FW logging config
+ * @hw: pointer to the HW structure
+ * @cfg: config to cache
+ */
+static void cache_cfg(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
+{
+ hw->fwlog_cfg = *cfg;
+}
+
+/**
+ * valid_module_entries - validate all the module entry IDs and log levels
+ * @hw: pointer to the HW structure
+ * @entries: entries to validate
+ * @num_entries: number of entries to validate
+ */
+static bool
+valid_module_entries(struct ice_hw *hw, struct ice_fwlog_module_entry *entries,
+ u16 num_entries)
+{
+ u16 i;
+
+ if (!entries) {
+ ice_debug(hw, ICE_DBG_FW_LOG, "Null ice_fwlog_module_entry array\n");
+ return false;
+ }
+
+ if (!num_entries) {
+ ice_debug(hw, ICE_DBG_FW_LOG, "num_entries must be non-zero\n");
+ return false;
+ }
+
+ for (i = 0; i < num_entries; i++) {
+ struct ice_fwlog_module_entry *entry = &entries[i];
+
+ if (entry->module_id >= ICE_AQC_FW_LOG_ID_MAX) {
+ ice_debug(hw, ICE_DBG_FW_LOG, "Invalid module_id %u, max valid module_id is %u\n",
+ entry->module_id, ICE_AQC_FW_LOG_ID_MAX - 1);
+ return false;
+ }
+
+ if (entry->log_level >= ICE_FWLOG_LEVEL_INVALID) {
+ ice_debug(hw, ICE_DBG_FW_LOG, "Invalid log_level %u, max valid log_level is %u\n",
+ entry->log_level,
+ ICE_AQC_FW_LOG_ID_MAX - 1);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * valid_cfg - validate entire configuration
+ * @hw: pointer to the HW structure
+ * @cfg: config to validate
+ */
+static bool valid_cfg(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
+{
+ if (!cfg) {
+ ice_debug(hw, ICE_DBG_FW_LOG, "Null ice_fwlog_cfg\n");
+ return false;
+ }
+
+ if (cfg->log_resolution < ICE_AQC_FW_LOG_MIN_RESOLUTION ||
+ cfg->log_resolution > ICE_AQC_FW_LOG_MAX_RESOLUTION) {
+ ice_debug(hw, ICE_DBG_FW_LOG, "Unsupported log_resolution %u, must be between %u and %u\n",
+ cfg->log_resolution, ICE_AQC_FW_LOG_MIN_RESOLUTION,
+ ICE_AQC_FW_LOG_MAX_RESOLUTION);
+ return false;
+ }
+
+ if (!valid_module_entries(hw, cfg->module_entries,
+ ICE_AQC_FW_LOG_ID_MAX))
+ return false;
+
+ return true;
+}
+
+/**
+ * ice_fwlog_init - Initialize cached structures for tracking FW logging
+ * @hw: pointer to the HW structure
+ * @cfg: config used to initialize the cached structures
+ *
+ * This function should be called on driver initialization and before calling
+ * ice_init_hw(). Firmware logging will be configured based on these settings
+ * and also the PF will be registered on init.
+ */
+enum ice_status
+ice_fwlog_init(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
+{
+ if (!valid_cfg(hw, cfg))
+ return ICE_ERR_PARAM;
+
+ cache_cfg(hw, cfg);
+
+ return ICE_SUCCESS;
+}
+
+/**
+ * ice_aq_fwlog_set - Set FW logging configuration AQ command (0xFF30)
+ * @hw: pointer to the HW structure
+ * @entries: entries to configure
+ * @num_entries: number of @entries
+ * @options: options from ice_fwlog_cfg->options structure
+ * @log_resolution: logging resolution
+ */
+static enum ice_status
+ice_aq_fwlog_set(struct ice_hw *hw, struct ice_fwlog_module_entry *entries,
+ u16 num_entries, u16 options, u16 log_resolution)
+{
+ struct ice_aqc_fw_log_cfg_resp *fw_modules;
+ struct ice_aqc_fw_log *cmd;
+ struct ice_aq_desc desc;
+ enum ice_status status;
+ u16 i;
+
+ fw_modules = (struct ice_aqc_fw_log_cfg_resp *)
+ ice_calloc(hw, num_entries, sizeof(*fw_modules));
+ if (!fw_modules)
+ return ICE_ERR_NO_MEMORY;
+
+ for (i = 0; i < num_entries; i++) {
+ fw_modules[i].module_identifier =
+ CPU_TO_LE16(entries[i].module_id);
+ fw_modules[i].log_level = entries[i].log_level;
+ }
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_config);
+ desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
+
+ cmd = &desc.params.fw_log;
+
+ cmd->cmd_flags = ICE_AQC_FW_LOG_CONF_SET_VALID;
+ cmd->ops.cfg.log_resolution = CPU_TO_LE16(log_resolution);
+ cmd->ops.cfg.mdl_cnt = CPU_TO_LE16(num_entries);
+
+ if (options & ICE_FWLOG_OPTION_ARQ_ENA)
+ cmd->cmd_flags |= ICE_AQC_FW_LOG_CONF_AQ_EN;
+ if (options & ICE_FWLOG_OPTION_UART_ENA)
+ cmd->cmd_flags |= ICE_AQC_FW_LOG_CONF_UART_EN;
+
+ status = ice_aq_send_cmd(hw, &desc, fw_modules,
+ sizeof(*fw_modules) * num_entries,
+ NULL);
+
+ ice_free(hw, fw_modules);
+
+ return status;
+}
+
+/**
+ * ice_fwlog_supported - Cached for whether FW supports FW logging or not
+ * @hw: pointer to the HW structure
+ *
+ * This will always return false if called before ice_init_hw(), so it must be
+ * called after ice_init_hw().
+ */
+bool ice_fwlog_supported(struct ice_hw *hw)
+{
+ return hw->fwlog_support_ena;
+}
+
+/**
+ * ice_fwlog_set - Set the firmware logging settings
+ * @hw: pointer to the HW structure
+ * @cfg: config used to set firmware logging
+ *
+ * This function should be called whenever the driver needs to set the firmware
+ * logging configuration. It can be called on initialization, reset, or during
+ * runtime.
+ *
+ * If the PF wishes to receive FW logging then it must register via
+ * ice_fwlog_register. Note, that ice_fwlog_register does not need to be called
+ * for init.
+ */
+enum ice_status
+ice_fwlog_set(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
+{
+ enum ice_status status;
+
+ if (!ice_fwlog_supported(hw))
+ return ICE_ERR_NOT_SUPPORTED;
+
+ if (!valid_cfg(hw, cfg))
+ return ICE_ERR_PARAM;
+
+ status = ice_aq_fwlog_set(hw, cfg->module_entries,
+ ICE_AQC_FW_LOG_ID_MAX, cfg->options,
+ cfg->log_resolution);
+ if (!status)
+ cache_cfg(hw, cfg);
+
+ return status;
+}
+
+/**
+ * update_cached_entries - Update module entries in cached FW logging config
+ * @hw: pointer to the HW structure
+ * @entries: entries to cache
+ * @num_entries: number of @entries
+ */
+static void
+update_cached_entries(struct ice_hw *hw, struct ice_fwlog_module_entry *entries,
+ u16 num_entries)
+{
+ u16 i;
+
+ for (i = 0; i < num_entries; i++) {
+ struct ice_fwlog_module_entry *updated = &entries[i];
+ u16 j;
+
+ for (j = 0; j < ICE_AQC_FW_LOG_ID_MAX; j++) {
+ struct ice_fwlog_module_entry *cached =
+ &hw->fwlog_cfg.module_entries[j];
+
+ if (cached->module_id == updated->module_id) {
+ cached->log_level = updated->log_level;
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * ice_fwlog_update_modules - Update the log level 1 or more FW logging modules
+ * @hw: pointer to the HW structure
+ * @entries: array of ice_fwlog_module_entry(s)
+ * @num_entries: number of entries
+ *
+ * This function should be called to update the log level of 1 or more FW
+ * logging modules via module ID.
+ *
+ * Only the entries passed in will be affected. All other firmware logging
+ * settings will be unaffected.
+ */
+enum ice_status
+ice_fwlog_update_modules(struct ice_hw *hw,
+ struct ice_fwlog_module_entry *entries,
+ u16 num_entries)
+{
+ struct ice_fwlog_cfg *cfg;
+ enum ice_status status;
+
+ if (!ice_fwlog_supported(hw))
+ return ICE_ERR_NOT_SUPPORTED;
+
+ if (!valid_module_entries(hw, entries, num_entries))
+ return ICE_ERR_PARAM;
+
+ cfg = (struct ice_fwlog_cfg *)ice_calloc(hw, 1, sizeof(*cfg));
+ if (!cfg)
+ return ICE_ERR_NO_MEMORY;
+
+ status = ice_fwlog_get(hw, cfg);
+ if (status)
+ goto status_out;
+
+ status = ice_aq_fwlog_set(hw, entries, num_entries, cfg->options,
+ cfg->log_resolution);
+ if (!status)
+ update_cached_entries(hw, entries, num_entries);
+
+status_out:
+ ice_free(hw, cfg);
+ return status;
+}
+
+/**
+ * ice_aq_fwlog_register - Register PF for firmware logging events (0xFF31)
+ * @hw: pointer to the HW structure
+ * @reg: true to register and false to unregister
+ */
+static enum ice_status ice_aq_fwlog_register(struct ice_hw *hw, bool reg)
+{
+ struct ice_aq_desc desc;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_register);
+
+ if (reg)
+ desc.params.fw_log.cmd_flags = ICE_AQC_FW_LOG_AQ_REGISTER;
+
+ return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
+}
+
+/**
+ * ice_fwlog_register - Register the PF for firmware logging
+ * @hw: pointer to the HW structure
+ *
+ * After this call the PF will start to receive firmware logging based on the
+ * configuration set in ice_fwlog_set.
+ */
+enum ice_status ice_fwlog_register(struct ice_hw *hw)
+{
+ enum ice_status status;
+
+ if (!ice_fwlog_supported(hw))
+ return ICE_ERR_NOT_SUPPORTED;
+
+ status = ice_aq_fwlog_register(hw, true);
+ if (status)
+ ice_debug(hw, ICE_DBG_FW_LOG, "Failed to register for firmware logging events over ARQ\n");
+ else
+ hw->fwlog_cfg.options |= ICE_FWLOG_OPTION_IS_REGISTERED;
+
+ return status;
+}
+
+/**
+ * ice_fwlog_unregister - Unregister the PF from firmware logging
+ * @hw: pointer to the HW structure
+ */
+enum ice_status ice_fwlog_unregister(struct ice_hw *hw)
+{
+ enum ice_status status;
+
+ if (!ice_fwlog_supported(hw))
+ return ICE_ERR_NOT_SUPPORTED;
+
+ status = ice_aq_fwlog_register(hw, false);
+ if (status)
+ ice_debug(hw, ICE_DBG_FW_LOG, "Failed to unregister from firmware logging events over ARQ\n");
+ else
+ hw->fwlog_cfg.options &= ~ICE_FWLOG_OPTION_IS_REGISTERED;
+
+ return status;
+}
+
+/**
+ * ice_aq_fwlog_get - Get the current firmware logging configuration (0xFF32)
+ * @hw: pointer to the HW structure
+ * @cfg: firmware logging configuration to populate
+ */
+static enum ice_status
+ice_aq_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
+{
+ struct ice_aqc_fw_log_cfg_resp *fw_modules;
+ struct ice_aqc_fw_log *cmd;
+ struct ice_aq_desc desc;
+ enum ice_status status;
+ u16 i, module_id_cnt;
+ void *buf;
+
+ ice_memset(cfg, 0, sizeof(*cfg), ICE_NONDMA_MEM);
+
+ buf = ice_calloc(hw, 1, ICE_AQ_MAX_BUF_LEN);
+ if (!buf)
+ return ICE_ERR_NO_MEMORY;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logs_query);
+ cmd = &desc.params.fw_log;
+
+ cmd->cmd_flags = ICE_AQC_FW_LOG_AQ_QUERY;
+
+ status = ice_aq_send_cmd(hw, &desc, buf, ICE_AQ_MAX_BUF_LEN, NULL);
+ if (status) {
+ ice_debug(hw, ICE_DBG_FW_LOG, "Failed to get FW log configuration\n");
+ goto status_out;
+ }
+
+ module_id_cnt = LE16_TO_CPU(cmd->ops.cfg.mdl_cnt);
+ if (module_id_cnt < ICE_AQC_FW_LOG_ID_MAX) {
+ ice_debug(hw, ICE_DBG_FW_LOG, "FW returned less than the expected number of FW log module IDs\n");
+ } else {
+ if (module_id_cnt > ICE_AQC_FW_LOG_ID_MAX)
+ ice_debug(hw, ICE_DBG_FW_LOG, "FW returned more than expected number of FW log module IDs, setting module_id_cnt to software expected max %u\n",
+ ICE_AQC_FW_LOG_ID_MAX);
+ module_id_cnt = ICE_AQC_FW_LOG_ID_MAX;
+ }
+
+ cfg->log_resolution = LE16_TO_CPU(cmd->ops.cfg.log_resolution);
+ if (cmd->cmd_flags & ICE_AQC_FW_LOG_CONF_AQ_EN)
+ cfg->options |= ICE_FWLOG_OPTION_ARQ_ENA;
+ if (cmd->cmd_flags & ICE_AQC_FW_LOG_CONF_UART_EN)
+ cfg->options |= ICE_FWLOG_OPTION_UART_ENA;
+ if (cmd->cmd_flags & ICE_AQC_FW_LOG_QUERY_REGISTERED)
+ cfg->options |= ICE_FWLOG_OPTION_IS_REGISTERED;
+
+ fw_modules = (struct ice_aqc_fw_log_cfg_resp *)buf;
+
+ for (i = 0; i < module_id_cnt; i++) {
+ struct ice_aqc_fw_log_cfg_resp *fw_module = &fw_modules[i];
+
+ cfg->module_entries[i].module_id =
+ LE16_TO_CPU(fw_module->module_identifier);
+ cfg->module_entries[i].log_level = fw_module->log_level;
+ }
+
+status_out:
+ ice_free(hw, buf);
+ return status;
+}
+
+/**
+ * ice_fwlog_set_support_ena - Set if FW logging is supported by FW
+ * @hw: pointer to the HW struct
+ *
+ * If FW returns success to the ice_aq_fwlog_get call then it supports FW
+ * logging, else it doesn't. Set the fwlog_support_ena flag accordingly.
+ *
+ * This function is only meant to be called during driver init to determine if
+ * the FW support FW logging.
+ */
+void ice_fwlog_set_support_ena(struct ice_hw *hw)
+{
+ struct ice_fwlog_cfg *cfg;
+ enum ice_status status;
+
+ hw->fwlog_support_ena = false;
+
+ cfg = (struct ice_fwlog_cfg *)ice_calloc(hw, 1, sizeof(*cfg));
+ if (!cfg)
+ return;
+
+ /* don't call ice_fwlog_get() because that would overwrite the cached
+ * configuration from the call to ice_fwlog_init(), which is expected to
+ * be called prior to this function
+ */
+ status = ice_aq_fwlog_get(hw, cfg);
+ if (status)
+ ice_debug(hw, ICE_DBG_FW_LOG, "ice_fwlog_get failed, FW logging is not supported on this version of FW, status %d\n",
+ status);
+ else
+ hw->fwlog_support_ena = true;
+
+ ice_free(hw, cfg);
+}
+
+/**
+ * ice_fwlog_get - Get the firmware logging settings
+ * @hw: pointer to the HW structure
+ * @cfg: config to populate based on current firmware logging settings
+ */
+enum ice_status
+ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg)
+{
+ enum ice_status status;
+
+ if (!ice_fwlog_supported(hw))
+ return ICE_ERR_NOT_SUPPORTED;
+
+ if (!cfg)
+ return ICE_ERR_PARAM;
+
+ status = ice_aq_fwlog_get(hw, cfg);
+ if (status)
+ return status;
+
+ cache_cfg(hw, cfg);
+
+ return ICE_SUCCESS;
+}
+
+/**
+ * ice_fwlog_event_dump - Dump the event received over the Admin Receive Queue
+ * @hw: pointer to the HW structure
+ * @desc: Admin Receive Queue descriptor
+ * @buf: buffer that contains the FW log event data
+ *
+ * If the driver receives the ice_aqc_opc_fw_logs_event on the Admin Receive
+ * Queue, then it should call this function to dump the FW log data.
+ */
+void
+ice_fwlog_event_dump(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf)
+{
+ if (!ice_fwlog_supported(hw))
+ return;
+
+ ice_info_fwlog(hw, 32, 1, (u8 *)buf, LE16_TO_CPU(desc->datalen));
+}
diff --git a/sys/dev/ice/ice_fwlog.h b/sys/dev/ice/ice_fwlog.h
new file mode 100644
index 000000000000..c8906d56a75a
--- /dev/null
+++ b/sys/dev/ice/ice_fwlog.h
@@ -0,0 +1,91 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/* Copyright (c) 2021, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*$FreeBSD$*/
+
+#ifndef _ICE_FWLOG_H_
+#define _ICE_FWLOG_H_
+#include "ice_adminq_cmd.h"
+
+struct ice_hw;
+
+/* Only a single log level should be set and all log levels under the set value
+ * are enabled, e.g. if log level is set to ICE_FW_LOG_LEVEL_VERBOSE, then all
+ * other log levels are included (except ICE_FW_LOG_LEVEL_NONE)
+ */
+enum ice_fwlog_level {
+ ICE_FWLOG_LEVEL_NONE = 0,
+ ICE_FWLOG_LEVEL_ERROR = 1,
+ ICE_FWLOG_LEVEL_WARNING = 2,
+ ICE_FWLOG_LEVEL_NORMAL = 3,
+ ICE_FWLOG_LEVEL_VERBOSE = 4,
+ ICE_FWLOG_LEVEL_INVALID, /* all values >= this entry are invalid */
+};
+
+struct ice_fwlog_module_entry {
+ /* module ID for the corresponding firmware logging event */
+ u16 module_id;
+ /* verbosity level for the module_id */
+ u8 log_level;
+};
+
+struct ice_fwlog_cfg {
+ /* list of modules for configuring log level */
+ struct ice_fwlog_module_entry module_entries[ICE_AQC_FW_LOG_ID_MAX];
+#define ICE_FWLOG_OPTION_ARQ_ENA BIT(0)
+#define ICE_FWLOG_OPTION_UART_ENA BIT(1)
+ /* set before calling ice_fwlog_init() so the PF registers for firmware
+ * logging on initialization
+ */
+#define ICE_FWLOG_OPTION_REGISTER_ON_INIT BIT(2)
+ /* set in the ice_fwlog_get() response if the PF is registered for FW
+ * logging events over ARQ
+ */
+#define ICE_FWLOG_OPTION_IS_REGISTERED BIT(3)
+ /* options used to configure firmware logging */
+ u16 options;
+ /* minimum number of log events sent per Admin Receive Queue event */
+ u8 log_resolution;
+};
+
+void ice_fwlog_set_support_ena(struct ice_hw *hw);
+bool ice_fwlog_supported(struct ice_hw *hw);
+enum ice_status ice_fwlog_init(struct ice_hw *hw, struct ice_fwlog_cfg *cfg);
+enum ice_status ice_fwlog_set(struct ice_hw *hw, struct ice_fwlog_cfg *cfg);
+enum ice_status ice_fwlog_get(struct ice_hw *hw, struct ice_fwlog_cfg *cfg);
+enum ice_status
+ice_fwlog_update_modules(struct ice_hw *hw,
+ struct ice_fwlog_module_entry *entries,
+ u16 num_entries);
+enum ice_status ice_fwlog_register(struct ice_hw *hw);
+enum ice_status ice_fwlog_unregister(struct ice_hw *hw);
+void
+ice_fwlog_event_dump(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf);
+#endif /* _ICE_FWLOG_H_ */
diff --git a/sys/dev/ice/ice_hw_autogen.h b/sys/dev/ice/ice_hw_autogen.h
index 7d2203849b23..a1e9024ba34e 100644
--- a/sys/dev/ice/ice_hw_autogen.h
+++ b/sys/dev/ice/ice_hw_autogen.h
@@ -30,10 +30,20 @@
*/
/*$FreeBSD$*/
-/* Machine-generated file; do not edit */
+/* Machine generated file. Do not edit. */
+
#ifndef _ICE_HW_AUTOGEN_H_
#define _ICE_HW_AUTOGEN_H_
+#define GL_HIDA(_i) (0x00082000 + ((_i) * 4))
+#define GL_HIBA(_i) (0x00081000 + ((_i) * 4))
+#define GL_HICR 0x00082040
+#define GL_HICR_EN 0x00082044
+#define GLGEN_CSR_DEBUG_C 0x00075750
+#define GLNVM_GENS 0x000B6100
+#define GLNVM_FLA 0x000B6108
+#define GL_HIDA_MAX_INDEX 15
+#define GL_HIBA_MAX_INDEX 1023
#define GL_RDPU_CNTRL 0x00052054 /* Reset Source: CORER */
#define GL_RDPU_CNTRL_RX_PAD_EN_S 0
#define GL_RDPU_CNTRL_RX_PAD_EN_M BIT(0)
@@ -476,8 +486,8 @@
#define PF0INT_OICR_CPM_PAGE_RSV3_M BIT(23)
#define PF0INT_OICR_CPM_PAGE_STORM_DETECT_S 24
#define PF0INT_OICR_CPM_PAGE_STORM_DETECT_M BIT(24)
-#define PF0INT_OICR_CPM_PAGE_LINK_STAT_CHANGE_S 25
-#define PF0INT_OICR_CPM_PAGE_LINK_STAT_CHANGE_M BIT(25)
+#define PF0INT_OICR_CPM_PAGE_LINK_STAT_CHANGE_S 25
+#define PF0INT_OICR_CPM_PAGE_LINK_STAT_CHANGE_M BIT(25)
#define PF0INT_OICR_CPM_PAGE_HMC_ERR_S 26
#define PF0INT_OICR_CPM_PAGE_HMC_ERR_M BIT(26)
#define PF0INT_OICR_CPM_PAGE_PE_PUSH_S 27
@@ -540,8 +550,8 @@
#define PF0INT_OICR_HLP_PAGE_RSV3_M BIT(23)
#define PF0INT_OICR_HLP_PAGE_STORM_DETECT_S 24
#define PF0INT_OICR_HLP_PAGE_STORM_DETECT_M BIT(24)
-#define PF0INT_OICR_HLP_PAGE_LINK_STAT_CHANGE_S 25
-#define PF0INT_OICR_HLP_PAGE_LINK_STAT_CHANGE_M BIT(25)
+#define PF0INT_OICR_HLP_PAGE_LINK_STAT_CHANGE_S 25
+#define PF0INT_OICR_HLP_PAGE_LINK_STAT_CHANGE_M BIT(25)
#define PF0INT_OICR_HLP_PAGE_HMC_ERR_S 26
#define PF0INT_OICR_HLP_PAGE_HMC_ERR_M BIT(26)
#define PF0INT_OICR_HLP_PAGE_PE_PUSH_S 27
@@ -589,8 +599,8 @@
#define PF0INT_OICR_PSM_PAGE_RSV3_M BIT(23)
#define PF0INT_OICR_PSM_PAGE_STORM_DETECT_S 24
#define PF0INT_OICR_PSM_PAGE_STORM_DETECT_M BIT(24)
-#define PF0INT_OICR_PSM_PAGE_LINK_STAT_CHANGE_S 25
-#define PF0INT_OICR_PSM_PAGE_LINK_STAT_CHANGE_M BIT(25)
+#define PF0INT_OICR_PSM_PAGE_LINK_STAT_CHANGE_S 25
+#define PF0INT_OICR_PSM_PAGE_LINK_STAT_CHANGE_M BIT(25)
#define PF0INT_OICR_PSM_PAGE_HMC_ERR_S 26
#define PF0INT_OICR_PSM_PAGE_HMC_ERR_M BIT(26)
#define PF0INT_OICR_PSM_PAGE_PE_PUSH_S 27
@@ -730,8 +740,8 @@
#define GL_ACL_PROFILE_BWSB_SEL_WSB_SRC_OFF_M MAKEMASK(0x1F, 8)
#define GL_ACL_PROFILE_DWSB_SEL(_i) (0x00391088 + ((_i) * 4)) /* _i=0...15 */ /* Reset Source: CORER */
#define GL_ACL_PROFILE_DWSB_SEL_MAX_INDEX 15
-#define GL_ACL_PROFILE_DWSB_SEL_DWORD_SEL_OFF_S 0
-#define GL_ACL_PROFILE_DWSB_SEL_DWORD_SEL_OFF_M MAKEMASK(0xF, 0)
+#define GL_ACL_PROFILE_DWSB_SEL_DWORD_SEL_OFF_S 0
+#define GL_ACL_PROFILE_DWSB_SEL_DWORD_SEL_OFF_M MAKEMASK(0xF, 0)
#define GL_ACL_PROFILE_PF_CFG(_i) (0x003910C8 + ((_i) * 4)) /* _i=0...7 */ /* Reset Source: CORER */
#define GL_ACL_PROFILE_PF_CFG_MAX_INDEX 7
#define GL_ACL_PROFILE_PF_CFG_SCEN_SEL_S 0
@@ -889,8 +899,8 @@
#define GLLAN_TCLAN_CACHE_CTL_FETCH_CL_ALIGN_M BIT(6)
#define GLLAN_TCLAN_CACHE_CTL_MIN_ALLOC_THRESH_S 7
#define GLLAN_TCLAN_CACHE_CTL_MIN_ALLOC_THRESH_M MAKEMASK(0x7F, 7)
-#define GLLAN_TCLAN_CACHE_CTL_CACHE_ENTRY_CNT_S 14
-#define GLLAN_TCLAN_CACHE_CTL_CACHE_ENTRY_CNT_M MAKEMASK(0xFF, 14)
+#define GLLAN_TCLAN_CACHE_CTL_CACHE_ENTRY_CNT_S 14
+#define GLLAN_TCLAN_CACHE_CTL_CACHE_ENTRY_CNT_M MAKEMASK(0xFF, 14)
#define GLLAN_TCLAN_CACHE_CTL_CACHE_DESC_LIM_S 22
#define GLLAN_TCLAN_CACHE_CTL_CACHE_DESC_LIM_M MAKEMASK(0x3FF, 22)
#define GLTCLAN_CQ_CNTX0(_CQ) (0x000F0800 + ((_CQ) * 4)) /* _i=0...511 */ /* Reset Source: CORER */
@@ -2233,8 +2243,8 @@
#define PRTDCB_TX_DSCP2UP_CTL 0x00040980 /* Reset Source: CORER */
#define PRTDCB_TX_DSCP2UP_CTL_DSCP2UP_ENA_S 0
#define PRTDCB_TX_DSCP2UP_CTL_DSCP2UP_ENA_M BIT(0)
-#define PRTDCB_TX_DSCP2UP_CTL_DSCP_DEFAULT_UP_S 1
-#define PRTDCB_TX_DSCP2UP_CTL_DSCP_DEFAULT_UP_M MAKEMASK(0x7, 1)
+#define PRTDCB_TX_DSCP2UP_CTL_DSCP_DEFAULT_UP_S 1
+#define PRTDCB_TX_DSCP2UP_CTL_DSCP_DEFAULT_UP_M MAKEMASK(0x7, 1)
#define PRTDCB_TX_DSCP2UP_IPV4_LUT(_i) (0x000409A0 + ((_i) * 32)) /* _i=0...7 */ /* Reset Source: CORER */
#define PRTDCB_TX_DSCP2UP_IPV4_LUT_MAX_INDEX 7
#define PRTDCB_TX_DSCP2UP_IPV4_LUT_DSCP2UP_LUT_0_S 0
@@ -2382,8 +2392,8 @@
#define TPB_PRTTCB_LL_DWRR_REG_CREDITS_CREDITS_S 0
#define TPB_PRTTCB_LL_DWRR_REG_CREDITS_CREDITS_M MAKEMASK(0x3FFFF, 0)
#define TPB_PRTTCB_LL_DWRR_WB_CREDITS 0x00099320 /* Reset Source: CORER */
-#define TPB_PRTTCB_LL_DWRR_WB_CREDITS_CREDITS_S 0
-#define TPB_PRTTCB_LL_DWRR_WB_CREDITS_CREDITS_M MAKEMASK(0x3FFFF, 0)
+#define TPB_PRTTCB_LL_DWRR_WB_CREDITS_CREDITS_S 0
+#define TPB_PRTTCB_LL_DWRR_WB_CREDITS_CREDITS_M MAKEMASK(0x3FFFF, 0)
#define TPB_WB_RL_TC_CFG(_i) (0x00099360 + ((_i) * 4)) /* _i=0...31 */ /* Reset Source: CORER */
#define TPB_WB_RL_TC_CFG_MAX_INDEX 31
#define TPB_WB_RL_TC_CFG_TOKENS_S 0
@@ -2448,8 +2458,8 @@
#define GL_ACLEXT_FORCE_L1CDID_MAX_INDEX 2
#define GL_ACLEXT_FORCE_L1CDID_STATIC_CDID_S 0
#define GL_ACLEXT_FORCE_L1CDID_STATIC_CDID_M MAKEMASK(0xF, 0)
-#define GL_ACLEXT_FORCE_L1CDID_STATIC_CDID_EN_S 31
-#define GL_ACLEXT_FORCE_L1CDID_STATIC_CDID_EN_M BIT(31)
+#define GL_ACLEXT_FORCE_L1CDID_STATIC_CDID_EN_S 31
+#define GL_ACLEXT_FORCE_L1CDID_STATIC_CDID_EN_M BIT(31)
#define GL_ACLEXT_FORCE_PID(_i) (0x00210000 + ((_i) * 4)) /* _i=0...2 */ /* Reset Source: CORER */
#define GL_ACLEXT_FORCE_PID_MAX_INDEX 2
#define GL_ACLEXT_FORCE_PID_STATIC_PID_S 0
@@ -2642,8 +2652,8 @@
#define GL_PREEXT_FORCE_L1CDID_MAX_INDEX 2
#define GL_PREEXT_FORCE_L1CDID_STATIC_CDID_S 0
#define GL_PREEXT_FORCE_L1CDID_STATIC_CDID_M MAKEMASK(0xF, 0)
-#define GL_PREEXT_FORCE_L1CDID_STATIC_CDID_EN_S 31
-#define GL_PREEXT_FORCE_L1CDID_STATIC_CDID_EN_M BIT(31)
+#define GL_PREEXT_FORCE_L1CDID_STATIC_CDID_EN_S 31
+#define GL_PREEXT_FORCE_L1CDID_STATIC_CDID_EN_M BIT(31)
#define GL_PREEXT_FORCE_PID(_i) (0x0020F000 + ((_i) * 4)) /* _i=0...2 */ /* Reset Source: CORER */
#define GL_PREEXT_FORCE_PID_MAX_INDEX 2
#define GL_PREEXT_FORCE_PID_STATIC_PID_S 0
@@ -2844,8 +2854,8 @@
#define GL_PSTEXT_FORCE_L1CDID_MAX_INDEX 2
#define GL_PSTEXT_FORCE_L1CDID_STATIC_CDID_S 0
#define GL_PSTEXT_FORCE_L1CDID_STATIC_CDID_M MAKEMASK(0xF, 0)
-#define GL_PSTEXT_FORCE_L1CDID_STATIC_CDID_EN_S 31
-#define GL_PSTEXT_FORCE_L1CDID_STATIC_CDID_EN_M BIT(31)
+#define GL_PSTEXT_FORCE_L1CDID_STATIC_CDID_EN_S 31
+#define GL_PSTEXT_FORCE_L1CDID_STATIC_CDID_EN_M BIT(31)
#define GL_PSTEXT_FORCE_PID(_i) (0x0020E000 + ((_i) * 4)) /* _i=0...2 */ /* Reset Source: CORER */
#define GL_PSTEXT_FORCE_PID_MAX_INDEX 2
#define GL_PSTEXT_FORCE_PID_STATIC_PID_S 0
@@ -3012,10 +3022,10 @@
#define GLFLXP_RX_CMD_LX_PROT_IDX_L4_OFFSET_INDEX_M MAKEMASK(0x7, 4)
#define GLFLXP_RX_CMD_LX_PROT_IDX_PAYLOAD_OFFSET_INDEX_S 8
#define GLFLXP_RX_CMD_LX_PROT_IDX_PAYLOAD_OFFSET_INDEX_M MAKEMASK(0x7, 8)
-#define GLFLXP_RX_CMD_LX_PROT_IDX_L3_PROTOCOL_S 12
-#define GLFLXP_RX_CMD_LX_PROT_IDX_L3_PROTOCOL_M MAKEMASK(0x3, 12)
-#define GLFLXP_RX_CMD_LX_PROT_IDX_L4_PROTOCOL_S 14
-#define GLFLXP_RX_CMD_LX_PROT_IDX_L4_PROTOCOL_M MAKEMASK(0x3, 14)
+#define GLFLXP_RX_CMD_LX_PROT_IDX_L3_PROTOCOL_S 12
+#define GLFLXP_RX_CMD_LX_PROT_IDX_L3_PROTOCOL_M MAKEMASK(0x3, 12)
+#define GLFLXP_RX_CMD_LX_PROT_IDX_L4_PROTOCOL_S 14
+#define GLFLXP_RX_CMD_LX_PROT_IDX_L4_PROTOCOL_M MAKEMASK(0x3, 14)
#define GLFLXP_RX_CMD_PROTIDS(_i, _j) (0x0045A000 + ((_i) * 4 + (_j) * 1024)) /* _i=0...255, _j=0...5 */ /* Reset Source: CORER */
#define GLFLXP_RX_CMD_PROTIDS_MAX_INDEX 255
#define GLFLXP_RX_CMD_PROTIDS_PROTID_4N_S 0
@@ -3094,8 +3104,8 @@
#define GLFLXP_TX_SCHED_CORRECT_PROTD_ID_2N_M MAKEMASK(0xFF, 0)
#define GLFLXP_TX_SCHED_CORRECT_RECIPE_2N_S 8
#define GLFLXP_TX_SCHED_CORRECT_RECIPE_2N_M MAKEMASK(0x1F, 8)
-#define GLFLXP_TX_SCHED_CORRECT_PROTD_ID_2N_1_S 16
-#define GLFLXP_TX_SCHED_CORRECT_PROTD_ID_2N_1_M MAKEMASK(0xFF, 16)
+#define GLFLXP_TX_SCHED_CORRECT_PROTD_ID_2N_1_S 16
+#define GLFLXP_TX_SCHED_CORRECT_PROTD_ID_2N_1_M MAKEMASK(0xFF, 16)
#define GLFLXP_TX_SCHED_CORRECT_RECIPE_2N_1_S 24
#define GLFLXP_TX_SCHED_CORRECT_RECIPE_2N_1_M MAKEMASK(0x1F, 24)
#define QRXFLXP_CNTXT(_QRX) (0x00480000 + ((_QRX) * 4)) /* _i=0...2047 */ /* Reset Source: CORER */
@@ -3308,18 +3318,18 @@
#define GLGEN_ANA_PROFIL_CTRL_PROFILE_SELECT_MDSTART_M MAKEMASK(0xF, 5)
#define GLGEN_ANA_PROFIL_CTRL_PROFILE_SELECT_MD_LEN_S 9
#define GLGEN_ANA_PROFIL_CTRL_PROFILE_SELECT_MD_LEN_M MAKEMASK(0x1F, 9)
-#define GLGEN_ANA_PROFIL_CTRL_NUM_CTRL_DOMAIN_S 14
-#define GLGEN_ANA_PROFIL_CTRL_NUM_CTRL_DOMAIN_M MAKEMASK(0x3, 14)
+#define GLGEN_ANA_PROFIL_CTRL_NUM_CTRL_DOMAIN_S 14
+#define GLGEN_ANA_PROFIL_CTRL_NUM_CTRL_DOMAIN_M MAKEMASK(0x3, 14)
#define GLGEN_ANA_PROFIL_CTRL_DEF_PROF_ID_S 16
#define GLGEN_ANA_PROFIL_CTRL_DEF_PROF_ID_M MAKEMASK(0xF, 16)
-#define GLGEN_ANA_PROFIL_CTRL_SEL_DEF_PROF_ID_S 20
-#define GLGEN_ANA_PROFIL_CTRL_SEL_DEF_PROF_ID_M BIT(20)
+#define GLGEN_ANA_PROFIL_CTRL_SEL_DEF_PROF_ID_S 20
+#define GLGEN_ANA_PROFIL_CTRL_SEL_DEF_PROF_ID_M BIT(20)
#define GLGEN_ANA_TX_ABORT_PTYPE 0x0020D21C /* Reset Source: CORER */
#define GLGEN_ANA_TX_ABORT_PTYPE_ABORT_S 0
#define GLGEN_ANA_TX_ABORT_PTYPE_ABORT_M MAKEMASK(0x3FF, 0)
#define GLGEN_ANA_TX_ALU_ACCSS_OUT_OF_PKT 0x0020D208 /* Reset Source: CORER */
-#define GLGEN_ANA_TX_ALU_ACCSS_OUT_OF_PKT_NPC_S 0
-#define GLGEN_ANA_TX_ALU_ACCSS_OUT_OF_PKT_NPC_M MAKEMASK(0xFF, 0)
+#define GLGEN_ANA_TX_ALU_ACCSS_OUT_OF_PKT_NPC_S 0
+#define GLGEN_ANA_TX_ALU_ACCSS_OUT_OF_PKT_NPC_M MAKEMASK(0xFF, 0)
#define GLGEN_ANA_TX_CFG_CTRL 0x0020D104 /* Reset Source: CORER */
#define GLGEN_ANA_TX_CFG_CTRL_LINE_IDX_S 0
#define GLGEN_ANA_TX_CFG_CTRL_LINE_IDX_M MAKEMASK(0x3FFFF, 0)
@@ -3345,10 +3355,10 @@
#define GLGEN_ANA_TX_CFG_RDDATA_RD_DATA_S 0
#define GLGEN_ANA_TX_CFG_RDDATA_RD_DATA_M MAKEMASK(0xFFFFFFFF, 0)
#define GLGEN_ANA_TX_CFG_SPLBUF_LU_RESULT 0x0020D15C /* Reset Source: CORER */
-#define GLGEN_ANA_TX_CFG_SPLBUF_LU_RESULT_HIT_S 0
-#define GLGEN_ANA_TX_CFG_SPLBUF_LU_RESULT_HIT_M BIT(0)
-#define GLGEN_ANA_TX_CFG_SPLBUF_LU_RESULT_RSV_S 1
-#define GLGEN_ANA_TX_CFG_SPLBUF_LU_RESULT_RSV_M MAKEMASK(0x7, 1)
+#define GLGEN_ANA_TX_CFG_SPLBUF_LU_RESULT_HIT_S 0
+#define GLGEN_ANA_TX_CFG_SPLBUF_LU_RESULT_HIT_M BIT(0)
+#define GLGEN_ANA_TX_CFG_SPLBUF_LU_RESULT_RSV_S 1
+#define GLGEN_ANA_TX_CFG_SPLBUF_LU_RESULT_RSV_M MAKEMASK(0x7, 1)
#define GLGEN_ANA_TX_CFG_SPLBUF_LU_RESULT_ADDR_S 4
#define GLGEN_ANA_TX_CFG_SPLBUF_LU_RESULT_ADDR_M MAKEMASK(0x1FF, 4)
#define GLGEN_ANA_TX_CFG_WRDATA 0x0020D108 /* Reset Source: CORER */
@@ -3667,8 +3677,8 @@
#define GLHMC_FWSDDATAHIGH_PMSDDATAHIGH_S 0
#define GLHMC_FWSDDATAHIGH_PMSDDATAHIGH_M MAKEMASK(0xFFFFFFFF, 0)
#define GLHMC_FWSDDATAHIGH_FPMAT 0x00102078 /* Reset Source: CORER */
-#define GLHMC_FWSDDATAHIGH_FPMAT_PMSDDATAHIGH_S 0
-#define GLHMC_FWSDDATAHIGH_FPMAT_PMSDDATAHIGH_M MAKEMASK(0xFFFFFFFF, 0)
+#define GLHMC_FWSDDATAHIGH_FPMAT_PMSDDATAHIGH_S 0
+#define GLHMC_FWSDDATAHIGH_FPMAT_PMSDDATAHIGH_M MAKEMASK(0xFFFFFFFF, 0)
#define GLHMC_FWSDDATALOW 0x00522074 /* Reset Source: CORER */
#define GLHMC_FWSDDATALOW_PMSDVALID_S 0
#define GLHMC_FWSDDATALOW_PMSDVALID_M BIT(0)
@@ -4066,8 +4076,8 @@
#define GLHMC_VFPEMRCNT_FPMPEMRSZ_M MAKEMASK(0x1FFFFFFF, 0)
#define GLHMC_VFPEOOISCBASE(_i) (0x0052E600 + ((_i) * 4)) /* _i=0...31 */ /* Reset Source: CORER */
#define GLHMC_VFPEOOISCBASE_MAX_INDEX 31
-#define GLHMC_VFPEOOISCBASE_GLHMC_PEOOISCBASE_S 0
-#define GLHMC_VFPEOOISCBASE_GLHMC_PEOOISCBASE_M MAKEMASK(0xFFFFFFFF, 0)
+#define GLHMC_VFPEOOISCBASE_GLHMC_PEOOISCBASE_S 0
+#define GLHMC_VFPEOOISCBASE_GLHMC_PEOOISCBASE_M MAKEMASK(0xFFFFFFFF, 0)
#define GLHMC_VFPEOOISCCNT(_i) (0x0052E700 + ((_i) * 4)) /* _i=0...31 */ /* Reset Source: CORER */
#define GLHMC_VFPEOOISCCNT_MAX_INDEX 31
#define GLHMC_VFPEOOISCCNT_GLHMC_PEOOISCCNT_S 0
@@ -4114,8 +4124,8 @@
#define GLHMC_VFPERRFCNT_GLHMC_PERRFCNT_M MAKEMASK(0xFFFFFFFF, 0)
#define GLHMC_VFPERRFFLBASE(_i) (0x0052EA00 + ((_i) * 4)) /* _i=0...31 */ /* Reset Source: CORER */
#define GLHMC_VFPERRFFLBASE_MAX_INDEX 31
-#define GLHMC_VFPERRFFLBASE_GLHMC_PERRFFLBASE_S 0
-#define GLHMC_VFPERRFFLBASE_GLHMC_PERRFFLBASE_M MAKEMASK(0xFFFFFFFF, 0)
+#define GLHMC_VFPERRFFLBASE_GLHMC_PERRFFLBASE_S 0
+#define GLHMC_VFPERRFFLBASE_GLHMC_PERRFFLBASE_M MAKEMASK(0xFFFFFFFF, 0)
#define GLHMC_VFPETIMERBASE(_i) (0x0052DA00 + ((_i) * 4)) /* _i=0...31 */ /* Reset Source: CORER */
#define GLHMC_VFPETIMERBASE_MAX_INDEX 31
#define GLHMC_VFPETIMERBASE_FPMPETIMERBASE_S 0
@@ -4142,8 +4152,8 @@
#define GLHMC_VFSDDATAHIGH_PMSDDATAHIGH_M MAKEMASK(0xFFFFFFFF, 0)
#define GLHMC_VFSDDATAHIGH_FPMAT(_i) (0x00108200 + ((_i) * 4)) /* _i=0...31 */ /* Reset Source: CORER */
#define GLHMC_VFSDDATAHIGH_FPMAT_MAX_INDEX 31
-#define GLHMC_VFSDDATAHIGH_FPMAT_PMSDDATAHIGH_S 0
-#define GLHMC_VFSDDATAHIGH_FPMAT_PMSDDATAHIGH_M MAKEMASK(0xFFFFFFFF, 0)
+#define GLHMC_VFSDDATAHIGH_FPMAT_PMSDDATAHIGH_S 0
+#define GLHMC_VFSDDATAHIGH_FPMAT_PMSDDATAHIGH_M MAKEMASK(0xFFFFFFFF, 0)
#define GLHMC_VFSDDATALOW(_i) (0x00528100 + ((_i) * 4)) /* _i=0...31 */ /* Reset Source: CORER */
#define GLHMC_VFSDDATALOW_MAX_INDEX 31
#define GLHMC_VFSDDATALOW_PMSDVALID_S 0
@@ -4249,8 +4259,8 @@
#define PFHMC_ERRORINFO_FPMAT_PMF_ISVF_M BIT(7)
#define PFHMC_ERRORINFO_FPMAT_HMC_ERROR_TYPE_S 8
#define PFHMC_ERRORINFO_FPMAT_HMC_ERROR_TYPE_M MAKEMASK(0xF, 8)
-#define PFHMC_ERRORINFO_FPMAT_HMC_OBJECT_TYPE_S 16
-#define PFHMC_ERRORINFO_FPMAT_HMC_OBJECT_TYPE_M MAKEMASK(0x1F, 16)
+#define PFHMC_ERRORINFO_FPMAT_HMC_OBJECT_TYPE_S 16
+#define PFHMC_ERRORINFO_FPMAT_HMC_OBJECT_TYPE_M MAKEMASK(0x1F, 16)
#define PFHMC_ERRORINFO_FPMAT_ERROR_DETECTED_S 31
#define PFHMC_ERRORINFO_FPMAT_ERROR_DETECTED_M BIT(31)
#define PFHMC_PDINV 0x00520300 /* Reset Source: PFR */
@@ -4337,8 +4347,8 @@
#define GL_MDCK_TDAT_TCLAN_TSO_SUM_BUFFS_LT_SUM_HDRS_M BIT(11)
#define GL_MDCK_TDAT_TCLAN_TSO_ZERO_MSS_TLEN_HDRS_S 12
#define GL_MDCK_TDAT_TCLAN_TSO_ZERO_MSS_TLEN_HDRS_M BIT(12)
-#define GL_MDCK_TDAT_TCLAN_TSO_CTX_DESC_IPSEC_S 13
-#define GL_MDCK_TDAT_TCLAN_TSO_CTX_DESC_IPSEC_M BIT(13)
+#define GL_MDCK_TDAT_TCLAN_TSO_CTX_DESC_IPSEC_S 13
+#define GL_MDCK_TDAT_TCLAN_TSO_CTX_DESC_IPSEC_M BIT(13)
#define GL_MDCK_TDAT_TCLAN_SSO_COMS_NOT_WHOLE_PKT_NUM_IN_QUANTA_S 14
#define GL_MDCK_TDAT_TCLAN_SSO_COMS_NOT_WHOLE_PKT_NUM_IN_QUANTA_M BIT(14)
#define GL_MDCK_TDAT_TCLAN_COMS_QUANTA_BYTES_EXCEED_PKTLEN_X_64_S 15
@@ -5233,10 +5243,10 @@
#define PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL 0x001E36C0 /* Reset Source: GLOBR */
#define PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_S 0
#define PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_M BIT(0)
-#define PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1 0x001E3220 /* Reset Source: GLOBR */
+#define PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1 0x001E3220 /* Reset Source: GLOBR */
#define PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_S 0
#define PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_M MAKEMASK(0xFFFFFFFF, 0)
-#define PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2 0x001E3240 /* Reset Source: GLOBR */
+#define PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2 0x001E3240 /* Reset Source: GLOBR */
#define PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_S 0
#define PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_M MAKEMASK(0xFFFF, 0)
#define PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE 0x001E3180 /* Reset Source: GLOBR */
@@ -5337,10 +5347,10 @@
#define GL_MDCK_EN_TX_PQM_SSO_PKTCNT_EXCEED_M BIT(17)
#define GL_MDCK_EN_TX_PQM_SSO_NUMDESCS_ZERO_S 18
#define GL_MDCK_EN_TX_PQM_SSO_NUMDESCS_ZERO_M BIT(18)
-#define GL_MDCK_EN_TX_PQM_SSO_NUMDESCS_EXCEED_S 19
-#define GL_MDCK_EN_TX_PQM_SSO_NUMDESCS_EXCEED_M BIT(19)
-#define GL_MDCK_EN_TX_PQM_TAIL_GT_RING_LENGTH_S 20
-#define GL_MDCK_EN_TX_PQM_TAIL_GT_RING_LENGTH_M BIT(20)
+#define GL_MDCK_EN_TX_PQM_SSO_NUMDESCS_EXCEED_S 19
+#define GL_MDCK_EN_TX_PQM_SSO_NUMDESCS_EXCEED_M BIT(19)
+#define GL_MDCK_EN_TX_PQM_TAIL_GT_RING_LENGTH_S 20
+#define GL_MDCK_EN_TX_PQM_TAIL_GT_RING_LENGTH_M BIT(20)
#define GL_MDCK_EN_TX_PQM_RESERVED_DBL_TYPE_S 21
#define GL_MDCK_EN_TX_PQM_RESERVED_DBL_TYPE_M BIT(21)
#define GL_MDCK_EN_TX_PQM_ILLEGAL_HEAD_DROP_DBL_S 22
@@ -5359,8 +5369,8 @@
#define GL_MDCK_TX_TDPU 0x00049348 /* Reset Source: CORER */
#define GL_MDCK_TX_TDPU_TTL_ERR_ITR_DIS_S 0
#define GL_MDCK_TX_TDPU_TTL_ERR_ITR_DIS_M BIT(0)
-#define GL_MDCK_TX_TDPU_RCU_ANTISPOOF_ITR_DIS_S 1
-#define GL_MDCK_TX_TDPU_RCU_ANTISPOOF_ITR_DIS_M BIT(1)
+#define GL_MDCK_TX_TDPU_RCU_ANTISPOOF_ITR_DIS_S 1
+#define GL_MDCK_TX_TDPU_RCU_ANTISPOOF_ITR_DIS_M BIT(1)
#define GL_MDCK_TX_TDPU_PCIE_UR_ITR_DIS_S 2
#define GL_MDCK_TX_TDPU_PCIE_UR_ITR_DIS_M BIT(2)
#define GL_MDCK_TX_TDPU_MAL_OFFSET_ITR_DIS_S 3
@@ -5373,8 +5383,8 @@
#define GL_MDCK_TX_TDPU_L2_ACCEPT_FAIL_ITR_DIS_M BIT(6)
#define GL_MDCK_TX_TDPU_NIC_DSI_ITR_DIS_S 7
#define GL_MDCK_TX_TDPU_NIC_DSI_ITR_DIS_M BIT(7)
-#define GL_MDCK_TX_TDPU_MAL_IPSEC_CMD_ITR_DIS_S 8
-#define GL_MDCK_TX_TDPU_MAL_IPSEC_CMD_ITR_DIS_M BIT(8)
+#define GL_MDCK_TX_TDPU_MAL_IPSEC_CMD_ITR_DIS_S 8
+#define GL_MDCK_TX_TDPU_MAL_IPSEC_CMD_ITR_DIS_M BIT(8)
#define GL_MDCK_TX_TDPU_DSCP_CHECK_FAIL_ITR_DIS_S 9
#define GL_MDCK_TX_TDPU_DSCP_CHECK_FAIL_ITR_DIS_M BIT(9)
#define GL_MDCK_TX_TDPU_NIC_IPSEC_ITR_DIS_S 10
@@ -5456,8 +5466,8 @@
#define VP_MDET_TX_TDPU_VALID_M BIT(0)
#define GENERAL_MNG_FW_DBG_CSR(_i) (0x000B6180 + ((_i) * 4)) /* _i=0...9 */ /* Reset Source: POR */
#define GENERAL_MNG_FW_DBG_CSR_MAX_INDEX 9
-#define GENERAL_MNG_FW_DBG_CSR_GENERAL_FW_DBG_S 0
-#define GENERAL_MNG_FW_DBG_CSR_GENERAL_FW_DBG_M MAKEMASK(0xFFFFFFFF, 0)
+#define GENERAL_MNG_FW_DBG_CSR_GENERAL_FW_DBG_S 0
+#define GENERAL_MNG_FW_DBG_CSR_GENERAL_FW_DBG_M MAKEMASK(0xFFFFFFFF, 0)
#define GL_FWRESETCNT 0x00083100 /* Reset Source: POR */
#define GL_FWRESETCNT_FWRESETCNT_S 0
#define GL_FWRESETCNT_FWRESETCNT_M MAKEMASK(0xFFFFFFFF, 0)
@@ -5869,8 +5879,8 @@
#define GL_XLR_MARKER_TRIG_RCU_PRS 0x002001C0 /* Reset Source: CORER */
#define GL_XLR_MARKER_TRIG_RCU_PRS_VM_VF_NUM_S 0
#define GL_XLR_MARKER_TRIG_RCU_PRS_VM_VF_NUM_M MAKEMASK(0x3FF, 0)
-#define GL_XLR_MARKER_TRIG_RCU_PRS_VM_VF_TYPE_S 10
-#define GL_XLR_MARKER_TRIG_RCU_PRS_VM_VF_TYPE_M MAKEMASK(0x3, 10)
+#define GL_XLR_MARKER_TRIG_RCU_PRS_VM_VF_TYPE_S 10
+#define GL_XLR_MARKER_TRIG_RCU_PRS_VM_VF_TYPE_M MAKEMASK(0x3, 10)
#define GL_XLR_MARKER_TRIG_RCU_PRS_PF_NUM_S 12
#define GL_XLR_MARKER_TRIG_RCU_PRS_PF_NUM_M MAKEMASK(0x7, 12)
#define GL_XLR_MARKER_TRIG_RCU_PRS_PORT_NUM_S 16
@@ -6749,11 +6759,11 @@
#define GLPES_RDMARXUNALIGN_RDMRXAUNALIGN_S 0
#define GLPES_RDMARXUNALIGN_RDMRXAUNALIGN_M MAKEMASK(0xFFFFFFFF, 0)
#define GLPES_TCPRXFOURHOLEHI 0x0055E03C /* Reset Source: CORER */
-#define GLPES_TCPRXFOURHOLEHI_TCPRXFOURHOLEHI_S 0
-#define GLPES_TCPRXFOURHOLEHI_TCPRXFOURHOLEHI_M MAKEMASK(0xFFFFFF, 0)
+#define GLPES_TCPRXFOURHOLEHI_TCPRXFOURHOLEHI_S 0
+#define GLPES_TCPRXFOURHOLEHI_TCPRXFOURHOLEHI_M MAKEMASK(0xFFFFFF, 0)
#define GLPES_TCPRXFOURHOLELO 0x0055E038 /* Reset Source: CORER */
-#define GLPES_TCPRXFOURHOLELO_TCPRXFOURHOLELO_S 0
-#define GLPES_TCPRXFOURHOLELO_TCPRXFOURHOLELO_M MAKEMASK(0xFFFFFFFF, 0)
+#define GLPES_TCPRXFOURHOLELO_TCPRXFOURHOLELO_S 0
+#define GLPES_TCPRXFOURHOLELO_TCPRXFOURHOLELO_M MAKEMASK(0xFFFFFFFF, 0)
#define GLPES_TCPRXONEHOLEHI 0x0055E024 /* Reset Source: CORER */
#define GLPES_TCPRXONEHOLEHI_TCPRXONEHOLEHI_S 0
#define GLPES_TCPRXONEHOLEHI_TCPRXONEHOLEHI_M MAKEMASK(0xFFFFFF, 0)
@@ -8234,7 +8244,7 @@
#define TPB_PRTTPB_STAT_PKT_SENT_PKTCNT_S 0
#define TPB_PRTTPB_STAT_PKT_SENT_PKTCNT_M MAKEMASK(0xFFFFFFFF, 0)
#define TPB_PRTTPB_STAT_TC_BYTES_SENT(_i) (0x00099094 + ((_i) * 4)) /* _i=0...63 */ /* Reset Source: CORER */
-#define TPB_PRTTPB_STAT_TC_BYTES_SENT_MAX_INDEX 63
+#define TPB_PRTTPB_STAT_TC_BYTES_SENT_MAX_INDEX 63
#define TPB_PRTTPB_STAT_TC_BYTES_SENT_TCCNT_S 0
#define TPB_PRTTPB_STAT_TC_BYTES_SENT_TCCNT_M MAKEMASK(0xFFFFFFFF, 0)
#define EMP_SWT_PRUNIND 0x00204020 /* Reset Source: CORER */
@@ -9476,5 +9486,5 @@
#define VFPE_WQEALLOC1_PEQPID_M MAKEMASK(0x3FFFF, 0)
#define VFPE_WQEALLOC1_WQE_DESC_INDEX_S 20
#define VFPE_WQEALLOC1_WQE_DESC_INDEX_M MAKEMASK(0xFFF, 20)
+#endif /* !_ICE_HW_AUTOGEN_H_ */
-#endif
diff --git a/sys/dev/ice/ice_iflib.h b/sys/dev/ice/ice_iflib.h
index 7864a7a1ebfa..947881f1d076 100644
--- a/sys/dev/ice/ice_iflib.h
+++ b/sys/dev/ice/ice_iflib.h
@@ -137,6 +137,8 @@ struct ice_irq_vector {
* @tx_paddr: the physical address for this queue
* @q_teid: the Tx queue TEID returned from firmware
* @stats: queue statistics
+ * @tc: traffic class queue belongs to
+ * @q_handle: qidx in tc; used in TXQ enable functions
*
* Other parameters may be iflib driver specific
*/
@@ -151,6 +153,8 @@ struct ice_tx_queue {
struct ice_irq_vector *irqv;
u32 q_teid;
u32 me;
+ u16 q_handle;
+ u8 tc;
/* descriptor writeback status */
qidx_t *tx_rsq;
@@ -171,6 +175,7 @@ struct ice_tx_queue {
* @rx_paddr: the physical address for this queue
* @tail: the tail register address for this queue
* @stats: queue statistics
+ * @tc: traffic class queue belongs to
*
* Other parameters may be iflib driver specific
*/
@@ -183,6 +188,7 @@ struct ice_rx_queue {
u32 tail;
struct ice_irq_vector *irqv;
u32 me;
+ u8 tc;
struct if_irq que_irq;
};
diff --git a/sys/dev/ice/ice_iflib_txrx.c b/sys/dev/ice/ice_iflib_txrx.c
index 0ce59d96c0ed..52c4364a2430 100644
--- a/sys/dev/ice/ice_iflib_txrx.c
+++ b/sys/dev/ice/ice_iflib_txrx.c
@@ -55,6 +55,7 @@ static int ice_ift_txd_credits_update(void *arg, uint16_t txqid, bool clear);
static int ice_ift_rxd_available(void *arg, uint16_t rxqid, qidx_t pidx, qidx_t budget);
static void ice_ift_rxd_flush(void *arg, uint16_t rxqid, uint8_t flidx, qidx_t pidx);
static void ice_ift_rxd_refill(void *arg, if_rxd_update_t iru);
+static qidx_t ice_ift_queue_select(void *arg, struct mbuf *m);
/* Macro to help extract the NIC mode flexible Rx descriptor fields from the
* advanced 32byte Rx descriptors.
@@ -78,6 +79,7 @@ struct if_txrx ice_txrx = {
.ift_rxd_pkt_get = ice_ift_rxd_pkt_get,
.ift_rxd_refill = ice_ift_rxd_refill,
.ift_rxd_flush = ice_ift_rxd_flush,
+ .ift_txq_select = ice_ift_queue_select,
};
/**
@@ -276,7 +278,7 @@ ice_ift_rxd_available(void *arg, uint16_t rxqid, qidx_t pidx, qidx_t budget)
*
* This function is called by iflib, and executes in ithread context. It is
* called by iflib to obtain data which has been DMA'ed into host memory.
- * Returns zero on success, and an error code on failure.
+ * Returns zero on success, and EBADMSG on failure.
*/
static int
ice_ift_rxd_pkt_get(void *arg, if_rxd_info_t ri)
@@ -300,8 +302,6 @@ ice_ift_rxd_pkt_get(void *arg, if_rxd_info_t ri)
status0 = le16toh(cur->wb.status_error0);
plen = le16toh(cur->wb.pkt_len) &
ICE_RX_FLX_DESC_PKT_LEN_M;
- ptype = le16toh(cur->wb.ptype_flex_flags0) &
- ICE_RX_FLEX_DESC_PTYPE_M;
/* we should never be called without a valid descriptor */
MPASS((status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_DD_S)) != 0);
@@ -311,14 +311,6 @@ ice_ift_rxd_pkt_get(void *arg, if_rxd_info_t ri)
cur->wb.status_error0 = 0;
eop = (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_EOF_S));
- /*
- * Make sure packets with bad L2 values are discarded.
- * NOTE: Only the EOP descriptor has valid error results.
- */
- if (eop && (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_RXE_S))) {
- rxq->stats.desc_errs++;
- return (EBADMSG);
- }
ri->iri_frags[i].irf_flid = 0;
ri->iri_frags[i].irf_idx = cidx;
ri->iri_frags[i].irf_len = plen;
@@ -327,19 +319,36 @@ ice_ift_rxd_pkt_get(void *arg, if_rxd_info_t ri)
i++;
} while (!eop);
- /* capture soft statistics for this Rx queue */
+ /* End of Packet reached; cur is eop/last descriptor */
+
+ /* Make sure packets with bad L2 values are discarded.
+ * This bit is only valid in the last descriptor.
+ */
+ if (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_RXE_S)) {
+ rxq->stats.desc_errs++;
+ return (EBADMSG);
+ }
+
+ /* Get VLAN tag information if one is in descriptor */
+ if (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_L2TAG1P_S)) {
+ ri->iri_vtag = le16toh(cur->wb.l2tag1);
+ ri->iri_flags |= M_VLANTAG;
+ }
+
+ /* Capture soft statistics for this Rx queue */
rxq->stats.rx_packets++;
rxq->stats.rx_bytes += ri->iri_len;
+ /* Get packet type and set checksum flags */
+ ptype = le16toh(cur->wb.ptype_flex_flags0) &
+ ICE_RX_FLEX_DESC_PTYPE_M;
if ((scctx->isc_capenable & IFCAP_RXCSUM) != 0)
ice_rx_checksum(rxq, &ri->iri_csum_flags,
&ri->iri_csum_data, status0, ptype);
+
+ /* Set remaining iflib RX descriptor info fields */
ri->iri_flowid = le32toh(RX_FLEX_NIC(&cur->wb, rss_hash));
ri->iri_rsstype = ice_ptype_to_hash(ptype);
- if (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_L2TAG1P_S)) {
- ri->iri_vtag = le16toh(cur->wb.l2tag1);
- ri->iri_flags |= M_VLANTAG;
- }
ri->iri_nfrags = i;
return (0);
}
@@ -397,3 +406,44 @@ ice_ift_rxd_flush(void *arg, uint16_t rxqid, uint8_t flidx __unused,
wr32(hw, rxq->tail, pidx);
}
+
+static qidx_t
+ice_ift_queue_select(void *arg, struct mbuf *m)
+{
+ struct ice_softc *sc = (struct ice_softc *)arg;
+ struct ice_vsi *vsi = &sc->pf_vsi;
+ u16 tc_base_queue, tc_qcount;
+ u8 up, tc;
+
+#ifdef ALTQ
+ /* Included to match default iflib behavior */
+ /* Only go out on default queue if ALTQ is enabled */
+ struct ifnet *ifp = (struct ifnet *)iflib_get_ifp(sc->ctx);
+ if (ALTQ_IS_ENABLED(&ifp->if_snd))
+ return (0);
+#endif
+
+ if (!ice_test_state(&sc->state, ICE_STATE_MULTIPLE_TCS)) {
+ if (M_HASHTYPE_GET(m)) {
+ /* Default iflib queue selection method */
+ return (m->m_pkthdr.flowid % sc->pf_vsi.num_tx_queues);
+ } else
+ return (0);
+ }
+
+ /* Use default TC unless overridden */
+ tc = 0; /* XXX: Get default TC for traffic if >1 TC? */
+
+ if (m->m_flags & M_VLANTAG) {
+ up = EVL_PRIOFTAG(m->m_pkthdr.ether_vtag);
+ tc = sc->hw.port_info->qos_cfg.local_dcbx_cfg.etscfg.prio_table[up];
+ }
+
+ tc_base_queue = vsi->tc_info[tc].qoffset;
+ tc_qcount = vsi->tc_info[tc].qcount_tx;
+
+ if (M_HASHTYPE_GET(m))
+ return ((m->m_pkthdr.flowid % tc_qcount) + tc_base_queue);
+ else
+ return (tc_base_queue);
+}
diff --git a/sys/dev/ice/ice_lan_tx_rx.h b/sys/dev/ice/ice_lan_tx_rx.h
index 6e3051719a24..5cc611fef25f 100644
--- a/sys/dev/ice/ice_lan_tx_rx.h
+++ b/sys/dev/ice/ice_lan_tx_rx.h
@@ -280,7 +280,6 @@ enum ice_rx_l2_ptype {
};
struct ice_rx_ptype_decoded {
- u32 ptype:10;
u32 known:1;
u32 outer_ip:1;
u32 outer_ip_ver:2;
@@ -794,6 +793,15 @@ enum ice_rx_flex_desc_exstat_bits {
ICE_RX_FLEX_DESC_EXSTAT_OVERSIZE_S = 3,
};
+/*
+ * For ice_32b_rx_flex_desc.ts_low:
+ * [0]: Timestamp-low validity bit
+ * [1:7]: Timestamp-low value
+ */
+#define ICE_RX_FLEX_DESC_TS_L_VALID_S 0x01
+#define ICE_RX_FLEX_DESC_TS_L_VALID_M ICE_RX_FLEX_DESC_TS_L_VALID_S
+#define ICE_RX_FLEX_DESC_TS_L_M 0xFE
+
#define ICE_RXQ_CTX_SIZE_DWORDS 8
#define ICE_RXQ_CTX_SZ (ICE_RXQ_CTX_SIZE_DWORDS * sizeof(u32))
#define ICE_TX_CMPLTNQ_CTX_SIZE_DWORDS 22
@@ -940,6 +948,11 @@ struct ice_tx_ctx_desc {
__le64 qw1;
};
+#define ICE_TX_GSC_DESC_START 0 /* 7 BITS */
+#define ICE_TX_GSC_DESC_OFFSET 7 /* 4 BITS */
+#define ICE_TX_GSC_DESC_TYPE 11 /* 2 BITS */
+#define ICE_TX_GSC_DESC_ENA 13 /* 1 BIT */
+
#define ICE_TXD_CTX_QW1_DTYPE_S 0
#define ICE_TXD_CTX_QW1_DTYPE_M (0xFUL << ICE_TXD_CTX_QW1_DTYPE_S)
@@ -1162,8 +1175,7 @@ struct ice_tx_drbell_q_ctx {
/* macro to make the table lines short */
#define ICE_PTT(PTYPE, OUTER_IP, OUTER_IP_VER, OUTER_FRAG, T, TE, TEF, I, PL)\
- { PTYPE, \
- 1, \
+ { 1, \
ICE_RX_PTYPE_OUTER_##OUTER_IP, \
ICE_RX_PTYPE_OUTER_##OUTER_IP_VER, \
ICE_RX_PTYPE_##OUTER_FRAG, \
@@ -1173,14 +1185,14 @@ struct ice_tx_drbell_q_ctx {
ICE_RX_PTYPE_INNER_PROT_##I, \
ICE_RX_PTYPE_PAYLOAD_LAYER_##PL }
-#define ICE_PTT_UNUSED_ENTRY(PTYPE) { PTYPE, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+#define ICE_PTT_UNUSED_ENTRY(PTYPE) { 0, 0, 0, 0, 0, 0, 0, 0, 0 }
/* shorter macros makes the table fit but are terse */
#define ICE_RX_PTYPE_NOF ICE_RX_PTYPE_NOT_FRAG
#define ICE_RX_PTYPE_FRG ICE_RX_PTYPE_FRAG
-/* Lookup table mapping the HW PTYPE to the bit field for decoding */
-static const struct ice_rx_ptype_decoded ice_ptype_lkup[] = {
+/* Lookup table mapping the 10-bit HW PTYPE to the bit field for decoding */
+static const struct ice_rx_ptype_decoded ice_ptype_lkup[1024] = {
/* L2 Packet types */
ICE_PTT_UNUSED_ENTRY(0),
ICE_PTT(1, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
@@ -2342,7 +2354,7 @@ static const struct ice_rx_ptype_decoded ice_ptype_lkup[] = {
ICE_PTT_UNUSED_ENTRY(1020),
ICE_PTT_UNUSED_ENTRY(1021),
ICE_PTT_UNUSED_ENTRY(1022),
- ICE_PTT_UNUSED_ENTRY(1023),
+ ICE_PTT_UNUSED_ENTRY(1023)
};
static inline struct ice_rx_ptype_decoded ice_decode_rx_desc_ptype(u16 ptype)
@@ -2362,5 +2374,4 @@ static inline struct ice_rx_ptype_decoded ice_decode_rx_desc_ptype(u16 ptype)
#define ICE_LINK_SPEED_40000MBPS 40000
#define ICE_LINK_SPEED_50000MBPS 50000
#define ICE_LINK_SPEED_100000MBPS 100000
-
#endif /* _ICE_LAN_TX_RX_H_ */
diff --git a/sys/dev/ice/ice_lib.c b/sys/dev/ice/ice_lib.c
index ecea51a95ae4..501c39eb3986 100644
--- a/sys/dev/ice/ice_lib.c
+++ b/sys/dev/ice/ice_lib.c
@@ -106,6 +106,15 @@ static uint64_t ice_phy_types_to_max_rate(struct ice_port_info *pi);
static void ice_add_sysctls_sw_stats(struct ice_vsi *vsi,
struct sysctl_ctx_list *ctx,
struct sysctl_oid *parent);
+static void
+ice_add_sysctls_mac_pfc_one_stat(struct sysctl_ctx_list *ctx,
+ struct sysctl_oid_list *parent_list,
+ u64* pfc_stat_location,
+ const char *node_name,
+ const char *descr);
+static void ice_add_sysctls_mac_pfc_stats(struct sysctl_ctx_list *ctx,
+ struct sysctl_oid *parent,
+ struct ice_hw_port_stats *stats);
static void ice_setup_vsi_common(struct ice_softc *sc, struct ice_vsi *vsi,
enum ice_vsi_type type, int idx,
bool dynamic);
@@ -141,13 +150,31 @@ ice_print_ldo_tlv(struct ice_softc *sc,
static void
ice_sysctl_speeds_to_aq_phy_types(u16 sysctl_speeds, u64 *phy_type_low,
u64 *phy_type_high);
-static u16 ice_apply_supported_speed_filter(u16 report_speeds);
+static u16 ice_apply_supported_speed_filter(u16 report_speeds, u8 mod_type);
static void
ice_handle_health_status_event(struct ice_softc *sc,
struct ice_rq_event_info *event);
static void
ice_print_health_status_string(device_t dev,
struct ice_aqc_health_status_elem *elem);
+static void
+ice_debug_print_mib_change_event(struct ice_softc *sc,
+ struct ice_rq_event_info *event);
+static bool ice_check_ets_bw(u8 *table);
+static bool
+ice_dcb_needs_reconfig(struct ice_softc *sc, struct ice_dcbx_cfg *old_cfg,
+ struct ice_dcbx_cfg *new_cfg);
+static void ice_dcb_recfg(struct ice_softc *sc);
+static u8 ice_dcb_num_tc(u8 tc_map);
+static int ice_ets_str_to_tbl(const char *str, u8 *table, u8 limit);
+static int ice_pf_vsi_cfg_tc(struct ice_softc *sc, u8 tc_map);
+static void ice_sbuf_print_ets_cfg(struct sbuf *sbuf, const char *name,
+ struct ice_dcb_ets_cfg *ets);
+static void ice_stop_pf_vsi(struct ice_softc *sc);
+static void ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt);
+static void ice_do_dcb_reconfig(struct ice_softc *sc);
+static int ice_config_pfc(struct ice_softc *sc, u8 new_mode);
+static u8 ice_dcb_get_tc_map(const struct ice_dcbx_cfg *dcbcfg);
static int ice_module_init(void);
static int ice_module_exit(void);
@@ -195,6 +222,12 @@ static int ice_sysctl_tx_cso_stat(SYSCTL_HANDLER_ARGS);
static int ice_sysctl_rx_cso_stat(SYSCTL_HANDLER_ARGS);
static int ice_sysctl_pba_number(SYSCTL_HANDLER_ARGS);
static int ice_sysctl_rx_errors_stat(SYSCTL_HANDLER_ARGS);
+static int ice_sysctl_dump_dcbx_cfg(SYSCTL_HANDLER_ARGS);
+static int ice_sysctl_dump_vsi_cfg(SYSCTL_HANDLER_ARGS);
+static int ice_sysctl_ets_min_rate(SYSCTL_HANDLER_ARGS);
+static int ice_sysctl_up2tc_map(SYSCTL_HANDLER_ARGS);
+static int ice_sysctl_pfc_config(SYSCTL_HANDLER_ARGS);
+static int ice_sysctl_query_port_ets(SYSCTL_HANDLER_ARGS);
/**
* ice_map_bar - Map PCIe BAR memory
@@ -607,7 +640,7 @@ ice_initialize_vsi(struct ice_vsi *vsi)
}
vsi->info = ctx.info;
- /* TODO: DCB traffic class support? */
+ /* Initialize VSI with just 1 TC to start */
max_txqs[0] = vsi->num_tx_queues;
status = ice_cfg_vsi_lan(hw->port_info, vsi->idx,
@@ -691,7 +724,12 @@ ice_release_vsi(struct ice_vsi *vsi)
ice_del_vsi_sysctl_ctx(vsi);
- ice_deinit_vsi(vsi);
+ /*
+ * If we unload the driver after a reset fails, we do not need to do
+ * this step.
+ */
+ if (!ice_test_state(&sc->state, ICE_STATE_RESET_FAILED))
+ ice_deinit_vsi(vsi);
ice_free_vsi_qmaps(vsi);
@@ -1420,12 +1458,14 @@ ice_cfg_vsi_for_tx(struct ice_vsi *vsi)
ice_set_ctx(hw, (u8 *)&tlan_ctx, qg->txqs[0].txq_ctx,
ice_tlan_ctx_info);
- status = ice_ena_vsi_txq(hw->port_info, vsi->idx, 0,
- i, 1, qg, qg_size, NULL);
+ status = ice_ena_vsi_txq(hw->port_info, vsi->idx, txq->tc,
+ txq->q_handle, 1, qg, qg_size, NULL);
if (status) {
device_printf(dev,
- "Failed to set LAN Tx queue context, err %s aq_err %s\n",
- ice_status_str(status), ice_aq_str(hw->adminq.sq_last_status));
+ "Failed to set LAN Tx queue %d (TC %d, handle %d) context, err %s aq_err %s\n",
+ i, txq->tc, txq->q_handle,
+ ice_status_str(status),
+ ice_aq_str(hw->adminq.sq_last_status));
err = ENODEV;
goto free_txqg;
}
@@ -1986,6 +2026,9 @@ ice_process_ctrlq_event(struct ice_softc *sc, const char *qname,
case ice_mbx_opc_send_msg_to_pf:
/* TODO: handle IOV event */
break;
+ case ice_aqc_opc_fw_logs_event:
+ ice_handle_fw_log_event(sc, &event->desc, event->msg_buf);
+ break;
case ice_aqc_opc_lldp_set_mib_change:
ice_handle_mib_change_event(sc, event);
break;
@@ -2347,6 +2390,11 @@ ice_update_pf_stats(struct ice_softc *sc)
cur_ps = &sc->stats.cur;
lport = hw->port_info->lport;
+#define ICE_PF_STAT_PFC(name, location, index) \
+ ice_stat_update40(hw, name(lport, index), \
+ sc->stats.offsets_loaded, \
+ &prev_ps->location[index], &cur_ps->location[index])
+
#define ICE_PF_STAT40(name, location) \
ice_stat_update40(hw, name ## L(lport), \
sc->stats.offsets_loaded, \
@@ -2386,6 +2434,15 @@ ice_update_pf_stats(struct ice_softc *sc)
ICE_PF_STAT40(GLPRT_PTC1522, tx_size_1522);
ICE_PF_STAT40(GLPRT_PTC9522, tx_size_big);
+ /* Update Priority Flow Control Stats */
+ for (int i = 0; i <= GLPRT_PXOFFRXC_MAX_INDEX; i++) {
+ ICE_PF_STAT_PFC(GLPRT_PXONRXC, priority_xon_rx, i);
+ ICE_PF_STAT_PFC(GLPRT_PXOFFRXC, priority_xoff_rx, i);
+ ICE_PF_STAT_PFC(GLPRT_PXONTXC, priority_xon_tx, i);
+ ICE_PF_STAT_PFC(GLPRT_PXOFFTXC, priority_xoff_tx, i);
+ ICE_PF_STAT_PFC(GLPRT_RXON2OFFCNT, priority_xon_2_xoff, i);
+ }
+
ICE_PF_STAT32(GLPRT_LXONRXC, link_xon_rx);
ICE_PF_STAT32(GLPRT_LXOFFRXC, link_xoff_rx);
ICE_PF_STAT32(GLPRT_LXONTXC, link_xon_tx);
@@ -2402,6 +2459,7 @@ ice_update_pf_stats(struct ice_softc *sc)
#undef ICE_PF_STAT40
#undef ICE_PF_STAT32
+#undef ICE_PF_STAT_PFC
sc->stats.offsets_loaded = true;
}
@@ -2912,7 +2970,8 @@ ice_intersect_phy_types_and_speeds(struct ice_softc *sc,
report_speeds = ice_aq_phy_types_to_link_speeds(phy_data->phy_low_orig,
phy_data->phy_high_orig);
if (apply_speed_filter) {
- temp_speeds = ice_apply_supported_speed_filter(report_speeds);
+ temp_speeds = ice_apply_supported_speed_filter(report_speeds,
+ pcaps.module_type[0]);
if ((phy_data->user_speeds_orig & temp_speeds) == 0) {
device_printf(sc->dev,
"User-specified speeds (\"0x%04X\") not supported\n",
@@ -3202,9 +3261,18 @@ ice_sysctl_fc_config(SYSCTL_HANDLER_ARGS)
}
}
- /* Set the flow control mode in FW */
+ /* Save flow control mode from user */
pi->phy.curr_user_fc_req = new_mode;
+ /* Turn off Priority Flow Control when Link Flow Control is enabled */
+ if ((hw->port_info->qos_cfg.is_sw_lldp) &&
+ (hw->port_info->qos_cfg.local_dcbx_cfg.pfc.pfcena != 0) &&
+ (new_mode != ICE_FC_NONE)) {
+ ret = ice_config_pfc(sc, 0x0);
+ if (ret)
+ return (ret);
+ }
+
/* Apply settings requested by user */
return ice_apply_saved_phy_cfg(sc, ICE_APPLY_FC);
}
@@ -3682,6 +3750,321 @@ retry_start_lldp:
return (ret);
}
+#define ICE_SYSCTL_HELP_ETS_MIN_RATE \
+"\nIn FW DCB mode (fw_lldp_agent=1), displays the current ETS bandwidth table." \
+"\nIn SW DCB mode, displays and allows setting the table." \
+"\nInput must be in the format e.g. 30,10,10,10,10,10,10,10" \
+"\nWhere the bandwidth total must add up to 100"
+
+/**
+ * ice_sysctl_ets_min_rate - Report/configure ETS bandwidth
+ * @oidp: sysctl oid structure
+ * @arg1: pointer to private data structure
+ * @arg2: unused
+ * @req: sysctl request pointer
+ *
+ * Returns the current ETS TC bandwidth table
+ * cached by the driver.
+ *
+ * In SW DCB mode this sysctl also accepts a value that will
+ * be sent to the firmware for configuration.
+ */
+static int
+ice_sysctl_ets_min_rate(SYSCTL_HANDLER_ARGS)
+{
+ struct ice_softc *sc = (struct ice_softc *)arg1;
+ struct ice_dcbx_cfg *local_dcbx_cfg;
+ struct ice_port_info *pi;
+ struct ice_hw *hw = &sc->hw;
+ device_t dev = sc->dev;
+ enum ice_status status;
+ struct sbuf *sbuf;
+ int ret;
+
+ /* Store input rates from user */
+ char ets_user_buf[128] = "";
+ u8 new_ets_table[ICE_MAX_TRAFFIC_CLASS] = {};
+
+ UNREFERENCED_PARAMETER(arg2);
+
+ if (ice_driver_is_detaching(sc))
+ return (ESHUTDOWN);
+
+ if (req->oldptr == NULL && req->newptr == NULL) {
+ ret = SYSCTL_OUT(req, 0, 128);
+ return (ret);
+ }
+
+ pi = hw->port_info;
+ local_dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg;
+
+ sbuf = sbuf_new(NULL, ets_user_buf, 128, SBUF_FIXEDLEN | SBUF_INCLUDENUL);
+
+ /* Format ETS BW data for output */
+ for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
+ sbuf_printf(sbuf, "%d", local_dcbx_cfg->etscfg.tcbwtable[i]);
+ if (i != ICE_MAX_TRAFFIC_CLASS - 1)
+ sbuf_printf(sbuf, ",");
+ }
+
+ sbuf_finish(sbuf);
+ sbuf_delete(sbuf);
+
+ /* Read in the new ETS values */
+ ret = sysctl_handle_string(oidp, ets_user_buf, sizeof(ets_user_buf), req);
+ if ((ret) || (req->newptr == NULL))
+ return (ret);
+
+ /* Don't allow setting changes in FW DCB mode */
+ if (!hw->port_info->qos_cfg.is_sw_lldp)
+ return (EPERM);
+
+ ret = ice_ets_str_to_tbl(ets_user_buf, new_ets_table, 100);
+ if (ret) {
+ device_printf(dev, "%s: Could not parse input BW table: %s\n",
+ __func__, ets_user_buf);
+ return (ret);
+ }
+
+ if (!ice_check_ets_bw(new_ets_table)) {
+ device_printf(dev, "%s: Bandwidth sum does not equal 100: %s\n",
+ __func__, ets_user_buf);
+ return (EINVAL);
+ }
+
+ memcpy(local_dcbx_cfg->etscfg.tcbwtable, new_ets_table,
+ sizeof(new_ets_table));
+
+ /* If BW > 0, then set TSA entry to 2 */
+ for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
+ if (new_ets_table[i] > 0)
+ local_dcbx_cfg->etscfg.tsatable[i] = 2;
+ else
+ local_dcbx_cfg->etscfg.tsatable[i] = 0;
+ }
+ local_dcbx_cfg->etscfg.willing = 0;
+ local_dcbx_cfg->etsrec = local_dcbx_cfg->etscfg;
+ local_dcbx_cfg->app_mode = ICE_DCBX_APPS_NON_WILLING;
+
+ status = ice_set_dcb_cfg(pi);
+ if (status) {
+ device_printf(dev,
+ "%s: Failed to set DCB config; status %s, aq_err %s\n",
+ __func__, ice_status_str(status),
+ ice_aq_str(hw->adminq.sq_last_status));
+ return (EIO);
+ }
+
+ ice_do_dcb_reconfig(sc);
+
+ return (0);
+}
+
+#define ICE_SYSCTL_HELP_UP2TC_MAP \
+"\nIn FW DCB mode (fw_lldp_agent=1), displays the current ETS priority assignment table." \
+"\nIn SW DCB mode, displays and allows setting the table." \
+"\nInput must be in this format: 0,1,2,3,4,5,6,7" \
+"\nWhere the 1st number is the TC for UP0, 2nd number is the TC for UP1, etc"
+
+/**
+ * ice_sysctl_up2tc_map - Report or configure UP2TC mapping
+ * @oidp: sysctl oid structure
+ * @arg1: pointer to private data structure
+ * @arg2: unused
+ * @req: sysctl request pointer
+ *
+ * In FW DCB mode, returns the current ETS prio table /
+ * UP2TC mapping from the local MIB.
+ *
+ * In SW DCB mode this sysctl also accepts a value that will
+ * be sent to the firmware for configuration.
+ */
+static int
+ice_sysctl_up2tc_map(SYSCTL_HANDLER_ARGS)
+{
+ struct ice_softc *sc = (struct ice_softc *)arg1;
+ struct ice_dcbx_cfg *local_dcbx_cfg;
+ struct ice_port_info *pi;
+ struct ice_hw *hw = &sc->hw;
+ device_t dev = sc->dev;
+ enum ice_status status;
+ struct sbuf *sbuf;
+ int ret;
+
+ /* Store input rates from user */
+ char up2tc_user_buf[128] = "";
+ /* This array is indexed by UP, not TC */
+ u8 new_up2tc[ICE_MAX_TRAFFIC_CLASS] = {};
+
+ UNREFERENCED_PARAMETER(arg2);
+
+ if (ice_driver_is_detaching(sc))
+ return (ESHUTDOWN);
+
+ if (req->oldptr == NULL && req->newptr == NULL) {
+ ret = SYSCTL_OUT(req, 0, 128);
+ return (ret);
+ }
+
+ pi = hw->port_info;
+ local_dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg;
+
+ sbuf = sbuf_new(NULL, up2tc_user_buf, 128, SBUF_FIXEDLEN | SBUF_INCLUDENUL);
+
+ /* Format ETS Priority Mapping Table for output */
+ for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
+ sbuf_printf(sbuf, "%d", local_dcbx_cfg->etscfg.prio_table[i]);
+ if (i != ICE_MAX_TRAFFIC_CLASS - 1)
+ sbuf_printf(sbuf, ",");
+ }
+
+ sbuf_finish(sbuf);
+ sbuf_delete(sbuf);
+
+ /* Read in the new ETS priority mapping */
+ ret = sysctl_handle_string(oidp, up2tc_user_buf, sizeof(up2tc_user_buf), req);
+ if ((ret) || (req->newptr == NULL))
+ return (ret);
+
+ /* Don't allow setting changes in FW DCB mode */
+ if (!hw->port_info->qos_cfg.is_sw_lldp)
+ return (EPERM);
+
+ ret = ice_ets_str_to_tbl(up2tc_user_buf, new_up2tc, 7);
+ if (ret) {
+ device_printf(dev, "%s: Could not parse input priority assignment table: %s\n",
+ __func__, up2tc_user_buf);
+ return (ret);
+ }
+
+ /* Prepare updated ETS TLV */
+ memcpy(local_dcbx_cfg->etscfg.prio_table, new_up2tc,
+ sizeof(new_up2tc));
+
+ status = ice_set_dcb_cfg(pi);
+ if (status) {
+ device_printf(dev,
+ "%s: Failed to set DCB config; status %s, aq_err %s\n",
+ __func__, ice_status_str(status),
+ ice_aq_str(hw->adminq.sq_last_status));
+ return (EIO);
+ }
+
+ ice_do_dcb_reconfig(sc);
+
+ return (0);
+}
+
+/**
+ * ice_config_pfc - helper function to set PFC config in FW
+ * @sc: device private structure
+ * @new_mode: bit flags indicating PFC status for TCs
+ *
+ * @pre must be in SW DCB mode
+ *
+ * Configures the driver's local PFC TLV and sends it to the
+ * FW for configuration, then reconfigures the driver/VSI
+ * for DCB if needed.
+ */
+static int
+ice_config_pfc(struct ice_softc *sc, u8 new_mode)
+{
+ struct ice_dcbx_cfg *local_dcbx_cfg;
+ struct ice_hw *hw = &sc->hw;
+ struct ice_port_info *pi;
+ device_t dev = sc->dev;
+ enum ice_status status;
+
+ pi = hw->port_info;
+ local_dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg;
+
+ /* Prepare updated PFC TLV */
+ local_dcbx_cfg->pfc.pfcena = new_mode;
+ local_dcbx_cfg->pfc.pfccap = ICE_MAX_TRAFFIC_CLASS;
+ local_dcbx_cfg->pfc.willing = 0;
+ local_dcbx_cfg->pfc.mbc = 0;
+
+ status = ice_set_dcb_cfg(pi);
+ if (status) {
+ device_printf(dev,
+ "%s: Failed to set DCB config; status %s, aq_err %s\n",
+ __func__, ice_status_str(status),
+ ice_aq_str(hw->adminq.sq_last_status));
+ return (EIO);
+ }
+
+ ice_do_dcb_reconfig(sc);
+
+ return (0);
+}
+
+#define ICE_SYSCTL_HELP_PFC_CONFIG \
+"\nIn FW DCB mode (fw_lldp_agent=1), displays the current Priority Flow Control configuration" \
+"\nIn SW DCB mode, displays and allows setting the configuration" \
+"\nInput/Output is in this format: 0xff" \
+"\nWhere bit position # enables/disables PFC for that Traffic Class #"
+
+/**
+ * ice_sysctl_pfc_config - Report or configure enabled PFC TCs
+ * @oidp: sysctl oid structure
+ * @arg1: pointer to private data structure
+ * @arg2: unused
+ * @req: sysctl request pointer
+ *
+ * In FW DCB mode, returns a bitmap containing the current TCs
+ * that have PFC enabled on them.
+ *
+ * In SW DCB mode this sysctl also accepts a value that will
+ * be sent to the firmware for configuration.
+ */
+static int
+ice_sysctl_pfc_config(SYSCTL_HANDLER_ARGS)
+{
+ struct ice_softc *sc = (struct ice_softc *)arg1;
+ struct ice_dcbx_cfg *local_dcbx_cfg;
+ struct ice_port_info *pi;
+ struct ice_hw *hw = &sc->hw;
+ int ret;
+
+ /* Store input flags from user */
+ u8 user_pfc;
+
+ UNREFERENCED_PARAMETER(arg2);
+
+ if (ice_driver_is_detaching(sc))
+ return (ESHUTDOWN);
+
+ if (req->oldptr == NULL && req->newptr == NULL) {
+ ret = SYSCTL_OUT(req, 0, sizeof(u8));
+ return (ret);
+ }
+
+ pi = hw->port_info;
+ local_dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg;
+
+ /* Format current PFC enable setting for output */
+ user_pfc = local_dcbx_cfg->pfc.pfcena;
+
+ /* Read in the new PFC config */
+ ret = sysctl_handle_8(oidp, &user_pfc, 0, req);
+ if ((ret) || (req->newptr == NULL))
+ return (ret);
+
+ /* Don't allow setting changes in FW DCB mode */
+ if (!hw->port_info->qos_cfg.is_sw_lldp)
+ return (EPERM);
+
+ /* If LFC is active and PFC is going to be turned on, turn LFC off */
+ if (user_pfc != 0 && pi->phy.curr_user_fc_req != ICE_FC_NONE) {
+ pi->phy.curr_user_fc_req = ICE_FC_NONE;
+ ret = ice_apply_saved_phy_cfg(sc, ICE_APPLY_FC);
+ if (ret)
+ return (ret);
+ }
+
+ return ice_config_pfc(sc, user_pfc);
+}
+
/**
* ice_add_device_sysctls - add device specific dynamic sysctls
* @sc: device private structure
@@ -3707,9 +4090,11 @@ ice_add_device_sysctls(struct ice_softc *sc)
OID_AUTO, "fw_version", CTLTYPE_STRING | CTLFLAG_RD,
sc, 0, ice_sysctl_show_fw, "A", "Firmware version");
- SYSCTL_ADD_PROC(ctx, ctx_list,
- OID_AUTO, "pba_number", CTLTYPE_STRING | CTLFLAG_RD,
- sc, 0, ice_sysctl_pba_number, "A", "Product Board Assembly Number");
+ if (ice_is_bit_set(sc->feat_en, ICE_FEATURE_HAS_PBA)) {
+ SYSCTL_ADD_PROC(ctx, ctx_list,
+ OID_AUTO, "pba_number", CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
+ ice_sysctl_pba_number, "A", "Product Board Assembly Number");
+ }
SYSCTL_ADD_PROC(ctx, ctx_list,
OID_AUTO, "ddp_version", CTLTYPE_STRING | CTLFLAG_RD,
@@ -3739,6 +4124,18 @@ ice_add_device_sysctls(struct ice_softc *sc)
OID_AUTO, "fw_lldp_agent", CTLTYPE_U8 | CTLFLAG_RWTUN,
sc, 0, ice_sysctl_fw_lldp_agent, "CU", ICE_SYSCTL_HELP_FW_LLDP_AGENT);
+ SYSCTL_ADD_PROC(ctx, ctx_list,
+ OID_AUTO, "ets_min_rate", CTLTYPE_STRING | CTLFLAG_RW,
+ sc, 0, ice_sysctl_ets_min_rate, "A", ICE_SYSCTL_HELP_ETS_MIN_RATE);
+
+ SYSCTL_ADD_PROC(ctx, ctx_list,
+ OID_AUTO, "up2tc_map", CTLTYPE_STRING | CTLFLAG_RW,
+ sc, 0, ice_sysctl_up2tc_map, "A", ICE_SYSCTL_HELP_UP2TC_MAP);
+
+ SYSCTL_ADD_PROC(ctx, ctx_list,
+ OID_AUTO, "pfc", CTLTYPE_U8 | CTLFLAG_RW,
+ sc, 0, ice_sysctl_pfc_config, "CU", ICE_SYSCTL_HELP_PFC_CONFIG);
+
/* Differentiate software and hardware statistics, by keeping hw stats
* in their own node. This isn't in ice_add_device_tunables, because
* we won't have any CTLFLAG_TUN sysctls under this node.
@@ -4120,7 +4517,7 @@ ice_add_vsi_sysctls(struct ice_vsi *vsi)
{
struct sysctl_ctx_list *ctx = &vsi->ctx;
struct sysctl_oid *hw_node, *sw_node;
- struct sysctl_oid_list *vsi_list, *hw_list, *sw_list;
+ struct sysctl_oid_list *vsi_list, *hw_list;
vsi_list = SYSCTL_CHILDREN(vsi->vsi_node);
@@ -4152,12 +4549,89 @@ ice_add_vsi_sysctls(struct ice_vsi *vsi)
/* Add a node for statistics tracked by software. */
sw_node = SYSCTL_ADD_NODE(ctx, vsi_list, OID_AUTO, "sw", CTLFLAG_RD,
NULL, "VSI Software Statistics");
- sw_list = SYSCTL_CHILDREN(sw_node);
ice_add_sysctls_sw_stats(vsi, ctx, sw_node);
}
/**
+ * ice_add_sysctls_mac_pfc_one_stat - Add sysctl node for a PFC statistic
+ * @ctx: sysctl ctx to use
+ * @parent_list: parent sysctl list to add sysctls under
+ * @pfc_stat_location: address of statistic for sysctl to display
+ * @node_name: Name for statistic node
+ * @descr: Description used for nodes added in this function
+ *
+ * A helper function for ice_add_sysctls_mac_pfc_stats that adds a node
+ * for a stat and leaves for each traffic class for that stat.
+ */
+static void
+ice_add_sysctls_mac_pfc_one_stat(struct sysctl_ctx_list *ctx,
+ struct sysctl_oid_list *parent_list,
+ u64* pfc_stat_location,
+ const char *node_name,
+ const char *descr)
+{
+ struct sysctl_oid_list *node_list;
+ struct sysctl_oid *node;
+ struct sbuf *namebuf, *descbuf;
+
+ node = SYSCTL_ADD_NODE(ctx, parent_list, OID_AUTO, node_name, CTLFLAG_RD,
+ NULL, descr);
+ node_list = SYSCTL_CHILDREN(node);
+
+ namebuf = sbuf_new_auto();
+ descbuf = sbuf_new_auto();
+ for (int i = 0; i < ICE_MAX_DCB_TCS; i++) {
+ sbuf_clear(namebuf);
+ sbuf_clear(descbuf);
+
+ sbuf_printf(namebuf, "%d", i);
+ sbuf_printf(descbuf, "%s for TC %d", descr, i);
+
+ sbuf_finish(namebuf);
+ sbuf_finish(descbuf);
+
+ SYSCTL_ADD_U64(ctx, node_list, OID_AUTO, sbuf_data(namebuf),
+ CTLFLAG_RD | CTLFLAG_STATS, &pfc_stat_location[i], 0,
+ sbuf_data(descbuf));
+ }
+
+ sbuf_delete(namebuf);
+ sbuf_delete(descbuf);
+}
+
+/**
+ * ice_add_sysctls_mac_pfc_stats - Add sysctls for MAC PFC statistics
+ * @ctx: the sysctl ctx to use
+ * @parent: parent node to add the sysctls under
+ * @stats: the hw ports stat structure to pull values from
+ *
+ * Add global Priority Flow Control MAC statistics sysctls. These are
+ * structured as a node with the PFC statistic, where there are eight
+ * nodes for each traffic class.
+ */
+static void
+ice_add_sysctls_mac_pfc_stats(struct sysctl_ctx_list *ctx,
+ struct sysctl_oid *parent,
+ struct ice_hw_port_stats *stats)
+{
+ struct sysctl_oid_list *parent_list;
+
+ parent_list = SYSCTL_CHILDREN(parent);
+
+ ice_add_sysctls_mac_pfc_one_stat(ctx, parent_list, stats->priority_xon_rx,
+ "p_xon_recvd", "PFC XON received");
+ ice_add_sysctls_mac_pfc_one_stat(ctx, parent_list, stats->priority_xoff_rx,
+ "p_xoff_recvd", "PFC XOFF received");
+ ice_add_sysctls_mac_pfc_one_stat(ctx, parent_list, stats->priority_xon_tx,
+ "p_xon_txd", "PFC XON transmitted");
+ ice_add_sysctls_mac_pfc_one_stat(ctx, parent_list, stats->priority_xoff_tx,
+ "p_xoff_txd", "PFC XOFF transmitted");
+ ice_add_sysctls_mac_pfc_one_stat(ctx, parent_list, stats->priority_xon_2_xoff,
+ "p_xon2xoff", "PFC XON to XOFF transitions");
+}
+
+/**
* ice_add_sysctls_mac_stats - Add sysctls for global MAC statistics
* @ctx: the sysctl ctx to use
* @parent: parent node to add the sysctls under
@@ -4179,9 +4653,12 @@ ice_add_sysctls_mac_stats(struct sysctl_ctx_list *ctx,
NULL, "Mac Hardware Statistics");
mac_list = SYSCTL_CHILDREN(mac_node);
- /* add the common ethernet statistics */
+ /* Add the ethernet statistics common to VSI and MAC */
ice_add_sysctls_eth_stats(ctx, mac_node, &stats->eth);
+ /* Add PFC stats that add per-TC counters */
+ ice_add_sysctls_mac_pfc_stats(ctx, mac_node, stats);
+
const struct ice_sysctl_info ctls[] = {
/* Packet Reception Stats */
{&stats->rx_size_64, "rx_frames_64", "64 byte frames received"},
@@ -5129,23 +5606,27 @@ ice_add_debug_tunables(struct ice_softc *sc)
debug_list = SYSCTL_CHILDREN(sc->debug_sysctls);
SYSCTL_ADD_U64(ctx, debug_list, OID_AUTO, "debug_mask",
- CTLFLAG_RW | CTLFLAG_TUN, &sc->hw.debug_mask, 0,
+ ICE_CTLFLAG_DEBUG | CTLFLAG_RW | CTLFLAG_TUN,
+ &sc->hw.debug_mask, 0,
"Debug message enable/disable mask");
/* Load the default value from the global sysctl first */
sc->enable_tx_fc_filter = ice_enable_tx_fc_filter;
SYSCTL_ADD_BOOL(ctx, debug_list, OID_AUTO, "enable_tx_fc_filter",
- CTLFLAG_RDTUN, &sc->enable_tx_fc_filter, 0,
+ ICE_CTLFLAG_DEBUG | CTLFLAG_RDTUN,
+ &sc->enable_tx_fc_filter, 0,
"Drop Ethertype 0x8808 control frames originating from software on this PF");
/* Load the default value from the global sysctl first */
sc->enable_tx_lldp_filter = ice_enable_tx_lldp_filter;
SYSCTL_ADD_BOOL(ctx, debug_list, OID_AUTO, "enable_tx_lldp_filter",
- CTLFLAG_RDTUN, &sc->enable_tx_lldp_filter, 0,
+ ICE_CTLFLAG_DEBUG | CTLFLAG_RDTUN,
+ &sc->enable_tx_lldp_filter, 0,
"Drop Ethertype 0x88cc LLDP frames originating from software on this PF");
+ ice_add_fw_logging_tunables(sc, sc->debug_sysctls);
}
#define ICE_SYSCTL_HELP_REQUEST_RESET \
@@ -5302,105 +5783,146 @@ ice_add_debug_sysctls(struct ice_softc *sc)
debug_list = SYSCTL_CHILDREN(sc->debug_sysctls);
SYSCTL_ADD_PROC(ctx, debug_list, OID_AUTO, "request_reset",
- CTLTYPE_STRING | CTLFLAG_WR, sc, 0,
+ ICE_CTLFLAG_DEBUG | CTLTYPE_STRING | CTLFLAG_WR, sc, 0,
ice_sysctl_request_reset, "A",
ICE_SYSCTL_HELP_REQUEST_RESET);
- SYSCTL_ADD_U32(ctx, debug_list, OID_AUTO, "pfr_count", CTLFLAG_RD,
- &sc->soft_stats.pfr_count, 0, "# of PF resets handled");
-
- SYSCTL_ADD_U32(ctx, debug_list, OID_AUTO, "corer_count", CTLFLAG_RD,
- &sc->soft_stats.corer_count, 0, "# of CORE resets handled");
-
- SYSCTL_ADD_U32(ctx, debug_list, OID_AUTO, "globr_count", CTLFLAG_RD,
- &sc->soft_stats.globr_count, 0, "# of Global resets handled");
-
- SYSCTL_ADD_U32(ctx, debug_list, OID_AUTO, "empr_count", CTLFLAG_RD,
- &sc->soft_stats.empr_count, 0, "# of EMP resets handled");
-
- SYSCTL_ADD_U32(ctx, debug_list, OID_AUTO, "tx_mdd_count", CTLFLAG_RD,
- &sc->soft_stats.tx_mdd_count, 0, "# of Tx MDD events detected");
-
- SYSCTL_ADD_U32(ctx, debug_list, OID_AUTO, "rx_mdd_count", CTLFLAG_RD,
- &sc->soft_stats.rx_mdd_count, 0, "# of Rx MDD events detected");
-
- SYSCTL_ADD_PROC(ctx, debug_list,
- OID_AUTO, "state", CTLTYPE_STRING | CTLFLAG_RD,
- sc, 0, ice_sysctl_dump_state_flags, "A", "Driver State Flags");
-
- SYSCTL_ADD_PROC(ctx, debug_list,
- OID_AUTO, "phy_type_low", CTLTYPE_U64 | CTLFLAG_RW,
- sc, 0, ice_sysctl_phy_type_low, "QU",
+ SYSCTL_ADD_U32(ctx, debug_list, OID_AUTO, "pfr_count",
+ ICE_CTLFLAG_DEBUG | CTLFLAG_RD,
+ &sc->soft_stats.pfr_count, 0,
+ "# of PF resets handled");
+
+ SYSCTL_ADD_U32(ctx, debug_list, OID_AUTO, "corer_count",
+ ICE_CTLFLAG_DEBUG | CTLFLAG_RD,
+ &sc->soft_stats.corer_count, 0,
+ "# of CORE resets handled");
+
+ SYSCTL_ADD_U32(ctx, debug_list, OID_AUTO, "globr_count",
+ ICE_CTLFLAG_DEBUG | CTLFLAG_RD,
+ &sc->soft_stats.globr_count, 0,
+ "# of Global resets handled");
+
+ SYSCTL_ADD_U32(ctx, debug_list, OID_AUTO, "empr_count",
+ ICE_CTLFLAG_DEBUG | CTLFLAG_RD,
+ &sc->soft_stats.empr_count, 0,
+ "# of EMP resets handled");
+
+ SYSCTL_ADD_U32(ctx, debug_list, OID_AUTO, "tx_mdd_count",
+ ICE_CTLFLAG_DEBUG | CTLFLAG_RD,
+ &sc->soft_stats.tx_mdd_count, 0,
+ "# of Tx MDD events detected");
+
+ SYSCTL_ADD_U32(ctx, debug_list, OID_AUTO, "rx_mdd_count",
+ ICE_CTLFLAG_DEBUG | CTLFLAG_RD,
+ &sc->soft_stats.rx_mdd_count, 0,
+ "# of Rx MDD events detected");
+
+ SYSCTL_ADD_PROC(ctx, debug_list, OID_AUTO, "state",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
+ ice_sysctl_dump_state_flags, "A",
+ "Driver State Flags");
+
+ SYSCTL_ADD_PROC(ctx, debug_list, OID_AUTO, "phy_type_low",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_U64 | CTLFLAG_RW, sc, 0,
+ ice_sysctl_phy_type_low, "QU",
"PHY type Low from Get PHY Caps/Set PHY Cfg");
- SYSCTL_ADD_PROC(ctx, debug_list,
- OID_AUTO, "phy_type_high", CTLTYPE_U64 | CTLFLAG_RW,
- sc, 0, ice_sysctl_phy_type_high, "QU",
+ SYSCTL_ADD_PROC(ctx, debug_list, OID_AUTO, "phy_type_high",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_U64 | CTLFLAG_RW, sc, 0,
+ ice_sysctl_phy_type_high, "QU",
"PHY type High from Get PHY Caps/Set PHY Cfg");
- SYSCTL_ADD_PROC(ctx, debug_list,
- OID_AUTO, "phy_sw_caps", CTLTYPE_STRUCT | CTLFLAG_RD,
- sc, 0, ice_sysctl_phy_sw_caps, "",
+ SYSCTL_ADD_PROC(ctx, debug_list, OID_AUTO, "phy_sw_caps",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_STRUCT | CTLFLAG_RD, sc, 0,
+ ice_sysctl_phy_sw_caps, "",
"Get PHY Capabilities (Software configuration)");
- SYSCTL_ADD_PROC(ctx, debug_list,
- OID_AUTO, "phy_nvm_caps", CTLTYPE_STRUCT | CTLFLAG_RD,
- sc, 0, ice_sysctl_phy_nvm_caps, "",
+ SYSCTL_ADD_PROC(ctx, debug_list, OID_AUTO, "phy_nvm_caps",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_STRUCT | CTLFLAG_RD, sc, 0,
+ ice_sysctl_phy_nvm_caps, "",
"Get PHY Capabilities (NVM configuration)");
- SYSCTL_ADD_PROC(ctx, debug_list,
- OID_AUTO, "phy_topo_caps", CTLTYPE_STRUCT | CTLFLAG_RD,
- sc, 0, ice_sysctl_phy_topo_caps, "",
+ SYSCTL_ADD_PROC(ctx, debug_list, OID_AUTO, "phy_topo_caps",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_STRUCT | CTLFLAG_RD, sc, 0,
+ ice_sysctl_phy_topo_caps, "",
"Get PHY Capabilities (Topology configuration)");
- SYSCTL_ADD_PROC(ctx, debug_list,
- OID_AUTO, "phy_link_status", CTLTYPE_STRUCT | CTLFLAG_RD,
- sc, 0, ice_sysctl_phy_link_status, "",
+ SYSCTL_ADD_PROC(ctx, debug_list, OID_AUTO, "phy_link_status",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_STRUCT | CTLFLAG_RD, sc, 0,
+ ice_sysctl_phy_link_status, "",
"Get PHY Link Status");
- SYSCTL_ADD_PROC(ctx, debug_list,
- OID_AUTO, "read_i2c_diag_data", CTLTYPE_STRING | CTLFLAG_RD,
- sc, 0, ice_sysctl_read_i2c_diag_data, "A",
+ SYSCTL_ADD_PROC(ctx, debug_list, OID_AUTO, "read_i2c_diag_data",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
+ ice_sysctl_read_i2c_diag_data, "A",
"Dump selected diagnostic data from FW");
- SYSCTL_ADD_U32(ctx, debug_list, OID_AUTO, "fw_build", CTLFLAG_RD,
- &sc->hw.fw_build, 0, "FW Build ID");
+ SYSCTL_ADD_U32(ctx, debug_list, OID_AUTO, "fw_build",
+ ICE_CTLFLAG_DEBUG | CTLFLAG_RD, &sc->hw.fw_build, 0,
+ "FW Build ID");
- SYSCTL_ADD_PROC(ctx, debug_list, OID_AUTO, "os_ddp_version", CTLTYPE_STRING | CTLFLAG_RD,
- sc, 0, ice_sysctl_os_pkg_version, "A",
+ SYSCTL_ADD_PROC(ctx, debug_list, OID_AUTO, "os_ddp_version",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
+ ice_sysctl_os_pkg_version, "A",
"DDP package name and version found in ice_ddp");
- SYSCTL_ADD_PROC(ctx, debug_list,
- OID_AUTO, "cur_lldp_persist_status", CTLTYPE_STRING | CTLFLAG_RD,
- sc, 0, ice_sysctl_fw_cur_lldp_persist_status, "A", "Current LLDP persistent status");
+ SYSCTL_ADD_PROC(ctx, debug_list, OID_AUTO, "cur_lldp_persist_status",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
+ ice_sysctl_fw_cur_lldp_persist_status, "A",
+ "Current LLDP persistent status");
+
+ SYSCTL_ADD_PROC(ctx, debug_list, OID_AUTO, "dflt_lldp_persist_status",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
+ ice_sysctl_fw_dflt_lldp_persist_status, "A",
+ "Default LLDP persistent status");
+
+ SYSCTL_ADD_PROC(ctx, debug_list, OID_AUTO, "negotiated_fc",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
+ ice_sysctl_negotiated_fc, "A",
+ "Current Negotiated Flow Control mode");
- SYSCTL_ADD_PROC(ctx, debug_list,
- OID_AUTO, "dflt_lldp_persist_status", CTLTYPE_STRING | CTLFLAG_RD,
- sc, 0, ice_sysctl_fw_dflt_lldp_persist_status, "A", "Default LLDP persistent status");
+ SYSCTL_ADD_PROC(ctx, debug_list, OID_AUTO, "local_dcbx_cfg",
+ CTLTYPE_STRING | CTLFLAG_RD, sc, ICE_AQ_LLDP_MIB_LOCAL,
+ ice_sysctl_dump_dcbx_cfg, "A",
+ "Dumps Local MIB information from firmware");
- SYSCTL_ADD_PROC(ctx, debug_list,
- OID_AUTO, "negotiated_fc", CTLTYPE_STRING | CTLFLAG_RD,
- sc, 0, ice_sysctl_negotiated_fc, "A", "Current Negotiated Flow Control mode");
+ SYSCTL_ADD_PROC(ctx, debug_list, OID_AUTO, "remote_dcbx_cfg",
+ CTLTYPE_STRING | CTLFLAG_RD, sc, ICE_AQ_LLDP_MIB_REMOTE,
+ ice_sysctl_dump_dcbx_cfg, "A",
+ "Dumps Remote MIB information from firmware");
+
+ SYSCTL_ADD_PROC(ctx, debug_list, OID_AUTO, "pf_vsi_cfg", CTLTYPE_STRING | CTLFLAG_RD,
+ sc, 0, ice_sysctl_dump_vsi_cfg, "A",
+ "Dumps Selected PF VSI parameters from firmware");
+
+ SYSCTL_ADD_PROC(ctx, debug_list, OID_AUTO, "query_port_ets", CTLTYPE_STRING | CTLFLAG_RD,
+ sc, 0, ice_sysctl_query_port_ets, "A",
+ "Prints selected output from Query Port ETS AQ command");
sw_node = SYSCTL_ADD_NODE(ctx, debug_list, OID_AUTO, "switch",
- CTLFLAG_RD, NULL, "Switch Configuration");
+ ICE_CTLFLAG_DEBUG | CTLFLAG_RD, NULL,
+ "Switch Configuration");
sw_list = SYSCTL_CHILDREN(sw_node);
- SYSCTL_ADD_PROC(ctx, sw_list,
- OID_AUTO, "mac_filters", CTLTYPE_STRING | CTLFLAG_RD,
- sc, 0, ice_sysctl_dump_mac_filters, "A", "MAC Filters");
+ SYSCTL_ADD_PROC(ctx, sw_list, OID_AUTO, "mac_filters",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
+ ice_sysctl_dump_mac_filters, "A",
+ "MAC Filters");
- SYSCTL_ADD_PROC(ctx, sw_list,
- OID_AUTO, "vlan_filters", CTLTYPE_STRING | CTLFLAG_RD,
- sc, 0, ice_sysctl_dump_vlan_filters, "A", "VLAN Filters");
+ SYSCTL_ADD_PROC(ctx, sw_list, OID_AUTO, "vlan_filters",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
+ ice_sysctl_dump_vlan_filters, "A",
+ "VLAN Filters");
- SYSCTL_ADD_PROC(ctx, sw_list,
- OID_AUTO, "ethertype_filters", CTLTYPE_STRING | CTLFLAG_RD,
- sc, 0, ice_sysctl_dump_ethertype_filters, "A", "Ethertype Filters");
+ SYSCTL_ADD_PROC(ctx, sw_list, OID_AUTO, "ethertype_filters",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
+ ice_sysctl_dump_ethertype_filters, "A",
+ "Ethertype Filters");
- SYSCTL_ADD_PROC(ctx, sw_list,
- OID_AUTO, "ethertype_mac_filters", CTLTYPE_STRING | CTLFLAG_RD,
- sc, 0, ice_sysctl_dump_ethertype_mac_filters, "A", "Ethertype/MAC Filters");
+ SYSCTL_ADD_PROC(ctx, sw_list, OID_AUTO, "ethertype_mac_filters",
+ ICE_CTLFLAG_DEBUG | CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
+ ice_sysctl_dump_ethertype_mac_filters, "A",
+ "Ethertype/MAC Filters");
}
@@ -5419,51 +5941,68 @@ ice_vsi_disable_tx(struct ice_vsi *vsi)
enum ice_status status;
u32 *q_teids;
u16 *q_ids, *q_handles;
- int i, err = 0;
+ size_t q_teids_size, q_ids_size, q_handles_size;
+ int tc, j, buf_idx, err = 0;
if (vsi->num_tx_queues > 255)
return (ENOSYS);
- q_teids = (u32 *)malloc(sizeof(*q_teids) * vsi->num_tx_queues,
- M_ICE, M_NOWAIT|M_ZERO);
+ q_teids_size = sizeof(*q_teids) * vsi->num_tx_queues;
+ q_teids = (u32 *)malloc(q_teids_size, M_ICE, M_NOWAIT|M_ZERO);
if (!q_teids)
return (ENOMEM);
- q_ids = (u16 *)malloc(sizeof(*q_ids) * vsi->num_tx_queues,
- M_ICE, M_NOWAIT|M_ZERO);
+ q_ids_size = sizeof(*q_ids) * vsi->num_tx_queues;
+ q_ids = (u16 *)malloc(q_ids_size, M_ICE, M_NOWAIT|M_ZERO);
if (!q_ids) {
err = (ENOMEM);
goto free_q_teids;
}
- q_handles = (u16 *)malloc(sizeof(*q_handles) * vsi->num_tx_queues,
- M_ICE, M_NOWAIT|M_ZERO);
+ q_handles_size = sizeof(*q_handles) * vsi->num_tx_queues;
+ q_handles = (u16 *)malloc(q_handles_size, M_ICE, M_NOWAIT|M_ZERO);
if (!q_handles) {
err = (ENOMEM);
goto free_q_ids;
}
+ ice_for_each_traffic_class(tc) {
+ buf_idx = 0;
+ for (j = 0; j < vsi->num_tx_queues; j++) {
+ struct ice_tx_queue *txq = &vsi->tx_queues[j];
- for (i = 0; i < vsi->num_tx_queues; i++) {
- struct ice_tx_queue *txq = &vsi->tx_queues[i];
+ if (txq->tc != tc)
+ continue;
- q_ids[i] = vsi->tx_qmap[i];
- q_handles[i] = i;
- q_teids[i] = txq->q_teid;
- }
+ q_ids[buf_idx] = vsi->tx_qmap[j];
+ q_handles[buf_idx] = txq->q_handle;
+ q_teids[buf_idx] = txq->q_teid;
+ buf_idx++;
+ }
+ /* Skip TC if no queues belong to it */
+ if (buf_idx == 0)
+ continue;
- status = ice_dis_vsi_txq(hw->port_info, vsi->idx, 0, vsi->num_tx_queues,
- q_handles, q_ids, q_teids, ICE_NO_RESET, 0, NULL);
- if (status == ICE_ERR_DOES_NOT_EXIST) {
- ; /* Queues have already been disabled, no need to report this as an error */
- } else if (status == ICE_ERR_RESET_ONGOING) {
- device_printf(sc->dev,
- "Reset in progress. LAN Tx queues already disabled\n");
- } else if (status) {
- device_printf(sc->dev,
- "Failed to disable LAN Tx queues: err %s aq_err %s\n",
- ice_status_str(status), ice_aq_str(hw->adminq.sq_last_status));
- err = (ENODEV);
+ status = ice_dis_vsi_txq(hw->port_info, vsi->idx, tc, buf_idx,
+ q_handles, q_ids, q_teids, ICE_NO_RESET, 0, NULL);
+ if (status == ICE_ERR_DOES_NOT_EXIST) {
+ ; /* Queues have already been disabled, no need to report this as an error */
+ } else if (status == ICE_ERR_RESET_ONGOING) {
+ device_printf(sc->dev,
+ "Reset in progress. LAN Tx queues already disabled\n");
+ break;
+ } else if (status) {
+ device_printf(sc->dev,
+ "Failed to disable LAN Tx queues: err %s aq_err %s\n",
+ ice_status_str(status), ice_aq_str(hw->adminq.sq_last_status));
+ err = (ENODEV);
+ break;
+ }
+
+ /* Clear buffers */
+ memset(q_teids, 0, q_teids_size);
+ memset(q_ids, 0, q_ids_size);
+ memset(q_handles, 0, q_handles_size);
}
/* free_q_handles: */
@@ -5639,6 +6178,10 @@ ice_add_txq_sysctls(struct ice_tx_queue *txq)
entry->description);
entry++;
}
+
+ SYSCTL_ADD_U8(ctx, this_txq_list, OID_AUTO, "tc",
+ CTLFLAG_RD, &txq->tc, 0,
+ "Traffic Class that Queue belongs to");
}
/**
@@ -5681,6 +6224,10 @@ ice_add_rxq_sysctls(struct ice_rx_queue *rxq)
entry->description);
entry++;
}
+
+ SYSCTL_ADD_U8(ctx, this_rxq_list, OID_AUTO, "tc",
+ CTLFLAG_RD, &rxq->tc, 0,
+ "Traffic Class that Queue belongs to");
}
/**
@@ -6813,7 +7360,12 @@ ice_init_dcb_setup(struct ice_softc *sc)
* checked here because a more detailed dcbx agent status is
* retrieved and checked in ice_init_dcb() and below.
*/
- ice_aq_start_stop_dcbx(hw, true, &dcbx_agent_status, NULL);
+ status = ice_aq_start_stop_dcbx(hw, true, &dcbx_agent_status, NULL);
+ if (status && hw->adminq.sq_last_status != ICE_AQ_RC_EPERM)
+ device_printf(dev,
+ "start_stop_dcbx failed, err %s aq_err %s\n",
+ ice_status_str(status),
+ ice_aq_str(hw->adminq.sq_last_status));
}
/* This sets hw->port_info->qos_cfg.is_sw_lldp */
@@ -6856,25 +7408,79 @@ ice_init_dcb_setup(struct ice_softc *sc)
}
/**
- * ice_handle_mib_change_event - helper function to log LLDP MIB change events
- * @sc: device softc
- * @event: event received on a control queue
+ * ice_dcb_get_tc_map - Scans config to get bitmap of enabled TCs
+ * @dcbcfg: DCB configuration to examine
*
- * Prints out the type of an LLDP MIB change event in a DCB debug message.
+ * Scans a TC mapping table inside dcbcfg to find traffic classes
+ * enabled and @returns a bitmask of enabled TCs
+ */
+static u8
+ice_dcb_get_tc_map(const struct ice_dcbx_cfg *dcbcfg)
+{
+ u8 tc_map = 0;
+ int i = 0;
+
+ switch (dcbcfg->pfc_mode) {
+ case ICE_QOS_MODE_VLAN:
+ /* XXX: "i" is actually "User Priority" here, not
+ * Traffic Class, but the max for both is 8, so it works
+ * out here.
+ */
+ for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++)
+ tc_map |= BIT(dcbcfg->etscfg.prio_table[i]);
+ break;
+ default:
+ /* Invalid Mode */
+ tc_map = ICE_DFLT_TRAFFIC_CLASS;
+ break;
+ }
+
+ return (tc_map);
+}
+
+/**
+ * ice_dcb_num_tc - Count the number of TCs in a bitmap
+ * @tc_map: bitmap of enabled traffic classes
*
- * XXX: Should be extended to do more if the driver decides to notify other SW
- * of LLDP MIB changes, or needs to extract info from the MIB.
+ * @return the number of traffic classes in
+ * an 8-bit TC bitmap, or 0 if they are noncontiguous
+ */
+static u8
+ice_dcb_num_tc(u8 tc_map)
+{
+ bool tc_unused = false;
+ u8 ret = 0;
+ int i = 0;
+
+ ice_for_each_traffic_class(i) {
+ if (tc_map & BIT(i)) {
+ if (!tc_unused) {
+ ret++;
+ } else {
+ /* Non-contiguous TCs detected */
+ return (0);
+ }
+ } else
+ tc_unused = true;
+ }
+
+ return (ret);
+}
+
+/**
+ * ice_debug_print_mib_change_event - helper function to log LLDP MIB change events
+ * @sc: the device private softc
+ * @event: event received on a control queue
+ *
+ * Prints out the type and contents of an LLDP MIB change event in a DCB debug message.
*/
static void
-ice_handle_mib_change_event(struct ice_softc *sc, struct ice_rq_event_info *event)
+ice_debug_print_mib_change_event(struct ice_softc *sc, struct ice_rq_event_info *event)
{
struct ice_aqc_lldp_get_mib *params =
(struct ice_aqc_lldp_get_mib *)&event->desc.params.lldp_get_mib;
u8 mib_type, bridge_type, tx_status;
- /* XXX: To get the contents of the MIB that caused the event, set the
- * ICE_DBG_AQ debug mask and read that output
- */
static const char* mib_type_strings[] = {
"Local MIB",
"Remote MIB",
@@ -6891,7 +7497,7 @@ ice_handle_mib_change_event(struct ice_softc *sc, struct ice_rq_event_info *even
"Port's TX active",
"Port's TX suspended and drained",
"Reserved",
- "Port's TX suspended and srained; blocked TC pipe flushed"
+ "Port's TX suspended and drained; blocked TC pipe flushed"
};
mib_type = (params->type & ICE_AQ_LLDP_MIB_TYPE_M) >>
@@ -6904,6 +7510,409 @@ ice_handle_mib_change_event(struct ice_softc *sc, struct ice_rq_event_info *even
ice_debug(&sc->hw, ICE_DBG_DCB, "LLDP MIB Change Event (%s, %s, %s)\n",
mib_type_strings[mib_type], bridge_type_strings[bridge_type],
tx_status_strings[tx_status]);
+
+ /* Nothing else to report */
+ if (!event->msg_buf)
+ return;
+
+ ice_debug(&sc->hw, ICE_DBG_DCB, "- %s contents:\n", mib_type_strings[mib_type]);
+ ice_debug_array(&sc->hw, ICE_DBG_DCB, 16, 1, event->msg_buf,
+ event->msg_len);
+}
+
+/**
+ * ice_dcb_needs_reconfig - Returns true if driver needs to reconfigure
+ * @sc: the device private softc
+ * @old_cfg: Old DCBX configuration to compare against
+ * @new_cfg: New DCBX configuration to check
+ *
+ * @return true if something changed in new_cfg that requires the driver
+ * to do some reconfiguration.
+ */
+static bool
+ice_dcb_needs_reconfig(struct ice_softc *sc, struct ice_dcbx_cfg *old_cfg,
+ struct ice_dcbx_cfg *new_cfg)
+{
+ struct ice_hw *hw = &sc->hw;
+ bool needs_reconfig = false;
+
+ /* Check if ETS config has changed */
+ if (memcmp(&new_cfg->etscfg, &old_cfg->etscfg,
+ sizeof(new_cfg->etscfg))) {
+ /* If Priority Table has changed, then driver reconfig is needed */
+ if (memcmp(&new_cfg->etscfg.prio_table,
+ &old_cfg->etscfg.prio_table,
+ sizeof(new_cfg->etscfg.prio_table))) {
+ ice_debug(hw, ICE_DBG_DCB, "ETS UP2TC changed\n");
+ needs_reconfig = true;
+ }
+
+ /* These are just informational */
+ if (memcmp(&new_cfg->etscfg.tcbwtable,
+ &old_cfg->etscfg.tcbwtable,
+ sizeof(new_cfg->etscfg.tcbwtable)))
+ ice_debug(hw, ICE_DBG_DCB, "ETS TCBW table changed\n");
+
+ if (memcmp(&new_cfg->etscfg.tsatable,
+ &old_cfg->etscfg.tsatable,
+ sizeof(new_cfg->etscfg.tsatable)))
+ ice_debug(hw, ICE_DBG_DCB, "ETS TSA table changed\n");
+ }
+
+ /* Check if PFC config has changed */
+ if (memcmp(&new_cfg->pfc, &old_cfg->pfc, sizeof(new_cfg->pfc))) {
+ needs_reconfig = true;
+ ice_debug(hw, ICE_DBG_DCB, "PFC config changed\n");
+ }
+
+ ice_debug(hw, ICE_DBG_DCB, "%s result: %d\n", __func__, needs_reconfig);
+
+ return (needs_reconfig);
+}
+
+/**
+ * ice_stop_pf_vsi - Stop queues for PF LAN VSI
+ * @sc: the device private softc
+ *
+ * Flushes interrupts and stops the queues associated with the PF LAN VSI.
+ */
+static void
+ice_stop_pf_vsi(struct ice_softc *sc)
+{
+ /* Dissociate the Tx and Rx queues from the interrupts */
+ ice_flush_txq_interrupts(&sc->pf_vsi);
+ ice_flush_rxq_interrupts(&sc->pf_vsi);
+
+ if (!ice_testandclear_state(&sc->state, ICE_STATE_DRIVER_INITIALIZED))
+ return;
+
+ /* Disable the Tx and Rx queues */
+ ice_vsi_disable_tx(&sc->pf_vsi);
+ ice_control_rx_queues(&sc->pf_vsi, false);
+}
+
+/**
+ * ice_vsi_setup_q_map - Setup a VSI queue map
+ * @vsi: the VSI being configured
+ * @ctxt: VSI context structure
+ */
+static void
+ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt)
+{
+ u16 offset = 0, qmap = 0, pow = 0;
+ u16 num_txq_per_tc, num_rxq_per_tc, qcount_rx;
+ int i, j, k;
+
+ if (vsi->num_tcs == 0) {
+ /* at least TC0 should be enabled by default */
+ vsi->num_tcs = 1;
+ vsi->tc_map = 0x1;
+ }
+
+ qcount_rx = vsi->num_rx_queues;
+ num_rxq_per_tc = min(qcount_rx / vsi->num_tcs, ICE_MAX_RXQS_PER_TC);
+ if (!num_rxq_per_tc)
+ num_rxq_per_tc = 1;
+
+ /* Have TX queue count match RX queue count */
+ num_txq_per_tc = num_rxq_per_tc;
+
+ /* find the (rounded up) power-of-2 of qcount */
+ pow = flsl(num_rxq_per_tc - 1);
+
+ /* TC mapping is a function of the number of Rx queues assigned to the
+ * VSI for each traffic class and the offset of these queues.
+ * The first 10 bits are for queue offset for TC0, next 4 bits for no:of
+ * queues allocated to TC0. No:of queues is a power-of-2.
+ *
+ * If TC is not enabled, the queue offset is set to 0, and allocate one
+ * queue, this way, traffic for the given TC will be sent to the default
+ * queue.
+ *
+ * Setup number and offset of Rx queues for all TCs for the VSI
+ */
+ ice_for_each_traffic_class(i) {
+ if (!(vsi->tc_map & BIT(i))) {
+ /* TC is not enabled */
+ vsi->tc_info[i].qoffset = 0;
+ vsi->tc_info[i].qcount_rx = 1;
+ vsi->tc_info[i].qcount_tx = 1;
+
+ ctxt->info.tc_mapping[i] = 0;
+ continue;
+ }
+
+ /* TC is enabled */
+ vsi->tc_info[i].qoffset = offset;
+ vsi->tc_info[i].qcount_rx = num_rxq_per_tc;
+ vsi->tc_info[i].qcount_tx = num_txq_per_tc;
+
+ qmap = ((offset << ICE_AQ_VSI_TC_Q_OFFSET_S) &
+ ICE_AQ_VSI_TC_Q_OFFSET_M) |
+ ((pow << ICE_AQ_VSI_TC_Q_NUM_S) &
+ ICE_AQ_VSI_TC_Q_NUM_M);
+ ctxt->info.tc_mapping[i] = CPU_TO_LE16(qmap);
+
+ /* Store traffic class and handle data in queue structures */
+ for (j = offset, k = 0; j < offset + num_txq_per_tc; j++, k++) {
+ vsi->tx_queues[j].q_handle = k;
+ vsi->tx_queues[j].tc = i;
+ }
+ for (j = offset; j < offset + num_rxq_per_tc; j++)
+ vsi->rx_queues[j].tc = i;
+
+ offset += num_rxq_per_tc;
+ }
+
+ /* Rx queue mapping */
+ ctxt->info.mapping_flags |= CPU_TO_LE16(ICE_AQ_VSI_Q_MAP_CONTIG);
+ ctxt->info.q_mapping[0] = CPU_TO_LE16(vsi->rx_qmap[0]);
+ ctxt->info.q_mapping[1] = CPU_TO_LE16(vsi->num_rx_queues);
+}
+
+/**
+ * ice_pf_vsi_cfg_tc - Configure PF VSI for a given TC map
+ * @sc: the device private softc
+ * @tc_map: traffic class bitmap
+ *
+ * @pre VSI queues are stopped
+ *
+ * @return 0 if configuration is successful
+ * @return EIO if Update VSI AQ cmd fails
+ * @return ENODEV if updating Tx Scheduler fails
+ */
+static int
+ice_pf_vsi_cfg_tc(struct ice_softc *sc, u8 tc_map)
+{
+ u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
+ struct ice_vsi *vsi = &sc->pf_vsi;
+ struct ice_hw *hw = &sc->hw;
+ struct ice_vsi_ctx ctx = { 0 };
+ device_t dev = sc->dev;
+ enum ice_status status;
+ u8 num_tcs = 0;
+ int i = 0;
+
+ /* Count the number of enabled Traffic Classes */
+ ice_for_each_traffic_class(i)
+ if (tc_map & BIT(i))
+ num_tcs++;
+
+ vsi->tc_map = tc_map;
+ vsi->num_tcs = num_tcs;
+
+ /* Set default parameters for context */
+ ctx.vf_num = 0;
+ ctx.info = vsi->info;
+
+ /* Setup queue map */
+ ice_vsi_setup_q_map(vsi, &ctx);
+
+ /* Update VSI configuration in firmware (RX queues) */
+ ctx.info.valid_sections = CPU_TO_LE16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID);
+ status = ice_update_vsi(hw, vsi->idx, &ctx, NULL);
+ if (status) {
+ device_printf(dev,
+ "%s: Update VSI AQ call failed, err %s aq_err %s\n",
+ __func__, ice_status_str(status),
+ ice_aq_str(hw->adminq.sq_last_status));
+ return (EIO);
+ }
+ vsi->info = ctx.info;
+
+ /* Use values derived in ice_vsi_setup_q_map() */
+ for (i = 0; i < num_tcs; i++)
+ max_txqs[i] = vsi->tc_info[i].qcount_tx;
+
+ /* Update LAN Tx queue info in firmware */
+ status = ice_cfg_vsi_lan(hw->port_info, vsi->idx, vsi->tc_map,
+ max_txqs);
+ if (status) {
+ device_printf(dev,
+ "%s: Failed VSI lan queue config, err %s aq_err %s\n",
+ __func__, ice_status_str(status),
+ ice_aq_str(hw->adminq.sq_last_status));
+ return (ENODEV);
+ }
+
+ vsi->info.valid_sections = 0;
+
+ return (0);
+}
+
+/**
+ * ice_dcb_recfg - Reconfigure VSI with new DCB settings
+ * @sc: the device private softc
+ *
+ * @pre All VSIs have been disabled/stopped
+ *
+ * Reconfigures VSI settings based on local_dcbx_cfg.
+ */
+static void
+ice_dcb_recfg(struct ice_softc *sc)
+{
+ struct ice_dcbx_cfg *dcbcfg =
+ &sc->hw.port_info->qos_cfg.local_dcbx_cfg;
+ device_t dev = sc->dev;
+ u8 tc_map = 0;
+ int ret;
+
+ tc_map = ice_dcb_get_tc_map(dcbcfg);
+
+ /* If non-contiguous TCs are used, then configure
+ * the default TC instead. There's no support for
+ * non-contiguous TCs being used.
+ */
+ if (ice_dcb_num_tc(tc_map) == 0) {
+ tc_map = ICE_DFLT_TRAFFIC_CLASS;
+ ice_set_default_local_lldp_mib(sc);
+ }
+
+ /* Reconfigure VSI queues to add/remove traffic classes */
+ ret = ice_pf_vsi_cfg_tc(sc, tc_map);
+ if (ret)
+ device_printf(dev,
+ "Failed to configure TCs for PF VSI, err %s\n",
+ ice_err_str(ret));
+
+}
+
+/**
+ * ice_do_dcb_reconfig - notify RDMA and reconfigure PF LAN VSI
+ * @sc: the device private softc
+ *
+ * @pre Determined that the DCB configuration requires a change
+ *
+ * Reconfigures the PF LAN VSI based on updated DCB configuration
+ * found in the hw struct's/port_info's/ local dcbx configuration.
+ */
+static void
+ice_do_dcb_reconfig(struct ice_softc *sc)
+{
+ struct ice_aqc_port_ets_elem port_ets = { 0 };
+ struct ice_dcbx_cfg *local_dcbx_cfg;
+ struct ice_hw *hw = &sc->hw;
+ struct ice_port_info *pi;
+ device_t dev = sc->dev;
+ enum ice_status status;
+ u8 tc_map;
+
+ pi = sc->hw.port_info;
+ local_dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg;
+
+ /* Set state when there's more than one TC */
+ tc_map = ice_dcb_get_tc_map(local_dcbx_cfg);
+ if (ice_dcb_num_tc(tc_map) > 1) {
+ device_printf(dev, "Multiple traffic classes enabled\n");
+ ice_set_state(&sc->state, ICE_STATE_MULTIPLE_TCS);
+ } else {
+ device_printf(dev, "Multiple traffic classes disabled\n");
+ ice_clear_state(&sc->state, ICE_STATE_MULTIPLE_TCS);
+ }
+
+ /* Disable PF VSI since it's going to be reconfigured */
+ ice_stop_pf_vsi(sc);
+
+ /* Query ETS configuration and update SW Tx scheduler info */
+ status = ice_query_port_ets(pi, &port_ets, sizeof(port_ets), NULL);
+ if (status != ICE_SUCCESS) {
+ device_printf(dev,
+ "Query Port ETS AQ call failed, err %s aq_err %s\n",
+ ice_status_str(status),
+ ice_aq_str(hw->adminq.sq_last_status));
+ /* This won't break traffic, but QoS will not work as expected */
+ }
+
+ /* Change PF VSI configuration */
+ ice_dcb_recfg(sc);
+
+ ice_request_stack_reinit(sc);
+}
+
+/**
+ * ice_handle_mib_change_event - helper function to handle LLDP MIB change events
+ * @sc: the device private softc
+ * @event: event received on a control queue
+ *
+ * Checks the updated MIB it receives and possibly reconfigures the PF LAN
+ * VSI depending on what has changed. This will also print out some debug
+ * information about the MIB event if ICE_DBG_DCB is enabled in the debug_mask.
+ */
+static void
+ice_handle_mib_change_event(struct ice_softc *sc, struct ice_rq_event_info *event)
+{
+ struct ice_aqc_lldp_get_mib *params =
+ (struct ice_aqc_lldp_get_mib *)&event->desc.params.lldp_get_mib;
+ struct ice_dcbx_cfg tmp_dcbx_cfg, *local_dcbx_cfg;
+ struct ice_port_info *pi;
+ device_t dev = sc->dev;
+ struct ice_hw *hw = &sc->hw;
+ bool needs_reconfig;
+ enum ice_status status;
+ u8 mib_type, bridge_type;
+
+ ASSERT_CFG_LOCKED(sc);
+
+ ice_debug_print_mib_change_event(sc, event);
+
+ pi = sc->hw.port_info;
+
+ mib_type = (params->type & ICE_AQ_LLDP_MIB_TYPE_M) >>
+ ICE_AQ_LLDP_MIB_TYPE_S;
+ bridge_type = (params->type & ICE_AQ_LLDP_BRID_TYPE_M) >>
+ ICE_AQ_LLDP_BRID_TYPE_S;
+
+ /* Ignore if event is not for Nearest Bridge */
+ if (bridge_type != ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID)
+ return;
+
+ /* Check MIB Type and return if event for Remote MIB update */
+ if (mib_type == ICE_AQ_LLDP_MIB_REMOTE) {
+ /* Update the cached remote MIB and return */
+ status = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_REMOTE,
+ ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID,
+ &pi->qos_cfg.remote_dcbx_cfg);
+ if (status)
+ device_printf(dev,
+ "%s: Failed to get Remote DCB config; status %s, aq_err %s\n",
+ __func__, ice_status_str(status),
+ ice_aq_str(hw->adminq.sq_last_status));
+ /* Not fatal if this fails */
+ return;
+ }
+
+ /* Save line length by aliasing the local dcbx cfg */
+ local_dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg;
+ /* Save off the old configuration and clear current config */
+ tmp_dcbx_cfg = *local_dcbx_cfg;
+ memset(local_dcbx_cfg, 0, sizeof(*local_dcbx_cfg));
+
+ /* Get updated DCBX data from firmware */
+ status = ice_get_dcb_cfg(pi);
+ if (status) {
+ device_printf(dev,
+ "%s: Failed to get Local DCB config; status %s, aq_err %s\n",
+ __func__, ice_status_str(status),
+ ice_aq_str(hw->adminq.sq_last_status));
+ return;
+ }
+
+ /* No change detected in DCBX config */
+ if (!memcmp(&tmp_dcbx_cfg, local_dcbx_cfg,
+ sizeof(tmp_dcbx_cfg))) {
+ ice_debug(hw, ICE_DBG_DCB, "No change detected in local DCBX configuration\n");
+ return;
+ }
+
+ /* Check to see if DCB needs reconfiguring */
+ needs_reconfig = ice_dcb_needs_reconfig(sc, &tmp_dcbx_cfg,
+ local_dcbx_cfg);
+
+ if (!needs_reconfig)
+ return;
+
+ /* Reconfigure */
+ ice_do_dcb_reconfig(sc);
}
/**
@@ -7441,7 +8450,6 @@ ice_apply_saved_phy_cfg(struct ice_softc *sc, u8 settings)
u64 phy_low, phy_high;
enum ice_status status;
enum ice_fec_mode dflt_fec_mode;
- enum ice_fc_mode dflt_fc_mode;
u16 dflt_user_speed;
if (!settings || settings > ICE_APPLY_LS_FEC_FC) {
@@ -7465,7 +8473,6 @@ ice_apply_saved_phy_cfg(struct ice_softc *sc, u8 settings)
/* Save off initial config parameters */
dflt_user_speed = ice_aq_phy_types_to_link_speeds(phy_low, phy_high);
dflt_fec_mode = ice_caps_to_fec_mode(pcaps.caps, pcaps.link_fec_options);
- dflt_fc_mode = ice_caps_to_fc_mode(pcaps.caps);
/* Setup new PHY config */
ice_copy_phy_caps_to_cfg(pi, &pcaps, &cfg);
@@ -8058,23 +9065,50 @@ ice_free_intr_tracking(struct ice_softc *sc)
/**
* ice_apply_supported_speed_filter - Mask off unsupported speeds
* @report_speeds: bit-field for the desired link speeds
+ * @mod_type: type of module/sgmii connection we have
*
* Given a bitmap of the desired lenient mode link speeds,
* this function will mask off the speeds that are not currently
* supported by the device.
*/
static u16
-ice_apply_supported_speed_filter(u16 report_speeds)
+ice_apply_supported_speed_filter(u16 report_speeds, u8 mod_type)
{
u16 speed_mask;
+ enum { IS_SGMII, IS_SFP, IS_QSFP } module;
+
+ /*
+ * The SFF specification says 0 is unknown, so we'll
+ * treat it like we're connected through SGMII for now.
+ * This may need revisiting if a new type is supported
+ * in the future.
+ */
+ switch (mod_type) {
+ case 0:
+ module = IS_SGMII;
+ break;
+ case 3:
+ module = IS_SFP;
+ break;
+ default:
+ module = IS_QSFP;
+ break;
+ }
- /* We won't offer anything lower than 1G for any part,
- * but we also won't offer anything under 25G for 100G
- * parts or under 10G for 50G parts.
+ /* We won't offer anything lower than 100M for any part,
+ * but we'll need to mask off other speeds based on the
+ * device and module type.
*/
- speed_mask = ~((u16)ICE_AQ_LINK_SPEED_1000MB - 1);
- if (report_speeds & ICE_AQ_LINK_SPEED_50GB)
- speed_mask = ~((u16)ICE_AQ_LINK_SPEED_10GB - 1);
+ speed_mask = ~((u16)ICE_AQ_LINK_SPEED_100MB - 1);
+ if ((report_speeds & ICE_AQ_LINK_SPEED_10GB) && (module == IS_SFP))
+ speed_mask = ~((u16)ICE_AQ_LINK_SPEED_1000MB - 1);
+ if (report_speeds & ICE_AQ_LINK_SPEED_25GB)
+ speed_mask = ~((u16)ICE_AQ_LINK_SPEED_1000MB - 1);
+ if (report_speeds & ICE_AQ_LINK_SPEED_50GB) {
+ speed_mask = ~((u16)ICE_AQ_LINK_SPEED_1000MB - 1);
+ if (module == IS_QSFP)
+ speed_mask = ~((u16)ICE_AQ_LINK_SPEED_10GB - 1);
+ }
if (report_speeds & ICE_AQ_LINK_SPEED_100GB)
speed_mask = ~((u16)ICE_AQ_LINK_SPEED_25GB - 1);
return (report_speeds & speed_mask);
@@ -8303,12 +9337,15 @@ ice_set_default_local_lldp_mib(struct ice_softc *sc)
struct ice_port_info *pi;
device_t dev = sc->dev;
enum ice_status status;
+ u8 maxtcs, maxtcs_ets;
pi = hw->port_info;
+
dcbcfg = &pi->qos_cfg.local_dcbx_cfg;
+ maxtcs = hw->func_caps.common_cap.maxtc;
/* This value is only 3 bits; 8 TCs maps to 0 */
- u8 maxtcs = hw->func_caps.common_cap.maxtc & ICE_IEEE_ETS_MAXTC_M;
+ maxtcs_ets = maxtcs & ICE_IEEE_ETS_MAXTC_M;
/**
* Setup the default settings used by the driver for the Set Local
@@ -8318,10 +9355,8 @@ ice_set_default_local_lldp_mib(struct ice_softc *sc)
memset(dcbcfg, 0, sizeof(*dcbcfg));
dcbcfg->etscfg.willing = 1;
dcbcfg->etscfg.tcbwtable[0] = 100;
- dcbcfg->etscfg.maxtcs = maxtcs;
- dcbcfg->etsrec.willing = 1;
- dcbcfg->etsrec.tcbwtable[0] = 100;
- dcbcfg->etsrec.maxtcs = maxtcs;
+ dcbcfg->etscfg.maxtcs = maxtcs_ets;
+ dcbcfg->etsrec = dcbcfg->etscfg;
dcbcfg->pfc.willing = 1;
dcbcfg->pfc.pfccap = maxtcs;
@@ -8333,3 +9368,352 @@ ice_set_default_local_lldp_mib(struct ice_softc *sc)
ice_status_str(status),
ice_aq_str(hw->adminq.sq_last_status));
}
+
+/**
+ * ice_sbuf_print_ets_cfg - Helper function to print ETS cfg
+ * @sbuf: string buffer to print to
+ * @name: prefix string to use
+ * @ets: structure to pull values from
+ *
+ * A helper function for ice_sysctl_dump_dcbx_cfg(), this
+ * formats the ETS rec and cfg TLVs into text.
+ */
+static void
+ice_sbuf_print_ets_cfg(struct sbuf *sbuf, const char *name, struct ice_dcb_ets_cfg *ets)
+{
+ sbuf_printf(sbuf, "%s.willing: %u\n", name, ets->willing);
+ sbuf_printf(sbuf, "%s.cbs: %u\n", name, ets->cbs);
+ sbuf_printf(sbuf, "%s.maxtcs: %u\n", name, ets->maxtcs);
+
+ sbuf_printf(sbuf, "%s.prio_table:", name);
+ for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++)
+ sbuf_printf(sbuf, " %d", ets->prio_table[i]);
+ sbuf_printf(sbuf, "\n");
+
+ sbuf_printf(sbuf, "%s.tcbwtable:", name);
+ for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++)
+ sbuf_printf(sbuf, " %d", ets->tcbwtable[i]);
+ sbuf_printf(sbuf, "\n");
+
+ sbuf_printf(sbuf, "%s.tsatable:", name);
+ for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++)
+ sbuf_printf(sbuf, " %d", ets->tsatable[i]);
+ sbuf_printf(sbuf, "\n");
+}
+
+/**
+ * ice_sysctl_dump_dcbx_cfg - Print out DCBX/DCB config info
+ * @oidp: sysctl oid structure
+ * @arg1: pointer to private data structure
+ * @arg2: AQ define for either Local or Remote MIB
+ * @req: sysctl request pointer
+ *
+ * Prints out DCB/DCBX configuration, including the contents
+ * of either the local or remote MIB, depending on the value
+ * used in arg2.
+ */
+static int
+ice_sysctl_dump_dcbx_cfg(SYSCTL_HANDLER_ARGS)
+{
+ struct ice_softc *sc = (struct ice_softc *)arg1;
+ struct ice_aqc_get_cee_dcb_cfg_resp cee_cfg = {};
+ struct ice_dcbx_cfg dcb_buf = {};
+ struct ice_dcbx_cfg *dcbcfg;
+ struct ice_hw *hw = &sc->hw;
+ device_t dev = sc->dev;
+ struct sbuf *sbuf;
+ enum ice_status status;
+ u8 maxtcs, dcbx_status, is_sw_lldp;
+
+ UNREFERENCED_PARAMETER(oidp);
+
+ if (ice_driver_is_detaching(sc))
+ return (ESHUTDOWN);
+
+ is_sw_lldp = hw->port_info->qos_cfg.is_sw_lldp;
+
+ /* The driver doesn't receive a Remote MIB via SW */
+ if (is_sw_lldp && arg2 == ICE_AQ_LLDP_MIB_REMOTE)
+ return (ENOENT);
+
+ dcbcfg = &hw->port_info->qos_cfg.local_dcbx_cfg;
+ if (!is_sw_lldp) {
+ /* Collect information from the FW in FW LLDP mode */
+ dcbcfg = &dcb_buf;
+ status = ice_aq_get_dcb_cfg(hw, (u8)arg2,
+ ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID, dcbcfg);
+ if (status && arg2 == ICE_AQ_LLDP_MIB_REMOTE &&
+ hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT) {
+ device_printf(dev,
+ "Unable to query Remote MIB; port has not received one yet\n");
+ return (ENOENT);
+ }
+ if (status) {
+ device_printf(dev, "Unable to query LLDP MIB, err %s aq_err %s\n",
+ ice_status_str(status),
+ ice_aq_str(hw->adminq.sq_last_status));
+ return (EIO);
+ }
+ }
+
+ status = ice_aq_get_cee_dcb_cfg(hw, &cee_cfg, NULL);
+ if (status == ICE_SUCCESS)
+ dcbcfg->dcbx_mode = ICE_DCBX_MODE_CEE;
+ else if (hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT)
+ dcbcfg->dcbx_mode = ICE_DCBX_MODE_IEEE;
+
+ maxtcs = hw->func_caps.common_cap.maxtc;
+ dcbx_status = ice_get_dcbx_status(hw);
+
+ sbuf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
+
+ /* Do the actual printing */
+ sbuf_printf(sbuf, "\n");
+ sbuf_printf(sbuf, "SW LLDP mode: %d\n", is_sw_lldp);
+ sbuf_printf(sbuf, "Function caps maxtcs: %d\n", maxtcs);
+ sbuf_printf(sbuf, "dcbx_status: %d\n", dcbx_status);
+
+ sbuf_printf(sbuf, "numapps: %u\n", dcbcfg->numapps);
+ sbuf_printf(sbuf, "CEE TLV status: %u\n", dcbcfg->tlv_status);
+ sbuf_printf(sbuf, "pfc_mode: %s\n", (dcbcfg->pfc_mode == ICE_QOS_MODE_DSCP) ?
+ "DSCP" : "VLAN");
+ sbuf_printf(sbuf, "dcbx_mode: %s\n",
+ (dcbcfg->dcbx_mode == ICE_DCBX_MODE_IEEE) ? "IEEE" :
+ (dcbcfg->dcbx_mode == ICE_DCBX_MODE_CEE) ? "CEE" :
+ "Unknown");
+
+ ice_sbuf_print_ets_cfg(sbuf, "etscfg", &dcbcfg->etscfg);
+ ice_sbuf_print_ets_cfg(sbuf, "etsrec", &dcbcfg->etsrec);
+
+ sbuf_printf(sbuf, "pfc.willing: %u\n", dcbcfg->pfc.willing);
+ sbuf_printf(sbuf, "pfc.mbc: %u\n", dcbcfg->pfc.mbc);
+ sbuf_printf(sbuf, "pfc.pfccap: 0x%0x\n", dcbcfg->pfc.pfccap);
+ sbuf_printf(sbuf, "pfc.pfcena: 0x%0x\n", dcbcfg->pfc.pfcena);
+
+ if (arg2 == ICE_AQ_LLDP_MIB_LOCAL) {
+ sbuf_printf(sbuf, "\nLocal registers:\n");
+ sbuf_printf(sbuf, "PRTDCB_GENC.NUMTC: %d\n",
+ (rd32(hw, PRTDCB_GENC) & PRTDCB_GENC_NUMTC_M)
+ >> PRTDCB_GENC_NUMTC_S);
+ sbuf_printf(sbuf, "PRTDCB_TUP2TC: 0x%0x\n",
+ (rd32(hw, PRTDCB_TUP2TC)));
+ sbuf_printf(sbuf, "PRTDCB_RUP2TC: 0x%0x\n",
+ (rd32(hw, PRTDCB_RUP2TC)));
+ sbuf_printf(sbuf, "GLDCB_TC2PFC: 0x%0x\n",
+ (rd32(hw, GLDCB_TC2PFC)));
+ }
+
+ /* Finish */
+ sbuf_finish(sbuf);
+ sbuf_delete(sbuf);
+
+ return (0);
+}
+
+/**
+ * ice_sysctl_dump_vsi_cfg - print PF LAN VSI configuration
+ * @oidp: sysctl oid structure
+ * @arg1: pointer to private data structure
+ * @arg2: unused
+ * @req: sysctl request pointer
+ *
+ * XXX: This could be extended to apply to arbitrary PF-owned VSIs,
+ * but for simplicity, this only works on the PF's LAN VSI.
+ */
+static int
+ice_sysctl_dump_vsi_cfg(SYSCTL_HANDLER_ARGS)
+{
+ struct ice_softc *sc = (struct ice_softc *)arg1;
+ struct ice_vsi_ctx ctx = { 0 };
+ struct ice_hw *hw = &sc->hw;
+ device_t dev = sc->dev;
+ struct sbuf *sbuf;
+ enum ice_status status;
+
+ UNREFERENCED_PARAMETER(oidp);
+ UNREFERENCED_PARAMETER(arg2);
+
+ if (ice_driver_is_detaching(sc))
+ return (ESHUTDOWN);
+
+ /* Get HW absolute index of a VSI */
+ ctx.vsi_num = ice_get_hw_vsi_num(hw, sc->pf_vsi.idx);
+
+ status = ice_aq_get_vsi_params(hw, &ctx, NULL);
+ if (status != ICE_SUCCESS) {
+ device_printf(dev,
+ "Get VSI AQ call failed, err %s aq_err %s\n",
+ ice_status_str(status),
+ ice_aq_str(hw->adminq.sq_last_status));
+ return (EIO);
+ }
+
+ sbuf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
+
+ /* Do the actual printing */
+ sbuf_printf(sbuf, "\n");
+
+ sbuf_printf(sbuf, "VSI NUM: %d\n", ctx.vsi_num);
+ sbuf_printf(sbuf, "VF NUM: %d\n", ctx.vf_num);
+ sbuf_printf(sbuf, "VSIs allocated: %d\n", ctx.vsis_allocd);
+ sbuf_printf(sbuf, "VSIs unallocated: %d\n", ctx.vsis_unallocated);
+
+ sbuf_printf(sbuf, "Rx Queue Map method: %d\n",
+ LE16_TO_CPU(ctx.info.mapping_flags));
+ /* The PF VSI is always contiguous, so there's no if-statement here */
+ sbuf_printf(sbuf, "Rx Queue base: %d\n",
+ LE16_TO_CPU(ctx.info.q_mapping[0]));
+ sbuf_printf(sbuf, "Rx Queue count: %d\n",
+ LE16_TO_CPU(ctx.info.q_mapping[1]));
+
+ sbuf_printf(sbuf, "TC qbases :");
+ for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
+ sbuf_printf(sbuf, " %4d",
+ ctx.info.tc_mapping[i] & ICE_AQ_VSI_TC_Q_OFFSET_M);
+ }
+ sbuf_printf(sbuf, "\n");
+
+ sbuf_printf(sbuf, "TC qcounts :");
+ for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
+ sbuf_printf(sbuf, " %4d",
+ 1 << (ctx.info.tc_mapping[i] >> ICE_AQ_VSI_TC_Q_NUM_S));
+ }
+
+ /* Finish */
+ sbuf_finish(sbuf);
+ sbuf_delete(sbuf);
+
+ return (0);
+}
+
+/**
+ * ice_ets_str_to_tbl - Parse string into ETS table
+ * @str: input string to parse
+ * @table: output eight values used for ETS values
+ * @limit: max valid value to accept for ETS values
+ *
+ * Parses a string and converts the eight values within
+ * into a table that can be used in setting ETS settings
+ * in a MIB.
+ *
+ * @return 0 on success, EINVAL if a parsed value is
+ * not between 0 and limit.
+ */
+static int
+ice_ets_str_to_tbl(const char *str, u8 *table, u8 limit)
+{
+ const char *str_start = str;
+ char *str_end;
+ long token;
+
+ for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
+ token = strtol(str_start, &str_end, 0);
+ if (token < 0 || token > limit)
+ return (EINVAL);
+
+ table[i] = (u8)token;
+ str_start = (str_end + 1);
+ }
+
+ return (0);
+}
+
+/**
+ * ice_check_ets_bw - Check if ETS bw vals are valid
+ * @table: eight values used for ETS bandwidth
+ *
+ * @return true if the sum of all 8 values in table
+ * equals 100.
+ */
+static bool
+ice_check_ets_bw(u8 *table)
+{
+ int sum = 0;
+ for (int i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++)
+ sum += (int)table[i];
+
+ return (sum == 100);
+}
+
+/**
+ * ice_cfg_pba_num - Determine if PBA Number is retrievable
+ * @sc: the device private softc structure
+ *
+ * Sets the feature flag for the existence of a PBA number
+ * based on the success of the read command. This does not
+ * cache the result.
+ */
+void
+ice_cfg_pba_num(struct ice_softc *sc)
+{
+ u8 pba_string[32] = "";
+
+ if ((ice_is_bit_set(sc->feat_cap, ICE_FEATURE_HAS_PBA)) &&
+ (ice_read_pba_string(&sc->hw, pba_string, sizeof(pba_string)) == 0))
+ ice_set_bit(ICE_FEATURE_HAS_PBA, sc->feat_en);
+}
+
+/**
+ * ice_sysctl_query_port_ets - print Port ETS Config from AQ
+ * @oidp: sysctl oid structure
+ * @arg1: pointer to private data structure
+ * @arg2: unused
+ * @req: sysctl request pointer
+ */
+static int
+ice_sysctl_query_port_ets(SYSCTL_HANDLER_ARGS)
+{
+ struct ice_softc *sc = (struct ice_softc *)arg1;
+ struct ice_aqc_port_ets_elem port_ets = { 0 };
+ struct ice_hw *hw = &sc->hw;
+ struct ice_port_info *pi;
+ device_t dev = sc->dev;
+ struct sbuf *sbuf;
+ enum ice_status status;
+ int i = 0;
+
+ UNREFERENCED_PARAMETER(oidp);
+ UNREFERENCED_PARAMETER(arg2);
+
+ if (ice_driver_is_detaching(sc))
+ return (ESHUTDOWN);
+
+ pi = hw->port_info;
+
+ status = ice_aq_query_port_ets(pi, &port_ets, sizeof(port_ets), NULL);
+ if (status != ICE_SUCCESS) {
+ device_printf(dev,
+ "Query Port ETS AQ call failed, err %s aq_err %s\n",
+ ice_status_str(status),
+ ice_aq_str(hw->adminq.sq_last_status));
+ return (EIO);
+ }
+
+ sbuf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
+
+ /* Do the actual printing */
+ sbuf_printf(sbuf, "\n");
+
+ sbuf_printf(sbuf, "Valid TC map: 0x%x\n", port_ets.tc_valid_bits);
+
+ sbuf_printf(sbuf, "TC BW %%:");
+ ice_for_each_traffic_class(i) {
+ sbuf_printf(sbuf, " %3d", port_ets.tc_bw_share[i]);
+ }
+ sbuf_printf(sbuf, "\n");
+
+ sbuf_printf(sbuf, "EIR profile ID: %d\n", port_ets.port_eir_prof_id);
+ sbuf_printf(sbuf, "CIR profile ID: %d\n", port_ets.port_cir_prof_id);
+ sbuf_printf(sbuf, "TC Node prio: 0x%x\n", port_ets.tc_node_prio);
+
+ sbuf_printf(sbuf, "TC Node TEIDs:\n");
+ ice_for_each_traffic_class(i) {
+ sbuf_printf(sbuf, "%d: %d\n", i, port_ets.tc_node_teid[i]);
+ }
+
+ /* Finish */
+ sbuf_finish(sbuf);
+ sbuf_delete(sbuf);
+
+ return (0);
+}
diff --git a/sys/dev/ice/ice_lib.h b/sys/dev/ice/ice_lib.h
index d8abe1ea9783..d0514a58a745 100644
--- a/sys/dev/ice/ice_lib.h
+++ b/sys/dev/ice/ice_lib.h
@@ -151,6 +151,8 @@ struct ice_bar_info {
#define ICE_MSIX_BAR 3
+#define ICE_MAX_DCB_TCS 8
+
#define ICE_DEFAULT_DESC_COUNT 1024
#define ICE_MAX_DESC_COUNT 8160
#define ICE_MIN_DESC_COUNT 64
@@ -199,7 +201,7 @@ struct ice_bar_info {
#define ICE_NVM_ACCESS \
(((((((('E' << 4) + '1') << 4) + 'K') << 4) + 'G') << 4) | 5)
-#define ICE_AQ_LEN 512
+#define ICE_AQ_LEN 1023
#define ICE_MBXQ_LEN 512
#define ICE_SBQ_LEN 512
@@ -247,6 +249,11 @@ struct ice_bar_info {
#define ICE_DEFAULT_VF_QUEUES 4
/*
+ * The maximum number of RX queues allowed per TC in a VSI.
+ */
+#define ICE_MAX_RXQS_PER_TC 256
+
+/*
* There are three settings that can be updated independently or
* altogether: Link speed, FEC, and Flow Control. These macros allow
* the caller to specify which setting(s) to update.
@@ -464,6 +471,19 @@ struct ice_pf_sw_stats {
};
/**
+ * @struct ice_tc_info
+ * @brief Traffic class information for a VSI
+ *
+ * Stores traffic class information used in configuring
+ * a VSI.
+ */
+struct ice_tc_info {
+ u16 qoffset; /* Offset in VSI queue space */
+ u16 qcount_tx; /* TX queues for this Traffic Class */
+ u16 qcount_rx; /* RX queues */
+};
+
+/**
* @struct ice_vsi
* @brief VSI structure
*
@@ -504,6 +524,12 @@ struct ice_vsi {
struct ice_aqc_vsi_props info;
+ /* DCB configuration */
+ u8 num_tcs; /* Total number of enabled TCs */
+ u16 tc_map; /* bitmap of enabled Traffic Classes */
+ /* Information for each traffic class */
+ struct ice_tc_info tc_info[ICE_MAX_TRAFFIC_CLASS];
+
/* context for per-VSI sysctls */
struct sysctl_ctx_list ctx;
struct sysctl_oid *vsi_node;
@@ -541,9 +567,11 @@ enum ice_state {
ICE_STATE_RECOVERY_MODE,
ICE_STATE_ROLLBACK_MODE,
ICE_STATE_LINK_STATUS_REPORTED,
+ ICE_STATE_ATTACHING,
ICE_STATE_DETACHING,
ICE_STATE_LINK_DEFAULT_OVERRIDE_PENDING,
ICE_STATE_LLDP_RX_FLTR_FROM_DRIVER,
+ ICE_STATE_MULTIPLE_TCS,
/* This entry must be last */
ICE_STATE_LAST,
};
@@ -648,6 +676,7 @@ struct ice_str_buf _ice_aq_str(enum ice_aq_err aq_err);
struct ice_str_buf _ice_status_str(enum ice_status status);
struct ice_str_buf _ice_err_str(int err);
struct ice_str_buf _ice_fltr_flag_str(u16 flag);
+struct ice_str_buf _ice_log_sev_str(u8 log_level);
struct ice_str_buf _ice_mdd_tx_tclan_str(u8 event);
struct ice_str_buf _ice_mdd_tx_pqm_str(u8 event);
struct ice_str_buf _ice_mdd_rx_str(u8 event);
@@ -662,6 +691,7 @@ struct ice_str_buf _ice_fw_lldp_status(u32 lldp_status);
#define ice_mdd_tx_pqm_str(event) _ice_mdd_tx_pqm_str(event).str
#define ice_mdd_rx_str(event) _ice_mdd_rx_str(event).str
+#define ice_log_sev_str(log_level) _ice_log_sev_str(log_level).str
#define ice_fw_lldp_status(lldp_status) _ice_fw_lldp_status(lldp_status).str
/**
@@ -738,6 +768,12 @@ void ice_request_stack_reinit(struct ice_softc *sc);
/* Details of how to check if the network stack is detaching us */
bool ice_driver_is_detaching(struct ice_softc *sc);
+const char * ice_fw_module_str(enum ice_aqc_fw_logging_mod module);
+void ice_add_fw_logging_tunables(struct ice_softc *sc,
+ struct sysctl_oid *parent);
+void ice_handle_fw_log_event(struct ice_softc *sc, struct ice_aq_desc *desc,
+ void *buf);
+
int ice_process_ctrlq(struct ice_softc *sc, enum ice_ctl_q q_type, u16 *pending);
int ice_map_bar(device_t dev, struct ice_bar_info *bar, int bar_num);
void ice_free_bar(device_t dev, struct ice_bar_info *bar);
@@ -826,5 +862,6 @@ int ice_alloc_intr_tracking(struct ice_softc *sc);
void ice_free_intr_tracking(struct ice_softc *sc);
void ice_set_default_local_lldp_mib(struct ice_softc *sc);
void ice_init_health_events(struct ice_softc *sc);
+void ice_cfg_pba_num(struct ice_softc *sc);
#endif /* _ICE_LIB_H_ */
diff --git a/sys/dev/ice/ice_nvm.c b/sys/dev/ice/ice_nvm.c
index 66ee4188c8c0..d4ec3cbb1bcd 100644
--- a/sys/dev/ice/ice_nvm.c
+++ b/sys/dev/ice/ice_nvm.c
@@ -32,6 +32,8 @@
#include "ice_common.h"
+#define GL_MNG_DEF_DEVID 0x000B611C
+
/**
* ice_aq_read_nvm
* @hw: pointer to the HW struct
@@ -584,6 +586,42 @@ ice_read_nvm_module(struct ice_hw *hw, enum ice_bank_select bank, u32 offset, u1
}
/**
+ * ice_get_nvm_css_hdr_len - Read the CSS header length from the NVM CSS header
+ * @hw: pointer to the HW struct
+ * @bank: whether to read from the active or inactive flash bank
+ * @hdr_len: storage for header length in words
+ *
+ * Read the CSS header length from the NVM CSS header and add the Authentication
+ * header size, and then convert to words.
+ */
+static enum ice_status
+ice_get_nvm_css_hdr_len(struct ice_hw *hw, enum ice_bank_select bank,
+ u32 *hdr_len)
+{
+ u16 hdr_len_l, hdr_len_h;
+ enum ice_status status;
+ u32 hdr_len_dword;
+
+ status = ice_read_nvm_module(hw, bank, ICE_NVM_CSS_HDR_LEN_L,
+ &hdr_len_l);
+ if (status)
+ return status;
+
+ status = ice_read_nvm_module(hw, bank, ICE_NVM_CSS_HDR_LEN_H,
+ &hdr_len_h);
+ if (status)
+ return status;
+
+ /* CSS header length is in DWORD, so convert to words and add
+ * authentication header size
+ */
+ hdr_len_dword = hdr_len_h << 16 | hdr_len_l;
+ *hdr_len = (hdr_len_dword * 2) + ICE_NVM_AUTH_HEADER_LEN;
+
+ return ICE_SUCCESS;
+}
+
+/**
* ice_read_nvm_sr_copy - Read a word from the Shadow RAM copy in the NVM bank
* @hw: pointer to the HW structure
* @bank: whether to read from the active or inactive NVM module
@@ -596,7 +634,16 @@ ice_read_nvm_module(struct ice_hw *hw, enum ice_bank_select bank, u32 offset, u1
static enum ice_status
ice_read_nvm_sr_copy(struct ice_hw *hw, enum ice_bank_select bank, u32 offset, u16 *data)
{
- return ice_read_nvm_module(hw, bank, ICE_NVM_SR_COPY_WORD_OFFSET + offset, data);
+ enum ice_status status;
+ u32 hdr_len;
+
+ status = ice_get_nvm_css_hdr_len(hw, bank, &hdr_len);
+ if (status)
+ return status;
+
+ hdr_len = ROUND_UP(hdr_len, 32);
+
+ return ice_read_nvm_module(hw, bank, hdr_len + offset, data);
}
/**
@@ -889,22 +936,26 @@ enum ice_status ice_get_inactive_nvm_ver(struct ice_hw *hw, struct ice_nvm_info
*/
static enum ice_status ice_get_orom_srev(struct ice_hw *hw, enum ice_bank_select bank, u32 *srev)
{
+ u32 orom_size_word = hw->flash.banks.orom_size / 2;
enum ice_status status;
u16 srev_l, srev_h;
u32 css_start;
+ u32 hdr_len;
- if (hw->flash.banks.orom_size < ICE_NVM_OROM_TRAILER_LENGTH) {
+ status = ice_get_nvm_css_hdr_len(hw, bank, &hdr_len);
+ if (status)
+ return status;
+
+ if (orom_size_word < hdr_len) {
ice_debug(hw, ICE_DBG_NVM, "Unexpected Option ROM Size of %u\n",
hw->flash.banks.orom_size);
return ICE_ERR_CFG;
}
/* calculate how far into the Option ROM the CSS header starts. Note
- * that ice_read_orom_module takes a word offset so we need to
- * divide by 2 here.
+ * that ice_read_orom_module takes a word offset
*/
- css_start = (hw->flash.banks.orom_size - ICE_NVM_OROM_TRAILER_LENGTH) / 2;
-
+ css_start = orom_size_word - hdr_len;
status = ice_read_orom_module(hw, bank, css_start + ICE_NVM_CSS_SREV_L, &srev_l);
if (status)
return status;
@@ -956,7 +1007,6 @@ ice_get_orom_civd_data(struct ice_hw *hw, enum ice_bank_select bank,
/* Verify that the simple checksum is zero */
for (i = 0; i < sizeof(tmp); i++)
- /* cppcheck-suppress objectIndex */
sum += ((u8 *)&tmp)[i];
if (sum) {
@@ -1908,6 +1958,7 @@ ice_validate_nvm_rw_reg(struct ice_nvm_access_cmd *cmd)
case GLGEN_CSR_DEBUG_C:
case GLGEN_RSTAT:
case GLPCI_LBARCTRL:
+ case GL_MNG_DEF_DEVID:
case GLNVM_GENS:
case GLNVM_FLA:
case PF_FUNC_RID:
@@ -1916,11 +1967,11 @@ ice_validate_nvm_rw_reg(struct ice_nvm_access_cmd *cmd)
break;
}
- for (i = 0; i <= ICE_NVM_ACCESS_GL_HIDA_MAX; i++)
+ for (i = 0; i <= GL_HIDA_MAX_INDEX; i++)
if (offset == (u32)GL_HIDA(i))
return ICE_SUCCESS;
- for (i = 0; i <= ICE_NVM_ACCESS_GL_HIBA_MAX; i++)
+ for (i = 0; i <= GL_HIBA_MAX_INDEX; i++)
if (offset == (u32)GL_HIBA(i))
return ICE_SUCCESS;
diff --git a/sys/dev/ice/ice_nvm.h b/sys/dev/ice/ice_nvm.h
index 640b1a16560c..b53e7d9fe91f 100644
--- a/sys/dev/ice/ice_nvm.h
+++ b/sys/dev/ice/ice_nvm.h
@@ -94,19 +94,6 @@ union ice_nvm_access_data {
struct ice_nvm_features drv_features; /* NVM features */
};
-/* NVM Access registers */
-#define GL_HIDA(_i) (0x00082000 + ((_i) * 4))
-#define GL_HIBA(_i) (0x00081000 + ((_i) * 4))
-#define GL_HICR 0x00082040
-#define GL_HICR_EN 0x00082044
-#define GLGEN_CSR_DEBUG_C 0x00075750
-#define GLPCI_LBARCTRL 0x0009DE74
-#define GLNVM_GENS 0x000B6100
-#define GLNVM_FLA 0x000B6108
-
-#define ICE_NVM_ACCESS_GL_HIDA_MAX 15
-#define ICE_NVM_ACCESS_GL_HIBA_MAX 1023
-
u32 ice_nvm_access_get_module(struct ice_nvm_access_cmd *cmd);
u32 ice_nvm_access_get_flags(struct ice_nvm_access_cmd *cmd);
u32 ice_nvm_access_get_adapter(struct ice_nvm_access_cmd *cmd);
diff --git a/sys/dev/ice/ice_osdep.c b/sys/dev/ice/ice_osdep.c
index 2587341faa38..ef1179614ad0 100644
--- a/sys/dev/ice/ice_osdep.c
+++ b/sys/dev/ice/ice_osdep.c
@@ -146,6 +146,42 @@ ice_debug_array(struct ice_hw *hw, uint64_t mask, uint32_t rowsize,
}
/**
+ * ice_info_fwlog - Format and print an array of values to the console
+ * @hw: private hardware structure
+ * @rowsize: preferred number of rows to use
+ * @groupsize: preferred size in bytes to print each chunk
+ * @buf: the array buffer to print
+ * @len: size of the array buffer
+ *
+ * Format the given array as a series of uint8_t values with hexadecimal
+ * notation and log the contents to the console log. This variation is
+ * specific to firmware logging.
+ *
+ * TODO: Currently only supports a group size of 1, due to the way hexdump is
+ * implemented.
+ */
+void
+ice_info_fwlog(struct ice_hw *hw, uint32_t rowsize, uint32_t __unused groupsize,
+ uint8_t *buf, size_t len)
+{
+ device_t dev = ice_hw_to_dev(hw);
+ char prettyname[20];
+
+ if (!ice_fwlog_supported(hw))
+ return;
+
+ /* Format the device header to a string */
+ snprintf(prettyname, sizeof(prettyname), "%s: FWLOG: ",
+ device_get_nameunit(dev));
+
+ /* Make sure the row-size isn't too large */
+ if (rowsize > 0xFF)
+ rowsize = 0xFF;
+
+ hexdump(buf, len, prettyname, HD_OMIT_CHARS | rowsize);
+}
+
+/**
* rd32 - Read a 32bit hardware register value
* @hw: the private hardware structure
* @reg: register address to read
diff --git a/sys/dev/ice/ice_osdep.h b/sys/dev/ice/ice_osdep.h
index 0c7d42911fb0..f8d33b72ceb6 100644
--- a/sys/dev/ice/ice_osdep.h
+++ b/sys/dev/ice/ice_osdep.h
@@ -69,6 +69,8 @@ device_t ice_hw_to_dev(struct ice_hw *hw);
void ice_debug(struct ice_hw *hw, uint64_t mask, char *fmt, ...) __printflike(3, 4);
void ice_debug_array(struct ice_hw *hw, uint64_t mask, uint32_t rowsize,
uint32_t groupsize, uint8_t *buf, size_t len);
+void ice_info_fwlog(struct ice_hw *hw, uint32_t rowsize, uint32_t groupsize,
+ uint8_t *buf, size_t len);
#define ice_info(_hw, _fmt, args...) \
device_printf(ice_hw_to_dev(_hw), (_fmt), ##args)
diff --git a/sys/dev/ice/ice_protocol_type.h b/sys/dev/ice/ice_protocol_type.h
index 94e9aad5a5c1..f20efa766113 100644
--- a/sys/dev/ice/ice_protocol_type.h
+++ b/sys/dev/ice/ice_protocol_type.h
@@ -96,10 +96,20 @@ enum ice_sw_tunnel_type {
ICE_SW_TUN_IPV6_GTP_IPV4_UDP,
ICE_SW_TUN_IPV6_GTP_IPV6_TCP,
ICE_SW_TUN_IPV6_GTP_IPV6_UDP,
+
+ /* following adds support for GTP, just using inner protocols,
+ * outer L3 and L4 protocols can be anything
+ */
+ ICE_SW_TUN_GTP_IPV4_TCP,
+ ICE_SW_TUN_GTP_IPV4_UDP,
+ ICE_SW_TUN_GTP_IPV6_TCP,
+ ICE_SW_TUN_GTP_IPV6_UDP,
ICE_SW_TUN_IPV4_GTPU_IPV4,
ICE_SW_TUN_IPV4_GTPU_IPV6,
ICE_SW_TUN_IPV6_GTPU_IPV4,
ICE_SW_TUN_IPV6_GTPU_IPV6,
+ ICE_SW_TUN_GTP_IPV4,
+ ICE_SW_TUN_GTP_IPV6,
ICE_ALL_TUNNELS /* All tunnel types including NVGRE */
};
@@ -127,8 +137,10 @@ enum ice_prot_id {
ICE_PROT_MPLS_IL = 29,
ICE_PROT_IPV4_OF_OR_S = 32,
ICE_PROT_IPV4_IL = 33,
+ ICE_PROT_IPV4_IL_IL = 34,
ICE_PROT_IPV6_OF_OR_S = 40,
ICE_PROT_IPV6_IL = 41,
+ ICE_PROT_IPV6_IL_IL = 42,
ICE_PROT_IPV6_FRAG = 47,
ICE_PROT_TCP_IL = 49,
ICE_PROT_UDP_OF = 52,
@@ -205,8 +217,8 @@ struct ice_ether_vlan_hdr {
};
struct ice_vlan_hdr {
- __be16 vlan;
__be16 type;
+ __be16 vlan;
};
struct ice_ipv4_hdr {
diff --git a/sys/dev/ice/ice_sched.c b/sys/dev/ice/ice_sched.c
index ab9b888ceac0..206f208886b6 100644
--- a/sys/dev/ice/ice_sched.c
+++ b/sys/dev/ice/ice_sched.c
@@ -1062,7 +1062,6 @@ ice_sched_add_nodes_to_layer(struct ice_port_info *pi,
*num_nodes_added = 0;
while (*num_nodes_added < num_nodes) {
u16 max_child_nodes, num_added = 0;
- /* cppcheck-suppress unusedVariable */
u32 temp;
status = ice_sched_add_nodes_to_hw_layer(pi, tc_node, parent,
@@ -2013,7 +2012,7 @@ ice_sched_cfg_vsi(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u16 maxqs,
}
/**
- * ice_sched_rm_agg_vsi_entry - remove aggregator related VSI info entry
+ * ice_sched_rm_agg_vsi_info - remove aggregator related VSI info entry
* @pi: port information structure
* @vsi_handle: software VSI handle
*
@@ -2870,8 +2869,8 @@ static enum ice_status
ice_sched_assoc_vsi_to_agg(struct ice_port_info *pi, u32 agg_id,
u16 vsi_handle, ice_bitmap_t *tc_bitmap)
{
- struct ice_sched_agg_vsi_info *agg_vsi_info;
- struct ice_sched_agg_info *agg_info;
+ struct ice_sched_agg_vsi_info *agg_vsi_info, *old_agg_vsi_info = NULL;
+ struct ice_sched_agg_info *agg_info, *old_agg_info;
enum ice_status status = ICE_SUCCESS;
struct ice_hw *hw = pi->hw;
u8 tc;
@@ -2881,6 +2880,20 @@ ice_sched_assoc_vsi_to_agg(struct ice_port_info *pi, u32 agg_id,
agg_info = ice_get_agg_info(hw, agg_id);
if (!agg_info)
return ICE_ERR_PARAM;
+ /* If the vsi is already part of another aggregator then update
+ * its vsi info list
+ */
+ old_agg_info = ice_get_vsi_agg_info(hw, vsi_handle);
+ if (old_agg_info && old_agg_info != agg_info) {
+ struct ice_sched_agg_vsi_info *vtmp;
+
+ LIST_FOR_EACH_ENTRY_SAFE(old_agg_vsi_info, vtmp,
+ &old_agg_info->agg_vsi_list,
+ ice_sched_agg_vsi_info, list_entry)
+ if (old_agg_vsi_info->vsi_handle == vsi_handle)
+ break;
+ }
+
/* check if entry already exist */
agg_vsi_info = ice_get_agg_vsi_info(agg_info, vsi_handle);
if (!agg_vsi_info) {
@@ -2905,6 +2918,12 @@ ice_sched_assoc_vsi_to_agg(struct ice_port_info *pi, u32 agg_id,
break;
ice_set_bit(tc, agg_vsi_info->tc_bitmap);
+ if (old_agg_vsi_info)
+ ice_clear_bit(tc, old_agg_vsi_info->tc_bitmap);
+ }
+ if (old_agg_vsi_info && !old_agg_vsi_info->tc_bitmap[0]) {
+ LIST_DEL(&old_agg_vsi_info->list_entry);
+ ice_free(pi->hw, old_agg_vsi_info);
}
return status;
}
@@ -2954,6 +2973,9 @@ ice_sched_update_elem(struct ice_hw *hw, struct ice_sched_node *node,
u16 num_elems = 1;
buf = *info;
+ /* For TC nodes, CIR config is not supported */
+ if (node->info.data.elem_type == ICE_AQC_ELEM_TYPE_TC)
+ buf.data.valid_sections &= ~ICE_AQC_ELEM_VALID_CIR;
/* Parent TEID is reserved field in this aq call */
buf.parent_teid = 0;
/* Element type is reserved field in this aq call */
@@ -3389,7 +3411,7 @@ ice_cfg_vsi_bw_lmt_per_tc(struct ice_port_info *pi, u16 vsi_handle, u8 tc,
}
/**
- * ice_cfg_dflt_vsi_bw_lmt_per_tc - configure default VSI BW limit per TC
+ * ice_cfg_vsi_bw_dflt_lmt_per_tc - configure default VSI BW limit per TC
* @pi: port information structure
* @vsi_handle: software VSI handle
* @tc: traffic class
@@ -3544,7 +3566,7 @@ ice_cfg_agg_bw_no_shared_lmt(struct ice_port_info *pi, u32 agg_id)
}
/**
- * ice_cfg_agg_bw_shared_lmt_per_tc - configure aggregator BW shared limit per tc
+ * ice_cfg_agg_bw_shared_lmt_per_tc - config aggregator BW shared limit per tc
* @pi: port information structure
* @agg_id: aggregator ID
* @tc: traffic class
@@ -3564,7 +3586,7 @@ ice_cfg_agg_bw_shared_lmt_per_tc(struct ice_port_info *pi, u32 agg_id, u8 tc,
}
/**
- * ice_cfg_agg_bw_shared_lmt_per_tc - configure aggregator BW shared limit per tc
+ * ice_cfg_agg_bw_no_shared_lmt_per_tc - cfg aggregator BW shared limit per tc
* @pi: port information structure
* @agg_id: aggregator ID
* @tc: traffic class
@@ -3582,7 +3604,7 @@ ice_cfg_agg_bw_no_shared_lmt_per_tc(struct ice_port_info *pi, u32 agg_id, u8 tc)
}
/**
- * ice_config_vsi_queue_priority - config VSI queue priority of node
+ * ice_cfg_vsi_q_priority - config VSI queue priority of node
* @pi: port information structure
* @num_qs: number of VSI queues
* @q_ids: queue IDs array
@@ -3678,7 +3700,6 @@ ice_cfg_agg_vsi_priority_per_tc(struct ice_port_info *pi, u32 agg_id,
LIST_FOR_EACH_ENTRY(agg_vsi_info, &agg_info->agg_vsi_list,
ice_sched_agg_vsi_info, list_entry)
if (agg_vsi_info->vsi_handle == vsi_handle) {
- /* cppcheck-suppress unreadVariable */
vsi_handle_valid = true;
break;
}
@@ -3837,8 +3858,8 @@ static u16 ice_sched_calc_wakeup(struct ice_hw *hw, s32 bw)
u16 wakeup = 0;
/* Get the wakeup integer value */
- bytes_per_sec = DIV_64BIT(((s64)bw * 1000), BITS_PER_BYTE);
- wakeup_int = DIV_64BIT(hw->psm_clk_freq, bytes_per_sec);
+ bytes_per_sec = DIV_S64(bw * 1000, BITS_PER_BYTE);
+ wakeup_int = DIV_S64(hw->psm_clk_freq, bytes_per_sec);
if (wakeup_int > 63) {
wakeup = (u16)((1 << 15) | wakeup_int);
} else {
@@ -3846,18 +3867,18 @@ static u16 ice_sched_calc_wakeup(struct ice_hw *hw, s32 bw)
* Convert Integer value to a constant multiplier
*/
wakeup_b = (s64)ICE_RL_PROF_MULTIPLIER * wakeup_int;
- wakeup_a = DIV_64BIT((s64)ICE_RL_PROF_MULTIPLIER *
- hw->psm_clk_freq, bytes_per_sec);
+ wakeup_a = DIV_S64(ICE_RL_PROF_MULTIPLIER *
+ hw->psm_clk_freq, bytes_per_sec);
/* Get Fraction value */
wakeup_f = wakeup_a - wakeup_b;
/* Round up the Fractional value via Ceil(Fractional value) */
- if (wakeup_f > DIV_64BIT(ICE_RL_PROF_MULTIPLIER, 2))
+ if (wakeup_f > DIV_S64(ICE_RL_PROF_MULTIPLIER, 2))
wakeup_f += 1;
- wakeup_f_int = (s32)DIV_64BIT(wakeup_f * ICE_RL_PROF_FRACTION,
- ICE_RL_PROF_MULTIPLIER);
+ wakeup_f_int = (s32)DIV_S64(wakeup_f * ICE_RL_PROF_FRACTION,
+ ICE_RL_PROF_MULTIPLIER);
wakeup |= (u16)(wakeup_int << 9);
wakeup |= (u16)(0x1ff & wakeup_f_int);
}
@@ -3889,20 +3910,20 @@ ice_sched_bw_to_rl_profile(struct ice_hw *hw, u32 bw,
return status;
/* Bytes per second from Kbps */
- bytes_per_sec = DIV_64BIT(((s64)bw * 1000), BITS_PER_BYTE);
+ bytes_per_sec = DIV_S64(bw * 1000, BITS_PER_BYTE);
/* encode is 6 bits but really useful are 5 bits */
for (i = 0; i < 64; i++) {
u64 pow_result = BIT_ULL(i);
- ts_rate = DIV_64BIT((s64)hw->psm_clk_freq,
- pow_result * ICE_RL_PROF_TS_MULTIPLIER);
+ ts_rate = DIV_S64(hw->psm_clk_freq,
+ pow_result * ICE_RL_PROF_TS_MULTIPLIER);
if (ts_rate <= 0)
continue;
/* Multiplier value */
- mv_tmp = DIV_64BIT(bytes_per_sec * ICE_RL_PROF_MULTIPLIER,
- ts_rate);
+ mv_tmp = DIV_S64(bytes_per_sec * ICE_RL_PROF_MULTIPLIER,
+ ts_rate);
/* Round to the nearest ICE_RL_PROF_MULTIPLIER */
mv = round_up_64bit(mv_tmp, ICE_RL_PROF_MULTIPLIER);
diff --git a/sys/dev/ice/ice_sriov.c b/sys/dev/ice/ice_sriov.c
deleted file mode 100644
index 2dced0ede171..000000000000
--- a/sys/dev/ice/ice_sriov.c
+++ /dev/null
@@ -1,596 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause */
-/* Copyright (c) 2021, Intel Corporation
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-/*$FreeBSD$*/
-
-#include "ice_common.h"
-#include "ice_sriov.h"
-
-/**
- * ice_aq_send_msg_to_vf
- * @hw: pointer to the hardware structure
- * @vfid: VF ID to send msg
- * @v_opcode: opcodes for VF-PF communication
- * @v_retval: return error code
- * @msg: pointer to the msg buffer
- * @msglen: msg length
- * @cd: pointer to command details
- *
- * Send message to VF driver (0x0802) using mailbox
- * queue and asynchronously sending message via
- * ice_sq_send_cmd() function
- */
-enum ice_status
-ice_aq_send_msg_to_vf(struct ice_hw *hw, u16 vfid, u32 v_opcode, u32 v_retval,
- u8 *msg, u16 msglen, struct ice_sq_cd *cd)
-{
- struct ice_aqc_pf_vf_msg *cmd;
- struct ice_aq_desc desc;
-
- ice_fill_dflt_direct_cmd_desc(&desc, ice_mbx_opc_send_msg_to_vf);
-
- cmd = &desc.params.virt;
- cmd->id = CPU_TO_LE32(vfid);
-
- desc.cookie_high = CPU_TO_LE32(v_opcode);
- desc.cookie_low = CPU_TO_LE32(v_retval);
-
- if (msglen)
- desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
-
- return ice_sq_send_cmd(hw, &hw->mailboxq, &desc, msg, msglen, cd);
-}
-
-/**
- * ice_aq_send_msg_to_pf
- * @hw: pointer to the hardware structure
- * @v_opcode: opcodes for VF-PF communication
- * @v_retval: return error code
- * @msg: pointer to the msg buffer
- * @msglen: msg length
- * @cd: pointer to command details
- *
- * Send message to PF driver using mailbox queue. By default, this
- * message is sent asynchronously, i.e. ice_sq_send_cmd()
- * does not wait for completion before returning.
- */
-enum ice_status
-ice_aq_send_msg_to_pf(struct ice_hw *hw, enum virtchnl_ops v_opcode,
- enum ice_status v_retval, u8 *msg, u16 msglen,
- struct ice_sq_cd *cd)
-{
- struct ice_aq_desc desc;
-
- ice_fill_dflt_direct_cmd_desc(&desc, ice_mbx_opc_send_msg_to_pf);
- desc.cookie_high = CPU_TO_LE32(v_opcode);
- desc.cookie_low = CPU_TO_LE32(v_retval);
-
- if (msglen)
- desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
-
- return ice_sq_send_cmd(hw, &hw->mailboxq, &desc, msg, msglen, cd);
-}
-
-/**
- * ice_conv_link_speed_to_virtchnl
- * @adv_link_support: determines the format of the returned link speed
- * @link_speed: variable containing the link_speed to be converted
- *
- * Convert link speed supported by HW to link speed supported by virtchnl.
- * If adv_link_support is true, then return link speed in Mbps. Else return
- * link speed as a VIRTCHNL_LINK_SPEED_* casted to a u32. Note that the caller
- * needs to cast back to an enum virtchnl_link_speed in the case where
- * adv_link_support is false, but when adv_link_support is true the caller can
- * expect the speed in Mbps.
- */
-u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed)
-{
- u32 speed;
-
- if (adv_link_support)
- switch (link_speed) {
- case ICE_AQ_LINK_SPEED_10MB:
- speed = ICE_LINK_SPEED_10MBPS;
- break;
- case ICE_AQ_LINK_SPEED_100MB:
- speed = ICE_LINK_SPEED_100MBPS;
- break;
- case ICE_AQ_LINK_SPEED_1000MB:
- speed = ICE_LINK_SPEED_1000MBPS;
- break;
- case ICE_AQ_LINK_SPEED_2500MB:
- speed = ICE_LINK_SPEED_2500MBPS;
- break;
- case ICE_AQ_LINK_SPEED_5GB:
- speed = ICE_LINK_SPEED_5000MBPS;
- break;
- case ICE_AQ_LINK_SPEED_10GB:
- speed = ICE_LINK_SPEED_10000MBPS;
- break;
- case ICE_AQ_LINK_SPEED_20GB:
- speed = ICE_LINK_SPEED_20000MBPS;
- break;
- case ICE_AQ_LINK_SPEED_25GB:
- speed = ICE_LINK_SPEED_25000MBPS;
- break;
- case ICE_AQ_LINK_SPEED_40GB:
- speed = ICE_LINK_SPEED_40000MBPS;
- break;
- case ICE_AQ_LINK_SPEED_50GB:
- speed = ICE_LINK_SPEED_50000MBPS;
- break;
- case ICE_AQ_LINK_SPEED_100GB:
- speed = ICE_LINK_SPEED_100000MBPS;
- break;
- default:
- speed = ICE_LINK_SPEED_UNKNOWN;
- break;
- }
- else
- /* Virtchnl speeds are not defined for every speed supported in
- * the hardware. To maintain compatibility with older AVF
- * drivers, while reporting the speed the new speed values are
- * resolved to the closest known virtchnl speeds
- */
- switch (link_speed) {
- case ICE_AQ_LINK_SPEED_10MB:
- case ICE_AQ_LINK_SPEED_100MB:
- speed = (u32)VIRTCHNL_LINK_SPEED_100MB;
- break;
- case ICE_AQ_LINK_SPEED_1000MB:
- case ICE_AQ_LINK_SPEED_2500MB:
- case ICE_AQ_LINK_SPEED_5GB:
- speed = (u32)VIRTCHNL_LINK_SPEED_1GB;
- break;
- case ICE_AQ_LINK_SPEED_10GB:
- speed = (u32)VIRTCHNL_LINK_SPEED_10GB;
- break;
- case ICE_AQ_LINK_SPEED_20GB:
- speed = (u32)VIRTCHNL_LINK_SPEED_20GB;
- break;
- case ICE_AQ_LINK_SPEED_25GB:
- speed = (u32)VIRTCHNL_LINK_SPEED_25GB;
- break;
- case ICE_AQ_LINK_SPEED_40GB:
- case ICE_AQ_LINK_SPEED_50GB:
- case ICE_AQ_LINK_SPEED_100GB:
- speed = (u32)VIRTCHNL_LINK_SPEED_40GB;
- break;
- default:
- speed = (u32)VIRTCHNL_LINK_SPEED_UNKNOWN;
- break;
- }
-
- return speed;
-}
-
-/* The mailbox overflow detection algorithm helps to check if there
- * is a possibility of a malicious VF transmitting too many MBX messages to the
- * PF.
- * 1. The mailbox snapshot structure, ice_mbx_snapshot, is initialized during
- * driver initialization in ice_init_hw() using ice_mbx_init_snapshot().
- * The struct ice_mbx_snapshot helps to track and traverse a static window of
- * messages within the mailbox queue while looking for a malicious VF.
- *
- * 2. When the caller starts processing its mailbox queue in response to an
- * interrupt, the structure ice_mbx_snapshot is expected to be cleared before
- * the algorithm can be run for the first time for that interrupt. This can be
- * done via ice_mbx_reset_snapshot().
- *
- * 3. For every message read by the caller from the MBX Queue, the caller must
- * call the detection algorithm's entry function ice_mbx_vf_state_handler().
- * Before every call to ice_mbx_vf_state_handler() the struct ice_mbx_data is
- * filled as it is required to be passed to the algorithm.
- *
- * 4. Every time a message is read from the MBX queue, a VFId is received which
- * is passed to the state handler. The boolean output is_malvf of the state
- * handler ice_mbx_vf_state_handler() serves as an indicator to the caller
- * whether this VF is malicious or not.
- *
- * 5. When a VF is identified to be malicious, the caller can send a message
- * to the system administrator. The caller can invoke ice_mbx_report_malvf()
- * to help determine if a malicious VF is to be reported or not. This function
- * requires the caller to maintain a global bitmap to track all malicious VFs
- * and pass that to ice_mbx_report_malvf() along with the VFID which was identified
- * to be malicious by ice_mbx_vf_state_handler().
- *
- * 6. The global bitmap maintained by PF can be cleared completely if PF is in
- * reset or the bit corresponding to a VF can be cleared if that VF is in reset.
- * When a VF is shut down and brought back up, we assume that the new VF
- * brought up is not malicious and hence report it if found malicious.
- *
- * 7. The function ice_mbx_reset_snapshot() is called to reset the information
- * in ice_mbx_snapshot for every new mailbox interrupt handled.
- *
- * 8. The memory allocated for variables in ice_mbx_snapshot is de-allocated
- * when driver is unloaded.
- */
-#define ICE_RQ_DATA_MASK(rq_data) ((rq_data) & PF_MBX_ARQH_ARQH_M)
-/* Using the highest value for an unsigned 16-bit value 0xFFFF to indicate that
- * the max messages check must be ignored in the algorithm
- */
-#define ICE_IGNORE_MAX_MSG_CNT 0xFFFF
-
-/**
- * ice_mbx_traverse - Pass through mailbox snapshot
- * @hw: pointer to the HW struct
- * @new_state: new algorithm state
- *
- * Traversing the mailbox static snapshot without checking
- * for malicious VFs.
- */
-static void
-ice_mbx_traverse(struct ice_hw *hw,
- enum ice_mbx_snapshot_state *new_state)
-{
- struct ice_mbx_snap_buffer_data *snap_buf;
- u32 num_iterations;
-
- snap_buf = &hw->mbx_snapshot.mbx_buf;
-
- /* As mailbox buffer is circular, applying a mask
- * on the incremented iteration count.
- */
- num_iterations = ICE_RQ_DATA_MASK(++snap_buf->num_iterations);
-
- /* Checking either of the below conditions to exit snapshot traversal:
- * Condition-1: If the number of iterations in the mailbox is equal to
- * the mailbox head which would indicate that we have reached the end
- * of the static snapshot.
- * Condition-2: If the maximum messages serviced in the mailbox for a
- * given interrupt is the highest possible value then there is no need
- * to check if the number of messages processed is equal to it. If not
- * check if the number of messages processed is greater than or equal
- * to the maximum number of mailbox entries serviced in current work item.
- */
- if (num_iterations == snap_buf->head ||
- (snap_buf->max_num_msgs_mbx < ICE_IGNORE_MAX_MSG_CNT &&
- ++snap_buf->num_msg_proc >= snap_buf->max_num_msgs_mbx))
- *new_state = ICE_MAL_VF_DETECT_STATE_NEW_SNAPSHOT;
-}
-
-/**
- * ice_mbx_detect_malvf - Detect malicious VF in snapshot
- * @hw: pointer to the HW struct
- * @vf_id: relative virtual function ID
- * @new_state: new algorithm state
- * @is_malvf: boolean output to indicate if VF is malicious
- *
- * This function tracks the number of asynchronous messages
- * sent per VF and marks the VF as malicious if it exceeds
- * the permissible number of messages to send.
- */
-static enum ice_status
-ice_mbx_detect_malvf(struct ice_hw *hw, u16 vf_id,
- enum ice_mbx_snapshot_state *new_state,
- bool *is_malvf)
-{
- struct ice_mbx_snapshot *snap = &hw->mbx_snapshot;
-
- if (vf_id >= snap->mbx_vf.vfcntr_len)
- return ICE_ERR_OUT_OF_RANGE;
-
- /* increment the message count in the VF array */
- snap->mbx_vf.vf_cntr[vf_id]++;
-
- if (snap->mbx_vf.vf_cntr[vf_id] >= ICE_ASYNC_VF_MSG_THRESHOLD)
- *is_malvf = true;
-
- /* continue to iterate through the mailbox snapshot */
- ice_mbx_traverse(hw, new_state);
-
- return ICE_SUCCESS;
-}
-
-/**
- * ice_mbx_reset_snapshot - Reset mailbox snapshot structure
- * @snap: pointer to mailbox snapshot structure in the ice_hw struct
- *
- * Reset the mailbox snapshot structure and clear VF counter array.
- */
-static void ice_mbx_reset_snapshot(struct ice_mbx_snapshot *snap)
-{
- u32 vfcntr_len;
-
- if (!snap || !snap->mbx_vf.vf_cntr)
- return;
-
- /* Clear VF counters. */
- vfcntr_len = snap->mbx_vf.vfcntr_len;
- if (vfcntr_len)
- ice_memset(snap->mbx_vf.vf_cntr, 0,
- (vfcntr_len * sizeof(*snap->mbx_vf.vf_cntr)),
- ICE_NONDMA_MEM);
-
- /* Reset mailbox snapshot for a new capture. */
- ice_memset(&snap->mbx_buf, 0, sizeof(snap->mbx_buf),
- ICE_NONDMA_MEM);
- snap->mbx_buf.state = ICE_MAL_VF_DETECT_STATE_NEW_SNAPSHOT;
-}
-
-/**
- * ice_mbx_vf_state_handler - Handle states of the overflow algorithm
- * @hw: pointer to the HW struct
- * @mbx_data: pointer to structure containing mailbox data
- * @vf_id: relative virtual function (VF) ID
- * @is_malvf: boolean output to indicate if VF is malicious
- *
- * The function serves as an entry point for the malicious VF
- * detection algorithm by handling the different states and state
- * transitions of the algorithm:
- * New snapshot: This state is entered when creating a new static
- * snapshot. The data from any previous mailbox snapshot is
- * cleared and a new capture of the mailbox head and tail is
- * logged. This will be the new static snapshot to detect
- * asynchronous messages sent by VFs. On capturing the snapshot
- * and depending on whether the number of pending messages in that
- * snapshot exceed the watermark value, the state machine enters
- * traverse or detect states.
- * Traverse: If pending message count is below watermark then iterate
- * through the snapshot without any action on VF.
- * Detect: If pending message count exceeds watermark traverse
- * the static snapshot and look for a malicious VF.
- */
-enum ice_status
-ice_mbx_vf_state_handler(struct ice_hw *hw,
- struct ice_mbx_data *mbx_data, u16 vf_id,
- bool *is_malvf)
-{
- struct ice_mbx_snapshot *snap = &hw->mbx_snapshot;
- struct ice_mbx_snap_buffer_data *snap_buf;
- struct ice_ctl_q_info *cq = &hw->mailboxq;
- enum ice_mbx_snapshot_state new_state;
- enum ice_status status = ICE_SUCCESS;
-
- if (!is_malvf || !mbx_data)
- return ICE_ERR_BAD_PTR;
-
- /* When entering the mailbox state machine assume that the VF
- * is not malicious until detected.
- */
- *is_malvf = false;
-
- /* Checking if max messages allowed to be processed while servicing current
- * interrupt is not less than the defined AVF message threshold.
- */
- if (mbx_data->max_num_msgs_mbx <= ICE_ASYNC_VF_MSG_THRESHOLD)
- return ICE_ERR_INVAL_SIZE;
-
- /* The watermark value should not be lesser than the threshold limit
- * set for the number of asynchronous messages a VF can send to mailbox
- * nor should it be greater than the maximum number of messages in the
- * mailbox serviced in current interrupt.
- */
- if (mbx_data->async_watermark_val < ICE_ASYNC_VF_MSG_THRESHOLD ||
- mbx_data->async_watermark_val > mbx_data->max_num_msgs_mbx)
- return ICE_ERR_PARAM;
-
- new_state = ICE_MAL_VF_DETECT_STATE_INVALID;
- snap_buf = &snap->mbx_buf;
-
- switch (snap_buf->state) {
- case ICE_MAL_VF_DETECT_STATE_NEW_SNAPSHOT:
- /* Clear any previously held data in mailbox snapshot structure. */
- ice_mbx_reset_snapshot(snap);
-
- /* Collect the pending ARQ count, number of messages processed and
- * the maximum number of messages allowed to be processed from the
- * Mailbox for current interrupt.
- */
- snap_buf->num_pending_arq = mbx_data->num_pending_arq;
- snap_buf->num_msg_proc = mbx_data->num_msg_proc;
- snap_buf->max_num_msgs_mbx = mbx_data->max_num_msgs_mbx;
-
- /* Capture a new static snapshot of the mailbox by logging the
- * head and tail of snapshot and set num_iterations to the tail
- * value to mark the start of the iteration through the snapshot.
- */
- snap_buf->head = ICE_RQ_DATA_MASK(cq->rq.next_to_clean +
- mbx_data->num_pending_arq);
- snap_buf->tail = ICE_RQ_DATA_MASK(cq->rq.next_to_clean - 1);
- snap_buf->num_iterations = snap_buf->tail;
-
- /* Pending ARQ messages returned by ice_clean_rq_elem
- * is the difference between the head and tail of the
- * mailbox queue. Comparing this value against the watermark
- * helps to check if we potentially have malicious VFs.
- */
- if (snap_buf->num_pending_arq >=
- mbx_data->async_watermark_val) {
- new_state = ICE_MAL_VF_DETECT_STATE_DETECT;
- status = ice_mbx_detect_malvf(hw, vf_id, &new_state, is_malvf);
- } else {
- new_state = ICE_MAL_VF_DETECT_STATE_TRAVERSE;
- ice_mbx_traverse(hw, &new_state);
- }
- break;
-
- case ICE_MAL_VF_DETECT_STATE_TRAVERSE:
- new_state = ICE_MAL_VF_DETECT_STATE_TRAVERSE;
- ice_mbx_traverse(hw, &new_state);
- break;
-
- case ICE_MAL_VF_DETECT_STATE_DETECT:
- new_state = ICE_MAL_VF_DETECT_STATE_DETECT;
- status = ice_mbx_detect_malvf(hw, vf_id, &new_state, is_malvf);
- break;
-
- default:
- new_state = ICE_MAL_VF_DETECT_STATE_INVALID;
- status = ICE_ERR_CFG;
- }
-
- snap_buf->state = new_state;
-
- return status;
-}
-
-/**
- * ice_mbx_report_malvf - Track and note malicious VF
- * @hw: pointer to the HW struct
- * @all_malvfs: all malicious VFs tracked by PF
- * @bitmap_len: length of bitmap in bits
- * @vf_id: relative virtual function ID of the malicious VF
- * @report_malvf: boolean to indicate if malicious VF must be reported
- *
- * This function will update a bitmap that keeps track of the malicious
- * VFs attached to the PF. A malicious VF must be reported only once if
- * discovered between VF resets or loading so the function checks
- * the input vf_id against the bitmap to verify if the VF has been
- * detected in any previous mailbox iterations.
- */
-enum ice_status
-ice_mbx_report_malvf(struct ice_hw *hw, ice_bitmap_t *all_malvfs,
- u16 bitmap_len, u16 vf_id, bool *report_malvf)
-{
- if (!all_malvfs || !report_malvf)
- return ICE_ERR_PARAM;
-
- *report_malvf = false;
-
- if (bitmap_len < hw->mbx_snapshot.mbx_vf.vfcntr_len)
- return ICE_ERR_INVAL_SIZE;
-
- if (vf_id >= bitmap_len)
- return ICE_ERR_OUT_OF_RANGE;
-
- /* If the vf_id is found in the bitmap set bit and boolean to true */
- if (!ice_is_bit_set(all_malvfs, vf_id)) {
- ice_set_bit(vf_id, all_malvfs);
- ice_debug(hw, ICE_DBG_TRACE, "Malicious VF=%d found\n", vf_id);
- *report_malvf = true;
- }
-
- return ICE_SUCCESS;
-}
-
-/**
- * ice_mbx_clear_malvf - Clear VF bitmap and counter for VF ID
- * @snap: pointer to the mailbox snapshot structure
- * @all_malvfs: all malicious VFs tracked by PF
- * @bitmap_len: length of bitmap in bits
- * @vf_id: relative virtual function ID of the malicious VF
- *
- * In case of a VF reset, this function can be called to clear
- * the bit corresponding to the VF ID in the bitmap tracking all
- * malicious VFs attached to the PF. The function also clears the
- * VF counter array at the index of the VF ID. This is to ensure
- * that the new VF loaded is not considered malicious before going
- * through the overflow detection algorithm.
- */
-enum ice_status
-ice_mbx_clear_malvf(struct ice_mbx_snapshot *snap, ice_bitmap_t *all_malvfs,
- u16 bitmap_len, u16 vf_id)
-{
- if (!snap || !all_malvfs)
- return ICE_ERR_PARAM;
-
- if (bitmap_len < snap->mbx_vf.vfcntr_len)
- return ICE_ERR_INVAL_SIZE;
-
- /* Ensure VF ID value is not larger than bitmap or VF counter length */
- if (vf_id >= bitmap_len || vf_id >= snap->mbx_vf.vfcntr_len)
- return ICE_ERR_OUT_OF_RANGE;
-
- /* Clear VF ID bit in the bitmap tracking malicious VFs attached to PF */
- ice_clear_bit(vf_id, all_malvfs);
-
- /* Clear the VF counter in the mailbox snapshot structure for that VF ID.
- * This is to ensure that if a VF is unloaded and a new one brought back
- * up with the same VF ID for a snapshot currently in traversal or detect
- * state the counter for that VF ID does not increment on top of existing
- * values in the mailbox overflow detection algorithm.
- */
- snap->mbx_vf.vf_cntr[vf_id] = 0;
-
- return ICE_SUCCESS;
-}
-
-/**
- * ice_mbx_init_snapshot - Initialize mailbox snapshot structure
- * @hw: pointer to the hardware structure
- * @vf_count: number of VFs allocated on a PF
- *
- * Clear the mailbox snapshot structure and allocate memory
- * for the VF counter array based on the number of VFs allocated
- * on that PF.
- *
- * Assumption: This function will assume ice_get_caps() has already been
- * called to ensure that the vf_count can be compared against the number
- * of VFs supported as defined in the functional capabilities of the device.
- */
-enum ice_status ice_mbx_init_snapshot(struct ice_hw *hw, u16 vf_count)
-{
- struct ice_mbx_snapshot *snap = &hw->mbx_snapshot;
-
- /* Ensure that the number of VFs allocated is non-zero and
- * is not greater than the number of supported VFs defined in
- * the functional capabilities of the PF.
- */
- if (!vf_count || vf_count > hw->func_caps.num_allocd_vfs)
- return ICE_ERR_INVAL_SIZE;
-
- snap->mbx_vf.vf_cntr =
- (u32 *)ice_calloc(hw, vf_count,
- sizeof(*snap->mbx_vf.vf_cntr));
- if (!snap->mbx_vf.vf_cntr)
- return ICE_ERR_NO_MEMORY;
-
- /* Setting the VF counter length to the number of allocated
- * VFs for given PF's functional capabilities.
- */
- snap->mbx_vf.vfcntr_len = vf_count;
-
- /* Clear mbx_buf in the mailbox snaphot structure and setting the
- * mailbox snapshot state to a new capture.
- */
- ice_memset(&snap->mbx_buf, 0, sizeof(snap->mbx_buf), ICE_NONDMA_MEM);
- snap->mbx_buf.state = ICE_MAL_VF_DETECT_STATE_NEW_SNAPSHOT;
-
- return ICE_SUCCESS;
-}
-
-/**
- * ice_mbx_deinit_snapshot - Free mailbox snapshot structure
- * @hw: pointer to the hardware structure
- *
- * Clear the mailbox snapshot structure and free the VF counter array.
- */
-void ice_mbx_deinit_snapshot(struct ice_hw *hw)
-{
- struct ice_mbx_snapshot *snap = &hw->mbx_snapshot;
-
- /* Free VF counter array and reset vf counter length */
- ice_free(hw, snap->mbx_vf.vf_cntr);
- snap->mbx_vf.vfcntr_len = 0;
-
- /* Clear mbx_buf in the mailbox snaphot structure */
- ice_memset(&snap->mbx_buf, 0, sizeof(snap->mbx_buf), ICE_NONDMA_MEM);
-}
diff --git a/sys/dev/ice/ice_sriov.h b/sys/dev/ice/ice_sriov.h
deleted file mode 100644
index 012d7d3e6e2d..000000000000
--- a/sys/dev/ice/ice_sriov.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause */
-/* Copyright (c) 2021, Intel Corporation
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-/*$FreeBSD$*/
-
-#ifndef _ICE_SRIOV_H_
-#define _ICE_SRIOV_H_
-
-#include "ice_type.h"
-#include "ice_controlq.h"
-
-/* Defining the mailbox message threshold as 63 asynchronous
- * pending messages. Normal VF functionality does not require
- * sending more than 63 asynchronous pending message.
- */
-#define ICE_ASYNC_VF_MSG_THRESHOLD 63
-
-enum ice_status
-ice_aq_send_msg_to_pf(struct ice_hw *hw, enum virtchnl_ops v_opcode,
- enum ice_status v_retval, u8 *msg, u16 msglen,
- struct ice_sq_cd *cd);
-enum ice_status
-ice_aq_send_msg_to_vf(struct ice_hw *hw, u16 vfid, u32 v_opcode, u32 v_retval,
- u8 *msg, u16 msglen, struct ice_sq_cd *cd);
-
-u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed);
-enum ice_status
-ice_mbx_vf_state_handler(struct ice_hw *hw, struct ice_mbx_data *mbx_data,
- u16 vf_id, bool *is_mal_vf);
-enum ice_status
-ice_mbx_clear_malvf(struct ice_mbx_snapshot *snap, ice_bitmap_t *all_malvfs,
- u16 bitmap_len, u16 vf_id);
-enum ice_status ice_mbx_init_snapshot(struct ice_hw *hw, u16 vf_count);
-void ice_mbx_deinit_snapshot(struct ice_hw *hw);
-enum ice_status
-ice_mbx_report_malvf(struct ice_hw *hw, ice_bitmap_t *all_malvfs,
- u16 bitmap_len, u16 vf_id, bool *report_malvf);
-#endif /* _ICE_SRIOV_H_ */
diff --git a/sys/dev/ice/ice_strings.c b/sys/dev/ice/ice_strings.c
index 0aa757a43a88..9a527a6dd8c4 100644
--- a/sys/dev/ice/ice_strings.c
+++ b/sys/dev/ice/ice_strings.c
@@ -700,6 +700,47 @@ _ice_fltr_flag_str(u16 flag)
}
/**
+ * ice_log_sev_str - Convert log level to a string
+ * @log_level: the log level to convert
+ *
+ * Convert the u8 log level of a FW logging module into a readable
+ * string for outputting in a sysctl.
+ */
+struct ice_str_buf
+_ice_log_sev_str(u8 log_level)
+{
+ struct ice_str_buf buf = { .str = "" };
+ const char *str = NULL;
+
+ switch (log_level) {
+ case ICE_FWLOG_LEVEL_NONE:
+ str = "none";
+ break;
+ case ICE_FWLOG_LEVEL_ERROR:
+ str = "error";
+ break;
+ case ICE_FWLOG_LEVEL_WARNING:
+ str = "warning";
+ break;
+ case ICE_FWLOG_LEVEL_NORMAL:
+ str = "normal";
+ break;
+ case ICE_FWLOG_LEVEL_VERBOSE:
+ str = "verbose";
+ break;
+ default:
+ break;
+ }
+
+ if (str)
+ snprintf(buf.str, ICE_STR_BUF_LEN, "%s", str);
+ else
+ snprintf(buf.str, ICE_STR_BUF_LEN, "%u", log_level);
+
+ return buf;
+}
+
+/**
* ice_fwd_act_str - convert filter action enum to a string
* @action: the filter action to convert
*
@@ -986,12 +1027,16 @@ ice_state_to_str(enum ice_state state)
return "ROLLBACK_MODE";
case ICE_STATE_LINK_STATUS_REPORTED:
return "LINK_STATUS_REPORTED";
+ case ICE_STATE_ATTACHING:
+ return "ATTACHING";
case ICE_STATE_DETACHING:
return "DETACHING";
case ICE_STATE_LINK_DEFAULT_OVERRIDE_PENDING:
return "LINK_DEFAULT_OVERRIDE_PENDING";
case ICE_STATE_LLDP_RX_FLTR_FROM_DRIVER:
return "LLDP_RX_FLTR_FROM_DRIVER";
+ case ICE_STATE_MULTIPLE_TCS:
+ return "MULTIPLE_TCS";
case ICE_STATE_LAST:
return NULL;
}
@@ -1000,6 +1045,91 @@ ice_state_to_str(enum ice_state state)
}
/**
+ * ice_fw_module_str - Convert a FW logging module to a string name
+ * @module: the module to convert
+ *
+ * Given a FW logging module id, convert it to a shorthand human readable
+ * name, for generating sysctl tunables.
+ */
+const char *
+ice_fw_module_str(enum ice_aqc_fw_logging_mod module)
+{
+ switch (module) {
+ case ICE_AQC_FW_LOG_ID_GENERAL:
+ return "general";
+ case ICE_AQC_FW_LOG_ID_CTRL:
+ return "ctrl";
+ case ICE_AQC_FW_LOG_ID_LINK:
+ return "link";
+ case ICE_AQC_FW_LOG_ID_LINK_TOPO:
+ return "link_topo";
+ case ICE_AQC_FW_LOG_ID_DNL:
+ return "dnl";
+ case ICE_AQC_FW_LOG_ID_I2C:
+ return "i2c";
+ case ICE_AQC_FW_LOG_ID_SDP:
+ return "sdp";
+ case ICE_AQC_FW_LOG_ID_MDIO:
+ return "mdio";
+ case ICE_AQC_FW_LOG_ID_ADMINQ:
+ return "adminq";
+ case ICE_AQC_FW_LOG_ID_HDMA:
+ return "hdma";
+ case ICE_AQC_FW_LOG_ID_LLDP:
+ return "lldp";
+ case ICE_AQC_FW_LOG_ID_DCBX:
+ return "dcbx";
+ case ICE_AQC_FW_LOG_ID_DCB:
+ return "dcb";
+ case ICE_AQC_FW_LOG_ID_XLR:
+ return "xlr";
+ case ICE_AQC_FW_LOG_ID_NVM:
+ return "nvm";
+ case ICE_AQC_FW_LOG_ID_AUTH:
+ return "auth";
+ case ICE_AQC_FW_LOG_ID_VPD:
+ return "vpd";
+ case ICE_AQC_FW_LOG_ID_IOSF:
+ return "iosf";
+ case ICE_AQC_FW_LOG_ID_PARSER:
+ return "parser";
+ case ICE_AQC_FW_LOG_ID_SW:
+ return "sw";
+ case ICE_AQC_FW_LOG_ID_SCHEDULER:
+ return "scheduler";
+ case ICE_AQC_FW_LOG_ID_TXQ:
+ return "txq";
+ case ICE_AQC_FW_LOG_ID_RSVD:
+ return "acl";
+ case ICE_AQC_FW_LOG_ID_POST:
+ return "post";
+ case ICE_AQC_FW_LOG_ID_WATCHDOG:
+ return "watchdog";
+ case ICE_AQC_FW_LOG_ID_TASK_DISPATCH:
+ return "task_dispatch";
+ case ICE_AQC_FW_LOG_ID_MNG:
+ return "mng";
+ case ICE_AQC_FW_LOG_ID_SYNCE:
+ return "synce";
+ case ICE_AQC_FW_LOG_ID_HEALTH:
+ return "health";
+ case ICE_AQC_FW_LOG_ID_TSDRV:
+ return "tsdrv";
+ case ICE_AQC_FW_LOG_ID_PFREG:
+ return "pfreg";
+ case ICE_AQC_FW_LOG_ID_MDLVER:
+ return "mdlver";
+ case ICE_AQC_FW_LOG_ID_MAX:
+ return "unknown";
+ }
+
+ /* The compiler generates errors on unhandled enum values if we omit
+ * the default case.
+ */
+ return "unknown";
+}
+
+/**
* ice_fw_lldp_status - Convert FW LLDP status to a string
* @lldp_status: firmware LLDP status value to convert
*
diff --git a/sys/dev/ice/ice_switch.c b/sys/dev/ice/ice_switch.c
index 6fe271734e38..c8331693c193 100644
--- a/sys/dev/ice/ice_switch.c
+++ b/sys/dev/ice/ice_switch.c
@@ -38,6 +38,7 @@
#define ICE_ETH_ETHTYPE_OFFSET 12
#define ICE_ETH_VLAN_TCI_OFFSET 14
#define ICE_MAX_VLAN_ID 0xFFF
+#define ICE_IPV6_ETHER_ID 0x86DD
#define ICE_ETH_P_8021Q 0x8100
/* Dummy ethernet header needed in the ice_aqc_sw_rules_elem
@@ -175,7 +176,7 @@ ice_alloc_global_lut_exit:
}
/**
- * ice_free_global_lut - free a RSS global LUT
+ * ice_free_rss_global_lut - free a RSS global LUT
* @hw: pointer to the HW struct
* @global_lut_id: ID of the RSS global LUT to free
*/
@@ -2271,7 +2272,7 @@ ice_aq_get_res_descs(struct ice_hw *hw, u16 num_entries,
* @sw: pointer to switch info struct for which function add rule
* @lport: logic port number on which function add rule
*
- * IMPORTANT: When the ucast_shared flag is set to false and m_list has
+ * IMPORTANT: When the umac_shared flag is set to false and m_list has
* multiple unicast addresses, the function assumes that all the
* addresses are unique in a given add_mac call. It doesn't
* check for duplicates in this case, removing duplicates from a given
@@ -2314,18 +2315,18 @@ ice_add_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list,
if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC ||
IS_ZERO_ETHER_ADDR(add))
return ICE_ERR_PARAM;
- if (IS_UNICAST_ETHER_ADDR(add) && !hw->ucast_shared) {
+ if (IS_UNICAST_ETHER_ADDR(add) && !hw->umac_shared) {
/* Don't overwrite the unicast address */
ice_acquire_lock(rule_lock);
if (ice_find_rule_entry(rule_head,
&m_list_itr->fltr_info)) {
ice_release_lock(rule_lock);
- return ICE_ERR_ALREADY_EXISTS;
+ continue;
}
ice_release_lock(rule_lock);
num_unicast++;
} else if (IS_MULTICAST_ETHER_ADDR(add) ||
- (IS_UNICAST_ETHER_ADDR(add) && hw->ucast_shared)) {
+ (IS_UNICAST_ETHER_ADDR(add) && hw->umac_shared)) {
m_list_itr->status =
ice_add_rule_internal(hw, recp_list, lport,
m_list_itr);
@@ -2930,7 +2931,7 @@ ice_remove_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list,
list_itr->fltr_info.fwd_id.hw_vsi_id =
ice_get_hw_vsi_num(hw, vsi_handle);
- if (IS_UNICAST_ETHER_ADDR(add) && !hw->ucast_shared) {
+ if (IS_UNICAST_ETHER_ADDR(add) && !hw->umac_shared) {
/* Don't remove the unicast address that belongs to
* another VSI on the switch, since it is not being
* shared...
@@ -3147,22 +3148,25 @@ static u8 ice_determine_promisc_mask(struct ice_fltr_info *fi)
* @promisc_mask: pointer to mask to be filled in
* @vid: VLAN ID of promisc VLAN VSI
* @sw: pointer to switch info struct for which function add rule
+ * @lkup: switch rule filter lookup type
*/
static enum ice_status
_ice_get_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask,
- u16 *vid, struct ice_switch_info *sw)
+ u16 *vid, struct ice_switch_info *sw,
+ enum ice_sw_lkup_type lkup)
{
struct ice_fltr_mgmt_list_entry *itr;
struct LIST_HEAD_TYPE *rule_head;
struct ice_lock *rule_lock; /* Lock to protect filter rule list */
- if (!ice_is_vsi_valid(hw, vsi_handle))
+ if (!ice_is_vsi_valid(hw, vsi_handle) ||
+ (lkup != ICE_SW_LKUP_PROMISC && lkup != ICE_SW_LKUP_PROMISC_VLAN))
return ICE_ERR_PARAM;
*vid = 0;
*promisc_mask = 0;
- rule_head = &sw->recp_list[ICE_SW_LKUP_PROMISC].filt_rules;
- rule_lock = &sw->recp_list[ICE_SW_LKUP_PROMISC].filt_rule_lock;
+ rule_head = &sw->recp_list[lkup].filt_rules;
+ rule_lock = &sw->recp_list[lkup].filt_rule_lock;
ice_acquire_lock(rule_lock);
LIST_FOR_EACH_ENTRY(itr, rule_head,
@@ -3192,47 +3196,7 @@ ice_get_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask,
u16 *vid)
{
return _ice_get_vsi_promisc(hw, vsi_handle, promisc_mask,
- vid, hw->switch_info);
-}
-
-/**
- * ice_get_vsi_vlan_promisc - get VLAN promiscuous mode of given VSI
- * @hw: pointer to the hardware structure
- * @vsi_handle: VSI handle to retrieve info from
- * @promisc_mask: pointer to mask to be filled in
- * @vid: VLAN ID of promisc VLAN VSI
- * @sw: pointer to switch info struct for which function add rule
- */
-static enum ice_status
-_ice_get_vsi_vlan_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask,
- u16 *vid, struct ice_switch_info *sw)
-{
- struct ice_fltr_mgmt_list_entry *itr;
- struct LIST_HEAD_TYPE *rule_head;
- struct ice_lock *rule_lock; /* Lock to protect filter rule list */
-
- if (!ice_is_vsi_valid(hw, vsi_handle))
- return ICE_ERR_PARAM;
-
- *vid = 0;
- *promisc_mask = 0;
- rule_head = &sw->recp_list[ICE_SW_LKUP_PROMISC_VLAN].filt_rules;
- rule_lock = &sw->recp_list[ICE_SW_LKUP_PROMISC_VLAN].filt_rule_lock;
-
- ice_acquire_lock(rule_lock);
- LIST_FOR_EACH_ENTRY(itr, rule_head, ice_fltr_mgmt_list_entry,
- list_entry) {
- /* Continue if this filter doesn't apply to this VSI or the
- * VSI ID is not in the VSI map for this filter
- */
- if (!ice_vsi_uses_fltr(itr, vsi_handle))
- continue;
-
- *promisc_mask |= ice_determine_promisc_mask(&itr->fltr_info);
- }
- ice_release_lock(rule_lock);
-
- return ICE_SUCCESS;
+ vid, hw->switch_info, ICE_SW_LKUP_PROMISC);
}
/**
@@ -3246,8 +3210,9 @@ enum ice_status
ice_get_vsi_vlan_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask,
u16 *vid)
{
- return _ice_get_vsi_vlan_promisc(hw, vsi_handle, promisc_mask,
- vid, hw->switch_info);
+ return _ice_get_vsi_promisc(hw, vsi_handle, promisc_mask,
+ vid, hw->switch_info,
+ ICE_SW_LKUP_PROMISC_VLAN);
}
/**
@@ -4211,7 +4176,7 @@ ice_replay_vsi_all_fltr(struct ice_hw *hw, struct ice_port_info *pi,
}
/**
- * ice_rm_all_sw_replay_rule - helper function to delete filter replay rules
+ * ice_rm_sw_replay_rule_info - helper function to delete filter replay rules
* @hw: pointer to the HW struct
* @sw: pointer to switch info struct for which function removes filters
*
diff --git a/sys/dev/ice/ice_switch.h b/sys/dev/ice/ice_switch.h
index a121ee4e42a8..cd5994d73fd6 100644
--- a/sys/dev/ice/ice_switch.h
+++ b/sys/dev/ice/ice_switch.h
@@ -213,12 +213,24 @@ struct ice_rule_query_data {
u16 vsi_handle;
};
+/*
+ * This structure allows to pass info about lb_en and lan_en
+ * flags to ice_add_adv_rule. Values in act would be used
+ * only if act_valid was set to true, otherwise dflt
+ * values would be used.
+ */
+struct ice_adv_rule_flags_info {
+ u32 act;
+ u8 act_valid; /* indicate if flags in act are valid */
+};
+
struct ice_adv_rule_info {
enum ice_sw_tunnel_type tun_type;
struct ice_sw_act_ctrl sw_act;
u32 priority;
u8 rx; /* true means LOOKUP_RX otherwise LOOKUP_TX */
u16 fltr_rule_id;
+ struct ice_adv_rule_flags_info flags_info;
};
/* A collection of one or more four word recipe */
diff --git a/sys/dev/ice/ice_type.h b/sys/dev/ice/ice_type.h
index e32ee4d120f0..d8480543e39a 100644
--- a/sys/dev/ice/ice_type.h
+++ b/sys/dev/ice/ice_type.h
@@ -78,17 +78,44 @@
#include "ice_flex_type.h"
#include "ice_protocol_type.h"
#include "ice_vlan_mode.h"
+#include "ice_fwlog.h"
static inline bool ice_is_tc_ena(ice_bitmap_t bitmap, u8 tc)
{
return !!(bitmap & BIT(tc));
}
-#define DIV_64BIT(n, d) ((n) / (d))
+/**
+ * DIV_S64 - Divide signed 64-bit value with signed 64-bit divisor
+ * @dividend: value to divide
+ * @divisor: value to divide by
+ *
+ * Use DIV_S64 for any 64-bit divide which operates on signed 64-bit dividends.
+ * Do not use this for unsigned 64-bit dividends as it will not produce
+ * correct results if the dividend is larger than S64_MAX.
+ */
+static inline s64 DIV_S64(s64 dividend, s64 divisor)
+{
+ return dividend / divisor;
+}
+
+/**
+ * DIV_U64 - Divide unsigned 64-bit value by unsigned 64-bit divisor
+ * @dividend: value to divide
+ * @divisor: value to divide by
+ *
+ * Use DIV_U64 for any 64-bit divide which operates on unsigned 64-bit
+ * dividends. Do not use this for signed 64-bit dividends as it will not
+ * handle negative values correctly.
+ */
+static inline u64 DIV_U64(u64 dividend, u64 divisor)
+{
+ return dividend / divisor;
+}
static inline u64 round_up_64bit(u64 a, u32 b)
{
- return DIV_64BIT(((a) + (b) / 2), (b));
+ return DIV_U64(((a) + (b) / 2), (b));
}
static inline u32 ice_round_to_num(u32 N, u32 R)
@@ -136,6 +163,7 @@ static inline u32 ice_round_to_num(u32 N, u32 R)
ICE_DBG_AQ_DESC | \
ICE_DBG_AQ_DESC_BUF | \
ICE_DBG_AQ_CMD)
+#define ICE_DBG_PARSER BIT_ULL(28)
#define ICE_DBG_USER BIT_ULL(31)
#define ICE_DBG_ALL 0xFFFFFFFFFFFFFFFFULL
@@ -390,6 +418,23 @@ struct ice_hw_common_caps {
#define ICE_NVM_MGMT_SEC_REV_DISABLED BIT(0)
#define ICE_NVM_MGMT_UPDATE_DISABLED BIT(1)
#define ICE_NVM_MGMT_UNIFIED_UPD_SUPPORT BIT(3)
+ /* PCIe reset avoidance */
+ bool pcie_reset_avoidance; /* false: not supported, true: supported */
+ /* Post update reset restriction */
+ bool reset_restrict_support; /* false: not supported, true: supported */
+
+ /* External topology device images within the NVM */
+#define ICE_EXT_TOPO_DEV_IMG_COUNT 4
+ u32 ext_topo_dev_img_ver_high[ICE_EXT_TOPO_DEV_IMG_COUNT];
+ u32 ext_topo_dev_img_ver_low[ICE_EXT_TOPO_DEV_IMG_COUNT];
+ u8 ext_topo_dev_img_part_num[ICE_EXT_TOPO_DEV_IMG_COUNT];
+#define ICE_EXT_TOPO_DEV_IMG_PART_NUM_S 8
+#define ICE_EXT_TOPO_DEV_IMG_PART_NUM_M \
+ MAKEMASK(0xFF, ICE_EXT_TOPO_DEV_IMG_PART_NUM_S)
+ bool ext_topo_dev_img_load_en[ICE_EXT_TOPO_DEV_IMG_COUNT];
+#define ICE_EXT_TOPO_DEV_IMG_LOAD_EN BIT(0)
+ bool ext_topo_dev_img_prog_en[ICE_EXT_TOPO_DEV_IMG_COUNT];
+#define ICE_EXT_TOPO_DEV_IMG_PROG_EN BIT(1)
};
/* Function specific capabilities */
@@ -759,7 +804,8 @@ struct ice_dcb_app_priority_table {
};
#define ICE_MAX_USER_PRIORITY 8
-#define ICE_DCBX_MAX_APPS 32
+#define ICE_DCBX_MAX_APPS 64
+#define ICE_DSCP_NUM_VAL 64
#define ICE_LLDPDU_SIZE 1500
#define ICE_TLV_STATUS_OPER 0x1
#define ICE_TLV_STATUS_SYNC 0x2
@@ -779,7 +825,14 @@ struct ice_dcbx_cfg {
struct ice_dcb_ets_cfg etscfg;
struct ice_dcb_ets_cfg etsrec;
struct ice_dcb_pfc_cfg pfc;
+#define ICE_QOS_MODE_VLAN 0x0
+#define ICE_QOS_MODE_DSCP 0x1
+ u8 pfc_mode;
struct ice_dcb_app_priority_table app[ICE_DCBX_MAX_APPS];
+ /* when DSCP mapping defined by user set its bit to 1 */
+ ice_declare_bitmap(dscp_mapped, ICE_DSCP_NUM_VAL);
+ /* array holding DSCP -> UP/TC values for DSCP L3 QoS mode */
+ u8 dscp_map[ICE_DSCP_NUM_VAL];
u8 dcbx_mode;
#define ICE_DCBX_MODE_CEE 0x1
#define ICE_DCBX_MODE_IEEE 0x2
@@ -831,6 +884,7 @@ struct ice_switch_info {
ice_declare_bitmap(prof_res_bm[ICE_MAX_NUM_PROFILES], ICE_MAX_FV_WORDS);
};
+
/* Enum defining the different states of the mailbox snapshot in the
* PF-VF mailbox overflow detection algorithm. The snapshot can be in
* states:
@@ -964,6 +1018,9 @@ struct ice_hw {
u8 fw_patch; /* firmware patch version */
u32 fw_build; /* firmware build number */
+ struct ice_fwlog_cfg fwlog_cfg;
+ bool fwlog_support_ena; /* does hardware support FW logging? */
+
/* Device max aggregate bandwidths corresponding to the GL_PWR_MODE_CTL
* register. Used for determining the ITR/INTRL granularity during
* initialization.
@@ -983,7 +1040,8 @@ struct ice_hw {
/* INTRL granularity in 1 us */
u8 intrl_gran;
- u8 ucast_shared; /* true if VSIs can share unicast addr */
+ /* true if VSIs can share unicast MAC addr */
+ u8 umac_shared;
#define ICE_PHY_PER_NAC 1
#define ICE_MAX_QUAD 2
@@ -995,6 +1053,7 @@ struct ice_hw {
/* Active package version (currently active) */
struct ice_pkg_ver active_pkg_ver;
+ u32 pkg_seg_id;
u32 active_track_id;
u8 active_pkg_name[ICE_PKG_NAME_SIZE];
u8 active_pkg_in_nvm;
@@ -1186,17 +1245,13 @@ struct ice_aq_get_set_rss_lut_params {
#define ICE_SR_POR_REGISTERS_AUTOLOAD_PTR 0x118
/* CSS Header words */
+#define ICE_NVM_CSS_HDR_LEN_L 0x02
+#define ICE_NVM_CSS_HDR_LEN_H 0x03
#define ICE_NVM_CSS_SREV_L 0x14
#define ICE_NVM_CSS_SREV_H 0x15
-/* Length of CSS header section in words */
-#define ICE_CSS_HEADER_LENGTH 330
-
-/* Offset of Shadow RAM copy in the NVM bank area. */
-#define ICE_NVM_SR_COPY_WORD_OFFSET ROUND_UP(ICE_CSS_HEADER_LENGTH, 32)
-
-/* Size in bytes of Option ROM trailer */
-#define ICE_NVM_OROM_TRAILER_LENGTH (2 * ICE_CSS_HEADER_LENGTH)
+/* Length of Authentication header section in words */
+#define ICE_NVM_AUTH_HEADER_LEN 0x08
/* The Link Topology Netlist section is stored as a series of words. It is
* stored in the NVM as a TLV, with the first two words containing the type
@@ -1290,4 +1345,8 @@ struct ice_aq_get_set_rss_lut_params {
#define ICE_FW_API_HEALTH_REPORT_MAJ 1
#define ICE_FW_API_HEALTH_REPORT_MIN 7
#define ICE_FW_API_HEALTH_REPORT_PATCH 6
+
+/* AQ API version for FW auto drop reports */
+#define ICE_FW_API_AUTO_DROP_MAJ 1
+#define ICE_FW_API_AUTO_DROP_MIN 4
#endif /* _ICE_TYPE_H_ */
diff --git a/sys/dev/ice/ice_vlan_mode.c b/sys/dev/ice/ice_vlan_mode.c
index 7860715264e8..bfddd75b6ff2 100644
--- a/sys/dev/ice/ice_vlan_mode.c
+++ b/sys/dev/ice/ice_vlan_mode.c
@@ -33,7 +33,7 @@
#include "ice_common.h"
/**
- * ice_pkg_supports_dvm - determine if DDP supports Double VLAN mode (DVM)
+ * ice_pkg_get_supported_vlan_mode - chk if DDP supports Double VLAN mode (DVM)
* @hw: pointer to the HW struct
* @dvm: output variable to determine if DDP supports DVM(true) or SVM(false)
*/
@@ -152,24 +152,17 @@ bool ice_is_dvm_ena(struct ice_hw *hw)
* configuration lock has been released because all ports on a device need to
* cache the VLAN mode.
*/
-void ice_cache_vlan_mode(struct ice_hw *hw)
+static void ice_cache_vlan_mode(struct ice_hw *hw)
{
hw->dvm_ena = ice_aq_is_dvm_ena(hw) ? true : false;
}
/**
- * ice_is_dvm_supported - check if Double VLAN Mode is supported
- * @hw: pointer to the hardware structure
- *
- * Returns true if Double VLAN Mode (DVM) is supported and false if only Single
- * VLAN Mode (SVM) is supported. In order for DVM to be supported the DDP and
- * firmware must support it, otherwise only SVM is supported. This function
- * should only be called while the global config lock is held and after the
- * package has been successfully downloaded.
+ * ice_pkg_supports_dvm - find out if DDP supports DVM
+ * @hw: pointer to the HW structure
*/
-static bool ice_is_dvm_supported(struct ice_hw *hw)
+static bool ice_pkg_supports_dvm(struct ice_hw *hw)
{
- struct ice_aqc_get_vlan_mode get_vlan_mode = { 0 };
enum ice_status status;
bool pkg_supports_dvm;
@@ -180,8 +173,17 @@ static bool ice_is_dvm_supported(struct ice_hw *hw)
return false;
}
- if (!pkg_supports_dvm)
- return false;
+ return pkg_supports_dvm;
+}
+
+/**
+ * ice_fw_supports_dvm - find out if FW supports DVM
+ * @hw: pointer to the HW structure
+ */
+static bool ice_fw_supports_dvm(struct ice_hw *hw)
+{
+ struct ice_aqc_get_vlan_mode get_vlan_mode = { 0 };
+ enum ice_status status;
/* If firmware returns success, then it supports DVM, else it only
* supports SVM
@@ -197,6 +199,31 @@ static bool ice_is_dvm_supported(struct ice_hw *hw)
}
/**
+ * ice_is_dvm_supported - check if Double VLAN Mode is supported
+ * @hw: pointer to the hardware structure
+ *
+ * Returns true if Double VLAN Mode (DVM) is supported and false if only Single
+ * VLAN Mode (SVM) is supported. In order for DVM to be supported the DDP and
+ * firmware must support it, otherwise only SVM is supported. This function
+ * should only be called while the global config lock is held and after the
+ * package has been successfully downloaded.
+ */
+static bool ice_is_dvm_supported(struct ice_hw *hw)
+{
+ if (!ice_pkg_supports_dvm(hw)) {
+ ice_debug(hw, ICE_DBG_PKG, "DDP doesn't support DVM\n");
+ return false;
+ }
+
+ if (!ice_fw_supports_dvm(hw)) {
+ ice_debug(hw, ICE_DBG_PKG, "FW doesn't support DVM\n");
+ return false;
+ }
+
+ return true;
+}
+
+/**
* ice_aq_set_vlan_mode - set the VLAN mode of the device
* @hw: pointer to the HW structure
* @set_params: requested VLAN mode configuration
@@ -273,9 +300,26 @@ static enum ice_status ice_set_svm(struct ice_hw *hw)
*/
enum ice_status ice_set_vlan_mode(struct ice_hw *hw)
{
-
if (!ice_is_dvm_supported(hw))
return ICE_SUCCESS;
return ice_set_svm(hw);
}
+
+/**
+ * ice_post_pkg_dwnld_vlan_mode_cfg - configure VLAN mode after DDP download
+ * @hw: pointer to the HW structure
+ *
+ * This function is meant to configure any VLAN mode specific functionality
+ * after the global configuration lock has been released and the DDP has been
+ * downloaded.
+ *
+ * Since only one PF downloads the DDP and configures the VLAN mode there needs
+ * to be a way to configure the other PFs after the DDP has been downloaded and
+ * the global configuration lock has been released. All such code should go in
+ * this function.
+ */
+void ice_post_pkg_dwnld_vlan_mode_cfg(struct ice_hw *hw)
+{
+ ice_cache_vlan_mode(hw);
+}
diff --git a/sys/dev/ice/ice_vlan_mode.h b/sys/dev/ice/ice_vlan_mode.h
index e18b4eef90f4..1e52214c9028 100644
--- a/sys/dev/ice/ice_vlan_mode.h
+++ b/sys/dev/ice/ice_vlan_mode.h
@@ -38,7 +38,7 @@
struct ice_hw;
bool ice_is_dvm_ena(struct ice_hw *hw);
-void ice_cache_vlan_mode(struct ice_hw *hw);
enum ice_status ice_set_vlan_mode(struct ice_hw *hw);
+void ice_post_pkg_dwnld_vlan_mode_cfg(struct ice_hw *hw);
#endif /* _ICE_VLAN_MODE_H */
diff --git a/sys/dev/ice/if_ice_iflib.c b/sys/dev/ice/if_ice_iflib.c
index d1f01ed64db4..e0e852725b33 100644
--- a/sys/dev/ice/if_ice_iflib.c
+++ b/sys/dev/ice/if_ice_iflib.c
@@ -446,6 +446,8 @@ ice_if_attach_pre(if_ctx_t ctx)
device_printf(iflib_get_dev(ctx), "Loading the iflib ice driver\n");
+ ice_set_state(&sc->state, ICE_STATE_ATTACHING);
+
sc->ctx = ctx;
sc->media = iflib_get_media(ctx);
sc->sctx = iflib_get_sctx(ctx);
@@ -776,6 +778,8 @@ ice_if_attach_post(if_ctx_t ctx)
ice_init_saved_phy_cfg(sc);
+ ice_cfg_pba_num(sc);
+
ice_add_device_sysctls(sc);
/* Get DCBX/LLDP state and start DCBX agent */
@@ -796,6 +800,8 @@ ice_if_attach_post(if_ctx_t ctx)
callout_reset(&sc->admin_timer, hz/2, ice_admin_timer, sc);
mtx_unlock(&sc->admin_mtx);
+ ice_clear_state(&sc->state, ICE_STATE_ATTACHING);
+
return 0;
} /* ice_if_attach_post */
@@ -819,6 +825,8 @@ ice_attach_post_recovery_mode(struct ice_softc *sc)
mtx_lock(&sc->admin_mtx);
callout_reset(&sc->admin_timer, hz/2, ice_admin_timer, sc);
mtx_unlock(&sc->admin_mtx);
+
+ ice_clear_state(&sc->state, ICE_STATE_ATTACHING);
}
/**
@@ -993,7 +1001,8 @@ ice_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs,
ice_vsi_add_txqs_ctx(vsi);
for (i = 0, txq = vsi->tx_queues; i < ntxqsets; i++, txq++) {
- txq->me = i;
+ /* q_handle == me when only one TC */
+ txq->me = txq->q_handle = i;
txq->vsi = vsi;
/* store the queue size for easier access */
@@ -2375,6 +2384,27 @@ ice_rebuild(struct ice_softc *sc)
goto err_shutdown_ctrlq;
}
+ /* Re-enable FW logging. Keep going even if this fails */
+ status = ice_fwlog_set(hw, &hw->fwlog_cfg);
+ if (!status) {
+ /*
+ * We should have the most updated cached copy of the
+ * configuration, regardless of whether we're rebuilding
+ * or not. So we'll simply check to see if logging was
+ * enabled pre-rebuild.
+ */
+ if (hw->fwlog_cfg.options & ICE_FWLOG_OPTION_IS_REGISTERED) {
+ status = ice_fwlog_register(hw);
+ if (status)
+ device_printf(dev, "failed to re-register fw logging, err %s aq_err %s\n",
+ ice_status_str(status),
+ ice_aq_str(hw->adminq.sq_last_status));
+ }
+ } else
+ device_printf(dev, "failed to rebuild fw logging configuration, err %s aq_err %s\n",
+ ice_status_str(status),
+ ice_aq_str(hw->adminq.sq_last_status));
+
err = ice_send_version(sc);
if (err)
goto err_shutdown_ctrlq;
@@ -2614,6 +2644,8 @@ ice_init_device_features(struct ice_softc *sc)
ice_set_bit(ICE_FEATURE_LINK_MGMT_VER_1, sc->feat_cap);
ice_set_bit(ICE_FEATURE_LINK_MGMT_VER_2, sc->feat_cap);
ice_set_bit(ICE_FEATURE_HEALTH_STATUS, sc->feat_cap);
+ ice_set_bit(ICE_FEATURE_FW_LOGGING, sc->feat_cap);
+ ice_set_bit(ICE_FEATURE_HAS_PBA, sc->feat_cap);
/* Disable features due to hardware limitations... */
if (!sc->hw.func_caps.common_cap.rss_table_size)
@@ -2621,6 +2653,14 @@ ice_init_device_features(struct ice_softc *sc)
/* Disable features due to firmware limitations... */
if (!ice_is_fw_health_report_supported(&sc->hw))
ice_clear_bit(ICE_FEATURE_HEALTH_STATUS, sc->feat_cap);
+ if (!ice_fwlog_supported(&sc->hw))
+ ice_clear_bit(ICE_FEATURE_FW_LOGGING, sc->feat_cap);
+ if (sc->hw.fwlog_cfg.options & ICE_FWLOG_OPTION_IS_REGISTERED) {
+ if (ice_is_bit_set(sc->feat_cap, ICE_FEATURE_FW_LOGGING))
+ ice_set_bit(ICE_FEATURE_FW_LOGGING, sc->feat_en);
+ else
+ ice_fwlog_unregister(&sc->hw);
+ }
/* Disable capabilities not supported by the OS */
ice_disable_unsupported_features(sc->feat_cap);
diff --git a/sys/dev/ice/virtchnl.h b/sys/dev/ice/virtchnl.h
index 936cbba1da14..0dd7fff09677 100644
--- a/sys/dev/ice/virtchnl.h
+++ b/sys/dev/ice/virtchnl.h
@@ -51,7 +51,7 @@
*
* The PF is required to return a status code in v_retval for all messages
* except RESET_VF, which does not require any response. The returned value
- * is of virtchnl_status_code type, defined in the shared type.h.
+ * is of virtchnl_status_code type, defined here.
*
* In general, VF driver initialization should roughly follow the order of
* these opcodes. The VF driver must first validate the API version of the
@@ -66,7 +66,23 @@
* value in current and future projects
*/
-/* Error Codes */
+#define VIRTCHNL_ETH_LENGTH_OF_ADDRESS 6
+
+/* These macros are used to generate compilation errors if a structure/union
+ * is not exactly the correct length. It gives a divide by zero error if the
+ * structure/union is not of the correct size, otherwise it creates an enum
+ * that is never used.
+ */
+#define VIRTCHNL_CHECK_STRUCT_LEN(n, X) enum virtchnl_static_assert_enum_##X \
+ { virtchnl_static_assert_##X = (n)/((sizeof(struct X) == (n)) ? 1 : 0) }
+#define VIRTCHNL_CHECK_UNION_LEN(n, X) enum virtchnl_static_asset_enum_##X \
+ { virtchnl_static_assert_##X = (n)/((sizeof(union X) == (n)) ? 1 : 0) }
+
+/* Error Codes
+ * Note that many older versions of various iAVF drivers convert the reported
+ * status code directly into an iavf_status enumeration. For this reason, it
+ * is important that the values of these enumerations line up.
+ */
enum virtchnl_status_code {
VIRTCHNL_STATUS_SUCCESS = 0,
VIRTCHNL_STATUS_ERR_PARAM = -5,
@@ -113,7 +129,9 @@ enum virtchnl_rx_hsplit {
VIRTCHNL_RX_HSPLIT_SPLIT_SCTP = 8,
};
-#define VIRTCHNL_ETH_LENGTH_OF_ADDRESS 6
+enum virtchnl_bw_limit_type {
+ VIRTCHNL_BW_SHAPER = 0,
+};
/* END GENERIC DEFINES */
/* Opcodes for VF-PF communication. These are placed in the v_opcode field
@@ -125,6 +143,7 @@ enum virtchnl_ops {
* VFs send requests to the PF using the other ops.
* Use of "advanced opcode" features must be negotiated as part of capabilities
* exchange and are not considered part of base mode feature set.
+ *
*/
VIRTCHNL_OP_UNKNOWN = 0,
VIRTCHNL_OP_VERSION = 1, /* must ALWAYS be 1 */
@@ -160,7 +179,10 @@ enum virtchnl_ops {
/* opcode 34 is reserved */
/* opcodes 38, 39, 40, 41, 42 and 43 are reserved */
/* opcode 44 is reserved */
- /* opcode 45, 46, 47, 48 and 49 are reserved */
+ VIRTCHNL_OP_ADD_RSS_CFG = 45,
+ VIRTCHNL_OP_DEL_RSS_CFG = 46,
+ VIRTCHNL_OP_ADD_FDIR_FILTER = 47,
+ VIRTCHNL_OP_DEL_FDIR_FILTER = 48,
VIRTCHNL_OP_GET_MAX_RSS_QREGION = 50,
VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS = 51,
VIRTCHNL_OP_ADD_VLAN_V2 = 52,
@@ -171,7 +193,10 @@ enum virtchnl_ops {
VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2 = 57,
VIRTCHNL_OP_ENABLE_VLAN_FILTERING_V2 = 58,
VIRTCHNL_OP_DISABLE_VLAN_FILTERING_V2 = 59,
- /* opcodes 60 through 69 are reserved */
+ /* opcodes 60 through 65 are reserved */
+ VIRTCHNL_OP_GET_QOS_CAPS = 66,
+ VIRTCHNL_OP_CONFIG_QUEUE_TC_MAP = 67,
+ /* opcode 68, 69 are reserved */
VIRTCHNL_OP_ENABLE_QUEUES_V2 = 107,
VIRTCHNL_OP_DISABLE_QUEUES_V2 = 108,
VIRTCHNL_OP_MAP_QUEUE_VECTOR = 111,
@@ -239,6 +264,14 @@ static inline const char *virtchnl_op_str(enum virtchnl_ops v_opcode)
return "VIRTCHNL_OP_ADD_CLOUD_FILTER";
case VIRTCHNL_OP_DEL_CLOUD_FILTER:
return "VIRTCHNL_OP_DEL_CLOUD_FILTER";
+ case VIRTCHNL_OP_ADD_RSS_CFG:
+ return "VIRTCHNL_OP_ADD_RSS_CFG";
+ case VIRTCHNL_OP_DEL_RSS_CFG:
+ return "VIRTCHNL_OP_DEL_RSS_CFG";
+ case VIRTCHNL_OP_ADD_FDIR_FILTER:
+ return "VIRTCHNL_OP_ADD_FDIR_FILTER";
+ case VIRTCHNL_OP_DEL_FDIR_FILTER:
+ return "VIRTCHNL_OP_DEL_FDIR_FILTER";
case VIRTCHNL_OP_GET_MAX_RSS_QREGION:
return "VIRTCHNL_OP_GET_MAX_RSS_QREGION";
case VIRTCHNL_OP_ENABLE_QUEUES_V2:
@@ -272,15 +305,29 @@ static inline const char *virtchnl_op_str(enum virtchnl_ops v_opcode)
}
}
-/* These macros are used to generate compilation errors if a structure/union
- * is not exactly the correct length. It gives a divide by zero error if the
- * structure/union is not of the correct size, otherwise it creates an enum
- * that is never used.
- */
-#define VIRTCHNL_CHECK_STRUCT_LEN(n, X) enum virtchnl_static_assert_enum_##X \
- { virtchnl_static_assert_##X = (n)/((sizeof(struct X) == (n)) ? 1 : 0) }
-#define VIRTCHNL_CHECK_UNION_LEN(n, X) enum virtchnl_static_asset_enum_##X \
- { virtchnl_static_assert_##X = (n)/((sizeof(union X) == (n)) ? 1 : 0) }
+static inline const char *virtchnl_stat_str(enum virtchnl_status_code v_status)
+{
+ switch (v_status) {
+ case VIRTCHNL_STATUS_SUCCESS:
+ return "VIRTCHNL_STATUS_SUCCESS";
+ case VIRTCHNL_STATUS_ERR_PARAM:
+ return "VIRTCHNL_STATUS_ERR_PARAM";
+ case VIRTCHNL_STATUS_ERR_NO_MEMORY:
+ return "VIRTCHNL_STATUS_ERR_NO_MEMORY";
+ case VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH:
+ return "VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH";
+ case VIRTCHNL_STATUS_ERR_CQP_COMPL_ERROR:
+ return "VIRTCHNL_STATUS_ERR_CQP_COMPL_ERROR";
+ case VIRTCHNL_STATUS_ERR_INVALID_VF_ID:
+ return "VIRTCHNL_STATUS_ERR_INVALID_VF_ID";
+ case VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR:
+ return "VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR";
+ case VIRTCHNL_STATUS_ERR_NOT_SUPPORTED:
+ return "VIRTCHNL_STATUS_ERR_NOT_SUPPORTED";
+ default:
+ return "Unknown status code (update virtchnl.h)";
+ }
+}
/* Virtual channel message descriptor. This overlays the admin queue
* descriptor. All other data is passed in external buffers.
@@ -326,8 +373,9 @@ struct virtchnl_version_info {
VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_version_info);
-#define VF_IS_V10(_v) (((_v)->major == 1) && ((_v)->minor == 0))
+#define VF_IS_V10(_ver) (((_ver)->major == 1) && ((_ver)->minor == 0))
#define VF_IS_V11(_ver) (((_ver)->major == 1) && ((_ver)->minor == 1))
+#define VF_IS_V20(_ver) (((_ver)->major == 2) && ((_ver)->minor == 0))
/* VIRTCHNL_OP_RESET_VF
* VF sends this request to PF with no parameters
@@ -374,35 +422,36 @@ VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_vsi_resource);
* VIRTCHNL_VF_OFFLOAD_L2 flag is inclusive of base mode L2 offloads including
* TX/RX Checksum offloading and TSO for non-tunnelled packets.
*/
-#define VIRTCHNL_VF_OFFLOAD_L2 0x00000001
-#define VIRTCHNL_VF_OFFLOAD_IWARP 0x00000002
-#define VIRTCHNL_VF_OFFLOAD_RSVD 0x00000004
-#define VIRTCHNL_VF_OFFLOAD_RSS_AQ 0x00000008
-#define VIRTCHNL_VF_OFFLOAD_RSS_REG 0x00000010
-#define VIRTCHNL_VF_OFFLOAD_WB_ON_ITR 0x00000020
-#define VIRTCHNL_VF_OFFLOAD_REQ_QUEUES 0x00000040
-#define VIRTCHNL_VF_OFFLOAD_CRC 0x00000080
- /* 0X00000100 is reserved */
-#define VIRTCHNL_VF_LARGE_NUM_QPAIRS 0x00000200
-#define VIRTCHNL_VF_OFFLOAD_VLAN_V2 0x00008000
-#define VIRTCHNL_VF_OFFLOAD_VLAN 0x00010000
-#define VIRTCHNL_VF_OFFLOAD_RX_POLLING 0x00020000
-#define VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2 0x00040000
-#define VIRTCHNL_VF_OFFLOAD_RSS_PF 0X00080000
-#define VIRTCHNL_VF_OFFLOAD_ENCAP 0X00100000
-#define VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM 0X00200000
-#define VIRTCHNL_VF_OFFLOAD_RX_ENCAP_CSUM 0X00400000
-#define VIRTCHNL_VF_OFFLOAD_ADQ 0X00800000
-#define VIRTCHNL_VF_OFFLOAD_ADQ_V2 0X01000000
-#define VIRTCHNL_VF_OFFLOAD_USO 0X02000000
- /* 0x04000000 is reserved */
- /* 0X08000000 and 0X10000000 are reserved */
- /* 0X20000000 is reserved */
- /* 0X40000000 is reserved */
- /* 0X80000000 is reserved */
-
-/* Define below the capability flags that are not offloads */
-#define VIRTCHNL_VF_CAP_ADV_LINK_SPEED 0x00000080
+#define VIRTCHNL_VF_OFFLOAD_L2 BIT(0)
+#define VIRTCHNL_VF_OFFLOAD_IWARP BIT(1)
+#define VIRTCHNL_VF_CAP_RDMA VIRTCHNL_VF_OFFLOAD_IWARP
+#define VIRTCHNL_VF_OFFLOAD_RSS_AQ BIT(3)
+#define VIRTCHNL_VF_OFFLOAD_RSS_REG BIT(4)
+#define VIRTCHNL_VF_OFFLOAD_WB_ON_ITR BIT(5)
+#define VIRTCHNL_VF_OFFLOAD_REQ_QUEUES BIT(6)
+/* used to negotiate communicating link speeds in Mbps */
+#define VIRTCHNL_VF_CAP_ADV_LINK_SPEED BIT(7)
+ /* BIT(8) is reserved */
+#define VIRTCHNL_VF_LARGE_NUM_QPAIRS BIT(9)
+#define VIRTCHNL_VF_OFFLOAD_CRC BIT(10)
+#define VIRTCHNL_VF_OFFLOAD_VLAN_V2 BIT(15)
+#define VIRTCHNL_VF_OFFLOAD_VLAN BIT(16)
+#define VIRTCHNL_VF_OFFLOAD_RX_POLLING BIT(17)
+#define VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2 BIT(18)
+#define VIRTCHNL_VF_OFFLOAD_RSS_PF BIT(19)
+#define VIRTCHNL_VF_OFFLOAD_ENCAP BIT(20)
+#define VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM BIT(21)
+#define VIRTCHNL_VF_OFFLOAD_RX_ENCAP_CSUM BIT(22)
+#define VIRTCHNL_VF_OFFLOAD_ADQ BIT(23)
+#define VIRTCHNL_VF_OFFLOAD_ADQ_V2 BIT(24)
+#define VIRTCHNL_VF_OFFLOAD_USO BIT(25)
+ /* BIT(26) is reserved */
+#define VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF BIT(27)
+#define VIRTCHNL_VF_OFFLOAD_FDIR_PF BIT(28)
+#define VIRTCHNL_VF_OFFLOAD_QOS BIT(29)
+ /* BIT(30) is reserved */
+ /* BIT(31) is reserved */
+
#define VF_BASE_MODE_OFFLOADS (VIRTCHNL_VF_OFFLOAD_L2 | \
VIRTCHNL_VF_OFFLOAD_VLAN | \
VIRTCHNL_VF_OFFLOAD_RSS_PF)
@@ -440,6 +489,54 @@ struct virtchnl_txq_info {
VIRTCHNL_CHECK_STRUCT_LEN(24, virtchnl_txq_info);
+/* RX descriptor IDs (range from 0 to 63) */
+enum virtchnl_rx_desc_ids {
+ VIRTCHNL_RXDID_0_16B_BASE = 0,
+ /* 32B_BASE and FLEX_SPLITQ share desc ids as default descriptors
+ * because they can be differentiated based on queue model; e.g. single
+ * queue model can only use 32B_BASE and split queue model can only use
+ * FLEX_SPLITQ. Having these as 1 allows them to be used as default
+ * descriptors without negotiation.
+ */
+ VIRTCHNL_RXDID_1_32B_BASE = 1,
+ VIRTCHNL_RXDID_1_FLEX_SPLITQ = 1,
+ VIRTCHNL_RXDID_2_FLEX_SQ_NIC = 2,
+ VIRTCHNL_RXDID_3_FLEX_SQ_SW = 3,
+ VIRTCHNL_RXDID_4_FLEX_SQ_NIC_VEB = 4,
+ VIRTCHNL_RXDID_5_FLEX_SQ_NIC_ACL = 5,
+ VIRTCHNL_RXDID_6_FLEX_SQ_NIC_2 = 6,
+ VIRTCHNL_RXDID_7_HW_RSVD = 7,
+ /* 9 through 15 are reserved */
+ VIRTCHNL_RXDID_16_COMMS_GENERIC = 16,
+ VIRTCHNL_RXDID_17_COMMS_AUX_VLAN = 17,
+ VIRTCHNL_RXDID_18_COMMS_AUX_IPV4 = 18,
+ VIRTCHNL_RXDID_19_COMMS_AUX_IPV6 = 19,
+ VIRTCHNL_RXDID_20_COMMS_AUX_FLOW = 20,
+ VIRTCHNL_RXDID_21_COMMS_AUX_TCP = 21,
+ /* 22 through 63 are reserved */
+};
+
+/* RX descriptor ID bitmasks */
+enum virtchnl_rx_desc_id_bitmasks {
+ VIRTCHNL_RXDID_0_16B_BASE_M = BIT(VIRTCHNL_RXDID_0_16B_BASE),
+ VIRTCHNL_RXDID_1_32B_BASE_M = BIT(VIRTCHNL_RXDID_1_32B_BASE),
+ VIRTCHNL_RXDID_1_FLEX_SPLITQ_M = BIT(VIRTCHNL_RXDID_1_FLEX_SPLITQ),
+ VIRTCHNL_RXDID_2_FLEX_SQ_NIC_M = BIT(VIRTCHNL_RXDID_2_FLEX_SQ_NIC),
+ VIRTCHNL_RXDID_3_FLEX_SQ_SW_M = BIT(VIRTCHNL_RXDID_3_FLEX_SQ_SW),
+ VIRTCHNL_RXDID_4_FLEX_SQ_NIC_VEB_M = BIT(VIRTCHNL_RXDID_4_FLEX_SQ_NIC_VEB),
+ VIRTCHNL_RXDID_5_FLEX_SQ_NIC_ACL_M = BIT(VIRTCHNL_RXDID_5_FLEX_SQ_NIC_ACL),
+ VIRTCHNL_RXDID_6_FLEX_SQ_NIC_2_M = BIT(VIRTCHNL_RXDID_6_FLEX_SQ_NIC_2),
+ VIRTCHNL_RXDID_7_HW_RSVD_M = BIT(VIRTCHNL_RXDID_7_HW_RSVD),
+ /* 9 through 15 are reserved */
+ VIRTCHNL_RXDID_16_COMMS_GENERIC_M = BIT(VIRTCHNL_RXDID_16_COMMS_GENERIC),
+ VIRTCHNL_RXDID_17_COMMS_AUX_VLAN_M = BIT(VIRTCHNL_RXDID_17_COMMS_AUX_VLAN),
+ VIRTCHNL_RXDID_18_COMMS_AUX_IPV4_M = BIT(VIRTCHNL_RXDID_18_COMMS_AUX_IPV4),
+ VIRTCHNL_RXDID_19_COMMS_AUX_IPV6_M = BIT(VIRTCHNL_RXDID_19_COMMS_AUX_IPV6),
+ VIRTCHNL_RXDID_20_COMMS_AUX_FLOW_M = BIT(VIRTCHNL_RXDID_20_COMMS_AUX_FLOW),
+ VIRTCHNL_RXDID_21_COMMS_AUX_TCP_M = BIT(VIRTCHNL_RXDID_21_COMMS_AUX_TCP),
+ /* 22 through 63 are reserved */
+};
+
/* VIRTCHNL_OP_CONFIG_RX_QUEUE
* VF sends this message to set up parameters for one RX queue.
* External data buffer contains one instance of virtchnl_rxq_info.
@@ -1127,6 +1224,14 @@ struct virtchnl_rss_hena {
VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_rss_hena);
+/* Type of RSS algorithm */
+enum virtchnl_rss_algorithm {
+ VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC = 0,
+ VIRTCHNL_RSS_ALG_R_ASYMMETRIC = 1,
+ VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC = 2,
+ VIRTCHNL_RSS_ALG_XOR_SYMMETRIC = 3,
+};
+
/* This is used by PF driver to enforce how many channels can be supported.
* When ADQ_V2 capability is negotiated, it will allow 16 channels otherwise
* PF driver will allow only max 4 channels
@@ -1225,6 +1330,14 @@ struct virtchnl_filter {
VIRTCHNL_CHECK_STRUCT_LEN(272, virtchnl_filter);
+struct virtchnl_shaper_bw {
+ /* Unit is Kbps */
+ u32 committed;
+ u32 peak;
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_shaper_bw);
+
/* VIRTCHNL_OP_EVENT
* PF sends this message to inform the VF driver of events that may affect it.
* No direct response is expected from the VF, though it may generate other
@@ -1296,6 +1409,393 @@ enum virtchnl_vfr_states {
VIRTCHNL_VFR_VFACTIVE,
};
+#define VIRTCHNL_MAX_NUM_PROTO_HDRS 32
+#define PROTO_HDR_SHIFT 5
+#define PROTO_HDR_FIELD_START(proto_hdr_type) \
+ (proto_hdr_type << PROTO_HDR_SHIFT)
+#define PROTO_HDR_FIELD_MASK ((1UL << PROTO_HDR_SHIFT) - 1)
+
+/* VF use these macros to configure each protocol header.
+ * Specify which protocol headers and protocol header fields base on
+ * virtchnl_proto_hdr_type and virtchnl_proto_hdr_field.
+ * @param hdr: a struct of virtchnl_proto_hdr
+ * @param hdr_type: ETH/IPV4/TCP, etc
+ * @param field: SRC/DST/TEID/SPI, etc
+ */
+#define VIRTCHNL_ADD_PROTO_HDR_FIELD(hdr, field) \
+ ((hdr)->field_selector |= BIT((field) & PROTO_HDR_FIELD_MASK))
+#define VIRTCHNL_DEL_PROTO_HDR_FIELD(hdr, field) \
+ ((hdr)->field_selector &= ~BIT((field) & PROTO_HDR_FIELD_MASK))
+#define VIRTCHNL_TEST_PROTO_HDR_FIELD(hdr, val) \
+ ((hdr)->field_selector & BIT((val) & PROTO_HDR_FIELD_MASK))
+#define VIRTCHNL_GET_PROTO_HDR_FIELD(hdr) ((hdr)->field_selector)
+
+#define VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, hdr_type, field) \
+ (VIRTCHNL_ADD_PROTO_HDR_FIELD(hdr, \
+ VIRTCHNL_PROTO_HDR_ ## hdr_type ## _ ## field))
+#define VIRTCHNL_DEL_PROTO_HDR_FIELD_BIT(hdr, hdr_type, field) \
+ (VIRTCHNL_DEL_PROTO_HDR_FIELD(hdr, \
+ VIRTCHNL_PROTO_HDR_ ## hdr_type ## _ ## field))
+
+#define VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, hdr_type) \
+ ((hdr)->type = VIRTCHNL_PROTO_HDR_ ## hdr_type)
+#define VIRTCHNL_GET_PROTO_HDR_TYPE(hdr) \
+ (((hdr)->type) >> PROTO_HDR_SHIFT)
+#define VIRTCHNL_TEST_PROTO_HDR_TYPE(hdr, val) \
+ ((hdr)->type == ((s32)((val) >> PROTO_HDR_SHIFT)))
+#define VIRTCHNL_TEST_PROTO_HDR(hdr, val) \
+ (VIRTCHNL_TEST_PROTO_HDR_TYPE(hdr, val) && \
+ VIRTCHNL_TEST_PROTO_HDR_FIELD(hdr, val))
+
+/* Protocol header type within a packet segment. A segment consists of one or
+ * more protocol headers that make up a logical group of protocol headers. Each
+ * logical group of protocol headers encapsulates or is encapsulated using/by
+ * tunneling or encapsulation protocols for network virtualization.
+ */
+enum virtchnl_proto_hdr_type {
+ VIRTCHNL_PROTO_HDR_NONE,
+ VIRTCHNL_PROTO_HDR_ETH,
+ VIRTCHNL_PROTO_HDR_S_VLAN,
+ VIRTCHNL_PROTO_HDR_C_VLAN,
+ VIRTCHNL_PROTO_HDR_IPV4,
+ VIRTCHNL_PROTO_HDR_IPV6,
+ VIRTCHNL_PROTO_HDR_TCP,
+ VIRTCHNL_PROTO_HDR_UDP,
+ VIRTCHNL_PROTO_HDR_SCTP,
+ VIRTCHNL_PROTO_HDR_GTPU_IP,
+ VIRTCHNL_PROTO_HDR_GTPU_EH,
+ VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_DWN,
+ VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_UP,
+ VIRTCHNL_PROTO_HDR_PPPOE,
+ VIRTCHNL_PROTO_HDR_L2TPV3,
+ VIRTCHNL_PROTO_HDR_ESP,
+ VIRTCHNL_PROTO_HDR_AH,
+ VIRTCHNL_PROTO_HDR_PFCP,
+ VIRTCHNL_PROTO_HDR_GTPC,
+ VIRTCHNL_PROTO_HDR_ECPRI,
+ VIRTCHNL_PROTO_HDR_L2TPV2,
+ VIRTCHNL_PROTO_HDR_PPP,
+ /* IPv4 and IPv6 Fragment header types are only associated to
+ * VIRTCHNL_PROTO_HDR_IPV4 and VIRTCHNL_PROTO_HDR_IPV6 respectively,
+ * cannot be used independently.
+ */
+ VIRTCHNL_PROTO_HDR_IPV4_FRAG,
+ VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG,
+ VIRTCHNL_PROTO_HDR_GRE,
+};
+
+/* Protocol header field within a protocol header. */
+enum virtchnl_proto_hdr_field {
+ /* ETHER */
+ VIRTCHNL_PROTO_HDR_ETH_SRC =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_ETH),
+ VIRTCHNL_PROTO_HDR_ETH_DST,
+ VIRTCHNL_PROTO_HDR_ETH_ETHERTYPE,
+ /* S-VLAN */
+ VIRTCHNL_PROTO_HDR_S_VLAN_ID =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_S_VLAN),
+ /* C-VLAN */
+ VIRTCHNL_PROTO_HDR_C_VLAN_ID =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_C_VLAN),
+ /* IPV4 */
+ VIRTCHNL_PROTO_HDR_IPV4_SRC =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_IPV4),
+ VIRTCHNL_PROTO_HDR_IPV4_DST,
+ VIRTCHNL_PROTO_HDR_IPV4_DSCP,
+ VIRTCHNL_PROTO_HDR_IPV4_TTL,
+ VIRTCHNL_PROTO_HDR_IPV4_PROT,
+ VIRTCHNL_PROTO_HDR_IPV4_CHKSUM,
+ /* IPV6 */
+ VIRTCHNL_PROTO_HDR_IPV6_SRC =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_IPV6),
+ VIRTCHNL_PROTO_HDR_IPV6_DST,
+ VIRTCHNL_PROTO_HDR_IPV6_TC,
+ VIRTCHNL_PROTO_HDR_IPV6_HOP_LIMIT,
+ VIRTCHNL_PROTO_HDR_IPV6_PROT,
+ /* IPV6 Prefix */
+ VIRTCHNL_PROTO_HDR_IPV6_PREFIX32_SRC,
+ VIRTCHNL_PROTO_HDR_IPV6_PREFIX32_DST,
+ VIRTCHNL_PROTO_HDR_IPV6_PREFIX40_SRC,
+ VIRTCHNL_PROTO_HDR_IPV6_PREFIX40_DST,
+ VIRTCHNL_PROTO_HDR_IPV6_PREFIX48_SRC,
+ VIRTCHNL_PROTO_HDR_IPV6_PREFIX48_DST,
+ VIRTCHNL_PROTO_HDR_IPV6_PREFIX56_SRC,
+ VIRTCHNL_PROTO_HDR_IPV6_PREFIX56_DST,
+ VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_SRC,
+ VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_DST,
+ VIRTCHNL_PROTO_HDR_IPV6_PREFIX96_SRC,
+ VIRTCHNL_PROTO_HDR_IPV6_PREFIX96_DST,
+ /* TCP */
+ VIRTCHNL_PROTO_HDR_TCP_SRC_PORT =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_TCP),
+ VIRTCHNL_PROTO_HDR_TCP_DST_PORT,
+ VIRTCHNL_PROTO_HDR_TCP_CHKSUM,
+ /* UDP */
+ VIRTCHNL_PROTO_HDR_UDP_SRC_PORT =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_UDP),
+ VIRTCHNL_PROTO_HDR_UDP_DST_PORT,
+ VIRTCHNL_PROTO_HDR_UDP_CHKSUM,
+ /* SCTP */
+ VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_SCTP),
+ VIRTCHNL_PROTO_HDR_SCTP_DST_PORT,
+ VIRTCHNL_PROTO_HDR_SCTP_CHKSUM,
+ /* GTPU_IP */
+ VIRTCHNL_PROTO_HDR_GTPU_IP_TEID =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_GTPU_IP),
+ /* GTPU_EH */
+ VIRTCHNL_PROTO_HDR_GTPU_EH_PDU =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_GTPU_EH),
+ VIRTCHNL_PROTO_HDR_GTPU_EH_QFI,
+ /* PPPOE */
+ VIRTCHNL_PROTO_HDR_PPPOE_SESS_ID =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_PPPOE),
+ /* L2TPV3 */
+ VIRTCHNL_PROTO_HDR_L2TPV3_SESS_ID =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_L2TPV3),
+ /* ESP */
+ VIRTCHNL_PROTO_HDR_ESP_SPI =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_ESP),
+ /* AH */
+ VIRTCHNL_PROTO_HDR_AH_SPI =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_AH),
+ /* PFCP */
+ VIRTCHNL_PROTO_HDR_PFCP_S_FIELD =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_PFCP),
+ VIRTCHNL_PROTO_HDR_PFCP_SEID,
+ /* GTPC */
+ VIRTCHNL_PROTO_HDR_GTPC_TEID =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_GTPC),
+ /* ECPRI */
+ VIRTCHNL_PROTO_HDR_ECPRI_MSG_TYPE =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_ECPRI),
+ VIRTCHNL_PROTO_HDR_ECPRI_PC_RTC_ID,
+ /* IPv4 Dummy Fragment */
+ VIRTCHNL_PROTO_HDR_IPV4_FRAG_PKID =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_IPV4_FRAG),
+ /* IPv6 Extension Fragment */
+ VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG_PKID =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG),
+ /* GTPU_DWN/UP */
+ VIRTCHNL_PROTO_HDR_GTPU_DWN_QFI =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_DWN),
+ VIRTCHNL_PROTO_HDR_GTPU_UP_QFI =
+ PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_UP),
+};
+
+struct virtchnl_proto_hdr {
+ /* see enum virtchnl_proto_hdr_type */
+ s32 type;
+ u32 field_selector; /* a bit mask to select field for header type */
+ u8 buffer[64];
+ /**
+ * binary buffer in network order for specific header type.
+ * For example, if type = VIRTCHNL_PROTO_HDR_IPV4, a IPv4
+ * header is expected to be copied into the buffer.
+ */
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(72, virtchnl_proto_hdr);
+
+struct virtchnl_proto_hdrs {
+ u8 tunnel_level;
+ /**
+ * specify where protocol header start from.
+ * 0 - from the outer layer
+ * 1 - from the first inner layer
+ * 2 - from the second inner layer
+ * ....
+ **/
+ int count; /* the proto layers must < VIRTCHNL_MAX_NUM_PROTO_HDRS */
+ struct virtchnl_proto_hdr proto_hdr[VIRTCHNL_MAX_NUM_PROTO_HDRS];
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(2312, virtchnl_proto_hdrs);
+
+struct virtchnl_rss_cfg {
+ struct virtchnl_proto_hdrs proto_hdrs; /* protocol headers */
+
+ /* see enum virtchnl_rss_algorithm; rss algorithm type */
+ s32 rss_algorithm;
+ u8 reserved[128]; /* reserve for future */
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(2444, virtchnl_rss_cfg);
+
+/* action configuration for FDIR */
+struct virtchnl_filter_action {
+ /* see enum virtchnl_action type */
+ s32 type;
+ union {
+ /* used for queue and qgroup action */
+ struct {
+ u16 index;
+ u8 region;
+ } queue;
+ /* used for count action */
+ struct {
+ /* share counter ID with other flow rules */
+ u8 shared;
+ u32 id; /* counter ID */
+ } count;
+ /* used for mark action */
+ u32 mark_id;
+ u8 reserve[32];
+ } act_conf;
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(36, virtchnl_filter_action);
+
+#define VIRTCHNL_MAX_NUM_ACTIONS 8
+
+struct virtchnl_filter_action_set {
+ /* action number must be less then VIRTCHNL_MAX_NUM_ACTIONS */
+ int count;
+ struct virtchnl_filter_action actions[VIRTCHNL_MAX_NUM_ACTIONS];
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(292, virtchnl_filter_action_set);
+
+/* pattern and action for FDIR rule */
+struct virtchnl_fdir_rule {
+ struct virtchnl_proto_hdrs proto_hdrs;
+ struct virtchnl_filter_action_set action_set;
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(2604, virtchnl_fdir_rule);
+
+/* Status returned to VF after VF requests FDIR commands
+ * VIRTCHNL_FDIR_SUCCESS
+ * VF FDIR related request is successfully done by PF
+ * The request can be OP_ADD/DEL/QUERY_FDIR_FILTER.
+ *
+ * VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE
+ * OP_ADD_FDIR_FILTER request is failed due to no Hardware resource.
+ *
+ * VIRTCHNL_FDIR_FAILURE_RULE_EXIST
+ * OP_ADD_FDIR_FILTER request is failed due to the rule is already existed.
+ *
+ * VIRTCHNL_FDIR_FAILURE_RULE_CONFLICT
+ * OP_ADD_FDIR_FILTER request is failed due to conflict with existing rule.
+ *
+ * VIRTCHNL_FDIR_FAILURE_RULE_NONEXIST
+ * OP_DEL_FDIR_FILTER request is failed due to this rule doesn't exist.
+ *
+ * VIRTCHNL_FDIR_FAILURE_RULE_INVALID
+ * OP_ADD_FDIR_FILTER request is failed due to parameters validation
+ * or HW doesn't support.
+ *
+ * VIRTCHNL_FDIR_FAILURE_RULE_TIMEOUT
+ * OP_ADD/DEL_FDIR_FILTER request is failed due to timing out
+ * for programming.
+ *
+ * VIRTCHNL_FDIR_FAILURE_QUERY_INVALID
+ * OP_QUERY_FDIR_FILTER request is failed due to parameters validation,
+ * for example, VF query counter of a rule who has no counter action.
+ */
+enum virtchnl_fdir_prgm_status {
+ VIRTCHNL_FDIR_SUCCESS = 0,
+ VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE,
+ VIRTCHNL_FDIR_FAILURE_RULE_EXIST,
+ VIRTCHNL_FDIR_FAILURE_RULE_CONFLICT,
+ VIRTCHNL_FDIR_FAILURE_RULE_NONEXIST,
+ VIRTCHNL_FDIR_FAILURE_RULE_INVALID,
+ VIRTCHNL_FDIR_FAILURE_RULE_TIMEOUT,
+ VIRTCHNL_FDIR_FAILURE_QUERY_INVALID,
+};
+
+/* VIRTCHNL_OP_ADD_FDIR_FILTER
+ * VF sends this request to PF by filling out vsi_id,
+ * validate_only and rule_cfg. PF will return flow_id
+ * if the request is successfully done and return add_status to VF.
+ */
+struct virtchnl_fdir_add {
+ u16 vsi_id; /* INPUT */
+ /*
+ * 1 for validating a fdir rule, 0 for creating a fdir rule.
+ * Validate and create share one ops: VIRTCHNL_OP_ADD_FDIR_FILTER.
+ */
+ u16 validate_only; /* INPUT */
+ u32 flow_id; /* OUTPUT */
+ struct virtchnl_fdir_rule rule_cfg; /* INPUT */
+
+ /* see enum virtchnl_fdir_prgm_status; OUTPUT */
+ s32 status;
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(2616, virtchnl_fdir_add);
+
+/* VIRTCHNL_OP_DEL_FDIR_FILTER
+ * VF sends this request to PF by filling out vsi_id
+ * and flow_id. PF will return del_status to VF.
+ */
+struct virtchnl_fdir_del {
+ u16 vsi_id; /* INPUT */
+ u16 pad;
+ u32 flow_id; /* INPUT */
+
+ /* see enum virtchnl_fdir_prgm_status; OUTPUT */
+ s32 status;
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_fdir_del);
+
+/* VIRTCHNL_OP_GET_QOS_CAPS
+ * VF sends this message to get its QoS Caps, such as
+ * TC number, Arbiter and Bandwidth.
+ */
+struct virtchnl_qos_cap_elem {
+ u8 tc_num;
+ u8 tc_prio;
+#define VIRTCHNL_ABITER_STRICT 0
+#define VIRTCHNL_ABITER_ETS 2
+ u8 arbiter;
+#define VIRTCHNL_STRICT_WEIGHT 1
+ u8 weight;
+ enum virtchnl_bw_limit_type type;
+ union {
+ struct virtchnl_shaper_bw shaper;
+ u8 pad2[32];
+ };
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(40, virtchnl_qos_cap_elem);
+
+struct virtchnl_qos_cap_list {
+ u16 vsi_id;
+ u16 num_elem;
+ struct virtchnl_qos_cap_elem cap[1];
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(44, virtchnl_qos_cap_list);
+
+/* VIRTCHNL_OP_CONFIG_QUEUE_TC_MAP
+ * VF sends message virtchnl_queue_tc_mapping to set queue to tc
+ * mapping for all the Tx and Rx queues with a specified VSI, and
+ * would get response about bitmap of valid user priorities
+ * associated with queues.
+ */
+struct virtchnl_queue_tc_mapping {
+ u16 vsi_id;
+ u16 num_tc;
+ u16 num_queue_pairs;
+ u8 pad[2];
+ union {
+ struct {
+ u16 start_queue_id;
+ u16 queue_count;
+ } req;
+ struct {
+#define VIRTCHNL_USER_PRIO_TYPE_UP 0
+#define VIRTCHNL_USER_PRIO_TYPE_DSCP 1
+ u16 prio_type;
+ u16 valid_prio_bitmap;
+ } resp;
+ } tc[1];
+};
+
+VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_queue_tc_mapping);
+
/* TX and RX queue types are valid in legacy as well as split queue models.
* With Split Queue model, 2 additional types are introduced - TX_COMPLETION
* and RX_BUFFER. In split queue model, RX corresponds to the queue where HW
@@ -1605,6 +2105,31 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode,
case VIRTCHNL_OP_DEL_CLOUD_FILTER:
valid_len = sizeof(struct virtchnl_filter);
break;
+ case VIRTCHNL_OP_ADD_RSS_CFG:
+ case VIRTCHNL_OP_DEL_RSS_CFG:
+ valid_len = sizeof(struct virtchnl_rss_cfg);
+ break;
+ case VIRTCHNL_OP_ADD_FDIR_FILTER:
+ valid_len = sizeof(struct virtchnl_fdir_add);
+ break;
+ case VIRTCHNL_OP_DEL_FDIR_FILTER:
+ valid_len = sizeof(struct virtchnl_fdir_del);
+ break;
+ case VIRTCHNL_OP_GET_QOS_CAPS:
+ break;
+ case VIRTCHNL_OP_CONFIG_QUEUE_TC_MAP:
+ valid_len = sizeof(struct virtchnl_queue_tc_mapping);
+ if (msglen >= valid_len) {
+ struct virtchnl_queue_tc_mapping *q_tc =
+ (struct virtchnl_queue_tc_mapping *)msg;
+ if (q_tc->num_tc == 0) {
+ err_msg_format = true;
+ break;
+ }
+ valid_len += (q_tc->num_tc - 1) *
+ sizeof(q_tc->tc[0]);
+ }
+ break;
case VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS:
break;
case VIRTCHNL_OP_ADD_VLAN_V2:
diff --git a/sys/dev/ice/virtchnl_inline_ipsec.h b/sys/dev/ice/virtchnl_inline_ipsec.h
index 438a3022e7e8..a8b1c7d12d97 100644
--- a/sys/dev/ice/virtchnl_inline_ipsec.h
+++ b/sys/dev/ice/virtchnl_inline_ipsec.h
@@ -50,6 +50,16 @@
#define VIRTCHNL_CIPHER 2
#define VIRTCHNL_AEAD 3
+/* caps enabled */
+#define VIRTCHNL_IPSEC_ESN_ENA BIT(0)
+#define VIRTCHNL_IPSEC_UDP_ENCAP_ENA BIT(1)
+#define VIRTCHNL_IPSEC_SA_INDEX_SW_ENA BIT(2)
+#define VIRTCHNL_IPSEC_AUDIT_ENA BIT(3)
+#define VIRTCHNL_IPSEC_BYTE_LIMIT_ENA BIT(4)
+#define VIRTCHNL_IPSEC_DROP_ON_AUTH_FAIL_ENA BIT(5)
+#define VIRTCHNL_IPSEC_ARW_CHECK_ENA BIT(6)
+#define VIRTCHNL_IPSEC_24BIT_SPI_ENA BIT(7)
+
/* algorithm type */
/* Hash Algorithm */
#define VIRTCHNL_HASH_NO_ALG 0 /* NULL algorithm */
@@ -162,6 +172,7 @@ struct virtchnl_sym_crypto_cap {
* VF pass virtchnl_ipsec_cap to PF
* and PF return capability of ipsec from virtchnl.
*/
+#pragma pack(1)
struct virtchnl_ipsec_cap {
/* max number of SA per VF */
u16 max_sa_num;
@@ -175,41 +186,22 @@ struct virtchnl_ipsec_cap {
/* IPSec SA Direction - value ref VIRTCHNL_DIR_XXX */
u8 virtchnl_direction;
- /* type of esn - !0:enable/0:disable */
- u8 esn_enabled;
-
- /* type of udp_encap - !0:enable/0:disable */
- u8 udp_encap_enabled;
-
/* termination mode - value ref VIRTCHNL_TERM_XXX */
u8 termination_mode;
- /* SA index mode - !0:enable/0:disable */
- u8 sa_index_sw_enabled;
-
- /* auditing mode - !0:enable/0:disable */
- u8 audit_enabled;
-
- /* lifetime byte limit - !0:enable/0:disable */
- u8 byte_limit_enabled;
-
- /* drop on authentication failure - !0:enable/0:disable */
- u8 drop_on_auth_fail_enabled;
-
- /* anti-replay window check - !0:enable/0:disable */
- u8 arw_check_enabled;
-
/* number of supported crypto capability */
u8 crypto_cap_num;
/* descriptor ID */
u16 desc_id;
+ /* capabilities enabled - value ref VIRTCHNL_IPSEC_XXX_ENA */
+ u32 caps_enabled;
+
/* crypto capabilities */
struct virtchnl_sym_crypto_cap cap[VIRTCHNL_IPSEC_MAX_CRYPTO_CAP_NUM];
};
-#pragma pack(1)
/* configuration of crypto function */
struct virtchnl_ipsec_crypto_cfg_item {
u8 crypto_type;
diff --git a/sys/dev/ice/virtchnl_lan_desc.h b/sys/dev/ice/virtchnl_lan_desc.h
index 5ca63253da34..2dd4106de721 100644
--- a/sys/dev/ice/virtchnl_lan_desc.h
+++ b/sys/dev/ice/virtchnl_lan_desc.h
@@ -34,56 +34,94 @@
#define _VIRTCHNL_LAN_DESC_H_
/* Rx */
-/* For virtchnl_splitq_base_rx_flex desc members */
-#define VIRTCHNL_RXD_FLEX_PTYPE_S 0
-#define VIRTCHNL_RXD_FLEX_PTYPE_M \
- MAKEMASK(0x3FFUL, VIRTCHNL_RXD_FLEX_PTYPE_S)
-#define VIRTCHNL_RXD_FLEX_UMBCAST_S 10
-#define VIRTCHNL_RXD_FLEX_UMBCAST_M \
- MAKEMASK(0x3UL, VIRTCHNL_RXD_FLEX_UMBCAST_S)
-#define VIRTCHNL_RXD_FLEX_FF0_S 12
-#define VIRTCHNL_RXD_FLEX_FF0_M MAKEMASK(0xFUL, VIRTCHNL_RXD_FLEX_FF0_S)
-#define VIRTCHNL_RXD_FLEX_LEN_PBUF_S 0
-#define VIRTCHNL_RXD_FLEX_LEN_PBUF_M \
- MAKEMASK(0x3FFFUL, VIRTCHNL_RXD_FLEX_LEN_PBUF_S)
-#define VIRTCHNL_RXD_FLEX_GEN_S 14
-#define VIRTCHNL_RXD_FLEX_GEN_M BIT_ULL(VIRTCHNL_RXD_FLEX_GEN_S)
-#define VIRTCHNL_RXD_FLEX_BUFQ_ID_S 15
-#define VIRTCHNL_RXD_FLEX_BUFQ_ID_M \
- BIT_ULL(VIRTCHNL_RXD_FLEX_BUFQ_ID_S)
-#define VIRTCHNL_RXD_FLEX_LEN_HDR_S 0
-#define VIRTCHNL_RXD_FLEX_LEN_HDR_M \
- MAKEMASK(0x3FFUL, VIRTCHNL_RXD_FLEX_LEN_HDR_S)
-#define VIRTCHNL_RXD_FLEX_RSC_S 10
-#define VIRTCHNL_RXD_FLEX_RSC_M BIT_ULL(VIRTCHNL_RXD_FLEX_RSC_S)
-#define VIRTCHNL_RXD_FLEX_SPH_S 11
-#define VIRTCHNL_RXD_FLEX_SPH_M BIT_ULL(VIRTCHNL_RXD_FLEX_SPH_S)
-#define VIRTCHNL_RXD_FLEX_MISS_S 12
-#define VIRTCHNL_RXD_FLEX_MISS_M \
- BIT_ULL(VIRTCHNL_RXD_FLEX_MISS_S)
-#define VIRTCHNL_RXD_FLEX_FF1_S 13
-#define VIRTCHNL_RXD_FLEX_FF1_M MAKEMASK(0x7UL, VIRTCHNL_RXD_FLEX_FF1_M)
-
-/* For virtchnl_singleq_base_rx_legacy desc members */
-#define VIRTCHNL_RXD_QW1_LEN_SPH_S 63
-#define VIRTCHNL_RXD_QW1_LEN_SPH_M BIT_ULL(VIRTCHNL_RXD_QW1_LEN_SPH_S)
-#define VIRTCHNL_RXD_QW1_LEN_HBUF_S 52
-#define VIRTCHNL_RXD_QW1_LEN_HBUF_M \
- MAKEMASK(0x7FFULL, VIRTCHNL_RXD_QW1_LEN_HBUF_S)
-#define VIRTCHNL_RXD_QW1_LEN_PBUF_S 38
-#define VIRTCHNL_RXD_QW1_LEN_PBUF_M \
- MAKEMASK(0x3FFFULL, VIRTCHNL_RXD_QW1_LEN_PBUF_S)
-#define VIRTCHNL_RXD_QW1_PTYPE_S 30
-#define VIRTCHNL_RXD_QW1_PTYPE_M \
- MAKEMASK(0xFFULL, VIRTCHNL_RXD_QW1_PTYPE_S)
-#define VIRTCHNL_RXD_QW1_ERROR_S 19
-#define VIRTCHNL_RXD_QW1_ERROR_M \
- MAKEMASK(0xFFUL, VIRTCHNL_RXD_QW1_ERROR_S)
-#define VIRTCHNL_RXD_QW1_STATUS_S 0
-#define VIRTCHNL_RXD_QW1_STATUS_M \
- MAKEMASK(0x7FFFFUL, VIRTCHNL_RXD_QW1_STATUS_S)
-
-enum virtchnl_rx_flex_desc_status_error_0_qw1_bits {
+/* For splitq virtchnl_rx_flex_desc_adv desc members */
+#define VIRTCHNL_RX_FLEX_DESC_ADV_RXDID_S 0
+#define VIRTCHNL_RX_FLEX_DESC_ADV_RXDID_M \
+ MAKEMASK(0xFUL, VIRTCHNL_RX_FLEX_DESC_ADV_RXDID_S)
+#define VIRTCHNL_RX_FLEX_DESC_ADV_PTYPE_S 0
+#define VIRTCHNL_RX_FLEX_DESC_ADV_PTYPE_M \
+ MAKEMASK(0x3FFUL, VIRTCHNL_RX_FLEX_DESC_ADV_PTYPE_S)
+#define VIRTCHNL_RX_FLEX_DESC_ADV_UMBCAST_S 10
+#define VIRTCHNL_RX_FLEX_DESC_ADV_UMBCAST_M \
+ MAKEMASK(0x3UL, VIRTCHNL_RX_FLEX_DESC_ADV_UMBCAST_S)
+#define VIRTCHNL_RX_FLEX_DESC_ADV_FF0_S 12
+#define VIRTCHNL_RX_FLEX_DESC_ADV_FF0_M \
+ MAKEMASK(0xFUL, VIRTCHNL_RX_FLEX_DESC_ADV_FF0_S)
+#define VIRTCHNL_RX_FLEX_DESC_ADV_LEN_PBUF_S 0
+#define VIRTCHNL_RX_FLEX_DESC_ADV_LEN_PBUF_M \
+ MAKEMASK(0x3FFFUL, VIRTCHNL_RX_FLEX_DESC_ADV_LEN_PBUF_S)
+#define VIRTCHNL_RX_FLEX_DESC_ADV_GEN_S 14
+#define VIRTCHNL_RX_FLEX_DESC_ADV_GEN_M \
+ BIT_ULL(VIRTCHNL_RX_FLEX_DESC_ADV_GEN_S)
+#define VIRTCHNL_RX_FLEX_DESC_ADV_BUFQ_ID_S 15
+#define VIRTCHNL_RX_FLEX_DESC_ADV_BUFQ_ID_M \
+ BIT_ULL(VIRTCHNL_RX_FLEX_DESC_ADV_BUFQ_ID_S)
+#define VIRTCHNL_RX_FLEX_DESC_ADV_LEN_HDR_S 0
+#define VIRTCHNL_RX_FLEX_DESC_ADV_LEN_HDR_M \
+ MAKEMASK(0x3FFUL, VIRTCHNL_RX_FLEX_DESC_ADV_LEN_HDR_S)
+#define VIRTCHNL_RX_FLEX_DESC_ADV_RSC_S 10
+#define VIRTCHNL_RX_FLEX_DESC_ADV_RSC_M \
+ BIT_ULL(VIRTCHNL_RX_FLEX_DESC_ADV_RSC_S)
+#define VIRTCHNL_RX_FLEX_DESC_ADV_SPH_S 11
+#define VIRTCHNL_RX_FLEX_DESC_ADV_SPH_M \
+ BIT_ULL(VIRTCHNL_RX_FLEX_DESC_ADV_SPH_S)
+#define VIRTCHNL_RX_FLEX_DESC_ADV_MISS_S 12
+#define VIRTCHNL_RX_FLEX_DESC_ADV_MISS_M \
+ BIT_ULL(VIRTCHNL_RX_FLEX_DESC_ADV_MISS_S)
+#define VIRTCHNL_RX_FLEX_DESC_ADV_FF1_S 13
+#define VIRTCHNL_RX_FLEX_DESC_ADV_FF1_M \
+ MAKEMASK(0x7UL, VIRTCHNL_RX_FLEX_DESC_ADV_FF1_M)
+
+enum virtchnl_rx_flex_desc_adv_status_error_0_qw1_bits {
+ /* Note: These are predefined bit offsets */
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS0_DD_S = 0,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS0_EOF_S,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS0_HBO_S,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS0_L3L4P_S,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS0_XSUM_IPE_S,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS0_XSUM_L4E_S,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS0_XSUM_EIPE_S,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS0_XSUM_EUDPE_S,
+};
+
+enum virtchnl_rx_flex_desc_adv_status_error_0_qw0_bits {
+ /* Note: These are predefined bit offsets */
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS0_LPBK_S = 0,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS0_IPV6EXADD_S,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS0_RXE_S,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS0_CRCP_S,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS0_RSS_VALID_S,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS0_L2TAG1P_S,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS0_XTRMD0_VALID_S,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS0_XTRMD1_VALID_S,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS0_LAST /* this entry must be last!!! */
+};
+
+enum virtchnl_rx_flex_desc_adv_status_error_1_bits {
+ /* Note: These are predefined bit offsets */
+ /* 2 bits */
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS1_RSVD_S = 0,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS1_ATRAEFAIL_S = 2,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS1_L2TAG2P_S = 3,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS1_XTRMD2_VALID_S = 4,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS1_XTRMD3_VALID_S = 5,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS1_XTRMD4_VALID_S = 6,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS1_XTRMD5_VALID_S = 7,
+ VIRTCHNL_RX_FLEX_DESC_ADV_STATUS1_LAST /* this entry must be last!!! */
+};
+
+/* for singleq (flex) virtchnl_rx_flex_desc fields */
+/* for virtchnl_rx_flex_desc.ptype_flex_flags0 member */
+#define VIRTCHNL_RX_FLEX_DESC_PTYPE_S 0
+#define VIRTCHNL_RX_FLEX_DESC_PTYPE_M \
+ MAKEMASK(0x3FFUL, VIRTCHNL_RX_FLEX_DESC_PTYPE_S) /* 10-bits */
+
+/* for virtchnl_rx_flex_desc.pkt_length member */
+#define VIRTCHNL_RX_FLEX_DESC_PKT_LEN_S 0
+#define VIRTCHNL_RX_FLEX_DESC_PKT_LEN_M \
+ MAKEMASK(0x3FFFUL, VIRTCHNL_RX_FLEX_DESC_PKT_LEN_S) /* 14-bits */
+
+enum virtchnl_rx_flex_desc_status_error_0_bits {
/* Note: These are predefined bit offsets */
VIRTCHNL_RX_FLEX_DESC_STATUS0_DD_S = 0,
VIRTCHNL_RX_FLEX_DESC_STATUS0_EOF_S,
@@ -93,10 +131,7 @@ enum virtchnl_rx_flex_desc_status_error_0_qw1_bits {
VIRTCHNL_RX_FLEX_DESC_STATUS0_XSUM_L4E_S,
VIRTCHNL_RX_FLEX_DESC_STATUS0_XSUM_EIPE_S,
VIRTCHNL_RX_FLEX_DESC_STATUS0_XSUM_EUDPE_S,
-};
-
-enum virtchnl_rx_flex_desc_status_error_0_qw0_bits {
- VIRTCHNL_RX_FLEX_DESC_STATUS0_LPBK_S = 0,
+ VIRTCHNL_RX_FLEX_DESC_STATUS0_LPBK_S,
VIRTCHNL_RX_FLEX_DESC_STATUS0_IPV6EXADD_S,
VIRTCHNL_RX_FLEX_DESC_STATUS0_RXE_S,
VIRTCHNL_RX_FLEX_DESC_STATUS0_CRCP_S,
@@ -109,53 +144,80 @@ enum virtchnl_rx_flex_desc_status_error_0_qw0_bits {
enum virtchnl_rx_flex_desc_status_error_1_bits {
/* Note: These are predefined bit offsets */
- VIRTCHNL_RX_FLEX_DESC_STATUS1_RSVD_S = 0, /* 2 bits */
- VIRTCHNL_RX_FLEX_DESC_STATUS1_ATRAEFAIL_S = 2,
- VIRTCHNL_RX_FLEX_DESC_STATUS1_L2TAG2P_S = 3,
- VIRTCHNL_RX_FLEX_DESC_STATUS1_XTRMD2_VALID_S = 4,
- VIRTCHNL_RX_FLEX_DESC_STATUS1_XTRMD3_VALID_S = 5,
- VIRTCHNL_RX_FLEX_DESC_STATUS1_XTRMD4_VALID_S = 6,
- VIRTCHNL_RX_FLEX_DESC_STATUS1_XTRMD5_VALID_S = 7,
+ VIRTCHNL_RX_FLEX_DESC_STATUS1_CPM_S = 0, /* 4 bits */
+ VIRTCHNL_RX_FLEX_DESC_STATUS1_NAT_S = 4,
+ VIRTCHNL_RX_FLEX_DESC_STATUS1_CRYPTO_S = 5,
+ /* [10:6] reserved */
+ VIRTCHNL_RX_FLEX_DESC_STATUS1_L2TAG2P_S = 11,
+ VIRTCHNL_RX_FLEX_DESC_STATUS1_XTRMD2_VALID_S = 12,
+ VIRTCHNL_RX_FLEX_DESC_STATUS1_XTRMD3_VALID_S = 13,
+ VIRTCHNL_RX_FLEX_DESC_STATUS1_XTRMD4_VALID_S = 14,
+ VIRTCHNL_RX_FLEX_DESC_STATUS1_XTRMD5_VALID_S = 15,
VIRTCHNL_RX_FLEX_DESC_STATUS1_LAST /* this entry must be last!!! */
};
+/* For singleq (non flex) virtchnl_singleq_base_rx_desc legacy desc members */
+#define VIRTCHNL_RX_BASE_DESC_QW1_LEN_SPH_S 63
+#define VIRTCHNL_RX_BASE_DESC_QW1_LEN_SPH_M \
+ BIT_ULL(VIRTCHNL_RX_BASE_DESC_QW1_LEN_SPH_S)
+#define VIRTCHNL_RX_BASE_DESC_QW1_LEN_HBUF_S 52
+#define VIRTCHNL_RX_BASE_DESC_QW1_LEN_HBUF_M \
+ MAKEMASK(0x7FFULL, VIRTCHNL_RX_BASE_DESC_QW1_LEN_HBUF_S)
+#define VIRTCHNL_RX_BASE_DESC_QW1_LEN_PBUF_S 38
+#define VIRTCHNL_RX_BASE_DESC_QW1_LEN_PBUF_M \
+ MAKEMASK(0x3FFFULL, VIRTCHNL_RX_BASE_DESC_QW1_LEN_PBUF_S)
+#define VIRTCHNL_RX_BASE_DESC_QW1_PTYPE_S 30
+#define VIRTCHNL_RX_BASE_DESC_QW1_PTYPE_M \
+ MAKEMASK(0xFFULL, VIRTCHNL_RX_BASE_DESC_QW1_PTYPE_S)
+#define VIRTCHNL_RX_BASE_DESC_QW1_ERROR_S 19
+#define VIRTCHNL_RX_BASE_DESC_QW1_ERROR_M \
+ MAKEMASK(0xFFUL, VIRTCHNL_RX_BASE_DESC_QW1_ERROR_S)
+#define VIRTCHNL_RX_BASE_DESC_QW1_STATUS_S 0
+#define VIRTCHNL_RX_BASE_DESC_QW1_STATUS_M \
+ MAKEMASK(0x7FFFFUL, VIRTCHNL_RX_BASE_DESC_QW1_STATUS_S)
+
enum virtchnl_rx_base_desc_status_bits {
/* Note: These are predefined bit offsets */
VIRTCHNL_RX_BASE_DESC_STATUS_DD_S = 0,
VIRTCHNL_RX_BASE_DESC_STATUS_EOF_S = 1,
- VIRTCHNL_RX_BASE_DESC_STATUS_L2TAG1P_S = 2,
- VIRTCHNL_RX_BASE_DESC_STATUS_L3L4P_S = 3,
+ VIRTCHNL_RX_BASE_DESC_STATUS_L2TAG1P_S = 2,
+ VIRTCHNL_RX_BASE_DESC_STATUS_L3L4P_S = 3,
VIRTCHNL_RX_BASE_DESC_STATUS_CRCP_S = 4,
VIRTCHNL_RX_BASE_DESC_STATUS_RSVD_S = 5, /* 3 BITS */
VIRTCHNL_RX_BASE_DESC_STATUS_EXT_UDP_0_S = 8,
- VIRTCHNL_RX_BASE_DESC_STATUS_UMBCAST_S = 9, /* 2 BITS */
+ VIRTCHNL_RX_BASE_DESC_STATUS_UMBCAST_S = 9, /* 2 BITS */
VIRTCHNL_RX_BASE_DESC_STATUS_FLM_S = 11,
- VIRTCHNL_RX_BASE_DESC_STATUS_FLTSTAT_S = 12, /* 2 BITS */
+ VIRTCHNL_RX_BASE_DESC_STATUS_FLTSTAT_S = 12, /* 2 BITS */
VIRTCHNL_RX_BASE_DESC_STATUS_LPBK_S = 14,
VIRTCHNL_RX_BASE_DESC_STATUS_IPV6EXADD_S = 15,
- VIRTCHNL_RX_BASE_DESC_STATUS_RSVD1_S = 16, /* 2 BITS */
+ VIRTCHNL_RX_BASE_DESC_STATUS_RSVD1_S = 16, /* 2 BITS */
VIRTCHNL_RX_BASE_DESC_STATUS_INT_UDP_0_S = 18,
VIRTCHNL_RX_BASE_DESC_STATUS_LAST /* this entry must be last!!! */
};
-enum virtchnl_rx_desc_fltstat_values {
- VIRTCHNL_RX_DESC_FLTSTAT_NO_DATA = 0,
- VIRTCHNL_RX_DESC_FLTSTAT_RSV_FD_ID = 1, /* 16byte desc? FD_ID : RSV */
- VIRTCHNL_RX_DESC_FLTSTAT_RSV = 2,
- VIRTCHNL_RX_DESC_FLTSTAT_RSS_HASH = 3,
+enum virtchnl_rx_base_desc_ext_status_bits {
+ /* Note: These are predefined bit offsets */
+ VIRTCHNL_RX_BASE_DESC_EXT_STATUS_L2TAG2P_S = 0
};
enum virtchnl_rx_base_desc_error_bits {
/* Note: These are predefined bit offsets */
VIRTCHNL_RX_BASE_DESC_ERROR_RXE_S = 0,
- VIRTCHNL_RX_BASE_DESC_ERROR_ATRAEFAIL_S = 1,
+ VIRTCHNL_RX_BASE_DESC_ERROR_ATRAEFAIL_S = 1,
VIRTCHNL_RX_BASE_DESC_ERROR_HBO_S = 2,
VIRTCHNL_RX_BASE_DESC_ERROR_L3L4E_S = 3, /* 3 BITS */
VIRTCHNL_RX_BASE_DESC_ERROR_IPE_S = 3,
VIRTCHNL_RX_BASE_DESC_ERROR_L4E_S = 4,
VIRTCHNL_RX_BASE_DESC_ERROR_EIPE_S = 5,
- VIRTCHNL_RX_BASE_DESC_ERROR_OVERSIZE_S = 6,
- VIRTCHNL_RX_BASE_DESC_ERROR_RSVD_S = 7
+ VIRTCHNL_RX_BASE_DESC_ERROR_OVERSIZE_S = 6,
+ VIRTCHNL_RX_BASE_DESC_ERROR_PPRS_S = 7
+};
+
+enum virtchnl_rx_base_desc_fltstat_values {
+ VIRTCHNL_RX_BASE_DESC_FLTSTAT_NO_DATA = 0,
+ VIRTCHNL_RX_BASE_DESC_FLTSTAT_FD_ID = 1,
+ VIRTCHNL_RX_BASE_DESC_FLTSTAT_RSV = 2,
+ VIRTCHNL_RX_BASE_DESC_FLTSTAT_RSS_HASH = 3,
};
/* Receive Descriptors */
@@ -277,7 +339,7 @@ struct virtchnl_rx_flex_desc_nic {
/* Qword 0 */
u8 rxdid;
u8 mir_id_umb_cast;
- __le16 ptype_flexi_flags0;
+ __le16 ptype_flex_flags0;
__le16 pkt_len;
__le16 hdr_len_sph_flex_flags1;
@@ -312,7 +374,7 @@ struct virtchnl_rx_flex_desc_sw {
/* Qword 0 */
u8 rxdid;
u8 mir_id_umb_cast;
- __le16 ptype_flexi_flags0;
+ __le16 ptype_flex_flags0;
__le16 pkt_len;
__le16 hdr_len_sph_flex_flags1;
@@ -334,71 +396,6 @@ struct virtchnl_rx_flex_desc_sw {
__le32 ts_high;
};
-/* Rx Flex Descriptor NIC VEB Profile
- * RxDID Profile Id 4
- * Flex-field 0: Destination Vsi
- */
-struct virtchnl_rx_flex_desc_nic_veb_dbg {
- /* Qword 0 */
- u8 rxdid;
- u8 mir_id_umb_cast;
- __le16 ptype_flexi_flags0;
- __le16 pkt_len;
- __le16 hdr_len_sph_flex_flags1;
-
- /* Qword 1 */
- __le16 status_error0;
- __le16 l2tag1;
- __le16 dst_vsi; /* [0:12]: destination vsi */
- /* 13: vsi valid bit */
- /* [14:15] are reserved */
- __le16 flex_field_1;
-
- /* Qword 2 */
- __le16 status_error1;
- u8 flex_flags2;
- u8 ts_low;
- __le16 l2tag2_1st;
- __le16 l2tag2_2nd;
-
- /* Qword 3 */
- __le32 rsvd; /* flex words 2-3 are reserved */
- __le32 ts_high;
-};
-
-/* Rx Flex Descriptor NIC ACL Profile
- * RxDID Profile Id 5
- * Flex-field 0: ACL Counter 0
- * Flex-field 1: ACL Counter 1
- * Flex-field 2: ACL Counter 2
- */
-struct virtchnl_rx_flex_desc_nic_acl_dbg {
- /* Qword 0 */
- u8 rxdid;
- u8 mir_id_umb_cast;
- __le16 ptype_flexi_flags0;
- __le16 pkt_len;
- __le16 hdr_len_sph_flex_flags1;
-
- /* Qword 1 */
- __le16 status_error0;
- __le16 l2tag1;
- __le16 acl_ctr0;
- __le16 acl_ctr1;
-
- /* Qword 2 */
- __le16 status_error1;
- u8 flex_flags2;
- u8 ts_low;
- __le16 l2tag2_1st;
- __le16 l2tag2_2nd;
-
- /* Qword 3 */
- __le16 acl_ctr2;
- __le16 rsvd; /* flex words 2-3 are reserved */
- __le32 ts_high;
-};
-
/* Rx Flex Descriptor NIC Profile
* RxDID Profile Id 6
* Flex-field 0: RSS hash lower 16-bits
@@ -411,7 +408,7 @@ struct virtchnl_rx_flex_desc_nic_2 {
/* Qword 0 */
u8 rxdid;
u8 mir_id_umb_cast;
- __le16 ptype_flexi_flags0;
+ __le16 ptype_flex_flags0;
__le16 pkt_len;
__le16 hdr_len_sph_flex_flags1;
@@ -540,10 +537,14 @@ struct virtchnl_rx_flex_desc_adv_nic_3 {
}; /* writeback */
union virtchnl_rx_desc {
- struct virtchnl_singleq_rx_buf_desc read;
- struct virtchnl_singleq_base_rx_desc base_wb;
- struct virtchnl_rx_flex_desc flex_wb;
- struct virtchnl_rx_flex_desc_adv flex_wb_adv;
+ struct virtchnl_singleq_rx_buf_desc read;
+ struct virtchnl_singleq_base_rx_desc base_wb;
+ struct virtchnl_rx_flex_desc flex_wb;
+ struct virtchnl_rx_flex_desc_nic flex_nic_wb;
+ struct virtchnl_rx_flex_desc_sw flex_sw_wb;
+ struct virtchnl_rx_flex_desc_nic_2 flex_nic_2_wb;
+ struct virtchnl_rx_flex_desc_adv flex_adv_wb;
+ struct virtchnl_rx_flex_desc_adv_nic_3 flex_adv_nic_3_wb;
};
#endif /* _VIRTCHNL_LAN_DESC_H_ */
diff --git a/sys/modules/ice/Makefile b/sys/modules/ice/Makefile
index 1add23486668..fb307fa7dba2 100644
--- a/sys/modules/ice/Makefile
+++ b/sys/modules/ice/Makefile
@@ -7,9 +7,10 @@ SRCS = device_if.h bus_if.h pci_if.h ifdi_if.h
SRCS += opt_inet.h opt_inet6.h opt_rss.h opt_iflib.h
SRCS += ice_lib.c ice_osdep.c ice_resmgr.c ice_strings.c
SRCS += ice_iflib_recovery_txrx.c ice_iflib_txrx.c if_ice_iflib.c
+SRCS += ice_fw_logging.c
# Shared source
SRCS += ice_common.c ice_controlq.c ice_dcb.c ice_flex_pipe.c ice_flow.c
-SRCS += ice_nvm.c ice_sched.c ice_sriov.c ice_switch.c ice_vlan_mode.c
+SRCS += ice_nvm.c ice_sched.c ice_switch.c ice_vlan_mode.c ice_fwlog.c
.include <bsd.kmod.mk>