Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1086486/?format=api
{ "id": 1086486, "url": "http://patchwork.ozlabs.org/api/patches/1086486/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20190416173052.28928-7-anirudh.venkataramanan@intel.com/", "project": { "id": 46, "url": "http://patchwork.ozlabs.org/api/projects/46/?format=api", "name": "Intel Wired Ethernet development", "link_name": "intel-wired-lan", "list_id": "intel-wired-lan.osuosl.org", "list_email": "intel-wired-lan@osuosl.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20190416173052.28928-7-anirudh.venkataramanan@intel.com>", "list_archive_url": null, "date": "2019-04-16T17:30:43", "name": "[S20,06/15] ice: Add handler for ethtool selftest", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "04b7c8ac6c515797cfad8b8eefe076f9b3de6a39", "submitter": { "id": 73601, "url": "http://patchwork.ozlabs.org/api/people/73601/?format=api", "name": "Anirudh Venkataramanan", "email": "anirudh.venkataramanan@intel.com" }, "delegate": { "id": 68, "url": "http://patchwork.ozlabs.org/api/users/68/?format=api", "username": "jtkirshe", "first_name": "Jeff", "last_name": "Kirsher", "email": "jeffrey.t.kirsher@intel.com" }, "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20190416173052.28928-7-anirudh.venkataramanan@intel.com/mbox/", "series": [ { "id": 103108, "url": "http://patchwork.ozlabs.org/api/series/103108/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=103108", "date": "2019-04-16T17:30:37", "name": "Fixes and feature updates for ice", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/103108/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1086486/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1086486/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<intel-wired-lan-bounces@osuosl.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Delivered-To": [ "patchwork-incoming@bilbo.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Authentication-Results": [ "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=osuosl.org\n\t(client-ip=140.211.166.137; helo=fraxinus.osuosl.org;\n\tenvelope-from=intel-wired-lan-bounces@osuosl.org;\n\treceiver=<UNKNOWN>)", "ozlabs.org;\n\tdmarc=fail (p=none dis=none) header.from=intel.com" ], "Received": [ "from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 44kC8s6V0Fz9s55\n\tfor <incoming@patchwork.ozlabs.org>;\n\tWed, 17 Apr 2019 03:31:41 +1000 (AEST)", "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 865B0834FB;\n\tTue, 16 Apr 2019 17:31:40 +0000 (UTC)", "from fraxinus.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id 1vFykuI0tTvD; Tue, 16 Apr 2019 17:31:34 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 5CC1585F35;\n\tTue, 16 Apr 2019 17:31:34 +0000 (UTC)", "from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n\tby ash.osuosl.org (Postfix) with ESMTP id E634B1BF28D\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 16 Apr 2019 17:31:30 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id E32D32206D\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 16 Apr 2019 17:31:30 +0000 (UTC)", "from silver.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id tUN3ZwRONjil for <intel-wired-lan@lists.osuosl.org>;\n\tTue, 16 Apr 2019 17:31:26 +0000 (UTC)", "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n\tby silver.osuosl.org (Postfix) with ESMTPS id B325A23600\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 16 Apr 2019 17:31:26 +0000 (UTC)", "from orsmga002.jf.intel.com ([10.7.209.21])\n\tby orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t16 Apr 2019 10:31:25 -0700", "from shasta.jf.intel.com ([10.166.244.191])\n\tby orsmga002.jf.intel.com with ESMTP; 16 Apr 2019 10:31:25 -0700" ], "X-Virus-Scanned": [ "amavisd-new at osuosl.org", "amavisd-new at osuosl.org" ], "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6", "X-Amp-Result": "SKIPPED(no attachment in message)", "X-Amp-File-Uploaded": "False", "X-ExtLoop1": "1", "X-IronPort-AV": "E=Sophos;i=\"5.60,358,1549958400\"; d=\"scan'208\";a=\"151390480\"", "From": "Anirudh Venkataramanan <anirudh.venkataramanan@intel.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Tue, 16 Apr 2019 10:30:43 -0700", "Message-Id": "<20190416173052.28928-7-anirudh.venkataramanan@intel.com>", "X-Mailer": "git-send-email 2.20.1", "In-Reply-To": "<20190416173052.28928-1-anirudh.venkataramanan@intel.com>", "References": "<20190416173052.28928-1-anirudh.venkataramanan@intel.com>", "MIME-Version": "1.0", "Subject": "[Intel-wired-lan] [PATCH S20 06/15] ice: Add handler for ethtool\n\tselftest", "X-BeenThere": "intel-wired-lan@osuosl.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n\t<intel-wired-lan.osuosl.org>", "List-Unsubscribe": "<https://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=unsubscribe>", "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>", "List-Post": "<mailto:intel-wired-lan@osuosl.org>", "List-Help": "<mailto:intel-wired-lan-request@osuosl.org?subject=help>", "List-Subscribe": "<https://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=subscribe>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "intel-wired-lan-bounces@osuosl.org", "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@osuosl.org>" }, "content": "This patch adds a handler for ethtool selftest. Selftest includes\ntesting link, interrupts, eeprom, registers and packet loopback.\n\nSigned-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com>\n---\n[Anirudh Venkataramanan <anirudh.venkataramanan@intel.com> squashed multiple commits]\n---\n drivers/net/ethernet/intel/ice/ice.h | 8 +\n .../net/ethernet/intel/ice/ice_adminq_cmd.h | 23 +\n drivers/net/ethernet/intel/ice/ice_common.c | 23 +\n drivers/net/ethernet/intel/ice/ice_common.h | 5 +\n drivers/net/ethernet/intel/ice/ice_ethtool.c | 592 ++++++++++++++++++\n .../net/ethernet/intel/ice/ice_hw_autogen.h | 4 +\n drivers/net/ethernet/intel/ice/ice_lib.c | 44 +-\n drivers/net/ethernet/intel/ice/ice_main.c | 33 +-\n drivers/net/ethernet/intel/ice/ice_nvm.c | 31 +\n drivers/net/ethernet/intel/ice/ice_status.h | 1 +\n drivers/net/ethernet/intel/ice/ice_type.h | 1 +\n 11 files changed, 752 insertions(+), 13 deletions(-)", "diff": "diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h\nindex 0555d09614d8..5c5b9e3e9e5c 100644\n--- a/drivers/net/ethernet/intel/ice/ice.h\n+++ b/drivers/net/ethernet/intel/ice/ice.h\n@@ -189,6 +189,7 @@ struct ice_sw {\n };\n \n enum ice_state {\n+\t__ICE_TESTING,\n \t__ICE_DOWN,\n \t__ICE_NEEDS_RESTART,\n \t__ICE_PREPARED_FOR_RESET,\t/* set by driver when prepared */\n@@ -399,6 +400,7 @@ struct ice_pf {\n \tunsigned long tx_timeout_last_recovery;\n \tu32 tx_timeout_recovery_level;\n \tchar int_name[ICE_INT_NAME_STR_LEN];\n+\tu32 sw_int_count;\n };\n \n struct ice_netdev_priv {\n@@ -451,9 +453,13 @@ ice_find_vsi_by_type(struct ice_pf *pf, enum ice_vsi_type type)\n \treturn NULL;\n }\n \n+int ice_vsi_setup_tx_rings(struct ice_vsi *vsi);\n+int ice_vsi_setup_rx_rings(struct ice_vsi *vsi);\n void ice_set_ethtool_ops(struct net_device *netdev);\n int ice_up(struct ice_vsi *vsi);\n int ice_down(struct ice_vsi *vsi);\n+int ice_vsi_cfg(struct ice_vsi *vsi);\n+struct ice_vsi *ice_lb_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi);\n int ice_set_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size);\n int ice_get_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size);\n void ice_fill_rss_lut(u8 *lut, u16 rss_table_size, u16 rss_size);\n@@ -462,5 +468,7 @@ void ice_print_link_msg(struct ice_vsi *vsi, bool isup);\n int ice_pf_ena_all_vsi(struct ice_pf *pf, bool locked);\n void ice_pf_dis_all_vsi(struct ice_pf *pf, bool locked);\n #endif /* CONFIG_DCB */\n+int ice_open(struct net_device *netdev);\n+int ice_stop(struct net_device *netdev);\n \n #endif /* _ICE_H_ */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\nindex 6ef083002f5b..99eeee930dfa 100644\n--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\n+++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\n@@ -1112,6 +1112,14 @@ struct ice_aqc_set_event_mask {\n \tu8\treserved1[6];\n };\n \n+/* Set MAC Loopback command (direct 0x0620) */\n+struct ice_aqc_set_mac_lb {\n+\tu8 lb_mode;\n+#define ICE_AQ_MAC_LB_EN\t\tBIT(0)\n+#define ICE_AQ_MAC_LB_OSC_CLK\t\tBIT(1)\n+\tu8 reserved[15];\n+};\n+\n /* Set Port Identification LED (direct, 0x06E9) */\n struct ice_aqc_set_port_id_led {\n \tu8 lport_num;\n@@ -1145,6 +1153,17 @@ struct ice_aqc_nvm {\n \t__le32 addr_low;\n };\n \n+/* NVM Checksum Command (direct, 0x0706) */\n+struct ice_aqc_nvm_checksum {\n+\tu8 flags;\n+#define ICE_AQC_NVM_CHECKSUM_VERIFY\tBIT(0)\n+#define ICE_AQC_NVM_CHECKSUM_RECALC\tBIT(1)\n+\tu8 rsvd;\n+\t__le16 checksum; /* Used only by response */\n+#define ICE_AQC_NVM_CHECKSUM_CORRECT\t0xBABA\n+\tu8 rsvd2[12];\n+};\n+\n /**\n * Send to PF command (indirect 0x0801) ID is only used by PF\n *\n@@ -1539,6 +1558,7 @@ struct ice_aq_desc {\n \t\tstruct ice_aqc_query_txsched_res query_sched_res;\n \t\tstruct ice_aqc_query_port_ets port_ets;\n \t\tstruct ice_aqc_nvm nvm;\n+\t\tstruct ice_aqc_nvm_checksum nvm_checksum;\n \t\tstruct ice_aqc_pf_vf_msg virt;\n \t\tstruct ice_aqc_lldp_get_mib lldp_get_mib;\n \t\tstruct ice_aqc_lldp_set_mib_change lldp_set_event;\n@@ -1554,6 +1574,7 @@ struct ice_aq_desc {\n \t\tstruct ice_aqc_add_update_free_vsi_resp add_update_free_vsi_res;\n \t\tstruct ice_aqc_fw_logging fw_logging;\n \t\tstruct ice_aqc_get_clear_fw_log get_clear_fw_log;\n+\t\tstruct ice_aqc_set_mac_lb set_mac_lb;\n \t\tstruct ice_aqc_alloc_free_res_cmd sw_res_ctrl;\n \t\tstruct ice_aqc_set_event_mask set_event_mask;\n \t\tstruct ice_aqc_get_link_status get_link_status;\n@@ -1642,10 +1663,12 @@ enum ice_adminq_opc {\n \tice_aqc_opc_restart_an\t\t\t\t= 0x0605,\n \tice_aqc_opc_get_link_status\t\t\t= 0x0607,\n \tice_aqc_opc_set_event_mask\t\t\t= 0x0613,\n+\tice_aqc_opc_set_mac_lb\t\t\t\t= 0x0620,\n \tice_aqc_opc_set_port_id_led\t\t\t= 0x06E9,\n \n \t/* NVM commands */\n \tice_aqc_opc_nvm_read\t\t\t\t= 0x0701,\n+\tice_aqc_opc_nvm_checksum\t\t\t= 0x0706,\n \n \t/* PF/VF mailbox commands */\n \tice_mbx_opc_send_msg_to_pf\t\t\t= 0x0801,\ndiff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c\nindex a14c6ec219b3..2826711873d1 100644\n--- a/drivers/net/ethernet/intel/ice/ice_common.c\n+++ b/drivers/net/ethernet/intel/ice/ice_common.c\n@@ -2169,6 +2169,29 @@ ice_aq_set_event_mask(struct ice_hw *hw, u8 port_num, u16 mask,\n \treturn ice_aq_send_cmd(hw, &desc, NULL, 0, cd);\n }\n \n+/**\n+ * ice_aq_set_mac_loopback\n+ * @hw: pointer to the HW struct\n+ * @ena_lpbk: Enable or Disable loopback\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * Enable/disable loopback on a given port\n+ */\n+enum ice_status\n+ice_aq_set_mac_loopback(struct ice_hw *hw, bool ena_lpbk, struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aqc_set_mac_lb *cmd;\n+\tstruct ice_aq_desc desc;\n+\n+\tcmd = &desc.params.set_mac_lb;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_lb);\n+\tif (ena_lpbk)\n+\t\tcmd->lb_mode = ICE_AQ_MAC_LB_EN;\n+\n+\treturn ice_aq_send_cmd(hw, &desc, NULL, 0, cd);\n+}\n+\n /**\n * ice_aq_set_port_id_led\n * @pi: pointer to the port information\ndiff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h\nindex f1ddebf45231..9773d7b2e9c9 100644\n--- a/drivers/net/ethernet/intel/ice/ice_common.h\n+++ b/drivers/net/ethernet/intel/ice/ice_common.h\n@@ -9,6 +9,8 @@\n #include \"ice_switch.h\"\n #include <linux/avf/virtchnl.h>\n \n+enum ice_status ice_nvm_validate_checksum(struct ice_hw *hw);\n+\n void\n ice_debug_cq(struct ice_hw *hw, u32 mask, void *desc, void *buf, u16 buf_len);\n enum ice_status ice_init_hw(struct ice_hw *hw);\n@@ -94,6 +96,9 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,\n enum ice_status\n ice_aq_set_event_mask(struct ice_hw *hw, u8 port_num, u16 mask,\n \t\t struct ice_sq_cd *cd);\n+enum ice_status\n+ice_aq_set_mac_loopback(struct ice_hw *hw, bool ena_lpbk, struct ice_sq_cd *cd);\n+\n enum ice_status\n ice_aq_set_port_id_led(struct ice_port_info *pi, bool is_orig_mode,\n \t\t struct ice_sq_cd *cd);\ndiff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c\nindex 1214325eb80b..9dd628e20091 100644\n--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c\n+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c\n@@ -61,6 +61,24 @@ static const struct ice_stats ice_gstrings_vsi_stats[] = {\n \tICE_VSI_STAT(\"tx_linearize\", tx_linearize),\n };\n \n+enum ice_ethtool_test_id {\n+\tICE_ETH_TEST_REG = 0,\n+\tICE_ETH_TEST_EEPROM,\n+\tICE_ETH_TEST_INTR,\n+\tICE_ETH_TEST_LOOP,\n+\tICE_ETH_TEST_LINK,\n+};\n+\n+static const char ice_gstrings_test[][ETH_GSTRING_LEN] = {\n+\t\"Register test (offline)\",\n+\t\"EEPROM test (offline)\",\n+\t\"Interrupt test (offline)\",\n+\t\"Loopback test (offline)\",\n+\t\"Link test (on/offline)\",\n+};\n+\n+#define ICE_TEST_LEN (sizeof(ice_gstrings_test) / ETH_GSTRING_LEN)\n+\n /* These PF_STATs might look like duplicates of some NETDEV_STATs,\n * but they aren't. This device is capable of supporting multiple\n * VSIs/netdevs on a single PF. The NETDEV_STATs are for individual\n@@ -120,6 +138,9 @@ static const u32 ice_regs_dump_list[] = {\n \tQINT_RQCTL(0),\n \tPFINT_OICR_ENA,\n \tQRX_ITR(0),\n+\tPF0INT_ITR_0(0),\n+\tPF0INT_ITR_1(0),\n+\tPF0INT_ITR_2(0),\n };\n \n struct ice_priv_flag {\n@@ -278,6 +299,571 @@ ice_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,\n \treturn ret;\n }\n \n+/**\n+ * ice_active_vfs - check if there are any active VFs\n+ * @pf: board private structure\n+ *\n+ * Returns true if an active VF is found, otherwise returns false\n+ */\n+static bool ice_active_vfs(struct ice_pf *pf)\n+{\n+\tstruct ice_vf *vf = pf->vf;\n+\tint i;\n+\n+\tfor (i = 0; i < pf->num_alloc_vfs; i++, vf++)\n+\t\tif (test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))\n+\t\t\treturn true;\n+\treturn false;\n+}\n+\n+/**\n+ * ice_link_test - perform a link test on a given net_device\n+ * @netdev: network interface device structure\n+ *\n+ * This function performs one of the self-tests required by ethtool.\n+ * Returns 0 on success, non-zero on failure.\n+ */\n+static u64 ice_link_test(struct net_device *netdev)\n+{\n+\tstruct ice_netdev_priv *np = netdev_priv(netdev);\n+\tenum ice_status status;\n+\tbool link_up = false;\n+\n+\tnetdev_info(netdev, \"link test\\n\");\n+\tstatus = ice_get_link_status(np->vsi->port_info, &link_up);\n+\tif (status) {\n+\t\tnetdev_err(netdev, \"link query error, status = %d\\n\", status);\n+\t\treturn 1;\n+\t}\n+\n+\tif (!link_up)\n+\t\treturn 2;\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_eeprom_test - perform an EEPROM test on a given net_device\n+ * @netdev: network interface device structure\n+ *\n+ * This function performs one of the self-tests required by ethtool.\n+ * Returns 0 on success, non-zero on failure.\n+ */\n+static u64 ice_eeprom_test(struct net_device *netdev)\n+{\n+\tstruct ice_netdev_priv *np = netdev_priv(netdev);\n+\tstruct ice_pf *pf = np->vsi->back;\n+\n+\tnetdev_info(netdev, \"EEPROM test\\n\");\n+\treturn !!(ice_nvm_validate_checksum(&pf->hw));\n+}\n+\n+/**\n+ * ice_reg_pattern_test\n+ * @hw: pointer to the HW struct\n+ * @reg: reg to be tested\n+ * @mask: bits to be touched\n+ */\n+static int ice_reg_pattern_test(struct ice_hw *hw, u32 reg, u32 mask)\n+{\n+\tstruct ice_pf *pf = (struct ice_pf *)hw->back;\n+\tstatic const u32 patterns[] = {\n+\t\t0x5A5A5A5A, 0xA5A5A5A5,\n+\t\t0x00000000, 0xFFFFFFFF\n+\t};\n+\tu32 val, orig_val;\n+\tint i;\n+\n+\torig_val = rd32(hw, reg);\n+\tfor (i = 0; i < ARRAY_SIZE(patterns); ++i) {\n+\t\tu32 pattern = patterns[i] & mask;\n+\n+\t\twr32(hw, reg, pattern);\n+\t\tval = rd32(hw, reg);\n+\t\tif (val == pattern)\n+\t\t\tcontinue;\n+\t\tdev_err(&pf->pdev->dev,\n+\t\t\t\"%s: reg pattern test failed - reg 0x%08x pat 0x%08x val 0x%08x\\n\"\n+\t\t\t, __func__, reg, pattern, val);\n+\t\treturn 1;\n+\t}\n+\n+\twr32(hw, reg, orig_val);\n+\tval = rd32(hw, reg);\n+\tif (val != orig_val) {\n+\t\tdev_err(&pf->pdev->dev,\n+\t\t\t\"%s: reg restore test failed - reg 0x%08x orig 0x%08x val 0x%08x\\n\"\n+\t\t\t, __func__, reg, orig_val, val);\n+\t\treturn 1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_reg_test - perform a register test on a given net_device\n+ * @netdev: network interface device structure\n+ *\n+ * This function performs one of the self-tests required by ethtool.\n+ * Returns 0 on success, non-zero on failure.\n+ */\n+static u64 ice_reg_test(struct net_device *netdev)\n+{\n+\tstruct ice_netdev_priv *np = netdev_priv(netdev);\n+\tstruct ice_hw *hw = np->vsi->port_info->hw;\n+\tu32 int_elements = hw->func_caps.common_cap.num_msix_vectors ?\n+\t\thw->func_caps.common_cap.num_msix_vectors - 1 : 1;\n+\tstruct ice_diag_reg_test_info {\n+\t\tu32 address;\n+\t\tu32 mask;\n+\t\tu32 elem_num;\n+\t\tu32 elem_size;\n+\t} ice_reg_list[] = {\n+\t\t{GLINT_ITR(0, 0), 0x00000fff, int_elements,\n+\t\t\tGLINT_ITR(0, 1) - GLINT_ITR(0, 0)},\n+\t\t{GLINT_ITR(1, 0), 0x00000fff, int_elements,\n+\t\t\tGLINT_ITR(1, 1) - GLINT_ITR(1, 0)},\n+\t\t{GLINT_ITR(0, 0), 0x00000fff, int_elements,\n+\t\t\tGLINT_ITR(2, 1) - GLINT_ITR(2, 0)},\n+\t\t{GLINT_CTL, 0xffff0001, 1, 0}\n+\t};\n+\tint i;\n+\n+\tnetdev_dbg(netdev, \"Register test\\n\");\n+\tfor (i = 0; i < ARRAY_SIZE(ice_reg_list); ++i) {\n+\t\tu32 j;\n+\n+\t\tfor (j = 0; j < ice_reg_list[i].elem_num; ++j) {\n+\t\t\tu32 mask = ice_reg_list[i].mask;\n+\t\t\tu32 reg = ice_reg_list[i].address +\n+\t\t\t\t(j * ice_reg_list[i].elem_size);\n+\n+\t\t\t/* bail on failure (non-zero return) */\n+\t\t\tif (ice_reg_pattern_test(hw, reg, mask))\n+\t\t\t\treturn 1;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_lbtest_prepare_rings - configure Tx/Rx test rings\n+ * @vsi: pointer to the VSI structure\n+ *\n+ * Function configures rings of a VSI for loopback test without\n+ * enabling interrupts or informing the kernel about new queues.\n+ *\n+ * Returns 0 on success, negative on failure.\n+ */\n+static int ice_lbtest_prepare_rings(struct ice_vsi *vsi)\n+{\n+\tint status;\n+\n+\tstatus = ice_vsi_setup_tx_rings(vsi);\n+\tif (status)\n+\t\tgoto err_setup_tx_ring;\n+\n+\tstatus = ice_vsi_setup_rx_rings(vsi);\n+\tif (status)\n+\t\tgoto err_setup_rx_ring;\n+\n+\tstatus = ice_vsi_cfg(vsi);\n+\tif (status)\n+\t\tgoto err_setup_rx_ring;\n+\n+\tstatus = ice_vsi_start_rx_rings(vsi);\n+\tif (status)\n+\t\tgoto err_start_rx_ring;\n+\n+\treturn status;\n+\n+err_start_rx_ring:\n+\tice_vsi_free_rx_rings(vsi);\n+err_setup_rx_ring:\n+\tice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, 0);\n+err_setup_tx_ring:\n+\tice_vsi_free_tx_rings(vsi);\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_lbtest_disable_rings - disable Tx/Rx test rings after loopback test\n+ * @vsi: pointer to the VSI structure\n+ *\n+ * Function stops and frees VSI rings after a loopback test.\n+ * Returns 0 on success, negative on failure.\n+ */\n+static int ice_lbtest_disable_rings(struct ice_vsi *vsi)\n+{\n+\tint status;\n+\n+\tstatus = ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, 0);\n+\tif (status)\n+\t\tnetdev_err(vsi->netdev, \"Failed to stop Tx rings, VSI %d error %d\\n\",\n+\t\t\t vsi->vsi_num, status);\n+\n+\tstatus = ice_vsi_stop_rx_rings(vsi);\n+\tif (status)\n+\t\tnetdev_err(vsi->netdev, \"Failed to stop Rx rings, VSI %d error %d\\n\",\n+\t\t\t vsi->vsi_num, status);\n+\n+\tice_vsi_free_tx_rings(vsi);\n+\tice_vsi_free_rx_rings(vsi);\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_lbtest_create_frame - create test packet\n+ * @pf: pointer to the PF structure\n+ * @ret_data: allocated frame buffer\n+ * @size: size of the packet data\n+ *\n+ * Function allocates a frame with a test pattern on specific offsets.\n+ * Returns 0 on success, non-zero on failure.\n+ */\n+static int ice_lbtest_create_frame(struct ice_pf *pf, u8 **ret_data, u16 size)\n+{\n+\tu8 *data;\n+\n+\tif (!pf)\n+\t\treturn -EINVAL;\n+\n+\tdata = devm_kzalloc(&pf->pdev->dev, size, GFP_KERNEL);\n+\tif (!data)\n+\t\treturn -ENOMEM;\n+\n+\t/* Since the ethernet test frame should always be at least\n+\t * 64 bytes long, fill some octets in the payload with test data.\n+\t */\n+\tmemset(data, 0xFF, size);\n+\tdata[32] = 0xDE;\n+\tdata[42] = 0xAD;\n+\tdata[44] = 0xBE;\n+\tdata[46] = 0xEF;\n+\n+\t*ret_data = data;\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_lbtest_check_frame - verify received loopback frame\n+ * @frame: pointer to the raw packet data\n+ *\n+ * Function verifies received test frame with a pattern.\n+ * Returns true if frame matches the pattern, false otherwise.\n+ */\n+static bool ice_lbtest_check_frame(u8 *frame)\n+{\n+\t/* Validate bytes of a frame under offsets chosen earlier */\n+\tif (frame[32] == 0xDE &&\n+\t frame[42] == 0xAD &&\n+\t frame[44] == 0xBE &&\n+\t frame[46] == 0xEF &&\n+\t frame[48] == 0xFF)\n+\t\treturn true;\n+\n+\treturn false;\n+}\n+\n+/**\n+ * ice_diag_send - send test frames to the test ring\n+ * @tx_ring: pointer to the transmit ring\n+ * @data: pointer to the raw packet data\n+ * @size: size of the packet to send\n+ *\n+ * Function sends loopback packets on a test Tx ring.\n+ */\n+static int ice_diag_send(struct ice_ring *tx_ring, u8 *data, u16 size)\n+{\n+\tstruct ice_tx_desc *tx_desc;\n+\tstruct ice_tx_buf *tx_buf;\n+\tdma_addr_t dma;\n+\tu64 td_cmd;\n+\n+\ttx_desc = ICE_TX_DESC(tx_ring, tx_ring->next_to_use);\n+\ttx_buf = &tx_ring->tx_buf[tx_ring->next_to_use];\n+\n+\tdma = dma_map_single(tx_ring->dev, data, size, DMA_TO_DEVICE);\n+\tif (dma_mapping_error(tx_ring->dev, dma))\n+\t\treturn -EINVAL;\n+\n+\ttx_desc->buf_addr = cpu_to_le64(dma);\n+\n+\t/* These flags are required for a descriptor to be pushed out */\n+\ttd_cmd = (u64)(ICE_TX_DESC_CMD_EOP | ICE_TX_DESC_CMD_RS);\n+\ttx_desc->cmd_type_offset_bsz =\n+\t\tcpu_to_le64(ICE_TX_DESC_DTYPE_DATA |\n+\t\t\t (td_cmd << ICE_TXD_QW1_CMD_S) |\n+\t\t\t ((u64)0 << ICE_TXD_QW1_OFFSET_S) |\n+\t\t\t ((u64)size << ICE_TXD_QW1_TX_BUF_SZ_S) |\n+\t\t\t ((u64)0 << ICE_TXD_QW1_L2TAG1_S));\n+\n+\ttx_buf->next_to_watch = tx_desc;\n+\n+\t/* Force memory write to complete before letting h/w know\n+\t * there are new descriptors to fetch.\n+\t */\n+\twmb();\n+\n+\ttx_ring->next_to_use++;\n+\tif (tx_ring->next_to_use >= tx_ring->count)\n+\t\ttx_ring->next_to_use = 0;\n+\n+\twritel_relaxed(tx_ring->next_to_use, tx_ring->tail);\n+\n+\t/* Wait until the packets get transmitted to the receive queue. */\n+\tusleep_range(1000, 2000);\n+\tdma_unmap_single(tx_ring->dev, dma, size, DMA_TO_DEVICE);\n+\n+\treturn 0;\n+}\n+\n+#define ICE_LB_FRAME_SIZE 64\n+/**\n+ * ice_lbtest_receive_frames - receive and verify test frames\n+ * @rx_ring: pointer to the receive ring\n+ *\n+ * Function receives loopback packets and verify their correctness.\n+ * Returns number of received valid frames.\n+ */\n+static int ice_lbtest_receive_frames(struct ice_ring *rx_ring)\n+{\n+\tstruct ice_rx_buf *rx_buf;\n+\tint valid_frames, i;\n+\tu8 *received_buf;\n+\n+\tvalid_frames = 0;\n+\n+\tfor (i = 0; i < rx_ring->count; i++) {\n+\t\tunion ice_32b_rx_flex_desc *rx_desc;\n+\n+\t\trx_desc = ICE_RX_DESC(rx_ring, i);\n+\n+\t\tif (!(rx_desc->wb.status_error0 &\n+\t\t cpu_to_le16(ICE_TX_DESC_CMD_EOP | ICE_TX_DESC_CMD_RS)))\n+\t\t\tcontinue;\n+\n+\t\trx_buf = &rx_ring->rx_buf[i];\n+\t\treceived_buf = page_address(rx_buf->page);\n+\n+\t\tif (ice_lbtest_check_frame(received_buf))\n+\t\t\tvalid_frames++;\n+\t}\n+\n+\treturn valid_frames;\n+}\n+\n+/**\n+ * ice_loopback_test - perform a loopback test on a given net_device\n+ * @netdev: network interface device structure\n+ *\n+ * This function performs one of the self-tests required by ethtool.\n+ * Returns 0 on success, non-zero on failure.\n+ */\n+static u64 ice_loopback_test(struct net_device *netdev)\n+{\n+\tstruct ice_netdev_priv *np = netdev_priv(netdev);\n+\tstruct ice_vsi *orig_vsi = np->vsi, *test_vsi;\n+\tstruct ice_pf *pf = orig_vsi->back;\n+\tstruct ice_ring *tx_ring, *rx_ring;\n+\tu8 broadcast[ETH_ALEN], ret = 0;\n+\tint num_frames, valid_frames;\n+\tLIST_HEAD(tmp_list);\n+\tu8 *tx_frame;\n+\tint i;\n+\n+\tnetdev_info(netdev, \"loopback test\\n\");\n+\n+\ttest_vsi = ice_lb_vsi_setup(pf, pf->hw.port_info);\n+\tif (!test_vsi) {\n+\t\tnetdev_err(netdev, \"Failed to create a VSI for the loopback test\");\n+\t\treturn 1;\n+\t}\n+\n+\ttest_vsi->netdev = netdev;\n+\ttx_ring = test_vsi->tx_rings[0];\n+\trx_ring = test_vsi->rx_rings[0];\n+\n+\tif (ice_lbtest_prepare_rings(test_vsi)) {\n+\t\tret = 2;\n+\t\tgoto lbtest_vsi_close;\n+\t}\n+\n+\tif (ice_alloc_rx_bufs(rx_ring, rx_ring->count)) {\n+\t\tret = 3;\n+\t\tgoto lbtest_rings_dis;\n+\t}\n+\n+\t/* Enable MAC loopback in firmware */\n+\tif (ice_aq_set_mac_loopback(&pf->hw, true, NULL)) {\n+\t\tret = 4;\n+\t\tgoto lbtest_mac_dis;\n+\t}\n+\n+\t/* Test VSI needs to receive broadcast packets */\n+\teth_broadcast_addr(broadcast);\n+\tif (ice_add_mac_to_list(test_vsi, &tmp_list, broadcast)) {\n+\t\tret = 5;\n+\t\tgoto lbtest_mac_dis;\n+\t}\n+\n+\tif (ice_add_mac(&pf->hw, &tmp_list)) {\n+\t\tret = 6;\n+\t\tgoto free_mac_list;\n+\t}\n+\n+\tif (ice_lbtest_create_frame(pf, &tx_frame, ICE_LB_FRAME_SIZE)) {\n+\t\tret = 7;\n+\t\tgoto remove_mac_filters;\n+\t}\n+\n+\tnum_frames = min_t(int, tx_ring->count, 32);\n+\tfor (i = 0; i < num_frames; i++) {\n+\t\tif (ice_diag_send(tx_ring, tx_frame, ICE_LB_FRAME_SIZE)) {\n+\t\t\tret = 8;\n+\t\t\tgoto lbtest_free_frame;\n+\t\t}\n+\t}\n+\n+\tvalid_frames = ice_lbtest_receive_frames(rx_ring);\n+\tif (!valid_frames)\n+\t\tret = 9;\n+\telse if (valid_frames != num_frames)\n+\t\tret = 10;\n+\n+lbtest_free_frame:\n+\tdevm_kfree(&pf->pdev->dev, tx_frame);\n+remove_mac_filters:\n+\tif (ice_remove_mac(&pf->hw, &tmp_list))\n+\t\tnetdev_err(netdev, \"Could not remove MAC filter for the test VSI\");\n+free_mac_list:\n+\tice_free_fltr_list(&pf->pdev->dev, &tmp_list);\n+lbtest_mac_dis:\n+\t/* Disable MAC loopback after the test is completed. */\n+\tif (ice_aq_set_mac_loopback(&pf->hw, false, NULL))\n+\t\tnetdev_err(netdev, \"Could not disable MAC loopback\\n\");\n+lbtest_rings_dis:\n+\tif (ice_lbtest_disable_rings(test_vsi))\n+\t\tnetdev_err(netdev, \"Could not disable test rings\\n\");\n+lbtest_vsi_close:\n+\ttest_vsi->netdev = NULL;\n+\tif (ice_vsi_release(test_vsi))\n+\t\tnetdev_err(netdev, \"Failed to remove the test VSI\");\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * ice_intr_test - perform an interrupt test on a given net_device\n+ * @netdev: network interface device structure\n+ *\n+ * This function performs one of the self-tests required by ethtool.\n+ * Returns 0 on success, non-zero on failure.\n+ */\n+static u64 ice_intr_test(struct net_device *netdev)\n+{\n+\tstruct ice_netdev_priv *np = netdev_priv(netdev);\n+\tstruct ice_pf *pf = np->vsi->back;\n+\tu16 swic_old = pf->sw_int_count;\n+\n+\tnetdev_info(netdev, \"interrupt test\\n\");\n+\n+\twr32(&pf->hw, GLINT_DYN_CTL(pf->sw_oicr_idx),\n+\t GLINT_DYN_CTL_SW_ITR_INDX_M |\n+\t GLINT_DYN_CTL_INTENA_MSK_M |\n+\t GLINT_DYN_CTL_SWINT_TRIG_M);\n+\n+\tusleep_range(1000, 2000);\n+\treturn (swic_old == pf->sw_int_count);\n+}\n+\n+/**\n+ * ice_self_test - handler function for performing a self-test by ethtool\n+ * @netdev: network interface device structure\n+ * @eth_test: ethtool_test structure\n+ * @data: required by ethtool.self_test\n+ *\n+ * This function is called after invoking 'ethtool -t devname' command where\n+ * devname is the name of the network device on which ethtool should operate.\n+ * It performs a set of self-tests to check if a device works properly.\n+ */\n+static void\n+ice_self_test(struct net_device *netdev, struct ethtool_test *eth_test,\n+\t u64 *data)\n+{\n+\tstruct ice_netdev_priv *np = netdev_priv(netdev);\n+\tbool if_running = netif_running(netdev);\n+\tstruct ice_pf *pf = np->vsi->back;\n+\n+\tif (eth_test->flags == ETH_TEST_FL_OFFLINE) {\n+\t\tnetdev_info(netdev, \"offline testing starting\\n\");\n+\n+\t\tset_bit(__ICE_TESTING, pf->state);\n+\n+\t\tif (ice_active_vfs(pf)) {\n+\t\t\tdev_warn(&pf->pdev->dev,\n+\t\t\t\t \"Please take active VFs and Netqueues offline and restart the adapter before running NIC diagnostics\\n\");\n+\t\t\tdata[ICE_ETH_TEST_REG] = 1;\n+\t\t\tdata[ICE_ETH_TEST_EEPROM] = 1;\n+\t\t\tdata[ICE_ETH_TEST_INTR] = 1;\n+\t\t\tdata[ICE_ETH_TEST_LOOP] = 1;\n+\t\t\tdata[ICE_ETH_TEST_LINK] = 1;\n+\t\t\teth_test->flags |= ETH_TEST_FL_FAILED;\n+\t\t\tclear_bit(__ICE_TESTING, pf->state);\n+\t\t\tgoto skip_ol_tests;\n+\t\t}\n+\t\t/* If the device is online then take it offline */\n+\t\tif (if_running)\n+\t\t\t/* indicate we're in test mode */\n+\t\t\tice_stop(netdev);\n+\n+\t\tdata[ICE_ETH_TEST_LINK] = ice_link_test(netdev);\n+\t\tdata[ICE_ETH_TEST_EEPROM] = ice_eeprom_test(netdev);\n+\t\tdata[ICE_ETH_TEST_INTR] = ice_intr_test(netdev);\n+\t\tdata[ICE_ETH_TEST_LOOP] = ice_loopback_test(netdev);\n+\t\tdata[ICE_ETH_TEST_REG] = ice_reg_test(netdev);\n+\n+\t\tif (data[ICE_ETH_TEST_LINK] ||\n+\t\t data[ICE_ETH_TEST_EEPROM] ||\n+\t\t data[ICE_ETH_TEST_LOOP] ||\n+\t\t data[ICE_ETH_TEST_INTR] ||\n+\t\t data[ICE_ETH_TEST_REG])\n+\t\t\teth_test->flags |= ETH_TEST_FL_FAILED;\n+\n+\t\tclear_bit(__ICE_TESTING, pf->state);\n+\n+\t\tif (if_running) {\n+\t\t\tint status = ice_open(netdev);\n+\n+\t\t\tif (status) {\n+\t\t\t\tdev_err(&pf->pdev->dev,\n+\t\t\t\t\t\"Could not open device %s, err %d\",\n+\t\t\t\t\tpf->int_name, status);\n+\t\t\t}\n+\t\t}\n+\t} else {\n+\t\t/* Online tests */\n+\t\tnetdev_info(netdev, \"online testing starting\\n\");\n+\n+\t\tdata[ICE_ETH_TEST_LINK] = ice_link_test(netdev);\n+\t\tif (data[ICE_ETH_TEST_LINK])\n+\t\t\teth_test->flags |= ETH_TEST_FL_FAILED;\n+\n+\t\t/* Offline only tests, not run in online; pass by default */\n+\t\tdata[ICE_ETH_TEST_REG] = 0;\n+\t\tdata[ICE_ETH_TEST_EEPROM] = 0;\n+\t\tdata[ICE_ETH_TEST_INTR] = 0;\n+\t\tdata[ICE_ETH_TEST_LOOP] = 0;\n+\t}\n+\n+skip_ol_tests:\n+\tnetdev_info(netdev, \"testing finished\\n\");\n+}\n+\n static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data)\n {\n \tstruct ice_netdev_priv *np = netdev_priv(netdev);\n@@ -335,6 +921,9 @@ static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data)\n \t\t\tp += ETH_GSTRING_LEN;\n \t\t}\n \t\tbreak;\n+\tcase ETH_SS_TEST:\n+\t\tmemcpy(data, ice_gstrings_test, ICE_TEST_LEN * ETH_GSTRING_LEN);\n+\t\tbreak;\n \tcase ETH_SS_PRIV_FLAGS:\n \t\tfor (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) {\n \t\t\tsnprintf(p, ETH_GSTRING_LEN, \"%s\",\n@@ -529,6 +1118,8 @@ static int ice_get_sset_count(struct net_device *netdev, int sset)\n \t\t * not safe.\n \t\t */\n \t\treturn ICE_ALL_STATS_LEN(netdev);\n+\tcase ETH_SS_TEST:\n+\t\treturn ICE_TEST_LEN;\n \tcase ETH_SS_PRIV_FLAGS:\n \t\treturn ICE_PRIV_FLAG_ARRAY_SIZE;\n \tdefault:\n@@ -2558,6 +3149,7 @@ static const struct ethtool_ops ice_ethtool_ops = {\n \t.get_regs = ice_get_regs,\n \t.get_msglevel = ice_get_msglevel,\n \t.set_msglevel = ice_set_msglevel,\n+\t.self_test\t\t= ice_self_test,\n \t.get_link\t\t= ethtool_op_get_link,\n \t.get_eeprom_len\t\t= ice_get_eeprom_len,\n \t.get_eeprom\t\t= ice_get_eeprom,\ndiff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h\nindex ec25f26069b0..6c5ce05742b1 100644\n--- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h\n+++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h\n@@ -6,6 +6,9 @@\n #ifndef _ICE_HW_AUTOGEN_H_\n #define _ICE_HW_AUTOGEN_H_\n \n+#define PF0INT_ITR_0(_i)\t\t\t(0x03000004 + ((_i) * 4096))\n+#define PF0INT_ITR_1(_i)\t\t\t(0x03000008 + ((_i) * 4096))\n+#define PF0INT_ITR_2(_i)\t\t\t(0x0300000C + ((_i) * 4096))\n #define QTX_COMM_DBELL(_DBQM)\t\t\t(0x002C0000 + ((_DBQM) * 4))\n #define QTX_COMM_HEAD(_DBQM)\t\t\t(0x000E0000 + ((_DBQM) * 4))\n #define QTX_COMM_HEAD_HEAD_S\t\t\t0\n@@ -155,6 +158,7 @@\n #define PFINT_OICR_HMC_ERR_M\t\t\tBIT(26)\n #define PFINT_OICR_PE_CRITERR_M\t\t\tBIT(28)\n #define PFINT_OICR_VFLR_M\t\t\tBIT(29)\n+#define PFINT_OICR_SWINT_M\t\t\tBIT(31)\n #define PFINT_OICR_CTL\t\t\t\t0x0016CA80\n #define PFINT_OICR_CTL_MSIX_INDX_M\t\tICE_M(0x7FF, 0)\n #define PFINT_OICR_CTL_ITR_INDX_S\t\t11\ndiff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c\nindex 749d36add524..95323ee49e58 100644\n--- a/drivers/net/ethernet/intel/ice/ice_lib.c\n+++ b/drivers/net/ethernet/intel/ice/ice_lib.c\n@@ -137,6 +137,8 @@ ice_setup_tx_ctx(struct ice_ring *ring, struct ice_tlan_ctx *tlan_ctx, u16 pf_q)\n \t * for PF or EMP this field should be set to zero\n \t */\n \tswitch (vsi->type) {\n+\tcase ICE_VSI_LB:\n+\t\t/* fall through */\n \tcase ICE_VSI_PF:\n \t\ttlan_ctx->vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_PF;\n \t\tbreak;\n@@ -251,6 +253,10 @@ static int ice_vsi_alloc_arrays(struct ice_vsi *vsi)\n \tif (!vsi->rx_rings)\n \t\tgoto err_rxrings;\n \n+\t/* There is no need to allocate q_vectors for a loopback VSI. */\n+\tif (vsi->type == ICE_VSI_LB)\n+\t\treturn 0;\n+\n \t/* allocate memory for q_vector pointers */\n \tvsi->q_vectors = devm_kcalloc(&pf->pdev->dev, vsi->num_q_vectors,\n \t\t\t\t sizeof(*vsi->q_vectors), GFP_KERNEL);\n@@ -275,6 +281,8 @@ static void ice_vsi_set_num_desc(struct ice_vsi *vsi)\n {\n \tswitch (vsi->type) {\n \tcase ICE_VSI_PF:\n+\t\t/* fall through */\n+\tcase ICE_VSI_LB:\n \t\tvsi->num_rx_desc = ICE_DFLT_NUM_RX_DESC;\n \t\tvsi->num_tx_desc = ICE_DFLT_NUM_TX_DESC;\n \t\tbreak;\n@@ -318,6 +326,10 @@ static void ice_vsi_set_num_qs(struct ice_vsi *vsi, u16 vf_id)\n \t\t */\n \t\tvsi->num_q_vectors = pf->num_vf_msix - 1;\n \t\tbreak;\n+\tcase ICE_VSI_LB:\n+\t\tvsi->alloc_txq = 1;\n+\t\tvsi->alloc_rxq = 1;\n+\t\tbreak;\n \tdefault:\n \t\tdev_warn(&pf->pdev->dev, \"Unknown VSI type %d\\n\", vsi->type);\n \t\tbreak;\n@@ -516,6 +528,10 @@ ice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type type, u16 vf_id)\n \t\tif (ice_vsi_alloc_arrays(vsi))\n \t\t\tgoto err_rings;\n \t\tbreak;\n+\tcase ICE_VSI_LB:\n+\t\tif (ice_vsi_alloc_arrays(vsi))\n+\t\t\tgoto err_rings;\n+\t\tbreak;\n \tdefault:\n \t\tdev_warn(&pf->pdev->dev, \"Unknown VSI type %d\\n\", vsi->type);\n \t\tgoto unlock_pf;\n@@ -732,6 +748,8 @@ static void ice_vsi_set_rss_params(struct ice_vsi *vsi)\n \t\t\t\t BIT(cap->rss_table_entry_width));\n \t\tvsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI;\n \t\tbreak;\n+\tcase ICE_VSI_LB:\n+\t\tbreak;\n \tdefault:\n \t\tdev_warn(&pf->pdev->dev, \"Unknown VSI type %d\\n\",\n \t\t\t vsi->type);\n@@ -924,6 +942,9 @@ static void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi)\n \t\tlut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI;\n \t\thash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ;\n \t\tbreak;\n+\tcase ICE_VSI_LB:\n+\t\tdev_dbg(&pf->pdev->dev, \"Unsupported VSI type %d\\n\", vsi->type);\n+\t\treturn;\n \tdefault:\n \t\tdev_warn(&pf->pdev->dev, \"Unknown VSI type %d\\n\", vsi->type);\n \t\treturn;\n@@ -955,6 +976,8 @@ static int ice_vsi_init(struct ice_vsi *vsi)\n \n \tctxt->info = vsi->info;\n \tswitch (vsi->type) {\n+\tcase ICE_VSI_LB:\n+\t\t/* fall through */\n \tcase ICE_VSI_PF:\n \t\tctxt->flags = ICE_AQ_VSI_TYPE_PF;\n \t\tbreak;\n@@ -2071,8 +2094,7 @@ ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,\n \t\t\tbreak;\n \n \t\tfor (i = 0; i < vsi->tc_cfg.tc_info[tc].qcount_tx; i++) {\n-\t\t\tif (!rings || !rings[q_idx] ||\n-\t\t\t !rings[q_idx]->q_vector) {\n+\t\t\tif (!rings || !rings[q_idx]) {\n \t\t\t\terr = -EINVAL;\n \t\t\t\tgoto err_out;\n \t\t\t}\n@@ -2092,9 +2114,13 @@ ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,\n \t\t\t/* trigger a software interrupt for the vector\n \t\t\t * associated to the queue to schedule NAPI handler\n \t\t\t */\n-\t\t\twr32(hw, GLINT_DYN_CTL(rings[i]->q_vector->reg_idx),\n-\t\t\t GLINT_DYN_CTL_SWINT_TRIG_M |\n-\t\t\t GLINT_DYN_CTL_INTENA_MSK_M);\n+\t\t\tif (rings[q_idx]->q_vector) {\n+\t\t\t\tint reg_idx = rings[i]->q_vector->reg_idx;\n+\n+\t\t\t\twr32(hw, GLINT_DYN_CTL(reg_idx),\n+\t\t\t\t GLINT_DYN_CTL_SWINT_TRIG_M |\n+\t\t\t\t GLINT_DYN_CTL_INTENA_MSK_M);\n+\t\t\t}\n \t\t\tq_idx++;\n \t\t}\n \t\tstatus = ice_dis_vsi_txq(vsi->port_info, vsi->idx, tc,\n@@ -2408,6 +2434,11 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,\n \t\tpf->q_left_tx -= vsi->alloc_txq;\n \t\tpf->q_left_rx -= vsi->alloc_rxq;\n \t\tbreak;\n+\tcase ICE_VSI_LB:\n+\t\tret = ice_vsi_alloc_rings(vsi);\n+\t\tif (ret)\n+\t\t\tgoto unroll_vsi_init;\n+\t\tbreak;\n \tdefault:\n \t\t/* clean up the resources and exit */\n \t\tgoto unroll_vsi_init;\n@@ -2768,7 +2799,8 @@ int ice_vsi_release(struct ice_vsi *vsi)\n \t\tice_rss_clean(vsi);\n \n \t/* Disable VSI and free resources */\n-\tice_vsi_dis_irq(vsi);\n+\tif (vsi->type != ICE_VSI_LB)\n+\t\tice_vsi_dis_irq(vsi);\n \tice_vsi_close(vsi);\n \n \t/* reclaim interrupt vectors back to PF */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c\nindex eaa1b25dd1b0..4ca2d7a8d172 100644\n--- a/drivers/net/ethernet/intel/ice/ice_main.c\n+++ b/drivers/net/ethernet/intel/ice/ice_main.c\n@@ -1430,6 +1430,11 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)\n \toicr = rd32(hw, PFINT_OICR);\n \tena_mask = rd32(hw, PFINT_OICR_ENA);\n \n+\tif (oicr & PFINT_OICR_SWINT_M) {\n+\t\tena_mask &= ~PFINT_OICR_SWINT_M;\n+\t\tpf->sw_int_count++;\n+\t}\n+\n \tif (oicr & PFINT_OICR_MAL_DETECT_M) {\n \t\tena_mask &= ~PFINT_OICR_MAL_DETECT_M;\n \t\tset_bit(__ICE_MDD_EVENT_PENDING, pf->state);\n@@ -1803,8 +1808,8 @@ void ice_fill_rss_lut(u8 *lut, u16 rss_table_size, u16 rss_size)\n * @pf: board private structure\n * @pi: pointer to the port_info instance\n *\n- * Returns pointer to the successfully allocated VSI sw struct on success,\n- * otherwise returns NULL on failure.\n+ * Returns pointer to the successfully allocated VSI software struct\n+ * on success, otherwise returns NULL on failure.\n */\n static struct ice_vsi *\n ice_pf_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)\n@@ -1812,6 +1817,20 @@ ice_pf_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)\n \treturn ice_vsi_setup(pf, pi, ICE_VSI_PF, ICE_INVAL_VFID);\n }\n \n+/**\n+ * ice_lb_vsi_setup - Set up a loopback VSI\n+ * @pf: board private structure\n+ * @pi: pointer to the port_info instance\n+ *\n+ * Returns pointer to the successfully allocated VSI software struct\n+ * on success, otherwise returns NULL on failure.\n+ */\n+struct ice_vsi *\n+ice_lb_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)\n+{\n+\treturn ice_vsi_setup(pf, pi, ICE_VSI_LB, ICE_INVAL_VFID);\n+}\n+\n /**\n * ice_vlan_rx_add_vid - Add a VLAN ID filter to HW offload\n * @netdev: network interface to be adjusted\n@@ -2908,7 +2927,7 @@ static int ice_vsi_vlan_setup(struct ice_vsi *vsi)\n *\n * Return 0 on success and negative value on error\n */\n-static int ice_vsi_cfg(struct ice_vsi *vsi)\n+int ice_vsi_cfg(struct ice_vsi *vsi)\n {\n \tint err;\n \n@@ -3463,7 +3482,7 @@ int ice_down(struct ice_vsi *vsi)\n *\n * Return 0 on success, negative on failure\n */\n-static int ice_vsi_setup_tx_rings(struct ice_vsi *vsi)\n+int ice_vsi_setup_tx_rings(struct ice_vsi *vsi)\n {\n \tint i, err = 0;\n \n@@ -3489,7 +3508,7 @@ static int ice_vsi_setup_tx_rings(struct ice_vsi *vsi)\n *\n * Return 0 on success, negative on failure\n */\n-static int ice_vsi_setup_rx_rings(struct ice_vsi *vsi)\n+int ice_vsi_setup_rx_rings(struct ice_vsi *vsi)\n {\n \tint i, err = 0;\n \n@@ -4248,7 +4267,7 @@ static void ice_tx_timeout(struct net_device *netdev)\n *\n * Returns 0 on success, negative value on failure\n */\n-static int ice_open(struct net_device *netdev)\n+int ice_open(struct net_device *netdev)\n {\n \tstruct ice_netdev_priv *np = netdev_priv(netdev);\n \tstruct ice_vsi *vsi = np->vsi;\n@@ -4285,7 +4304,7 @@ static int ice_open(struct net_device *netdev)\n *\n * Returns success only - not allowed to fail\n */\n-static int ice_stop(struct net_device *netdev)\n+int ice_stop(struct net_device *netdev)\n {\n \tstruct ice_netdev_priv *np = netdev_priv(netdev);\n \tstruct ice_vsi *vsi = np->vsi;\ndiff --git a/drivers/net/ethernet/intel/ice/ice_nvm.c b/drivers/net/ethernet/intel/ice/ice_nvm.c\nindex 6d4adaed5810..bcb431f1bd92 100644\n--- a/drivers/net/ethernet/intel/ice/ice_nvm.c\n+++ b/drivers/net/ethernet/intel/ice/ice_nvm.c\n@@ -316,3 +316,34 @@ ice_read_sr_buf(struct ice_hw *hw, u16 offset, u16 *words, u16 *data)\n \n \treturn status;\n }\n+\n+/**\n+ * ice_nvm_validate_checksum\n+ * @hw: pointer to the HW struct\n+ *\n+ * Verify NVM PFA checksum validity (0x0706)\n+ */\n+enum ice_status ice_nvm_validate_checksum(struct ice_hw *hw)\n+{\n+\tstruct ice_aqc_nvm_checksum *cmd;\n+\tstruct ice_aq_desc desc;\n+\tenum ice_status status;\n+\n+\tstatus = ice_acquire_nvm(hw, ICE_RES_READ);\n+\tif (status)\n+\t\treturn status;\n+\n+\tcmd = &desc.params.nvm_checksum;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_checksum);\n+\tcmd->flags = ICE_AQC_NVM_CHECKSUM_VERIFY;\n+\n+\tstatus = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);\n+\tice_release_nvm(hw);\n+\n+\tif (!status)\n+\t\tif (le16_to_cpu(cmd->checksum) != ICE_AQC_NVM_CHECKSUM_CORRECT)\n+\t\t\tstatus = ICE_ERR_NVM_CHECKSUM;\n+\n+\treturn status;\n+}\ndiff --git a/drivers/net/ethernet/intel/ice/ice_status.h b/drivers/net/ethernet/intel/ice/ice_status.h\nindex 17afe6acb18a..c01597885629 100644\n--- a/drivers/net/ethernet/intel/ice/ice_status.h\n+++ b/drivers/net/ethernet/intel/ice/ice_status.h\n@@ -26,6 +26,7 @@ enum ice_status {\n \tICE_ERR_IN_USE\t\t\t\t= -16,\n \tICE_ERR_MAX_LIMIT\t\t\t= -17,\n \tICE_ERR_RESET_ONGOING\t\t\t= -18,\n+\tICE_ERR_NVM_CHECKSUM\t\t\t= -51,\n \tICE_ERR_BUF_TOO_SHORT\t\t\t= -52,\n \tICE_ERR_NVM_BLANK_MODE\t\t\t= -53,\n \tICE_ERR_AQ_ERROR\t\t\t= -100,\ndiff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h\nindex a862af4cbf78..0a0fa30a85bb 100644\n--- a/drivers/net/ethernet/intel/ice/ice_type.h\n+++ b/drivers/net/ethernet/intel/ice/ice_type.h\n@@ -86,6 +86,7 @@ enum ice_media_type {\n enum ice_vsi_type {\n \tICE_VSI_PF = 0,\n \tICE_VSI_VF,\n+\tICE_VSI_LB = 6,\n };\n \n struct ice_link_status {\n", "prefixes": [ "S20", "06/15" ] }