Skip to content

Commit 74a2921

Browse files
John Garrymartinkpetersen
authored andcommitted
scsi: hisi_sas: Expose HW queues for v2 hw
As a performance enhancement, make the completion queue interrupts managed. In addition, in commit bf0beec ("blk-mq: drain I/O when all CPUs in a hctx are offline"), CPU hotplug for MQ devices using managed interrupts is made safe. So expose HW queues to blk-mq to take advantage of this. Flag Scsi_host.host_tagset is also set to ensure that the HBA is not sent more commands than it can handle. However the driver still does not use request tag for IPTT as there are many HW bugs means that special rules apply for IPTT allocation. Link: https://lore.kernel.org/r/1606905417-183214-6-git-send-email-john.garry@huawei.com Signed-off-by: John Garry <john.garry@huawei.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 81e7eb5 commit 74a2921

File tree

3 files changed

+68
-13
lines changed

3 files changed

+68
-13
lines changed

drivers/scsi/hisi_sas/hisi_sas.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/debugfs.h>
1515
#include <linux/dmapool.h>
1616
#include <linux/iopoll.h>
17+
#include <linux/irq.h>
1718
#include <linux/lcm.h>
1819
#include <linux/libata.h>
1920
#include <linux/mfd/syscon.h>
@@ -312,6 +313,7 @@ enum {
312313

313314
struct hisi_sas_hw {
314315
int (*hw_init)(struct hisi_hba *hisi_hba);
316+
int (*interrupt_preinit)(struct hisi_hba *hisi_hba);
315317
void (*setup_itct)(struct hisi_hba *hisi_hba,
316318
struct hisi_sas_device *device);
317319
int (*slot_index_alloc)(struct hisi_hba *hisi_hba,
@@ -418,6 +420,8 @@ struct hisi_hba {
418420
u32 refclk_frequency_mhz;
419421
u8 sas_addr[SAS_ADDR_SIZE];
420422

423+
int *irq_map; /* v2 hw */
424+
421425
int n_phy;
422426
spinlock_t lock;
423427
struct semaphore sem;

drivers/scsi/hisi_sas/hisi_sas_main.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2620,6 +2620,13 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
26202620
return NULL;
26212621
}
26222622

2623+
static int hisi_sas_interrupt_preinit(struct hisi_hba *hisi_hba)
2624+
{
2625+
if (hisi_hba->hw->interrupt_preinit)
2626+
return hisi_hba->hw->interrupt_preinit(hisi_hba);
2627+
return 0;
2628+
}
2629+
26232630
int hisi_sas_probe(struct platform_device *pdev,
26242631
const struct hisi_sas_hw *hw)
26252632
{
@@ -2677,6 +2684,10 @@ int hisi_sas_probe(struct platform_device *pdev,
26772684
sha->sas_port[i] = &hisi_hba->port[i].sas_port;
26782685
}
26792686

2687+
rc = hisi_sas_interrupt_preinit(hisi_hba);
2688+
if (rc)
2689+
goto err_out_ha;
2690+
26802691
rc = scsi_add_host(shost, &pdev->dev);
26812692
if (rc)
26822693
goto err_out_ha;

drivers/scsi/hisi_sas/hisi_sas_v2_hw.c

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3302,6 +3302,28 @@ static irq_handler_t fatal_interrupts[HISI_SAS_FATAL_INT_NR] = {
33023302
fatal_axi_int_v2_hw
33033303
};
33043304

3305+
#define CQ0_IRQ_INDEX (96)
3306+
3307+
static int hisi_sas_v2_interrupt_preinit(struct hisi_hba *hisi_hba)
3308+
{
3309+
struct platform_device *pdev = hisi_hba->platform_dev;
3310+
struct Scsi_Host *shost = hisi_hba->shost;
3311+
struct irq_affinity desc = {
3312+
.pre_vectors = CQ0_IRQ_INDEX,
3313+
.post_vectors = 16,
3314+
};
3315+
int resv = desc.pre_vectors + desc.post_vectors, minvec = resv + 1, nvec;
3316+
3317+
nvec = devm_platform_get_irqs_affinity(pdev, &desc, minvec, 128,
3318+
&hisi_hba->irq_map);
3319+
if (nvec < 0)
3320+
return nvec;
3321+
3322+
shost->nr_hw_queues = hisi_hba->cq_nvecs = nvec - resv;
3323+
3324+
return 0;
3325+
}
3326+
33053327
/*
33063328
* There is a limitation in the hip06 chipset that we need
33073329
* to map in all mbigen interrupts, even if they are not used.
@@ -3310,14 +3332,11 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
33103332
{
33113333
struct platform_device *pdev = hisi_hba->platform_dev;
33123334
struct device *dev = &pdev->dev;
3313-
int irq, rc = 0, irq_map[128];
3335+
int irq, rc = 0;
33143336
int i, phy_no, fatal_no, queue_no;
33153337

3316-
for (i = 0; i < 128; i++)
3317-
irq_map[i] = platform_get_irq(pdev, i);
3318-
33193338
for (i = 0; i < HISI_SAS_PHY_INT_NR; i++) {
3320-
irq = irq_map[i + 1]; /* Phy up/down is irq1 */
3339+
irq = hisi_hba->irq_map[i + 1]; /* Phy up/down is irq1 */
33213340
rc = devm_request_irq(dev, irq, phy_interrupts[i], 0,
33223341
DRV_NAME " phy", hisi_hba);
33233342
if (rc) {
@@ -3331,7 +3350,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
33313350
for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) {
33323351
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
33333352

3334-
irq = irq_map[phy_no + 72];
3353+
irq = hisi_hba->irq_map[phy_no + 72];
33353354
rc = devm_request_irq(dev, irq, sata_int_v2_hw, 0,
33363355
DRV_NAME " sata", phy);
33373356
if (rc) {
@@ -3343,7 +3362,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
33433362
}
33443363

33453364
for (fatal_no = 0; fatal_no < HISI_SAS_FATAL_INT_NR; fatal_no++) {
3346-
irq = irq_map[fatal_no + 81];
3365+
irq = hisi_hba->irq_map[fatal_no + 81];
33473366
rc = devm_request_irq(dev, irq, fatal_interrupts[fatal_no], 0,
33483367
DRV_NAME " fatal", hisi_hba);
33493368
if (rc) {
@@ -3354,24 +3373,22 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
33543373
}
33553374
}
33563375

3357-
for (queue_no = 0; queue_no < hisi_hba->queue_count; queue_no++) {
3376+
for (queue_no = 0; queue_no < hisi_hba->cq_nvecs; queue_no++) {
33583377
struct hisi_sas_cq *cq = &hisi_hba->cq[queue_no];
33593378

3360-
cq->irq_no = irq_map[queue_no + 96];
3379+
cq->irq_no = hisi_hba->irq_map[queue_no + 96];
33613380
rc = devm_request_threaded_irq(dev, cq->irq_no,
33623381
cq_interrupt_v2_hw,
33633382
cq_thread_v2_hw, IRQF_ONESHOT,
33643383
DRV_NAME " cq", cq);
33653384
if (rc) {
33663385
dev_err(dev, "irq init: could not request cq interrupt %d, rc=%d\n",
3367-
irq, rc);
3386+
cq->irq_no, rc);
33683387
rc = -ENOENT;
33693388
goto err_out;
33703389
}
3390+
cq->irq_mask = irq_get_affinity_mask(cq->irq_no);
33713391
}
3372-
3373-
hisi_hba->cq_nvecs = hisi_hba->queue_count;
3374-
33753392
err_out:
33763393
return rc;
33773394
}
@@ -3529,6 +3546,26 @@ static struct device_attribute *host_attrs_v2_hw[] = {
35293546
NULL
35303547
};
35313548

3549+
static int map_queues_v2_hw(struct Scsi_Host *shost)
3550+
{
3551+
struct hisi_hba *hisi_hba = shost_priv(shost);
3552+
struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT];
3553+
const struct cpumask *mask;
3554+
unsigned int queue, cpu;
3555+
3556+
for (queue = 0; queue < qmap->nr_queues; queue++) {
3557+
mask = irq_get_affinity_mask(hisi_hba->irq_map[96 + queue]);
3558+
if (!mask)
3559+
continue;
3560+
3561+
for_each_cpu(cpu, mask)
3562+
qmap->mq_map[cpu] = qmap->queue_offset + queue;
3563+
}
3564+
3565+
return 0;
3566+
3567+
}
3568+
35323569
static struct scsi_host_template sht_v2_hw = {
35333570
.name = DRV_NAME,
35343571
.proc_name = DRV_NAME,
@@ -3553,10 +3590,13 @@ static struct scsi_host_template sht_v2_hw = {
35533590
#endif
35543591
.shost_attrs = host_attrs_v2_hw,
35553592
.host_reset = hisi_sas_host_reset,
3593+
.map_queues = map_queues_v2_hw,
3594+
.host_tagset = 1,
35563595
};
35573596

35583597
static const struct hisi_sas_hw hisi_sas_v2_hw = {
35593598
.hw_init = hisi_sas_v2_init,
3599+
.interrupt_preinit = hisi_sas_v2_interrupt_preinit,
35603600
.setup_itct = setup_itct_v2_hw,
35613601
.slot_index_alloc = slot_index_alloc_quirk_v2_hw,
35623602
.alloc_dev = alloc_dev_quirk_v2_hw,

0 commit comments

Comments
 (0)