Skip to content

Commit

Permalink
scsi: hisi_sas_v3: convert private reply queue to blk-mq hw queue
Browse files Browse the repository at this point in the history
SCSI's reply qeueue is very similar with blk-mq's hw queue, both
assigned by IRQ vector, so map te private reply queue into blk-mq's hw
queue via .host_tagset.

Then the private reply mapping can be removed.

Another benefit is that the request/irq lost issue may be solved in
generic approach because managed IRQ may be shutdown during CPU
hotplug.

Signed-off-by: Ming Lei <ming.lei@redhat.com>
  • Loading branch information
Ming Lei committed Jun 24, 2019
1 parent 3b46792 commit 0d2cd3c
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 60 deletions.
2 changes: 1 addition & 1 deletion drivers/scsi/hisi_sas/hisi_sas.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/blk-mq-pci.h>
#include <scsi/sas_ata.h>
#include <scsi/libsas.h>

Expand Down Expand Up @@ -373,7 +374,6 @@ struct hisi_hba {
u32 intr_coal_count; /* Interrupt count to coalesce */

int cq_nvecs;
unsigned int *reply_map;

/* debugfs memories */
u32 *debugfs_global_reg;
Expand Down
36 changes: 19 additions & 17 deletions drivers/scsi/hisi_sas/hisi_sas_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,19 @@ static int hisi_sas_dif_dma_map(struct hisi_hba *hisi_hba,
return rc;
}

static struct scsi_cmnd *sas_task_to_scsi_cmd(struct sas_task *task)
{
if (!task->uldd_task)
return NULL;

if (dev_is_sata(task->dev)) {
struct ata_queued_cmd *qc = task->uldd_task;
return qc->scsicmd;
} else {
return task->uldd_task;
}
}

static int hisi_sas_task_prep(struct sas_task *task,
struct hisi_sas_dq **dq_pointer,
bool is_tmf, struct hisi_sas_tmf_task *tmf,
Expand All @@ -454,6 +467,7 @@ static int hisi_sas_task_prep(struct sas_task *task,
struct hisi_sas_dq *dq;
unsigned long flags;
int wr_q_index;
struct scsi_cmnd *scsi_cmnd;

if (DEV_IS_GONE(sas_dev)) {
if (sas_dev)
Expand All @@ -466,9 +480,10 @@ static int hisi_sas_task_prep(struct sas_task *task,
return -ECOMM;
}

if (hisi_hba->reply_map) {
int cpu = raw_smp_processor_id();
unsigned int dq_index = hisi_hba->reply_map[cpu];
scsi_cmnd = sas_task_to_scsi_cmd(task);
if (hisi_hba->shost->hostt->host_tagset) {
unsigned int dq_index = scsi_cmnd_hctx_index(
hisi_hba->shost, scsi_cmnd);

*dq_pointer = dq = &hisi_hba->dq[dq_index];
} else {
Expand Down Expand Up @@ -498,21 +513,8 @@ static int hisi_sas_task_prep(struct sas_task *task,

if (hisi_hba->hw->slot_index_alloc)
rc = hisi_hba->hw->slot_index_alloc(hisi_hba, device);
else {
struct scsi_cmnd *scsi_cmnd = NULL;

if (task->uldd_task) {
struct ata_queued_cmd *qc;

if (dev_is_sata(device)) {
qc = task->uldd_task;
scsi_cmnd = qc->scsicmd;
} else {
scsi_cmnd = task->uldd_task;
}
}
else
rc = hisi_sas_slot_index_alloc(hisi_hba, scsi_cmnd);
}
if (rc < 0)
goto err_out_dif_dma_unmap;

Expand Down
80 changes: 38 additions & 42 deletions drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -2339,36 +2339,9 @@ static irqreturn_t cq_interrupt_v3_hw(int irq_no, void *p)
return IRQ_HANDLED;
}

static void setup_reply_map_v3_hw(struct hisi_hba *hisi_hba, int nvecs)
static int interrupt_pre_init_v3_hw(struct hisi_hba *hisi_hba)
{
const struct cpumask *mask;
int queue, cpu;

for (queue = 0; queue < nvecs; queue++) {
struct hisi_sas_cq *cq = &hisi_hba->cq[queue];

mask = pci_irq_get_affinity(hisi_hba->pci_dev, queue +
BASE_VECTORS_V3_HW);
if (!mask)
goto fallback;
cq->pci_irq_mask = mask;
for_each_cpu(cpu, mask)
hisi_hba->reply_map[cpu] = queue;
}
return;

fallback:
for_each_possible_cpu(cpu)
hisi_hba->reply_map[cpu] = cpu % hisi_hba->queue_count;
/* Don't clean all CQ masks */
}

static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba)
{
struct device *dev = hisi_hba->dev;
struct pci_dev *pdev = hisi_hba->pci_dev;
int vectors, rc;
int i, k;
int vectors;
int max_msi = HISI_SAS_MSI_COUNT_V3_HW, min_msi;

if (auto_affine_msi_experimental) {
Expand All @@ -2378,36 +2351,39 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba)

min_msi = MIN_AFFINE_VECTORS_V3_HW;

hisi_hba->reply_map = devm_kcalloc(dev, nr_cpu_ids,
sizeof(unsigned int),
GFP_KERNEL);
if (!hisi_hba->reply_map)
return -ENOMEM;
vectors = pci_alloc_irq_vectors_affinity(hisi_hba->pci_dev,
min_msi, max_msi,
PCI_IRQ_MSI |
PCI_IRQ_AFFINITY,
&desc);
if (vectors < 0)
return -ENOENT;
setup_reply_map_v3_hw(hisi_hba, vectors - BASE_VECTORS_V3_HW);
} else {
min_msi = max_msi;
vectors = pci_alloc_irq_vectors(hisi_hba->pci_dev, min_msi,
max_msi, PCI_IRQ_MSI);
if (vectors < 0)
return vectors;
}

hisi_hba->cq_nvecs = vectors - BASE_VECTORS_V3_HW;

return 0;
}

static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba)
{
struct device *dev = hisi_hba->dev;
struct pci_dev *pdev = hisi_hba->pci_dev;
int rc, i, k;

dev_err(dev, "%s hisi_hba->cq_nvecs=%d\n", __func__, hisi_hba->cq_nvecs);

rc = devm_request_irq(dev, pci_irq_vector(pdev, 1),
int_phy_up_down_bcast_v3_hw, 0,
DRV_NAME " phy", hisi_hba);
if (rc) {
dev_err(dev, "could not request phy interrupt, rc=%d\n", rc);
rc = -ENOENT;
goto free_irq_vectors;
return -ENOENT;
}

rc = devm_request_irq(dev, pci_irq_vector(pdev, 2),
Expand Down Expand Up @@ -2462,8 +2438,6 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba)
free_irq(pci_irq_vector(pdev, 2), hisi_hba);
free_phy_irq:
free_irq(pci_irq_vector(pdev, 1), hisi_hba);
free_irq_vectors:
pci_free_irq_vectors(pdev);
return rc;
}

Expand Down Expand Up @@ -2891,6 +2865,18 @@ static void debugfs_snapshot_restore_v3_hw(struct hisi_hba *hisi_hba)
clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
}

static int hisi_sas_map_queues(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];

if (auto_affine_msi_experimental)
return blk_mq_pci_map_queues(qmap, hisi_hba->pci_dev,
BASE_VECTORS_V3_HW);
else
return blk_mq_map_queues(qmap);
}

static struct scsi_host_template sht_v3_hw = {
.name = DRV_NAME,
.module = THIS_MODULE,
Expand All @@ -2901,6 +2887,8 @@ static struct scsi_host_template sht_v3_hw = {
.scan_start = hisi_sas_scan_start,
.change_queue_depth = sas_change_queue_depth,
.bios_param = sas_bios_param,
.map_queues = hisi_sas_map_queues,
.host_tagset = 1,
.this_id = -1,
.sg_tablesize = HISI_SAS_SGE_PAGE_CNT,
.sg_prot_tablesize = HISI_SAS_SGE_PAGE_CNT,
Expand Down Expand Up @@ -3087,15 +3075,21 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (hisi_sas_debugfs_enable)
hisi_sas_debugfs_init(hisi_hba);


rc = interrupt_pre_init_v3_hw(hisi_hba);
if (rc < 0)
goto err_out_interrupts;
shost->nr_hw_queues = hisi_hba->cq_nvecs;

rc = scsi_add_host(shost, dev);
if (rc)
goto err_out_ha;
goto err_out_interrupts;

rc = sas_register_ha(sha);
if (rc)
goto err_out_register_ha;

rc = hisi_hba->hw->hw_init(hisi_hba);
rc = hisi_sas_v3_init(hisi_hba);
if (rc)
goto err_out_register_ha;

Expand All @@ -3105,6 +3099,8 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)

err_out_register_ha:
scsi_remove_host(shost);
err_out_interrupts:
pci_free_irq_vectors(pdev);
err_out_ha:
scsi_host_put(shost);
err_out_regions:
Expand Down

0 comments on commit 0d2cd3c

Please sign in to comment.