Skip to content

Commit 0d9f0a5

Browse files
Christoph Hellwigmstsirkin
authored andcommitted
virtio_scsi: use virtio IRQ affinity
Use automatic IRQ affinity assignment in the virtio layer if available, and build the blk-mq queues based on it. Signed-off-by: Christoph Hellwig <[email protected]> Signed-off-by: Michael S. Tsirkin <[email protected]>
1 parent ad71473 commit 0d9f0a5

File tree

2 files changed

+12
-115
lines changed

2 files changed

+12
-115
lines changed

drivers/scsi/virtio_scsi.c

Lines changed: 12 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/module.h>
1919
#include <linux/slab.h>
2020
#include <linux/mempool.h>
21+
#include <linux/interrupt.h>
2122
#include <linux/virtio.h>
2223
#include <linux/virtio_ids.h>
2324
#include <linux/virtio_config.h>
@@ -29,6 +30,7 @@
2930
#include <scsi/scsi_cmnd.h>
3031
#include <scsi/scsi_tcq.h>
3132
#include <linux/seqlock.h>
33+
#include <linux/blk-mq-virtio.h>
3234

3335
#define VIRTIO_SCSI_MEMPOOL_SZ 64
3436
#define VIRTIO_SCSI_EVENT_LEN 8
@@ -108,7 +110,6 @@ struct virtio_scsi {
108110
bool affinity_hint_set;
109111

110112
struct hlist_node node;
111-
struct hlist_node node_dead;
112113

113114
/* Protected by event_vq lock */
114115
bool stop_events;
@@ -118,7 +119,6 @@ struct virtio_scsi {
118119
struct virtio_scsi_vq req_vqs[];
119120
};
120121

121-
static enum cpuhp_state virtioscsi_online;
122122
static struct kmem_cache *virtscsi_cmd_cache;
123123
static mempool_t *virtscsi_cmd_pool;
124124

@@ -766,6 +766,13 @@ static void virtscsi_target_destroy(struct scsi_target *starget)
766766
kfree(tgt);
767767
}
768768

769+
static int virtscsi_map_queues(struct Scsi_Host *shost)
770+
{
771+
struct virtio_scsi *vscsi = shost_priv(shost);
772+
773+
return blk_mq_virtio_map_queues(&shost->tag_set, vscsi->vdev, 2);
774+
}
775+
769776
static struct scsi_host_template virtscsi_host_template_single = {
770777
.module = THIS_MODULE,
771778
.name = "Virtio SCSI HBA",
@@ -801,6 +808,7 @@ static struct scsi_host_template virtscsi_host_template_multi = {
801808
.use_clustering = ENABLE_CLUSTERING,
802809
.target_alloc = virtscsi_target_alloc,
803810
.target_destroy = virtscsi_target_destroy,
811+
.map_queues = virtscsi_map_queues,
804812
.track_queue_depth = 1,
805813
};
806814

@@ -817,80 +825,6 @@ static struct scsi_host_template virtscsi_host_template_multi = {
817825
virtio_cwrite(vdev, struct virtio_scsi_config, fld, &__val); \
818826
} while(0)
819827

820-
static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity)
821-
{
822-
int i;
823-
int cpu;
824-
825-
/* In multiqueue mode, when the number of cpu is equal
826-
* to the number of request queues, we let the qeueues
827-
* to be private to one cpu by setting the affinity hint
828-
* to eliminate the contention.
829-
*/
830-
if ((vscsi->num_queues == 1 ||
831-
vscsi->num_queues != num_online_cpus()) && affinity) {
832-
if (vscsi->affinity_hint_set)
833-
affinity = false;
834-
else
835-
return;
836-
}
837-
838-
if (affinity) {
839-
i = 0;
840-
for_each_online_cpu(cpu) {
841-
virtqueue_set_affinity(vscsi->req_vqs[i].vq, cpu);
842-
i++;
843-
}
844-
845-
vscsi->affinity_hint_set = true;
846-
} else {
847-
for (i = 0; i < vscsi->num_queues; i++) {
848-
if (!vscsi->req_vqs[i].vq)
849-
continue;
850-
851-
virtqueue_set_affinity(vscsi->req_vqs[i].vq, -1);
852-
}
853-
854-
vscsi->affinity_hint_set = false;
855-
}
856-
}
857-
858-
static void virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity)
859-
{
860-
get_online_cpus();
861-
__virtscsi_set_affinity(vscsi, affinity);
862-
put_online_cpus();
863-
}
864-
865-
static int virtscsi_cpu_online(unsigned int cpu, struct hlist_node *node)
866-
{
867-
struct virtio_scsi *vscsi = hlist_entry_safe(node, struct virtio_scsi,
868-
node);
869-
__virtscsi_set_affinity(vscsi, true);
870-
return 0;
871-
}
872-
873-
static int virtscsi_cpu_notif_add(struct virtio_scsi *vi)
874-
{
875-
int ret;
876-
877-
ret = cpuhp_state_add_instance(virtioscsi_online, &vi->node);
878-
if (ret)
879-
return ret;
880-
881-
ret = cpuhp_state_add_instance(CPUHP_VIRT_SCSI_DEAD, &vi->node_dead);
882-
if (ret)
883-
cpuhp_state_remove_instance(virtioscsi_online, &vi->node);
884-
return ret;
885-
}
886-
887-
static void virtscsi_cpu_notif_remove(struct virtio_scsi *vi)
888-
{
889-
cpuhp_state_remove_instance_nocalls(virtioscsi_online, &vi->node);
890-
cpuhp_state_remove_instance_nocalls(CPUHP_VIRT_SCSI_DEAD,
891-
&vi->node_dead);
892-
}
893-
894828
static void virtscsi_init_vq(struct virtio_scsi_vq *virtscsi_vq,
895829
struct virtqueue *vq)
896830
{
@@ -900,14 +834,8 @@ static void virtscsi_init_vq(struct virtio_scsi_vq *virtscsi_vq,
900834

901835
static void virtscsi_remove_vqs(struct virtio_device *vdev)
902836
{
903-
struct Scsi_Host *sh = virtio_scsi_host(vdev);
904-
struct virtio_scsi *vscsi = shost_priv(sh);
905-
906-
virtscsi_set_affinity(vscsi, false);
907-
908837
/* Stop all the virtqueues. */
909838
vdev->config->reset(vdev);
910-
911839
vdev->config->del_vqs(vdev);
912840
}
913841

@@ -920,6 +848,7 @@ static int virtscsi_init(struct virtio_device *vdev,
920848
vq_callback_t **callbacks;
921849
const char **names;
922850
struct virtqueue **vqs;
851+
struct irq_affinity desc = { .pre_vectors = 2 };
923852

924853
num_vqs = vscsi->num_queues + VIRTIO_SCSI_VQ_BASE;
925854
vqs = kmalloc(num_vqs * sizeof(struct virtqueue *), GFP_KERNEL);
@@ -942,7 +871,7 @@ static int virtscsi_init(struct virtio_device *vdev,
942871

943872
/* Discover virtqueues and write information to configuration. */
944873
err = vdev->config->find_vqs(vdev, num_vqs, vqs, callbacks, names,
945-
NULL);
874+
&desc);
946875
if (err)
947876
goto out;
948877

@@ -1008,10 +937,6 @@ static int virtscsi_probe(struct virtio_device *vdev)
1008937
if (err)
1009938
goto virtscsi_init_failed;
1010939

1011-
err = virtscsi_cpu_notif_add(vscsi);
1012-
if (err)
1013-
goto scsi_add_host_failed;
1014-
1015940
cmd_per_lun = virtscsi_config_get(vdev, cmd_per_lun) ?: 1;
1016941
shost->cmd_per_lun = min_t(u32, cmd_per_lun, shost->can_queue);
1017942
shost->max_sectors = virtscsi_config_get(vdev, max_sectors) ?: 0xFFFF;
@@ -1066,20 +991,13 @@ static void virtscsi_remove(struct virtio_device *vdev)
1066991
virtscsi_cancel_event_work(vscsi);
1067992

1068993
scsi_remove_host(shost);
1069-
1070-
virtscsi_cpu_notif_remove(vscsi);
1071-
1072994
virtscsi_remove_vqs(vdev);
1073995
scsi_host_put(shost);
1074996
}
1075997

1076998
#ifdef CONFIG_PM_SLEEP
1077999
static int virtscsi_freeze(struct virtio_device *vdev)
10781000
{
1079-
struct Scsi_Host *sh = virtio_scsi_host(vdev);
1080-
struct virtio_scsi *vscsi = shost_priv(sh);
1081-
1082-
virtscsi_cpu_notif_remove(vscsi);
10831001
virtscsi_remove_vqs(vdev);
10841002
return 0;
10851003
}
@@ -1094,11 +1012,6 @@ static int virtscsi_restore(struct virtio_device *vdev)
10941012
if (err)
10951013
return err;
10961014

1097-
err = virtscsi_cpu_notif_add(vscsi);
1098-
if (err) {
1099-
vdev->config->del_vqs(vdev);
1100-
return err;
1101-
}
11021015
virtio_device_ready(vdev);
11031016

11041017
if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG))
@@ -1153,16 +1066,6 @@ static int __init init(void)
11531066
pr_err("mempool_create() for virtscsi_cmd_pool failed\n");
11541067
goto error;
11551068
}
1156-
ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
1157-
"scsi/virtio:online",
1158-
virtscsi_cpu_online, NULL);
1159-
if (ret < 0)
1160-
goto error;
1161-
virtioscsi_online = ret;
1162-
ret = cpuhp_setup_state_multi(CPUHP_VIRT_SCSI_DEAD, "scsi/virtio:dead",
1163-
NULL, virtscsi_cpu_online);
1164-
if (ret)
1165-
goto error;
11661069
ret = register_virtio_driver(&virtio_scsi_driver);
11671070
if (ret < 0)
11681071
goto error;
@@ -1178,17 +1081,12 @@ static int __init init(void)
11781081
kmem_cache_destroy(virtscsi_cmd_cache);
11791082
virtscsi_cmd_cache = NULL;
11801083
}
1181-
if (virtioscsi_online)
1182-
cpuhp_remove_multi_state(virtioscsi_online);
1183-
cpuhp_remove_multi_state(CPUHP_VIRT_SCSI_DEAD);
11841084
return ret;
11851085
}
11861086

11871087
static void __exit fini(void)
11881088
{
11891089
unregister_virtio_driver(&virtio_scsi_driver);
1190-
cpuhp_remove_multi_state(virtioscsi_online);
1191-
cpuhp_remove_multi_state(CPUHP_VIRT_SCSI_DEAD);
11921090
mempool_destroy(virtscsi_cmd_pool);
11931091
kmem_cache_destroy(virtscsi_cmd_cache);
11941092
}

include/linux/cpuhotplug.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ enum cpuhp_state {
2626
CPUHP_ARM_OMAP_WAKE_DEAD,
2727
CPUHP_IRQ_POLL_DEAD,
2828
CPUHP_BLOCK_SOFTIRQ_DEAD,
29-
CPUHP_VIRT_SCSI_DEAD,
3029
CPUHP_ACPI_CPUDRV_DEAD,
3130
CPUHP_S390_PFAULT_DEAD,
3231
CPUHP_BLK_MQ_DEAD,

0 commit comments

Comments
 (0)