From: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
To: I Viswanath <viswanathiyyappan@gmail.com>
Cc: netdev@vger.kernel.org, virtualization@lists.linux.dev,
linux-kernel@vger.kernel.org,
I Viswanath <viswanathiyyappan@gmail.com>,
edumazet@google.com, andrew+netdev@lunn.ch, horms@kernel.org,
kuba@kernel.org, pabeni@redhat.com, mst@redhat.com,
eperezma@redhat.com, jasowang@redhat.com
Subject: Re: [PATCH net-next v7 2/2] virtio-net: Implement ndo_write_rx_mode callback
Date: Tue, 6 Jan 2026 19:22:37 +0800 [thread overview]
Message-ID: <1767698557.9158366-1-xuanzhuo@linux.alibaba.com> (raw)
In-Reply-To: <20260102180530.1559514-3-viswanathiyyappan@gmail.com>
If this is a common requirement, it would be better to provide more examples of
driver modifications.
Thanks.
On Fri, 2 Jan 2026 23:35:30 +0530, I Viswanath <viswanathiyyappan@gmail.com> wrote:
> Implement ndo_write_rx_mode callback for virtio-net
>
> Signed-off-by: I Viswanath <viswanathiyyappan@gmail.com>
> ---
> drivers/net/virtio_net.c | 55 +++++++++++++++-------------------------
> 1 file changed, 21 insertions(+), 34 deletions(-)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index 1bb3aeca66c6..83d543bf6ae2 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -460,9 +460,6 @@ struct virtnet_info {
> /* Work struct for config space updates */
> struct work_struct config_work;
>
> - /* Work struct for setting rx mode */
> - struct work_struct rx_mode_work;
> -
> /* OK to queue work setting RX mode? */
> bool rx_mode_work_enabled;
>
> @@ -3866,33 +3863,31 @@ static int virtnet_close(struct net_device *dev)
> return 0;
> }
>
> -static void virtnet_rx_mode_work(struct work_struct *work)
> +static void virtnet_write_rx_mode(struct net_device *dev)
> {
> - struct virtnet_info *vi =
> - container_of(work, struct virtnet_info, rx_mode_work);
> + struct virtnet_info *vi = netdev_priv(dev);
> u8 *promisc_allmulti __free(kfree) = NULL;
> - struct net_device *dev = 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 idx;
> int i;
>
> /* We can't dynamically set ndo_set_rx_mode, so return gracefully */
> if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX))
> return;
>
> - promisc_allmulti = kzalloc(sizeof(*promisc_allmulti), GFP_KERNEL);
> + promisc_allmulti = kzalloc(sizeof(*promisc_allmulti), GFP_ATOMIC);
> if (!promisc_allmulti) {
> dev_warn(&dev->dev, "Failed to set RX mode, no memory.\n");
> return;
> }
>
> - rtnl_lock();
> -
> - *promisc_allmulti = !!(dev->flags & IFF_PROMISC);
> + *promisc_allmulti = netif_rx_mode_get_cfg(dev,
> + NETIF_RX_MODE_CFG_PROMISC);
> sg_init_one(sg, promisc_allmulti, sizeof(*promisc_allmulti));
>
> if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
> @@ -3900,7 +3895,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");
>
> - *promisc_allmulti = !!(dev->flags & IFF_ALLMULTI);
> + *promisc_allmulti = netif_rx_mode_get_cfg(dev,
> + NETIF_RX_MODE_CFG_ALLMULTI);
> sg_init_one(sg, promisc_allmulti, sizeof(*promisc_allmulti));
>
> if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
> @@ -3908,27 +3904,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");
>
> - netif_addr_lock_bh(dev);
> -
> - uc_count = netdev_uc_count(dev);
> - mc_count = netdev_mc_count(dev);
> + uc_count = netif_rx_mode_get_uc_count(dev);
> + mc_count = netif_rx_mode_get_mc_count(dev);
> /* MAC filter - use one buffer for both lists */
> buf = kzalloc(((uc_count + mc_count) * ETH_ALEN) +
> (2 * sizeof(mac_data->entries)), GFP_ATOMIC);
> mac_data = buf;
> - if (!buf) {
> - netif_addr_unlock_bh(dev);
> - rtnl_unlock();
> + if (!buf)
> return;
> - }
>
> sg_init_table(sg, 2);
>
> /* Store the unicast list and count in the front of the buffer */
> mac_data->entries = cpu_to_virtio32(vi->vdev, uc_count);
> i = 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(dev, ha_addr, idx)
> + memcpy(&mac_data->macs[i++][0], ha_addr, ETH_ALEN);
>
> sg_set_buf(&sg[0], mac_data,
> sizeof(mac_data->entries) + (uc_count * ETH_ALEN));
> @@ -3938,10 +3929,8 @@ static void virtnet_rx_mode_work(struct work_struct *work)
>
> mac_data->entries = cpu_to_virtio32(vi->vdev, mc_count);
> i = 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(dev, ha_addr, idx)
> + memcpy(&mac_data->macs[i++][0], ha_addr, ETH_ALEN);
>
> sg_set_buf(&sg[1], mac_data,
> sizeof(mac_data->entries) + (mc_count * ETH_ALEN));
> @@ -3950,17 +3939,15 @@ 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");
>
> - rtnl_unlock();
> -
> kfree(buf);
> }
>
> static void virtnet_set_rx_mode(struct net_device *dev)
> {
> struct virtnet_info *vi = netdev_priv(dev);
> + char cfg_disabled = !vi->rx_mode_work_enabled;
>
> - if (vi->rx_mode_work_enabled)
> - schedule_work(&vi->rx_mode_work);
> + netif_rx_mode_set_flag(dev, NETIF_RX_MODE_SET_SKIP, cfg_disabled);
> }
>
> static int virtnet_vlan_rx_add_vid(struct net_device *dev,
> @@ -5776,7 +5763,7 @@ static void virtnet_freeze_down(struct virtio_device *vdev)
> /* 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);
> + netif_flush_rx_mode_work(vi->dev);
>
> if (netif_running(vi->dev)) {
> rtnl_lock();
> @@ -6279,6 +6266,7 @@ static const struct net_device_ops virtnet_netdev = {
> .ndo_validate_addr = eth_validate_addr,
> .ndo_set_mac_address = virtnet_set_mac_address,
> .ndo_set_rx_mode = virtnet_set_rx_mode,
> + .ndo_write_rx_mode = virtnet_write_rx_mode,
> .ndo_get_stats64 = virtnet_stats,
> .ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid,
> .ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid,
> @@ -6900,7 +6888,6 @@ static int virtnet_probe(struct virtio_device *vdev)
> vdev->priv = vi;
>
> INIT_WORK(&vi->config_work, virtnet_config_changed_work);
> - INIT_WORK(&vi->rx_mode_work, virtnet_rx_mode_work);
> spin_lock_init(&vi->refill_lock);
>
> if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) {
> @@ -7205,7 +7192,7 @@ static void virtnet_remove(struct virtio_device *vdev)
> /* 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);
> + netif_flush_rx_mode_work(vi->dev);
>
> virtnet_free_irq_moder(vi);
>
> --
> 2.47.3
>
next prev parent reply other threads:[~2026-01-06 11:24 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-02 18:05 [PATCH net-next v7 0/2] net: Split ndo_set_rx_mode into snapshot and deferred write I Viswanath
2026-01-02 18:05 ` [PATCH net-next v7 1/2] net: refactor set_rx_mode into snapshot and deferred I/O I Viswanath
2026-01-06 10:28 ` I Viswanath
2026-01-02 18:05 ` [PATCH net-next v7 2/2] virtio-net: Implement ndo_write_rx_mode callback I Viswanath
2026-01-06 11:22 ` Xuan Zhuo [this message]
2026-01-07 6:12 ` I Viswanath
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1767698557.9158366-1-xuanzhuo@linux.alibaba.com \
--to=xuanzhuo@linux.alibaba.com \
--cc=andrew+netdev@lunn.ch \
--cc=edumazet@google.com \
--cc=eperezma@redhat.com \
--cc=horms@kernel.org \
--cc=jasowang@redhat.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mst@redhat.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=virtualization@lists.linux.dev \
--cc=viswanathiyyappan@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.