From patchwork Mon Jan 21 11:25:24 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [V6,3/3] virtio-net: reset virtqueue affinity when doing cpu hotplug Date: Mon, 21 Jan 2013 01:25:24 -0000 From: Wanlong Gao X-Patchwork-Id: 214096 Message-Id: <1358767524-17934-3-git-send-email-gaowanlong@cn.fujitsu.com> To: linux-kernel@vger.kernel.org Cc: Rusty Russell , "Michael S. Tsirkin" , Jason Wang , Eric Dumazet , virtualization@lists.linux-foundation.org, netdev@vger.kernel.org, Wanlong Gao Add a cpu notifier to virtio-net, so that we can reset the virtqueue affinity if the cpu hotplug happens. It improve the performance through enabling or disabling the virtqueue affinity after doing cpu hotplug. Cc: Rusty Russell Cc: "Michael S. Tsirkin" Cc: Jason Wang Cc: Eric Dumazet Cc: virtualization@lists.linux-foundation.org Cc: netdev@vger.kernel.org Signed-off-by: Wanlong Gao --- V5->V6: deal with CPU_DOWN_PREPARE separately by just cleaning affinity V4->V5: New method to deal with the cpu hotplug actions (Rusty) drivers/net/virtio_net.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 1a35a8c..1d93999 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -26,6 +26,7 @@ #include #include #include +#include static int napi_weight = 128; module_param(napi_weight, int, 0444); @@ -126,6 +127,9 @@ struct virtnet_info { /* Per-cpu variable to show the mapping from CPU to virtqueue */ int __percpu *vq_index; + + /* CPU hot plug notifier */ + struct notifier_block nb; }; struct skb_vnet_hdr { @@ -1067,6 +1071,26 @@ static void virtnet_set_affinity(struct virtnet_info *vi) vi->affinity_hint_set = true; } +static int virtnet_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + struct virtnet_info *vi = container_of(nfb, struct virtnet_info, nb); + + switch(action & ~CPU_TASKS_FROZEN) { + case CPU_ONLINE: + case CPU_DOWN_FAILED: + case CPU_DEAD: + virtnet_set_affinity(vi); + break; + case CPU_DOWN_PREPARE: + virtnet_clean_affinity(vi, (long)hcpu); + break; + default: + break; + } + return NOTIFY_OK; +} + static void virtnet_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring) { @@ -1541,6 +1565,13 @@ static int virtnet_probe(struct virtio_device *vdev) } } + vi->nb.notifier_call = &virtnet_cpu_callback; + err = register_hotcpu_notifier(&vi->nb); + if (err) { + pr_debug("virtio_net: registering cpu notifier failed\n"); + goto free_recv_bufs; + } + /* Assume link up if device can't report link status, otherwise get link status from config. */ if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) { @@ -1587,6 +1618,8 @@ static void virtnet_remove(struct virtio_device *vdev) { struct virtnet_info *vi = vdev->priv; + unregister_hotcpu_notifier(&vi->nb); + /* Prevent config work handler from accessing the device. */ mutex_lock(&vi->config_lock); vi->config_enable = false;