get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/719278/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 719278,
    "url": "http://patchwork.ozlabs.org/api/patches/719278/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/1485282241-3579-2-git-send-email-bimmy.pujari@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": "<1485282241-3579-2-git-send-email-bimmy.pujari@intel.com>",
    "list_archive_url": null,
    "date": "2017-01-24T18:23:59",
    "name": "[next,S58-V3,2/4] i40evf: add client interface",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "a4f77bcf01a3eb8a31c94967e4cbaa5e3ec2710f",
    "submitter": {
        "id": 68919,
        "url": "http://patchwork.ozlabs.org/api/people/68919/?format=api",
        "name": "Pujari, Bimmy",
        "email": "bimmy.pujari@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/1485282241-3579-2-git-send-email-bimmy.pujari@intel.com/mbox/",
    "series": [],
    "comments": "http://patchwork.ozlabs.org/api/patches/719278/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/719278/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<intel-wired-lan-bounces@lists.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"
        ],
        "Received": [
            "from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3v7FTK39jDz9s3T\n\tfor <incoming@patchwork.ozlabs.org>;\n\tWed, 25 Jan 2017 04:26:13 +1100 (AEDT)",
            "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 9C52D832F6;\n\tTue, 24 Jan 2017 17:26:11 +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 wJ36FkbbEVgq; Tue, 24 Jan 2017 17:26:06 +0000 (UTC)",
            "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id BE86D88F58;\n\tTue, 24 Jan 2017 17:26:05 +0000 (UTC)",
            "from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n\tby ash.osuosl.org (Postfix) with ESMTP id 8017E1C0493\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 24 Jan 2017 17:26:04 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id 5032A30A5F\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 24 Jan 2017 17:26:04 +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 v7S5SvCmCr5b for <intel-wired-lan@lists.osuosl.org>;\n\tTue, 24 Jan 2017 17:25:58 +0000 (UTC)",
            "from mga11.intel.com (mga11.intel.com [192.55.52.93])\n\tby silver.osuosl.org (Postfix) with ESMTPS id C368130A02\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 24 Jan 2017 17:25:58 +0000 (UTC)",
            "from fmsmga004.fm.intel.com ([10.253.24.48])\n\tby fmsmga102.fm.intel.com with ESMTP; 24 Jan 2017 09:25:58 -0800",
            "from bimmy.jf.intel.com (HELO bimmy.linux1.jf.intel.com)\n\t([134.134.2.167])\n\tby fmsmga004.fm.intel.com with ESMTP; 24 Jan 2017 09:25:58 -0800"
        ],
        "X-Virus-Scanned": [
            "amavisd-new at osuosl.org",
            "amavisd-new at osuosl.org"
        ],
        "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.33,278,1477983600\"; d=\"scan'208\";a=\"217089092\"",
        "From": "Bimmy Pujari <bimmy.pujari@intel.com>",
        "To": "intel-wired-lan@lists.osuosl.org",
        "Date": "Tue, 24 Jan 2017 10:23:59 -0800",
        "Message-Id": "<1485282241-3579-2-git-send-email-bimmy.pujari@intel.com>",
        "X-Mailer": "git-send-email 2.4.11",
        "In-Reply-To": "<1485282241-3579-1-git-send-email-bimmy.pujari@intel.com>",
        "References": "<1485282241-3579-1-git-send-email-bimmy.pujari@intel.com>",
        "Subject": "[Intel-wired-lan] [next PATCH S58-V3 2/4] i40evf: add client\n\tinterface",
        "X-BeenThere": "intel-wired-lan@lists.osuosl.org",
        "X-Mailman-Version": "2.1.18-1",
        "Precedence": "list",
        "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n\t<intel-wired-lan.lists.osuosl.org>",
        "List-Unsubscribe": "<http://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@lists.osuosl.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>",
        "List-Post": "<mailto:intel-wired-lan@lists.osuosl.org>",
        "List-Help": "<mailto:intel-wired-lan-request@lists.osuosl.org?subject=help>",
        "List-Subscribe": "<http://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@lists.osuosl.org?subject=subscribe>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Errors-To": "intel-wired-lan-bounces@lists.osuosl.org",
        "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@lists.osuosl.org>"
    },
    "content": "From: Mitch Williams <mitch.a.williams@intel.com>\n\nIn preparation for upcoming RDMA-capable hardware, add a client\ninterface to the VF driver. This is a slightly-simplified version\nof the PF client interface, with the names changed to protect the\ninnocent.\n\nDue to the nature of the VF<->PF interactions, the client interface\nsometimes needs to call back into itself to pass messages. Because\nof this, we can't use the coarse-grained locking like the PF's\nclient interface uses. Instead, we handle all client interactions\nin a separate thread so the watchdog can still run and process\nvirtual channel messages.\n\nSigned-off-by: Mitch Williams <mitch.a.williams@intel.com>\nSigned-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>\nSigned-off-by: Anjali Singhai Jain <anjali.singhai@intel.com>\nSigned-off-by: Avinash Dayanand <avinash.dayanand@intel.com>\n---\n drivers/net/ethernet/intel/i40evf/Makefile         |   2 +-\n drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h  |  33 ++\n drivers/net/ethernet/intel/i40evf/i40evf.h         |  24 +-\n drivers/net/ethernet/intel/i40evf/i40evf_client.c  | 563 +++++++++++++++++++++\n drivers/net/ethernet/intel/i40evf/i40evf_client.h  | 166 ++++++\n drivers/net/ethernet/intel/i40evf/i40evf_main.c    |  83 ++-\n .../net/ethernet/intel/i40evf/i40evf_virtchnl.c    |  13 +-\n 7 files changed, 873 insertions(+), 11 deletions(-)\n create mode 100644 drivers/net/ethernet/intel/i40evf/i40evf_client.c\n create mode 100644 drivers/net/ethernet/intel/i40evf/i40evf_client.h",
    "diff": "diff --git a/drivers/net/ethernet/intel/i40evf/Makefile b/drivers/net/ethernet/intel/i40evf/Makefile\nindex 3a42383..827c7a6 100644\n--- a/drivers/net/ethernet/intel/i40evf/Makefile\n+++ b/drivers/net/ethernet/intel/i40evf/Makefile\n@@ -32,5 +32,5 @@\n obj-$(CONFIG_I40EVF) += i40evf.o\n \n i40evf-objs :=\ti40evf_main.o i40evf_ethtool.o i40evf_virtchnl.o \\\n-\t\ti40e_txrx.o i40e_common.o i40e_adminq.o\n+\t\ti40e_txrx.o i40e_common.o i40e_adminq.o i40evf_client.o\n \ndiff --git a/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h b/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h\nindex d38a2b2..f431fbc 100644\n--- a/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h\n+++ b/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h\n@@ -81,7 +81,9 @@ enum i40e_virtchnl_ops {\n \tI40E_VIRTCHNL_OP_GET_STATS = 15,\n \tI40E_VIRTCHNL_OP_FCOE = 16,\n \tI40E_VIRTCHNL_OP_EVENT = 17, /* must ALWAYS be 17 */\n+\tI40E_VIRTCHNL_OP_IWARP = 20,\n \tI40E_VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP = 21,\n+\tI40E_VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP = 22,\n \tI40E_VIRTCHNL_OP_CONFIG_RSS_KEY = 23,\n \tI40E_VIRTCHNL_OP_CONFIG_RSS_LUT = 24,\n \tI40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS = 25,\n@@ -393,6 +395,37 @@ struct i40e_virtchnl_pf_event {\n \tint severity;\n };\n \n+/* I40E_VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP\n+ * VF uses this message to request PF to map IWARP vectors to IWARP queues.\n+ * The request for this originates from the VF IWARP driver through\n+ * a client interface between VF LAN and VF IWARP driver.\n+ * A vector could have an AEQ and CEQ attached to it although\n+ * there is a single AEQ per VF IWARP instance in which case\n+ * most vectors will have an INVALID_IDX for aeq and valid idx for ceq.\n+ * There will never be a case where there will be multiple CEQs attached\n+ * to a single vector.\n+ * PF configures interrupt mapping and returns status.\n+ */\n+\n+/* HW does not define a type value for AEQ; only for RX/TX and CEQ.\n+ * In order for us to keep the interface simple, SW will define a\n+ * unique type value for AEQ.\n+ */\n+#define I40E_QUEUE_TYPE_PE_AEQ  0x80\n+#define I40E_QUEUE_INVALID_IDX  0xFFFF\n+\n+struct i40e_virtchnl_iwarp_qv_info {\n+\tu32 v_idx; /* msix_vector */\n+\tu16 ceq_idx;\n+\tu16 aeq_idx;\n+\tu8 itr_idx;\n+};\n+\n+struct i40e_virtchnl_iwarp_qvlist_info {\n+\tu32 num_vectors;\n+\tstruct i40e_virtchnl_iwarp_qv_info qv_info[1];\n+};\n+\n /* VF reset states - these are written into the RSTAT register:\n  * I40E_VFGEN_RSTAT1 on the PF\n  * I40E_VFGEN_RSTAT on the VF\ndiff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h\nindex f16d9d1..b2b4851 100644\n--- a/drivers/net/ethernet/intel/i40evf/i40evf.h\n+++ b/drivers/net/ethernet/intel/i40evf/i40evf.h\n@@ -60,6 +60,7 @@ struct i40e_vsi {\n \tint base_vector;\n \tu16 work_limit;\n \tu16 qs_handle;\n+\tvoid *priv;     /* client driver data reference. */\n };\n \n /* How many Rx Buffers do we bundle into one write to the hardware ? */\n@@ -169,6 +170,7 @@ enum i40evf_state_t {\n \n enum i40evf_critical_section_t {\n \t__I40EVF_IN_CRITICAL_TASK,\t/* cannot be interrupted */\n+\t__I40EVF_IN_CLIENT_TASK,\n };\n /* make common code happy */\n #define __I40E_DOWN __I40EVF_DOWN\n@@ -178,6 +180,7 @@ struct i40evf_adapter {\n \tstruct timer_list watchdog_timer;\n \tstruct work_struct reset_task;\n \tstruct work_struct adminq_task;\n+\tstruct delayed_work client_task;\n \tstruct delayed_work init_task;\n \tstruct i40e_q_vector *q_vectors;\n \tstruct list_head vlan_filter_list;\n@@ -195,7 +198,10 @@ struct i40evf_adapter {\n \tu64 hw_csum_rx_error;\n \tu32 rx_desc_count;\n \tint num_msix_vectors;\n+\tint num_iwarp_msix;\n+\tint iwarp_base_vector;\n \tu32 client_pending;\n+\tstruct i40e_client_instance *cinst;\n \tstruct msix_entry *msix_entries;\n \n \tu32 flags;\n@@ -211,8 +217,11 @@ struct i40evf_adapter {\n #define I40EVF_FLAG_OUTER_UDP_CSUM_CAPABLE\tBIT(12)\n #define I40EVF_FLAG_ADDR_SET_BY_PF\t\tBIT(13)\n #define I40EVF_FLAG_SERVICE_CLIENT_REQUESTED\tBIT(14)\n-#define I40EVF_FLAG_PROMISC_ON\t\t\tBIT(15)\n-#define I40EVF_FLAG_ALLMULTI_ON\t\t\tBIT(16)\n+#define I40EVF_FLAG_CLIENT_NEEDS_OPEN\t\tBIT(15)\n+#define I40EVF_FLAG_CLIENT_NEEDS_CLOSE\t\tBIT(16)\n+#define I40EVF_FLAG_CLIENT_NEEDS_L2_PARAMS\tBIT(17)\n+#define I40EVF_FLAG_PROMISC_ON\t\t\tBIT(18)\n+#define I40EVF_FLAG_ALLMULTI_ON\t\t\tBIT(19)\n /* duplicates for common code */\n #define I40E_FLAG_FDIR_ATR_ENABLED\t\t0\n #define I40E_FLAG_DCB_ENABLED\t\t\t0\n@@ -258,10 +267,11 @@ struct i40evf_adapter {\n \tbool link_up;\n \tenum i40e_aq_link_speed link_speed;\n \tenum i40e_virtchnl_ops current_op;\n-#define CLIENT_ENABLED(_a) ((_a)->vf_res ? \\\n+#define CLIENT_ALLOWED(_a) ((_a)->vf_res ? \\\n \t\t\t    (_a)->vf_res->vf_offload_flags & \\\n \t\t\t\tI40E_VIRTCHNL_VF_OFFLOAD_IWARP : \\\n \t\t\t    0)\n+#define CLIENT_ENABLED(_a) ((_a)->cinst)\n /* RSS by the PF should be preferred over RSS via other methods. */\n #define RSS_PF(_a) ((_a)->vf_res->vf_offload_flags & \\\n \t\t    I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF)\n@@ -292,6 +302,12 @@ struct i40evf_adapter {\n \n /* Ethtool Private Flags */\n \n+/* lan device */\n+struct i40e_device {\n+\tstruct list_head list;\n+\tstruct i40evf_adapter *vf;\n+};\n+\n /* needed by i40evf_ethtool.c */\n extern char i40evf_driver_name[];\n extern const char i40evf_driver_version[];\n@@ -343,5 +359,5 @@ void i40evf_client_subtask(struct i40evf_adapter *adapter);\n void i40evf_notify_client_message(struct i40e_vsi *vsi, u8 *msg, u16 len);\n void i40evf_notify_client_l2_params(struct i40e_vsi *vsi);\n void i40evf_notify_client_open(struct i40e_vsi *vsi);\n-void i40evf_notify_client_close(struct i40e_vsi *vsi);\n+void i40evf_notify_client_close(struct i40e_vsi *vsi, bool reset);\n #endif /* _I40EVF_H_ */\ndiff --git a/drivers/net/ethernet/intel/i40evf/i40evf_client.c b/drivers/net/ethernet/intel/i40evf/i40evf_client.c\nnew file mode 100644\nindex 0000000..5b43e5b\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/i40evf/i40evf_client.c\n@@ -0,0 +1,563 @@\n+#include <linux/list.h>\n+#include <linux/errno.h>\n+\n+#include \"i40evf.h\"\n+#include \"i40e_prototype.h\"\n+#include \"i40evf_client.h\"\n+\n+static\n+const char i40evf_client_interface_version_str[] = I40EVF_CLIENT_VERSION_STR;\n+static struct i40e_client *vf_registered_client;\n+static LIST_HEAD(i40evf_devices);\n+static DEFINE_MUTEX(i40evf_device_mutex);\n+\n+static u32 i40evf_client_virtchnl_send(struct i40e_info *ldev,\n+\t\t\t\t       struct i40e_client *client,\n+\t\t\t\t       u8 *msg, u16 len);\n+\n+static int i40evf_client_setup_qvlist(struct i40e_info *ldev,\n+\t\t\t\t      struct i40e_client *client,\n+\t\t\t\t      struct i40e_qvlist_info *qvlist_info);\n+\n+static struct i40e_ops i40evf_lan_ops = {\n+\t.virtchnl_send = i40evf_client_virtchnl_send,\n+\t.setup_qvlist = i40evf_client_setup_qvlist,\n+};\n+\n+/**\n+ * i40evf_notify_client_message - call the client message receive callback\n+ * @vsi: the VSI associated with this client\n+ * @msg: message buffer\n+ * @len: length of message\n+ *\n+ * If there is a client to this VSI, call the client\n+ **/\n+void i40evf_notify_client_message(struct i40e_vsi *vsi, u8 *msg, u16 len)\n+{\n+\tstruct i40evf_adapter *adapter = vsi->back;\n+\tstruct i40e_client_instance *cinst = adapter->cinst;\n+\n+\tif (!vsi)\n+\t\treturn;\n+\n+\tif (!cinst || !cinst->client || !cinst->client->ops ||\n+\t    !cinst->client->ops->virtchnl_receive) {\n+\t\tdev_dbg(&vsi->back->pdev->dev,\n+\t\t\t\"Cannot locate client instance virtchnl_receive function\\n\");\n+\t\treturn;\n+\t}\n+\tcinst->client->ops->virtchnl_receive(&cinst->lan_info,  cinst->client,\n+\t\t\t\t\t     msg, len);\n+}\n+\n+/**\n+ * i40evf_notify_client_l2_params - call the client notify callback\n+ * @vsi: the VSI with l2 param changes\n+ *\n+ * If there is a client to this VSI, call the client\n+ **/\n+void i40evf_notify_client_l2_params(struct i40e_vsi *vsi)\n+{\n+\tstruct i40evf_adapter *adapter = vsi->back;\n+\tstruct i40e_client_instance *cinst = adapter->cinst;\n+\tstruct i40e_params params;\n+\n+\tif (!vsi)\n+\t\treturn;\n+\tmemset(&params, 0, sizeof(params));\n+\tparams.mtu = vsi->netdev->mtu;\n+\tparams.link_up = vsi->back->link_up;\n+\tparams.qos.prio_qos[0].qs_handle = vsi->qs_handle;\n+\n+\tif (!cinst || !cinst->client || !cinst->client->ops ||\n+\t    !cinst->client->ops->l2_param_change) {\n+\t\tdev_dbg(&vsi->back->pdev->dev,\n+\t\t\t\"Cannot locate client instance l2_param_change function\\n\");\n+\t\treturn;\n+\t}\n+\tcinst->client->ops->l2_param_change(&cinst->lan_info, cinst->client,\n+\t\t\t\t\t    &params);\n+}\n+\n+/**\n+ * i40evf_notify_client_open - call the client open callback\n+ * @vsi: the VSI with netdev opened\n+ *\n+ * If there is a client to this netdev, call the client with open\n+ **/\n+void i40evf_notify_client_open(struct i40e_vsi *vsi)\n+{\n+\tstruct i40evf_adapter *adapter = vsi->back;\n+\tstruct i40e_client_instance *cinst = adapter->cinst;\n+\tint ret;\n+\n+\tif (!cinst || !cinst->client || !cinst->client->ops ||\n+\t    !cinst->client->ops->open) {\n+\t\tdev_dbg(&vsi->back->pdev->dev,\n+\t\t\t\"Cannot locate client instance open function\\n\");\n+\t\treturn;\n+\t}\n+\tif (!(test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state))) {\n+\t\tret = cinst->client->ops->open(&cinst->lan_info, cinst->client);\n+\t\tif (!ret)\n+\t\t\tset_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state);\n+\t}\n+}\n+\n+/**\n+ * i40evf_client_release_qvlist - send a message to the PF to release iwarp qv map\n+ * @ldev: pointer to L2 context.\n+ *\n+ * Return 0 on success or < 0 on error\n+ **/\n+static int i40evf_client_release_qvlist(struct i40e_info *ldev)\n+{\n+\tstruct i40evf_adapter *adapter = ldev->vf;\n+\ti40e_status err;\n+\n+\tif (adapter->aq_required)\n+\t\treturn -EAGAIN;\n+\n+\terr = i40e_aq_send_msg_to_pf(&adapter->hw,\n+\t\t\tI40E_VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP,\n+\t\t\tI40E_SUCCESS, NULL, 0, NULL);\n+\n+\tif (err)\n+\t\tdev_err(&adapter->pdev->dev,\n+\t\t\t\"Unable to send iWarp vector release message to PF, error %d, aq status %d\\n\",\n+\t\t\terr, adapter->hw.aq.asq_last_status);\n+\n+\treturn err;\n+}\n+\n+/**\n+ * i40evf_notify_client_close - call the client close callback\n+ * @vsi: the VSI with netdev closed\n+ * @reset: true when close called due to reset pending\n+ *\n+ * If there is a client to this netdev, call the client with close\n+ **/\n+void i40evf_notify_client_close(struct i40e_vsi *vsi, bool reset)\n+{\n+\tstruct i40evf_adapter *adapter = vsi->back;\n+\tstruct i40e_client_instance *cinst = adapter->cinst;\n+\n+\tif (!cinst || !cinst->client || !cinst->client->ops ||\n+\t    !cinst->client->ops->close) {\n+\t\tdev_dbg(&vsi->back->pdev->dev,\n+\t\t\t\"Cannot locate client instance close function\\n\");\n+\t\treturn;\n+\t}\n+\tcinst->client->ops->close(&cinst->lan_info, cinst->client, reset);\n+\ti40evf_client_release_qvlist(&cinst->lan_info);\n+\tclear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state);\n+}\n+\n+/**\n+ * i40evf_client_add_instance - add a client instance to the instance list\n+ * @adapter: pointer to the board struct\n+ * @client: pointer to a client struct in the client list.\n+ *\n+ * Returns cinst ptr on success, NULL on failure\n+ **/\n+static struct i40e_client_instance *\n+i40evf_client_add_instance(struct i40evf_adapter *adapter)\n+{\n+\tstruct i40e_client_instance *cinst = NULL;\n+\tstruct netdev_hw_addr *mac = NULL;\n+\tstruct i40e_vsi *vsi = &adapter->vsi;\n+\tint i;\n+\n+\tif (!vf_registered_client)\n+\t\tgoto out;\n+\n+\tif (adapter->cinst) {\n+\t\tcinst = adapter->cinst;\n+\t\tgoto out;\n+\t}\n+\n+\tcinst = kzalloc(sizeof(*cinst), GFP_KERNEL);\n+\tif (!cinst)\n+\t\tgoto out;\n+\n+\tcinst->lan_info.vf = (void *)adapter;\n+\tcinst->lan_info.netdev = vsi->netdev;\n+\tcinst->lan_info.pcidev = adapter->pdev;\n+\tcinst->lan_info.fid = 0;\n+\tcinst->lan_info.ftype = I40E_CLIENT_FTYPE_VF;\n+\tcinst->lan_info.hw_addr = adapter->hw.hw_addr;\n+\tcinst->lan_info.ops = &i40evf_lan_ops;\n+\tcinst->lan_info.version.major = I40EVF_CLIENT_VERSION_MAJOR;\n+\tcinst->lan_info.version.minor = I40EVF_CLIENT_VERSION_MINOR;\n+\tcinst->lan_info.version.build = I40EVF_CLIENT_VERSION_BUILD;\n+\tset_bit(__I40E_CLIENT_INSTANCE_NONE, &cinst->state);\n+\n+\tcinst->lan_info.msix_count = adapter->num_iwarp_msix;\n+\tcinst->lan_info.msix_entries =\n+\t\t\t&adapter->msix_entries[adapter->iwarp_base_vector];\n+\n+\tfor (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {\n+\t\tcinst->lan_info.params.qos.prio_qos[i].tc = 0;\n+\t\tcinst->lan_info.params.qos.prio_qos[i].qs_handle =\n+\t\t\t\t\t\t\t\tvsi->qs_handle;\n+\t}\n+\n+\tmac = list_first_entry(&cinst->lan_info.netdev->dev_addrs.list,\n+\t\t\t       struct netdev_hw_addr, list);\n+\tif (mac)\n+\t\tether_addr_copy(cinst->lan_info.lanmac, mac->addr);\n+\telse\n+\t\tdev_err(&adapter->pdev->dev, \"MAC address list is empty!\\n\");\n+\n+\tcinst->client = vf_registered_client;\n+\tadapter->cinst = cinst;\n+out:\n+\treturn cinst;\n+}\n+\n+/**\n+ * i40evf_client_del_instance - removes a client instance from the list\n+ * @adapter: pointer to the board struct\n+ * @client: pointer to the client struct\n+ *\n+ **/\n+static\n+void i40evf_client_del_instance(struct i40evf_adapter *adapter)\n+{\n+\tkfree(adapter->cinst);\n+\tadapter->cinst = NULL;\n+}\n+\n+/**\n+ * i40evf_client_subtask - client maintenance work\n+ * @adapter: board private structure\n+ **/\n+void i40evf_client_subtask(struct i40evf_adapter *adapter)\n+{\n+\tstruct i40e_client *client = vf_registered_client;\n+\tstruct i40e_client_instance *cinst;\n+\tint ret = 0;\n+\n+\tif (adapter->state < __I40EVF_DOWN)\n+\t\treturn;\n+\n+\t/* first check client is registered */\n+\tif (!client)\n+\t\treturn;\n+\n+\t/* Add the client instance to the instance list */\n+\tcinst = i40evf_client_add_instance(adapter);\n+\tif (!cinst)\n+\t\treturn;\n+\n+\tdev_info(&adapter->pdev->dev, \"Added instance of Client %s\\n\",\n+\t\t client->name);\n+\n+\tif (!test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state)) {\n+\t\t/* Send an Open request to the client */\n+\n+\t\tif (client->ops && client->ops->open)\n+\t\t\tret = client->ops->open(&cinst->lan_info, client);\n+\t\tif (!ret)\n+\t\t\tset_bit(__I40E_CLIENT_INSTANCE_OPENED,\n+\t\t\t\t&cinst->state);\n+\t\telse\n+\t\t\t/* remove client instance */\n+\t\t\ti40evf_client_del_instance(adapter);\n+\t}\n+}\n+\n+/**\n+ * i40evf_lan_add_device - add a lan device struct to the list of lan devices\n+ * @adapter: pointer to the board struct\n+ *\n+ * Returns 0 on success or none 0 on error\n+ **/\n+int i40evf_lan_add_device(struct i40evf_adapter *adapter)\n+{\n+\tstruct i40e_device *ldev;\n+\tint ret = 0;\n+\n+\tmutex_lock(&i40evf_device_mutex);\n+\tlist_for_each_entry(ldev, &i40evf_devices, list) {\n+\t\tif (ldev->vf == adapter) {\n+\t\t\tret = -EEXIST;\n+\t\t\tgoto out;\n+\t\t}\n+\t}\n+\tldev = kzalloc(sizeof(*ldev), GFP_KERNEL);\n+\tif (!ldev) {\n+\t\tret = -ENOMEM;\n+\t\tgoto out;\n+\t}\n+\tldev->vf = adapter;\n+\tINIT_LIST_HEAD(&ldev->list);\n+\tlist_add(&ldev->list, &i40evf_devices);\n+\tdev_info(&adapter->pdev->dev, \"Added LAN device bus=0x%02x dev=0x%02x func=0x%02x\\n\",\n+\t\t adapter->hw.bus.bus_id, adapter->hw.bus.device,\n+\t\t adapter->hw.bus.func);\n+\n+\t/* Since in some cases register may have happened before a device gets\n+\t * added, we can schedule a subtask to go initiate the clients.\n+\t */\n+\tadapter->flags |= I40EVF_FLAG_SERVICE_CLIENT_REQUESTED;\n+\n+out:\n+\tmutex_unlock(&i40evf_device_mutex);\n+\treturn ret;\n+}\n+\n+/**\n+ * i40evf_lan_del_device - removes a lan device from the device list\n+ * @adapter: pointer to the board struct\n+ *\n+ * Returns 0 on success or non-0 on error\n+ **/\n+int i40evf_lan_del_device(struct i40evf_adapter *adapter)\n+{\n+\tstruct i40e_device *ldev, *tmp;\n+\tint ret = -ENODEV;\n+\n+\tmutex_lock(&i40evf_device_mutex);\n+\tlist_for_each_entry_safe(ldev, tmp, &i40evf_devices, list) {\n+\t\tif (ldev->vf == adapter) {\n+\t\t\tdev_info(&adapter->pdev->dev,\n+\t\t\t\t \"Deleted LAN device bus=0x%02x dev=0x%02x func=0x%02x\\n\",\n+\t\t\t\t adapter->hw.bus.bus_id, adapter->hw.bus.device,\n+\t\t\t\t adapter->hw.bus.func);\n+\t\t\tlist_del(&ldev->list);\n+\t\t\tkfree(ldev);\n+\t\t\tret = 0;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tmutex_unlock(&i40evf_device_mutex);\n+\treturn ret;\n+}\n+\n+/**\n+ * i40evf_client_release - release client specific resources\n+ * @client: pointer to the registered client\n+ *\n+ **/\n+static void i40evf_client_release(struct i40e_client *client)\n+{\n+\tstruct i40e_client_instance *cinst;\n+\tstruct i40e_device *ldev;\n+\tstruct i40evf_adapter *adapter;\n+\n+\tmutex_lock(&i40evf_device_mutex);\n+\tlist_for_each_entry(ldev, &i40evf_devices, list) {\n+\t\tadapter = ldev->vf;\n+\t\tcinst = adapter->cinst;\n+\t\tif (!cinst)\n+\t\t\tcontinue;\n+\t\tif (test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state)) {\n+\t\t\tif (client->ops && client->ops->close)\n+\t\t\t\tclient->ops->close(&cinst->lan_info, client,\n+\t\t\t\t\t\t   false);\n+\t\t\ti40evf_client_release_qvlist(&cinst->lan_info);\n+\t\t\tclear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state);\n+\n+\t\t\tdev_warn(&adapter->pdev->dev,\n+\t\t\t\t \"Client %s instance closed\\n\", client->name);\n+\t\t}\n+\t\t/* delete the client instance */\n+\t\ti40evf_client_del_instance(adapter);\n+\t\tdev_info(&adapter->pdev->dev, \"Deleted client instance of Client %s\\n\",\n+\t\t\t client->name);\n+\t}\n+\tmutex_unlock(&i40evf_device_mutex);\n+}\n+\n+/**\n+ * i40evf_client_prepare - prepare client specific resources\n+ * @client: pointer to the registered client\n+ *\n+ **/\n+static void i40evf_client_prepare(struct i40e_client *client)\n+{\n+\tstruct i40e_device *ldev;\n+\tstruct i40evf_adapter *adapter;\n+\n+\tmutex_lock(&i40evf_device_mutex);\n+\tlist_for_each_entry(ldev, &i40evf_devices, list) {\n+\t\tadapter = ldev->vf;\n+\t\t/* Signal the watchdog to service the client */\n+\t\tadapter->flags |= I40EVF_FLAG_SERVICE_CLIENT_REQUESTED;\n+\t}\n+\tmutex_unlock(&i40evf_device_mutex);\n+}\n+\n+/**\n+ * i40evf_client_virtchnl_send - send a message to the PF instance\n+ * @ldev: pointer to L2 context.\n+ * @client: Client pointer.\n+ * @msg: pointer to message buffer\n+ * @len: message length\n+ *\n+ * Return 0 on success or < 0 on error\n+ **/\n+static u32 i40evf_client_virtchnl_send(struct i40e_info *ldev,\n+\t\t\t\t       struct i40e_client *client,\n+\t\t\t\t       u8 *msg, u16 len)\n+{\n+\tstruct i40evf_adapter *adapter = ldev->vf;\n+\ti40e_status err;\n+\n+\tif (adapter->aq_required)\n+\t\treturn -EAGAIN;\n+\n+\terr = i40e_aq_send_msg_to_pf(&adapter->hw, I40E_VIRTCHNL_OP_IWARP,\n+\t\t\t\t     I40E_SUCCESS, msg, len, NULL);\n+\tif (err)\n+\t\tdev_err(&adapter->pdev->dev, \"Unable to send iWarp message to PF, error %d, aq status %d\\n\",\n+\t\t\terr, adapter->hw.aq.asq_last_status);\n+\n+\treturn err;\n+}\n+\n+/**\n+ * i40evf_client_setup_qvlist - send a message to the PF to setup iwarp qv map\n+ * @ldev: pointer to L2 context.\n+ * @client: Client pointer.\n+ * @qv_info: queue and vector list\n+ *\n+ * Return 0 on success or < 0 on error\n+ **/\n+static int i40evf_client_setup_qvlist(struct i40e_info *ldev,\n+\t\t\t\t      struct i40e_client *client,\n+\t\t\t\t      struct i40e_qvlist_info *qvlist_info)\n+{\n+\tstruct i40e_virtchnl_iwarp_qvlist_info *v_qvlist_info;\n+\tstruct i40evf_adapter *adapter = ldev->vf;\n+\tstruct i40e_qv_info *qv_info;\n+\ti40e_status err;\n+\tu32 v_idx, i;\n+\tu32 msg_size;\n+\n+\tif (adapter->aq_required)\n+\t\treturn -EAGAIN;\n+\n+\t/* A quick check on whether the vectors belong to the client */\n+\tfor (i = 0; i < qvlist_info->num_vectors; i++) {\n+\t\tqv_info = &qvlist_info->qv_info[i];\n+\t\tif (!qv_info)\n+\t\t\tcontinue;\n+\t\tv_idx = qv_info->v_idx;\n+\t\tif ((v_idx >=\n+\t\t    (adapter->iwarp_base_vector + adapter->num_iwarp_msix)) ||\n+\t\t    (v_idx < adapter->iwarp_base_vector))\n+\t\t\treturn -EINVAL;\n+\t}\n+\n+\tv_qvlist_info = (struct i40e_virtchnl_iwarp_qvlist_info *)qvlist_info;\n+\tmsg_size = sizeof(struct i40e_virtchnl_iwarp_qvlist_info) +\n+\t\t\t(sizeof(struct i40e_virtchnl_iwarp_qv_info) *\n+\t\t\t(v_qvlist_info->num_vectors - 1));\n+\n+\tadapter->client_pending |= BIT(I40E_VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP);\n+\terr = i40e_aq_send_msg_to_pf(&adapter->hw,\n+\t\t\tI40E_VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP,\n+\t\t\tI40E_SUCCESS, (u8 *)v_qvlist_info, msg_size, NULL);\n+\n+\tif (err) {\n+\t\tdev_err(&adapter->pdev->dev,\n+\t\t\t\"Unable to send iWarp vector config message to PF, error %d, aq status %d\\n\",\n+\t\t\terr, adapter->hw.aq.asq_last_status);\n+\t\tgoto out;\n+\t}\n+\n+\terr = -EBUSY;\n+\tfor (i = 0; i < 5; i++) {\n+\t\tmsleep(100);\n+\t\tif (!(adapter->client_pending &\n+\t\t      BIT(I40E_VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP))) {\n+\t\t\terr = 0;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+out:\n+\treturn err;\n+}\n+\n+/**\n+ * i40evf_register_client - Register a i40e client driver with the L2 driver\n+ * @client: pointer to the i40e_client struct\n+ *\n+ * Returns 0 on success or non-0 on error\n+ **/\n+int i40evf_register_client(struct i40e_client *client)\n+{\n+\tint ret = 0;\n+\n+\tif (!client) {\n+\t\tret = -EIO;\n+\t\tgoto out;\n+\t}\n+\n+\tif (strlen(client->name) == 0) {\n+\t\tpr_info(\"i40evf: Failed to register client with no name\\n\");\n+\t\tret = -EIO;\n+\t\tgoto out;\n+\t}\n+\n+\tif (vf_registered_client) {\n+\t\tpr_info(\"i40evf: Client %s has already been registered!\\n\",\n+\t\t\tclient->name);\n+\t\tret = -EEXIST;\n+\t\tgoto out;\n+\t}\n+\n+\tif ((client->version.major != I40EVF_CLIENT_VERSION_MAJOR) ||\n+\t    (client->version.minor != I40EVF_CLIENT_VERSION_MINOR)) {\n+\t\tpr_info(\"i40evf: Failed to register client %s due to mismatched client interface version\\n\",\n+\t\t\tclient->name);\n+\t\tpr_info(\"Client is using version: %02d.%02d.%02d while LAN driver supports %s\\n\",\n+\t\t\tclient->version.major, client->version.minor,\n+\t\t\tclient->version.build,\n+\t\t\ti40evf_client_interface_version_str);\n+\t\tret = -EIO;\n+\t\tgoto out;\n+\t}\n+\n+\tvf_registered_client = client;\n+\n+\ti40evf_client_prepare(client);\n+\n+\tpr_info(\"i40evf: Registered client %s with return code %d\\n\",\n+\t\tclient->name, ret);\n+out:\n+\treturn ret;\n+}\n+EXPORT_SYMBOL(i40evf_register_client);\n+\n+/**\n+ * i40evf_unregister_client - Unregister a i40e client driver with the L2 driver\n+ * @client: pointer to the i40e_client struct\n+ *\n+ * Returns 0 on success or non-0 on error\n+ **/\n+int i40evf_unregister_client(struct i40e_client *client)\n+{\n+\tint ret = 0;\n+\n+\t/* When a unregister request comes through we would have to send\n+\t * a close for each of the client instances that were opened.\n+\t * client_release function is called to handle this.\n+\t */\n+\ti40evf_client_release(client);\n+\n+\tif (vf_registered_client != client) {\n+\t\tpr_info(\"i40evf: Client %s has not been registered\\n\",\n+\t\t\tclient->name);\n+\t\tret = -ENODEV;\n+\t\tgoto out;\n+\t}\n+\tvf_registered_client = NULL;\n+\tpr_info(\"i40evf: Unregistered client %s\\n\", client->name);\n+out:\n+\treturn ret;\n+}\n+EXPORT_SYMBOL(i40evf_unregister_client);\ndiff --git a/drivers/net/ethernet/intel/i40evf/i40evf_client.h b/drivers/net/ethernet/intel/i40evf/i40evf_client.h\nnew file mode 100644\nindex 0000000..7d283c7\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/i40evf/i40evf_client.h\n@@ -0,0 +1,166 @@\n+#ifndef _I40E_CLIENT_H_\n+#define _I40E_CLIENT_H_\n+\n+#define I40EVF_CLIENT_STR_LENGTH 10\n+\n+/* Client interface version should be updated anytime there is a change in the\n+ * existing APIs or data structures.\n+ */\n+#define I40EVF_CLIENT_VERSION_MAJOR 0\n+#define I40EVF_CLIENT_VERSION_MINOR 01\n+#define I40EVF_CLIENT_VERSION_BUILD 00\n+#define I40EVF_CLIENT_VERSION_STR     \\\n+\t__stringify(I40EVF_CLIENT_VERSION_MAJOR) \".\" \\\n+\t__stringify(I40EVF_CLIENT_VERSION_MINOR) \".\" \\\n+\t__stringify(I40EVF_CLIENT_VERSION_BUILD)\n+\n+struct i40e_client_version {\n+\tu8 major;\n+\tu8 minor;\n+\tu8 build;\n+\tu8 rsvd;\n+};\n+\n+enum i40e_client_state {\n+\t__I40E_CLIENT_NULL,\n+\t__I40E_CLIENT_REGISTERED\n+};\n+\n+enum i40e_client_instance_state {\n+\t__I40E_CLIENT_INSTANCE_NONE,\n+\t__I40E_CLIENT_INSTANCE_OPENED,\n+};\n+\n+struct i40e_ops;\n+struct i40e_client;\n+\n+/* HW does not define a type value for AEQ; only for RX/TX and CEQ.\n+ * In order for us to keep the interface simple, SW will define a\n+ * unique type value for AEQ.\n+ */\n+#define I40E_QUEUE_TYPE_PE_AEQ  0x80\n+#define I40E_QUEUE_INVALID_IDX\t0xFFFF\n+\n+struct i40e_qv_info {\n+\tu32 v_idx; /* msix_vector */\n+\tu16 ceq_idx;\n+\tu16 aeq_idx;\n+\tu8 itr_idx;\n+};\n+\n+struct i40e_qvlist_info {\n+\tu32 num_vectors;\n+\tstruct i40e_qv_info qv_info[1];\n+};\n+\n+#define I40E_CLIENT_MSIX_ALL 0xFFFFFFFF\n+\n+/* set of LAN parameters useful for clients managed by LAN */\n+\n+/* Struct to hold per priority info */\n+struct i40e_prio_qos_params {\n+\tu16 qs_handle; /* qs handle for prio */\n+\tu8 tc; /* TC mapped to prio */\n+\tu8 reserved;\n+};\n+\n+#define I40E_CLIENT_MAX_USER_PRIORITY        8\n+/* Struct to hold Client QoS */\n+struct i40e_qos_params {\n+\tstruct i40e_prio_qos_params prio_qos[I40E_CLIENT_MAX_USER_PRIORITY];\n+};\n+\n+struct i40e_params {\n+\tstruct i40e_qos_params qos;\n+\tu16 mtu;\n+\tu16 link_up; /* boolean */\n+};\n+\n+/* Structure to hold LAN device info for a client device */\n+struct i40e_info {\n+\tstruct i40e_client_version version;\n+\tu8 lanmac[6];\n+\tstruct net_device *netdev;\n+\tstruct pci_dev *pcidev;\n+\tu8 __iomem *hw_addr;\n+\tu8 fid;\t/* function id, PF id or VF id */\n+#define I40E_CLIENT_FTYPE_PF 0\n+#define I40E_CLIENT_FTYPE_VF 1\n+\tu8 ftype; /* function type, PF or VF */\n+\tvoid *vf; /* cast to i40evf_adapter */\n+\n+\t/* All L2 params that could change during the life span of the device\n+\t * and needs to be communicated to the client when they change\n+\t */\n+\tstruct i40e_params params;\n+\tstruct i40e_ops *ops;\n+\n+\tu16 msix_count;\t /* number of msix vectors*/\n+\t/* Array down below will be dynamically allocated based on msix_count */\n+\tstruct msix_entry *msix_entries;\n+\tu16 itr_index; /* Which ITR index the PE driver is suppose to use */\n+};\n+\n+struct i40e_ops {\n+\t/* setup_q_vector_list enables queues with a particular vector */\n+\tint (*setup_qvlist)(struct i40e_info *ldev, struct i40e_client *client,\n+\t\t\t    struct i40e_qvlist_info *qv_info);\n+\n+\tu32 (*virtchnl_send)(struct i40e_info *ldev, struct i40e_client *client,\n+\t\t\t     u8 *msg, u16 len);\n+\n+\t/* If the PE Engine is unresponsive, RDMA driver can request a reset.*/\n+\tvoid (*request_reset)(struct i40e_info *ldev,\n+\t\t\t      struct i40e_client *client);\n+};\n+\n+struct i40e_client_ops {\n+\t/* Should be called from register_client() or whenever the driver is\n+\t * ready to create a specific client instance.\n+\t */\n+\tint (*open)(struct i40e_info *ldev, struct i40e_client *client);\n+\n+\t/* Should be closed when netdev is unavailable or when unregister\n+\t * call comes in. If the close happens due to a reset, set the reset\n+\t * bit to true.\n+\t */\n+\tvoid (*close)(struct i40e_info *ldev, struct i40e_client *client,\n+\t\t      bool reset);\n+\n+\t/* called when some l2 managed parameters changes - mss */\n+\tvoid (*l2_param_change)(struct i40e_info *ldev,\n+\t\t\t\tstruct i40e_client *client,\n+\t\t\t\tstruct i40e_params *params);\n+\n+\t/* called when a message is received from the PF */\n+\tint (*virtchnl_receive)(struct i40e_info *ldev,\n+\t\t\t\tstruct i40e_client *client,\n+\t\t\t\tu8 *msg, u16 len);\n+};\n+\n+/* Client device */\n+struct i40e_client_instance {\n+\tstruct list_head list;\n+\tstruct i40e_info lan_info;\n+\tstruct i40e_client *client;\n+\tunsigned long  state;\n+};\n+\n+struct i40e_client {\n+\tstruct list_head list;\t\t/* list of registered clients */\n+\tchar name[I40EVF_CLIENT_STR_LENGTH];\n+\tstruct i40e_client_version version;\n+\tunsigned long state;\t\t/* client state */\n+\tatomic_t ref_cnt;  /* Count of all the client devices of this kind */\n+\tu32 flags;\n+#define I40E_CLIENT_FLAGS_LAUNCH_ON_PROBE\tBIT(0)\n+#define I40E_TX_FLAGS_NOTIFY_OTHER_EVENTS\tBIT(2)\n+\tu8 type;\n+#define I40E_CLIENT_IWARP 0\n+\tstruct i40e_client_ops *ops;\t/* client ops provided by the client */\n+};\n+\n+/* used by clients */\n+int i40evf_register_client(struct i40e_client *client);\n+int i40evf_unregister_client(struct i40e_client *client);\n+#endif /* _I40E_CLIENT_H_ */\ndiff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c\nindex f35dcaa..9492b20 100644\n--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c\n+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c\n@@ -26,6 +26,7 @@\n \n #include \"i40evf.h\"\n #include \"i40e_prototype.h\"\n+#include \"i40evf_client.h\"\n static int i40evf_setup_all_tx_resources(struct i40evf_adapter *adapter);\n static int i40evf_setup_all_rx_resources(struct i40evf_adapter *adapter);\n static int i40evf_close(struct net_device *netdev);\n@@ -1058,6 +1059,8 @@ static void i40evf_up_complete(struct i40evf_adapter *adapter)\n \ti40evf_napi_enable_all(adapter);\n \n \tadapter->aq_required |= I40EVF_FLAG_AQ_ENABLE_QUEUES;\n+\tif (CLIENT_ENABLED(adapter))\n+\t\tadapter->flags |= I40EVF_FLAG_CLIENT_NEEDS_OPEN;\n \tmod_timer_pending(&adapter->watchdog_timer, jiffies + 1);\n }\n \n@@ -1685,6 +1688,7 @@ static void i40evf_watchdog_task(struct work_struct *work)\n \t\ti40evf_set_promiscuous(adapter, 0);\n \t\tgoto watchdog_done;\n \t}\n+\tschedule_delayed_work(&adapter->client_task, msecs_to_jiffies(5));\n \n \tif (adapter->state == __I40EVF_RUNNING)\n \t\ti40evf_request_stats(adapter);\n@@ -1773,10 +1777,17 @@ static void i40evf_reset_task(struct work_struct *work)\n \tu32 reg_val;\n \tint i = 0, err;\n \n-\twhile (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,\n+\twhile (test_and_set_bit(__I40EVF_IN_CLIENT_TASK,\n \t\t\t\t&adapter->crit_section))\n \t\tusleep_range(500, 1000);\n-\n+\tif (CLIENT_ENABLED(adapter)) {\n+\t\tadapter->flags &= ~(I40EVF_FLAG_CLIENT_NEEDS_OPEN |\n+\t\t\t\t    I40EVF_FLAG_CLIENT_NEEDS_CLOSE |\n+\t\t\t\t    I40EVF_FLAG_CLIENT_NEEDS_L2_PARAMS |\n+\t\t\t\t    I40EVF_FLAG_SERVICE_CLIENT_REQUESTED);\n+\t\tcancel_delayed_work_sync(&adapter->client_task);\n+\t\ti40evf_notify_client_close(&adapter->vsi, true);\n+\t}\n \ti40evf_misc_irq_disable(adapter);\n \tif (adapter->flags & I40EVF_FLAG_RESET_NEEDED) {\n \t\tadapter->flags &= ~I40EVF_FLAG_RESET_NEEDED;\n@@ -1819,6 +1830,7 @@ static void i40evf_reset_task(struct work_struct *work)\n \t\tdev_err(&adapter->pdev->dev, \"Reset never finished (%x)\\n\",\n \t\t\treg_val);\n \t\ti40evf_disable_vf(adapter);\n+\t\tclear_bit(__I40EVF_IN_CLIENT_TASK, &adapter->crit_section);\n \t\treturn; /* Do not attempt to reinit. It's dead, Jim. */\n \t}\n \n@@ -1861,9 +1873,8 @@ static void i40evf_reset_task(struct work_struct *work)\n \t}\n \tadapter->aq_required |= I40EVF_FLAG_AQ_ADD_MAC_FILTER;\n \tadapter->aq_required |= I40EVF_FLAG_AQ_ADD_VLAN_FILTER;\n-\t/* Open RDMA Client again */\n-\tadapter->aq_required |= I40EVF_FLAG_SERVICE_CLIENT_REQUESTED;\n \tclear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);\n+\tclear_bit(__I40EVF_IN_CLIENT_TASK, &adapter->crit_section);\n \ti40evf_misc_irq_enable(adapter);\n \n \tmod_timer(&adapter->watchdog_timer, jiffies + 2);\n@@ -1980,6 +1991,48 @@ static void i40evf_adminq_task(struct work_struct *work)\n }\n \n /**\n+ * i40evf_client_task - worker thread to perform client work\n+ * @work: pointer to work_struct containing our data\n+ *\n+ * This task handles client interactions. Because client calls can be\n+ * reentrant, we can't handle them in the watchdog.\n+ **/\n+static void i40evf_client_task(struct work_struct *work)\n+{\n+\tstruct i40evf_adapter *adapter =\n+\t\tcontainer_of(work, struct i40evf_adapter, client_task.work);\n+\n+\t/* If we can't get the client bit, just give up. We'll be rescheduled\n+\t * later.\n+\t */\n+\n+\tif (test_and_set_bit(__I40EVF_IN_CLIENT_TASK, &adapter->crit_section))\n+\t\treturn;\n+\n+\tif (adapter->flags & I40EVF_FLAG_SERVICE_CLIENT_REQUESTED) {\n+\t\ti40evf_client_subtask(adapter);\n+\t\tadapter->flags &= ~I40EVF_FLAG_SERVICE_CLIENT_REQUESTED;\n+\t\tgoto out;\n+\t}\n+\tif (adapter->flags & I40EVF_FLAG_CLIENT_NEEDS_CLOSE) {\n+\t\ti40evf_notify_client_close(&adapter->vsi, false);\n+\t\tadapter->flags &= ~I40EVF_FLAG_CLIENT_NEEDS_CLOSE;\n+\t\tgoto out;\n+\t}\n+\tif (adapter->flags & I40EVF_FLAG_CLIENT_NEEDS_OPEN) {\n+\t\ti40evf_notify_client_open(&adapter->vsi);\n+\t\tadapter->flags &= ~I40EVF_FLAG_CLIENT_NEEDS_OPEN;\n+\t\tgoto out;\n+\t}\n+\tif (adapter->flags & I40EVF_FLAG_CLIENT_NEEDS_L2_PARAMS) {\n+\t\ti40evf_notify_client_l2_params(&adapter->vsi);\n+\t\tadapter->flags &= ~I40EVF_FLAG_CLIENT_NEEDS_L2_PARAMS;\n+\t}\n+out:\n+\tclear_bit(__I40EVF_IN_CLIENT_TASK, &adapter->crit_section);\n+}\n+\n+/**\n  * i40evf_free_all_tx_resources - Free Tx Resources for All Queues\n  * @adapter: board private structure\n  *\n@@ -2148,6 +2201,8 @@ static int i40evf_close(struct net_device *netdev)\n \n \n \tset_bit(__I40E_DOWN, &adapter->vsi.state);\n+\tif (CLIENT_ENABLED(adapter))\n+\t\tadapter->flags |= I40EVF_FLAG_CLIENT_NEEDS_CLOSE;\n \n \ti40evf_down(adapter);\n \tadapter->state = __I40EVF_DOWN_PENDING;\n@@ -2188,6 +2243,10 @@ static int i40evf_change_mtu(struct net_device *netdev, int new_mtu)\n \tstruct i40evf_adapter *adapter = netdev_priv(netdev);\n \n \tnetdev->mtu = new_mtu;\n+\tif (CLIENT_ENABLED(adapter)) {\n+\t\ti40evf_notify_client_l2_params(&adapter->vsi);\n+\t\tadapter->flags |= I40EVF_FLAG_SERVICE_CLIENT_REQUESTED;\n+\t}\n \tadapter->flags |= I40EVF_FLAG_RESET_NEEDED;\n \tschedule_work(&adapter->reset_task);\n \n@@ -2581,6 +2640,12 @@ static void i40evf_init_task(struct work_struct *work)\n \tadapter->netdev_registered = true;\n \n \tnetif_tx_stop_all_queues(netdev);\n+\tif (CLIENT_ALLOWED(adapter)) {\n+\t\terr = i40evf_lan_add_device(adapter);\n+\t\tif (err)\n+\t\t\tdev_info(&pdev->dev, \"Failed to add VF to client API service list: %d\\n\",\n+\t\t\t\t err);\n+\t}\n \n \tdev_info(&pdev->dev, \"MAC address: %pM\\n\", adapter->hw.mac.addr);\n \tif (netdev->features & NETIF_F_GRO)\n@@ -2745,6 +2810,7 @@ static int i40evf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)\n \tINIT_WORK(&adapter->reset_task, i40evf_reset_task);\n \tINIT_WORK(&adapter->adminq_task, i40evf_adminq_task);\n \tINIT_WORK(&adapter->watchdog_task, i40evf_watchdog_task);\n+\tINIT_DELAYED_WORK(&adapter->client_task, i40evf_client_task);\n \tINIT_DELAYED_WORK(&adapter->init_task, i40evf_init_task);\n \tschedule_delayed_work(&adapter->init_task,\n \t\t\t      msecs_to_jiffies(5 * (pdev->devfn & 0x07)));\n@@ -2857,14 +2923,21 @@ static void i40evf_remove(struct pci_dev *pdev)\n \tstruct i40evf_adapter *adapter = netdev_priv(netdev);\n \tstruct i40evf_mac_filter *f, *ftmp;\n \tstruct i40e_hw *hw = &adapter->hw;\n+\tint err;\n \n \tcancel_delayed_work_sync(&adapter->init_task);\n \tcancel_work_sync(&adapter->reset_task);\n-\n+\tcancel_delayed_work_sync(&adapter->client_task);\n \tif (adapter->netdev_registered) {\n \t\tunregister_netdev(netdev);\n \t\tadapter->netdev_registered = false;\n \t}\n+\tif (CLIENT_ALLOWED(adapter)) {\n+\t\terr = i40evf_lan_del_device(adapter);\n+\t\tif (err)\n+\t\t\tdev_warn(&pdev->dev, \"Failed to delete client device: %d\\n\",\n+\t\t\t\t err);\n+\t}\n \n \t/* Shut down all the garbage mashers on the detention level */\n \tadapter->state = __I40EVF_REMOVE;\ndiff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c\nindex bee58af..a2a7354 100644\n--- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c\n+++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c\n@@ -26,6 +26,7 @@\n \n #include \"i40evf.h\"\n #include \"i40e_prototype.h\"\n+#include \"i40evf_client.h\"\n \n /* busy wait delay in msec */\n #define I40EVF_BUSY_WAIT_DELAY 10\n@@ -999,6 +1000,16 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,\n \t\tif (v_opcode != adapter->current_op)\n \t\t\treturn;\n \t\tbreak;\n+\tcase I40E_VIRTCHNL_OP_IWARP:\n+\t\t/* Gobble zero-length replies from the PF. They indicate that\n+\t\t * a previous message was received OK, and the client doesn't\n+\t\t * care about that.\n+\t\t */\n+\t\tif (msglen && CLIENT_ENABLED(adapter))\n+\t\t\ti40evf_notify_client_message(&adapter->vsi,\n+\t\t\t\t\t\t     msg, msglen);\n+\t\tbreak;\n+\n \tcase I40E_VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP:\n \t\tadapter->client_pending &=\n \t\t\t\t~(BIT(I40E_VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP));\n@@ -1014,7 +1025,7 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,\n \t\t}\n \t\tbreak;\n \tdefault:\n-\t\tif (v_opcode != adapter->current_op)\n+\t\tif (adapter->current_op && (v_opcode != adapter->current_op))\n \t\t\tdev_warn(&adapter->pdev->dev, \"Expected response %d from PF, received %d\\n\",\n \t\t\t\t adapter->current_op, v_opcode);\n \t\tbreak;\n",
    "prefixes": [
        "next",
        "S58-V3",
        "2/4"
    ]
}