Skip to content

Commit 0e47eff

Browse files
Xiang Chenmartinkpetersen
authored andcommitted
scsi: hisi_sas: Add poll support for v3 hw
Add a module parameter to set how many queues are used for iopoll. Also fill the interface mq_poll. For internal I/Os from libsas and libata we use non-iopoll queue (queue 0) to deliver and complete them. But for internal abort I/Os, just don't send them for poll queues. There is still a risk associated as this sends internal abort commands to non-iopoll queues which actually requires sending an internal abort command to every queue. As a result, make the module parameter as "experimental" for now. Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> Link: https://lore.kernel.org/r/1678169355-76215-3-git-send-email-chenxiang66@hisilicon.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 538a604 commit 0e47eff

3 files changed

Lines changed: 82 additions & 10 deletions

File tree

drivers/scsi/hisi_sas/hisi_sas.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ struct hisi_sas_cq {
207207
int rd_point;
208208
int id;
209209
int irq_no;
210+
spinlock_t poll_lock;
210211
};
211212

212213
struct hisi_sas_dq {
@@ -484,6 +485,8 @@ struct hisi_hba {
484485
struct dentry *debugfs_dump_dentry;
485486
struct dentry *debugfs_bist_dentry;
486487
struct dentry *debugfs_fifo_dentry;
488+
489+
int iopoll_q_cnt;
487490
};
488491

489492
/* Generic HW DMA host memory structures */

drivers/scsi/hisi_sas/hisi_sas_main.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -529,10 +529,21 @@ static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags)
529529
dq_index = blk_mq_unique_tag_to_hwq(blk_tag);
530530
dq = &hisi_hba->dq[dq_index];
531531
} else {
532-
struct Scsi_Host *shost = hisi_hba->shost;
533-
struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT];
534-
int queue = qmap->mq_map[raw_smp_processor_id()];
532+
int queue;
533+
534+
if (hisi_hba->iopoll_q_cnt) {
535+
/*
536+
* Use interrupt queue (queue 0) to deliver and complete
537+
* internal IOs of libsas or libata when there is at least
538+
* one iopoll queue
539+
*/
540+
queue = 0;
541+
} else {
542+
struct Scsi_Host *shost = hisi_hba->shost;
543+
struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT];
535544

545+
queue = qmap->mq_map[raw_smp_processor_id()];
546+
}
536547
dq = &hisi_hba->dq[queue];
537548
}
538549
break;
@@ -2101,6 +2112,7 @@ int hisi_sas_alloc(struct hisi_hba *hisi_hba)
21012112
/* Completion queue structure */
21022113
cq->id = i;
21032114
cq->hisi_hba = hisi_hba;
2115+
spin_lock_init(&cq->poll_lock);
21042116

21052117
/* Delivery queue structure */
21062118
spin_lock_init(&dq->lock);

drivers/scsi/hisi_sas/hisi_sas_v3_hw.c

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,11 @@ static int prot_mask;
552552
module_param(prot_mask, int, 0444);
553553
MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=0x0 ");
554554

555+
/* the index of iopoll queues are bigger than interrupt queues' */
556+
static int experimental_iopoll_q_cnt;
557+
module_param(experimental_iopoll_q_cnt, int, 0444);
558+
MODULE_PARM_DESC(experimental_iopoll_q_cnt, "number of queues to be used as poll mode, def=0");
559+
555560
static void debugfs_work_handler_v3_hw(struct work_struct *work);
556561
static void debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba);
557562

@@ -2391,18 +2396,20 @@ static void slot_complete_v3_hw(struct hisi_hba *hisi_hba,
23912396
task->task_done(task);
23922397
}
23932398

2394-
static void complete_v3_hw(struct hisi_sas_cq *cq)
2399+
static int complete_v3_hw(struct hisi_sas_cq *cq)
23952400
{
23962401
struct hisi_sas_complete_v3_hdr *complete_queue;
23972402
struct hisi_hba *hisi_hba = cq->hisi_hba;
23982403
u32 rd_point, wr_point;
23992404
int queue = cq->id;
2405+
int completed;
24002406

24012407
rd_point = cq->rd_point;
24022408
complete_queue = hisi_hba->complete_hdr[queue];
24032409

24042410
wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR +
24052411
(0x14 * queue));
2412+
completed = (wr_point + HISI_SAS_QUEUE_SLOTS - rd_point) % HISI_SAS_QUEUE_SLOTS;
24062413

24072414
while (rd_point != wr_point) {
24082415
struct hisi_sas_complete_v3_hdr *complete_hdr;
@@ -2450,6 +2457,21 @@ static void complete_v3_hw(struct hisi_sas_cq *cq)
24502457
/* update rd_point */
24512458
cq->rd_point = rd_point;
24522459
hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
2460+
2461+
return completed;
2462+
}
2463+
2464+
static int queue_complete_v3_hw(struct Scsi_Host *shost, unsigned int queue)
2465+
{
2466+
struct hisi_hba *hisi_hba = shost_priv(shost);
2467+
struct hisi_sas_cq *cq = &hisi_hba->cq[queue];
2468+
int completed;
2469+
2470+
spin_lock(&cq->poll_lock);
2471+
completed = complete_v3_hw(cq);
2472+
spin_unlock(&cq->poll_lock);
2473+
2474+
return completed;
24532475
}
24542476

24552477
static irqreturn_t cq_thread_v3_hw(int irq_no, void *p)
@@ -2481,8 +2503,9 @@ static void hisi_sas_v3_free_vectors(void *data)
24812503

24822504
static int interrupt_preinit_v3_hw(struct hisi_hba *hisi_hba)
24832505
{
2484-
int vectors;
2485-
int max_msi = HISI_SAS_MSI_COUNT_V3_HW, min_msi;
2506+
/* Allocate all MSI vectors to avoid re-insertion issue */
2507+
int max_msi = HISI_SAS_MSI_COUNT_V3_HW;
2508+
int vectors, min_msi;
24862509
struct Scsi_Host *shost = hisi_hba->shost;
24872510
struct pci_dev *pdev = hisi_hba->pci_dev;
24882511
struct irq_affinity desc = {
@@ -2499,8 +2522,8 @@ static int interrupt_preinit_v3_hw(struct hisi_hba *hisi_hba)
24992522
return -ENOENT;
25002523

25012524

2502-
hisi_hba->cq_nvecs = vectors - BASE_VECTORS_V3_HW;
2503-
shost->nr_hw_queues = hisi_hba->cq_nvecs;
2525+
hisi_hba->cq_nvecs = vectors - BASE_VECTORS_V3_HW - hisi_hba->iopoll_q_cnt;
2526+
shost->nr_hw_queues = hisi_hba->cq_nvecs + hisi_hba->iopoll_q_cnt;
25042527

25052528
devm_add_action(&pdev->dev, hisi_sas_v3_free_vectors, pdev);
25062529
return 0;
@@ -3218,9 +3241,31 @@ static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable)
32183241
static void hisi_sas_map_queues(struct Scsi_Host *shost)
32193242
{
32203243
struct hisi_hba *hisi_hba = shost_priv(shost);
3221-
struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT];
3244+
struct blk_mq_queue_map *qmap;
3245+
int i, qoff;
3246+
3247+
for (i = 0, qoff = 0; i < shost->nr_maps; i++) {
3248+
qmap = &shost->tag_set.map[i];
3249+
if (i == HCTX_TYPE_DEFAULT) {
3250+
qmap->nr_queues = hisi_hba->cq_nvecs;
3251+
} else if (i == HCTX_TYPE_POLL) {
3252+
qmap->nr_queues = hisi_hba->iopoll_q_cnt;
3253+
} else {
3254+
qmap->nr_queues = 0;
3255+
continue;
3256+
}
32223257

3223-
blk_mq_pci_map_queues(qmap, hisi_hba->pci_dev, BASE_VECTORS_V3_HW);
3258+
/* At least one interrupt hardware queue */
3259+
if (!qmap->nr_queues)
3260+
WARN_ON(i == HCTX_TYPE_DEFAULT);
3261+
qmap->queue_offset = qoff;
3262+
if (i == HCTX_TYPE_POLL)
3263+
blk_mq_map_queues(qmap);
3264+
else
3265+
blk_mq_pci_map_queues(qmap, hisi_hba->pci_dev,
3266+
BASE_VECTORS_V3_HW);
3267+
qoff += qmap->nr_queues;
3268+
}
32243269
}
32253270

32263271
static struct scsi_host_template sht_v3_hw = {
@@ -3252,6 +3297,7 @@ static struct scsi_host_template sht_v3_hw = {
32523297
.tag_alloc_policy = BLK_TAG_ALLOC_RR,
32533298
.host_reset = hisi_sas_host_reset,
32543299
.host_tagset = 1,
3300+
.mq_poll = queue_complete_v3_hw,
32553301
};
32563302

32573303
static const struct hisi_sas_hw hisi_sas_v3_hw = {
@@ -3311,6 +3357,13 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev)
33113357
if (hisi_sas_get_fw_info(hisi_hba) < 0)
33123358
goto err_out;
33133359

3360+
if (experimental_iopoll_q_cnt < 0 ||
3361+
experimental_iopoll_q_cnt >= hisi_hba->queue_count)
3362+
dev_err(dev, "iopoll queue count %d cannot exceed or equal 16, using default 0\n",
3363+
experimental_iopoll_q_cnt);
3364+
else
3365+
hisi_hba->iopoll_q_cnt = experimental_iopoll_q_cnt;
3366+
33143367
if (hisi_sas_alloc(hisi_hba)) {
33153368
hisi_sas_free(hisi_hba);
33163369
goto err_out;
@@ -4866,6 +4919,10 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
48664919
shost->max_cmd_len = 16;
48674920
shost->can_queue = HISI_SAS_UNRESERVED_IPTT;
48684921
shost->cmd_per_lun = HISI_SAS_UNRESERVED_IPTT;
4922+
if (hisi_hba->iopoll_q_cnt)
4923+
shost->nr_maps = 3;
4924+
else
4925+
shost->nr_maps = 1;
48694926

48704927
sha->sas_ha_name = DRV_NAME;
48714928
sha->dev = dev;

0 commit comments

Comments
 (0)