scsi: hisi_sas: Select a suitable queue for internal I/Os
authorXiang Chen <chenxiang66@hisilicon.com>
Mon, 7 Dec 2020 13:30:55 +0000 (21:30 +0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 8 Dec 2020 02:23:51 +0000 (21:23 -0500)
For when managed interrupts are used (and shost->nr_hw_queues is set), a
fixed queue - set per-device - is still used for internal I/Os.

If all the CPUs mapped to that queue are offlined, then the completions for
that queue are not serviced and any internal I/Os will time out.

Fix by selecting a queue for internal I/Os from the queue mapped from the
current CPU in this scenario.

This is still not ideal as it does not deal with CPU hotplug for inflight
internal I/Os, and needs proper support from [0].

[0] https://lore.kernel.org/linux-scsi/20200703130122.111448-1-hare@suse.de/T/#m7d77d049b18f33a24ef206af69ebb66d07440556

Link: https://lore.kernel.org/r/1607347855-59091-1-git-send-email-john.garry@huawei.com
Fixes: 8d98416a55eb ("scsi: hisi_sas: Switch v3 hw to MQ")
Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
Signed-off-by: John Garry <john.garry@huawei.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/hisi_sas/hisi_sas_main.c
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c

index c8dd858..274ccf1 100644 (file)
@@ -452,6 +452,12 @@ static int hisi_sas_task_prep(struct sas_task *task,
                blk_tag = blk_mq_unique_tag(scmd->request);
                dq_index = blk_mq_unique_tag_to_hwq(blk_tag);
                *dq_pointer = dq = &hisi_hba->dq[dq_index];
+       } else if (hisi_hba->shost->nr_hw_queues)  {
+               struct Scsi_Host *shost = hisi_hba->shost;
+               struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT];
+               int queue = qmap->mq_map[raw_smp_processor_id()];
+
+               *dq_pointer = dq = &hisi_hba->dq[queue];
        } else {
                *dq_pointer = dq = sas_dev->dq;
        }
index 7133ca8..960de37 100644 (file)
@@ -2452,6 +2452,11 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba)
                        rc = -ENOENT;
                        goto free_irq_vectors;
                }
+               cq->irq_mask = pci_irq_get_affinity(pdev, i + BASE_VECTORS_V3_HW);
+               if (!cq->irq_mask) {
+                       dev_err(dev, "could not get cq%d irq affinity!\n", i);
+                       return -ENOENT;
+               }
        }
 
        return 0;