Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1122384/?format=api
{ "id": 1122384, "url": "http://patchwork.ozlabs.org/api/patches/1122384/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20190625144207.56248-1-anthony.l.nguyen@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": "<20190625144207.56248-1-anthony.l.nguyen@intel.com>", "list_archive_url": null, "date": "2019-06-25T14:42:06", "name": "[IDC,1/2] ice: Initialize and register platform device to provide RDMA", "commit_ref": null, "pull_url": null, "state": "rejected", "archived": false, "hash": "465ef1a2b1057953ac73f7fe40dd02391e4c41d4", "submitter": { "id": 68875, "url": "http://patchwork.ozlabs.org/api/people/68875/?format=api", "name": "Tony Nguyen", "email": "anthony.l.nguyen@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/20190625144207.56248-1-anthony.l.nguyen@intel.com/mbox/", "series": [ { "id": 116119, "url": "http://patchwork.ozlabs.org/api/series/116119/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=116119", "date": "2019-06-25T14:42:06", "name": "[IDC,1/2] ice: Initialize and register platform device to provide RDMA", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/116119/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1122384/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1122384/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 45YMLX6H7sz9s4V\n\tfor <incoming@patchwork.ozlabs.org>;\n\tWed, 26 Jun 2019 09:09:40 +1000 (AEST)", "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id F2EB785F91;\n\tTue, 25 Jun 2019 23:09:38 +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 RriaWAxCJXvE; Tue, 25 Jun 2019 23:09:34 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id D4E29844B2;\n\tTue, 25 Jun 2019 23:09:34 +0000 (UTC)", "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\tby ash.osuosl.org (Postfix) with ESMTP id 3E78E1BF30F\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 25 Jun 2019 23:09:34 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 3AAB0879A3\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 25 Jun 2019 23:09:34 +0000 (UTC)", "from hemlock.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id lD5lGzzh+vWH for <intel-wired-lan@lists.osuosl.org>;\n\tTue, 25 Jun 2019 23:09:32 +0000 (UTC)", "from mga01.intel.com (mga01.intel.com [192.55.52.88])\n\tby hemlock.osuosl.org (Postfix) with ESMTPS id 015C887360\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 25 Jun 2019 23:09:31 +0000 (UTC)", "from fmsmga006.fm.intel.com ([10.253.24.20])\n\tby fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t25 Jun 2019 16:09:31 -0700", "from unknown (HELO localhost.jf.intel.com) ([10.166.244.174])\n\tby fmsmga006.fm.intel.com with ESMTP; 25 Jun 2019 16:09:31 -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.63,417,1557212400\"; d=\"scan'208\";a=\"360548052\"", "From": "Tony Nguyen <anthony.l.nguyen@intel.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Tue, 25 Jun 2019 07:42:06 -0700", "Message-Id": "<20190625144207.56248-1-anthony.l.nguyen@intel.com>", "X-Mailer": "git-send-email 2.20.1", "MIME-Version": "1.0", "Subject": "[Intel-wired-lan] [IDC 1/2] ice: Initialize and register platform\n\tdevice to provide RDMA", "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": "The RDMA block does not advertise on the PCI bus or any other bus.\nThus the ice driver needs to provide access to the RDMA hardware block\nvia a virtual bus; utilize the platform bus to provide this access.\n\nThis patch initializes the driver to support RDMA as well as creates\nand registers a platform device for the RDMA driver to register to. At\nthis point the driver is fully initialized to register a platform\ndriver, however, can not yet register as the ops have not been\nimplemented.\n\nWe refer to the interaction of this platform device as Inter-Driver\nCommunication (IDC); where the platform device is referred to as the peer\ndevice and the platform driver is referred to as the peer driver.\n\nSigned-off-by: Dave Ertman <david.m.ertman@intel.com>\nSigned-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>\n---\n drivers/net/ethernet/intel/ice/Makefile | 1 +\n drivers/net/ethernet/intel/ice/ice.h | 13 +\n .../net/ethernet/intel/ice/ice_adminq_cmd.h | 1 +\n drivers/net/ethernet/intel/ice/ice_common.c | 5 +\n drivers/net/ethernet/intel/ice/ice_dcb_lib.c | 31 ++\n drivers/net/ethernet/intel/ice/ice_dcb_lib.h | 2 +\n .../net/ethernet/intel/ice/ice_hw_autogen.h | 1 +\n drivers/net/ethernet/intel/ice/ice_idc.c | 427 ++++++++++++++++++\n drivers/net/ethernet/intel/ice/ice_idc.h | 360 +++++++++++++++\n drivers/net/ethernet/intel/ice/ice_idc_int.h | 67 +++\n drivers/net/ethernet/intel/ice/ice_main.c | 42 ++\n drivers/net/ethernet/intel/ice/ice_type.h | 1 +\n 12 files changed, 951 insertions(+)\n create mode 100644 drivers/net/ethernet/intel/ice/ice_idc.c\n create mode 100644 drivers/net/ethernet/intel/ice/ice_idc.h\n create mode 100644 drivers/net/ethernet/intel/ice/ice_idc_int.h", "diff": "diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile\nindex 54bad11e4736..54741293b355 100644\n--- a/drivers/net/ethernet/intel/ice/Makefile\n+++ b/drivers/net/ethernet/intel/ice/Makefile\n@@ -15,6 +15,7 @@ ice-y := ice_main.o\t\\\n \t ice_sched.o\t\\\n \t ice_lib.o\t\\\n \t ice_txrx.o\t\\\n+\t ice_idc.o\t\\\n \t ice_ethtool.o\n ice-$(CONFIG_PCI_IOV) += ice_virtchnl_pf.o ice_sriov.o\n ice-$(CONFIG_DCB) += ice_dcb.o ice_dcb_lib.o\ndiff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h\nindex 3639cf8c75ac..9498df43fb5e 100644\n--- a/drivers/net/ethernet/intel/ice/ice.h\n+++ b/drivers/net/ethernet/intel/ice/ice.h\n@@ -43,6 +43,7 @@\n #include \"ice_switch.h\"\n #include \"ice_common.h\"\n #include \"ice_sched.h\"\n+#include \"ice_idc_int.h\"\n #include \"ice_virtchnl_pf.h\"\n #include \"ice_sriov.h\"\n \n@@ -89,6 +90,7 @@ extern const char ice_drv_ver[];\n #define ICE_MAX_SMALL_RSS_QS\t8\n #define ICE_RES_VALID_BIT\t0x8000\n #define ICE_RES_MISC_VEC_ID\t(ICE_RES_VALID_BIT - 1)\n+#define ICE_RES_RDMA_VEC_ID\t(ICE_RES_MISC_VEC_ID - 1)\n #define ICE_INVAL_Q_INDEX\t0xffff\n #define ICE_INVAL_VFID\t\t256\n #define ICE_MAX_VF_COUNT\t256\n@@ -343,6 +345,7 @@ struct ice_q_vector {\n enum ice_pf_flags {\n \tICE_FLAG_MSIX_ENA,\n \tICE_FLAG_FLTR_SYNC,\n+\tICE_FLAG_IWARP_ENA,\n \tICE_FLAG_RSS_ENA,\n \tICE_FLAG_SRIOV_ENA,\n \tICE_FLAG_SRIOV_CAPABLE,\n@@ -385,6 +388,9 @@ struct ice_pf {\n \tstruct mutex avail_q_mutex;\t/* protects access to avail_[rx|tx]qs */\n \tstruct mutex sw_mutex;\t\t/* lock for protecting VSI alloc flow */\n \tu32 msg_enable;\n+\t/* Total number of MSIX vectors reserved for base driver */\n+\tu32 num_rdma_msix;\n+\tu32 rdma_base_vector;\n \tu32 hw_csum_rx_error;\n \tu32 oicr_idx;\t\t/* Other interrupt cause MSIX vector index */\n \tu32 num_avail_sw_msix;\t/* remaining MSIX SW vectors left unclaimed */\n@@ -411,6 +417,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+\tstruct ice_peer_dev_int **peers;\n \tu32 sw_int_count;\n };\n \n@@ -418,6 +425,8 @@ struct ice_netdev_priv {\n \tstruct ice_vsi *vsi;\n };\n \n+extern struct ida ice_peer_index_ida;\n+\n /**\n * ice_irq_dynamic_ena - Enable default interrupt generation settings\n * @hw: pointer to HW struct\n@@ -510,6 +519,10 @@ 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 void ice_print_link_msg(struct ice_vsi *vsi, bool isup);\n+int ice_init_peer_devices(struct ice_pf *pf);\n+int\n+ice_for_each_peer(struct ice_pf *pf, void *data,\n+\t\t int (*fn)(struct ice_peer_dev_int *, void *));\n #ifdef CONFIG_DCB\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);\ndiff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\nindex 765e3c2ed045..1e1bd5f0c2a2 100644\n--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\n+++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\n@@ -96,6 +96,7 @@ struct ice_aqc_list_caps_elem {\n #define ICE_AQC_CAPS_TXQS\t\t\t\t0x0042\n #define ICE_AQC_CAPS_MSIX\t\t\t\t0x0043\n #define ICE_AQC_CAPS_MAX_MTU\t\t\t\t0x0047\n+#define ICE_AQC_CAPS_IWARP\t\t\t\t0x0051\n \n \tu8 major_ver;\n \tu8 minor_ver;\ndiff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c\nindex 2e0731c1e1a3..2788b2ede440 100644\n--- a/drivers/net/ethernet/intel/ice/ice_common.c\n+++ b/drivers/net/ethernet/intel/ice/ice_common.c\n@@ -1613,6 +1613,11 @@ ice_parse_caps(struct ice_hw *hw, void *buf, u32 cap_count,\n \t\t\t\t \"%s: MSIX first vector index = %d\\n\", prefix,\n \t\t\t\t caps->msix_vector_first_id);\n \t\t\tbreak;\n+\t\tcase ICE_AQC_CAPS_IWARP:\n+\t\t\tcaps->iwarp = (number == 1);\n+\t\t\tice_debug(hw, ICE_DBG_INIT,\n+\t\t\t\t \"%s: iWARP = %d\\n\", prefix, caps->iwarp);\n+\t\t\tbreak;\n \t\tcase ICE_AQC_CAPS_MAX_MTU:\n \t\t\tcaps->max_mtu = number;\n \t\t\tice_debug(hw, ICE_DBG_INIT, \"%s: max MTU = %d\\n\",\ndiff --git a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c\nindex fe88b127ca42..c6466e16eef1 100644\n--- a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c\n+++ b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c\n@@ -501,6 +501,37 @@ ice_tx_prepare_vlan_flags_dcb(struct ice_ring *tx_ring,\n \treturn 0;\n }\n \n+/**\n+ * ice_setup_dcb_qos_info - Setup DCB QoS information\n+ * @pf: ptr to ice_pf\n+ * @qos_info: QoS param instance\n+ */\n+void ice_setup_dcb_qos_info(struct ice_pf *pf, struct ice_qos_params *qos_info)\n+{\n+\tstruct ice_dcbx_cfg *dcbx_cfg;\n+\tu32 up2tc;\n+\tint i;\n+\n+\tdcbx_cfg = &pf->hw.port_info->local_dcbx_cfg;\n+\tup2tc = rd32(&pf->hw, PRTDCB_TUP2TC);\n+\tqos_info->num_apps = dcbx_cfg->numapps;\n+\n+\tqos_info->num_tc = ice_dcb_get_num_tc(dcbx_cfg);\n+\n+\tfor (i = 0; i < ICE_IDC_MAX_USER_PRIORITY; i++)\n+\t\tqos_info->up2tc[i] = (up2tc >> (i * 3)) & 0x7;\n+\n+\tfor (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)\n+\t\tqos_info->tc_info[i].rel_bw =\n+\t\t\tdcbx_cfg->etscfg.tcbwtable[i];\n+\n+\tfor (i = 0; i < qos_info->num_apps; i++) {\n+\t\tqos_info->apps[i].priority = dcbx_cfg->app[i].priority;\n+\t\tqos_info->apps[i].prot_id = dcbx_cfg->app[i].prot_id;\n+\t\tqos_info->apps[i].selector = dcbx_cfg->app[i].selector;\n+\t}\n+}\n+\n /**\n * ice_dcb_need_recfg - Check if DCB needs reconfig\n * @pf: board private structure\ndiff --git a/drivers/net/ethernet/intel/ice/ice_dcb_lib.h b/drivers/net/ethernet/intel/ice/ice_dcb_lib.h\nindex 819081053ff5..bce3899afb3a 100644\n--- a/drivers/net/ethernet/intel/ice/ice_dcb_lib.h\n+++ b/drivers/net/ethernet/intel/ice/ice_dcb_lib.h\n@@ -19,6 +19,7 @@ void ice_update_dcb_stats(struct ice_pf *pf);\n int\n ice_tx_prepare_vlan_flags_dcb(struct ice_ring *tx_ring,\n \t\t\t struct ice_tx_buf *first);\n+void ice_setup_dcb_qos_info(struct ice_pf *pf, struct ice_qos_params *qos_info);\n void\n ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf,\n \t\t\t\t struct ice_rq_event_info *event);\n@@ -56,6 +57,7 @@ ice_tx_prepare_vlan_flags_dcb(struct ice_ring __always_unused *tx_ring,\n \n #define ice_update_dcb_stats(pf) do {} while (0)\n #define ice_vsi_cfg_dcb_rings(vsi) do {} while (0)\n+#define ice_setup_dcb_qos_info(pf, qos_info) do {} while (0)\n #define ice_dcb_process_lldp_set_mib_change(pf, event) do {} while (0)\n #define ice_set_cgd_num(tlan_ctx, ring) do {} while (0)\n #endif /* CONFIG_DCB */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h\nindex 6c5ce05742b1..0fa393f909dd 100644\n--- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h\n+++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h\n@@ -55,6 +55,7 @@\n #define PRTDCB_GENS\t\t\t\t0x00083020\n #define PRTDCB_GENS_DCBX_STATUS_S\t\t0\n #define PRTDCB_GENS_DCBX_STATUS_M\t\tICE_M(0x7, 0)\n+#define PRTDCB_TUP2TC\t\t\t\t0x001D26C0\n #define GLFLXP_RXDID_FLAGS(_i, _j)\t\t(0x0045D000 + ((_i) * 4 + (_j) * 256))\n #define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S\t0\n #define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_M\tICE_M(0x3F, 0)\ndiff --git a/drivers/net/ethernet/intel/ice/ice_idc.c b/drivers/net/ethernet/intel/ice/ice_idc.c\nnew file mode 100644\nindex 000000000000..0bf66e9fa159\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/ice/ice_idc.c\n@@ -0,0 +1,427 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/* Copyright (c) 2019, Intel Corporation. */\n+\n+/* Inter-Driver Communication */\n+#include \"ice.h\"\n+#include \"ice_lib.h\"\n+#include \"ice_dcb_lib.h\"\n+\n+DEFINE_IDA(ice_peer_index_ida);\n+\n+static const struct peer_dev_id peer_dev_ids[] = ASSIGN_PEER_INFO;\n+\n+/**\n+ * ice_peer_state_change - manage state machine for peer\n+ * @peer_dev: pointer to peer's configuration\n+ * @new_state: the state requested to transition into\n+ * @locked: boolean to determine if call made with mutex held\n+ *\n+ * This function handles all state transitions for peer devices.\n+ * The state machine is as follows:\n+ *\n+ * +<-----------------------+<-----------------------------+\n+ *\t\t\t\t|<-------+<----------+\t +\n+ *\t\t\t\t\\/\t +\t +\t +\n+ * INIT --------------> PROBED --> OPENING\t CLOSED --> REMOVED\n+ *\t\t\t\t\t + +\n+ *\t\t\t\t OPENED --> CLOSING\n+ *\t\t\t\t\t +\t +\n+ *\t\t\t\t PREP_RST\t +\n+ *\t\t\t\t\t +\t +\n+ *\t\t\t\t PREPPED\t +\n+ *\t\t\t\t\t +---------->+\n+ */\n+static void\n+ice_peer_state_change(struct ice_peer_dev_int *peer_dev, long new_state,\n+\t\t bool locked)\n+{\n+\tif (!locked)\n+\t\tmutex_lock(&peer_dev->peer_dev_state_mutex);\n+\n+\tswitch (new_state) {\n+\tcase ICE_PEER_DEV_STATE_INIT:\n+\t\tif (test_and_clear_bit(ICE_PEER_DEV_STATE_REMOVED,\n+\t\t\t\t peer_dev->state)) {\n+\t\t\tset_bit(ICE_PEER_DEV_STATE_INIT, peer_dev->state);\n+\t\t\tdev_info(&peer_dev->peer_dev.platform_dev.dev,\n+\t\t\t\t \"state transition from _REMOVED to _INIT\\n\");\n+\t\t} else {\n+\t\t\tset_bit(ICE_PEER_DEV_STATE_INIT, peer_dev->state);\n+\t\t\tdev_info(&peer_dev->peer_dev.platform_dev.dev,\n+\t\t\t\t \"state set to _INIT\\n\");\n+\t\t}\n+\t\tbreak;\n+\tcase ICE_PEER_DEV_STATE_PROBED:\n+\t\tif (test_and_clear_bit(ICE_PEER_DEV_STATE_INIT,\n+\t\t\t\t peer_dev->state)) {\n+\t\t\tset_bit(ICE_PEER_DEV_STATE_PROBED, peer_dev->state);\n+\t\t\tdev_info(&peer_dev->peer_dev.platform_dev.dev,\n+\t\t\t\t \"state transition from _INIT to _PROBED\\n\");\n+\t\t} else if (test_and_clear_bit(ICE_PEER_DEV_STATE_REMOVED,\n+\t\t\t\t\t peer_dev->state)) {\n+\t\t\tset_bit(ICE_PEER_DEV_STATE_PROBED, peer_dev->state);\n+\t\t\tdev_info(&peer_dev->peer_dev.platform_dev.dev,\n+\t\t\t\t \"state transition from _REMOVED to _PROBED\\n\");\n+\t\t} else if (test_and_clear_bit(ICE_PEER_DEV_STATE_OPENING,\n+\t\t\t\t\t peer_dev->state)) {\n+\t\t\tset_bit(ICE_PEER_DEV_STATE_PROBED, peer_dev->state);\n+\t\t\tdev_info(&peer_dev->peer_dev.platform_dev.dev,\n+\t\t\t\t \"state transition from _OPENING to _PROBED\\n\");\n+\t\t}\n+\t\tbreak;\n+\tcase ICE_PEER_DEV_STATE_OPENING:\n+\t\tif (test_and_clear_bit(ICE_PEER_DEV_STATE_PROBED,\n+\t\t\t\t peer_dev->state)) {\n+\t\t\tset_bit(ICE_PEER_DEV_STATE_OPENING, peer_dev->state);\n+\t\t\tdev_info(&peer_dev->peer_dev.platform_dev.dev,\n+\t\t\t\t \"state transition from _PROBED to _OPENING\\n\");\n+\t\t} else if (test_and_clear_bit(ICE_PEER_DEV_STATE_CLOSED,\n+\t\t\t\t\t peer_dev->state)) {\n+\t\t\tset_bit(ICE_PEER_DEV_STATE_OPENING, peer_dev->state);\n+\t\t\tdev_info(&peer_dev->peer_dev.platform_dev.dev,\n+\t\t\t\t \"state transition from _CLOSED to _OPENING\\n\");\n+\t\t}\n+\t\tbreak;\n+\tcase ICE_PEER_DEV_STATE_OPENED:\n+\t\tif (test_and_clear_bit(ICE_PEER_DEV_STATE_OPENING,\n+\t\t\t\t peer_dev->state)) {\n+\t\t\tset_bit(ICE_PEER_DEV_STATE_OPENED, peer_dev->state);\n+\t\t\tdev_info(&peer_dev->peer_dev.platform_dev.dev,\n+\t\t\t\t \"state transition from _OPENING to _OPENED\\n\");\n+\t\t}\n+\t\tbreak;\n+\tcase ICE_PEER_DEV_STATE_PREP_RST:\n+\t\tif (test_and_clear_bit(ICE_PEER_DEV_STATE_OPENED,\n+\t\t\t\t peer_dev->state)) {\n+\t\t\tset_bit(ICE_PEER_DEV_STATE_PREP_RST, peer_dev->state);\n+\t\t\tdev_info(&peer_dev->peer_dev.platform_dev.dev,\n+\t\t\t\t \"state transition from _OPENED to _PREP_RST\\n\");\n+\t\t}\n+\t\tbreak;\n+\tcase ICE_PEER_DEV_STATE_PREPPED:\n+\t\tif (test_and_clear_bit(ICE_PEER_DEV_STATE_PREP_RST,\n+\t\t\t\t peer_dev->state)) {\n+\t\t\tset_bit(ICE_PEER_DEV_STATE_PREPPED, peer_dev->state);\n+\t\t\tdev_info(&peer_dev->peer_dev.platform_dev.dev,\n+\t\t\t\t \"state transition _PREP_RST to _PREPPED\\n\");\n+\t\t}\n+\t\tbreak;\n+\tcase ICE_PEER_DEV_STATE_CLOSING:\n+\t\tif (test_and_clear_bit(ICE_PEER_DEV_STATE_OPENED,\n+\t\t\t\t peer_dev->state)) {\n+\t\t\tset_bit(ICE_PEER_DEV_STATE_CLOSING, peer_dev->state);\n+\t\t\tdev_info(&peer_dev->peer_dev.platform_dev.dev,\n+\t\t\t\t \"state transition from _OPENED to _CLOSING\\n\");\n+\t\t}\n+\t\tif (test_and_clear_bit(ICE_PEER_DEV_STATE_PREPPED,\n+\t\t\t\t peer_dev->state)) {\n+\t\t\tset_bit(ICE_PEER_DEV_STATE_CLOSING, peer_dev->state);\n+\t\t\tdev_info(&peer_dev->peer_dev.platform_dev.dev,\n+\t\t\t\t \"state transition _PREPPED to _CLOSING\\n\");\n+\t\t}\n+\t\t/* NOTE - up to peer to handle this situation correctly */\n+\t\tif (test_and_clear_bit(ICE_PEER_DEV_STATE_PREP_RST,\n+\t\t\t\t peer_dev->state)) {\n+\t\t\tset_bit(ICE_PEER_DEV_STATE_CLOSING, peer_dev->state);\n+\t\t\tdev_warn(&peer_dev->peer_dev.platform_dev.dev,\n+\t\t\t\t \"WARN: Peer state PREP_RST to _CLOSING\\n\");\n+\t\t}\n+\t\tbreak;\n+\tcase ICE_PEER_DEV_STATE_CLOSED:\n+\t\tif (test_and_clear_bit(ICE_PEER_DEV_STATE_CLOSING,\n+\t\t\t\t peer_dev->state)) {\n+\t\t\tset_bit(ICE_PEER_DEV_STATE_CLOSED, peer_dev->state);\n+\t\t\tdev_info(&peer_dev->peer_dev.platform_dev.dev,\n+\t\t\t\t \"state transition from _CLOSING to _CLOSED\\n\");\n+\t\t}\n+\t\tbreak;\n+\tcase ICE_PEER_DEV_STATE_REMOVED:\n+\t\tif (test_and_clear_bit(ICE_PEER_DEV_STATE_OPENED,\n+\t\t\t\t peer_dev->state) ||\n+\t\t test_and_clear_bit(ICE_PEER_DEV_STATE_CLOSED,\n+\t\t\t\t peer_dev->state)) {\n+\t\t\tset_bit(ICE_PEER_DEV_STATE_REMOVED, peer_dev->state);\n+\t\t\tdev_info(&peer_dev->peer_dev.platform_dev.dev,\n+\t\t\t\t \"state from _OPENED/_CLOSED to _REMOVED\\n\");\n+\t\t\t/* Clear registration for events when peer removed */\n+\t\t\tbitmap_zero(peer_dev->events, ICE_PEER_DEV_STATE_NBITS);\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\tif (!locked)\n+\t\tmutex_unlock(&peer_dev->peer_dev_state_mutex);\n+}\n+\n+/**\n+ * ice_for_each_peer - iterate across and call function for each peer dev\n+ * @pf: pointer to private board struct\n+ * @data: data to pass to function on each call\n+ * @fn: pointer to function to call for each peer\n+ *\n+ * This function is to be used similarly to ice_for_each_peer\n+ */\n+int\n+ice_for_each_peer(struct ice_pf *pf, void *data,\n+\t\t int (*fn)(struct ice_peer_dev_int *, void *))\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < ARRAY_SIZE(peer_dev_ids); i++) {\n+\t\tstruct ice_peer_dev_int *peer_dev_int;\n+\t\tint ret;\n+\n+\t\tpeer_dev_int = pf->peers[i];\n+\t\tif (peer_dev_int) {\n+\t\t\tret = fn(peer_dev_int, data);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_unreg_peer_device - unregister specified device\n+ * @peer_dev_int: ptr to peer device internal\n+ * @data: ptr to opaque data\n+ *\n+ * This function invokes device unregistration, removes ID associated with\n+ * the specified device.\n+ */\n+int\n+ice_unreg_peer_device(struct ice_peer_dev_int *peer_dev_int,\n+\t\t void __always_unused *data)\n+{\n+\tstruct ice_pf *pf;\n+\n+\tif (!peer_dev_int)\n+\t\treturn 0;\n+\n+\tplatform_device_unregister(&peer_dev_int->peer_dev.platform_dev);\n+\n+\tpf = pci_get_drvdata(peer_dev_int->peer_dev.pdev);\n+\tif (!pf)\n+\t\treturn 0;\n+\n+\tif (peer_dev_int->ice_peer_wq) {\n+\t\tif (peer_dev_int->peer_prep_task.func)\n+\t\t\tcancel_work_sync(&peer_dev_int->peer_prep_task);\n+\n+\t\tif (peer_dev_int->peer_close_task.func)\n+\t\t\tcancel_work_sync(&peer_dev_int->peer_close_task);\n+\t\tdestroy_workqueue(peer_dev_int->ice_peer_wq);\n+\t}\n+\n+\t/* Cleanup the allocated ID for this peer device */\n+\tida_simple_remove(&ice_peer_index_ida, peer_dev_int->peer_dev.index);\n+\n+\tdevm_kfree(&pf->pdev->dev, peer_dev_int);\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_unroll_peer - destroy peers and peer_wq in case of error\n+ * @peer_dev_int: ptr to peer device internal struct\n+ * @data: ptr to opaque data\n+ *\n+ * This function releases resources in the event of a failure in creating\n+ * peer devices or their individual work_queues. Meant to be called from\n+ * a ice_for_each_peer invocation\n+ */\n+int\n+ice_unroll_peer(struct ice_peer_dev_int *peer_dev_int,\n+\t\tvoid __always_unused *data)\n+{\n+\tstruct ice_pf *pf;\n+\n+\tpf = pci_get_drvdata(peer_dev_int->peer_dev.pdev);\n+\n+\tif (peer_dev_int->ice_peer_wq)\n+\t\tdestroy_workqueue(peer_dev_int->ice_peer_wq);\n+\tdevm_kfree(&pf->pdev->dev, peer_dev_int);\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_reserve_peer_qvector - Reserve vector resources for peer drivers\n+ * @pf: board private structure to initialize\n+ */\n+static int ice_reserve_peer_qvector(struct ice_pf *pf)\n+{\n+\tif (test_bit(ICE_FLAG_IWARP_ENA, pf->flags)) {\n+\t\tint index;\n+\n+\t\tindex = ice_get_res(pf, pf->irq_tracker, pf->num_rdma_msix,\n+\t\t\t\t ICE_RES_RDMA_VEC_ID);\n+\t\tif (index < 0)\n+\t\t\treturn index;\n+\t\tpf->num_avail_sw_msix -= pf->num_rdma_msix;\n+\t\tpf->rdma_base_vector = index;\n+\t}\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_peer_device_release - release function for platform peer device\n+ * @dev: pointer to device structure\n+ *\n+ * This callback function is accessed by platform bus infrastructure when\n+ * all references on the peer platform device we registered are removed\n+ * (e.g. the peer priver has been removed). We will use this opportunity\n+ * to set the peer's state to init to be ready if the peer driver re-loads.\n+ */\n+static void ice_peer_device_release(struct device *dev)\n+{\n+\tstruct ice_peer_dev_int *peer_dev_int;\n+\tstruct ice_peer_dev *peer_dev;\n+\n+\tpeer_dev = dev_to_ice_peer(dev);\n+\tpeer_dev_int = container_of(peer_dev, struct ice_peer_dev_int,\n+\t\t\t\t peer_dev);\n+\n+\tice_peer_state_change(peer_dev_int, ICE_PEER_DEV_STATE_INIT, false);\n+}\n+\n+/**\n+ * ice_init_peer_devices - initializes peer devices\n+ * @pf: ptr to ice_pf\n+ *\n+ * This function initializes peer devices and associates them with specified\n+ * pci_dev as their parent.\n+ */\n+int ice_init_peer_devices(struct ice_pf *pf)\n+{\n+\tstruct pci_dev *pdev = pf->pdev;\n+\tstruct msix_entry *entry = NULL;\n+\tstruct ice_port_info *port_info;\n+\tstruct ice_vsi *vsi;\n+\tint status = 0;\n+\tint i;\n+\n+\t/* Reserve vector resources */\n+\tstatus = ice_reserve_peer_qvector(pf);\n+\tif (status < 0) {\n+\t\tdev_err(&pdev->dev,\n+\t\t\t\"failed to reserve vectors for peer drivers\\n\");\n+\t\treturn status;\n+\t}\n+\tfor (i = 0; i < ARRAY_SIZE(peer_dev_ids); i++) {\n+\t\tstruct ice_peer_dev_int *peer_dev_int;\n+\t\tstruct platform_device *platform_dev;\n+\t\tstruct ice_qos_params *qos_info;\n+\t\tstruct ice_peer_dev *peer_dev;\n+\t\tint j;\n+\n+\t\t/* don't create an RDMA platform_device if NIC does not\n+\t\t * support RDMA functionality\n+\t\t */\n+\t\tif (peer_dev_ids[i].id == ICE_PEER_RDMA_DEV &&\n+\t\t !test_bit(ICE_FLAG_IWARP_ENA, pf->flags)) {\n+\t\t\tdev_warn(&pf->pdev->dev,\n+\t\t\t\t \"RDMA not possible with this device config\\n\");\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tpeer_dev_int = devm_kzalloc(&pdev->dev, sizeof(*peer_dev_int),\n+\t\t\t\t\t GFP_KERNEL);\n+\t\tif (!peer_dev_int)\n+\t\t\treturn -ENOMEM;\n+\t\tpf->peers[i] = peer_dev_int;\n+\n+\t\tmutex_init(&peer_dev_int->peer_dev_state_mutex);\n+\n+\t\tpeer_dev = &peer_dev_int->peer_dev;\n+\t\tpeer_dev->peer_ops = NULL;\n+\t\tpeer_dev->hw_addr = (u8 __iomem *)pf->hw.hw_addr;\n+\t\tpeer_dev->ver.major = ICE_PEER_MAJOR_VER;\n+\t\tpeer_dev->ver.minor = ICE_PEER_MINOR_VER;\n+\t\tpeer_dev->ver.support = ICE_IDC_FEATURES;\n+\t\tpeer_dev->peer_dev_id = peer_dev_ids[i].id;\n+\t\tport_info = pf->hw.port_info;\n+\t\tvsi = pf->vsi[0];\n+\t\tpeer_dev->pf_vsi_num = vsi->vsi_num;\n+\t\tpeer_dev->netdev = vsi->netdev;\n+\t\tpeer_dev->initial_mtu = vsi->netdev->mtu;\n+\t\tether_addr_copy(peer_dev->lan_addr, port_info->mac.lan_addr);\n+\n+\t\tplatform_dev = &peer_dev->platform_dev;\n+\t\tplatform_dev->name = peer_dev_ids[i].name;\n+\t\tplatform_dev->id = PLATFORM_DEVID_AUTO;\n+\t\tplatform_dev->id_auto = true;\n+\t\tplatform_dev->dev.release = ice_peer_device_release;\n+\t\tplatform_dev->dev.parent = &pdev->dev;\n+\t\tpeer_dev_int->ice_peer_wq =\n+\t\t\talloc_ordered_workqueue(\"ice_peer_wq_%d\", WQ_UNBOUND,\n+\t\t\t\t\t\ti);\n+\t\tif (!peer_dev_int->ice_peer_wq)\n+\t\t\treturn -ENOMEM;\n+\n+\t\t/* Assign a unique index and hence name for peer device */\n+\t\tstatus = ida_simple_get(&ice_peer_index_ida, 0, 0, GFP_KERNEL);\n+\t\tif (status < 0) {\n+\t\t\tdev_err(&pdev->dev,\n+\t\t\t\t\"failed to get unique index for device\\n\");\n+\t\t\tdevm_kfree(&pdev->dev, peer_dev);\n+\t\t\treturn status;\n+\t\t}\n+\t\tpeer_dev->index = status;\n+\t\tpeer_dev->pdev = pdev;\n+\t\tpeer_dev->ari_ena = pci_ari_enabled(pdev->bus);\n+\t\tpeer_dev->bus_num = PCI_BUS_NUM(pdev->devfn);\n+\t\tif (!peer_dev->ari_ena) {\n+\t\t\tpeer_dev->dev_num = PCI_SLOT(pdev->devfn);\n+\t\t\tpeer_dev->fn_num = PCI_FUNC(pdev->devfn);\n+\t\t} else {\n+\t\t\tpeer_dev->dev_num = 0;\n+\t\t\tpeer_dev->fn_num = pdev->devfn & 0xff;\n+\t\t}\n+\n+\t\tqos_info = &peer_dev->initial_qos_info;\n+\n+\t\t/* setup qos_info fields with defaults */\n+\t\tqos_info->num_apps = 0;\n+\t\tqos_info->num_tc = 1;\n+\n+\t\tfor (j = 0; j < ICE_IDC_MAX_USER_PRIORITY; j++)\n+\t\t\tqos_info->up2tc[j] = 0;\n+\n+\t\tqos_info->tc_info[0].rel_bw = 100;\n+\t\tfor (j = 1; j < IEEE_8021QAZ_MAX_TCS; j++)\n+\t\t\tqos_info->tc_info[j].rel_bw = 0;\n+\n+\t\t/* for DCB, override the qos_info defaults. */\n+\t\tice_setup_dcb_qos_info(pf, qos_info);\n+\n+\t\t/* make sure peer specific resources such as msix_count and\n+\t\t * msix_entries are initialized\n+\t\t */\n+\t\tswitch (peer_dev_ids[i].id) {\n+\t\tcase ICE_PEER_RDMA_DEV:\n+\t\t\tif (test_bit(ICE_FLAG_IWARP_ENA, pf->flags)) {\n+\t\t\t\tpeer_dev->msix_count = pf->num_rdma_msix;\n+\t\t\t\tentry = &pf->msix_entries[pf->rdma_base_vector];\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tpeer_dev->msix_entries = entry;\n+\t\tice_peer_state_change(peer_dev_int, ICE_PEER_DEV_STATE_INIT,\n+\t\t\t\t false);\n+\t\tstatus = platform_device_register(platform_dev);\n+\t\tif (status) {\n+\t\t\tpr_err(\"Failed to register peer device %s\\n\",\n+\t\t\t platform_dev->name);\n+\t\t\treturn status;\n+\t\t}\n+\t}\n+\n+\treturn status;\n+}\ndiff --git a/drivers/net/ethernet/intel/ice/ice_idc.h b/drivers/net/ethernet/intel/ice/ice_idc.h\nnew file mode 100644\nindex 000000000000..87fe53f76f94\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/ice/ice_idc.h\n@@ -0,0 +1,360 @@\n+/* SPDX-License-Identifier: GPL-2.0 */\n+/* Copyright (c) 2019, Intel Corporation. */\n+\n+#ifndef _ICE_IDC_H_\n+#define _ICE_IDC_H_\n+\n+#include <linux/kernel.h>\n+#include <linux/device.h>\n+#include <linux/if_ether.h>\n+#include <linux/netdevice.h>\n+#include <linux/dcbnl.h>\n+#include <linux/platform_device.h>\n+\n+/* This major and minor version represent IDC API version information.\n+ * During peer driver registration, peer driver specifies major and minor\n+ * version information (via. peer_driver:ver_info). It gets checked against\n+ * following defines and if mismatch, then peer driver registration\n+ * fails and appropriate message gets logged.\n+ */\n+#define ICE_PEER_MAJOR_VER\t\t6\n+#define ICE_PEER_MINOR_VER\t\t1\n+\n+enum ice_peer_features {\n+\tICE_PEER_FEATURE_ADK_SUPPORT,\n+\tICE_PEER_FEATURE_PTP_SUPPORT,\n+\tICE_PEER_FEATURE_SRIOV_SUPPORT,\n+\tICE_PEER_FEATURE_PCIIOV_SUPPORT,\n+\tICE_PEER_FEATURE_NBITS\n+};\n+\n+#define ICE_SRIOV_SUP\t\tBIT(ICE_PEER_FEATURE_SRIOV_SUPPORT)\n+\n+#ifdef CONFIG_PCI_IOV\n+#define ICE_PCIIOV_SUP\t\tBIT(ICE_PEER_FEATURE_PCIIOV_SUPPORT)\n+#else\n+#define ICE_PCIIOV_SUP\t\t0\n+#endif /* CONFIG_PCI_IOV */\n+\n+#define ICE_IDC_FEATURES (ICE_SRIOV_SUP | ICE_PCIIOV_SUP)\n+\n+enum ice_event_type {\n+\tICE_EVENT_LINK_CHANGE = 0x0,\n+\tICE_EVENT_MTU_CHANGE,\n+\tICE_EVENT_TC_CHANGE,\n+\tICE_EVENT_API_CHANGE,\n+\tICE_EVENT_MBX_CHANGE,\n+\tICE_EVENT_NBITS\t\t/* must be last */\n+};\n+\n+enum ice_res_type {\n+\tICE_INVAL_RES = 0x0,\n+\tICE_VSI,\n+\tICE_VEB,\n+\tICE_EVENT_Q,\n+\tICE_EGRESS_CMPL_Q,\n+\tICE_CMPL_EVENT_Q,\n+\tICE_ASYNC_EVENT_Q,\n+\tICE_DOORBELL_Q,\n+\tICE_RDMA_QSETS_TXSCHED,\n+};\n+\n+enum ice_peer_reset_type {\n+\tICE_PEER_PFR = 0,\n+\tICE_PEER_CORER,\n+\tICE_PEER_CORER_SW_CORE,\n+\tICE_PEER_CORER_SW_FULL,\n+\tICE_PEER_GLOBR,\n+};\n+\n+/* reason notified to peer driver as part of event handling */\n+enum ice_close_reason {\n+\tICE_REASON_INVAL = 0x0,\n+\tICE_REASON_HW_UNRESPONSIVE,\n+\tICE_REASON_INTERFACE_DOWN, /* Administrative down */\n+\tICE_REASON_PEER_DRV_UNREG, /* peer driver getting unregistered */\n+\tICE_REASON_PEER_DEV_UNINIT,\n+\tICE_REASON_GLOBR_REQ,\n+\tICE_REASON_CORER_REQ,\n+\tICE_REASON_EMPR_REQ,\n+\tICE_REASON_PFR_REQ,\n+\tICE_REASON_HW_RESET_PENDING,\n+\tICE_REASON_PARAM_CHANGE,\n+};\n+\n+enum ice_rdma_filter {\n+\tICE_RDMA_FILTER_INVAL = 0x0,\n+\tICE_RDMA_FILTER_IWARP,\n+\tICE_RDMA_FILTER_ROCEV2,\n+\tICE_RDMA_FILTER_BOTH,\n+};\n+\n+/* This information is needed to handle peer driver registration,\n+ * instead of adding more params to peer_drv_registration function,\n+ * let's get it thru' peer_drv object.\n+ */\n+struct ice_ver_info {\n+\tu16 major;\n+\tu16 minor;\n+\tu64 support;\n+};\n+\n+/* Struct to hold per DCB APP info */\n+struct ice_dcb_app_info {\n+\tu8 priority;\n+\tu8 selector;\n+\tu16 prot_id;\n+};\n+\n+struct ice_peer_dev;\n+struct ice_peer_dev_int;\n+\n+#define ICE_IDC_MAX_USER_PRIORITY 8\n+#define ICE_IDC_MAX_APPS 8\n+\n+/* Struct to hold per RDMA Qset info */\n+struct ice_rdma_qset_params {\n+\tu32 teid;\t/* qset TEID */\n+\tu16 qs_handle; /* RDMA driver provides this */\n+\tu16 vsi_id; /* VSI index */\n+\tu8 tc; /* TC branch the QSet should belong to */\n+\tu8 reserved[3];\n+};\n+\n+struct ice_res_base {\n+\t/* Union for future provision e.g. other res_type */\n+\tunion {\n+\t\tstruct ice_rdma_qset_params qsets;\n+\t} res;\n+};\n+\n+struct ice_res {\n+\t/* Type of resource. Filled by peer driver */\n+\tenum ice_res_type res_type;\n+\t/* Count requested by peer driver */\n+\tu16 cnt_req;\n+\n+\t/* Number of resources allocated. Filled in by callee.\n+\t * Based on this value, caller to fill up \"resources\"\n+\t */\n+\tu16 res_allocated;\n+\n+\t/* Unique handle to resources allocated. Zero if call fails.\n+\t * Allocated by callee and for now used by caller for internal\n+\t * tracking purpose.\n+\t */\n+\tu32 res_handle;\n+\n+\t/* Peer driver has to allocate sufficient memory, to accommodate\n+\t * cnt_requested before calling this function.\n+\t * Memory has to be zero initialized. It is input/output param.\n+\t * As a result of alloc_res API, this structures will be populated.\n+\t */\n+\tstruct ice_res_base res[1];\n+};\n+\n+struct ice_qos_info {\n+\tu64 tc_ctx;\n+\tu8 rel_bw;\n+\tu8 prio_type;\n+\tu8 egress_virt_up;\n+\tu8 ingress_virt_up;\n+};\n+\n+/* Struct to hold QoS info */\n+struct ice_qos_params {\n+\tstruct ice_qos_info tc_info[IEEE_8021QAZ_MAX_TCS];\n+\tu8 up2tc[ICE_IDC_MAX_USER_PRIORITY];\n+\tu8 vsi_relative_bw;\n+\tu8 vsi_priority_type;\n+\tu32 num_apps;\n+\tstruct ice_dcb_app_info apps[ICE_IDC_MAX_APPS];\n+\tu8 num_tc;\n+};\n+\n+union ice_event_info {\n+\t/* ICE_EVENT_LINK_CHANGE */\n+\tstruct {\n+\t\tstruct net_device *lwr_nd;\n+\t\tu16 vsi_num; /* HW index of VSI corresponding to lwr ndev */\n+\t\tu8 new_link_state;\n+\t\tu8 lport;\n+\t} link_info;\n+\t/* ICE_EVENT_MTU_CHANGE */\n+\tu16 mtu;\n+\t/* ICE_EVENT_TC_CHANGE */\n+\tstruct ice_qos_params port_qos;\n+\t/* ICE_EVENT_API_CHANGE */\n+\tu8 api_rdy;\n+\t/* ICE_EVENT_MBX_CHANGE */\n+\tu8 mbx_rdy;\n+};\n+\n+/* ice_event elements are to be passed back and forth between the ice driver\n+ * and the peer drivers. They are to be used to both register/unregister\n+ * for event reporting and to report an event (events can be either ice\n+ * generated or peer generated).\n+ *\n+ * For (un)registering for events, the structure needs to be populated with:\n+ * reporter - pointer to the ice_peer_dev struct of the peer (un)registering\n+ * type - bitmap with bits set for event types to (un)register for\n+ *\n+ * For reporting events, the structure needs to be populated with:\n+ * reporter - pointer to peer that generated the event (NULL for ice)\n+ * type - bitmap with single bit set for this event type\n+ * info - union containing data relevant to this event type\n+ */\n+struct ice_event {\n+\tstruct ice_peer_dev *reporter;\n+\tDECLARE_BITMAP(type, ICE_EVENT_NBITS);\n+\tunion ice_event_info info;\n+};\n+\n+/* Following APIs are implemented by ICE driver and invoked by peer drivers */\n+struct ice_ops {\n+\t/* APIs to allocate resources such as VEB, VSI, Doorbell queues,\n+\t * completion queues, Tx/Rx queues, etc...\n+\t */\n+\tint (*alloc_res)(struct ice_peer_dev *peer_dev,\n+\t\t\t struct ice_res *res,\n+\t\t\t int partial_acceptable);\n+\tint (*free_res)(struct ice_peer_dev *peer_dev,\n+\t\t\tstruct ice_res *res);\n+\n+\tint (*is_vsi_ready)(struct ice_peer_dev *peer_dev);\n+\tint (*peer_register)(struct ice_peer_dev *peer_dev);\n+\tint (*peer_unregister)(struct ice_peer_dev *peer_dev);\n+\tint (*request_reset)(struct ice_peer_dev *dev,\n+\t\t\t enum ice_peer_reset_type reset_type);\n+\n+\tvoid (*notify_state_change)(struct ice_peer_dev *dev,\n+\t\t\t\t struct ice_event *event);\n+\n+\t/* Notification APIs */\n+\tvoid (*reg_for_notification)(struct ice_peer_dev *dev,\n+\t\t\t\t struct ice_event *event);\n+\tvoid (*unreg_for_notification)(struct ice_peer_dev *dev,\n+\t\t\t\t struct ice_event *event);\n+\tint (*update_vsi_filter)(struct ice_peer_dev *peer_dev,\n+\t\t\t\t enum ice_rdma_filter filter, bool enable);\n+\tint (*vc_send)(struct ice_peer_dev *peer_dev, u32 vf_id, u8 *msg,\n+\t\t u16 len);\n+};\n+\n+/* Following APIs are implemented by peer drivers and invoked by ICE driver */\n+struct ice_peer_ops {\n+\tvoid (*event_handler)(struct ice_peer_dev *peer_dev,\n+\t\t\t struct ice_event *event);\n+\n+\t/* Why we have 'open' and when it is expected to be called:\n+\t * 1. symmetric set of API w.r.t close\n+\t * 2. To be invoked form driver initialization path\n+\t * - call peer_driver:open once ice driver is fully initialized\n+\t * 3. To be invoked upon RESET complete\n+\t *\n+\t * Calls to open are performed from ice_finish_init_peer_device\n+\t * which is invoked from the service task. This helps keep devices\n+\t * from having their open called until the ice driver is ready and\n+\t * has scheduled its service task.\n+\t */\n+\tint (*open)(struct ice_peer_dev *peer_dev);\n+\n+\t/* Peer's close function is to be called when the peer needs to be\n+\t * quiesced. This can be for a variety of reasons (enumerated in the\n+\t * ice_close_reason enum struct). A call to close will only be\n+\t * followed by a call to either remove or open. No IDC calls from the\n+\t * peer should be accepted until it is re-opened.\n+\t *\n+\t * The *reason* parameter is the reason for the call to close. This\n+\t * can be for any reason enumerated in the ice_close_reason struct.\n+\t * It's primary reason is for the peer's bookkeeping and in case the\n+\t * peer want to perform any different tasks dictated by the reason.\n+\t */\n+\tvoid (*close)(struct ice_peer_dev *peer_dev,\n+\t\t enum ice_close_reason reason);\n+\n+\tint (*vc_receive)(struct ice_peer_dev *peer_dev, u32 vf_id, u8 *msg,\n+\t\t\t u16 len);\n+\t/* tell RDMA peer to prepare for TC change in a blocking call\n+\t * that will directly precede the change event\n+\t */\n+\tvoid (*prep_tc_change)(struct ice_peer_dev *peer_dev);\n+};\n+\n+#define ICE_PEER_RDMA_NAME\t\"ice_rdma\"\n+#define ICE_PEER_RDMA_DEV\t0x00000010\n+#define ICE_MAX_NUM_PEERS\t4\n+\n+/* The const struct that instantiates peer_dev_id needs to be initialized\n+ * in the .c with the macro ASSIGN_PEER_INFO.\n+ * For example:\n+ * static const struct peer_dev_id peer_dev_ids[] = ASSIGN_PEER_INFO;\n+ */\n+struct peer_dev_id {\n+\tchar *name;\n+\tint id;\n+};\n+\n+#define ASSIGN_PEER_INFO\t\t\t\t\t\\\n+{\t\t\t\t\t\t\t\t\\\n+\t{ ICE_PEER_RDMA_NAME, ICE_PEER_RDMA_DEV },\t\t\\\n+}\n+\n+/* structure representing peer device */\n+struct ice_peer_dev {\n+\tstruct platform_device platform_dev;\n+\tstruct ice_ver_info ver;\n+\tstruct pci_dev *pdev; /* PCI device of corresponding to main function */\n+\t/* KVA / Linear address corresponding to BAR0 of underlying\n+\t * pci_device.\n+\t */\n+\tu8 __iomem *hw_addr;\n+\tint peer_dev_id;\n+\n+\tunsigned int index;\n+\n+\tu8 ftype;\t/* PF(false) or VF (true) */\n+\n+\t/* Data VSI created by driver */\n+\tu16 pf_vsi_num;\n+\n+\tu8 lan_addr[ETH_ALEN]; /* default MAC address of main netdev */\n+\tu16 initial_mtu; /* Initial MTU of main netdev */\n+\tstruct ice_qos_params initial_qos_info;\n+\tstruct net_device *netdev;\n+\t/* PCI info */\n+\tu8 ari_ena;\n+\tu16 bus_num;\n+\tu16 dev_num;\n+\tu16 fn_num;\n+\n+\t/* Based on peer driver type, this shall point to corresponding MSIx\n+\t * entries in pf->msix_entries (which were allocated as part of driver\n+\t * initialization) e.g. for RDMA driver, msix_entries reserved will be\n+\t * num_online_cpus + 1.\n+\t */\n+\tu16 msix_count; /* How many vectors are reserved for this device */\n+\tstruct msix_entry *msix_entries;\n+\n+\t/* Following struct contains function pointers to be initialized\n+\t * by ICE driver and called by peer driver\n+\t */\n+\tconst struct ice_ops *ops;\n+\n+\t/* Following struct contains function pointers to be initialized\n+\t * by peer driver and called by ICE driver\n+\t */\n+\tconst struct ice_peer_ops *peer_ops;\n+\n+\t/* Pointer to peer_drv struct to be populated by peer driver */\n+\tstruct ice_peer_drv *peer_drv;\n+};\n+\n+static inline struct ice_peer_dev *dev_to_ice_peer(struct device *_dev)\n+{\n+\tstruct platform_device *platform_dev;\n+\n+\tplatform_dev = container_of(_dev, struct platform_device, dev);\n+\treturn container_of(platform_dev, struct ice_peer_dev, platform_dev);\n+}\n+#endif /* _ICE_IDC_H_*/\ndiff --git a/drivers/net/ethernet/intel/ice/ice_idc_int.h b/drivers/net/ethernet/intel/ice/ice_idc_int.h\nnew file mode 100644\nindex 000000000000..664cf5cc959f\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/ice/ice_idc_int.h\n@@ -0,0 +1,67 @@\n+/* SPDX-License-Identifier: GPL-2.0 */\n+/* Copyright (c) 2019, Intel Corporation. */\n+\n+#ifndef _ICE_IDC_INT_H_\n+#define _ICE_IDC_INT_H_\n+\n+#include \"ice_idc.h\"\n+\n+int ice_unroll_peer(struct ice_peer_dev_int *peer_dev_int, void *data);\n+int ice_unreg_peer_device(struct ice_peer_dev_int *peer_dev_int, void *data);\n+\n+enum ice_peer_dev_state {\n+\tICE_PEER_DEV_STATE_INIT,\n+\tICE_PEER_DEV_STATE_PROBED,\n+\tICE_PEER_DEV_STATE_OPENING,\n+\tICE_PEER_DEV_STATE_OPENED,\n+\tICE_PEER_DEV_STATE_PREP_RST,\n+\tICE_PEER_DEV_STATE_PREPPED,\n+\tICE_PEER_DEV_STATE_CLOSING,\n+\tICE_PEER_DEV_STATE_CLOSED,\n+\tICE_PEER_DEV_STATE_REMOVED,\n+\tICE_PEER_DEV_STATE_API_RDY,\n+\tICE_PEER_DEV_STATE_NBITS, /* must be last */\n+};\n+\n+enum ice_peer_drv_state {\n+\tICE_PEER_DRV_STATE_MBX_RDY,\n+\tICE_PEER_DRV_STATE_NBITS, /* must be last */\n+};\n+\n+struct ice_peer_drv_int {\n+\tstruct ice_peer_drv *peer_drv;\n+\tstruct ice_peer_dev *peer_dev;\n+\n+\t/* States associated with peer driver */\n+\tDECLARE_BITMAP(state, ICE_PEER_DRV_STATE_NBITS);\n+\n+\t/* if this peer_dev is the originator of an event, these are the\n+\t * most recent events of each type\n+\t */\n+\tstruct ice_event current_events[ICE_EVENT_NBITS];\n+};\n+\n+struct ice_peer_dev_int {\n+\tstruct ice_peer_dev peer_dev; /* public structure */\n+\tstruct ice_peer_drv_int *peer_drv_int; /* driver private structure */\n+\n+\t/* if this peer_dev is the originator of an event, these are the\n+\t * most recent events of each type\n+\t */\n+\tstruct ice_event current_events[ICE_EVENT_NBITS];\n+\t/* Events a peer has registered to be notified about */\n+\tDECLARE_BITMAP(events, ICE_EVENT_NBITS);\n+\n+\t/* States associated with peer device */\n+\tDECLARE_BITMAP(state, ICE_PEER_DEV_STATE_NBITS);\n+\tstruct mutex peer_dev_state_mutex; /* peer_dev state mutex */\n+\n+\t/* per peer workqueue */\n+\tstruct workqueue_struct *ice_peer_wq;\n+\n+\tstruct work_struct peer_prep_task;\n+\tstruct work_struct peer_close_task;\n+\n+\tenum ice_close_reason rst_type;\n+};\n+#endif /* !_ICE_IDC_INT_H_ */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c\nindex 5f45548f2940..6af2b827ab3b 100644\n--- a/drivers/net/ethernet/intel/ice/ice_main.c\n+++ b/drivers/net/ethernet/intel/ice/ice_main.c\n@@ -2402,6 +2402,8 @@ static void ice_init_pf(struct ice_pf *pf)\n {\n \tbitmap_zero(pf->flags, ICE_PF_FLAGS_NBITS);\n \tset_bit(ICE_FLAG_MSIX_ENA, pf->flags);\n+\tif (pf->hw.func_caps.common_cap.iwarp)\n+\t\tset_bit(ICE_FLAG_IWARP_ENA, pf->flags);\n #ifdef CONFIG_PCI_IOV\n \tif (pf->hw.func_caps.common_cap.sr_iov_1_1) {\n \t\tstruct ice_hw *hw = &pf->hw;\n@@ -2455,6 +2457,17 @@ static int ice_ena_msix_range(struct ice_pf *pf)\n \tv_budget += pf->num_lan_msix;\n \tv_left -= pf->num_lan_msix;\n \n+\t/* reserve vectors for RDMA peer driver */\n+\tif (test_bit(ICE_FLAG_IWARP_ENA, pf->flags)) {\n+\t\t/* RDMA peer driver needs one extra to handle misc causes */\n+\t\tneeded = min_t(int, num_online_cpus(), v_left) + 1;\n+\t\tif (v_left < needed)\n+\t\t\tgoto no_vecs_left_err;\n+\t\tpf->num_rdma_msix = needed;\n+\t\tv_budget += needed;\n+\t\tv_left -= needed;\n+\t}\n+\n \tpf->msix_entries = devm_kcalloc(&pf->pdev->dev, v_budget,\n \t\t\t\t\tsizeof(*pf->msix_entries), GFP_KERNEL);\n \n@@ -2481,6 +2494,8 @@ static int ice_ena_msix_range(struct ice_pf *pf)\n \t\t\t \"not enough vectors. requested = %d, obtained = %d\\n\",\n \t\t\t v_budget, v_actual);\n \t\tif (v_actual >= (pf->num_lan_msix + 1)) {\n+\t\t\tclear_bit(ICE_FLAG_IWARP_ENA, pf->flags);\n+\t\t\tpf->num_rdma_msix = 0;\n \t\t\tpf->num_avail_sw_msix = v_actual -\n \t\t\t\t\t\t(pf->num_lan_msix + 1);\n \t\t} else if (v_actual >= 2) {\n@@ -2499,6 +2514,11 @@ static int ice_ena_msix_range(struct ice_pf *pf)\n \tdevm_kfree(&pf->pdev->dev, pf->msix_entries);\n \tgoto exit_err;\n \n+no_vecs_left_err:\n+\tdev_err(&pf->pdev->dev,\n+\t\t\"not enough vectors. requested = %d, available = %d\\n\",\n+\t\tneeded, v_left);\n+\terr = -ERANGE;\n exit_err:\n \tpf->num_lan_msix = 0;\n \tclear_bit(ICE_FLAG_MSIX_ENA, pf->flags);\n@@ -2661,6 +2681,12 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)\n \n \tice_init_pf(pf);\n \n+\tpf->peers = devm_kcalloc(dev, ICE_MAX_NUM_PEERS, sizeof(*pf->peers),\n+\t\t\t\t GFP_KERNEL);\n+\tif (!pf->peers) {\n+\t\terr = -ENOMEM;\n+\t\tgoto err_init_peer_unroll;\n+\t}\n \terr = ice_init_pf_dcb(pf, false);\n \tif (err) {\n \t\tclear_bit(ICE_FLAG_DCB_CAPABLE, pf->flags);\n@@ -2742,10 +2768,20 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)\n \t\tgoto err_alloc_sw_unroll;\n \t}\n \n+\terr = ice_init_peer_devices(pf);\n+\tif (err) {\n+\t\tdev_err(dev, \"Failed to initialize peer devices: 0x%x\\n\", err);\n+\t\terr = -EIO;\n+\t\tgoto err_init_peer_unroll;\n+\t}\n+\n \tice_verify_cacheline_size(pf);\n \n \treturn 0;\n \n+\t/* Unwind non-managed device resources, etc. if something failed */\n+err_init_peer_unroll:\n+\tice_for_each_peer(pf, NULL, ice_unroll_peer);\n err_alloc_sw_unroll:\n \tset_bit(__ICE_SERVICE_DIS, pf->state);\n \tset_bit(__ICE_DOWN, pf->state);\n@@ -2787,6 +2823,7 @@ static void ice_remove(struct pci_dev *pdev)\n \tif (test_bit(ICE_FLAG_SRIOV_ENA, pf->flags))\n \t\tice_free_vfs(pf);\n \tice_vsi_release_all(pf);\n+\tice_for_each_peer(pf, NULL, ice_unreg_peer_device);\n \tice_free_irq_msix_misc(pf);\n \tice_for_each_vsi(pf, i) {\n \t\tif (!pf->vsi[i])\n@@ -2986,6 +3023,7 @@ static int __init ice_module_init(void)\n \tif (status) {\n \t\tpr_err(\"failed to register PCI driver, err %d\\n\", status);\n \t\tdestroy_workqueue(ice_wq);\n+\t\tida_destroy(&ice_peer_index_ida);\n \t}\n \n \treturn status;\n@@ -3002,6 +3040,10 @@ static void __exit ice_module_exit(void)\n {\n \tpci_unregister_driver(&ice_driver);\n \tdestroy_workqueue(ice_wq);\n+\t/* release all cached layer within ida tree, associated with\n+\t * ice_peer_index_ida object\n+\t */\n+\tida_destroy(&ice_peer_index_ida);\n \tpr_info(\"module unloaded\\n\");\n }\n module_exit(ice_module_exit);\ndiff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h\nindex 24bbef8bbe69..99822b4e8621 100644\n--- a/drivers/net/ethernet/intel/ice/ice_type.h\n+++ b/drivers/net/ethernet/intel/ice/ice_type.h\n@@ -161,6 +161,7 @@ struct ice_hw_common_caps {\n \tu8 rss_table_entry_width;\t/* RSS Entry width in bits */\n \n \tu8 dcb;\n+\tu8 iwarp;\n };\n \n /* Function specific capabilities */\n", "prefixes": [ "IDC", "1/2" ] }