{"id":2227309,"url":"http://patchwork.ozlabs.org/api/patches/2227309/?format=json","web_url":"http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20260423130405.139568-4-jtornosm@redhat.com/","project":{"id":46,"url":"http://patchwork.ozlabs.org/api/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":"","list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<20260423130405.139568-4-jtornosm@redhat.com>","list_archive_url":null,"date":"2026-04-23T13:04:04","name":"[net,v4,3/4] iavf: send MAC change request synchronously","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"6da770951a1c49b417d11ad740abd79227856b56","submitter":{"id":93070,"url":"http://patchwork.ozlabs.org/api/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/20260423130405.139568-4-jtornosm@redhat.com/mbox/","series":[{"id":501193,"url":"http://patchwork.ozlabs.org/api/series/501193/?format=json","web_url":"http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=501193","date":"2026-04-23T13:04:02","name":"Fix i40e/ice/iavf VF bonding after netdev lock changes","version":4,"mbox":"http://patchwork.ozlabs.org/series/501193/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2227309/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2227309/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@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=PODPRu08;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=osuosl.org\n (client-ip=2605:bc80:3010::137; helo=smtp4.osuosl.org;\n envelope-from=intel-wired-lan-bounces@osuosl.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137])\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 4g1bsg0FMtz1yD5\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 23 Apr 2026 23:04:55 +1000 (AEST)","from localhost (localhost [127.0.0.1])\n\tby smtp4.osuosl.org (Postfix) with ESMTP id A805140F6B;\n\tThu, 23 Apr 2026 13:04:53 +0000 (UTC)","from smtp4.osuosl.org ([127.0.0.1])\n by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id L3ErN2FqCkt2; Thu, 23 Apr 2026 13:04:49 +0000 (UTC)","from lists1.osuosl.org (lists1.osuosl.org [140.211.166.142])\n\tby smtp4.osuosl.org (Postfix) with ESMTP id C866740F71;\n\tThu, 23 Apr 2026 13:04:49 +0000 (UTC)","from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n by lists1.osuosl.org (Postfix) with ESMTP id 1168324D\n for <intel-wired-lan@lists.osuosl.org>; Thu, 23 Apr 2026 13:04:48 +0000 (UTC)","from localhost (localhost [127.0.0.1])\n by smtp2.osuosl.org (Postfix) with ESMTP id 033FB403D7\n for <intel-wired-lan@lists.osuosl.org>; Thu, 23 Apr 2026 13:04:48 +0000 (UTC)","from smtp2.osuosl.org ([127.0.0.1])\n by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id pr6EKr1pjv8L for <intel-wired-lan@lists.osuosl.org>;\n Thu, 23 Apr 2026 13:04:43 +0000 (UTC)","from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.129.124])\n by smtp2.osuosl.org (Postfix) with ESMTPS id 2B5CD400A0\n for <intel-wired-lan@lists.osuosl.org>; Thu, 23 Apr 2026 13:04:42 +0000 (UTC)","from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-677-HdyM2jtlOQ6CL-txtnKIqA-1; Thu,\n 23 Apr 2026 09:04:40 -0400","from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12])\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-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id 85AD61955F0B; Thu, 23 Apr 2026 13:04:36 +0000 (UTC)","from fedora.redhat.com (unknown [10.44.32.35])\n by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id AE8D819560AB; Thu, 23 Apr 2026 13:04:31 +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 smtp4.osuosl.org C866740F71","OpenDKIM Filter v2.11.0 smtp2.osuosl.org 2B5CD400A0"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=osuosl.org;\n\ts=default; t=1776949489;\n\tbh=vjdtH9kLkJw7JMDDM4w0dM9rLKPqBsQXKMj1MJx953E=;\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=PODPRu08PhYj437WIQNc24eKomOytczUS+wTghk8MaVhjAHlulevjAjtOUKD6SzEX\n\t lct1IJ3kbjJqxvFGSmGqfRiOXVCCJNCHJuH0LEbFi+GryS3suPyCRPioajnjS5/bH4\n\t eINbMENWt2JmjE3s+zffob6NWHNAV27sJ5u7GUYLkPFos4XGnFyWKcXni842ueCEDK\n\t vjh7Mhaf51/U1A7ssWiOj+t/45/7LTgh7h6r5WJL8FkTOsCGLSkgLtRXKQhI16J545\n\t kTuSBgvyPaIv3/6792asGb/t3A2L0Z5O7O2mN4cztBfgi2D553FUny94f8p2u1FQ+Q\n\t yb6iOIS7B1M6g==","Received-SPF":"Pass (mailfrom) identity=mailfrom; client-ip=170.10.129.124;\n helo=us-smtp-delivery-124.mimecast.com; envelope-from=jtornosm@redhat.com;\n receiver=<UNKNOWN>","DMARC-Filter":"OpenDMARC Filter v1.4.2 smtp2.osuosl.org 2B5CD400A0","X-MC-Unique":"HdyM2jtlOQ6CL-txtnKIqA-1","X-Mimecast-MFC-AGG-ID":"HdyM2jtlOQ6CL-txtnKIqA_1776949476","From":"Jose Ignacio Tornos Martinez <jtornosm@redhat.com>","To":"netdev@vger.kernel.org","Cc":"intel-wired-lan@lists.osuosl.org, przemyslaw.kitszel@intel.com,\n aleksandr.loktionov@intel.com, jacob.e.keller@intel.com, horms@kernel.org,\n jesse.brandeburg@intel.com, anthony.l.nguyen@intel.com,\n davem@davemloft.net, edumazet@google.com, kuba@kernel.org,\n pabeni@redhat.com, Jose Ignacio Tornos Martinez <jtornosm@redhat.com>,\n stable@vger.kernel.org","Date":"Thu, 23 Apr 2026 15:04:04 +0200","Message-ID":"<20260423130405.139568-4-jtornosm@redhat.com>","In-Reply-To":"<20260423130405.139568-1-jtornosm@redhat.com>","References":"<20260423130405.139568-1-jtornosm@redhat.com>","MIME-Version":"1.0","X-Scanned-By":"MIMEDefang 3.0 on 10.30.177.12","X-Mimecast-MFC-PROC-ID":"ySPv5NHKUr6qofJIJ7sZ84F1TNi0o75tXDAkLo8f1qU_1776949476","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=1776949482;\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=vjdtH9kLkJw7JMDDM4w0dM9rLKPqBsQXKMj1MJx953E=;\n b=Lznovn48O2OnsPr94RIFR2+e1qxR3ypupys9mnva+3r8b16yjC7ebp+1idg8yonRuIkOd0\n Cip+uOARUssV6qlQG63oOelA3CFGo63u6RWKBHRaj5ka2d3kgRYxfk0f+GhAYMytVLDv1X\n 2WHc4eTjqq3KWWm5CI7HepvXxmpRY+I=","X-Mailman-Original-Authentication-Results":["smtp2.osuosl.org;\n dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com","smtp2.osuosl.org;\n dkim=pass (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=Lznovn48"],"Subject":"[Intel-wired-lan] [PATCH net v4 3/4] 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. Additionally,\nexport iavf_mac_add_reject() to enable proper rollback on local failures\n(timeouts, send errors) - PF rejections are already handled automatically\nby iavf_virtchnl_completion().\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---\nv4: Complete with Przemek Kitszel comments:\n    - Remove vc_waitqueue entirely (not needed any more)\n    - Add named parameters to callback function pointer declaration for\n      clarity\n    - Simplify callback signature: add v_op parameter so callback\n      receives the opcode from the processed message to identify which\n      response was received\n    - Optimize polling loop to single condition check per iteration\n      instead of checking both before and after message processing\n    Address AI review (sashiko.dev) from Simon Horman:\n    - Complete iavf_add_ether_addrs() error handling\n    - Skip non-virtchnl hardware events (received_op=VIRTCHNL_OP_UNKNOWN),\n      these can cause false completion detection\n    - Complete rollback for local failures (not PF rejection) reusing\n      iavf_mac_add_reject() to restore the old primary filter\nv3: https://lore.kernel.org/netdev/20260414110006.124286-4-jtornosm@redhat.com/\n\n drivers/net/ethernet/intel/iavf/iavf.h        | 10 +-\n drivers/net/ethernet/intel/iavf/iavf_main.c   | 70 +++++++++----\n .../net/ethernet/intel/iavf/iavf_virtchnl.c   | 99 +++++++++++++++++--\n 3 files changed, 151 insertions(+), 28 deletions(-)","diff":"diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h\nindex e9fb0a0919e3..78fa3df06e11 100644\n--- a/drivers/net/ethernet/intel/iavf/iavf.h\n+++ b/drivers/net/ethernet/intel/iavf/iavf.h\n@@ -260,7 +260,6 @@ struct iavf_adapter {\n \tstruct work_struct adminq_task;\n \tstruct work_struct finish_config;\n \twait_queue_head_t down_waitqueue;\n-\twait_queue_head_t vc_waitqueue;\n \tstruct iavf_q_vector *q_vectors;\n \tstruct list_head vlan_filter_list;\n \tint num_vlan_filters;\n@@ -589,8 +588,9 @@ 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_mac_add_reject(struct iavf_adapter *adapter);\n void iavf_add_vlans(struct iavf_adapter *adapter);\n void iavf_del_vlans(struct iavf_adapter *adapter);\n void iavf_set_promiscuous(struct iavf_adapter *adapter);\n@@ -607,6 +607,12 @@ 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 *adapter,\n+\t\t\t\t\t\t  const void *data,\n+\t\t\t\t\t\t  enum virtchnl_ops v_op),\n+\t\t\t\tconst void *cond_data,\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..bc5994bf2cd9 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,48 @@ 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+ * @v_op: virtchnl opcode from processed message\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,\n+\t\t\t\t const void *data, enum virtchnl_ops v_op)\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,\n+\t\t\t\t\t   addr, 2500);\n+}\n+\n /**\n  * iavf_set_mac - NDO callback to set port MAC address\n  * @netdev: network interface device structure\n@@ -1067,25 +1109,20 @@ 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\t/* Rollback for local failures (timeout, send error, -EBUSY).\n+\t\t * Note: If PF rejects the request (sends error response),\n+\t\t * iavf_virtchnl_completion() automatically calls\n+\t\t * iavf_mac_add_reject(), ret=0, and this is not executed.\n+\t\t * Only local failures (no PF response received) need manual rollback.\n+\t\t */\n+\t\tiavf_mac_add_reject(adapter);\n \t\treturn ret;\n-\n-\tif (!ret)\n-\t\treturn -EAGAIN;\n+\t}\n \n \tif (!ether_addr_equal(netdev->dev_addr, addr->sa_data))\n \t\treturn -EACCES;\n@@ -5415,9 +5452,6 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)\n \t/* Setup the wait queue for indicating transition to down status */\n \tinit_waitqueue_head(&adapter->down_waitqueue);\n \n-\t/* Setup the wait queue for indicating virtchannel events */\n-\tinit_waitqueue_head(&adapter->vc_waitqueue);\n-\n \tINIT_LIST_HEAD(&adapter->ptp.aq_cmds);\n \tinit_waitqueue_head(&adapter->ptp.phc_time_waitqueue);\n \tmutex_init(&adapter->ptp.aq_cmd_lock);\ndiff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c\nindex a52c100dcbc5..d1afb8261c24 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,20 +556,23 @@ 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 \tint i = 0, count = 0;\n \tbool more = false;\n \tsize_t len;\n+\tint ret;\n \n \tif (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {\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 +584,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@@ -594,8 +598,9 @@ void iavf_add_ether_addrs(struct iavf_adapter *adapter)\n \n \tveal = kzalloc(len, GFP_ATOMIC);\n \tif (!veal) {\n+\t\tadapter->current_op = VIRTCHNL_OP_UNKNOWN;\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@@ -615,8 +620,15 @@ void iavf_add_ether_addrs(struct iavf_adapter *adapter)\n \n \tspin_unlock_bh(&adapter->mac_vlan_list_lock);\n \n-\tiavf_send_pf_msg(adapter, VIRTCHNL_OP_ADD_ETH_ADDR, (u8 *)veal, len);\n+\tret = iavf_send_pf_msg(adapter, VIRTCHNL_OP_ADD_ETH_ADDR, (u8 *)veal, len);\n \tkfree(veal);\n+\tif (ret) {\n+\t\tdev_err(&adapter->pdev->dev,\n+\t\t\t\"Unable to send ADD_ETH_ADDR message to PF, error %d\\n\", ret);\n+\t\tadapter->current_op = VIRTCHNL_OP_UNKNOWN;\n+\t}\n+\n+\treturn ret;\n }\n \n /**\n@@ -713,7 +725,7 @@ static void iavf_mac_add_ok(struct iavf_adapter *adapter)\n  *\n  * Remove filters from list based on PF response.\n  **/\n-static void iavf_mac_add_reject(struct iavf_adapter *adapter)\n+void iavf_mac_add_reject(struct iavf_adapter *adapter)\n {\n \tstruct net_device *netdev = adapter->netdev;\n \tstruct iavf_mac_filter *f, *ftmp;\n@@ -2389,7 +2401,6 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,\n \t\t\tiavf_mac_add_reject(adapter);\n \t\t\t/* restore administratively set MAC address */\n \t\t\tether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr);\n-\t\t\twake_up(&adapter->vc_waitqueue);\n \t\t\tbreak;\n \t\tcase VIRTCHNL_OP_DEL_VLAN:\n \t\t\tdev_err(&adapter->pdev->dev, \"Failed to delete VLAN filter, error %s\\n\",\n@@ -2586,7 +2597,6 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,\n \t\t\t\teth_hw_addr_set(netdev, adapter->hw.mac.addr);\n \t\t\t\tnetif_addr_unlock_bh(netdev);\n \t\t\t}\n-\t\twake_up(&adapter->vc_waitqueue);\n \t\tbreak;\n \tcase VIRTCHNL_OP_GET_STATS: {\n \t\tstruct iavf_eth_stats *stats =\n@@ -2956,3 +2966,76 @@ 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_poll_virtchnl_response - Poll admin queue for virtchnl response\n+ * @adapter: adapter structure\n+ * @condition: callback to check if desired response received\n+ * @cond_data: context data passed to condition callback\n+ * @timeout_ms: maximum time to wait in milliseconds\n+ *\n+ * Polls the admin queue and processes all incoming virtchnl messages.\n+ * After processing each valid message, calls the condition callback to check\n+ * if the expected response has been received. The callback receives the opcode\n+ * of the processed message to identify which response was received. Continues\n+ * polling until the callback returns true or timeout expires.\n+ * Clear current_op on timeout to prevent permanent -EBUSY state.\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 code\n+ **/\n+int iavf_poll_virtchnl_response(struct iavf_adapter *adapter,\n+\t\t\t\tbool (*condition)(struct iavf_adapter *adapter,\n+\t\t\t\t\t\t  const void *data,\n+\t\t\t\t\t\t  enum virtchnl_ops v_op),\n+\t\t\t\tconst void *cond_data,\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 received_op;\n+\tunsigned long timeout;\n+\tu32 v_retval;\n+\tu16 pending;\n+\tint ret = -EAGAIN;\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_clean_arq_element(hw, &event, &pending) == IAVF_SUCCESS) {\n+\t\t\treceived_op = (enum virtchnl_ops)le32_to_cpu(event.desc.cookie_high);\n+\t\t\tif (received_op != VIRTCHNL_OP_UNKNOWN) {\n+\t\t\t\tv_retval = le32_to_cpu(event.desc.cookie_low);\n+\n+\t\t\t\tiavf_virtchnl_completion(adapter, received_op,\n+\t\t\t\t\t\t\t (enum iavf_status)v_retval,\n+\t\t\t\t\t\t\t event.msg_buf, event.msg_len);\n+\n+\t\t\t\tif (condition(adapter, cond_data, received_op)) {\n+\t\t\t\t\tret = 0;\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t}\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 (ret == -EAGAIN && adapter->current_op != VIRTCHNL_OP_UNKNOWN)\n+\t\tadapter->current_op = VIRTCHNL_OP_UNKNOWN;\n+\n+\tkfree(event.msg_buf);\n+\treturn ret;\n+}\n","prefixes":["net","v4","3/4"]}