scsi: hisi_sas: Select a suitable queue for internal I/Os

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>

authored by Xiang Chen and committed by Martin K. Petersen 359db633 673235f9

Changed files
+11
drivers
+6
drivers/scsi/hisi_sas/hisi_sas_main.c
··· 452 452 blk_tag = blk_mq_unique_tag(scmd->request); 453 453 dq_index = blk_mq_unique_tag_to_hwq(blk_tag); 454 454 *dq_pointer = dq = &hisi_hba->dq[dq_index]; 455 + } else if (hisi_hba->shost->nr_hw_queues) { 456 + struct Scsi_Host *shost = hisi_hba->shost; 457 + struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT]; 458 + int queue = qmap->mq_map[raw_smp_processor_id()]; 459 + 460 + *dq_pointer = dq = &hisi_hba->dq[queue]; 455 461 } else { 456 462 *dq_pointer = dq = sas_dev->dq; 457 463 }
+5
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
··· 2452 2452 rc = -ENOENT; 2453 2453 goto free_irq_vectors; 2454 2454 } 2455 + cq->irq_mask = pci_irq_get_affinity(pdev, i + BASE_VECTORS_V3_HW); 2456 + if (!cq->irq_mask) { 2457 + dev_err(dev, "could not get cq%d irq affinity!\n", i); 2458 + return -ENOENT; 2459 + } 2455 2460 } 2456 2461 2457 2462 return 0;