From 0290abc9860917f1ee8b58309c2bbd740a39ee8e Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Sun, 17 Nov 2024 22:20:29 +0100 Subject: [PATCH 01/16] wireguard: selftests: load nf_conntrack if not present Some distros may not load nf_conntrack by default, which will cause subsequent nf_conntrack sets to fail. Load this module if it is not already loaded. Fixes: e7096c131e51 ("net: WireGuard secure network tunnel") Signed-off-by: Hangbin Liu Reviewed-by: Simon Horman [ Jason: add [[ -e ... ]] check so this works in the qemu harness. ] Signed-off-by: Jason A. Donenfeld Link: https://patch.msgid.link/20241117212030.629159-4-Jason@zx2c4.com Signed-off-by: Jakub Kicinski --- tools/testing/selftests/wireguard/netns.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/testing/selftests/wireguard/netns.sh b/tools/testing/selftests/wireguard/netns.sh index 405ff262ca93..55500f901fbc 100755 --- a/tools/testing/selftests/wireguard/netns.sh +++ b/tools/testing/selftests/wireguard/netns.sh @@ -332,6 +332,7 @@ waitiface $netns1 vethc waitiface $netns2 veths n0 bash -c 'printf 1 > /proc/sys/net/ipv4/ip_forward' +[[ -e /proc/sys/net/netfilter/nf_conntrack_udp_timeout ]] || modprobe nf_conntrack n0 bash -c 'printf 2 > /proc/sys/net/netfilter/nf_conntrack_udp_timeout' n0 bash -c 'printf 2 > /proc/sys/net/netfilter/nf_conntrack_udp_timeout_stream' n0 iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -d 10.0.0.0/24 -j SNAT --to 10.0.0.1 -- 2.51.0 From 06a34f7db773e01efa8a90c5b4d912207a80dd60 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Sun, 17 Nov 2024 22:20:30 +0100 Subject: [PATCH 02/16] wireguard: device: support big tcp GSO Advertise GSO_MAX_SIZE as TSO max size in order support BIG TCP for wireguard. This helps to improve wireguard performance a bit when enabled as it allows wireguard to aggregate larger skbs in wg_packet_consume_data_done() via napi_gro_receive(), but also allows the stack to build larger skbs on xmit where the driver then segments them before encryption inside wg_xmit(). We've seen a 15% improvement in TCP stream performance. Signed-off-by: Daniel Borkmann Signed-off-by: Jason A. Donenfeld Link: https://patch.msgid.link/20241117212030.629159-5-Jason@zx2c4.com Signed-off-by: Jakub Kicinski --- drivers/net/wireguard/device.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c index a2ba71fbbed4..6cf173a008e7 100644 --- a/drivers/net/wireguard/device.c +++ b/drivers/net/wireguard/device.c @@ -302,6 +302,8 @@ static void wg_setup(struct net_device *dev) /* We need to keep the dst around in case of icmp replies. */ netif_keep_dst(dev); + netif_set_tso_max_size(dev, GSO_MAX_SIZE); + wg->dev = dev; } -- 2.51.0 From ff00bcc9ecccf4a1ce3a06eb38a9b4592f870f80 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 15 Nov 2024 07:14:27 -0800 Subject: [PATCH 03/16] bnxt_en: Update firmware interface spec to 1.10.3.85 The major change is the new firmware command to flush the FW debug logs to the host backing store context memory buffers. Reviewed-by: Hongguang Gao Reviewed-by: Kalesh AP Signed-off-by: Michael Chan Link: https://patch.msgid.link/20241115151438.550106-2-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h | 173 ++++++++++++++---- 1 file changed, 136 insertions(+), 37 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h index f8ef6f1a1964..5f8de1634378 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h @@ -42,6 +42,10 @@ struct hwrm_resp_hdr { #define TLV_TYPE_MODIFY_ROCE_CC_GEN1 0x5UL #define TLV_TYPE_QUERY_ROCE_CC_GEN2 0x6UL #define TLV_TYPE_MODIFY_ROCE_CC_GEN2 0x7UL +#define TLV_TYPE_QUERY_ROCE_CC_GEN1_EXT 0x8UL +#define TLV_TYPE_MODIFY_ROCE_CC_GEN1_EXT 0x9UL +#define TLV_TYPE_QUERY_ROCE_CC_GEN2_EXT 0xaUL +#define TLV_TYPE_MODIFY_ROCE_CC_GEN2_EXT 0xbUL #define TLV_TYPE_ENGINE_CKV_ALIAS_ECC_PUBLIC_KEY 0x8001UL #define TLV_TYPE_ENGINE_CKV_IV 0x8003UL #define TLV_TYPE_ENGINE_CKV_AUTH_TAG 0x8004UL @@ -509,6 +513,7 @@ struct cmd_nums { #define HWRM_TFC_IF_TBL_GET 0x399UL #define HWRM_TFC_TBL_SCOPE_CONFIG_GET 0x39aUL #define HWRM_TFC_RESC_USAGE_QUERY 0x39bUL + #define HWRM_TFC_GLOBAL_ID_FREE 0x39cUL #define HWRM_SV 0x400UL #define HWRM_DBG_SERDES_TEST 0xff0eUL #define HWRM_DBG_LOG_BUFFER_FLUSH 0xff0fUL @@ -624,8 +629,8 @@ struct hwrm_err_output { #define HWRM_VERSION_MAJOR 1 #define HWRM_VERSION_MINOR 10 #define HWRM_VERSION_UPDATE 3 -#define HWRM_VERSION_RSVD 68 -#define HWRM_VERSION_STR "1.10.3.68" +#define HWRM_VERSION_RSVD 85 +#define HWRM_VERSION_STR "1.10.3.85" /* hwrm_ver_get_input (size:192b/24B) */ struct hwrm_ver_get_input { @@ -1302,6 +1307,43 @@ struct hwrm_async_event_cmpl_error_report { #define ASYNC_EVENT_CMPL_ERROR_REPORT_EVENT_DATA1_ERROR_TYPE_SFT 0 }; +/* hwrm_async_event_cmpl_dbg_buf_producer (size:128b/16B) */ +struct hwrm_async_event_cmpl_dbg_buf_producer { + __le16 type; + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_TYPE_MASK 0x3fUL + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_TYPE_SFT 0 + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_TYPE_HWRM_ASYNC_EVENT 0x2eUL + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_TYPE_LAST ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_TYPE_HWRM_ASYNC_EVENT + __le16 event_id; + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_ID_DBG_BUF_PRODUCER 0x4cUL + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_ID_LAST ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_ID_DBG_BUF_PRODUCER + __le32 event_data2; + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA2_CURR_OFF_MASK 0xffffffffUL + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA2_CURR_OFF_SFT 0 + u8 opaque_v; + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_V 0x1UL + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_OPAQUE_MASK 0xfeUL + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_OPAQUE_SFT 1 + u8 timestamp_lo; + __le16 timestamp_hi; + __le32 event_data1; + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_MASK 0xffffUL + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_SFT 0 + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_SRT_TRACE 0x0UL + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_SRT2_TRACE 0x1UL + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_CRT_TRACE 0x2UL + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_CRT2_TRACE 0x3UL + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_RIGP0_TRACE 0x4UL + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_L2_HWRM_TRACE 0x5UL + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_ROCE_HWRM_TRACE 0x6UL + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_CA0_TRACE 0x7UL + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_CA1_TRACE 0x8UL + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_CA2_TRACE 0x9UL + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_RIGP1_TRACE 0xaUL + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_AFM_KONG_HWRM_TRACE 0xbUL + #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_LAST ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_AFM_KONG_HWRM_TRACE +}; + /* hwrm_async_event_cmpl_hwrm_error (size:128b/16B) */ struct hwrm_async_event_cmpl_hwrm_error { __le16 type; @@ -1864,7 +1906,10 @@ struct hwrm_func_qcaps_output { __le32 roce_vf_max_gid; __le32 flags_ext3; #define FUNC_QCAPS_RESP_FLAGS_EXT3_RM_RSV_WHILE_ALLOC_CAP 0x1UL - u8 unused_3[7]; + #define FUNC_QCAPS_RESP_FLAGS_EXT3_REQUIRE_L2_FILTER 0x2UL + #define FUNC_QCAPS_RESP_FLAGS_EXT3_MAX_ROCE_VFS_SUPPORTED 0x4UL + __le16 max_roce_vfs; + u8 unused_3[5]; u8 valid; }; @@ -2253,17 +2298,18 @@ struct hwrm_func_cfg_input { #define FUNC_CFG_REQ_FLAGS2_KTLS_KEY_CTX_ASSETS_TEST 0x1UL #define FUNC_CFG_REQ_FLAGS2_QUIC_KEY_CTX_ASSETS_TEST 0x2UL __le32 enables2; - #define FUNC_CFG_REQ_ENABLES2_KDNET 0x1UL - #define FUNC_CFG_REQ_ENABLES2_DB_PAGE_SIZE 0x2UL - #define FUNC_CFG_REQ_ENABLES2_QUIC_TX_KEY_CTXS 0x4UL - #define FUNC_CFG_REQ_ENABLES2_QUIC_RX_KEY_CTXS 0x8UL - #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_AV_PER_VF 0x10UL - #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_CQ_PER_VF 0x20UL - #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_MRW_PER_VF 0x40UL - #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_QP_PER_VF 0x80UL - #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_SRQ_PER_VF 0x100UL - #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_GID_PER_VF 0x200UL - #define FUNC_CFG_REQ_ENABLES2_XID_PARTITION_CFG 0x400UL + #define FUNC_CFG_REQ_ENABLES2_KDNET 0x1UL + #define FUNC_CFG_REQ_ENABLES2_DB_PAGE_SIZE 0x2UL + #define FUNC_CFG_REQ_ENABLES2_QUIC_TX_KEY_CTXS 0x4UL + #define FUNC_CFG_REQ_ENABLES2_QUIC_RX_KEY_CTXS 0x8UL + #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_AV_PER_VF 0x10UL + #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_CQ_PER_VF 0x20UL + #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_MRW_PER_VF 0x40UL + #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_QP_PER_VF 0x80UL + #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_SRQ_PER_VF 0x100UL + #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_GID_PER_VF 0x200UL + #define FUNC_CFG_REQ_ENABLES2_XID_PARTITION_CFG 0x400UL + #define FUNC_CFG_REQ_ENABLES2_PHYSICAL_SLOT_NUMBER 0x800UL u8 port_kdnet_mode; #define FUNC_CFG_REQ_PORT_KDNET_MODE_DISABLED 0x0UL #define FUNC_CFG_REQ_PORT_KDNET_MODE_ENABLED 0x1UL @@ -2281,7 +2327,7 @@ struct hwrm_func_cfg_input { #define FUNC_CFG_REQ_DB_PAGE_SIZE_2MB 0x9UL #define FUNC_CFG_REQ_DB_PAGE_SIZE_4MB 0xaUL #define FUNC_CFG_REQ_DB_PAGE_SIZE_LAST FUNC_CFG_REQ_DB_PAGE_SIZE_4MB - u8 unused_1[2]; + __le16 physical_slot_number; __le32 num_ktls_tx_key_ctxs; __le32 num_ktls_rx_key_ctxs; __le32 num_quic_tx_key_ctxs; @@ -3683,7 +3729,7 @@ struct hwrm_func_ptp_ext_qcfg_output { u8 valid; }; -/* hwrm_func_backing_store_cfg_v2_input (size:448b/56B) */ +/* hwrm_func_backing_store_cfg_v2_input (size:512b/64B) */ struct hwrm_func_backing_store_cfg_v2_input { __le16 req_type; __le16 cmpl_ring; @@ -3721,6 +3767,7 @@ struct hwrm_func_backing_store_cfg_v2_input { #define FUNC_BACKING_STORE_CFG_V2_REQ_TYPE_CA1_TRACE 0x27UL #define FUNC_BACKING_STORE_CFG_V2_REQ_TYPE_CA2_TRACE 0x28UL #define FUNC_BACKING_STORE_CFG_V2_REQ_TYPE_RIGP1_TRACE 0x29UL + #define FUNC_BACKING_STORE_CFG_V2_REQ_TYPE_AFM_KONG_HWRM_TRACE 0x2aUL #define FUNC_BACKING_STORE_CFG_V2_REQ_TYPE_INVALID 0xffffUL #define FUNC_BACKING_STORE_CFG_V2_REQ_TYPE_LAST FUNC_BACKING_STORE_CFG_V2_REQ_TYPE_INVALID __le16 instance; @@ -3752,6 +3799,9 @@ struct hwrm_func_backing_store_cfg_v2_input { __le32 split_entry_1; __le32 split_entry_2; __le32 split_entry_3; + __le32 enables; + #define FUNC_BACKING_STORE_CFG_V2_REQ_ENABLES_NEXT_BS_OFFSET 0x1UL + __le32 next_bs_offset; }; /* hwrm_func_backing_store_cfg_v2_output (size:128b/16B) */ @@ -3802,6 +3852,7 @@ struct hwrm_func_backing_store_qcfg_v2_input { #define FUNC_BACKING_STORE_QCFG_V2_REQ_TYPE_CA1_TRACE 0x27UL #define FUNC_BACKING_STORE_QCFG_V2_REQ_TYPE_CA2_TRACE 0x28UL #define FUNC_BACKING_STORE_QCFG_V2_REQ_TYPE_RIGP1_TRACE 0x29UL + #define FUNC_BACKING_STORE_QCFG_V2_REQ_TYPE_AFM_KONG_HWRM_TRACE 0x2aUL #define FUNC_BACKING_STORE_QCFG_V2_REQ_TYPE_INVALID 0xffffUL #define FUNC_BACKING_STORE_QCFG_V2_REQ_TYPE_LAST FUNC_BACKING_STORE_QCFG_V2_REQ_TYPE_INVALID __le16 instance; @@ -3963,6 +4014,7 @@ struct hwrm_func_backing_store_qcaps_v2_input { #define FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CA1_TRACE 0x27UL #define FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CA2_TRACE 0x28UL #define FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_RIGP1_TRACE 0x29UL + #define FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_AFM_KONG_HWRM_TRACE 0x2aUL #define FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_INVALID 0xffffUL #define FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_LAST FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_INVALID u8 rsvd[6]; @@ -4005,6 +4057,7 @@ struct hwrm_func_backing_store_qcaps_v2_output { #define FUNC_BACKING_STORE_QCAPS_V2_RESP_TYPE_CA1_TRACE 0x27UL #define FUNC_BACKING_STORE_QCAPS_V2_RESP_TYPE_CA2_TRACE 0x28UL #define FUNC_BACKING_STORE_QCAPS_V2_RESP_TYPE_RIGP1_TRACE 0x29UL + #define FUNC_BACKING_STORE_QCAPS_V2_RESP_TYPE_AFM_KONG_HWRM_TRACE 0x2aUL #define FUNC_BACKING_STORE_QCAPS_V2_RESP_TYPE_INVALID 0xffffUL #define FUNC_BACKING_STORE_QCAPS_V2_RESP_TYPE_LAST FUNC_BACKING_STORE_QCAPS_V2_RESP_TYPE_INVALID __le16 entry_size; @@ -4014,6 +4067,8 @@ struct hwrm_func_backing_store_qcaps_v2_output { #define FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_DRIVER_MANAGED_MEMORY 0x4UL #define FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_ROCE_QP_PSEUDO_STATIC_ALLOC 0x8UL #define FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_FW_DBG_TRACE 0x10UL + #define FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_FW_BIN_DBG_TRACE 0x20UL + #define FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_NEXT_BS_OFFSET 0x40UL __le32 instance_bit_map; u8 ctx_init_value; u8 ctx_init_offset; @@ -4034,7 +4089,8 @@ struct hwrm_func_backing_store_qcaps_v2_output { __le32 split_entry_1; __le32 split_entry_2; __le32 split_entry_3; - u8 rsvd3[3]; + __le16 max_instance_count; + u8 rsvd3; u8 valid; }; @@ -4535,11 +4591,12 @@ struct hwrm_port_phy_qcfg_output { #define PORT_PHY_QCFG_RESP_PHY_TYPE_800G_BASEDR8 0x3dUL #define PORT_PHY_QCFG_RESP_PHY_TYPE_LAST PORT_PHY_QCFG_RESP_PHY_TYPE_800G_BASEDR8 u8 media_type; - #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_UNKNOWN 0x0UL - #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP 0x1UL - #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC 0x2UL - #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_FIBRE 0x3UL - #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_LAST PORT_PHY_QCFG_RESP_MEDIA_TYPE_FIBRE + #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_UNKNOWN 0x0UL + #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP 0x1UL + #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC 0x2UL + #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_FIBRE 0x3UL + #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_BACKPLANE 0x4UL + #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_LAST PORT_PHY_QCFG_RESP_MEDIA_TYPE_BACKPLANE u8 xcvr_pkg_type; #define PORT_PHY_QCFG_RESP_XCVR_PKG_TYPE_XCVR_INTERNAL 0x1UL #define PORT_PHY_QCFG_RESP_XCVR_PKG_TYPE_XCVR_EXTERNAL 0x2UL @@ -4654,7 +4711,8 @@ struct hwrm_port_phy_qcfg_output { #define PORT_PHY_QCFG_RESP_LINK_PARTNER_PAM4_ADV_SPEEDS_100GB 0x2UL #define PORT_PHY_QCFG_RESP_LINK_PARTNER_PAM4_ADV_SPEEDS_200GB 0x4UL u8 link_down_reason; - #define PORT_PHY_QCFG_RESP_LINK_DOWN_REASON_RF 0x1UL + #define PORT_PHY_QCFG_RESP_LINK_DOWN_REASON_RF 0x1UL + #define PORT_PHY_QCFG_RESP_LINK_DOWN_REASON_OTP_SPEED_VIOLATION 0x2UL __le16 support_speeds2; #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_1GB 0x1UL #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_10GB 0x2UL @@ -9241,20 +9299,22 @@ struct hwrm_fw_set_time_output { /* hwrm_struct_hdr (size:128b/16B) */ struct hwrm_struct_hdr { __le16 struct_id; - #define STRUCT_HDR_STRUCT_ID_LLDP_CFG 0x41bUL - #define STRUCT_HDR_STRUCT_ID_DCBX_ETS 0x41dUL - #define STRUCT_HDR_STRUCT_ID_DCBX_PFC 0x41fUL - #define STRUCT_HDR_STRUCT_ID_DCBX_APP 0x421UL - #define STRUCT_HDR_STRUCT_ID_DCBX_FEATURE_STATE 0x422UL - #define STRUCT_HDR_STRUCT_ID_LLDP_GENERIC 0x424UL - #define STRUCT_HDR_STRUCT_ID_LLDP_DEVICE 0x426UL - #define STRUCT_HDR_STRUCT_ID_POWER_BKUP 0x427UL - #define STRUCT_HDR_STRUCT_ID_PEER_MMAP 0x429UL - #define STRUCT_HDR_STRUCT_ID_AFM_OPAQUE 0x1UL - #define STRUCT_HDR_STRUCT_ID_PORT_DESCRIPTION 0xaUL - #define STRUCT_HDR_STRUCT_ID_RSS_V2 0x64UL - #define STRUCT_HDR_STRUCT_ID_MSIX_PER_VF 0xc8UL - #define STRUCT_HDR_STRUCT_ID_LAST STRUCT_HDR_STRUCT_ID_MSIX_PER_VF + #define STRUCT_HDR_STRUCT_ID_LLDP_CFG 0x41bUL + #define STRUCT_HDR_STRUCT_ID_DCBX_ETS 0x41dUL + #define STRUCT_HDR_STRUCT_ID_DCBX_PFC 0x41fUL + #define STRUCT_HDR_STRUCT_ID_DCBX_APP 0x421UL + #define STRUCT_HDR_STRUCT_ID_DCBX_FEATURE_STATE 0x422UL + #define STRUCT_HDR_STRUCT_ID_LLDP_GENERIC 0x424UL + #define STRUCT_HDR_STRUCT_ID_LLDP_DEVICE 0x426UL + #define STRUCT_HDR_STRUCT_ID_POWER_BKUP 0x427UL + #define STRUCT_HDR_STRUCT_ID_PEER_MMAP 0x429UL + #define STRUCT_HDR_STRUCT_ID_AFM_OPAQUE 0x1UL + #define STRUCT_HDR_STRUCT_ID_PORT_DESCRIPTION 0xaUL + #define STRUCT_HDR_STRUCT_ID_RSS_V2 0x64UL + #define STRUCT_HDR_STRUCT_ID_MSIX_PER_VF 0xc8UL + #define STRUCT_HDR_STRUCT_ID_UDCC_RTT_BUCKET_COUNT 0x12cUL + #define STRUCT_HDR_STRUCT_ID_UDCC_RTT_BUCKET_BOUND 0x12dUL + #define STRUCT_HDR_STRUCT_ID_LAST STRUCT_HDR_STRUCT_ID_UDCC_RTT_BUCKET_BOUND __le16 len; u8 version; u8 count; @@ -9756,6 +9816,7 @@ struct hwrm_dbg_qcaps_output { #define DBG_QCAPS_RESP_FLAGS_COREDUMP_HOST_DDR 0x10UL #define DBG_QCAPS_RESP_FLAGS_COREDUMP_HOST_CAPTURE 0x20UL #define DBG_QCAPS_RESP_FLAGS_PTRACE 0x40UL + #define DBG_QCAPS_RESP_FLAGS_REG_ACCESS_RESTRICTED 0x80UL u8 unused_1[3]; u8 valid; }; @@ -9996,6 +10057,43 @@ struct hwrm_dbg_ring_info_get_output { u8 valid; }; +/* hwrm_dbg_log_buffer_flush_input (size:192b/24B) */ +struct hwrm_dbg_log_buffer_flush_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 type; + #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_SRT_TRACE 0x0UL + #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_SRT2_TRACE 0x1UL + #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CRT_TRACE 0x2UL + #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CRT2_TRACE 0x3UL + #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_RIGP0_TRACE 0x4UL + #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_L2_HWRM_TRACE 0x5UL + #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_ROCE_HWRM_TRACE 0x6UL + #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CA0_TRACE 0x7UL + #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CA1_TRACE 0x8UL + #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CA2_TRACE 0x9UL + #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_RIGP1_TRACE 0xaUL + #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_AFM_KONG_HWRM_TRACE 0xbUL + #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_LAST DBG_LOG_BUFFER_FLUSH_REQ_TYPE_AFM_KONG_HWRM_TRACE + u8 unused_1[2]; + __le32 flags; + #define DBG_LOG_BUFFER_FLUSH_REQ_FLAGS_FLUSH_ALL_BUFFERS 0x1UL +}; + +/* hwrm_dbg_log_buffer_flush_output (size:128b/16B) */ +struct hwrm_dbg_log_buffer_flush_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 current_buffer_offset; + u8 unused_1[3]; + u8 valid; +}; + /* hwrm_nvm_read_input (size:320b/40B) */ struct hwrm_nvm_read_input { __le16 req_type; @@ -10080,6 +10178,7 @@ struct hwrm_nvm_write_input { #define NVM_WRITE_REQ_FLAGS_KEEP_ORIG_ACTIVE_IMG 0x1UL #define NVM_WRITE_REQ_FLAGS_BATCH_MODE 0x2UL #define NVM_WRITE_REQ_FLAGS_BATCH_LAST 0x4UL + #define NVM_WRITE_REQ_FLAGS_SKIP_CRID_CHECK 0x8UL __le32 dir_item_length; __le32 offset; __le32 len; -- 2.51.0 From 0b350b4927e69d66629099dbb32cad8d2d56a26d Mon Sep 17 00:00:00 2001 From: Shruti Parab Date: Fri, 15 Nov 2024 07:14:28 -0800 Subject: [PATCH 04/16] bnxt_en: Add mem_valid bit to struct bnxt_ctx_mem_type Add a new bit to struct bnxt_ctx_mem_type to indicate that host memory has been successfully allocated for this context memory type. In the next patches, we'll be adding some additional context memory types for FW debugging/logging. If memory cannot be allocated for any of these new types, we will not abort and the cleared mem_valid bit will indicate to skip configuring the memory type. Reviewed-by: Hongguang Gao Signed-off-by: Shruti Parab Signed-of-by: Michael Chan Link: https://patch.msgid.link/20241115151438.550106-3-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 5 +++++ drivers/net/ethernet/broadcom/bnxt/bnxt.h | 1 + 2 files changed, 6 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 4c1302a8f72d..0143d976c5fe 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -8684,6 +8684,8 @@ static int bnxt_setup_ctxm_pg_tbls(struct bnxt *bp, rc = bnxt_alloc_ctx_pg_tbls(bp, &ctx_pg[i], mem_size, pg_lvl, ctxm->init_value ? ctxm : NULL); } + if (!rc) + ctxm->mem_valid = 1; return rc; } @@ -8754,6 +8756,8 @@ static int bnxt_backing_store_cfg_v2(struct bnxt *bp, u32 ena) for (type = 0 ; type < BNXT_CTX_V2_MAX; type++) { ctxm = &ctx->ctx_arr[type]; + if (!ctxm->mem_valid) + continue; rc = bnxt_hwrm_func_backing_store_cfg_v2(bp, ctxm, ctxm->last); if (rc) return rc; @@ -8783,6 +8787,7 @@ void bnxt_free_ctx_mem(struct bnxt *bp) kfree(ctx_pg); ctxm->pg_info = NULL; + ctxm->mem_valid = 0; } ctx->flags &= ~BNXT_CTX_FLAG_INITED; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 649955fa3e37..d1fa58d83897 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -1889,6 +1889,7 @@ struct bnxt_ctx_mem_type { u32 max_entries; u32 min_entries; u8 last:1; + u8 mem_valid:1; u8 split_entry_cnt; #define BNXT_MAX_SPLIT_ENTRY 4 union { -- 2.51.0 From 968d2cc07c2fc9a508a53bd2de61200f50206fbc Mon Sep 17 00:00:00 2001 From: Hongguang Gao Date: Fri, 15 Nov 2024 07:14:29 -0800 Subject: [PATCH 05/16] bnxt_en: Refactor bnxt_free_ctx_mem() Add a new function bnxt_free_one_ctx_mem() to free one context memory type. bnxt_free_ctx_mem() now calls the new function in the loop to free each context memory type. There is no change in behavior. Later patches will further make use of the new function. Signed-off-by: Hongguang Gao Signed-off-by: Michael Chan Link: https://patch.msgid.link/20241115151438.550106-4-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 31 +++++++++++++---------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 0143d976c5fe..8c79b88c92b0 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -8765,21 +8765,14 @@ static int bnxt_backing_store_cfg_v2(struct bnxt *bp, u32 ena) return 0; } -void bnxt_free_ctx_mem(struct bnxt *bp) +static void bnxt_free_one_ctx_mem(struct bnxt *bp, + struct bnxt_ctx_mem_type *ctxm) { - struct bnxt_ctx_mem_info *ctx = bp->ctx; - u16 type; - - if (!ctx) - return; - - for (type = 0; type < BNXT_CTX_V2_MAX; type++) { - struct bnxt_ctx_mem_type *ctxm = &ctx->ctx_arr[type]; - struct bnxt_ctx_pg_info *ctx_pg = ctxm->pg_info; - int i, n = 1; + struct bnxt_ctx_pg_info *ctx_pg; + int i, n = 1; - if (!ctx_pg) - continue; + ctx_pg = ctxm->pg_info; + if (ctx_pg) { if (ctxm->instance_bmap) n = hweight32(ctxm->instance_bmap); for (i = 0; i < n; i++) @@ -8789,6 +8782,18 @@ void bnxt_free_ctx_mem(struct bnxt *bp) ctxm->pg_info = NULL; ctxm->mem_valid = 0; } +} + +void bnxt_free_ctx_mem(struct bnxt *bp) +{ + struct bnxt_ctx_mem_info *ctx = bp->ctx; + u16 type; + + if (!ctx) + return; + + for (type = 0; type < BNXT_CTX_V2_MAX; type++) + bnxt_free_one_ctx_mem(bp, &ctx->ctx_arr[type]); ctx->flags &= ~BNXT_CTX_FLAG_INITED; kfree(ctx); -- 2.51.0 From 46010d43ab7b18fbc8a3a0bf4d65c775f8d2adbd Mon Sep 17 00:00:00 2001 From: Hongguang Gao Date: Fri, 15 Nov 2024 07:14:30 -0800 Subject: [PATCH 06/16] bnxt_en: Add a 'force' parameter to bnxt_free_ctx_mem() If 'force' is false, it will keep the memory pages and all data structures for the context memory type if the memory is valid. This patch always passes true for the 'force' parameter so there is no change in behavior. Later patches will adjust the 'force' parameter for the FW log context memory types so that the logs will not be reset after FW reset. Signed-off-by: Hongguang Gao Signed-off-by: Michael Chan Link: https://patch.msgid.link/20241115151438.550106-5-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 44 ++++++++++++------- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 2 +- .../net/ethernet/broadcom/bnxt/bnxt_devlink.c | 2 +- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 8c79b88c92b0..02a8d568857b 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -8233,7 +8233,7 @@ static int bnxt_hwrm_func_backing_store_qcaps_v2(struct bnxt *bp) { struct hwrm_func_backing_store_qcaps_v2_output *resp; struct hwrm_func_backing_store_qcaps_v2_input *req; - struct bnxt_ctx_mem_info *ctx; + struct bnxt_ctx_mem_info *ctx = bp->ctx; u16 type; int rc; @@ -8241,10 +8241,12 @@ static int bnxt_hwrm_func_backing_store_qcaps_v2(struct bnxt *bp) if (rc) return rc; - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - bp->ctx = ctx; + if (!ctx) { + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + bp->ctx = ctx; + } resp = hwrm_req_hold(bp, req); @@ -8293,7 +8295,8 @@ static int bnxt_hwrm_func_backing_store_qcaps(struct bnxt *bp) struct hwrm_func_backing_store_qcaps_input *req; int rc; - if (bp->hwrm_spec_code < 0x10902 || BNXT_VF(bp) || bp->ctx) + if (bp->hwrm_spec_code < 0x10902 || BNXT_VF(bp) || + (bp->ctx && bp->ctx->flags & BNXT_CTX_FLAG_INITED)) return 0; if (bp->fw_cap & BNXT_FW_CAP_BACKING_STORE_V2) @@ -8766,11 +8769,16 @@ static int bnxt_backing_store_cfg_v2(struct bnxt *bp, u32 ena) } static void bnxt_free_one_ctx_mem(struct bnxt *bp, - struct bnxt_ctx_mem_type *ctxm) + struct bnxt_ctx_mem_type *ctxm, bool force) { struct bnxt_ctx_pg_info *ctx_pg; int i, n = 1; + ctxm->last = 0; + + if (ctxm->mem_valid && !force) + return; + ctx_pg = ctxm->pg_info; if (ctx_pg) { if (ctxm->instance_bmap) @@ -8784,7 +8792,7 @@ static void bnxt_free_one_ctx_mem(struct bnxt *bp, } } -void bnxt_free_ctx_mem(struct bnxt *bp) +void bnxt_free_ctx_mem(struct bnxt *bp, bool force) { struct bnxt_ctx_mem_info *ctx = bp->ctx; u16 type; @@ -8793,11 +8801,13 @@ void bnxt_free_ctx_mem(struct bnxt *bp) return; for (type = 0; type < BNXT_CTX_V2_MAX; type++) - bnxt_free_one_ctx_mem(bp, &ctx->ctx_arr[type]); + bnxt_free_one_ctx_mem(bp, &ctx->ctx_arr[type], force); ctx->flags &= ~BNXT_CTX_FLAG_INITED; - kfree(ctx); - bp->ctx = NULL; + if (force) { + kfree(ctx); + bp->ctx = NULL; + } } static int bnxt_alloc_ctx_mem(struct bnxt *bp) @@ -11758,7 +11768,7 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up) set_bit(BNXT_STATE_FW_RESET_DET, &bp->state); if (!test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) bnxt_ulp_irq_stop(bp); - bnxt_free_ctx_mem(bp); + bnxt_free_ctx_mem(bp, true); bnxt_dcb_free(bp); rc = bnxt_fw_init_one(bp); if (rc) { @@ -13471,7 +13481,7 @@ static void bnxt_fw_reset_close(struct bnxt *bp) bnxt_hwrm_func_drv_unrgtr(bp); if (pci_is_enabled(bp->pdev)) pci_disable_device(bp->pdev); - bnxt_free_ctx_mem(bp); + bnxt_free_ctx_mem(bp, true); } static bool is_bnxt_fw_ok(struct bnxt *bp) @@ -15328,7 +15338,7 @@ static void bnxt_remove_one(struct pci_dev *pdev) kfree(bp->fw_health); bp->fw_health = NULL; bnxt_cleanup_pci(bp); - bnxt_free_ctx_mem(bp); + bnxt_free_ctx_mem(bp, true); bnxt_free_crash_dump_mem(bp); kfree(bp->rss_indir_tbl); bp->rss_indir_tbl = NULL; @@ -15970,7 +15980,7 @@ init_err_pci_clean: kfree(bp->fw_health); bp->fw_health = NULL; bnxt_cleanup_pci(bp); - bnxt_free_ctx_mem(bp); + bnxt_free_ctx_mem(bp, true); bnxt_free_crash_dump_mem(bp); kfree(bp->rss_indir_tbl); bp->rss_indir_tbl = NULL; @@ -16024,7 +16034,7 @@ static int bnxt_suspend(struct device *device) } bnxt_hwrm_func_drv_unrgtr(bp); pci_disable_device(bp->pdev); - bnxt_free_ctx_mem(bp); + bnxt_free_ctx_mem(bp, true); rtnl_unlock(); return rc; } @@ -16136,7 +16146,7 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev, if (pci_is_enabled(pdev)) pci_disable_device(pdev); - bnxt_free_ctx_mem(bp); + bnxt_free_ctx_mem(bp, true); rtnl_unlock(); /* Request a slot slot reset. */ diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index d1fa58d83897..a092ed3c2248 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -2824,7 +2824,7 @@ int bnxt_hwrm_vnic_alloc(struct bnxt *bp, struct bnxt_vnic_info *vnic, int __bnxt_hwrm_get_tx_rings(struct bnxt *bp, u16 fid, int *tx_rings); int bnxt_nq_rings_in_use(struct bnxt *bp); int bnxt_hwrm_set_coal(struct bnxt *); -void bnxt_free_ctx_mem(struct bnxt *bp); +void bnxt_free_ctx_mem(struct bnxt *bp, bool force); int bnxt_num_tx_to_cp(struct bnxt *bp, int tx); unsigned int bnxt_get_max_func_stat_ctxs(struct bnxt *bp); unsigned int bnxt_get_avail_stat_ctxs_for_en(struct bnxt *bp); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c index 4cb0fabf977e..901fd36757ed 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c @@ -463,7 +463,7 @@ static int bnxt_dl_reload_down(struct devlink *dl, bool netns_change, break; } bnxt_cancel_reservations(bp, false); - bnxt_free_ctx_mem(bp); + bnxt_free_ctx_mem(bp, true); break; } case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: { -- 2.51.0 From 24d694aec139e9e0a31c60993db79bd8ad575afe Mon Sep 17 00:00:00 2001 From: Shruti Parab Date: Fri, 15 Nov 2024 07:14:31 -0800 Subject: [PATCH 07/16] bnxt_en: Allocate backing store memory for FW trace logs Allocate the new FW trace log backing store context memory types if they are supported by the FW. FW debug logs are DMA'ed to the host backing store memory when the on-chip buffers are full. If host memory cannot be allocated for these memory types, the driver will not abort. Reviewed-by: Hongguang Gao Signed-off-by: Shruti Parab Signed-off-by: Michael Chan Link: https://patch.msgid.link/20241115151438.550106-6-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 43 ++++++++++++++++++----- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 27 +++++++++++--- 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 02a8d568857b..c7e7cb98f03b 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -2461,6 +2461,15 @@ static bool bnxt_auto_speed_updated(struct bnxt_link_info *link_info) return false; } +bool bnxt_bs_trace_avail(struct bnxt *bp, u16 type) +{ + u32 flags = bp->ctx->ctx_arr[type].flags; + + return (flags & BNXT_CTX_MEM_TYPE_VALID) && + ((flags & BNXT_CTX_MEM_FW_TRACE) || + (flags & BNXT_CTX_MEM_FW_BIN_TRACE)); +} + #define BNXT_EVENT_THERMAL_CURRENT_TEMP(data2) \ ((data2) & \ ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA2_CURRENT_TEMP_MASK) @@ -8744,16 +8753,34 @@ static int bnxt_backing_store_cfg_v2(struct bnxt *bp, u32 ena) { struct bnxt_ctx_mem_info *ctx = bp->ctx; struct bnxt_ctx_mem_type *ctxm; - u16 last_type; + u16 last_type = BNXT_CTX_INV; int rc = 0; u16 type; - if (!ena) - return 0; - else if (ena & FUNC_BACKING_STORE_CFG_REQ_ENABLES_TIM) - last_type = BNXT_CTX_MAX - 1; - else - last_type = BNXT_CTX_L2_MAX - 1; + for (type = BNXT_CTX_SRT; type <= BNXT_CTX_RIGP1; type++) { + ctxm = &ctx->ctx_arr[type]; + if (!bnxt_bs_trace_avail(bp, type)) + continue; + if (!ctxm->mem_valid) { + rc = bnxt_setup_ctxm_pg_tbls(bp, ctxm, + ctxm->max_entries, 1); + if (rc) { + netdev_warn(bp->dev, "Unable to setup ctx page for type:0x%x.\n", + type); + continue; + } + last_type = type; + } + } + + if (last_type == BNXT_CTX_INV) { + if (!ena) + return 0; + else if (ena & FUNC_BACKING_STORE_CFG_REQ_ENABLES_TIM) + last_type = BNXT_CTX_MAX - 1; + else + last_type = BNXT_CTX_L2_MAX - 1; + } ctx->ctx_arr[last_type].last = 1; for (type = 0 ; type < BNXT_CTX_V2_MAX; type++) { @@ -8776,7 +8803,7 @@ static void bnxt_free_one_ctx_mem(struct bnxt *bp, ctxm->last = 0; - if (ctxm->mem_valid && !force) + if (ctxm->mem_valid && !force && (ctxm->flags & BNXT_CTX_MEM_PERSIST)) return; ctx_pg = ctxm->pg_info; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index a092ed3c2248..d02860e7ea1c 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -1881,6 +1881,13 @@ struct bnxt_ctx_mem_type { u16 entry_size; u32 flags; #define BNXT_CTX_MEM_TYPE_VALID FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_TYPE_VALID +#define BNXT_CTX_MEM_FW_TRACE \ + FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_FW_DBG_TRACE +#define BNXT_CTX_MEM_FW_BIN_TRACE \ + FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_FW_BIN_DBG_TRACE +#define BNXT_CTX_MEM_PERSIST \ + FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_NEXT_BS_OFFSET + u32 instance_bmap; u8 init_value; u8 entry_multiple; @@ -1921,21 +1928,30 @@ struct bnxt_ctx_mem_type { #define BNXT_CTX_FTQM FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_FP_TQM_RING #define BNXT_CTX_MRAV FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_MRAV #define BNXT_CTX_TIM FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_TIM -#define BNXT_CTX_TKC FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_TKC -#define BNXT_CTX_RKC FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_RKC +#define BNXT_CTX_TCK FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_TX_CK +#define BNXT_CTX_RCK FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_RX_CK #define BNXT_CTX_MTQM FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_MP_TQM_RING #define BNXT_CTX_SQDBS FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_SQ_DB_SHADOW #define BNXT_CTX_RQDBS FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_RQ_DB_SHADOW #define BNXT_CTX_SRQDBS FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_SRQ_DB_SHADOW #define BNXT_CTX_CQDBS FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CQ_DB_SHADOW -#define BNXT_CTX_QTKC FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_QUIC_TKC -#define BNXT_CTX_QRKC FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_QUIC_RKC #define BNXT_CTX_TBLSC FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_TBL_SCOPE #define BNXT_CTX_XPAR FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_XID_PARTITION +#define BNXT_CTX_SRT FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_SRT_TRACE +#define BNXT_CTX_SRT2 FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_SRT2_TRACE +#define BNXT_CTX_CRT FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CRT_TRACE +#define BNXT_CTX_CRT2 FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CRT2_TRACE +#define BNXT_CTX_RIGP0 FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_RIGP0_TRACE +#define BNXT_CTX_L2HWRM FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_L2_HWRM_TRACE +#define BNXT_CTX_REHWRM FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_ROCE_HWRM_TRACE +#define BNXT_CTX_CA0 FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CA0_TRACE +#define BNXT_CTX_CA1 FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CA1_TRACE +#define BNXT_CTX_CA2 FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CA2_TRACE +#define BNXT_CTX_RIGP1 FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_RIGP1_TRACE #define BNXT_CTX_MAX (BNXT_CTX_TIM + 1) #define BNXT_CTX_L2_MAX (BNXT_CTX_FTQM + 1) -#define BNXT_CTX_V2_MAX (BNXT_CTX_XPAR + 1) +#define BNXT_CTX_V2_MAX (BNXT_CTX_RIGP1 + 1) #define BNXT_CTX_INV ((u16)-1) struct bnxt_ctx_mem_info { @@ -2793,6 +2809,7 @@ int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 prod, gfp_t gfp); void bnxt_reuse_rx_data(struct bnxt_rx_ring_info *rxr, u16 cons, void *data); u32 bnxt_fw_health_readl(struct bnxt *bp, int reg_idx); +bool bnxt_bs_trace_avail(struct bnxt *bp, u16 type); void bnxt_set_tpa_flags(struct bnxt *bp); void bnxt_set_ring_params(struct bnxt *); int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode); -- 2.51.0 From 84fcd9449fd7882ddfb05ba64d75f9be2d29b2e9 Mon Sep 17 00:00:00 2001 From: Shruti Parab Date: Fri, 15 Nov 2024 07:14:32 -0800 Subject: [PATCH 08/16] bnxt_en: Manage the FW trace context memory The FW trace memory pages will be added to the ethtool -w coredump in later patches. In addition to the raw data, the driver has to add a header to provide the head and tail information on each FW trace log segment when creating the coredump. The FW sends an async message to the driver after DMAing a chunk of logs to the context memory to indicate the last offset containing the tail of the logs. The driver needs to keep track of that. Reviewed-by: Hongguang Gao Signed-off-by: Shruti Parab Signed-off-by: Michael Chan Link: https://patch.msgid.link/20241115151438.550106-7-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 67 +++++++++++++++++++++++ drivers/net/ethernet/broadcom/bnxt/bnxt.h | 22 ++++++++ 2 files changed, 89 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index c7e7cb98f03b..07510df4497b 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -245,6 +245,21 @@ static const u16 bnxt_async_events_arr[] = { ASYNC_EVENT_CMPL_EVENT_ID_PPS_TIMESTAMP, ASYNC_EVENT_CMPL_EVENT_ID_ERROR_REPORT, ASYNC_EVENT_CMPL_EVENT_ID_PHC_UPDATE, + ASYNC_EVENT_CMPL_EVENT_ID_DBG_BUF_PRODUCER, +}; + +const u16 bnxt_bstore_to_trace[] = { + [BNXT_CTX_SRT] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_SRT_TRACE, + [BNXT_CTX_SRT2] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_SRT2_TRACE, + [BNXT_CTX_CRT] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CRT_TRACE, + [BNXT_CTX_CRT2] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CRT2_TRACE, + [BNXT_CTX_RIGP0] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_RIGP0_TRACE, + [BNXT_CTX_L2HWRM] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_L2_HWRM_TRACE, + [BNXT_CTX_REHWRM] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_ROCE_HWRM_TRACE, + [BNXT_CTX_CA0] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CA0_TRACE, + [BNXT_CTX_CA1] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CA1_TRACE, + [BNXT_CTX_CA2] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CA2_TRACE, + [BNXT_CTX_RIGP1] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_RIGP1_TRACE, }; static struct workqueue_struct *bnxt_pf_wq; @@ -2470,6 +2485,50 @@ bool bnxt_bs_trace_avail(struct bnxt *bp, u16 type) (flags & BNXT_CTX_MEM_FW_BIN_TRACE)); } +static void bnxt_bs_trace_init(struct bnxt *bp, struct bnxt_ctx_mem_type *ctxm) +{ + u32 mem_size, pages, rem_bytes, magic_byte_offset; + u16 trace_type = bnxt_bstore_to_trace[ctxm->type]; + struct bnxt_ctx_pg_info *ctx_pg = ctxm->pg_info; + struct bnxt_ring_mem_info *rmem, *rmem_pg_tbl; + struct bnxt_bs_trace_info *bs_trace; + int last_pg; + + if (ctxm->instance_bmap && ctxm->instance_bmap > 1) + return; + + mem_size = ctxm->max_entries * ctxm->entry_size; + rem_bytes = mem_size % BNXT_PAGE_SIZE; + pages = DIV_ROUND_UP(mem_size, BNXT_PAGE_SIZE); + + last_pg = (pages - 1) & (MAX_CTX_PAGES - 1); + magic_byte_offset = (rem_bytes ? rem_bytes : BNXT_PAGE_SIZE) - 1; + + rmem = &ctx_pg[0].ring_mem; + bs_trace = &bp->bs_trace[trace_type]; + bs_trace->ctx_type = ctxm->type; + bs_trace->trace_type = trace_type; + if (pages > MAX_CTX_PAGES) { + int last_pg_dir = rmem->nr_pages - 1; + + rmem_pg_tbl = &ctx_pg[0].ctx_pg_tbl[last_pg_dir]->ring_mem; + bs_trace->magic_byte = rmem_pg_tbl->pg_arr[last_pg]; + } else { + bs_trace->magic_byte = rmem->pg_arr[last_pg]; + } + bs_trace->magic_byte += magic_byte_offset; + *bs_trace->magic_byte = BNXT_TRACE_BUF_MAGIC_BYTE; +} + +#define BNXT_EVENT_BUF_PRODUCER_TYPE(data1) \ + (((data1) & ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_MASK) >>\ + ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_SFT) + +#define BNXT_EVENT_BUF_PRODUCER_OFFSET(data2) \ + (((data2) & \ + ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA2_CURR_OFF_MASK) >>\ + ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA2_CURR_OFF_SFT) + #define BNXT_EVENT_THERMAL_CURRENT_TEMP(data2) \ ((data2) & \ ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA2_CURRENT_TEMP_MASK) @@ -2786,6 +2845,13 @@ static int bnxt_async_event_process(struct bnxt *bp, hwrm_update_token(bp, seq_id, BNXT_HWRM_DEFERRED); goto async_event_process_exit; } + case ASYNC_EVENT_CMPL_EVENT_ID_DBG_BUF_PRODUCER: { + u16 type = (u16)BNXT_EVENT_BUF_PRODUCER_TYPE(data1); + u32 offset = BNXT_EVENT_BUF_PRODUCER_OFFSET(data2); + + bnxt_bs_trace_check_wrap(&bp->bs_trace[type], offset); + goto async_event_process_exit; + } default: goto async_event_process_exit; } @@ -8769,6 +8835,7 @@ static int bnxt_backing_store_cfg_v2(struct bnxt *bp, u32 ena) type); continue; } + bnxt_bs_trace_init(bp, ctxm); last_type = type; } } diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index d02860e7ea1c..4ebee79fbe52 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -2112,6 +2112,26 @@ enum board_idx { NETXTREME_E_P7_VF, }; +#define BNXT_TRACE_BUF_MAGIC_BYTE ((u8)0xbc) +#define BNXT_TRACE_MAX 11 + +struct bnxt_bs_trace_info { + u8 *magic_byte; + u32 last_offset; + u8 wrapped:1; + u16 ctx_type; + u16 trace_type; +}; + +static inline void bnxt_bs_trace_check_wrap(struct bnxt_bs_trace_info *bs_trace, + u32 offset) +{ + if (!bs_trace->wrapped && + *bs_trace->magic_byte != BNXT_TRACE_BUF_MAGIC_BYTE) + bs_trace->wrapped = 1; + bs_trace->last_offset = offset; +} + struct bnxt { void __iomem *bar0; void __iomem *bar1; @@ -2668,6 +2688,7 @@ struct bnxt { struct bnxt_ctx_pg_info *fw_crash_mem; u32 fw_crash_len; + struct bnxt_bs_trace_info bs_trace[BNXT_TRACE_MAX]; }; #define BNXT_NUM_RX_RING_STATS 8 @@ -2803,6 +2824,7 @@ static inline bool bnxt_sriov_cfg(struct bnxt *bp) #endif } +extern const u16 bnxt_bstore_to_trace[]; extern const u16 bnxt_lhint_arr[]; int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, -- 2.51.0 From de999362ad33d80ae5162670795d990f275960dd Mon Sep 17 00:00:00 2001 From: Hongguang Gao Date: Fri, 15 Nov 2024 07:14:33 -0800 Subject: [PATCH 09/16] bnxt_en: Do not free FW log context memory If FW supports appending new FW logs to an offset in the context memory after FW reset, then do not free this type of context memory during reset. The driver will provide the initial offset to the FW when configuring this type of context memory. This way, we don't lose the older FW logs after reset. Signed-off-by: Hongguang Gao Signed-off-by: Michael Chan Link: https://patch.msgid.link/20241115151438.550106-8-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 43 +++++++++++++++---- .../net/ethernet/broadcom/bnxt/bnxt_devlink.c | 2 +- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 07510df4497b..b0f3b431708c 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -8300,6 +8300,9 @@ static int bnxt_alloc_all_ctx_pg_info(struct bnxt *bp, int ctx_max) return 0; } +static void bnxt_free_one_ctx_mem(struct bnxt *bp, + struct bnxt_ctx_mem_type *ctxm, bool force); + #define BNXT_CTX_INIT_VALID(flags) \ (!!((flags) & \ FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_ENABLE_CTX_KIND_INIT)) @@ -8328,6 +8331,8 @@ static int bnxt_hwrm_func_backing_store_qcaps_v2(struct bnxt *bp) for (type = 0; type < BNXT_CTX_V2_MAX; ) { struct bnxt_ctx_mem_type *ctxm = &ctx->ctx_arr[type]; u8 init_val, init_off, i; + u32 max_entries; + u16 entry_size; __le32 *p; u32 flags; @@ -8337,15 +8342,26 @@ static int bnxt_hwrm_func_backing_store_qcaps_v2(struct bnxt *bp) goto ctx_done; flags = le32_to_cpu(resp->flags); type = le16_to_cpu(resp->next_valid_type); - if (!(flags & FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_TYPE_VALID)) + if (!(flags & BNXT_CTX_MEM_TYPE_VALID)) { + bnxt_free_one_ctx_mem(bp, ctxm, true); continue; - + } + entry_size = le16_to_cpu(resp->entry_size); + max_entries = le32_to_cpu(resp->max_num_entries); + if (ctxm->mem_valid) { + if (!(flags & BNXT_CTX_MEM_PERSIST) || + ctxm->entry_size != entry_size || + ctxm->max_entries != max_entries) + bnxt_free_one_ctx_mem(bp, ctxm, true); + else + continue; + } ctxm->type = le16_to_cpu(resp->type); - ctxm->entry_size = le16_to_cpu(resp->entry_size); + ctxm->entry_size = entry_size; ctxm->flags = flags; ctxm->instance_bmap = le32_to_cpu(resp->instance_bit_map); ctxm->entry_multiple = resp->entry_multiple; - ctxm->max_entries = le32_to_cpu(resp->max_num_entries); + ctxm->max_entries = max_entries; ctxm->min_entries = le32_to_cpu(resp->min_num_entries); init_val = resp->ctx_init_value; init_off = resp->ctx_init_offset; @@ -8790,6 +8806,16 @@ static int bnxt_hwrm_func_backing_store_cfg_v2(struct bnxt *bp, hwrm_req_hold(bp, req); req->type = cpu_to_le16(ctxm->type); req->entry_size = cpu_to_le16(ctxm->entry_size); + if ((ctxm->flags & BNXT_CTX_MEM_PERSIST) && + bnxt_bs_trace_avail(bp, ctxm->type)) { + struct bnxt_bs_trace_info *bs_trace; + u32 enables; + + enables = FUNC_BACKING_STORE_CFG_V2_REQ_ENABLES_NEXT_BS_OFFSET; + req->enables = cpu_to_le32(enables); + bs_trace = &bp->bs_trace[bnxt_bstore_to_trace[ctxm->type]]; + req->next_bs_offset = cpu_to_le32(bs_trace->last_offset); + } req->subtype_valid_cnt = ctxm->split_entry_cnt; for (i = 0, p = &req->split_entry_0; i < ctxm->split_entry_cnt; i++) p[i] = cpu_to_le32(ctxm->split[i]); @@ -8884,6 +8910,7 @@ static void bnxt_free_one_ctx_mem(struct bnxt *bp, ctxm->pg_info = NULL; ctxm->mem_valid = 0; } + memset(ctxm, 0, sizeof(*ctxm)); } void bnxt_free_ctx_mem(struct bnxt *bp, bool force) @@ -11862,7 +11889,7 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up) set_bit(BNXT_STATE_FW_RESET_DET, &bp->state); if (!test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) bnxt_ulp_irq_stop(bp); - bnxt_free_ctx_mem(bp, true); + bnxt_free_ctx_mem(bp, false); bnxt_dcb_free(bp); rc = bnxt_fw_init_one(bp); if (rc) { @@ -13575,7 +13602,7 @@ static void bnxt_fw_reset_close(struct bnxt *bp) bnxt_hwrm_func_drv_unrgtr(bp); if (pci_is_enabled(bp->pdev)) pci_disable_device(bp->pdev); - bnxt_free_ctx_mem(bp, true); + bnxt_free_ctx_mem(bp, false); } static bool is_bnxt_fw_ok(struct bnxt *bp) @@ -16128,7 +16155,7 @@ static int bnxt_suspend(struct device *device) } bnxt_hwrm_func_drv_unrgtr(bp); pci_disable_device(bp->pdev); - bnxt_free_ctx_mem(bp, true); + bnxt_free_ctx_mem(bp, false); rtnl_unlock(); return rc; } @@ -16240,7 +16267,7 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev, if (pci_is_enabled(pdev)) pci_disable_device(pdev); - bnxt_free_ctx_mem(bp, true); + bnxt_free_ctx_mem(bp, false); rtnl_unlock(); /* Request a slot slot reset. */ diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c index 901fd36757ed..ef8288fd68f4 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c @@ -463,7 +463,7 @@ static int bnxt_dl_reload_down(struct devlink *dl, bool netns_change, break; } bnxt_cancel_reservations(bp, false); - bnxt_free_ctx_mem(bp, true); + bnxt_free_ctx_mem(bp, false); break; } case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: { -- 2.51.0 From 23a18b91b609ea640fba0b1d1dabc3a4cc2ba817 Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Fri, 15 Nov 2024 07:14:34 -0800 Subject: [PATCH 10/16] bnxt_en: Add functions to copy host context memory Host context memory is used by the newer chips to store context information for various L2 and RoCE states and FW logs. This information will be useful for debugging. This patch adds the functions to copy all pages of a context memory type to a contiguous buffer. The next patches will include the context memory dump during ethtool -w coredump. Reviewed-by: Pavan Chebbi Reviewed-by: Hongguang Gao Co-developed-by: Shruti Parab Signed-off-by: Shruti Parab Signed-off-by: Sreekanth Reddy Signed-off-by: Michael Chan Link: https://patch.msgid.link/20241115151438.550106-9-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 103 ++++++++++++++++++++++ drivers/net/ethernet/broadcom/bnxt/bnxt.h | 4 + 2 files changed, 107 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index b0f3b431708c..5f7bdafcf05d 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -3493,6 +3493,35 @@ static void bnxt_init_ctx_mem(struct bnxt_ctx_mem_type *ctxm, void *p, int len) *(p2 + i + offset) = init_val; } +static size_t __bnxt_copy_ring(struct bnxt *bp, struct bnxt_ring_mem_info *rmem, + void *buf, size_t offset, size_t head, + size_t tail) +{ + int i, head_page, start_idx, source_offset; + size_t len, rem_len, total_len, max_bytes; + + head_page = head / rmem->page_size; + source_offset = head % rmem->page_size; + total_len = (tail - head) & MAX_CTX_BYTES_MASK; + if (!total_len) + total_len = MAX_CTX_BYTES; + start_idx = head_page % MAX_CTX_PAGES; + max_bytes = (rmem->nr_pages - start_idx) * rmem->page_size - + source_offset; + total_len = min(total_len, max_bytes); + rem_len = total_len; + + for (i = start_idx; rem_len; i++, source_offset = 0) { + len = min((size_t)(rmem->page_size - source_offset), rem_len); + if (buf) + memcpy(buf + offset, rmem->pg_arr[i] + source_offset, + len); + offset += len; + rem_len -= len; + } + return total_len; +} + static void bnxt_free_ring(struct bnxt *bp, struct bnxt_ring_mem_info *rmem) { struct pci_dev *pdev = bp->pdev; @@ -8728,6 +8757,36 @@ static int bnxt_alloc_ctx_pg_tbls(struct bnxt *bp, return rc; } +static size_t bnxt_copy_ctx_pg_tbls(struct bnxt *bp, + struct bnxt_ctx_pg_info *ctx_pg, + void *buf, size_t offset, size_t head, + size_t tail) +{ + struct bnxt_ring_mem_info *rmem = &ctx_pg->ring_mem; + size_t nr_pages = ctx_pg->nr_pages; + int page_size = rmem->page_size; + size_t len = 0, total_len = 0; + u16 depth = rmem->depth; + + tail %= nr_pages * page_size; + do { + if (depth > 1) { + int i = head / (page_size * MAX_CTX_PAGES); + struct bnxt_ctx_pg_info *pg_tbl; + + pg_tbl = ctx_pg->ctx_pg_tbl[i]; + rmem = &pg_tbl->ring_mem; + } + len = __bnxt_copy_ring(bp, rmem, buf, offset, head, tail); + head += len; + offset += len; + total_len += len; + if (head >= nr_pages * page_size) + head = 0; + } while (head != tail); + return total_len; +} + static void bnxt_free_ctx_pg_tbls(struct bnxt *bp, struct bnxt_ctx_pg_info *ctx_pg) { @@ -8888,6 +8947,50 @@ static int bnxt_backing_store_cfg_v2(struct bnxt *bp, u32 ena) return 0; } +/** + * __bnxt_copy_ctx_mem - copy host context memory + * @bp: The driver context + * @ctxm: The pointer to the context memory type + * @buf: The destination buffer or NULL to just obtain the length + * @offset: The buffer offset to copy the data to + * @head: The head offset of context memory to copy from + * @tail: The tail offset (last byte + 1) of context memory to end the copy + * + * This function is called for debugging purposes to dump the host context + * used by the chip. + * + * Return: Length of memory copied + */ +static size_t __bnxt_copy_ctx_mem(struct bnxt *bp, + struct bnxt_ctx_mem_type *ctxm, void *buf, + size_t offset, size_t head, size_t tail) +{ + struct bnxt_ctx_pg_info *ctx_pg = ctxm->pg_info; + size_t len = 0, total_len = 0; + int i, n = 1; + + if (!ctx_pg) + return 0; + + if (ctxm->instance_bmap) + n = hweight32(ctxm->instance_bmap); + for (i = 0; i < n; i++) { + len = bnxt_copy_ctx_pg_tbls(bp, &ctx_pg[i], buf, offset, head, + tail); + offset += len; + total_len += len; + } + return total_len; +} + +size_t bnxt_copy_ctx_mem(struct bnxt *bp, struct bnxt_ctx_mem_type *ctxm, + void *buf, size_t offset) +{ + size_t tail = ctxm->max_entries * ctxm->entry_size; + + return __bnxt_copy_ctx_mem(bp, ctxm, buf, offset, 0, tail); +} + static void bnxt_free_one_ctx_mem(struct bnxt *bp, struct bnxt_ctx_mem_type *ctxm, bool force) { diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 4ebee79fbe52..2d63490b9f14 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -1849,6 +1849,8 @@ struct bnxt_vf_rep { #define MAX_CTX_PAGES (BNXT_PAGE_SIZE / 8) #define MAX_CTX_TOTAL_PAGES (MAX_CTX_PAGES * MAX_CTX_PAGES) +#define MAX_CTX_BYTES ((size_t)MAX_CTX_TOTAL_PAGES * BNXT_PAGE_SIZE) +#define MAX_CTX_BYTES_MASK (MAX_CTX_BYTES - 1) struct bnxt_ctx_pg_info { u32 entries; @@ -2863,6 +2865,8 @@ int bnxt_hwrm_vnic_alloc(struct bnxt *bp, struct bnxt_vnic_info *vnic, int __bnxt_hwrm_get_tx_rings(struct bnxt *bp, u16 fid, int *tx_rings); int bnxt_nq_rings_in_use(struct bnxt *bp); int bnxt_hwrm_set_coal(struct bnxt *); +size_t bnxt_copy_ctx_mem(struct bnxt *bp, struct bnxt_ctx_mem_type *ctxm, + void *buf, size_t offset); void bnxt_free_ctx_mem(struct bnxt *bp, bool force); int bnxt_num_tx_to_cp(struct bnxt *bp, int tx); unsigned int bnxt_get_max_func_stat_ctxs(struct bnxt *bp); -- 2.51.0 From a854a17097b9e05d25e0c6354d5150acb4d841a5 Mon Sep 17 00:00:00 2001 From: Shruti Parab Date: Fri, 15 Nov 2024 07:14:35 -0800 Subject: [PATCH 11/16] bnxt_en: Add 2 parameters to bnxt_fill_coredump_seg_hdr() Pass the component ID and segment ID to this function to create the coredump segment header. This will be needed in the next patches to create more segments for the coredump. Reviewed-by: Hongguang Gao Signed-off-by: Shruti Parab Signed-off-by: Michael Chan Link: https://patch.msgid.link/20241115151438.550106-10-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- .../ethernet/broadcom/bnxt/bnxt_coredump.c | 20 +++++++++---------- .../ethernet/broadcom/bnxt/bnxt_coredump.h | 7 +++++++ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c index 4e2b938ed1f7..4dfc26cfc979 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c @@ -165,11 +165,12 @@ static int bnxt_hwrm_dbg_coredump_retrieve(struct bnxt *bp, u16 component_id, return rc; } -static void +void bnxt_fill_coredump_seg_hdr(struct bnxt *bp, struct bnxt_coredump_segment_hdr *seg_hdr, struct coredump_segment_record *seg_rec, u32 seg_len, - int status, u32 duration, u32 instance) + int status, u32 duration, u32 instance, u32 comp_id, + u32 seg_id) { memset(seg_hdr, 0, sizeof(*seg_hdr)); memcpy(seg_hdr->signature, "sEgM", 4); @@ -180,11 +181,8 @@ bnxt_fill_coredump_seg_hdr(struct bnxt *bp, seg_hdr->high_version = seg_rec->version_hi; seg_hdr->flags = cpu_to_le32(seg_rec->compress_flags); } else { - /* For hwrm_ver_get response Component id = 2 - * and Segment id = 0 - */ - seg_hdr->component_id = cpu_to_le32(2); - seg_hdr->segment_id = 0; + seg_hdr->component_id = cpu_to_le32(comp_id); + seg_hdr->segment_id = cpu_to_le32(seg_id); } seg_hdr->function_id = cpu_to_le16(bp->pdev->devfn); seg_hdr->length = cpu_to_le32(seg_len); @@ -287,11 +285,13 @@ static int __bnxt_get_coredump(struct bnxt *bp, void *buf, u32 *dump_len) start_utc = sys_tz.tz_minuteswest * 60; seg_hdr_len = sizeof(seg_hdr); - /* First segment should be hwrm_ver_get response */ + /* First segment should be hwrm_ver_get response. + * For hwrm_ver_get response Component id = 2 and Segment id = 0. + */ *dump_len = seg_hdr_len + ver_get_resp_len; if (buf) { bnxt_fill_coredump_seg_hdr(bp, &seg_hdr, NULL, ver_get_resp_len, - 0, 0, 0); + 0, 0, 0, BNXT_VER_GET_COMP_ID, 0); memcpy(buf + offset, &seg_hdr, seg_hdr_len); offset += seg_hdr_len; memcpy(buf + offset, &bp->ver_resp, ver_get_resp_len); @@ -346,7 +346,7 @@ next_seg: end = jiffies; duration = jiffies_to_msecs(end - start); bnxt_fill_coredump_seg_hdr(bp, &seg_hdr, seg_record, seg_len, - rc, duration, 0); + rc, duration, 0, 0, 0); if (buf) { /* Write segment header into the buffer */ diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h index a76d5c281413..f573e55f7e62 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h @@ -68,6 +68,8 @@ struct bnxt_coredump_record { __le16 rsvd3[313]; }; +#define BNXT_VER_GET_COMP_ID 2 + #define BNXT_CRASH_DUMP_LEN (8 << 20) #define COREDUMP_LIST_BUF_LEN 2048 @@ -118,6 +120,11 @@ struct hwrm_dbg_cmn_output { #define BNXT_DBG_CR_DUMP_MDM_CFG_DDR \ DBG_CRASHDUMP_MEDIUM_CFG_REQ_TYPE_DDR +void bnxt_fill_coredump_seg_hdr(struct bnxt *bp, + struct bnxt_coredump_segment_hdr *seg_hdr, + struct coredump_segment_record *seg_rec, + u32 seg_len, int status, u32 duration, + u32 instance, u32 comp_id, u32 seg_id); int bnxt_get_coredump(struct bnxt *bp, u16 dump_type, void *buf, u32 *dump_len); int bnxt_hwrm_get_dump_len(struct bnxt *bp, u16 dump_type, u32 *dump_len); u32 bnxt_get_coredump_length(struct bnxt *bp, u16 dump_type); -- 2.51.0 From bda2e63a508b7f728c2386c9a0de234113e8b809 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 15 Nov 2024 07:14:36 -0800 Subject: [PATCH 12/16] bnxt_en: Add a new ethtool -W dump flag Add a new ethtool -W dump flag (2) to include driver coredump segments. This patch adds the host backing store context memory pages used by the chip and FW to store various states to the coredump. The pages for each context memory type is dumped into a separate coredump segment. Reviewed-by: Andy Gospodarek Reviewed-by: Selvin Thyparampil Xavier Reviewed-by: Shruti Parab Reviewed-by: Kalesh AP Reviewed-by: Saravanan Vajravel Reviewed-by: Kashyap Desai Signed-off-by: Michael Chan Link: https://patch.msgid.link/20241115151438.550106-11-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 1 + .../ethernet/broadcom/bnxt/bnxt_coredump.c | 77 +++++++++++++++++-- .../ethernet/broadcom/bnxt/bnxt_coredump.h | 15 ++++ .../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 4 +- 4 files changed, 90 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 2d63490b9f14..231e38933984 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -2662,6 +2662,7 @@ struct bnxt { u16 dump_flag; #define BNXT_DUMP_LIVE 0 #define BNXT_DUMP_CRASH 1 +#define BNXT_DUMP_DRIVER 2 struct bpf_prog *xdp_prog; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c index 4dfc26cfc979..ff92443db01b 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c @@ -15,6 +15,18 @@ #include "bnxt_hwrm.h" #include "bnxt_coredump.h" +static const u16 bnxt_bstore_to_seg_id[] = { + [BNXT_CTX_QP] = BNXT_CTX_MEM_SEG_QP, + [BNXT_CTX_SRQ] = BNXT_CTX_MEM_SEG_SRQ, + [BNXT_CTX_CQ] = BNXT_CTX_MEM_SEG_CQ, + [BNXT_CTX_VNIC] = BNXT_CTX_MEM_SEG_VNIC, + [BNXT_CTX_STAT] = BNXT_CTX_MEM_SEG_STAT, + [BNXT_CTX_STQM] = BNXT_CTX_MEM_SEG_STQM, + [BNXT_CTX_FTQM] = BNXT_CTX_MEM_SEG_FTQM, + [BNXT_CTX_MRAV] = BNXT_CTX_MEM_SEG_MRAV, + [BNXT_CTX_TIM] = BNXT_CTX_MEM_SEG_TIM, +}; + static int bnxt_hwrm_dbg_dma_data(struct bnxt *bp, void *msg, struct bnxt_hwrm_dbg_dma_info *info) { @@ -267,7 +279,47 @@ bnxt_fill_coredump_record(struct bnxt *bp, struct bnxt_coredump_record *record, record->ioctl_high_version = 0; } -static int __bnxt_get_coredump(struct bnxt *bp, void *buf, u32 *dump_len) +static u32 bnxt_get_ctx_coredump(struct bnxt *bp, void *buf, u32 offset, + u32 *segs) +{ + struct bnxt_coredump_segment_hdr seg_hdr; + struct bnxt_ctx_mem_info *ctx = bp->ctx; + u32 comp_id = BNXT_DRV_COMP_ID; + void *data = NULL; + size_t len = 0; + u16 type; + + *segs = 0; + if (!ctx) + return 0; + + if (buf) + buf += offset; + for (type = 0 ; type <= BNXT_CTX_TIM; type++) { + struct bnxt_ctx_mem_type *ctxm = &ctx->ctx_arr[type]; + u32 seg_id = bnxt_bstore_to_seg_id[type]; + size_t seg_len; + + if (!ctxm->entry_size || !ctxm->pg_info || !seg_id) + continue; + + if (buf) + data = buf + BNXT_SEG_HDR_LEN; + seg_len = bnxt_copy_ctx_mem(bp, ctxm, data, 0); + if (buf) { + bnxt_fill_coredump_seg_hdr(bp, &seg_hdr, NULL, seg_len, + 0, 0, 0, comp_id, seg_id); + memcpy(buf, &seg_hdr, BNXT_SEG_HDR_LEN); + buf += BNXT_SEG_HDR_LEN + seg_len; + } + len += BNXT_SEG_HDR_LEN + seg_len; + *segs += 1; + } + return len; +} + +static int __bnxt_get_coredump(struct bnxt *bp, u16 dump_type, void *buf, + u32 *dump_len) { u32 ver_get_resp_len = sizeof(struct hwrm_ver_get_output); u32 offset = 0, seg_hdr_len, seg_record_len, buf_len = 0; @@ -298,6 +350,18 @@ static int __bnxt_get_coredump(struct bnxt *bp, void *buf, u32 *dump_len) offset += ver_get_resp_len; } + if (dump_type == BNXT_DUMP_DRIVER) { + u32 drv_len, segs = 0; + + drv_len = bnxt_get_ctx_coredump(bp, buf, offset, &segs); + *dump_len += drv_len; + offset += drv_len; + if (buf) + coredump.total_segs += segs; + goto err; + } + + seg_record_len = sizeof(*seg_record); rc = bnxt_hwrm_dbg_coredump_list(bp, &coredump); if (rc) { netdev_err(bp->dev, "Failed to get coredump segment list\n"); @@ -442,7 +506,7 @@ int bnxt_get_coredump(struct bnxt *bp, u16 dump_type, void *buf, u32 *dump_len) else return -EOPNOTSUPP; } else { - return __bnxt_get_coredump(bp, buf, dump_len); + return __bnxt_get_coredump(bp, dump_type, buf, dump_len); } } @@ -512,9 +576,12 @@ u32 bnxt_get_coredump_length(struct bnxt *bp, u16 dump_type) return bp->fw_crash_len; } - if (bnxt_hwrm_get_dump_len(bp, dump_type, &len)) { - if (dump_type != BNXT_DUMP_CRASH) - __bnxt_get_coredump(bp, NULL, &len); + if (dump_type != BNXT_DUMP_DRIVER) { + if (!bnxt_hwrm_get_dump_len(bp, dump_type, &len)) + return len; } + if (dump_type != BNXT_DUMP_CRASH) + __bnxt_get_coredump(bp, dump_type, NULL, &len); + return len; } diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h index f573e55f7e62..3a6084a51be8 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h @@ -69,12 +69,27 @@ struct bnxt_coredump_record { }; #define BNXT_VER_GET_COMP_ID 2 +#define BNXT_DRV_COMP_ID 0xd + +#define BNXT_CTX_MEM_SEG_ID_START 0x200 + +#define BNXT_CTX_MEM_SEG_QP (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_QP) +#define BNXT_CTX_MEM_SEG_SRQ (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_SRQ) +#define BNXT_CTX_MEM_SEG_CQ (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_CQ) +#define BNXT_CTX_MEM_SEG_VNIC (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_VNIC) +#define BNXT_CTX_MEM_SEG_STAT (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_STAT) +#define BNXT_CTX_MEM_SEG_STQM (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_STQM) +#define BNXT_CTX_MEM_SEG_FTQM (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_FTQM) +#define BNXT_CTX_MEM_SEG_MRAV (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_MRAV) +#define BNXT_CTX_MEM_SEG_TIM (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_TIM) #define BNXT_CRASH_DUMP_LEN (8 << 20) #define COREDUMP_LIST_BUF_LEN 2048 #define COREDUMP_RETRIEVE_BUF_LEN 4096 +#define BNXT_SEG_HDR_LEN sizeof(struct bnxt_coredump_segment_hdr) + struct bnxt_coredump { void *data; int data_size; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 061a40b1974b..2f4987ec7464 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -4984,8 +4984,8 @@ static int bnxt_set_dump(struct net_device *dev, struct ethtool_dump *dump) { struct bnxt *bp = netdev_priv(dev); - if (dump->flag > BNXT_DUMP_CRASH) { - netdev_info(dev, "Supports only Live(0) and Crash(1) dumps.\n"); + if (dump->flag > BNXT_DUMP_DRIVER) { + netdev_info(dev, "Supports only Live(0), Crash(1), Driver(2) dumps.\n"); return -EINVAL; } -- 2.51.0 From 3c2179e66355a2f85ff86a73719f0ce7dcf4a226 Mon Sep 17 00:00:00 2001 From: Shruti Parab Date: Fri, 15 Nov 2024 07:14:37 -0800 Subject: [PATCH 13/16] bnxt_en: Add FW trace coredump segments to the coredump The FW trace coredump segments are very similar to the context memory segments in the previous patch. The main difference is to call HWRM_DBG_LOG_BUFFER_FLUSH to flush the FW data to host memory and to include an additional record in the coredump that contains the head and tail information of the trace data. Reviewed-by: Hongguang Gao Signed-off-by: Shruti Parab Signed-off-by: Michael Chan Link: https://patch.msgid.link/20241115151438.550106-12-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- .../ethernet/broadcom/bnxt/bnxt_coredump.c | 75 +++++++++++++++++-- .../ethernet/broadcom/bnxt/bnxt_coredump.h | 21 ++++++ 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c index ff92443db01b..7236d8e548ab 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c @@ -25,8 +25,40 @@ static const u16 bnxt_bstore_to_seg_id[] = { [BNXT_CTX_FTQM] = BNXT_CTX_MEM_SEG_FTQM, [BNXT_CTX_MRAV] = BNXT_CTX_MEM_SEG_MRAV, [BNXT_CTX_TIM] = BNXT_CTX_MEM_SEG_TIM, + [BNXT_CTX_SRT] = BNXT_CTX_MEM_SEG_SRT, + [BNXT_CTX_SRT2] = BNXT_CTX_MEM_SEG_SRT2, + [BNXT_CTX_CRT] = BNXT_CTX_MEM_SEG_CRT, + [BNXT_CTX_CRT2] = BNXT_CTX_MEM_SEG_CRT2, + [BNXT_CTX_RIGP0] = BNXT_CTX_MEM_SEG_RIGP0, + [BNXT_CTX_L2HWRM] = BNXT_CTX_MEM_SEG_L2HWRM, + [BNXT_CTX_REHWRM] = BNXT_CTX_MEM_SEG_REHWRM, + [BNXT_CTX_CA0] = BNXT_CTX_MEM_SEG_CA0, + [BNXT_CTX_CA1] = BNXT_CTX_MEM_SEG_CA1, + [BNXT_CTX_CA2] = BNXT_CTX_MEM_SEG_CA2, + [BNXT_CTX_RIGP1] = BNXT_CTX_MEM_SEG_RIGP1, }; +static int bnxt_dbg_hwrm_log_buffer_flush(struct bnxt *bp, u16 type, u32 flags, + u32 *offset) +{ + struct hwrm_dbg_log_buffer_flush_output *resp; + struct hwrm_dbg_log_buffer_flush_input *req; + int rc; + + rc = hwrm_req_init(bp, req, HWRM_DBG_LOG_BUFFER_FLUSH); + if (rc) + return rc; + + req->flags = cpu_to_le32(flags); + req->type = cpu_to_le16(type); + resp = hwrm_req_hold(bp, req); + rc = hwrm_req_send(bp, req); + if (!rc) + *offset = le32_to_cpu(resp->current_buffer_offset); + hwrm_req_drop(bp, req); + return rc; +} + static int bnxt_hwrm_dbg_dma_data(struct bnxt *bp, void *msg, struct bnxt_hwrm_dbg_dma_info *info) { @@ -279,9 +311,29 @@ bnxt_fill_coredump_record(struct bnxt *bp, struct bnxt_coredump_record *record, record->ioctl_high_version = 0; } +static void bnxt_fill_drv_seg_record(struct bnxt *bp, + struct bnxt_driver_segment_record *record, + struct bnxt_ctx_mem_type *ctxm, u16 type) +{ + struct bnxt_bs_trace_info *bs_trace = &bp->bs_trace[type]; + u32 offset = 0; + int rc = 0; + + rc = bnxt_dbg_hwrm_log_buffer_flush(bp, type, 0, &offset); + if (rc) + return; + + bnxt_bs_trace_check_wrap(bs_trace, offset); + record->max_entries = cpu_to_le32(ctxm->max_entries); + record->entry_size = cpu_to_le32(ctxm->entry_size); + record->offset = cpu_to_le32(bs_trace->last_offset); + record->wrapped = bs_trace->wrapped; +} + static u32 bnxt_get_ctx_coredump(struct bnxt *bp, void *buf, u32 offset, u32 *segs) { + struct bnxt_driver_segment_record record = {}; struct bnxt_coredump_segment_hdr seg_hdr; struct bnxt_ctx_mem_info *ctx = bp->ctx; u32 comp_id = BNXT_DRV_COMP_ID; @@ -295,22 +347,33 @@ static u32 bnxt_get_ctx_coredump(struct bnxt *bp, void *buf, u32 offset, if (buf) buf += offset; - for (type = 0 ; type <= BNXT_CTX_TIM; type++) { + for (type = 0 ; type <= BNXT_CTX_RIGP1; type++) { struct bnxt_ctx_mem_type *ctxm = &ctx->ctx_arr[type]; + bool trace = bnxt_bs_trace_avail(bp, type); u32 seg_id = bnxt_bstore_to_seg_id[type]; - size_t seg_len; + size_t seg_len, extra_hlen = 0; - if (!ctxm->entry_size || !ctxm->pg_info || !seg_id) + if (!ctxm->mem_valid || !seg_id) continue; + if (trace) + extra_hlen = BNXT_SEG_RCD_LEN; if (buf) - data = buf + BNXT_SEG_HDR_LEN; - seg_len = bnxt_copy_ctx_mem(bp, ctxm, data, 0); + data = buf + BNXT_SEG_HDR_LEN + extra_hlen; + seg_len = bnxt_copy_ctx_mem(bp, ctxm, data, 0) + extra_hlen; if (buf) { bnxt_fill_coredump_seg_hdr(bp, &seg_hdr, NULL, seg_len, 0, 0, 0, comp_id, seg_id); memcpy(buf, &seg_hdr, BNXT_SEG_HDR_LEN); - buf += BNXT_SEG_HDR_LEN + seg_len; + buf += BNXT_SEG_HDR_LEN; + if (trace) { + u16 trace_type = bnxt_bstore_to_trace[type]; + + bnxt_fill_drv_seg_record(bp, &record, ctxm, + trace_type); + memcpy(buf, &record, BNXT_SEG_RCD_LEN); + } + buf += seg_len; } len += BNXT_SEG_HDR_LEN + seg_len; *segs += 1; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h index 3a6084a51be8..d1cd6387f3ab 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h @@ -68,6 +68,14 @@ struct bnxt_coredump_record { __le16 rsvd3[313]; }; +struct bnxt_driver_segment_record { + __le32 max_entries; + __le32 entry_size; + __le32 offset; + __u8 wrapped:1; + __u8 unused[3]; +}; + #define BNXT_VER_GET_COMP_ID 2 #define BNXT_DRV_COMP_ID 0xd @@ -83,12 +91,25 @@ struct bnxt_coredump_record { #define BNXT_CTX_MEM_SEG_MRAV (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_MRAV) #define BNXT_CTX_MEM_SEG_TIM (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_TIM) +#define BNXT_CTX_MEM_SEG_SRT 0x1 +#define BNXT_CTX_MEM_SEG_SRT2 0x2 +#define BNXT_CTX_MEM_SEG_CRT 0x3 +#define BNXT_CTX_MEM_SEG_CRT2 0x4 +#define BNXT_CTX_MEM_SEG_RIGP0 0x5 +#define BNXT_CTX_MEM_SEG_L2HWRM 0x6 +#define BNXT_CTX_MEM_SEG_REHWRM 0x7 +#define BNXT_CTX_MEM_SEG_CA0 0x8 +#define BNXT_CTX_MEM_SEG_CA1 0x9 +#define BNXT_CTX_MEM_SEG_CA2 0xa +#define BNXT_CTX_MEM_SEG_RIGP1 0xb + #define BNXT_CRASH_DUMP_LEN (8 << 20) #define COREDUMP_LIST_BUF_LEN 2048 #define COREDUMP_RETRIEVE_BUF_LEN 4096 #define BNXT_SEG_HDR_LEN sizeof(struct bnxt_coredump_segment_hdr) +#define BNXT_SEG_RCD_LEN sizeof(struct bnxt_driver_segment_record) struct bnxt_coredump { void *data; -- 2.51.0 From 6116075e18f79698419f2606d9cb34d23198f7e3 Mon Sep 17 00:00:00 2001 From: Mohan Prasad J Date: Fri, 15 Nov 2024 00:55:18 +0530 Subject: [PATCH 14/16] selftests: nic_link_layer: Add link layer selftest for NIC driver Add selftest file for the link layer tests of a NIC driver. Test for auto-negotiation is added. Add LinkConfig class for changing link layer configs. Selftest makes use of ksft modules and ethtool. Include selftest file in the Makefile. Signed-off-by: Mohan Prasad J Signed-off-by: Paolo Abeni --- .../testing/selftests/drivers/net/hw/Makefile | 1 + .../drivers/net/hw/lib/py/__init__.py | 1 + .../drivers/net/hw/lib/py/linkconfig.py | 222 ++++++++++++++++++ .../drivers/net/hw/nic_link_layer.py | 91 +++++++ 4 files changed, 315 insertions(+) create mode 100644 tools/testing/selftests/drivers/net/hw/lib/py/linkconfig.py create mode 100644 tools/testing/selftests/drivers/net/hw/nic_link_layer.py diff --git a/tools/testing/selftests/drivers/net/hw/Makefile b/tools/testing/selftests/drivers/net/hw/Makefile index 1c6a77480923..a87f1f17a10a 100644 --- a/tools/testing/selftests/drivers/net/hw/Makefile +++ b/tools/testing/selftests/drivers/net/hw/Makefile @@ -11,6 +11,7 @@ TEST_PROGS = \ hw_stats_l3.sh \ hw_stats_l3_gre.sh \ loopback.sh \ + nic_link_layer.py \ pp_alloc_fail.py \ rss_ctx.py \ # diff --git a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py b/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py index b582885786f5..399789a9676a 100644 --- a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py +++ b/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py @@ -9,6 +9,7 @@ try: sys.path.append(KSFT_DIR.as_posix()) from net.lib.py import * from drivers.net.lib.py import * + from .linkconfig import LinkConfig except ModuleNotFoundError as e: ksft_pr("Failed importing `net` library from kernel sources") ksft_pr(str(e)) diff --git a/tools/testing/selftests/drivers/net/hw/lib/py/linkconfig.py b/tools/testing/selftests/drivers/net/hw/lib/py/linkconfig.py new file mode 100644 index 000000000000..db84000fc75b --- /dev/null +++ b/tools/testing/selftests/drivers/net/hw/lib/py/linkconfig.py @@ -0,0 +1,222 @@ +# SPDX-License-Identifier: GPL-2.0 + +from lib.py import cmd, ethtool, ip +from lib.py import ksft_pr, ksft_eq, KsftSkipEx +from typing import Optional +import re +import time +import json + +#The LinkConfig class is implemented to handle the link layer configurations. +#Required minimum ethtool version is 6.10 + +class LinkConfig: + """Class for handling the link layer configurations""" + def __init__(self, cfg: object) -> None: + self.cfg = cfg + self.partner_netif = self.get_partner_netif_name() + + """Get the initial link configuration of local interface""" + self.common_link_modes = self.get_common_link_modes() + + def get_partner_netif_name(self) -> Optional[str]: + partner_netif = None + try: + if not self.verify_link_up(): + return None + """Get partner interface name""" + partner_json_output = ip("addr show", json=True, host=self.cfg.remote) + for interface in partner_json_output: + for addr in interface.get('addr_info', []): + if addr.get('local') == self.cfg.remote_addr: + partner_netif = interface['ifname'] + ksft_pr(f"Partner Interface name: {partner_netif}") + if partner_netif is None: + ksft_pr("Unable to get the partner interface name") + except Exception as e: + print(f"Unexpected error occurred while getting partner interface name: {e}") + self.partner_netif = partner_netif + return partner_netif + + def verify_link_up(self) -> bool: + """Verify whether the local interface link is up""" + with open(f"/sys/class/net/{self.cfg.ifname}/operstate", "r") as fp: + link_state = fp.read().strip() + + if link_state == "down": + ksft_pr(f"Link state of interface {self.cfg.ifname} is DOWN") + return False + else: + return True + + def reset_interface(self, local: bool = True, remote: bool = True) -> bool: + ksft_pr("Resetting interfaces in local and remote") + if remote: + if self.verify_link_up(): + if self.partner_netif is not None: + ifname = self.partner_netif + link_up_cmd = f"ip link set up {ifname}" + link_down_cmd = f"ip link set down {ifname}" + reset_cmd = f"{link_down_cmd} && sleep 5 && {link_up_cmd}" + try: + cmd(reset_cmd, host=self.cfg.remote) + except Exception as e: + ksft_pr(f"Unexpected error occurred while resetting remote: {e}") + else: + ksft_pr("Partner interface not available") + if local: + ifname = self.cfg.ifname + link_up_cmd = f"ip link set up {ifname}" + link_down_cmd = f"ip link set down {ifname}" + reset_cmd = f"{link_down_cmd} && sleep 5 && {link_up_cmd}" + try: + cmd(reset_cmd) + except Exception as e: + ksft_pr(f"Unexpected error occurred while resetting local: {e}") + time.sleep(10) + if self.verify_link_up() and self.get_ethtool_field("link-detected"): + ksft_pr("Local and remote interfaces reset to original state") + return True + else: + ksft_pr("Error occurred after resetting interfaces. Link is DOWN.") + return False + + def set_speed_and_duplex(self, speed: str, duplex: str, autoneg: bool = True) -> bool: + """Set the speed and duplex state for the interface""" + autoneg_state = "on" if autoneg is True else "off" + process = None + try: + process = ethtool(f"--change {self.cfg.ifname} speed {speed} duplex {duplex} autoneg {autoneg_state}") + except Exception as e: + ksft_pr(f"Unexpected error occurred while setting speed/duplex: {e}") + if process is None or process.ret != 0: + return False + else: + ksft_pr(f"Speed: {speed} Mbps, Duplex: {duplex} set for Interface: {self.cfg.ifname}") + return True + + def verify_speed_and_duplex(self, expected_speed: str, expected_duplex: str) -> bool: + if not self.verify_link_up(): + return False + """Verifying the speed and duplex state for the interface""" + with open(f"/sys/class/net/{self.cfg.ifname}/speed", "r") as fp: + actual_speed = fp.read().strip() + with open(f"/sys/class/net/{self.cfg.ifname}/duplex", "r") as fp: + actual_duplex = fp.read().strip() + + ksft_eq(actual_speed, expected_speed) + ksft_eq(actual_duplex, expected_duplex) + return True + + def set_autonegotiation_state(self, state: str, remote: bool = False) -> bool: + common_link_modes = self.common_link_modes + speeds, duplex_modes = self.get_speed_duplex_values(self.common_link_modes) + speed = speeds[0] + duplex = duplex_modes[0] + if not speed or not duplex: + ksft_pr("No speed or duplex modes found") + return False + + speed_duplex_cmd = f"speed {speed} duplex {duplex}" if state == "off" else "" + if remote: + if not self.verify_link_up(): + return False + """Set the autonegotiation state for the partner""" + command = f"-s {self.partner_netif} {speed_duplex_cmd} autoneg {state}" + partner_autoneg_change = None + """Set autonegotiation state for interface in remote pc""" + try: + partner_autoneg_change = ethtool(command, host=self.cfg.remote) + except Exception as e: + ksft_pr(f"Unexpected error occurred while changing auto-neg in remote: {e}") + if partner_autoneg_change is None or partner_autoneg_change.ret != 0: + ksft_pr(f"Not able to set autoneg parameter for interface {self.partner_netif}.") + return False + ksft_pr(f"Autoneg set as {state} for {self.partner_netif}") + else: + """Set the autonegotiation state for the interface""" + try: + process = ethtool(f"-s {self.cfg.ifname} {speed_duplex_cmd} autoneg {state}") + if process.ret != 0: + ksft_pr(f"Not able to set autoneg parameter for interface {self.cfg.ifname}") + return False + except Exception as e: + ksft_pr(f"Unexpected error occurred while changing auto-neg in local: {e}") + return False + ksft_pr(f"Autoneg set as {state} for {self.cfg.ifname}") + return True + + def check_autoneg_supported(self, remote: bool = False) -> bool: + if not remote: + local_autoneg = self.get_ethtool_field("supports-auto-negotiation") + if local_autoneg is None: + ksft_pr(f"Unable to fetch auto-negotiation status for interface {self.cfg.ifname}") + """Return autoneg status of the local interface""" + return local_autoneg + else: + if not self.verify_link_up(): + raise KsftSkipEx("Link is DOWN") + """Check remote auto-negotiation support status""" + partner_autoneg = False + if self.partner_netif is not None: + partner_autoneg = self.get_ethtool_field("supports-auto-negotiation", remote=True) + if partner_autoneg is None: + ksft_pr(f"Unable to fetch auto-negotiation status for interface {self.partner_netif}") + return partner_autoneg + + def get_common_link_modes(self) -> set[str]: + common_link_modes = [] + """Populate common link modes""" + link_modes = self.get_ethtool_field("supported-link-modes") + partner_link_modes = self.get_ethtool_field("link-partner-advertised-link-modes") + if link_modes is None: + raise KsftSkipEx(f"Link modes not available for {self.cfg.ifname}") + if partner_link_modes is None: + raise KsftSkipEx(f"Partner link modes not available for {self.cfg.ifname}") + common_link_modes = set(link_modes) and set(partner_link_modes) + return common_link_modes + + def get_speed_duplex_values(self, link_modes: list[str]) -> tuple[list[str], list[str]]: + speed = [] + duplex = [] + """Check the link modes""" + for data in link_modes: + parts = data.split('/') + speed_value = re.match(r'\d+', parts[0]) + if speed_value: + speed.append(speed_value.group()) + else: + ksft_pr(f"No speed value found for interface {self.ifname}") + return None, None + duplex.append(parts[1].lower()) + return speed, duplex + + def get_ethtool_field(self, field: str, remote: bool = False) -> Optional[str]: + process = None + if not remote: + """Get the ethtool field value for the local interface""" + try: + process = ethtool(self.cfg.ifname, json=True) + except Exception as e: + ksft_pr("Required minimum ethtool version is 6.10") + ksft_pr(f"Unexpected error occurred while getting ethtool field in local: {e}") + return None + else: + if not self.verify_link_up(): + return None + """Get the ethtool field value for the remote interface""" + self.cfg.require_cmd("ethtool", remote=True) + if self.partner_netif is None: + ksft_pr(f"Partner interface name is unavailable.") + return None + try: + process = ethtool(self.partner_netif, json=True, host=self.cfg.remote) + except Exception as e: + ksft_pr("Required minimum ethtool version is 6.10") + ksft_pr(f"Unexpected error occurred while getting ethtool field in remote: {e}") + return None + json_data = process[0] + """Check if the field exist in the json data""" + if field not in json_data: + raise KsftSkipEx(f"Field {field} does not exist in the output of interface {json_data["ifname"]}") + return json_data[field] diff --git a/tools/testing/selftests/drivers/net/hw/nic_link_layer.py b/tools/testing/selftests/drivers/net/hw/nic_link_layer.py new file mode 100644 index 000000000000..d8cc12e84a40 --- /dev/null +++ b/tools/testing/selftests/drivers/net/hw/nic_link_layer.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 + +#Introduction: +#This file has basic link layer tests for generic NIC drivers. +#The test comprises of auto-negotiation, speed and duplex checks. +# +#Setup: +#Connect the DUT PC with NIC card to partner pc back via ethernet medium of your choice(RJ45, T1) +# +# DUT PC Partner PC +#┌───────────────────────┐ ┌──────────────────────────┐ +#│ │ │ │ +#│ │ │ │ +#│ ┌───────────┐ │ │ +#│ │DUT NIC │ Eth │ │ +#│ │Interface ─┼─────────────────────────┼─ any eth Interface │ +#│ └───────────┘ │ │ +#│ │ │ │ +#│ │ │ │ +#└───────────────────────┘ └──────────────────────────┘ +# +#Configurations: +#Required minimum ethtool version is 6.10 (supports json) +#Default values: +#time_delay = 8 #time taken to wait for transitions to happen, in seconds. + +import time +import argparse +from lib.py import ksft_run, ksft_exit, ksft_pr, ksft_eq +from lib.py import KsftFailEx, KsftSkipEx +from lib.py import NetDrvEpEnv +from lib.py import LinkConfig + +def _pre_test_checks(cfg: object, link_config: LinkConfig) -> None: + if link_config.partner_netif is None: + KsftSkipEx("Partner interface is not available") + if not link_config.check_autoneg_supported() or not link_config.check_autoneg_supported(remote=True): + KsftSkipEx(f"Auto-negotiation not supported for interface {cfg.ifname} or {link_config.partner_netif}") + if not link_config.verify_link_up(): + raise KsftSkipEx(f"Link state of interface {cfg.ifname} is DOWN") + +def verify_autonegotiation(cfg: object, expected_state: str, link_config: LinkConfig) -> None: + if not link_config.verify_link_up(): + raise KsftSkipEx(f"Link state of interface {cfg.ifname} is DOWN") + """Verifying the autonegotiation state in partner""" + partner_autoneg_output = link_config.get_ethtool_field("auto-negotiation", remote=True) + if partner_autoneg_output is None: + KsftSkipEx(f"Auto-negotiation state not available for interface {link_config.partner_netif}") + partner_autoneg_state = "on" if partner_autoneg_output is True else "off" + + ksft_eq(partner_autoneg_state, expected_state) + + """Verifying the autonegotiation state of local""" + autoneg_output = link_config.get_ethtool_field("auto-negotiation") + if autoneg_output is None: + KsftSkipEx(f"Auto-negotiation state not available for interface {cfg.ifname}") + actual_state = "on" if autoneg_output is True else "off" + + ksft_eq(actual_state, expected_state) + + """Verifying the link establishment""" + link_available = link_config.get_ethtool_field("link-detected") + if link_available is None: + KsftSkipEx(f"Link status not available for interface {cfg.ifname}") + if link_available != True: + raise KsftSkipEx("Link not established at interface {cfg.ifname} after changing auto-negotiation") + +def test_autonegotiation(cfg: object, link_config: LinkConfig, time_delay: int) -> None: + _pre_test_checks(cfg, link_config) + for state in ["off", "on"]: + if not link_config.set_autonegotiation_state(state, remote=True): + raise KsftSkipEx(f"Unable to set auto-negotiation state for interface {link_config.partner_netif}") + if not link_config.set_autonegotiation_state(state): + raise KsftSkipEx(f"Unable to set auto-negotiation state for interface {cfg.ifname}") + time.sleep(time_delay) + verify_autonegotiation(cfg, state, link_config) + +def main() -> None: + parser = argparse.ArgumentParser(description="Run basic link layer tests for NIC driver") + parser.add_argument('--time-delay', type=int, default=8, help='Time taken to wait for transitions to happen(in seconds). Default is 8 seconds.') + args = parser.parse_args() + time_delay = args.time_delay + with NetDrvEpEnv(__file__, nsim_test=False) as cfg: + link_config = LinkConfig(cfg) + ksft_run(globs=globals(), case_pfx={"test_"}, args=(cfg, link_config, time_delay,)) + link_config.reset_interface() + ksft_exit() + +if __name__ == "__main__": + main() -- 2.51.0 From c087dc54394b3f8a2950007fb17a8937a38fe73a Mon Sep 17 00:00:00 2001 From: Mohan Prasad J Date: Fri, 15 Nov 2024 00:55:19 +0530 Subject: [PATCH 15/16] selftests: nic_link_layer: Add selftest case for speed and duplex states Add selftest case for testing the speed and duplex state of local NIC driver and the partner based on the supported link modes obtained from the ethtool. Speed and duplex states are varied and verified using ethtool. Signed-off-by: Mohan Prasad J Signed-off-by: Paolo Abeni --- .../drivers/net/hw/nic_link_layer.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tools/testing/selftests/drivers/net/hw/nic_link_layer.py b/tools/testing/selftests/drivers/net/hw/nic_link_layer.py index d8cc12e84a40..efd921180532 100644 --- a/tools/testing/selftests/drivers/net/hw/nic_link_layer.py +++ b/tools/testing/selftests/drivers/net/hw/nic_link_layer.py @@ -76,6 +76,28 @@ def test_autonegotiation(cfg: object, link_config: LinkConfig, time_delay: int) time.sleep(time_delay) verify_autonegotiation(cfg, state, link_config) +def test_network_speed(cfg: object, link_config: LinkConfig, time_delay: int) -> None: + _pre_test_checks(cfg, link_config) + common_link_modes = link_config.common_link_modes + if not common_link_modes: + KsftSkipEx("No common link modes exist") + speeds, duplex_modes = link_config.get_speed_duplex_values(common_link_modes) + + if speeds and duplex_modes and len(speeds) == len(duplex_modes): + for idx in range(len(speeds)): + speed = speeds[idx] + duplex = duplex_modes[idx] + if not link_config.set_speed_and_duplex(speed, duplex): + raise KsftFailEx(f"Unable to set speed and duplex parameters for {cfg.ifname}") + time.sleep(time_delay) + if not link_config.verify_speed_and_duplex(speed, duplex): + raise KsftSkipEx(f"Error occurred while verifying speed and duplex states for interface {cfg.ifname}") + else: + if not speeds or not duplex_modes: + KsftSkipEx(f"No supported speeds or duplex modes found for interface {cfg.ifname}") + else: + KsftSkipEx("Mismatch in the number of speeds and duplex modes") + def main() -> None: parser = argparse.ArgumentParser(description="Run basic link layer tests for NIC driver") parser.add_argument('--time-delay', type=int, default=8, help='Time taken to wait for transitions to happen(in seconds). Default is 8 seconds.') -- 2.51.0 From fbbf93556f0c1ad9b53fd1ec8fd2e67b2debb740 Mon Sep 17 00:00:00 2001 From: Mohan Prasad J Date: Fri, 15 Nov 2024 00:55:20 +0530 Subject: [PATCH 16/16] selftests: nic_performance: Add selftest for performance of NIC driver Add selftest case to check the send and receive throughput. Supported link modes between local NIC driver and partner are varied. Then send and receive throughput is captured and verified. Test uses iperf3 tool. Add iperf3 server/client function in GenerateTraffic class. Signed-off-by: Mohan Prasad J Signed-off-by: Paolo Abeni --- .../testing/selftests/drivers/net/hw/Makefile | 1 + .../drivers/net/hw/nic_performance.py | 137 ++++++++++++++++++ .../selftests/drivers/net/lib/py/load.py | 20 ++- 3 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/drivers/net/hw/nic_performance.py diff --git a/tools/testing/selftests/drivers/net/hw/Makefile b/tools/testing/selftests/drivers/net/hw/Makefile index a87f1f17a10a..21ba64ce1e34 100644 --- a/tools/testing/selftests/drivers/net/hw/Makefile +++ b/tools/testing/selftests/drivers/net/hw/Makefile @@ -12,6 +12,7 @@ TEST_PROGS = \ hw_stats_l3_gre.sh \ loopback.sh \ nic_link_layer.py \ + nic_performance.py \ pp_alloc_fail.py \ rss_ctx.py \ # diff --git a/tools/testing/selftests/drivers/net/hw/nic_performance.py b/tools/testing/selftests/drivers/net/hw/nic_performance.py new file mode 100644 index 000000000000..201403b76ea3 --- /dev/null +++ b/tools/testing/selftests/drivers/net/hw/nic_performance.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 + +#Introduction: +#This file has basic performance test for generic NIC drivers. +#The test comprises of throughput check for TCP and UDP streams. +# +#Setup: +#Connect the DUT PC with NIC card to partner pc back via ethernet medium of your choice(RJ45, T1) +# +# DUT PC Partner PC +#┌───────────────────────┐ ┌──────────────────────────┐ +#│ │ │ │ +#│ │ │ │ +#│ ┌───────────┐ │ │ +#│ │DUT NIC │ Eth │ │ +#│ │Interface ─┼─────────────────────────┼─ any eth Interface │ +#│ └───────────┘ │ │ +#│ │ │ │ +#│ │ │ │ +#└───────────────────────┘ └──────────────────────────┘ +# +#Configurations: +#To prevent interruptions, Add ethtool, ip to the sudoers list in remote PC and get the ssh key from remote. +#Required minimum ethtool version is 6.10 +#Change the below configuration based on your hw needs. +# """Default values""" +#time_delay = 8 #time taken to wait for transitions to happen, in seconds. +#test_duration = 10 #performance test duration for the throughput check, in seconds. +#send_throughput_threshold = 80 #percentage of send throughput required to pass the check +#receive_throughput_threshold = 50 #percentage of receive throughput required to pass the check + +import time +import json +import argparse +from lib.py import ksft_run, ksft_exit, ksft_pr, ksft_true +from lib.py import KsftFailEx, KsftSkipEx, GenerateTraffic +from lib.py import NetDrvEpEnv, bkg, wait_port_listen +from lib.py import cmd +from lib.py import LinkConfig + +class TestConfig: + def __init__(self, time_delay: int, test_duration: int, send_throughput_threshold: int, receive_throughput_threshold: int) -> None: + self.time_delay = time_delay + self.test_duration = test_duration + self.send_throughput_threshold = send_throughput_threshold + self.receive_throughput_threshold = receive_throughput_threshold + +def _pre_test_checks(cfg: object, link_config: LinkConfig) -> None: + if not link_config.verify_link_up(): + KsftSkipEx(f"Link state of interface {cfg.ifname} is DOWN") + common_link_modes = link_config.common_link_modes + if common_link_modes is None: + KsftSkipEx("No common link modes found") + if link_config.partner_netif == None: + KsftSkipEx("Partner interface is not available") + if link_config.check_autoneg_supported(): + KsftSkipEx("Auto-negotiation not supported by local") + if link_config.check_autoneg_supported(remote=True): + KsftSkipEx("Auto-negotiation not supported by remote") + cfg.require_cmd("iperf3", remote=True) + +def check_throughput(cfg: object, link_config: LinkConfig, test_config: TestConfig, protocol: str, traffic: GenerateTraffic) -> None: + common_link_modes = link_config.common_link_modes + speeds, duplex_modes = link_config.get_speed_duplex_values(common_link_modes) + """Test duration in seconds""" + duration = test_config.test_duration + + ksft_pr(f"{protocol} test") + test_type = "-u" if protocol == "UDP" else "" + + send_throughput = [] + receive_throughput = [] + for idx in range(0, len(speeds)): + if link_config.set_speed_and_duplex(speeds[idx], duplex_modes[idx]) == False: + raise KsftFailEx(f"Not able to set speed and duplex parameters for {cfg.ifname}") + time.sleep(test_config.time_delay) + if not link_config.verify_link_up(): + raise KsftSkipEx(f"Link state of interface {cfg.ifname} is DOWN") + + send_command=f"{test_type} -b 0 -t {duration} --json" + receive_command=f"{test_type} -b 0 -t {duration} --reverse --json" + + send_result = traffic.run_remote_test(cfg, command=send_command) + if send_result.ret != 0: + raise KsftSkipEx("Error occurred during data transmit: {send_result.stdout}") + + send_output = send_result.stdout + send_data = json.loads(send_output) + + """Convert throughput to Mbps""" + send_throughput.append(round(send_data['end']['sum_sent']['bits_per_second'] / 1e6, 2)) + ksft_pr(f"{protocol}: Send throughput: {send_throughput[idx]} Mbps") + + receive_result = traffic.run_remote_test(cfg, command=receive_command) + if receive_result.ret != 0: + raise KsftSkipEx("Error occurred during data receive: {receive_result.stdout}") + + receive_output = receive_result.stdout + receive_data = json.loads(receive_output) + + """Convert throughput to Mbps""" + receive_throughput.append(round(receive_data['end']['sum_received']['bits_per_second'] / 1e6, 2)) + ksft_pr(f"{protocol}: Receive throughput: {receive_throughput[idx]} Mbps") + + """Check whether throughput is not below the threshold (default values set at start)""" + for idx in range(0, len(speeds)): + send_threshold = float(speeds[idx]) * float(test_config.send_throughput_threshold / 100) + receive_threshold = float(speeds[idx]) * float(test_config.receive_throughput_threshold / 100) + ksft_true(send_throughput[idx] >= send_threshold, f"{protocol}: Send throughput is below threshold for {speeds[idx]} Mbps in {duplex_modes[idx]} duplex") + ksft_true(receive_throughput[idx] >= receive_threshold, f"{protocol}: Receive throughput is below threshold for {speeds[idx]} Mbps in {duplex_modes[idx]} duplex") + +def test_tcp_throughput(cfg: object, link_config: LinkConfig, test_config: TestConfig, traffic: GenerateTraffic) -> None: + _pre_test_checks(cfg, link_config) + check_throughput(cfg, link_config, test_config, 'TCP', traffic) + +def test_udp_throughput(cfg: object, link_config: LinkConfig, test_config: TestConfig, traffic: GenerateTraffic) -> None: + _pre_test_checks(cfg, link_config) + check_throughput(cfg, link_config, test_config, 'UDP', traffic) + +def main() -> None: + parser = argparse.ArgumentParser(description="Run basic performance test for NIC driver") + parser.add_argument('--time-delay', type=int, default=8, help='Time taken to wait for transitions to happen(in seconds). Default is 8 seconds.') + parser.add_argument('--test-duration', type=int, default=10, help='Performance test duration for the throughput check, in seconds. Default is 10 seconds.') + parser.add_argument('--stt', type=int, default=80, help='Send throughput Threshold: Percentage of send throughput upon actual throughput required to pass the throughput check (in percentage). Default is 80.') + parser.add_argument('--rtt', type=int, default=50, help='Receive throughput Threshold: Percentage of receive throughput upon actual throughput required to pass the throughput check (in percentage). Default is 50.') + args=parser.parse_args() + test_config = TestConfig(args.time_delay, args.test_duration, args.stt, args.rtt) + with NetDrvEpEnv(__file__, nsim_test=False) as cfg: + traffic = GenerateTraffic(cfg) + link_config = LinkConfig(cfg) + ksft_run(globs=globals(), case_pfx={"test_"}, args=(cfg, link_config, test_config, traffic, )) + link_config.reset_interface() + ksft_exit() + +if __name__ == "__main__": + main() diff --git a/tools/testing/selftests/drivers/net/lib/py/load.py b/tools/testing/selftests/drivers/net/lib/py/load.py index d9c10613ae67..da5af2c680fa 100644 --- a/tools/testing/selftests/drivers/net/lib/py/load.py +++ b/tools/testing/selftests/drivers/net/lib/py/load.py @@ -2,7 +2,7 @@ import time -from lib.py import ksft_pr, cmd, ip, rand_port, wait_port_listen +from lib.py import ksft_pr, cmd, ip, rand_port, wait_port_listen, bkg class GenerateTraffic: def __init__(self, env, port=None): @@ -23,6 +23,24 @@ class GenerateTraffic: self.stop(verbose=True) raise Exception("iperf3 traffic did not ramp up") + def run_remote_test(self, env: object, port=None, command=None): + if port is None: + port = rand_port() + try: + server_cmd = f"iperf3 -s 1 -p {port} --one-off" + with bkg(server_cmd, host=env.remote): + #iperf3 opens TCP connection as default in server + #-u to be specified in client command for UDP + wait_port_listen(port, host=env.remote) + except Exception as e: + raise Exception(f"Unexpected error occurred while running server command: {e}") + try: + client_cmd = f"iperf3 -c {env.remote_addr} -p {port} {command}" + proc = cmd(client_cmd) + return proc + except Exception as e: + raise Exception(f"Unexpected error occurred while running client command: {e}") + def _wait_pkts(self, pkt_cnt=None, pps=None): """ Wait until we've seen pkt_cnt or until traffic ramps up to pps. -- 2.51.0