{"id":2223071,"url":"http://patchwork.ozlabs.org/api/1.0/patches/2223071/?format=json","project":{"id":46,"url":"http://patchwork.ozlabs.org/api/1.0/projects/46/?format=json","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":""},"msgid":"<20260414110006.124286-4-jtornosm@redhat.com>","date":"2026-04-14T11:00:04","name":"[net,v3,3/5] iavf: send MAC change request synchronously","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"d546e8ae5085d2a05a443236a7e9ab41aef099bb","submitter":{"id":93070,"url":"http://patchwork.ozlabs.org/api/1.0/people/93070/?format=json","name":"Jose Ignacio Tornos Martinez","email":"jtornosm@redhat.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20260414110006.124286-4-jtornosm@redhat.com/mbox/","series":[{"id":499816,"url":"http://patchwork.ozlabs.org/api/1.0/series/499816/?format=json","date":"2026-04-14T11:00:01","name":"Fix i40e/ice/iavf VF bonding after netdev lock changes","version":3,"mbox":"http://patchwork.ozlabs.org/series/499816/mbox/"}],"check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2223071/checks/","tags":{},"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@legolas.ozlabs.org","intel-wired-lan@lists.osuosl.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=osuosl.org header.i=@osuosl.org header.a=rsa-sha256\n header.s=default header.b=dhySBGLG;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=osuosl.org\n (client-ip=2605:bc80:3010::138; helo=smtp1.osuosl.org;\n envelope-from=intel-wired-lan-bounces@osuosl.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fw1XV4d3yz1yDF\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 14 Apr 2026 21:00:42 +1000 (AEST)","from localhost (localhost [127.0.0.1])\n\tby smtp1.osuosl.org (Postfix) with ESMTP id 1EAE584C0F;\n\tTue, 14 Apr 2026 11:00:41 +0000 (UTC)","from smtp1.osuosl.org ([127.0.0.1])\n by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id BpQ9Va5BopIf; Tue, 14 Apr 2026 11:00:40 +0000 (UTC)","from lists1.osuosl.org (lists1.osuosl.org [140.211.166.142])\n\tby smtp1.osuosl.org (Postfix) with ESMTP id 026FE84C12;\n\tTue, 14 Apr 2026 11:00:40 +0000 (UTC)","from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138])\n by lists1.osuosl.org (Postfix) with ESMTP id 1DDD4237\n for <intel-wired-lan@lists.osuosl.org>; Tue, 14 Apr 2026 11:00:39 +0000 (UTC)","from localhost (localhost [127.0.0.1])\n by smtp1.osuosl.org (Postfix) with ESMTP id 0F65084C0F\n for <intel-wired-lan@lists.osuosl.org>; Tue, 14 Apr 2026 11:00:39 +0000 (UTC)","from smtp1.osuosl.org ([127.0.0.1])\n by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id mrJhuBCc4MKw for <intel-wired-lan@lists.osuosl.org>;\n Tue, 14 Apr 2026 11:00:38 +0000 (UTC)","from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by smtp1.osuosl.org (Postfix) with ESMTPS id C324D84C12\n for <intel-wired-lan@lists.osuosl.org>; Tue, 14 Apr 2026 11:00:37 +0000 (UTC)","from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-104-VOVcol09PqqHg_dO-BbPpg-1; Tue,\n 14 Apr 2026 07:00:33 -0400","from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id 306541800744; Tue, 14 Apr 2026 11:00:32 +0000 (UTC)","from fedora.redhat.com (unknown [10.44.48.43])\n by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id EC7E33000C16; Tue, 14 Apr 2026 11:00:27 +0000 (UTC)"],"X-Virus-Scanned":["amavis at osuosl.org","amavis at osuosl.org"],"X-Comment":"SPF check N/A for local connections - client-ip=140.211.166.142;\n helo=lists1.osuosl.org; envelope-from=intel-wired-lan-bounces@osuosl.org;\n receiver=<UNKNOWN> ","DKIM-Filter":["OpenDKIM Filter v2.11.0 smtp1.osuosl.org 026FE84C12","OpenDKIM Filter v2.11.0 smtp1.osuosl.org C324D84C12"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=osuosl.org;\n\ts=default; t=1776164440;\n\tbh=ofJfl+nF48wvj1XEymT1GwNhOqCH45oNIOPxHsKnjbU=;\n\th=From:To:Cc:Date:In-Reply-To:References:Subject:List-Id:\n\t List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe:\n\t From;\n\tb=dhySBGLG5XYA7T0eIQAjiV5xbFrsHeNJPMcmAWdeCK9mkLRRLJIGCH62oTwsGvLI8\n\t SxRSVAZ9FDJgDA60Tm8+qs5F7TwCyudxinDiNjvZT09e678EI7/wZhuAW3CSYtKcoX\n\t eMSbeSnO1m0P4iflR2hvTrKPUJM/xKPOTf5me5PDz1Rn9rpeO4FVZdGv5U4C2HnHCi\n\t no7T4dp3bogX/bwNSm09HFBG084sZA82gzzVyaSpzPFDwxMMQGaPKsI2idCMJ3O4UW\n\t /WC3EL1JDvt+XZUpb4CENpjmDYM1F0Ge01vJzWnDO8f6/lqzxLgVEk1DMIdNJu97VT\n\t tVl7uZO6pFELw==","Received-SPF":"Pass (mailfrom) identity=mailfrom; client-ip=170.10.133.124;\n helo=us-smtp-delivery-124.mimecast.com; envelope-from=jtornosm@redhat.com;\n receiver=<UNKNOWN>","DMARC-Filter":"OpenDMARC Filter v1.4.2 smtp1.osuosl.org C324D84C12","X-MC-Unique":"VOVcol09PqqHg_dO-BbPpg-1","X-Mimecast-MFC-AGG-ID":"VOVcol09PqqHg_dO-BbPpg_1776164432","From":"Jose Ignacio Tornos Martinez <jtornosm@redhat.com>","To":"netdev@vger.kernel.org","Cc":"intel-wired-lan@lists.osuosl.org, jesse.brandeburg@intel.com,\n anthony.l.nguyen@intel.com, davem@davemloft.net, edumazet@google.com,\n kuba@kernel.org, pabeni@redhat.com,\n Jose Ignacio Tornos Martinez <jtornosm@redhat.com>, stable@vger.kernel.org","Date":"Tue, 14 Apr 2026 13:00:04 +0200","Message-ID":"<20260414110006.124286-4-jtornosm@redhat.com>","In-Reply-To":"<20260414110006.124286-1-jtornosm@redhat.com>","References":"<20260414110006.124286-1-jtornosm@redhat.com>","MIME-Version":"1.0","X-Scanned-By":"MIMEDefang 3.4.1 on 10.30.177.4","X-Mimecast-MFC-PROC-ID":"Ml8951-7gdKpW6SeaHYKLo-1CWQzaSgrA_YaqlaU9Yc_1776164432","X-Mimecast-Originator":"redhat.com","Content-Transfer-Encoding":"8bit","content-type":"text/plain; charset=\"US-ASCII\"; x-default=true","X-Mailman-Original-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=redhat.com;\n s=mimecast20190719; t=1776164436;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=ofJfl+nF48wvj1XEymT1GwNhOqCH45oNIOPxHsKnjbU=;\n b=Relbj6UYDDngHCJ0DYMnZk7R8LDgvGhwwBj/gqAwJM48NTD1soBN1nTeqjtTeyLupnAuhL\n buWyj67aMimHkVG5KYNisEDVp0ZoBmo5sZck/Cw4DeU4HhaiYhEI1azXK04Vf8Fm7G79rm\n I6oq6qGkLVb+GTs6FU8lfC1ViPadurk=","X-Mailman-Original-Authentication-Results":["smtp1.osuosl.org;\n dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com","smtp1.osuosl.org;\n dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com\n header.a=rsa-sha256 header.s=mimecast20190719 header.b=Relbj6UY"],"Subject":"[Intel-wired-lan] [PATCH net v3 3/5] iavf: send MAC change request\n synchronously","X-BeenThere":"intel-wired-lan@osuosl.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"Intel Wired Ethernet Linux Kernel Driver Development\n <intel-wired-lan.osuosl.org>","List-Unsubscribe":"<https://lists.osuosl.org/mailman/options/intel-wired-lan>,\n <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 <mailto:intel-wired-lan-request@osuosl.org?subject=subscribe>","Errors-To":"intel-wired-lan-bounces@osuosl.org","Sender":"\"Intel-wired-lan\" <intel-wired-lan-bounces@osuosl.org>"},"content":"After commit ad7c7b2172c3 (\"net: hold netdev instance lock during sysfs\noperations\"), iavf_set_mac() is called with the netdev instance lock\nalready held.\n\nThe function queues a MAC address change request via\niavf_replace_primary_mac() and then waits for completion. However, in\nthe current flow, the actual virtchnl message is sent by the watchdog\ntask, which also needs to acquire the netdev lock to run. Additionally,\nthe adminq_task which processes virtchnl responses also needs the netdev\nlock.\n\nThis creates a deadlock scenario:\n1. iavf_set_mac() holds netdev lock and waits for MAC change\n2. Watchdog needs netdev lock to send the request -> blocked\n3. Even if request is sent, adminq_task needs netdev lock to process\n   PF response -> blocked\n4. MAC change times out after 2.5 seconds\n5. iavf_set_mac() returns -EAGAIN\n\nThis particularly affects VFs during bonding setup when multiple VFs are\nenslaved in quick succession.\n\nFix by implementing a synchronous MAC change operation similar to the\napproach used in commit fdadbf6e84c4 (\"iavf: fix incorrect reset handling\nin callbacks\").\n\nThe solution:\n1. Send the virtchnl ADD_ETH_ADDR message directly (not via watchdog)\n2. Poll the admin queue hardware directly for responses\n3. Process all received messages (including non-MAC messages)\n4. Return when MAC change completes or times out\n\nA new generic function iavf_poll_virtchnl_response() is introduced that\ncan be reused for any future synchronous virtchnl operations. It takes a\ncallback to check completion, allowing flexible condition checking.\n\nThis allows the operation to complete synchronously while holding\nnetdev_lock, without relying on watchdog or adminq_task. The function\ncan sleep for up to 2.5 seconds polling hardware, but this is acceptable\nsince netdev_lock is per-device and only serializes operations on the\nsame interface.\n\nTo support this, change iavf_add_ether_addrs() to return an error code\ninstead of void, allowing callers to detect failures.\n\nFixes: ad7c7b2172c3 (\"net: hold netdev instance lock during sysfs operations\")\ncc: stable@vger.kernel.org\nSigned-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>\n---\nv3: Complete with Przemek Kitszel comments:                                                                                                                                           \n    - Moved iavf_poll_virtchnl_response() to iavf_virtchnl.c for reusability                                                                                                                                               \n    - Changed kdoc to use \"Return:\" instead of \"Returns\"                                                                                                                                                                   \n    - Changed to do-while loop structure                                                                                                                                                                                   \n    - Added pending parameter to skip sleep when more messages queued                                                                                                                                                      \n    - Reduced sleep time to 50-75 usec (from 1000-2000, per commit 9e3f23f44f32)                                                                                                                                           \n    - Added v_opcode parameter for standard completion checking                                                                                                                                                            \n    - Callback parameter takes priority over opcode check                                                                                                                                                                  \n    - Made cond_data parameter const                                                                                                                                                                                       \n    - Final condition check after timeout before returning -EAGAIN                                                                                                                                                         \nv2: https://lore.kernel.org/netdev/20260407165206.1121317-4-jtornosm@redhat.com/\n\n drivers/net/ethernet/intel/iavf/iavf.h        |   7 +-\n drivers/net/ethernet/intel/iavf/iavf_main.c   |  57 ++++++---\n .../net/ethernet/intel/iavf/iavf_virtchnl.c   | 111 +++++++++++++++++-\n 3 files changed, 155 insertions(+), 20 deletions(-)","diff":"diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h\nindex e9fb0a0919e3..b012a91b0252 100644\n--- a/drivers/net/ethernet/intel/iavf/iavf.h\n+++ b/drivers/net/ethernet/intel/iavf/iavf.h\n@@ -589,7 +589,7 @@ void iavf_configure_queues(struct iavf_adapter *adapter);\n void iavf_enable_queues(struct iavf_adapter *adapter);\n void iavf_disable_queues(struct iavf_adapter *adapter);\n void iavf_map_queues(struct iavf_adapter *adapter);\n-void iavf_add_ether_addrs(struct iavf_adapter *adapter);\n+int iavf_add_ether_addrs(struct iavf_adapter *adapter);\n void iavf_del_ether_addrs(struct iavf_adapter *adapter);\n void iavf_add_vlans(struct iavf_adapter *adapter);\n void iavf_del_vlans(struct iavf_adapter *adapter);\n@@ -607,6 +607,11 @@ void iavf_disable_vlan_stripping(struct iavf_adapter *adapter);\n void iavf_virtchnl_completion(struct iavf_adapter *adapter,\n \t\t\t      enum virtchnl_ops v_opcode,\n \t\t\t      enum iavf_status v_retval, u8 *msg, u16 msglen);\n+int iavf_poll_virtchnl_response(struct iavf_adapter *adapter,\n+\t\t\t\tbool (*condition)(struct iavf_adapter *, const void *),\n+\t\t\t\tconst void *cond_data,\n+\t\t\t\tenum virtchnl_ops v_opcode,\n+\t\t\t\tunsigned int timeout_ms);\n int iavf_config_rss(struct iavf_adapter *adapter);\n void iavf_cfg_queues_bw(struct iavf_adapter *adapter);\n void iavf_cfg_queues_quanta_size(struct iavf_adapter *adapter);\ndiff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c\nindex 67aa14350b1b..80277d495a8d 100644\n--- a/drivers/net/ethernet/intel/iavf/iavf_main.c\n+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c\n@@ -1047,6 +1047,46 @@ static bool iavf_is_mac_set_handled(struct net_device *netdev,\n \treturn ret;\n }\n \n+/**\n+ * iavf_mac_change_done - Check if MAC change completed\n+ * @adapter: board private structure\n+ * @data: MAC address being checked (as const void *)\n+ *\n+ * Callback for iavf_poll_virtchnl_response() to check if MAC change completed.\n+ *\n+ * Returns true if MAC change completed, false otherwise\n+ */\n+static bool iavf_mac_change_done(struct iavf_adapter *adapter, const void *data)\n+{\n+\tconst u8 *addr = data;\n+\n+\treturn iavf_is_mac_set_handled(adapter->netdev, addr);\n+}\n+\n+/**\n+ * iavf_set_mac_sync - Synchronously change MAC address\n+ * @adapter: board private structure\n+ * @addr: MAC address to set\n+ *\n+ * Sends MAC change request to PF and polls admin queue for response.\n+ * Caller must hold netdev_lock. This can sleep for up to 2.5 seconds.\n+ *\n+ * Returns 0 on success, negative on failure\n+ */\n+static int iavf_set_mac_sync(struct iavf_adapter *adapter, const u8 *addr)\n+{\n+\tint ret;\n+\n+\tnetdev_assert_locked(adapter->netdev);\n+\n+\tret = iavf_add_ether_addrs(adapter);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn iavf_poll_virtchnl_response(adapter, iavf_mac_change_done, addr,\n+\t\t\t\t\t   VIRTCHNL_OP_UNKNOWN, 2500);\n+}\n+\n /**\n  * iavf_set_mac - NDO callback to set port MAC address\n  * @netdev: network interface device structure\n@@ -1067,26 +1107,13 @@ static int iavf_set_mac(struct net_device *netdev, void *p)\n \t\treturn -EADDRNOTAVAIL;\n \n \tret = iavf_replace_primary_mac(adapter, addr->sa_data);\n-\n \tif (ret)\n \t\treturn ret;\n \n-\tret = wait_event_interruptible_timeout(adapter->vc_waitqueue,\n-\t\t\t\t\t       iavf_is_mac_set_handled(netdev, addr->sa_data),\n-\t\t\t\t\t       msecs_to_jiffies(2500));\n-\n-\t/* If ret < 0 then it means wait was interrupted.\n-\t * If ret == 0 then it means we got a timeout.\n-\t * else it means we got response for set MAC from PF,\n-\t * check if netdev MAC was updated to requested MAC,\n-\t * if yes then set MAC succeeded otherwise it failed return -EACCES\n-\t */\n-\tif (ret < 0)\n+\tret = iavf_set_mac_sync(adapter, addr->sa_data);\n+\tif (ret)\n \t\treturn ret;\n \n-\tif (!ret)\n-\t\treturn -EAGAIN;\n-\n \tif (!ether_addr_equal(netdev->dev_addr, addr->sa_data))\n \t\treturn -EACCES;\n \ndiff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c\nindex a52c100dcbc5..df124f840ddb 100644\n--- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c\n+++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c\n@@ -2,6 +2,7 @@\n /* Copyright(c) 2013 - 2018 Intel Corporation. */\n \n #include <linux/net/intel/libie/rx.h>\n+#include <net/netdev_lock.h>\n \n #include \"iavf.h\"\n #include \"iavf_ptp.h\"\n@@ -555,8 +556,10 @@ iavf_set_mac_addr_type(struct virtchnl_ether_addr *virtchnl_ether_addr,\n  * @adapter: adapter structure\n  *\n  * Request that the PF add one or more addresses to our filters.\n+ *\n+ * Return: 0 on success, negative on failure\n  **/\n-void iavf_add_ether_addrs(struct iavf_adapter *adapter)\n+int iavf_add_ether_addrs(struct iavf_adapter *adapter)\n {\n \tstruct virtchnl_ether_addr_list *veal;\n \tstruct iavf_mac_filter *f;\n@@ -568,7 +571,7 @@ void iavf_add_ether_addrs(struct iavf_adapter *adapter)\n \t\t/* bail because we already have a command pending */\n \t\tdev_err(&adapter->pdev->dev, \"Cannot add filters, command %d pending\\n\",\n \t\t\tadapter->current_op);\n-\t\treturn;\n+\t\treturn -EBUSY;\n \t}\n \n \tspin_lock_bh(&adapter->mac_vlan_list_lock);\n@@ -580,7 +583,7 @@ void iavf_add_ether_addrs(struct iavf_adapter *adapter)\n \tif (!count) {\n \t\tadapter->aq_required &= ~IAVF_FLAG_AQ_ADD_MAC_FILTER;\n \t\tspin_unlock_bh(&adapter->mac_vlan_list_lock);\n-\t\treturn;\n+\t\treturn 0;\n \t}\n \tadapter->current_op = VIRTCHNL_OP_ADD_ETH_ADDR;\n \n@@ -595,7 +598,7 @@ void iavf_add_ether_addrs(struct iavf_adapter *adapter)\n \tveal = kzalloc(len, GFP_ATOMIC);\n \tif (!veal) {\n \t\tspin_unlock_bh(&adapter->mac_vlan_list_lock);\n-\t\treturn;\n+\t\treturn -ENOMEM;\n \t}\n \n \tveal->vsi_id = adapter->vsi_res->vsi_id;\n@@ -617,6 +620,7 @@ void iavf_add_ether_addrs(struct iavf_adapter *adapter)\n \n \tiavf_send_pf_msg(adapter, VIRTCHNL_OP_ADD_ETH_ADDR, (u8 *)veal, len);\n \tkfree(veal);\n+\treturn 0;\n }\n \n /**\n@@ -2956,3 +2960,102 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,\n \t} /* switch v_opcode */\n \tadapter->current_op = VIRTCHNL_OP_UNKNOWN;\n }\n+\n+/**\n+ * iavf_virtchnl_done - Check if virtchnl operation completed\n+ * @adapter: board private structure\n+ * @condition: optional callback for custom completion check\n+ *   (takes priority)\n+ * @cond_data: context data for callback\n+ * @v_opcode: virtchnl opcode value we're waiting for if no condition\n+ *   configured (typically VIRTCHNL_OP_UNKNOWN), if condition not used\n+ *\n+ * Checks completion status. Callback takes priority if provided. Otherwise\n+ * waits for current_op to reach v_opcode (typically VIRTCHNL_OP_UNKNOWN\n+ * after completion).\n+ *\n+ * Return: true if operation completed\n+ */\n+static inline bool iavf_virtchnl_done(struct iavf_adapter *adapter,\n+\t\t\t\t      bool (*condition)(struct iavf_adapter *, const void *),\n+\t\t\t\t      const void *cond_data,\n+\t\t\t\t      enum virtchnl_ops v_opcode)\n+{\n+\tif (condition)\n+\t\treturn condition(adapter, cond_data);\n+\n+\treturn adapter->current_op == v_opcode;\n+}\n+\n+/**\n+ * iavf_poll_virtchnl_response - Poll admin queue for virtchnl response\n+ * @adapter: board private structure\n+ * @condition: optional callback to check if desired response received\n+ *   (takes priority)\n+ * @cond_data: context data passed to condition callback\n+ * @v_opcode: virtchnl opcode value to wait for if no condition configured\n+ *   (typically VIRTCHNL_OP_UNKNOWN), if condition, not used\n+ * @timeout_ms: maximum time to wait in milliseconds\n+ *\n+ * Polls admin queue and processes all messages until condition returns true\n+ * or timeout expires. If condition is NULL, waits for current_op to become\n+ * v_opcode (typically VIRTCHNL_OP_UNKNOWN after operation completes).\n+ * Caller must hold netdev_lock. This can sleep for up to timeout_ms while\n+ * polling hardware.\n+ *\n+ * Return: 0 on success (condition met), -EAGAIN on timeout or error\n+ */\n+int iavf_poll_virtchnl_response(struct iavf_adapter *adapter,\n+\t\t\t\tbool (*condition)(struct iavf_adapter *, const void *),\n+\t\t\t\tconst void *cond_data,\n+\t\t\t\tenum virtchnl_ops v_opcode,\n+\t\t\t\tunsigned int timeout_ms)\n+{\n+\tstruct iavf_hw *hw = &adapter->hw;\n+\tstruct iavf_arq_event_info event;\n+\tenum virtchnl_ops v_op;\n+\tenum iavf_status v_ret;\n+\tunsigned long timeout;\n+\tu16 pending;\n+\tint ret;\n+\n+\tnetdev_assert_locked(adapter->netdev);\n+\n+\tevent.buf_len = IAVF_MAX_AQ_BUF_SIZE;\n+\tevent.msg_buf = kzalloc(event.buf_len, GFP_KERNEL);\n+\tif (!event.msg_buf)\n+\t\treturn -ENOMEM;\n+\n+\ttimeout = jiffies + msecs_to_jiffies(timeout_ms);\n+\tdo {\n+\t\tif (iavf_virtchnl_done(adapter, condition, cond_data, v_opcode)) {\n+\t\t\tret = 0;\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tret = iavf_clean_arq_element(hw, &event, &pending);\n+\t\tif (!ret) {\n+\t\t\tv_op = (enum virtchnl_ops)le32_to_cpu(event.desc.cookie_high);\n+\t\t\tv_ret = (enum iavf_status)le32_to_cpu(event.desc.cookie_low);\n+\n+\t\t\tiavf_virtchnl_completion(adapter, v_op, v_ret,\n+\t\t\t\t\t\t event.msg_buf, event.msg_len);\n+\n+\t\t\tmemset(event.msg_buf, 0, IAVF_MAX_AQ_BUF_SIZE);\n+\n+\t\t\tif (pending)\n+\t\t\t\tcontinue;\n+\t\t}\n+\n+\t\tusleep_range(50, 75);\n+\t} while (time_before(jiffies, timeout));\n+\n+\tif (iavf_virtchnl_done(adapter, condition, cond_data, v_opcode))\n+\t\tret = 0;\n+\telse\n+\t\tret = -EAGAIN;\n+\n+out:\n+\tkfree(event.msg_buf);\n+\treturn ret;\n+}\n","prefixes":["net","v3","3/5"]}