From nobody Tue Apr 7 07:34:04 2026 Received: from mail-pl1-f182.google.com (mail-pl1-f182.google.com [209.85.214.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7929130C610 for ; Sat, 14 Mar 2026 18:28:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773512930; cv=none; b=K0KjwAoLVpPxgLi/cKJQJttSA9X/7DEgW/uaxEU6ahhAbJe9c0qdmkCfL0YhlhYW0OxXPXreuzKGsCQHu9ZTu5m9BLTCwXOweLxAh0zVoqDWayWqd3bMMRmkBL3SV9geCrLOVSVREfaaLzAUkw9w7MR8y5t6NYmXB0ubosakIho= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773512930; c=relaxed/simple; bh=bPSZT7dVTriF4TZgmZTUAw22Sgou+Fmk1o1FCPOSVME=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LxWjtGj/eldov03e6tGc5BZkb/x0kzYT+OS96DozEbkAeMF1bpiqi24kpcSwHe5ITqUmw6qwUc9cC0LsluQllYV/Z5VUmi/pfGGujvVnENMUC9KnAbiBdyck+ShuKCy5wYnPiIxBISH56l4Ml7AV/PXuaT3jXZVmifAjngU+z1c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=bAATbJb3; arc=none smtp.client-ip=209.85.214.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="bAATbJb3" Received: by mail-pl1-f182.google.com with SMTP id d9443c01a7336-2ab46931cf1so31547305ad.0 for ; Sat, 14 Mar 2026 11:28:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773512929; x=1774117729; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=4KgmmudIxXUanwK3aFbv0ip54pwkZrkMg6RJuyR+qxA=; b=bAATbJb3Ii4e802Gy4kD7idMwljBlOjFyMjcXs25aop8D1oVDo0uAQ0gjeslGZmfc3 B9xUIjHrX2sUgyCP+p9uN5R0nhdV4TqszMkZjnSwH5xzPKpxe5SJly2/X/9eSJWS0eU7 PrQMlDvYzY/LkI7r7b7qL+m5zXT6dveayYBFNdqLNKJ9+mR5B6w6ZSW1xI0ERvv+6xkM pbjBjNWAY7vxO0Vy4tZZnk+49RMhHEGPEKFcAVFaYtrhJ5gMIxdHMeJwq9DcjcqE0YTm etrImy77Hb6/BASxW/+gNC0vNEI4oxugx6NTmv3gZgIjT3hy+p/CJzlO1PdYxmsla4DD HzBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773512929; x=1774117729; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=4KgmmudIxXUanwK3aFbv0ip54pwkZrkMg6RJuyR+qxA=; b=aNkadj648NTLOiSkPToSONHIR8HGIst22N9mDTEnRQiEaeDdGL62Kk2QyjVelXXJ1u T3ldBUlbOcQbCg/x0M5eUxRDWriX5c+/sIS8X8iAPvW3Db4sI299z3SGX0qVawnYuPEq IvXdH6WpAWWwGvZJPEunmyxO0DwBgG+QTiIPNb/6Jm2rOEC55phcUj7aooRDUTZDpY3q Dq4t8VQqxHbyozE/PCAd4VvQoJE0aDZdjkgmtD8Z0DDhEBcHK94M+Ma1d0diL3q37aRK WBLlGeS0Zfl4eGDD75QpgTFsyyH7Y+QTnfUMFR9zCLdEApofSLQ7sDI2l2FKY5MOyAwP AI8Q== X-Forwarded-Encrypted: i=1; AJvYcCXy4XF0jtbaweUU3Jj/3LnGz2e164NG2zB8WWt5rj99/eCvABhQIY7OP/+jAIzTlqRKytRF+/ZlFkEE+cs=@vger.kernel.org X-Gm-Message-State: AOJu0Yx3Dg9Qg/cB78CBT9oT6uwA1FJuhyXKonzp9GFMV9s5XEYsKdOj zt0SLtrxPZxPHCCIxz3dlQOaru2vOYCzykhNZ9tcwfDsSPtiAF0cbrTU X-Gm-Gg: ATEYQzwYz/0QZ5oLNuL7pDeAY9jSjTmACpaVt0QX2o15xx8I1DfiC0ZlPN4/W+ZsEAs LqvrQn3O5zlWwNL9QrW7aL04Lt/3fkhVytYF4hcI4uXcWMCso3ULqBPff7vVRu0+So/uKxmBoRe YDOodhYPg8iQXpPuoBdX5+q0pB54YeHLJc4QQG1Po+DK12NEyOTg5yQwqWyydTipZi7+HdxqXhV QqRpNYACdSU+geurmKEiTMj7PO7eyLFL3OnuUpjkWMt/qI5P1GQJSCDkzmcVsoI/IrMj7YIwVTZ vrGB3zOMVEx6rqrEIu/lTfb/V9nzNcy4qfLfdUifVneZ6QLz5KaH0/ukkHlSmgeC8mrsu2m7nxo 5MywKGLht5KjkUEXQ6+cjx+Us/kcXXSpaHErO/G2zuPMkWSy9rEHYj09AkC8jpxOvlpSN54hbDZ wQ6VuVVQMdTJNoL4llGjWPTF6v/Di87XvLZL2C49riIp7VlrR1W6UuwBJ26Ih7nxMjw2+MH0JgI kqIeQ== X-Received: by 2002:a17:902:ea09:b0:2b0:4cbe:fbea with SMTP id d9443c01a7336-2b04cbf0114mr7880195ad.25.1773512928560; Sat, 14 Mar 2026 11:28:48 -0700 (PDT) Received: from localhost.localdomain ([122.168.66.151]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2aece62c581sm77673525ad.33.2026.03.14.11.28.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 14 Mar 2026 11:28:47 -0700 (PDT) From: I Viswanath To: stfomichev@gmail.com, horms@kernel.org, edumazet@google.com, pabeni@redhat.com, andrew+netdev@lunn.ch, kuba@kernel.org, davem@davemloft.net, eperezma@redhat.com, xuanzhuo@linux.alibaba.com, jasowang@redhat.com, mst@redhat.com, przemyslaw.kitszel@intel.com, anthony.l.nguyen@intel.com, jacob.e.keller@intel.com, ronak.doshi@broadcom.com, pcnet32@frontier.com Cc: bcm-kernel-feedback-list@broadcom.com, netdev@vger.kernel.org, virtualization@lists.linux.dev, intel-wired-lan@lists.osuosl.org, linux-kernel@vger.kernel.org, I Viswanath Subject: [PATCH net-next v9 1/7] net: core: Add state tracking for async netdev ops Date: Sat, 14 Mar 2026 23:58:03 +0530 Message-ID: <20260314182809.362808-2-viswanathiyyappan@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260314182809.362808-1-viswanathiyyappan@gmail.com> References: <20260314182809.362808-1-viswanathiyyappan@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Async netdev ops are tricky because of the following problems: 1) Freeing the context associated with async netdev ops might require waiting for completion of the associated work which might require the rtnl lock or the instance lock. However this will deadlock in __dev_close_many as the cleanup is done with those locks already held. 2) We need a way to enable/disable async netdev ops depending on the PM state to allow/prevent hardware access as appropriate. We solve these problems by introducing a state variable to track the current state of netdev. This can take the following values: - ACTIVE (up and normal operation) - DOWN (down) - INACTIVE (in suspend/shutdown) To solve 1, we set the state to down in __dev_close_many. In the associated op handler, we check for the current state and return if the netdev is down. To solve 2, the commit introduces the following functions: - netif_enable_async_ops -> sets state to ACTIVE - netif_disable_async_ops -> sets state to INACTIVE and cancels any pending work as required. The op implementation can use the state information to do the required processing. Signed-off-by: I Viswanath Reviewed-by: Aleksandr Loktionov --- include/linux/netdevice.h | 29 ++++++++++++++ net/core/dev.c | 84 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 111 insertions(+), 2 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index ae269a2e7f4d..6d426dc66af9 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1062,6 +1062,16 @@ struct netdev_net_notifier { struct notifier_block *nb; }; =20 +enum netif_async_state { + NETIF_ASYNC_ACTIVE, + NETIF_ASYNC_DOWN, + NETIF_ASYNC_INACTIVE +}; + +struct netif_async_ctx { + enum netif_async_state state; +}; + /* * This structure defines the management hooks for network devices. * The following hooks can be defined; unless noted otherwise, they are @@ -2027,6 +2037,8 @@ enum netdev_reg_state { * @sfp_bus: attached &struct sfp_bus structure. * * @qdisc_tx_busylock: lockdep class annotating Qdisc->busylock spinlock + * @async_ctx : Context required for async ops + * @needs_async_ctx : Does dev need async op context? * * @proto_down: protocol port state information can be sent to the * switch driver and used to set the phys state of the @@ -2454,6 +2466,8 @@ struct net_device { struct phy_device *phydev; struct sfp_bus *sfp_bus; struct lock_class_key *qdisc_tx_busylock; + struct netif_async_ctx *async_ctx; + bool needs_async_ctx; bool proto_down; bool irq_affinity_auto; bool rx_cpu_rmap_auto; @@ -3376,6 +3390,21 @@ int dev_loopback_xmit(struct net *net, struct sock *= sk, struct sk_buff *newskb); u16 dev_pick_tx_zero(struct net_device *dev, struct sk_buff *skb, struct net_device *sb_dev); =20 +void netif_disable_async_ops(struct net_device *dev); +void netif_enable_async_ops(struct net_device *dev); + +static inline void netif_set_async_state(struct net_device *dev, + enum netif_async_state state) +{ + dev->async_ctx->state =3D state; +} + +static inline enum netif_async_state +netif_get_async_state(struct net_device *dev) +{ + return dev->async_ctx->state; +} + int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev); int __dev_direct_xmit(struct sk_buff *skb, u16 queue_id); =20 diff --git a/net/core/dev.c b/net/core/dev.c index 200d44883fc1..b1797bd28a6b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1664,6 +1664,33 @@ static int napi_kthread_create(struct napi_struct *n) return err; } =20 +static int __netif_alloc_async_ctx(struct net_device *dev) +{ + dev->async_ctx =3D kzalloc_obj(*dev->async_ctx); + if (!dev->async_ctx) + return -ENOMEM; + + netif_set_async_state(dev, NETIF_ASYNC_ACTIVE); + return 0; +} + +static int netif_alloc_async_ctx(struct net_device *dev) +{ + int ret; + + ret =3D __netif_alloc_async_ctx(dev); + return ret; +} + +static void netif_free_async_ctx(struct net_device *dev) +{ + if (!dev->async_ctx) + return; + + kfree(dev->async_ctx); + dev->async_ctx =3D NULL; +} + static int __dev_open(struct net_device *dev, struct netlink_ext_ack *exta= ck) { const struct net_device_ops *ops =3D dev->netdev_ops; @@ -1698,14 +1725,18 @@ static int __dev_open(struct net_device *dev, struc= t netlink_ext_ack *extack) if (ops->ndo_validate_addr) ret =3D ops->ndo_validate_addr(dev); =20 + if (!ret && dev->needs_async_ctx) + ret =3D netif_alloc_async_ctx(dev); + if (!ret && ops->ndo_open) ret =3D ops->ndo_open(dev); =20 netpoll_poll_enable(dev); =20 - if (ret) + if (ret) { clear_bit(__LINK_STATE_START, &dev->state); - else { + netif_free_async_ctx(dev); + } else { netif_set_up(dev, true); dev_set_rx_mode(dev); dev_activate(dev); @@ -1772,6 +1803,11 @@ static void __dev_close_many(struct list_head *head) =20 netdev_ops_assert_locked(dev); =20 + if (dev->needs_async_ctx) { + netif_set_async_state(dev, NETIF_ASYNC_DOWN); + netif_free_async_ctx(dev); + } + if (ops->ndo_stop) ops->ndo_stop(dev); =20 @@ -1821,6 +1857,50 @@ void netif_close(struct net_device *dev) } EXPORT_SYMBOL(netif_close); =20 +/* netif_disable_async_ops - disable execution of async NDOs. + * + * To be used in cases of the device shutting down, suspending or + * failing to resume. + * + * Should be called in the shutdown callback and in the PM suspend + * callbacks: @suspend(), @freeze(), @poweroff() and in the error + * path of PM resume callbacks. + */ +void netif_disable_async_ops(struct net_device *dev) +{ + netdev_lock_ops_compat(dev); + + if (!dev->needs_async_ctx || !netif_running(dev)) { + netdev_unlock_ops_compat(dev); + return; + } + + netif_set_async_state(dev, NETIF_ASYNC_INACTIVE); + netdev_unlock_ops_compat(dev); +} +EXPORT_SYMBOL(netif_disable_async_ops); + +/* netif_enable_async_ops - enable execution of async NDOs. + * + * To be used when the device attempts to resume or fails to suspend. + * + * Should be called in the PM resume callbacks: @resume(), @thaw(), + * @restore() and in the error path of PM suspend callbacks. + */ +void netif_enable_async_ops(struct net_device *dev) +{ + netdev_lock_ops_compat(dev); + + if (!dev->needs_async_ctx || !netif_running(dev)) { + netdev_unlock_ops_compat(dev); + return; + } + + netif_set_async_state(dev, NETIF_ASYNC_ACTIVE); + netdev_unlock_ops_compat(dev); +} +EXPORT_SYMBOL(netif_enable_async_ops); + void netif_disable_lro(struct net_device *dev) { struct net_device *lower_dev; --=20 2.47.3 From nobody Tue Apr 7 07:34:04 2026 Received: from mail-pl1-f182.google.com (mail-pl1-f182.google.com [209.85.214.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 65D2C314D37 for ; Sat, 14 Mar 2026 18:28:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773512941; cv=none; b=AD6mKpmD5LOOt4M/bZ6Oax8aywM44UeAVgcrJwiPjlx73INPlo0QrZF5DJmkoC2b7NT+PczknhjhUi72wvU7Hq7Btkh7RTpLi9CfcjaeoKj9lah+fug6VW6sqyf6O73cXCouijVWBQ5hg7sm+mNUcnOC5DMdngLWkhB5r4xBYJk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773512941; c=relaxed/simple; bh=e0azMONBUhPqODHGElI9gDKQUWDLTjuAbw7z9MqCdJc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XFd8wKM9TSEaXot5VUysyJyGbIwlH2g+Onnkg2j60nMXrov0AwcLKBsjk+ZS9/CkvCuKRxRH1/TcfpqMVYUlDwUTWgD8X5xwZ4ConBdj+g1qTUyQnp7JH7lzNZ0DRmGzVAjEUTHCaXrkqRhvv3FAuLAwCui/jyHWp7H+tjFDpqM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=A8OnXMaK; arc=none smtp.client-ip=209.85.214.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="A8OnXMaK" Received: by mail-pl1-f182.google.com with SMTP id d9443c01a7336-2ae82df847bso25521195ad.2 for ; Sat, 14 Mar 2026 11:28:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773512939; x=1774117739; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=bTvcRjBg7RZQjPVbwsm/XKOCF/7oOgDehhwAe6xkRiI=; b=A8OnXMaKRZKYCc6kwZnF8R2+VjgYCQrWkTopFySDxtDOsYzXFgQnKWY9CXHE2lzfzK bboTNchUDmYAGOHpi2xPkkBlH+NVG/LI855VSLzMq996atA2wIQQLLEiD6vey7MK3J4h Odqshg/L5bW4XLRFS1QW1HnccLnn6KLEmJvGRFEATllh1kvapLt/IP0KgJ2nwL8xctvF N1376rjGOnjysrnpRqNsK9gmPcmvRHfnes6MBc0LjFg6LrnDHCjZOfTXCIxyXLy4ozRq yVMUg2Bhv24NslGNxRgj75G+XkKJHzPrERYpqOZpeSCIZbH3DjFZDJjWJPmVJH4zjByT Pcyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773512939; x=1774117739; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=bTvcRjBg7RZQjPVbwsm/XKOCF/7oOgDehhwAe6xkRiI=; b=ED3zkSeeBQfzCaa15XvjSCbsQSRWBSc4zOel9b6Dr0zSa30AIso8vIC5dJQnt+8qr0 bio6SXfWSl1Fkc0TKNjQ7nKZWTyRaOl9/TdIQNw2W4PoISWMH/97HqskDX85zSC1CKbO 7hrLNC3QUAqjcDiaNFzNPYbXtfgohBIRQsaSZCMlkhR1nByH/a0vZpOTxLGcVNdUNk23 j5mIQU6U6ds1B9xXdk2I9CAFf/hi66KU5CuahApgVvyXgq29hG3A7Tk2xx4+l16XbjNk oSA4w0/1HmWE7WhHAgkTE9xSyyuF2Oh6UM2f+eOq+UVECRkMcfuBYGRqGijvniTmunge lA0A== X-Forwarded-Encrypted: i=1; AJvYcCVCExLpBEQ5+9ZfiZWtn/17brH6aHFIM2Jg6dpgljWuL+eSM95H4XFKWosaohZLkD7d321eZJUCeoxMsBY=@vger.kernel.org X-Gm-Message-State: AOJu0YyqeXkHCHbsiFoHQTDZ9Faq2sY3uDg5WKtJXg3H5FSCanPrFRfJ wwq7QE4Ow6Q6apKTTN1E4fgp9hAxGucW100nWQ3bUnit7z/7ptDXQXdv X-Gm-Gg: ATEYQzxQiZgmrqPUlTQhgC+6ZqQ+gRqyTxq1ugSUhim+vhHH/h862Gj+hbE9fpWj4dK rEIa1bprG0HA+nTB+oCLcIc4m6Y82Ey319wWlFlsOJB9tlCaXb3JXGreHzxWm/qXlXPp7VZD2nb gJZZMyFwzpd221B6yE9SWZrKmsyZUGPeh0VCsU+j92LAFjYmYlQqGf583iqiAV9kw5mYoGg0pXT RN39J1fQ7bhP8P/JLXarYHEXL/JZpW/1LEcK2aDDhVtMOxgfv300D1WHHo3nhsr3nLHTfwo6JJb Bv4+3VhTL2g/KgV2wONkdMUl1rG+QmOAwDihuKzW8N61aQnVbtEJeIxWIoYvbxJBzwz6jlkE22+ ZJnDm7mOt1aTR7CADAszYMk6kQ875yi3bSVONCV4xHdbqNQ34LtkBvdcNqFsLYwX43Gds/3MbZV 5jwXK2A5IcP6tKTcmhNbHFufYGvKZf0aL7xvGRrlyneVrawjTt0q2fmEi2Cl1tYgDQtdil2B0Um 8QTtTcqUYDvlqK/ X-Received: by 2002:a17:902:ce92:b0:2ae:41d1:344b with SMTP id d9443c01a7336-2aeca967ad1mr74232365ad.6.1773512938770; Sat, 14 Mar 2026 11:28:58 -0700 (PDT) Received: from localhost.localdomain ([122.168.66.151]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2aece62c581sm77673525ad.33.2026.03.14.11.28.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 14 Mar 2026 11:28:58 -0700 (PDT) From: I Viswanath To: stfomichev@gmail.com, horms@kernel.org, edumazet@google.com, pabeni@redhat.com, andrew+netdev@lunn.ch, kuba@kernel.org, davem@davemloft.net, eperezma@redhat.com, xuanzhuo@linux.alibaba.com, jasowang@redhat.com, mst@redhat.com, przemyslaw.kitszel@intel.com, anthony.l.nguyen@intel.com, jacob.e.keller@intel.com, ronak.doshi@broadcom.com, pcnet32@frontier.com Cc: bcm-kernel-feedback-list@broadcom.com, netdev@vger.kernel.org, virtualization@lists.linux.dev, intel-wired-lan@lists.osuosl.org, linux-kernel@vger.kernel.org, I Viswanath Subject: [PATCH net-next v9 2/7] net: core: Introduce callback ndo_set_rx_mode_async Date: Sat, 14 Mar 2026 23:58:04 +0530 Message-ID: <20260314182809.362808-3-viswanathiyyappan@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260314182809.362808-1-viswanathiyyappan@gmail.com> References: <20260314182809.362808-1-viswanathiyyappan@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The set_rx_mode callback is invoked under the addr_lock spinlock which makes it illegal to sleep. This means set_rx_mode is prone to sleep-in-atomic bugs as drivers have a tendency to do the I/O directly in the callback. This problem can be avoided if set_rx_mode were done in 2 stages: snapshot and commit. A handful of drivers implement this idea by implementing the rx_mode update as work and scheduling it in the set_rx_mode callback. Implement this idea in net/core as this is not driver specific. To facilitate this transition, a new async callback set_rx_mode_async is introduced. When this callback is provided, the set_rx_mode callback customizes the snapshot creation and the work behaviour as required while the set_rx_mode_async callback is run async as work and commits the prepared snapshot. Apart from this, the drivers need to be updated to have all the RX mode updates pass through the netif_set_rx_mode helper to ensure correctness. Suggested-by: Jakub Kicinski Signed-off-by: I Viswanath Reviewed-by: Aleksandr Loktionov --- include/linux/netdevice.h | 94 +++++++++++++- include/net/netdev_lock.h | 8 ++ net/core/dev.c | 251 +++++++++++++++++++++++++++++++++++++- 3 files changed, 347 insertions(+), 6 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 6d426dc66af9..a69377068f4a 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1068,7 +1068,36 @@ enum netif_async_state { NETIF_ASYNC_INACTIVE }; =20 +enum netif_rx_mode_cfg { + NETIF_RX_MODE_CFG_ALLMULTI, + NETIF_RX_MODE_CFG_PROMISC, + NETIF_RX_MODE_CFG_BROADCAST +}; + +enum netif_rx_mode_flags { + NETIF_RX_MODE_READY, + NETIF_RX_MODE_UC_SKIP, + NETIF_RX_MODE_MC_SKIP +}; + +struct netif_rx_mode_config { + char *uc_addrs; + char *mc_addrs; + int uc_count; + int mc_count; + int cfg; +}; + +struct netif_rx_mode_work { + struct netif_rx_mode_config *pending; + struct netif_rx_mode_config *ready; + struct work_struct work; + struct net_device *dev; + int flags; +}; + struct netif_async_ctx { + struct netif_rx_mode_work *rx_mode_work; enum netif_async_state state; }; =20 @@ -1124,9 +1153,15 @@ struct netif_async_ctx { * changes to configuration when multicast or promiscuous is enabled. * * void (*ndo_set_rx_mode)(struct net_device *dev); - * This function is called device changes address list filtering. + * This function is called when device changes address list filtering. * If driver handles unicast address filtering, it should set - * IFF_UNICAST_FLT in its priv_flags. + * IFF_UNICAST_FLT in its priv_flags. If the ndo_set_rx_mode_async + * callback is provided, This would be used to set up the + * rx mode snapshot that will be committed by ndo_set_rx_mode_async. + * + * void (*ndo_set_rx_mode_async)(struct net_device *dev); + * This function will be scheduled by dev_set_rx_mode and is + * responsible for committing the rx_mode snapshot to the hardware. * * int (*ndo_set_mac_address)(struct net_device *dev, void *addr); * This function is called when the Media Access Control address @@ -1447,6 +1482,7 @@ struct net_device_ops { void (*ndo_change_rx_flags)(struct net_device *dev, int flags); void (*ndo_set_rx_mode)(struct net_device *dev); + void (*ndo_set_rx_mode_async)(struct net_device *dev); int (*ndo_set_mac_address)(struct net_device *dev, void *addr); int (*ndo_validate_addr)(struct net_device *dev); @@ -3405,6 +3441,60 @@ netif_get_async_state(struct net_device *dev) return dev->async_ctx->state; } =20 +void netif_set_rx_mode(struct net_device *dev); + +/* Helpers to be used in the set_rx_mode callback */ +static inline void netif_set_rx_mode_cfg(struct net_device *dev, int b, + bool val) +{ + if (val) + dev->async_ctx->rx_mode_work->pending->cfg |=3D BIT(b); + else + dev->async_ctx->rx_mode_work->pending->cfg &=3D ~BIT(b); +} + +static inline void netif_set_rx_mode_flag(struct net_device *dev, int b, + bool val) +{ + if (val) + dev->async_ctx->rx_mode_work->flags |=3D BIT(b); + else + dev->async_ctx->rx_mode_work->flags &=3D ~BIT(b); +} + +/* Helpers to be used in the set_rx_mode_async callback */ +static inline bool netif_get_rx_mode_cfg(struct net_device *dev, int b) +{ + return !!(dev->async_ctx->rx_mode_work->ready->cfg & BIT(b)); +} + +static inline bool netif_get_rx_mode_flag(struct net_device *dev, int b) +{ + return !!(dev->async_ctx->rx_mode_work->flags & BIT(b)); +} + +static inline int netif_rx_mode_uc_count(struct net_device *dev) +{ + return dev->async_ctx->rx_mode_work->ready->uc_count; +} + +static inline int netif_rx_mode_mc_count(struct net_device *dev) +{ + return dev->async_ctx->rx_mode_work->ready->mc_count; +} + +#define netif_rx_mode_for_each_uc_addr(ha_addr, dev, __i) \ + for (__i =3D 0, \ + ha_addr =3D (dev)->async_ctx->rx_mode_work->ready->uc_addrs; \ + __i < (dev)->async_ctx->rx_mode_work->ready->uc_count; \ + __i++, ha_addr +=3D (dev)->addr_len) + +#define netif_rx_mode_for_each_mc_addr(ha_addr, dev, __i) \ + for (__i =3D 0, \ + ha_addr =3D (dev)->async_ctx->rx_mode_work->ready->mc_addrs; \ + __i < (dev)->async_ctx->rx_mode_work->ready->mc_count; \ + __i++, ha_addr +=3D (dev)->addr_len) + int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev); int __dev_direct_xmit(struct sk_buff *skb, u16 queue_id); =20 diff --git a/include/net/netdev_lock.h b/include/net/netdev_lock.h index 3d3aef80beac..118fa89232a0 100644 --- a/include/net/netdev_lock.h +++ b/include/net/netdev_lock.h @@ -80,6 +80,14 @@ netdev_ops_assert_locked_or_invisible(const struct net_d= evice *dev) netdev_ops_assert_locked(dev); } =20 +static inline bool netdev_trylock_ops_compat(struct net_device *dev) +{ + if (netdev_need_ops_lock(dev)) + return netdev_trylock(dev); + else + return rtnl_trylock(); +} + static inline void netdev_lock_ops_compat(struct net_device *dev) { if (netdev_need_ops_lock(dev)) diff --git a/net/core/dev.c b/net/core/dev.c index b1797bd28a6b..acf46a304d62 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1664,6 +1664,92 @@ static int napi_kthread_create(struct napi_struct *n) return err; } =20 +static void dev_set_rx_mode_async(struct work_struct *param) +{ + struct netif_rx_mode_work *ctx; + struct net_device *dev; + + ctx =3D container_of(param, struct netif_rx_mode_work, work); + dev =3D ctx->dev; + + /* This handler requires the instance lock and we cancel this work + * in dev_close where it is already held, resulting in a deadlock. + * Avoid that scenario by trying to acquire the lock and bailing + * out when we are in teardown. + */ + while (!netdev_trylock_ops_compat(dev)) { + if (netif_get_async_state(dev) =3D=3D NETIF_ASYNC_DOWN) + return; + + msleep(20); + } + + /* We could introduce a new lock for this but reusing the addr + * lock works well enough + */ + netif_addr_lock_bh(dev); + if (!netif_get_rx_mode_flag(dev, NETIF_RX_MODE_READY)) { + netif_addr_unlock_bh(dev); + goto out; + } + swap(ctx->ready, ctx->pending); + netif_set_rx_mode_flag(dev, NETIF_RX_MODE_READY, false); + netif_addr_unlock_bh(dev); + + dev->netdev_ops->ndo_set_rx_mode_async(dev); +out: + netdev_unlock_ops_compat(dev); +} + +static int netif_alloc_rx_mode_ctx(struct net_device *dev) +{ + struct netif_rx_mode_work *rx_mode_work; + + rx_mode_work =3D kzalloc_obj(*rx_mode_work); + if (!rx_mode_work) + goto fail; + + rx_mode_work->ready =3D kzalloc_obj(*rx_mode_work->ready); + if (!rx_mode_work->ready) + goto fail_ready; + + rx_mode_work->pending =3D kzalloc_obj(*rx_mode_work->pending); + if (!rx_mode_work->pending) + goto fail_pending; + + INIT_WORK(&rx_mode_work->work, dev_set_rx_mode_async); + rx_mode_work->dev =3D dev; + + dev->async_ctx->rx_mode_work =3D rx_mode_work; + return 0; + +fail_pending: + kfree(rx_mode_work->ready); +fail_ready: + kfree(rx_mode_work); +fail: + return -ENOMEM; +} + +static void netif_free_rx_mode_ctx(struct net_device *dev) +{ + if (!dev->async_ctx->rx_mode_work) + return; + + cancel_work_sync(&dev->async_ctx->rx_mode_work->work); + + kfree(dev->async_ctx->rx_mode_work->ready->uc_addrs); + kfree(dev->async_ctx->rx_mode_work->ready->mc_addrs); + kfree(dev->async_ctx->rx_mode_work->ready); + + kfree(dev->async_ctx->rx_mode_work->pending->uc_addrs); + kfree(dev->async_ctx->rx_mode_work->pending->mc_addrs); + kfree(dev->async_ctx->rx_mode_work->pending); + + kfree(dev->async_ctx->rx_mode_work); + dev->async_ctx->rx_mode_work =3D NULL; +} + static int __netif_alloc_async_ctx(struct net_device *dev) { dev->async_ctx =3D kzalloc_obj(*dev->async_ctx); @@ -1676,17 +1762,27 @@ static int __netif_alloc_async_ctx(struct net_devic= e *dev) =20 static int netif_alloc_async_ctx(struct net_device *dev) { + const struct net_device_ops *ops =3D dev->netdev_ops; int ret; =20 ret =3D __netif_alloc_async_ctx(dev); + + if (!ret && ops->ndo_set_rx_mode_async) + ret =3D netif_alloc_rx_mode_ctx(dev); + return ret; } =20 static void netif_free_async_ctx(struct net_device *dev) { + const struct net_device_ops *ops =3D dev->netdev_ops; + if (!dev->async_ctx) return; =20 + if (ops->ndo_set_rx_mode_async) + netif_free_rx_mode_ctx(dev); + kfree(dev->async_ctx); dev->async_ctx =3D NULL; } @@ -1868,6 +1964,8 @@ EXPORT_SYMBOL(netif_close); */ void netif_disable_async_ops(struct net_device *dev) { + const struct net_device_ops *ops =3D dev->netdev_ops; + netdev_lock_ops_compat(dev); =20 if (!dev->needs_async_ctx || !netif_running(dev)) { @@ -1877,6 +1975,9 @@ void netif_disable_async_ops(struct net_device *dev) =20 netif_set_async_state(dev, NETIF_ASYNC_INACTIVE); netdev_unlock_ops_compat(dev); + + if (ops->ndo_set_rx_mode_async) + cancel_work_sync(&dev->async_ctx->rx_mode_work->work); } EXPORT_SYMBOL(netif_disable_async_ops); =20 @@ -9749,6 +9850,88 @@ int netif_set_allmulti(struct net_device *dev, int i= nc, bool notify) return 0; } =20 +static int __netif_prepare_rx_mode(struct net_device *dev) +{ + bool skip_uc =3D false, skip_mc =3D false; + struct netif_rx_mode_config *pending; + int uc_count =3D 0, mc_count =3D 0; + struct netdev_hw_addr *ha; + char *tmp; + int i; + + pending =3D dev->async_ctx->rx_mode_work->pending; + + skip_uc =3D netif_get_rx_mode_flag(dev, NETIF_RX_MODE_UC_SKIP); + skip_mc =3D netif_get_rx_mode_flag(dev, NETIF_RX_MODE_MC_SKIP); + + /* The allocations need to be atomic since this will be called under + * netif_addr_lock_bh() + */ + if (!skip_uc) { + uc_count =3D netdev_uc_count(dev); + tmp =3D krealloc(pending->uc_addrs, uc_count * dev->addr_len, + GFP_ATOMIC); + if (!tmp) + return -ENOMEM; + + i =3D 0; + pending->uc_addrs =3D tmp; + pending->uc_count =3D uc_count; + netdev_for_each_uc_addr(ha, dev) + memcpy(pending->uc_addrs + (i++) * dev->addr_len, + ha->addr, dev->addr_len); + } + + if (!skip_mc) { + mc_count =3D netdev_mc_count(dev); + tmp =3D krealloc(pending->mc_addrs, mc_count * dev->addr_len, + GFP_ATOMIC); + if (!tmp) + return -ENOMEM; + + i =3D 0; + pending->mc_addrs =3D tmp; + pending->mc_count =3D mc_count; + netdev_for_each_mc_addr(ha, dev) + memcpy(pending->mc_addrs + (i++) * dev->addr_len, + ha->addr, dev->addr_len); + } + + return 0; +} + +/* Attempt to prepare the rx_mode snapshot and if successful, + * signal that it's ready. + */ +static int netif_prepare_rx_mode(struct net_device *dev) +{ + int rc; + + lockdep_assert_held(&dev->addr_list_lock); + rc =3D __netif_prepare_rx_mode(dev); + netif_set_rx_mode_flag(dev, NETIF_RX_MODE_READY, (rc =3D=3D 0)); + return rc; +} + +static void netif_schedule_rx_mode_work(struct net_device *dev) +{ + const struct net_device_ops *ops =3D dev->netdev_ops; + + if (ops->ndo_set_rx_mode) + ops->ndo_set_rx_mode(dev); + + if (!ops->ndo_set_rx_mode_async) + return; + + if (netif_get_async_state(dev) =3D=3D NETIF_ASYNC_INACTIVE) + return; + + if (netif_prepare_rx_mode(dev)) + return; + + schedule_work(&dev->async_ctx->rx_mode_work->work); +} + /* * Upload unicast and multicast address lists to device and * configure RX filtering. When the device doesn't support unicast @@ -9757,8 +9940,6 @@ int netif_set_allmulti(struct net_device *dev, int in= c, bool notify) */ void __dev_set_rx_mode(struct net_device *dev) { - const struct net_device_ops *ops =3D dev->netdev_ops; - /* dev_open will call this function so the list will stay sane. */ if (!(dev->flags&IFF_UP)) return; @@ -9779,8 +9960,7 @@ void __dev_set_rx_mode(struct net_device *dev) } } =20 - if (ops->ndo_set_rx_mode) - ops->ndo_set_rx_mode(dev); + netif_schedule_rx_mode_work(dev); } =20 void dev_set_rx_mode(struct net_device *dev) @@ -9790,6 +9970,66 @@ void dev_set_rx_mode(struct net_device *dev) netif_addr_unlock_bh(dev); } =20 +/* netif_set_rx_mode() - Helper to centralize RX mode requests in core. + * + * If ndo_set_rx_mode_async is provided, perform the required + * setup and invoke ndo_set_rx_mode_async callback. Otherwise this is the + * same as invoking the ndo_set_rx_mode callback. + * + * If ndo_set_rx_mode_async is implemented, the driver must perform all + * RX mode updates via this function and invoking the set_rx_mode callback + * directly is a bug. + */ +void netif_set_rx_mode(struct net_device *dev) +{ + const struct net_device_ops *ops =3D dev->netdev_ops; + struct netif_rx_mode_work *ctx; + bool netif_down; + int rc =3D 0; + + if (WARN_ON(!ops->ndo_set_rx_mode)) + return; + + if (!ops->ndo_set_rx_mode_async) { + ops->ndo_set_rx_mode(dev); + return; + } + + netdev_ops_assert_locked(dev); + + netif_down =3D !netif_running(dev); + if (netif_down) { + rc =3D __netif_alloc_async_ctx(dev); + if (!rc) + rc =3D netif_alloc_rx_mode_ctx(dev); + if (rc) + goto out; + } + + netif_addr_lock_bh(dev); + ops->ndo_set_rx_mode(dev); + rc =3D netif_prepare_rx_mode(dev); + if (rc) { + netif_addr_unlock_bh(dev); + goto out; + } + + /* There might be a work scheduled by dev_set_rx_mode before + * this function's execution that could be using outdated + * config. Clear the ready bit to prevent that work's execution. + */ + ctx =3D dev->async_ctx->rx_mode_work; + swap(ctx->ready, ctx->pending); + netif_set_rx_mode_flag(dev, NETIF_RX_MODE_READY, false); + netif_addr_unlock_bh(dev); + + ops->ndo_set_rx_mode_async(dev); +out: + if (netif_down) + netif_free_async_ctx(dev); +} +EXPORT_SYMBOL(netif_set_rx_mode); + /** * netif_get_flags() - get flags reported to userspace * @dev: device @@ -11451,6 +11691,9 @@ int register_netdevice(struct net_device *dev) } } =20 + if (dev->netdev_ops->ndo_set_rx_mode_async) + dev->needs_async_ctx =3D true; + if (((dev->hw_features | dev->features) & NETIF_F_HW_VLAN_CTAG_FILTER) && (!dev->netdev_ops->ndo_vlan_rx_add_vid || --=20 2.47.3 From nobody Tue Apr 7 07:34:04 2026 Received: from mail-pj1-f53.google.com (mail-pj1-f53.google.com [209.85.216.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 82F9030C610 for ; Sat, 14 Mar 2026 18:29:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773512953; cv=none; b=aD2b+CmxE+agV8kLgMkG7taXY6CameqmASRppds49RC/K4WiddMVi7TlTbNUXtWmUPrxNZrC5UQXMSzwATFZ3MXUhn4YBjgX9jN/QAd5Gmm3LgaFyKulacYOmxRYcxCo4EHeoxYb6WE9/VWsYpyOPucUILFwVR0sJa6HjSUcfFg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773512953; c=relaxed/simple; bh=VSzdK6fFXXfUKXv/QSuO1q2/KGkkuP3m3IoNyvnhahY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=j5YQ64EMHhdW2eS4SoJ3uGRixuFvkpeobeMb0a0CnZWTnQe/vy618FehKGG1jkHoBZTsxYxtW22LmC/qQ4e6ym94EGqwRhwwpwwtmVpuiqrExMyvMQKaSNhrEWmRejzkL9PPGhl30E6+0qF5lsTkuyOtmMJCb4eM+MpxodzXCIo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Hpm+UR2I; arc=none smtp.client-ip=209.85.216.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Hpm+UR2I" Received: by mail-pj1-f53.google.com with SMTP id 98e67ed59e1d1-35a08ce49dcso3044718a91.2 for ; Sat, 14 Mar 2026 11:29:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773512950; x=1774117750; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=vPjyZJZYcHWPj/blRqGZlp+ucpD5kzaKMmjNcDwFvP0=; b=Hpm+UR2ISoqTel3g0/QJQAMklk2H8ruIjLxccQ2UanzGSbxtebZP+AKADohef7TKO9 fOYm0/CY0vPXp5P59c2WxCegyZqtO2xCvLEBhT2GCMv4WfEoAA564Gr3o3gKBZK0GOLh w9iyC/3zE/aW2a9rd3Mkc1lc+jl8GBeHQ23KkJf6DLQxnVdDKUSPAueeeayvVceRZQ4E 7K8BwMM9juEJQkyF0WT1OR0hJYZXwqsgEitezBm6E+fMD4RqmYiBa3kuXowv2FrnQrF1 CcnbY1Qxk3NdLKwDiqaQIEZou1kQNHNMbF0hqh8P0LdcbZpqEWZyh3bkkXPysF9t4KgR MsSQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773512950; x=1774117750; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=vPjyZJZYcHWPj/blRqGZlp+ucpD5kzaKMmjNcDwFvP0=; b=PzA8Bv7235iz+8JP08EoTSbEduNoF2tj0G9jszbDWXy02L4ytzbOlMlFX4BHG3WhIr 9jeT3WWCg+8xfYFOddVakoqii9yPS+TCx14AqUPpF+mS1IIZI4Fkp7u7Oys2uHFmgKTr G2noAV9FTz1lR1pkoMYW5WdaNanNhIJxVlkf0oSiV1etNprtNBETRvE0mq8IBPmgqo8+ T2H0mQbedjqT4Y9n5F6hgFXurxFOrbg5FsD2+H+npnx6o3UElXTnyP/r82K5T4CVtXTh EDbLOMIzHREd+Yr4qIQ8ZanvwaR7zy+qJog1smL1AqW0W2sZ2XkjI3ZG4q790kkeOhEC naug== X-Forwarded-Encrypted: i=1; AJvYcCUyjmKruKm4bf0OOoNdcNtBP9DUsSf8gQV7m9saWbgH0FlqTYTOsvUdjFSJZt7Xc+BMMqMJYjDLZyUfB64=@vger.kernel.org X-Gm-Message-State: AOJu0Yzp3MP1VjP7XZ+OzELDDH04zpL2I5p4ODuj95OPyx7LIZiRVuZc CN2Vmj6/O0Mb+DIK7ocJAX1zf+5F9vIkEfyqbHGsfaKWsl0JMdi/I8MO X-Gm-Gg: ATEYQzxy+V0Skz/AmgQG+k5jt7fFpF+ydh2yLFm009K4XJE3b3xFTEOWyAbnR5LI8Nj 8c2PQvC4mk7hfNuxwttSPw7FaMlJ0mysuxSRaRk39cN53bIUMKIbgUtPSSrw7bL4IIQNUJo3tUX Q93128W7k/ybBqOLCs+eYQaRutqVLnVytYQIVCG06ITw0JbNdiRJVbJbwswetE41zacHwv4zPxk DiNoKax11uLSpRX0wAlX3N2+xygnuoenynWZXOrP+hJC6xcM1KZicD9gyzxRddFNMJ4dOyK+pcC DiNdHy+inYIsjfHIOlHijRkj8UW5/QlGq+cln/qA8JsYS0N/52t84NB0UCHrRWBCmpoSPmfhRQH VpIIyM/Tt1VcKD7p2AQs3LergUqjB0bcb1uJPNlhOA7FYFTFsnTmkFn2lRF+r8wR6fYi9TW+vYD aL6gdo1q1QGtXqwv7IbPjJ+1DWSJypd60A4EVn4FhP5kLE+nY3QcQmZaL8nsRUWAzNuAHujhNB5 oCB8A== X-Received: by 2002:a17:903:1210:b0:2ae:b9cd:d2df with SMTP id d9443c01a7336-2aecab1f32bmr78786355ad.34.1773512949621; Sat, 14 Mar 2026 11:29:09 -0700 (PDT) Received: from localhost.localdomain ([122.168.66.151]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2aece62c581sm77673525ad.33.2026.03.14.11.28.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 14 Mar 2026 11:29:09 -0700 (PDT) From: I Viswanath To: stfomichev@gmail.com, horms@kernel.org, edumazet@google.com, pabeni@redhat.com, andrew+netdev@lunn.ch, kuba@kernel.org, davem@davemloft.net, eperezma@redhat.com, xuanzhuo@linux.alibaba.com, jasowang@redhat.com, mst@redhat.com, przemyslaw.kitszel@intel.com, anthony.l.nguyen@intel.com, jacob.e.keller@intel.com, ronak.doshi@broadcom.com, pcnet32@frontier.com Cc: bcm-kernel-feedback-list@broadcom.com, netdev@vger.kernel.org, virtualization@lists.linux.dev, intel-wired-lan@lists.osuosl.org, linux-kernel@vger.kernel.org, I Viswanath Subject: [PATCH net-next v9 3/7] virtio-net: Implement ndo_set_rx_mode_async callback Date: Sat, 14 Mar 2026 23:58:05 +0530 Message-ID: <20260314182809.362808-4-viswanathiyyappan@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260314182809.362808-1-viswanathiyyappan@gmail.com> References: <20260314182809.362808-1-viswanathiyyappan@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement the ndo_set_rx_mode_async callback and update the driver to use the snapshot/commit model for RX mode update. Signed-off-by: I Viswanath Reviewed-by: Aleksandr Loktionov --- =20 There are no calls to netif_set_rx_mode in virtio-net =20 drivers/net/virtio_net.c | 85 ++++++++++++---------------------------- 1 file changed, 25 insertions(+), 60 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 811b90da15a9..70255d09401c 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -448,12 +448,6 @@ struct virtnet_info { /* Work struct for config space updates */ struct work_struct config_work; =20 - /* Work struct for setting rx mode */ - struct work_struct rx_mode_work; - - /* OK to queue work setting RX mode? */ - bool rx_mode_work_enabled; - /* Does the affinity hint is set for virtqueues? */ bool affinity_hint_set; =20 @@ -717,20 +711,6 @@ static void virtnet_rq_free_buf(struct virtnet_info *v= i, put_page(virt_to_head_page(buf)); } =20 -static void enable_rx_mode_work(struct virtnet_info *vi) -{ - rtnl_lock(); - vi->rx_mode_work_enabled =3D true; - rtnl_unlock(); -} - -static void disable_rx_mode_work(struct virtnet_info *vi) -{ - rtnl_lock(); - vi->rx_mode_work_enabled =3D false; - rtnl_unlock(); -} - static void virtqueue_napi_schedule(struct napi_struct *napi, struct virtqueue *vq) { @@ -3802,33 +3782,30 @@ static int virtnet_close(struct net_device *dev) return 0; } =20 -static void virtnet_rx_mode_work(struct work_struct *work) +static void virtnet_set_rx_mode_async(struct net_device *dev) { - struct virtnet_info *vi =3D - container_of(work, struct virtnet_info, rx_mode_work); + struct virtnet_info *vi =3D netdev_priv(dev); u8 *promisc_allmulti __free(kfree) =3D NULL; - struct net_device *dev =3D vi->dev; struct scatterlist sg[2]; struct virtio_net_ctrl_mac *mac_data; - struct netdev_hw_addr *ha; + char *ha_addr; int uc_count; int mc_count; void *buf; - int i; + int i, ni; =20 - /* We can't dynamically set ndo_set_rx_mode, so return gracefully */ + /* We can't dynamically set rx_mode, so return gracefully */ if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX)) return; =20 - promisc_allmulti =3D kzalloc_obj(*promisc_allmulti); + promisc_allmulti =3D kzalloc_obj(*promisc_allmulti, GFP_ATOMIC); if (!promisc_allmulti) { dev_warn(&dev->dev, "Failed to set RX mode, no memory.\n"); return; } =20 - rtnl_lock(); - - *promisc_allmulti =3D !!(dev->flags & IFF_PROMISC); + *promisc_allmulti =3D netif_get_rx_mode_cfg(dev, + NETIF_RX_MODE_CFG_PROMISC); sg_init_one(sg, promisc_allmulti, sizeof(*promisc_allmulti)); =20 if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, @@ -3836,7 +3813,8 @@ static void virtnet_rx_mode_work(struct work_struct *= work) dev_warn(&dev->dev, "Failed to %sable promisc mode.\n", *promisc_allmulti ? "en" : "dis"); =20 - *promisc_allmulti =3D !!(dev->flags & IFF_ALLMULTI); + *promisc_allmulti =3D netif_get_rx_mode_cfg(dev, + NETIF_RX_MODE_CFG_ALLMULTI); sg_init_one(sg, promisc_allmulti, sizeof(*promisc_allmulti)); =20 if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, @@ -3844,27 +3822,22 @@ static void virtnet_rx_mode_work(struct work_struct= *work) dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n", *promisc_allmulti ? "en" : "dis"); =20 - netif_addr_lock_bh(dev); - - uc_count =3D netdev_uc_count(dev); - mc_count =3D netdev_mc_count(dev); + uc_count =3D netif_rx_mode_uc_count(dev); + mc_count =3D netif_rx_mode_mc_count(dev); /* MAC filter - use one buffer for both lists */ buf =3D kzalloc(((uc_count + mc_count) * ETH_ALEN) + (2 * sizeof(mac_data->entries)), GFP_ATOMIC); mac_data =3D buf; - if (!buf) { - netif_addr_unlock_bh(dev); - rtnl_unlock(); + if (!buf) return; - } =20 sg_init_table(sg, 2); =20 /* Store the unicast list and count in the front of the buffer */ mac_data->entries =3D cpu_to_virtio32(vi->vdev, uc_count); i =3D 0; - netdev_for_each_uc_addr(ha, dev) - memcpy(&mac_data->macs[i++][0], ha->addr, ETH_ALEN); + netif_rx_mode_for_each_uc_addr(ha_addr, dev, ni) + memcpy(&mac_data->macs[i++][0], ha_addr, ETH_ALEN); =20 sg_set_buf(&sg[0], mac_data, sizeof(mac_data->entries) + (uc_count * ETH_ALEN)); @@ -3874,10 +3847,8 @@ static void virtnet_rx_mode_work(struct work_struct = *work) =20 mac_data->entries =3D cpu_to_virtio32(vi->vdev, mc_count); i =3D 0; - netdev_for_each_mc_addr(ha, dev) - memcpy(&mac_data->macs[i++][0], ha->addr, ETH_ALEN); - - netif_addr_unlock_bh(dev); + netif_rx_mode_for_each_mc_addr(ha_addr, dev, ni) + memcpy(&mac_data->macs[i++][0], ha_addr, ETH_ALEN); =20 sg_set_buf(&sg[1], mac_data, sizeof(mac_data->entries) + (mc_count * ETH_ALEN)); @@ -3886,17 +3857,16 @@ static void virtnet_rx_mode_work(struct work_struct= *work) VIRTIO_NET_CTRL_MAC_TABLE_SET, sg)) dev_warn(&dev->dev, "Failed to set MAC filter table.\n"); =20 - rtnl_unlock(); - kfree(buf); } =20 static void virtnet_set_rx_mode(struct net_device *dev) { - struct virtnet_info *vi =3D netdev_priv(dev); + bool allmulti =3D !!(dev->flags & IFF_ALLMULTI); + bool promisc =3D !!(dev->flags & IFF_PROMISC); =20 - if (vi->rx_mode_work_enabled) - schedule_work(&vi->rx_mode_work); + netif_set_rx_mode_cfg(dev, NETIF_RX_MODE_CFG_ALLMULTI, allmulti); + netif_set_rx_mode_cfg(dev, NETIF_RX_MODE_CFG_PROMISC, promisc); } =20 static int virtnet_vlan_rx_add_vid(struct net_device *dev, @@ -5711,8 +5681,6 @@ static void virtnet_freeze_down(struct virtio_device = *vdev) =20 /* Make sure no work handler is accessing the device */ flush_work(&vi->config_work); - disable_rx_mode_work(vi); - flush_work(&vi->rx_mode_work); =20 if (netif_running(vi->dev)) { rtnl_lock(); @@ -5738,8 +5706,6 @@ static int virtnet_restore_up(struct virtio_device *v= dev) =20 virtio_device_ready(vdev); =20 - enable_rx_mode_work(vi); - if (netif_running(vi->dev)) { rtnl_lock(); err =3D virtnet_open(vi->dev); @@ -6214,6 +6180,7 @@ static const struct net_device_ops virtnet_netdev =3D= { .ndo_validate_addr =3D eth_validate_addr, .ndo_set_mac_address =3D virtnet_set_mac_address, .ndo_set_rx_mode =3D virtnet_set_rx_mode, + .ndo_set_rx_mode_async =3D virtnet_set_rx_mode_async, .ndo_get_stats64 =3D virtnet_stats, .ndo_vlan_rx_add_vid =3D virtnet_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid =3D virtnet_vlan_rx_kill_vid, @@ -6834,7 +6801,6 @@ static int virtnet_probe(struct virtio_device *vdev) vdev->priv =3D vi; =20 INIT_WORK(&vi->config_work, virtnet_config_changed_work); - INIT_WORK(&vi->rx_mode_work, virtnet_rx_mode_work); =20 if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) { vi->mergeable_rx_bufs =3D true; @@ -6986,8 +6952,6 @@ static int virtnet_probe(struct virtio_device *vdev) if (vi->has_rss || vi->has_rss_hash_report) virtnet_init_default_rss(vi); =20 - enable_rx_mode_work(vi); - /* serialize netdev register + virtio_device_ready() with ndo_open() */ rtnl_lock(); =20 @@ -7136,8 +7100,6 @@ static void virtnet_remove(struct virtio_device *vdev) =20 /* Make sure no work handler is accessing the device. */ flush_work(&vi->config_work); - disable_rx_mode_work(vi); - flush_work(&vi->rx_mode_work); =20 virtnet_free_irq_moder(vi); =20 @@ -7158,6 +7120,7 @@ static __maybe_unused int virtnet_freeze(struct virti= o_device *vdev) virtnet_freeze_down(vdev); remove_vq_common(vi); =20 + netif_disable_async_ops(vi->dev); return 0; } =20 @@ -7166,6 +7129,7 @@ static __maybe_unused int virtnet_restore(struct virt= io_device *vdev) struct virtnet_info *vi =3D vdev->priv; int err; =20 + netif_enable_async_ops(vi->dev); err =3D virtnet_restore_up(vdev); if (err) return err; @@ -7175,6 +7139,7 @@ static __maybe_unused int virtnet_restore(struct virt= io_device *vdev) if (err) { virtnet_freeze_down(vdev); remove_vq_common(vi); + netif_disable_async_ops(vi->dev); return err; } =20 --=20 2.47.3 From nobody Tue Apr 7 07:34:04 2026 Received: from mail-pl1-f181.google.com (mail-pl1-f181.google.com [209.85.214.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 499C81C3C08 for ; Sat, 14 Mar 2026 18:29:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773512960; cv=none; b=gN3QdR6RyiApOXIeRBiqoN162UjBDIbXniBE98H7lXwKIENX4ymjyGrVzfL5nu+teASKKcTo0foFCJAnvIv25402XPbXCIZ6eLyiCLwlU3yZfcOMstha82PLs03yudV81wWoMWm3isYqOulSjYSeAhnMfSEIu/FRy4hlr2plusU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773512960; c=relaxed/simple; bh=dO/o0JMUv+1ZIvwhmT7hMk44yXS9kH2XOnxXr/908xQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uFsxp9FiPlTPR7iLI6ozzlxImH6G61P0wdqhyLr1EItu84Dd47jRwNT/qMJ4zwsvyz0IdecLUVrXN6yKH3jQQBWl9XuISRMboBI+9KiHrZtqdQdklztMNElw3TxvIR4v/kQKdD2/6rTONzoihcS6hmTEBqmg34vThv+qoCsycrU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Brohx7Mc; arc=none smtp.client-ip=209.85.214.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Brohx7Mc" Received: by mail-pl1-f181.google.com with SMTP id d9443c01a7336-2b042533de1so3856825ad.0 for ; Sat, 14 Mar 2026 11:29:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773512959; x=1774117759; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=HcUZRx+vC9EsPoreW0zaJm9GJsT/ODmp1Tzy9ZQGo5g=; b=Brohx7MccDU9TKHJVQ6jwhEuxgT8IHS2grEmygbD8Ziv+P/TywAabAjIuwFIia/uNc JXTvXCBON1LZnDjJwx5VkV/xdwM9uYJB61HWlievtZYpKYMFfFs0OQVKGuF+zgo4yuGp WlWsmr/5trnflvUnkvhKNq1Ahj6zEQBOUaJP1z/NXtWgBmrjQxpPgZ6NBPKbC4123uy+ wSbraUDANqQG2lZD05rARHJHVyHXWet+sV29TqvE0hFJA+0WVzvigvLpv4SOmcPr1YwH tpul6OJXGBqZ5eNoRMYMTTb+oRfiNWXBgIawDf0SGHRa4Y/iQ/Zb18toxKJp82a8xQVU aUMQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773512959; x=1774117759; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=HcUZRx+vC9EsPoreW0zaJm9GJsT/ODmp1Tzy9ZQGo5g=; b=hMk/Z6jATdX1uRA/z/I2XV6Gn485Y21f6Yt5ElXk7jdlutF0C0LSwJ+sCo0dTMykqN N75J2ijn9cC1JgSoFnjUqM48xxBZUh0KloCSaf937VKb/MTHHXjZ+pSA+VKY/tcqkQTm 3Ron04CquCwA9eKSDaVNU2AyHMiOIUEe7vAPOvxpdhMNd+K4AVhw91dmVIzjLRZJmrnN 6Ww+Y+sPPvWPmbs/AF04N4iJoUt5LuI2j0FSFNQSB/WuF3NfdnshfXBPZLXsdWRb625m qgi1Zmr4ugMSsgqftTgKUXs3XN5w+b+QKdgz6BTO4u6fCn1eMCt1wTUHTbqcHta2YM4l H2Qg== X-Forwarded-Encrypted: i=1; AJvYcCVw1sNTCG617OxHpi9pVg3L7qY6MlCKW08GolzBk19i6og2SctYzIluGd1/mdzvjV/rnHkgj3/spBpmMX8=@vger.kernel.org X-Gm-Message-State: AOJu0YyL8MzOFEun7R74IDMfTrsBQ6dty1GUTTVrqG3ufAz149TDOzVg 4Z76RCNa8tKI6YoeP9s3EPILh4eb+x9f48e1tmDTFs4vspccRra2KJNL X-Gm-Gg: ATEYQzzCoDjfL36RKsXhW816mR3l7oYZXxweO8oddLv75kR1f4xHXuxLs/BW87kKHN5 VzmJya9jNMM6LyLNRJf6qyKTWR04icuPb0HFZ3U9angVGn5RJxB/BRYQBazNAEWhAZ0E1tCs0pP Re6s/hHq+hhCwI7+biYbyrcWpUua4acxmHr3kmGTK2eDce+nuAxdMn4Dc+cjGaVMRSGvN+jo2RS 7PBYmhOxMQ3Lzyi7uYPDSgPbR0nr++h/l1wkw73AAAykhhK08f9YdCpfiQkYGpj61VyWV+Rlbv6 VF5fmmBh6ewo8Zi4GU/fZ17ZPFioJbGS+Whzma7ULIrLdIJ3h1DsVqxcQoibwrDbHUd+ElulGoX RXxZJGmtG+HMH+ig8vWO7ulL7xJqE/rVpGAFc0zmWo4vOE+6wTjFuJJxyWw2mDN4QFc2uZPmciz iruF51RqBBmIwnqrJQAlwRasYXGTHagSckahlfGbdG33NMLXgpNHSnVAb4oSUezxa4nIwR+wLub 7t8WBpXXtSMLyGV X-Received: by 2002:a17:903:2283:b0:2ae:c5b2:6a41 with SMTP id d9443c01a7336-2aecac84adamr78848905ad.52.1773512958550; Sat, 14 Mar 2026 11:29:18 -0700 (PDT) Received: from localhost.localdomain ([122.168.66.151]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2aece62c581sm77673525ad.33.2026.03.14.11.29.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 14 Mar 2026 11:29:17 -0700 (PDT) From: I Viswanath To: stfomichev@gmail.com, horms@kernel.org, edumazet@google.com, pabeni@redhat.com, andrew+netdev@lunn.ch, kuba@kernel.org, davem@davemloft.net, eperezma@redhat.com, xuanzhuo@linux.alibaba.com, jasowang@redhat.com, mst@redhat.com, przemyslaw.kitszel@intel.com, anthony.l.nguyen@intel.com, jacob.e.keller@intel.com, ronak.doshi@broadcom.com, pcnet32@frontier.com Cc: bcm-kernel-feedback-list@broadcom.com, netdev@vger.kernel.org, virtualization@lists.linux.dev, intel-wired-lan@lists.osuosl.org, linux-kernel@vger.kernel.org, I Viswanath Subject: [PATCH net-next v9 4/7] e1000: Implement ndo_set_rx_mode_async callback Date: Sat, 14 Mar 2026 23:58:06 +0530 Message-ID: <20260314182809.362808-5-viswanathiyyappan@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260314182809.362808-1-viswanathiyyappan@gmail.com> References: <20260314182809.362808-1-viswanathiyyappan@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement the ndo_set_rx_mode_async callback and update the driver to use the snapshot/commit model for RX mode update. Signed-off-by: I Viswanath Reviewed-by: Aleksandr Loktionov --- Call paths involving netif_set_rx_mode in e1000 netif_set_rx_mode |-- __e1000_shutdown (lock added) | `-- e1000_configure |-- e1000_open (ndo_open, takes lock) | `-- e1000_up |-- e1000_reinit_locked | |-- e1000_set_features (ndo_set_features, takes lock) | |-- e1000_reset_task (ethtool callback, takes lock) | |-- e1000_mii_ioctl | | `-- e1000_ioctl (ndo_do_ioctl, takes lock) | `-- e1000_nway_reset (ethtool callback, takes lock) | |-- e1000_change_mtu (ndo_change_mtu, takes lock) |-- e1000_resume (lock added) |-- e1000_io_resume (lock added) | |-- e1000_set_link_ksettings (ethtool callback, takes lock) |-- e1000_set_pauseparam (ethtool callback, takes lock) `-- e1000_set_ringparam (ethtool callback, takes lock) drivers/net/ethernet/intel/e1000/e1000_main.c | 77 ++++++++++++++----- 1 file changed, 59 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/et= hernet/intel/e1000/e1000_main.c index 9b09eb144b81..ec25b41c63b7 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -99,6 +99,7 @@ static void e1000_clean_tx_ring(struct e1000_adapter *ada= pter, static void e1000_clean_rx_ring(struct e1000_adapter *adapter, struct e1000_rx_ring *rx_ring); static void e1000_set_rx_mode(struct net_device *netdev); +static void e1000_set_rx_mode_async(struct net_device *netdev); static void e1000_update_phy_info_task(struct work_struct *work); static void e1000_watchdog(struct work_struct *work); static void e1000_82547_tx_fifo_stall_task(struct work_struct *work); @@ -359,7 +360,7 @@ static void e1000_configure(struct e1000_adapter *adapt= er) struct net_device *netdev =3D adapter->netdev; int i; =20 - e1000_set_rx_mode(netdev); + netif_set_rx_mode(netdev); =20 e1000_restore_vlan(adapter); e1000_init_manageability(adapter); @@ -823,6 +824,7 @@ static const struct net_device_ops e1000_netdev_ops =3D= { .ndo_stop =3D e1000_close, .ndo_start_xmit =3D e1000_xmit_frame, .ndo_set_rx_mode =3D e1000_set_rx_mode, + .ndo_set_rx_mode_async =3D e1000_set_rx_mode_async, .ndo_set_mac_address =3D e1000_set_mac, .ndo_tx_timeout =3D e1000_tx_timeout, .ndo_change_mtu =3D e1000_change_mtu, @@ -2223,23 +2225,44 @@ static int e1000_set_mac(struct net_device *netdev,= void *p) } =20 /** - * e1000_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode s= et + * e1000_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode + * config. * @netdev: network interface device structure * * The set_rx_mode entry point is called whenever the unicast or multicast * address lists or the network interface flags are updated. This routine = is - * responsible for configuring the hardware for proper unicast, multicast, - * promiscuous mode, and all-multi behavior. + * responsible for preparing the rx mode config and scheduling the rx_mode + * work which invokes the set_rx_mode_async callback. **/ static void e1000_set_rx_mode(struct net_device *netdev) +{ + bool allmulti =3D !!(netdev->flags & IFF_ALLMULTI); + bool promisc =3D !!(netdev->flags & IFF_PROMISC); + + netif_set_rx_mode_flag(netdev, NETIF_RX_MODE_UC_SKIP, promisc); + + netif_set_rx_mode_cfg(netdev, NETIF_RX_MODE_CFG_ALLMULTI, allmulti); + netif_set_rx_mode_cfg(netdev, NETIF_RX_MODE_CFG_PROMISC, promisc); +} + +/** + * e1000_set_rx_mode_async - Secondary Unicast, Multicast and Promiscuous = mode + * confirm. + * @netdev: network interface device structure + * + * The set_rx_mode_async callback is responsible for actually updating the + * hardware. This routine is responsible for configuring the hardware for + * proper unicast, multicast, promiscuous mode, and all-multi behavior. + **/ +static void e1000_set_rx_mode_async(struct net_device *netdev) { struct e1000_adapter *adapter =3D netdev_priv(netdev); struct e1000_hw *hw =3D &adapter->hw; - struct netdev_hw_addr *ha; bool use_uc =3D false; + char *ha_addr; u32 rctl; u32 hash_value; - int i, rar_entries =3D E1000_RAR_ENTRIES; + int i, rar_entries =3D E1000_RAR_ENTRIES, ni; int mta_reg_count =3D E1000_NUM_MTA_REGISTERS; u32 *mcarray =3D kcalloc(mta_reg_count, sizeof(u32), GFP_ATOMIC); =20 @@ -2250,11 +2273,11 @@ static void e1000_set_rx_mode(struct net_device *ne= tdev) =20 rctl =3D er32(RCTL); =20 - if (netdev->flags & IFF_PROMISC) { + if (netif_get_rx_mode_cfg(netdev, NETIF_RX_MODE_CFG_PROMISC)) { rctl |=3D (E1000_RCTL_UPE | E1000_RCTL_MPE); rctl &=3D ~E1000_RCTL_VFE; } else { - if (netdev->flags & IFF_ALLMULTI) + if (netif_get_rx_mode_cfg(netdev, NETIF_RX_MODE_CFG_ALLMULTI)) rctl |=3D E1000_RCTL_MPE; else rctl &=3D ~E1000_RCTL_MPE; @@ -2263,9 +2286,9 @@ static void e1000_set_rx_mode(struct net_device *netd= ev) rctl |=3D E1000_RCTL_VFE; } =20 - if (netdev_uc_count(netdev) > rar_entries - 1) { + if (netif_rx_mode_uc_count(netdev) > rar_entries - 1) { rctl |=3D E1000_RCTL_UPE; - } else if (!(netdev->flags & IFF_PROMISC)) { + } else if (!netif_get_rx_mode_cfg(netdev, NETIF_RX_MODE_CFG_PROMISC)) { rctl &=3D ~E1000_RCTL_UPE; use_uc =3D true; } @@ -2286,23 +2309,23 @@ static void e1000_set_rx_mode(struct net_device *ne= tdev) */ i =3D 1; if (use_uc) - netdev_for_each_uc_addr(ha, netdev) { + netif_rx_mode_for_each_uc_addr(ha_addr, netdev, ni) { if (i =3D=3D rar_entries) break; - e1000_rar_set(hw, ha->addr, i++); + e1000_rar_set(hw, ha_addr, i++); } =20 - netdev_for_each_mc_addr(ha, netdev) { + netif_rx_mode_for_each_mc_addr(ha_addr, netdev, ni) { if (i =3D=3D rar_entries) { /* load any remaining addresses into the hash table */ u32 hash_reg, hash_bit, mta; - hash_value =3D e1000_hash_mc_addr(hw, ha->addr); + hash_value =3D e1000_hash_mc_addr(hw, ha_addr); hash_reg =3D (hash_value >> 5) & 0x7F; hash_bit =3D hash_value & 0x1F; mta =3D (1 << hash_bit); mcarray[hash_reg] |=3D mta; } else { - e1000_rar_set(hw, ha->addr, i++); + e1000_rar_set(hw, ha_addr, i++); } } =20 @@ -5092,7 +5115,10 @@ static int __e1000_shutdown(struct pci_dev *pdev, bo= ol *enable_wake) =20 if (wufc) { e1000_setup_rctl(adapter); - e1000_set_rx_mode(netdev); + + rtnl_lock(); + netif_set_rx_mode(netdev); + rtnl_unlock(); =20 rctl =3D er32(RCTL); =20 @@ -5150,11 +5176,13 @@ static int e1000_suspend(struct device *dev) { int retval; struct pci_dev *pdev =3D to_pci_dev(dev); + struct net_device *netdev =3D pci_get_drvdata(pdev); bool wake; =20 retval =3D __e1000_shutdown(pdev, &wake); device_set_wakeup_enable(dev, wake); =20 + netif_disable_async_ops(netdev); return retval; } =20 @@ -5166,6 +5194,8 @@ static int e1000_resume(struct device *dev) struct e1000_hw *hw =3D &adapter->hw; u32 err; =20 + netif_enable_async_ops(netdev); + if (adapter->need_ioport) err =3D pci_enable_device(pdev); else @@ -5195,8 +5225,11 @@ static int e1000_resume(struct device *dev) =20 e1000_init_manageability(adapter); =20 - if (netif_running(netdev)) + if (netif_running(netdev)) { + rtnl_lock(); e1000_up(adapter); + rtnl_unlock(); + } =20 netif_device_attach(netdev); =20 @@ -5205,6 +5238,7 @@ static int e1000_resume(struct device *dev) =20 static void e1000_shutdown(struct pci_dev *pdev) { + struct net_device *netdev =3D pci_get_drvdata(pdev); bool wake; =20 __e1000_shutdown(pdev, &wake); @@ -5213,6 +5247,8 @@ static void e1000_shutdown(struct pci_dev *pdev) pci_wake_from_d3(pdev, wake); pci_set_power_state(pdev, PCI_D3hot); } + + netif_disable_async_ops(netdev); } =20 #ifdef CONFIG_NET_POLL_CONTROLLER @@ -5312,11 +5348,16 @@ static void e1000_io_resume(struct pci_dev *pdev) { struct net_device *netdev =3D pci_get_drvdata(pdev); struct e1000_adapter *adapter =3D netdev_priv(netdev); + int rc; =20 e1000_init_manageability(adapter); =20 if (netif_running(netdev)) { - if (e1000_up(adapter)) { + rtnl_lock(); + rc =3D e1000_up(adapter); + rtnl_unlock(); + + if (rc) { pr_info("can't bring device back up after reset\n"); return; } --=20 2.47.3 From nobody Tue Apr 7 07:34:04 2026 Received: from mail-pl1-f174.google.com (mail-pl1-f174.google.com [209.85.214.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8BF48BA21 for ; Sat, 14 Mar 2026 18:29:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773512970; cv=none; b=eFqrfKmvUemZdb+yqSfGQjlmE8p3BnVNfHUOGMYeDhvJp6UQZ117XkFHtXhVIHQPuqxF+XqyvkoJFALJb6MQti8Wha3JzPybF56HTMfIfymLUdwgNKkMmLe9qSFez3xTgIDe9UFvn1iRWZDVSgY/jIJQpS9Olpox6oM6n6SMZCk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773512970; c=relaxed/simple; bh=QLZYYEoj+5kLfwWS2IqKub9BTqN23yPeZ2bW6yAB0N4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mRkkifSJ0ngaFxf630E+LX0QiwLCNbZ4sapHTWtAX5SHVTT4DlmX8XJqPAo2yJSWqpoz2RBIHnw096CaHJ48T88RHX30imTHw+Fkf1ev3CJJpebL2rKQJMc2ydCz0r0neUXiuJBIaKLpAappryLw/QyOw/thTSMP2SYM2wxmmOU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=FMxYfnhi; arc=none smtp.client-ip=209.85.214.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="FMxYfnhi" Received: by mail-pl1-f174.google.com with SMTP id d9443c01a7336-2b04b4974abso2543325ad.1 for ; Sat, 14 Mar 2026 11:29:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773512969; x=1774117769; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=IB6x/lr1ek9kI9gI1prPQzKFPvlqHQ7Z+jL2sCBy488=; b=FMxYfnhi+21QvpNVJLMxrxfpYn3MFU1yIWd0SaDIllEPzEYag8eWm0OnHDVkw4oqo5 ZKddlHnxTnuB/klDtPkQ+DTYpMclDFn5km+vdZcbFwwicwWJvLnDzVaTW7cABi6+6VKi WBIYaySPmcowSec2oNIiMUPr/BvZIxnsJBdsQZBqcYr6r8CJCnciOJxOfrdHqKUBK7ax Yy4Wr7sa/TXEBDGcBBa6ypzAUdkXlj1rB/F9/GDmuRoHS0vy4KoCvfj8nzVAMbbpjNpj wy0t9uVa5iZvloU3tg1uHmeBzGqCxBiphUbmZK119U6/duD6yvWJdInRUfxIs7W+axxl CQPQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773512969; x=1774117769; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=IB6x/lr1ek9kI9gI1prPQzKFPvlqHQ7Z+jL2sCBy488=; b=mXTLdcGHdzYCqJSfXUzKee6t1SApBzHfcFVj4J3y7pUFqv6yrDGGYaRc2rL1hFoGRJ /7glbiKSvRttoP7D5pMXTEg3BFXzCRaQ/cIQw6EGhhQsY2doWQjWmubaFJ6vLnSzEmOi Nh6JPDAgRq7q1pr9aWcqj5864ySMsSyBdir9iqiOfWsQnwO81eT/JgCRty58f/wBH/Vk sUjsrh2J/kYIwj0mIPKolrp815d/Jbxy2Bea6N61GU4UFFllNPGEkOMv/h//d0SwwGjZ 5VDcdWMXgJCGsjDOdLiV1bzI8vkKwmnsJi3gSxwKvL0g1XAzDIWUrs6IaXCY878D89hv Nzpg== X-Forwarded-Encrypted: i=1; AJvYcCXGVFTGho0YXnizzyU6lIAzU9AenK4f5zgU93I5U/n8rcc/Ag3FJHqMBp0LM8ZWdgAP4iFdxwWqyi/icEc=@vger.kernel.org X-Gm-Message-State: AOJu0YzW2nHoHb/TeLZt5fQz57rdjbomA4nD1OIfkqIxc2MLZ47iI/5F itfWotFs9tiIPEcQJMTjShbvlxP2zyrPC/amU0uuBh9Ha2CreIsm7L3M X-Gm-Gg: ATEYQzzNSbzv5GtCfi1J60bMYuWPVUJIEYXRNJV4q47Ea/UI5irQ/mJRB4Qe9+RrXtM wxPdoXVuVUcTbED/QrXTY8MjGFgdYMAGEPJmT7MOSBGijczb2BSefOjpZS2hmaUFvYnMKNchN0K X5QZNXnl93unfIzyI2L1xyogDTrKRhNSlc6GaKj98Zh3gxBOsw/NKKlOSHrCRAUgjWXt0zdeH1J AjZFrr15LBM7kC8UFaH5rCP3VtNCngD4+CgOMDQ+sV8BMhcLkMqrTyfYTZDAb6jreecwuiurVfy XTDGK0wed8FtY3n9BPfWA/CxBzjL0ywUl2OyvGxBe3cQskA77ulDfwxdozdjpUUZtrGTUFsv44W jAvebmmAD0OdMKOgHLcbYQSLvmpjHCKGlLHCWKkiuXtp2gN7R++mhfLqlZiJ2n2DBXDp/GczJTe 7Osj8h/YQnedeiaOK8TqdoZQVfD5DBxAKbKXnJdshLyFLn8m8DXNvzOa4UJikkCAPPvVHVCc+Fx oT6Ng== X-Received: by 2002:a17:902:d592:b0:2ae:5ec4:2f78 with SMTP id d9443c01a7336-2aecaaa860dmr85707515ad.33.1773512968776; Sat, 14 Mar 2026 11:29:28 -0700 (PDT) Received: from localhost.localdomain ([122.168.66.151]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2aece62c581sm77673525ad.33.2026.03.14.11.29.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 14 Mar 2026 11:29:27 -0700 (PDT) From: I Viswanath To: stfomichev@gmail.com, horms@kernel.org, edumazet@google.com, pabeni@redhat.com, andrew+netdev@lunn.ch, kuba@kernel.org, davem@davemloft.net, eperezma@redhat.com, xuanzhuo@linux.alibaba.com, jasowang@redhat.com, mst@redhat.com, przemyslaw.kitszel@intel.com, anthony.l.nguyen@intel.com, jacob.e.keller@intel.com, ronak.doshi@broadcom.com, pcnet32@frontier.com Cc: bcm-kernel-feedback-list@broadcom.com, netdev@vger.kernel.org, virtualization@lists.linux.dev, intel-wired-lan@lists.osuosl.org, linux-kernel@vger.kernel.org, I Viswanath Subject: [PATCH net-next v9 5/7] 8139cp: Implement ndo_set_rx_mode_async callback Date: Sat, 14 Mar 2026 23:58:07 +0530 Message-ID: <20260314182809.362808-6-viswanathiyyappan@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260314182809.362808-1-viswanathiyyappan@gmail.com> References: <20260314182809.362808-1-viswanathiyyappan@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement the ndo_set_rx_mode_async callback and update the driver to use the snapshot/commit model for RX mode update. Signed-off-by: I Viswanath --- =20 Call paths involving netif_set_rx_mode in 8139cp netif_set_rx_mode |-- cp_init_hw | |-- cp_open (ndo_open, takes lock) | | `-- cp_change_mtu (ndo_change_mtu, takes lock) | | | `-- cp_resume (lock added) | `-- cp_tx_timeout (ndo_tx_timeout, takes lock) drivers/net/ethernet/realtek/8139cp.c | 49 ++++++++++++++++++--------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/r= ealtek/8139cp.c index 5652da8a178c..9651a0d9d8f0 100644 --- a/drivers/net/ethernet/realtek/8139cp.c +++ b/drivers/net/ethernet/realtek/8139cp.c @@ -372,7 +372,6 @@ struct cp_private { } while (0) =20 =20 -static void __cp_set_rx_mode (struct net_device *dev); static void cp_tx (struct cp_private *cp); static void cp_clean_rings (struct cp_private *cp); #ifdef CONFIG_NET_POLL_CONTROLLER @@ -885,30 +884,31 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, /* Set or clear the multicast filter for this adaptor. This routine is not state sensitive and need not be SMP locked. */ =20 -static void __cp_set_rx_mode (struct net_device *dev) +static void cp_set_rx_mode_async(struct net_device *dev) { struct cp_private *cp =3D netdev_priv(dev); u32 mc_filter[2]; /* Multicast hash filter */ + char *ha_addr; int rx_mode; + int ni; =20 /* Note: do not reorder, GCC is clever about common statements. */ - if (dev->flags & IFF_PROMISC) { + if (netif_get_rx_mode_cfg(dev, NETIF_RX_MODE_CFG_PROMISC)) { /* Unconditionally log net taps. */ rx_mode =3D AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys; mc_filter[1] =3D mc_filter[0] =3D 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { + } else if ((netif_rx_mode_mc_count(dev) > multicast_filter_limit) || + netif_get_rx_mode_cfg(dev, NETIF_RX_MODE_CFG_ALLMULTI)) { /* Too many to filter perfectly -- accept all multicasts. */ rx_mode =3D AcceptBroadcast | AcceptMulticast | AcceptMyPhys; mc_filter[1] =3D mc_filter[0] =3D 0xffffffff; } else { - struct netdev_hw_addr *ha; rx_mode =3D AcceptBroadcast | AcceptMyPhys; mc_filter[1] =3D mc_filter[0] =3D 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr =3D ether_crc(ETH_ALEN, ha->addr) >> 26; + netif_rx_mode_for_each_mc_addr(ha_addr, dev, ni) { + int bit_nr =3D ether_crc(ETH_ALEN, ha_addr) >> 26; =20 mc_filter[bit_nr >> 5] |=3D 1 << (bit_nr & 31); rx_mode |=3D AcceptMulticast; @@ -925,12 +925,14 @@ static void __cp_set_rx_mode (struct net_device *dev) =20 static void cp_set_rx_mode (struct net_device *dev) { - unsigned long flags; - struct cp_private *cp =3D netdev_priv(dev); + bool allmulti =3D !!(dev->flags & IFF_ALLMULTI); + bool promisc =3D !!(dev->flags & IFF_PROMISC); =20 - spin_lock_irqsave (&cp->lock, flags); - __cp_set_rx_mode(dev); - spin_unlock_irqrestore (&cp->lock, flags); + netif_set_rx_mode_flag(dev, NETIF_RX_MODE_UC_SKIP, true); + netif_set_rx_mode_flag(dev, NETIF_RX_MODE_MC_SKIP, promisc | allmulti); + + netif_set_rx_mode_cfg(dev, NETIF_RX_MODE_CFG_ALLMULTI, allmulti); + netif_set_rx_mode_cfg(dev, NETIF_RX_MODE_CFG_PROMISC, promisc); } =20 static void __cp_get_stats(struct cp_private *cp) @@ -1040,7 +1042,7 @@ static void cp_init_hw (struct cp_private *cp) cp_start_hw(cp); cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */ =20 - __cp_set_rx_mode(dev); + netif_set_rx_mode(dev); cpw32_f (TxConfig, IFG | (TX_DMA_BURST << TxDMAShift)); =20 cpw8(Config1, cpr8(Config1) | DriverLoaded | PMEnable); @@ -1262,7 +1264,7 @@ static void cp_tx_timeout(struct net_device *dev, uns= igned int txqueue) cp_clean_rings(cp); cp_init_rings(cp); cp_start_hw(cp); - __cp_set_rx_mode(dev); + netif_set_rx_mode(dev); cpw16_f(IntrMask, cp_norx_intr_mask); =20 netif_wake_queue(dev); @@ -1870,6 +1872,7 @@ static const struct net_device_ops cp_netdev_ops =3D { .ndo_validate_addr =3D eth_validate_addr, .ndo_set_mac_address =3D cp_set_mac_address, .ndo_set_rx_mode =3D cp_set_rx_mode, + .ndo_set_rx_mode_async =3D cp_set_rx_mode_async, .ndo_get_stats =3D cp_get_stats, .ndo_eth_ioctl =3D cp_ioctl, .ndo_start_xmit =3D cp_start_xmit, @@ -2071,7 +2074,7 @@ static int __maybe_unused cp_suspend(struct device *d= evice) spin_unlock_irqrestore (&cp->lock, flags); =20 device_set_wakeup_enable(device, cp->wol_enabled); - + netif_disable_async_ops(dev); return 0; } =20 @@ -2081,6 +2084,8 @@ static int __maybe_unused cp_resume(struct device *de= vice) struct cp_private *cp =3D netdev_priv(dev); unsigned long flags; =20 + netif_enable_async_ops(dev); + if (!netif_running(dev)) return 0; =20 @@ -2088,7 +2093,11 @@ static int __maybe_unused cp_resume(struct device *d= evice) =20 /* FIXME: sh*t may happen if the Rx ring buffer is depleted */ cp_init_rings_index (cp); + + rtnl_lock(); cp_init_hw (cp); + rtnl_unlock(); + cp_enable_irq(cp); netif_start_queue (dev); =20 @@ -2101,6 +2110,13 @@ static int __maybe_unused cp_resume(struct device *d= evice) return 0; } =20 +static void cp_shutdown(struct pci_dev *pdev) +{ + struct net_device *dev =3D pci_get_drvdata(pdev); + + netif_disable_async_ops(dev); +} + static const struct pci_device_id cp_pci_tbl[] =3D { { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139= ), }, { PCI_DEVICE(PCI_VENDOR_ID_TTTECH, PCI_DEVICE_ID_TTTECH_MC322= ), }, @@ -2116,6 +2132,7 @@ static struct pci_driver cp_driver =3D { .probe =3D cp_init_one, .remove =3D cp_remove_one, .driver.pm =3D &cp_pm_ops, + .shutdown =3D &cp_shutdown }; =20 module_pci_driver(cp_driver); --=20 2.47.3 From nobody Tue Apr 7 07:34:04 2026 Received: from mail-pl1-f177.google.com (mail-pl1-f177.google.com [209.85.214.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5229B22332E for ; Sat, 14 Mar 2026 18:29:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773512980; cv=none; b=kkeIkDjaAhWG6bVTHL8NP1excLg155ze42REOr3yDQiTlJRihujM+f0YRdw4KiyuhQhi1o1o5PkAly5fxfDDnNyMeyKcnl0wrTOpjHOHBkW9sjy6uL0Kw3u1sR1cwFGgPC/CQHcB5NV2iHd7fjqj1rZBnjFvPlT+FL0FMfZkIS4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773512980; c=relaxed/simple; bh=U3vvmkXelI8LTz8QU0K42inS4TOguEVJt/CLkeFByIg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=j0KZQJLSylCFsrmnPkZvUh2H/+gKTDF0Gms7ZFfvb33l+pWaIWDU0JFNuNHicTDUtTu14XFjQ4LicjGqlXljRkBMlTSd2e0P54g+AvYhwCKdT0AQL2296lhjW5x2zk/LFXk0Uvn5u8Gm1MoVBnb7wzd5IeQJ4JFsTI+8mjj1jGs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=anuh+vZ5; arc=none smtp.client-ip=209.85.214.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="anuh+vZ5" Received: by mail-pl1-f177.google.com with SMTP id d9443c01a7336-2aaed195901so15543285ad.0 for ; Sat, 14 Mar 2026 11:29:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773512979; x=1774117779; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7uJuhFREF46e+3OIYgkRDThTE1W9t/zG8t/Q5Vop1iU=; b=anuh+vZ5uzPU1sQInuK1t48Un7PhYhCzvpHWZj9A2u50KnpzOg00hwXaj15+EB5OiS OCKeXixRh1k7lgkliojup1kFRiFd3lkMXLgJIzip/mrV404pHctA3fbngJeBvteyWNIn zhLAAkbBDAgBJJQZtNJC816mwZwA7WUpHYY7BusUsx63tlXJBxACLY1B+A4JiVeSZsZo 5DN6W6VMGdCAge4Pv4js+6oaVqUfgUkPf7PtbRj5T1cK7/hGEPqD+uSjXrlzS4hwl78g qySxAG3nAQW2bAB+mf0pqDP3nwyfKQMb4kdiFQWxoQaqjsmV61GnFpP15sBQHemNd1Sb k96g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773512979; x=1774117779; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=7uJuhFREF46e+3OIYgkRDThTE1W9t/zG8t/Q5Vop1iU=; b=P3SbM0uKGdxbJYK5/9CQrGcMiDaTcdpZK90uOAn5hnWYRnz6MGHeSh6BRCzKp1wBHD wYSjapswQgC97povEWDIGekEj0F7fQq5bDbE8KYxHax65nZuqDdONx2Z6QI5oaJabkaQ rVsRNuUTpBC+BQu4jlih2v3xFlituby6oTuDMY8AIs2H7Hg07yuZNRur/q+obtCtVtFm qgI4IJZ2X5Fm1T9khw9mZHWg5Xcu+JLgQVrz0zrh+bE0Tx3RRbDY1+Lbn3ENFm74nxCF a0efbPkXnTmtQfMwNot3UtIVuwYxozLtinEkUxUyyn1WnxcwL5Gu+3obagZZOjMo0Dbr EuEA== X-Forwarded-Encrypted: i=1; AJvYcCWPQYnSj0pRq65TPPqOkuE8UH9p0xwXS/s2vZwdiRWfi40fNSmR+zDgsmUAO2bqQVL+mpolhZ5WuSc164s=@vger.kernel.org X-Gm-Message-State: AOJu0YwfKKxyZCBvvpQt46XX1YtvQa+Q0cwmBVWXA3z7BVet28KK+5N4 p/8cAqf2UC0dUN/0oBqA3Bu1p3X0fRKIrA9Hv2m6X5AnSI8YzRDmk0Uj X-Gm-Gg: ATEYQzz91JNklHyOgEjDCoVHY8et1/ePYdlWv1r6pT0bUtTnXiGg/D4tpKjRHYw6DYd iNg75c1ollXecUbFS7Iv1IiWhVZUoZWFDK3Ot4ZYBY9cI0bCiyxWf863fvVuUnx6g2Cf2BtuXyp be6ieF6jlXCvzuUbvp8bws8Z29fryQjP9vLxgt1yjhY/sLTQGTKZDyLKP7qCQ5RiqUUGRsJoFno YrRfeoFnmWoRl+jkog5k/F2hZO+MioObMqCHweB/wvtxaF/fOYkC+heWDv3g0CGM2+7vKOoLgSN vpgLM6bR69L/Hods7x+yeZ0w0nNLBueDDuS8/DV4TKmlV7ss+ZlgTY/UXmvvTY6HmwvKKG0Ac9L xwDyptpWYmcAUG305Gr5xSdXujw6c3yIYNqbcYmKbtAoucDYoOFb//gZI0XjlBTuTLp0mZPO0rf 8Wp47tQxQz2eEKb5aHWLQ6DV9X6xlc9u88t2utSuZw2eP1+p6AlX39mhWT2aD/k4v2x6DR8Sa5L jwBsA== X-Received: by 2002:a17:902:f70a:b0:2ae:5044:8dd4 with SMTP id d9443c01a7336-2aeca960929mr72806085ad.19.1773512978654; Sat, 14 Mar 2026 11:29:38 -0700 (PDT) Received: from localhost.localdomain ([122.168.66.151]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2aece62c581sm77673525ad.33.2026.03.14.11.29.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 14 Mar 2026 11:29:38 -0700 (PDT) From: I Viswanath To: stfomichev@gmail.com, horms@kernel.org, edumazet@google.com, pabeni@redhat.com, andrew+netdev@lunn.ch, kuba@kernel.org, davem@davemloft.net, eperezma@redhat.com, xuanzhuo@linux.alibaba.com, jasowang@redhat.com, mst@redhat.com, przemyslaw.kitszel@intel.com, anthony.l.nguyen@intel.com, jacob.e.keller@intel.com, ronak.doshi@broadcom.com, pcnet32@frontier.com Cc: bcm-kernel-feedback-list@broadcom.com, netdev@vger.kernel.org, virtualization@lists.linux.dev, intel-wired-lan@lists.osuosl.org, linux-kernel@vger.kernel.org, I Viswanath Subject: [PATCH net-next v9 6/7] vmxnet3: Implement ndo_set_rx_mode_async callback Date: Sat, 14 Mar 2026 23:58:08 +0530 Message-ID: <20260314182809.362808-7-viswanathiyyappan@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260314182809.362808-1-viswanathiyyappan@gmail.com> References: <20260314182809.362808-1-viswanathiyyappan@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement the ndo_set_rx_mode_async callback and update the driver to use the snapshot/commit model for RX mode update. Signed-off-by: I Viswanath Reviewed-by: Aleksandr Loktionov --- =20 Call paths involving netif_set_rx_mode in vmxnet3 netif_set_rx_mode `-- vmxnet3_activate_dev |-- vmxnet3_open (ndo_open, takes lock) |-- vmxnet3_change_mtu (ndo_change_mtu, takes lock) |-- vmxnet3_reset_work (takes lock) |-- vmxnet3_resume (lock added) |-- vmxnet3_set_ringparam (ethtool callback, takes lock) `-- vmxnet3_xdp_set `-- vmxnet3_xdp (ndo_bpf, takes lock) drivers/net/vmxnet3/vmxnet3_drv.c | 46 +++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet= 3_drv.c index 40522afc0532..350e44286c00 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -2775,18 +2775,18 @@ static u8 * vmxnet3_copy_mc(struct net_device *netdev) { u8 *buf =3D NULL; - u32 sz =3D netdev_mc_count(netdev) * ETH_ALEN; + u32 sz =3D netif_rx_mode_mc_count(netdev) * ETH_ALEN; + char *ha_addr; + int ni; =20 /* struct Vmxnet3_RxFilterConf.mfTableLen is u16. */ if (sz <=3D 0xffff) { /* We may be called with BH disabled */ buf =3D kmalloc(sz, GFP_ATOMIC); if (buf) { - struct netdev_hw_addr *ha; int i =3D 0; - - netdev_for_each_mc_addr(ha, netdev) - memcpy(buf + i++ * ETH_ALEN, ha->addr, + netif_rx_mode_for_each_mc_addr(ha_addr, netdev, ni) + memcpy(buf + i++ * ETH_ALEN, ha_addr, ETH_ALEN); } } @@ -2796,8 +2796,23 @@ vmxnet3_copy_mc(struct net_device *netdev) =20 static void vmxnet3_set_mc(struct net_device *netdev) +{ + bool allmulti =3D !!(netdev->flags & IFF_ALLMULTI); + bool promisc =3D !!(netdev->flags & IFF_PROMISC); + bool broadcast =3D !!(netdev->flags & IFF_BROADCAST); + + netif_set_rx_mode_flag(netdev, NETIF_RX_MODE_UC_SKIP, true); + netif_set_rx_mode_flag(netdev, NETIF_RX_MODE_MC_SKIP, allmulti); + + netif_set_rx_mode_cfg(netdev, NETIF_RX_MODE_CFG_ALLMULTI, allmulti); + netif_set_rx_mode_cfg(netdev, NETIF_RX_MODE_CFG_PROMISC, promisc); + netif_set_rx_mode_cfg(netdev, NETIF_RX_MODE_CFG_BROADCAST, broadcast); +} + +static void vmxnet3_set_mc_async(struct net_device *netdev) { struct vmxnet3_adapter *adapter =3D netdev_priv(netdev); + int mc_count =3D netif_rx_mode_mc_count(netdev); unsigned long flags; struct Vmxnet3_RxFilterConf *rxConf =3D &adapter->shared->devRead.rxFilterConf; @@ -2806,7 +2821,7 @@ vmxnet3_set_mc(struct net_device *netdev) bool new_table_pa_valid =3D false; u32 new_mode =3D VMXNET3_RXM_UCAST; =20 - if (netdev->flags & IFF_PROMISC) { + if (netif_get_rx_mode_cfg(netdev, NETIF_RX_MODE_CFG_PROMISC)) { u32 *vfTable =3D adapter->shared->devRead.rxFilterConf.vfTable; memset(vfTable, 0, VMXNET3_VFT_SIZE * sizeof(*vfTable)); =20 @@ -2815,16 +2830,16 @@ vmxnet3_set_mc(struct net_device *netdev) vmxnet3_restore_vlan(adapter); } =20 - if (netdev->flags & IFF_BROADCAST) + if (netif_get_rx_mode_cfg(netdev, NETIF_RX_MODE_CFG_BROADCAST)) new_mode |=3D VMXNET3_RXM_BCAST; =20 - if (netdev->flags & IFF_ALLMULTI) + if (netif_get_rx_mode_cfg(netdev, NETIF_RX_MODE_CFG_ALLMULTI)) new_mode |=3D VMXNET3_RXM_ALL_MULTI; else - if (!netdev_mc_empty(netdev)) { + if (mc_count) { new_table =3D vmxnet3_copy_mc(netdev); if (new_table) { - size_t sz =3D netdev_mc_count(netdev) * ETH_ALEN; + size_t sz =3D mc_count * ETH_ALEN; =20 rxConf->mfTableLen =3D cpu_to_le16(sz); new_table_pa =3D dma_map_single( @@ -3213,7 +3228,7 @@ vmxnet3_activate_dev(struct vmxnet3_adapter *adapter) } =20 /* Apply the rx filter settins last. */ - vmxnet3_set_mc(adapter->netdev); + netif_set_rx_mode(adapter->netdev); =20 /* * Check link state when first activating device. It will start the @@ -3977,6 +3992,7 @@ vmxnet3_probe_device(struct pci_dev *pdev, .ndo_get_stats64 =3D vmxnet3_get_stats64, .ndo_tx_timeout =3D vmxnet3_tx_timeout, .ndo_set_rx_mode =3D vmxnet3_set_mc, + .ndo_set_rx_mode_async =3D vmxnet3_set_mc_async, .ndo_vlan_rx_add_vid =3D vmxnet3_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid =3D vmxnet3_vlan_rx_kill_vid, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -4400,6 +4416,7 @@ static void vmxnet3_shutdown_device(struct pci_dev *p= dev) vmxnet3_disable_all_intrs(adapter); =20 clear_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state); + netif_disable_async_ops(netdev); } =20 =20 @@ -4518,6 +4535,7 @@ vmxnet3_suspend(struct device *device) pci_disable_device(pdev); pci_set_power_state(pdev, pci_choose_state(pdev, PMSG_SUSPEND)); =20 + netif_disable_async_ops(netdev); return 0; } =20 @@ -4531,6 +4549,8 @@ vmxnet3_resume(struct device *device) struct net_device *netdev =3D pci_get_drvdata(pdev); struct vmxnet3_adapter *adapter =3D netdev_priv(netdev); =20 + netif_enable_async_ops(netdev); + if (!netif_running(netdev)) return 0; =20 @@ -4559,7 +4579,11 @@ vmxnet3_resume(struct device *device) vmxnet3_rq_cleanup_all(adapter); =20 vmxnet3_reset_dev(adapter); + + rtnl_lock(); err =3D vmxnet3_activate_dev(adapter); + rtnl_unlock(); + if (err !=3D 0) { netdev_err(netdev, "failed to re-activate on resume, error: %d", err); --=20 2.47.3 From nobody Tue Apr 7 07:34:04 2026 Received: from mail-pl1-f171.google.com (mail-pl1-f171.google.com [209.85.214.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D2C493B28D for ; Sat, 14 Mar 2026 18:29:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773512991; cv=none; b=eEbOKT8Q0SqXkXBD9gDwEGvnili6afrgt5r1ugf3lVrffei+0LcVJ2+3MmQlqWifTjst5eb2g54TgEHFR8mNsTa2djh06Q72N9HxPhzLaaTGwhwJsbNLif2VbwZ30m6qWzWQcHSNMjGpRNFuNrbRzcDx/WWm+DiJIFY6xSLZgI0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773512991; c=relaxed/simple; bh=1tG9qcJg/ScoAbc2s3rBPup6tclQThm8ZNIWVQwHMpc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=m3osnsN2BQOUAUbypWYX4UjIT+hCPLX1hL9bBaPVWl0xzTgv2RYdwUqAugeOrc1hV3LCXpSP6sW/X3/wGP9tIUJdjRi4wyPA4SrrYEB3U/3zhQshmNEXls8GSI0BjDVHaCHBrj8fgls5CMeErDU0ZG6hu5hAa5/8IU2WDPYljXM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=b0/7fHcx; arc=none smtp.client-ip=209.85.214.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="b0/7fHcx" Received: by mail-pl1-f171.google.com with SMTP id d9443c01a7336-2ae4e538abdso36154105ad.3 for ; Sat, 14 Mar 2026 11:29:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773512988; x=1774117788; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=+JSH/0/b9giaRQVQnVF9Hnbf5bM9rYVcnC9nwZ0R2/U=; b=b0/7fHcxe40SglyAJpzqO/8MW0rbtz36KdXFN9hn8IZMIH71iVumPVuhdmWBAr8r/R EYtlVNQwLsO6QePN8Wm82otF2dEHFj7S4LBHrIYCrnAjta3EfDniIs3+vWAIoCLIeZjk SB/lLcZC5NZx++H4HjSRkQSEzlbnzstxT3e1mGQ+AhAbcWBxtkKDSAEa7fdJG6N8zYkR oQvySAVyozI4jSDx0gVzxhnwpAhBjlm2CFH/71laegsy/SgK7Hvf+bkVECUPesXozosi gLaRvvngod35hpDBkkepVzzX45BZ6bme9ttA/0UHgLsVVTgDPokQ/L8JCshxEZAQaVv7 hL7g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773512988; x=1774117788; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=+JSH/0/b9giaRQVQnVF9Hnbf5bM9rYVcnC9nwZ0R2/U=; b=N3maWBvvQfzMgUz1QruTaE6EULFOenQgQpojE7g0kViJo3iUZAPX+kHJJoPwiBF/Ij 8zoleGXnBtUxGy8+a0DW8zgrxj6iWHWjk4bdc8xyhSecBStc2+ESNs7adspYrHdzodRO DmqnfzB1gJ+r148ay8fuaOPJBCiFiWq1H/5DPVYpxIbXA/utRf2IvyB0morwuGE07JY/ fd33yqCS/drhGJIcpypR0rO1LG9f4mPuj9ka2FFBsmtaU77GF71fLL9Qkq6yFvpabmQC vGdIOe2LCv1ru4X8c2ZPEI2tqWMnw+9klZbRO7aafij/M7ix1K87urZSZ4MbILbfbN2J v/3g== X-Forwarded-Encrypted: i=1; AJvYcCU8LpvfeVA7xPtvypZ8VkMrt5s/ug4zTI4faQSfZ4dvF66foTM4bBeqgonWhaBma3DvHuSnhop2/deeS9Y=@vger.kernel.org X-Gm-Message-State: AOJu0YyNb9ufVlAzU+TIkpDrzE2X05wXH3q305NBn3faIulhVeRxGv2u 2HUrAdEEy+gqnXHQuiguwDA3CopHJx9DgaSnEDXWMiiDTqPkSrQsSBX6 X-Gm-Gg: ATEYQzwpl6OtaMBfLF8/3ljJhlbpD1b0EzN7OBpQ9vgxPu1Ns9iHYhvZJ3uLviwI8iv f11J4cOQq8GVzWBa9LL49D45502Z6hYYS4lv2F8JV4SZ6/DeSlqMxZKRT+OWsGr1GMlcrk4Txhp 1ilaR28IkJLPvE3q0l8RYQA3p3RDKfAO8Ze1ppPrQC5XoguUqqmlZqvq1gKiw3t3Zgs7sa7dbb/ TTzZfG6jmzigvU5bScUvhZWBu78KX1FYc56LC5Az5ag9q6W88GnduZw5qDzVbZQkvJQw/A8K0gY X4jDbDGMaIPfc4Aft6G9yKOnDJPO7YheoiJO1dY2LLQixRALaFr9nNjqtrAxmnGcmeXplFdE6xj xi55TmMicMI7Zafmkw+uXR/O2DiPcLI6weguttlbgkjanlk55LiCGAu+zcsmnEx+lkQ0LrTHIdF 97YyTL3FuH0mWmvPesuvKO50uVKKvRPb5LKz3K3lLdxUcMyxj3J1VbFy0FwKbwxBFSP0HlCLoxL Lgtwg== X-Received: by 2002:a17:903:90f:b0:2ae:59d3:27f8 with SMTP id d9443c01a7336-2aeca999738mr72086855ad.19.1773512988217; Sat, 14 Mar 2026 11:29:48 -0700 (PDT) Received: from localhost.localdomain ([122.168.66.151]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2aece62c581sm77673525ad.33.2026.03.14.11.29.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 14 Mar 2026 11:29:47 -0700 (PDT) From: I Viswanath To: stfomichev@gmail.com, horms@kernel.org, edumazet@google.com, pabeni@redhat.com, andrew+netdev@lunn.ch, kuba@kernel.org, davem@davemloft.net, eperezma@redhat.com, xuanzhuo@linux.alibaba.com, jasowang@redhat.com, mst@redhat.com, przemyslaw.kitszel@intel.com, anthony.l.nguyen@intel.com, jacob.e.keller@intel.com, ronak.doshi@broadcom.com, pcnet32@frontier.com Cc: bcm-kernel-feedback-list@broadcom.com, netdev@vger.kernel.org, virtualization@lists.linux.dev, intel-wired-lan@lists.osuosl.org, linux-kernel@vger.kernel.org, I Viswanath Subject: [PATCH net-next v9 7/7] pcnet32: Implement ndo_set_rx_mode_async callback Date: Sat, 14 Mar 2026 23:58:09 +0530 Message-ID: <20260314182809.362808-8-viswanathiyyappan@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260314182809.362808-1-viswanathiyyappan@gmail.com> References: <20260314182809.362808-1-viswanathiyyappan@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement the ndo_set_rx_mode_async callback and update the driver to use the snapshot/commit model for RX mode update. Signed-off-by: I Viswanath Reviewed-by: Aleksandr Loktionov --- =20 There are no calls to netif_set_rx_mode in pcnet32 =20 drivers/net/ethernet/amd/pcnet32.c | 65 ++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/= pcnet32.c index 911808ab13a7..d5ad96985d68 100644 --- a/drivers/net/ethernet/amd/pcnet32.c +++ b/drivers/net/ethernet/amd/pcnet32.c @@ -314,8 +314,9 @@ static void pcnet32_tx_timeout(struct net_device *dev, = unsigned int txqueue); static irqreturn_t pcnet32_interrupt(int, void *); static int pcnet32_close(struct net_device *); static struct net_device_stats *pcnet32_get_stats(struct net_device *); -static void pcnet32_load_multicast(struct net_device *dev); +static void pcnet32_load_multicast(struct net_device *dev, bool is_open); static void pcnet32_set_multicast_list(struct net_device *); +static void pcnet32_set_multicast_list_async(struct net_device *); static int pcnet32_ioctl(struct net_device *, struct ifreq *, int); static void pcnet32_watchdog(struct timer_list *); static int mdio_read(struct net_device *dev, int phy_id, int reg_num); @@ -1580,6 +1581,7 @@ static const struct net_device_ops pcnet32_netdev_ops= =3D { .ndo_tx_timeout =3D pcnet32_tx_timeout, .ndo_get_stats =3D pcnet32_get_stats, .ndo_set_rx_mode =3D pcnet32_set_multicast_list, + .ndo_set_rx_mode_async =3D pcnet32_set_multicast_list_async, .ndo_eth_ioctl =3D pcnet32_ioctl, .ndo_set_mac_address =3D eth_mac_addr, .ndo_validate_addr =3D eth_validate_addr, @@ -2260,7 +2262,7 @@ static int pcnet32_open(struct net_device *dev) =20 lp->init_block->mode =3D cpu_to_le16((lp->options & PCNET32_PORT_PORTSEL) << 7); - pcnet32_load_multicast(dev); + pcnet32_load_multicast(dev, true); =20 if (pcnet32_init_ring(dev)) { rc =3D -ENOMEM; @@ -2676,18 +2678,26 @@ static struct net_device_stats *pcnet32_get_stats(s= truct net_device *dev) } =20 /* taken from the sunlance driver, which it took from the depca driver */ -static void pcnet32_load_multicast(struct net_device *dev) +static void pcnet32_load_multicast(struct net_device *dev, bool is_open) { struct pcnet32_private *lp =3D netdev_priv(dev); volatile struct pcnet32_init_block *ib =3D lp->init_block; volatile __le16 *mcast_table =3D (__le16 *)ib->filter; struct netdev_hw_addr *ha; + char *ha_addr; + bool allmulti; unsigned long ioaddr =3D dev->base_addr; - int i; + int i, ni; u32 crc; =20 + if (is_open) + allmulti =3D dev->flags & IFF_ALLMULTI; + else + allmulti =3D netif_get_rx_mode_cfg(dev, + NETIF_RX_MODE_CFG_ALLMULTI); + /* set all multicast bits */ - if (dev->flags & IFF_ALLMULTI) { + if (allmulti) { ib->filter[0] =3D cpu_to_le32(~0U); ib->filter[1] =3D cpu_to_le32(~0U); lp->a->write_csr(ioaddr, PCNET32_MC_FILTER, 0xffff); @@ -2701,20 +2711,41 @@ static void pcnet32_load_multicast(struct net_devic= e *dev) ib->filter[1] =3D 0; =20 /* Add addresses */ - netdev_for_each_mc_addr(ha, dev) { - crc =3D ether_crc_le(6, ha->addr); - crc =3D crc >> 26; - mcast_table[crc >> 4] |=3D cpu_to_le16(1 << (crc & 0xf)); + if (is_open) { + netdev_for_each_mc_addr(ha, dev) { + crc =3D ether_crc_le(6, ha->addr); + crc =3D crc >> 26; + mcast_table[crc >> 4] |=3D cpu_to_le16(1 << (crc & 0xf)); + } + } else { + netif_rx_mode_for_each_mc_addr(ha_addr, dev, ni) { + crc =3D ether_crc_le(6, ha_addr); + crc =3D crc >> 26; + mcast_table[crc >> 4] |=3D cpu_to_le16(1 << (crc & 0xf)); + } } + for (i =3D 0; i < 4; i++) lp->a->write_csr(ioaddr, PCNET32_MC_FILTER + i, le16_to_cpu(mcast_table[i])); } =20 +static void pcnet32_set_multicast_list(struct net_device *dev) +{ + bool allmulti =3D !!(dev->flags & IFF_ALLMULTI); + bool promisc =3D !!(dev->flags & IFF_PROMISC); + + netif_set_rx_mode_flag(dev, NETIF_RX_MODE_UC_SKIP, true); + netif_set_rx_mode_flag(dev, NETIF_RX_MODE_MC_SKIP, promisc | allmulti); + + netif_set_rx_mode_cfg(dev, NETIF_RX_MODE_CFG_ALLMULTI, allmulti); + netif_set_rx_mode_cfg(dev, NETIF_RX_MODE_CFG_PROMISC, promisc); +} + /* * Set or clear the multicast filter for this adaptor. */ -static void pcnet32_set_multicast_list(struct net_device *dev) +static void pcnet32_set_multicast_list_async(struct net_device *dev) { unsigned long ioaddr =3D dev->base_addr, flags; struct pcnet32_private *lp =3D netdev_priv(dev); @@ -2723,7 +2754,7 @@ static void pcnet32_set_multicast_list(struct net_dev= ice *dev) spin_lock_irqsave(&lp->lock, flags); suspended =3D pcnet32_suspend(dev, &flags, 0); csr15 =3D lp->a->read_csr(ioaddr, CSR15); - if (dev->flags & IFF_PROMISC) { + if (netif_get_rx_mode_cfg(dev, NETIF_RX_MODE_CFG_PROMISC)) { /* Log any net taps. */ netif_info(lp, hw, dev, "Promiscuous mode enabled\n"); lp->init_block->mode =3D @@ -2734,7 +2765,7 @@ static void pcnet32_set_multicast_list(struct net_dev= ice *dev) lp->init_block->mode =3D cpu_to_le16((lp->options & PCNET32_PORT_PORTSEL) << 7); lp->a->write_csr(ioaddr, CSR15, csr15 & 0x7fff); - pcnet32_load_multicast(dev); + pcnet32_load_multicast(dev, false); } =20 if (suspended) { @@ -2922,6 +2953,7 @@ static int __maybe_unused pcnet32_pm_suspend(struct d= evice *device_d) pcnet32_close(dev); } =20 + netif_disable_async_ops(dev); return 0; } =20 @@ -2929,6 +2961,7 @@ static int __maybe_unused pcnet32_pm_resume(struct de= vice *device_d) { struct net_device *dev =3D dev_get_drvdata(device_d); =20 + netif_enable_async_ops(dev); if (netif_running(dev)) { pcnet32_open(dev); netif_device_attach(dev); @@ -2937,6 +2970,13 @@ static int __maybe_unused pcnet32_pm_resume(struct d= evice *device_d) return 0; } =20 +static void pcnet32_shutdown(struct pci_dev *pdev) +{ + struct net_device *dev =3D pci_get_drvdata(pdev); + + netif_disable_async_ops(dev); +} + static void pcnet32_remove_one(struct pci_dev *pdev) { struct net_device *dev =3D pci_get_drvdata(pdev); @@ -2964,6 +3004,7 @@ static struct pci_driver pcnet32_driver =3D { .driver =3D { .pm =3D &pcnet32_pm_ops, }, + .shutdown =3D pcnet32_shutdown, }; =20 /* An additional parameter that may be passed in... */ --=20 2.47.3