Skip to content

Commit 42f22fe

Browse files
John Garrymartinkpetersen
authored andcommitted
scsi: pm8001: Expose hardware queues for pm80xx
In commit 05c6c02 ("scsi: pm80xx: Increase number of supported queues"), support for 80xx chip was improved by enabling multiple HW queues. In this, like other SCSI MQ HBA drivers at the time, the HW queues were not exposed to upper layer, and instead the driver managed the queues internally. However, this management duplicates blk-mq code. In addition, the HW queue management is sub-optimal for a system where the number of CPUs exceeds the HW queues - this is because queues are selected in a round-robin fashion, when it would be better to make adjacent CPUs submit on the same queue. And finally, the affinity of the completion queue interrupts is not set to mirror the cpu<->HQ queue mapping, which is suboptimal. As such, for when MSIX is supported, expose HW queues to upper layer. We always use queue index #0 for "internal" commands, i.e. anything which does not come from the block layer, so omit this from the affinity spreading. Link: https://lore.kernel.org/r/1654879602-33497-5-git-send-email-john.garry@huawei.com Tested-by: Damien Le Moal <damien.lemoal@opensource.wdc.com> Signed-off-by: John Garry <john.garry@huawei.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 940f5ef commit 42f22fe

File tree

3 files changed

+69
-18
lines changed

3 files changed

+69
-18
lines changed

drivers/scsi/pm8001/pm8001_init.c

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,18 @@ LIST_HEAD(hba_list);
8181

8282
struct workqueue_struct *pm8001_wq;
8383

84+
static int pm8001_map_queues(struct Scsi_Host *shost)
85+
{
86+
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
87+
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
88+
struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT];
89+
90+
if (pm8001_ha->number_of_intr > 1)
91+
blk_mq_pci_map_queues(qmap, pm8001_ha->pdev, 1);
92+
93+
return blk_mq_map_queues(qmap);
94+
}
95+
8496
/*
8597
* The main structure which LLDD must register for scsi core.
8698
*/
@@ -110,6 +122,7 @@ static struct scsi_host_template pm8001_sht = {
110122
.shost_groups = pm8001_host_groups,
111123
.track_queue_depth = 1,
112124
.cmd_per_lun = 32,
125+
.map_queues = pm8001_map_queues,
113126
};
114127

115128
/*
@@ -928,31 +941,35 @@ static int pm8001_configure_phy_settings(struct pm8001_hba_info *pm8001_ha)
928941
*/
929942
static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
930943
{
931-
u32 number_of_intr;
932-
int rc, cpu_online_count;
933944
unsigned int allocated_irq_vectors;
945+
int rc;
934946

935947
/* SPCv controllers supports 64 msi-x */
936948
if (pm8001_ha->chip_id == chip_8001) {
937-
number_of_intr = 1;
949+
rc = pci_alloc_irq_vectors(pm8001_ha->pdev, 1, 1,
950+
PCI_IRQ_MSIX);
938951
} else {
939-
number_of_intr = PM8001_MAX_MSIX_VEC;
952+
/*
953+
* Queue index #0 is used always for housekeeping, so don't
954+
* include in the affinity spreading.
955+
*/
956+
struct irq_affinity desc = {
957+
.pre_vectors = 1,
958+
};
959+
rc = pci_alloc_irq_vectors_affinity(
960+
pm8001_ha->pdev, 2, PM8001_MAX_MSIX_VEC,
961+
PCI_IRQ_MSIX | PCI_IRQ_AFFINITY, &desc);
940962
}
941963

942-
cpu_online_count = num_online_cpus();
943-
number_of_intr = min_t(int, cpu_online_count, number_of_intr);
944-
rc = pci_alloc_irq_vectors(pm8001_ha->pdev, number_of_intr,
945-
number_of_intr, PCI_IRQ_MSIX);
946964
allocated_irq_vectors = rc;
947965
if (rc < 0)
948966
return rc;
949967

950968
/* Assigns the number of interrupts */
951-
number_of_intr = min_t(int, allocated_irq_vectors, number_of_intr);
952-
pm8001_ha->number_of_intr = number_of_intr;
969+
pm8001_ha->number_of_intr = allocated_irq_vectors;
953970

954971
/* Maximum queue number updating in HBA structure */
955-
pm8001_ha->max_q_num = number_of_intr;
972+
pm8001_ha->max_q_num = allocated_irq_vectors;
956973

957974
pm8001_dbg(pm8001_ha, INIT,
958975
"pci_alloc_irq_vectors request ret:%d no of intr %d\n",
@@ -1123,8 +1140,19 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
11231140
if (rc)
11241141
goto err_out_enable;
11251142

1143+
11261144
PM8001_CHIP_DISP->chip_post_init(pm8001_ha);
11271145

1146+
if (pm8001_ha->number_of_intr > 1) {
1147+
shost->nr_hw_queues = pm8001_ha->number_of_intr - 1;
1148+
/*
1149+
* For now, ensure we're not sent too many commands by setting
1150+
* host_tagset. This is also required if we start using request
1151+
* tag.
1152+
*/
1153+
shost->host_tagset = 1;
1154+
}
1155+
11281156
rc = scsi_add_host(shost, &pdev->dev);
11291157
if (rc)
11301158
goto err_out_ha_free;

drivers/scsi/pm8001/pm8001_sas.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@
5555
#include <scsi/scsi_tcq.h>
5656
#include <scsi/sas_ata.h>
5757
#include <linux/atomic.h>
58+
#include <linux/blk-mq.h>
59+
#include <linux/blk-mq-pci.h>
5860
#include "pm8001_defs.h"
5961

6062
#define DRV_NAME "pm80xx"

drivers/scsi/pm8001/pm80xx_hwi.c

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4351,6 +4351,29 @@ static int check_enc_sat_cmd(struct sas_task *task)
43514351
return ret;
43524352
}
43534353

4354+
static u32 pm80xx_chip_get_q_index(struct sas_task *task)
4355+
{
4356+
struct scsi_cmnd *scmd = NULL;
4357+
u32 blk_tag;
4358+
4359+
if (task->uldd_task) {
4360+
struct ata_queued_cmd *qc;
4361+
4362+
if (dev_is_sata(task->dev)) {
4363+
qc = task->uldd_task;
4364+
scmd = qc->scsicmd;
4365+
} else {
4366+
scmd = task->uldd_task;
4367+
}
4368+
}
4369+
4370+
if (!scmd)
4371+
return 0;
4372+
4373+
blk_tag = blk_mq_unique_tag(scsi_cmd_to_rq(scmd));
4374+
return blk_mq_unique_tag_to_hwq(blk_tag);
4375+
}
4376+
43544377
/**
43554378
* pm80xx_chip_ssp_io_req - send an SSP task to FW
43564379
* @pm8001_ha: our hba card information.
@@ -4366,7 +4389,7 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
43664389
u32 tag = ccb->ccb_tag;
43674390
u64 phys_addr, end_addr;
43684391
u32 end_addr_high, end_addr_low;
4369-
u32 q_index, cpu_id;
4392+
u32 q_index;
43704393
u32 opc = OPC_INB_SSPINIIOSTART;
43714394

43724395
memset(&ssp_cmd, 0, sizeof(ssp_cmd));
@@ -4387,8 +4410,7 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
43874410
ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7);
43884411
memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cmd->cmnd,
43894412
task->ssp_task.cmd->cmd_len);
4390-
cpu_id = smp_processor_id();
4391-
q_index = (u32) (cpu_id) % (pm8001_ha->max_q_num);
4413+
q_index = pm80xx_chip_get_q_index(task);
43924414

43934415
/* Check if encryption is set */
43944416
if (pm8001_ha->chip->encrypt &&
@@ -4517,8 +4539,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
45174539
struct domain_device *dev = task->dev;
45184540
struct pm8001_device *pm8001_ha_dev = dev->lldd_dev;
45194541
struct ata_queued_cmd *qc = task->uldd_task;
4520-
u32 tag = ccb->ccb_tag;
4521-
u32 q_index, cpu_id;
4542+
u32 tag = ccb->ccb_tag, q_index;
45224543
struct sata_start_req sata_cmd;
45234544
u32 hdr_tag, ncg_tag = 0;
45244545
u64 phys_addr, end_addr;
@@ -4528,8 +4549,8 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
45284549
unsigned long flags;
45294550
u32 opc = OPC_INB_SATA_HOST_OPSTART;
45304551
memset(&sata_cmd, 0, sizeof(sata_cmd));
4531-
cpu_id = smp_processor_id();
4532-
q_index = (u32) (cpu_id) % (pm8001_ha->max_q_num);
4552+
4553+
q_index = pm80xx_chip_get_q_index(task);
45334554

45344555
if (task->data_dir == DMA_NONE && !task->ata_task.use_ncq) {
45354556
ATAP = 0x04; /* no data*/

0 commit comments

Comments
 (0)