diff options
author | Wanlong Gao <gaowanlong@cn.fujitsu.com> | 2013-04-08 09:35:49 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2013-04-08 09:36:56 -0400 |
commit | 285e71ea6f3583a85e27cb2b9a7d8c35d4c0d558 (patch) | |
tree | 16c15b5d499c91f6e18bf4ca2e6953813ded6d14 /drivers/scsi/virtio_scsi.c | |
parent | 9141a4ca0d9551729573042660e9bce83a01e0af (diff) |
virtio-scsi: reset virtqueue affinity when doing cpu hotplug
Add hot cpu notifier to reset the request virtqueue affinity
when doing cpu hotplug.
Cc: linux-scsi@vger.kernel.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Wanlong Gao <gaowanlong@cn.fujitsu.com>
Reviewed-by: Asias He <asias@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/scsi/virtio_scsi.c')
-rw-r--r-- | drivers/scsi/virtio_scsi.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 8dcdef0783db..2168258fb2c3 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c | |||
@@ -110,6 +110,9 @@ struct virtio_scsi { | |||
110 | /* If the affinity hint is set for virtqueues */ | 110 | /* If the affinity hint is set for virtqueues */ |
111 | bool affinity_hint_set; | 111 | bool affinity_hint_set; |
112 | 112 | ||
113 | /* CPU hotplug notifier */ | ||
114 | struct notifier_block nb; | ||
115 | |||
113 | struct virtio_scsi_vq ctrl_vq; | 116 | struct virtio_scsi_vq ctrl_vq; |
114 | struct virtio_scsi_vq event_vq; | 117 | struct virtio_scsi_vq event_vq; |
115 | struct virtio_scsi_vq req_vqs[]; | 118 | struct virtio_scsi_vq req_vqs[]; |
@@ -762,6 +765,23 @@ static void virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity) | |||
762 | put_online_cpus(); | 765 | put_online_cpus(); |
763 | } | 766 | } |
764 | 767 | ||
768 | static int virtscsi_cpu_callback(struct notifier_block *nfb, | ||
769 | unsigned long action, void *hcpu) | ||
770 | { | ||
771 | struct virtio_scsi *vscsi = container_of(nfb, struct virtio_scsi, nb); | ||
772 | switch(action) { | ||
773 | case CPU_ONLINE: | ||
774 | case CPU_ONLINE_FROZEN: | ||
775 | case CPU_DEAD: | ||
776 | case CPU_DEAD_FROZEN: | ||
777 | __virtscsi_set_affinity(vscsi, true); | ||
778 | break; | ||
779 | default: | ||
780 | break; | ||
781 | } | ||
782 | return NOTIFY_OK; | ||
783 | } | ||
784 | |||
765 | static void virtscsi_init_vq(struct virtio_scsi_vq *virtscsi_vq, | 785 | static void virtscsi_init_vq(struct virtio_scsi_vq *virtscsi_vq, |
766 | struct virtqueue *vq) | 786 | struct virtqueue *vq) |
767 | { | 787 | { |
@@ -884,6 +904,13 @@ static int virtscsi_probe(struct virtio_device *vdev) | |||
884 | if (err) | 904 | if (err) |
885 | goto virtscsi_init_failed; | 905 | goto virtscsi_init_failed; |
886 | 906 | ||
907 | vscsi->nb.notifier_call = &virtscsi_cpu_callback; | ||
908 | err = register_hotcpu_notifier(&vscsi->nb); | ||
909 | if (err) { | ||
910 | pr_err("registering cpu notifier failed\n"); | ||
911 | goto scsi_add_host_failed; | ||
912 | } | ||
913 | |||
887 | cmd_per_lun = virtscsi_config_get(vdev, cmd_per_lun) ?: 1; | 914 | cmd_per_lun = virtscsi_config_get(vdev, cmd_per_lun) ?: 1; |
888 | shost->cmd_per_lun = min_t(u32, cmd_per_lun, shost->can_queue); | 915 | shost->cmd_per_lun = min_t(u32, cmd_per_lun, shost->can_queue); |
889 | shost->max_sectors = virtscsi_config_get(vdev, max_sectors) ?: 0xFFFF; | 916 | shost->max_sectors = virtscsi_config_get(vdev, max_sectors) ?: 0xFFFF; |
@@ -921,6 +948,8 @@ static void virtscsi_remove(struct virtio_device *vdev) | |||
921 | 948 | ||
922 | scsi_remove_host(shost); | 949 | scsi_remove_host(shost); |
923 | 950 | ||
951 | unregister_hotcpu_notifier(&vscsi->nb); | ||
952 | |||
924 | virtscsi_remove_vqs(vdev); | 953 | virtscsi_remove_vqs(vdev); |
925 | scsi_host_put(shost); | 954 | scsi_host_put(shost); |
926 | } | 955 | } |