Skip to content

Commit

Permalink
scsi: hisi_sas: Expose HW queues for v2 hw
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
John Garry authored and Martin K. Petersen committed Dec 22, 2020
1 parent 81e7eb5 commit 74a2921
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 13 deletions.
4 changes: 4 additions & 0 deletions drivers/scsi/hisi_sas/hisi_sas.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/debugfs.h>
#include <linux/dmapool.h>
#include <linux/iopoll.h>
#include <linux/irq.h>
#include <linux/lcm.h>
#include <linux/libata.h>
#include <linux/mfd/syscon.h>
Expand Down Expand Up @@ -312,6 +313,7 @@ enum {

struct hisi_sas_hw {
int (*hw_init)(struct hisi_hba *hisi_hba);
int (*interrupt_preinit)(struct hisi_hba *hisi_hba);
void (*setup_itct)(struct hisi_hba *hisi_hba,
struct hisi_sas_device *device);
int (*slot_index_alloc)(struct hisi_hba *hisi_hba,
Expand Down Expand Up @@ -418,6 +420,8 @@ struct hisi_hba {
u32 refclk_frequency_mhz;
u8 sas_addr[SAS_ADDR_SIZE];

int *irq_map; /* v2 hw */

int n_phy;
spinlock_t lock;
struct semaphore sem;
Expand Down
11 changes: 11 additions & 0 deletions drivers/scsi/hisi_sas/hisi_sas_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2620,6 +2620,13 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
return NULL;
}

static int hisi_sas_interrupt_preinit(struct hisi_hba *hisi_hba)
{
if (hisi_hba->hw->interrupt_preinit)
return hisi_hba->hw->interrupt_preinit(hisi_hba);
return 0;
}

int hisi_sas_probe(struct platform_device *pdev,
const struct hisi_sas_hw *hw)
{
Expand Down Expand Up @@ -2677,6 +2684,10 @@ int hisi_sas_probe(struct platform_device *pdev,
sha->sas_port[i] = &hisi_hba->port[i].sas_port;
}

rc = hisi_sas_interrupt_preinit(hisi_hba);
if (rc)
goto err_out_ha;

rc = scsi_add_host(shost, &pdev->dev);
if (rc)
goto err_out_ha;
Expand Down
66 changes: 53 additions & 13 deletions drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -3302,6 +3302,28 @@ static irq_handler_t fatal_interrupts[HISI_SAS_FATAL_INT_NR] = {
fatal_axi_int_v2_hw
};

#define CQ0_IRQ_INDEX (96)

static int hisi_sas_v2_interrupt_preinit(struct hisi_hba *hisi_hba)
{
struct platform_device *pdev = hisi_hba->platform_dev;
struct Scsi_Host *shost = hisi_hba->shost;
struct irq_affinity desc = {
.pre_vectors = CQ0_IRQ_INDEX,
.post_vectors = 16,
};
int resv = desc.pre_vectors + desc.post_vectors, minvec = resv + 1, nvec;

nvec = devm_platform_get_irqs_affinity(pdev, &desc, minvec, 128,
&hisi_hba->irq_map);
if (nvec < 0)
return nvec;

shost->nr_hw_queues = hisi_hba->cq_nvecs = nvec - resv;

return 0;
}

/*
* There is a limitation in the hip06 chipset that we need
* to map in all mbigen interrupts, even if they are not used.
Expand All @@ -3310,14 +3332,11 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
{
struct platform_device *pdev = hisi_hba->platform_dev;
struct device *dev = &pdev->dev;
int irq, rc = 0, irq_map[128];
int irq, rc = 0;
int i, phy_no, fatal_no, queue_no;

for (i = 0; i < 128; i++)
irq_map[i] = platform_get_irq(pdev, i);

for (i = 0; i < HISI_SAS_PHY_INT_NR; i++) {
irq = irq_map[i + 1]; /* Phy up/down is irq1 */
irq = hisi_hba->irq_map[i + 1]; /* Phy up/down is irq1 */
rc = devm_request_irq(dev, irq, phy_interrupts[i], 0,
DRV_NAME " phy", hisi_hba);
if (rc) {
Expand All @@ -3331,7 +3350,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) {
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];

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

for (fatal_no = 0; fatal_no < HISI_SAS_FATAL_INT_NR; fatal_no++) {
irq = irq_map[fatal_no + 81];
irq = hisi_hba->irq_map[fatal_no + 81];
rc = devm_request_irq(dev, irq, fatal_interrupts[fatal_no], 0,
DRV_NAME " fatal", hisi_hba);
if (rc) {
Expand All @@ -3354,24 +3373,22 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
}
}

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

cq->irq_no = irq_map[queue_no + 96];
cq->irq_no = hisi_hba->irq_map[queue_no + 96];
rc = devm_request_threaded_irq(dev, cq->irq_no,
cq_interrupt_v2_hw,
cq_thread_v2_hw, IRQF_ONESHOT,
DRV_NAME " cq", cq);
if (rc) {
dev_err(dev, "irq init: could not request cq interrupt %d, rc=%d\n",
irq, rc);
cq->irq_no, rc);
rc = -ENOENT;
goto err_out;
}
cq->irq_mask = irq_get_affinity_mask(cq->irq_no);
}

hisi_hba->cq_nvecs = hisi_hba->queue_count;

err_out:
return rc;
}
Expand Down Expand Up @@ -3529,6 +3546,26 @@ static struct device_attribute *host_attrs_v2_hw[] = {
NULL
};

static int map_queues_v2_hw(struct Scsi_Host *shost)
{
struct hisi_hba *hisi_hba = shost_priv(shost);
struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT];
const struct cpumask *mask;
unsigned int queue, cpu;

for (queue = 0; queue < qmap->nr_queues; queue++) {
mask = irq_get_affinity_mask(hisi_hba->irq_map[96 + queue]);
if (!mask)
continue;

for_each_cpu(cpu, mask)
qmap->mq_map[cpu] = qmap->queue_offset + queue;
}

return 0;

}

static struct scsi_host_template sht_v2_hw = {
.name = DRV_NAME,
.proc_name = DRV_NAME,
Expand All @@ -3553,10 +3590,13 @@ static struct scsi_host_template sht_v2_hw = {
#endif
.shost_attrs = host_attrs_v2_hw,
.host_reset = hisi_sas_host_reset,
.map_queues = map_queues_v2_hw,
.host_tagset = 1,
};

static const struct hisi_sas_hw hisi_sas_v2_hw = {
.hw_init = hisi_sas_v2_init,
.interrupt_preinit = hisi_sas_v2_interrupt_preinit,
.setup_itct = setup_itct_v2_hw,
.slot_index_alloc = slot_index_alloc_quirk_v2_hw,
.alloc_dev = alloc_dev_quirk_v2_hw,
Expand Down

0 comments on commit 74a2921

Please sign in to comment.