Skip to content

Commit 9e4bec5

Browse files
kadesai16martinkpetersen
authored andcommitted
scsi: megaraid_sas: mq_poll support
Implement mq_poll interface support in megaraid_sas. This feature requires shared host tag support in kernel and driver. The driver can work in non-IRQ mode which means there will not be any MSI-x vector associated for poll_queues. The MegaRAID hardware has a single submission queue and multiple reply queues. However, using the shared host tagset support will enable the driver to simulate multiple hardware queues. Change driver to allocate some extra reply queues which will be marked as poll_queues. These poll_queues will not have associated MSI-x vectors. All I/O completions on these queues will be done through the IOPOLL interface. megaraid_sas with 8 poll_queues and using the io_uring hiprio=1 setting can reach 3.2M IOPS with zero interrupts generated by the hardware. The IOPOLL feature can be enabled using module parameter poll_queues. Link: https://lore.kernel.org/r/[email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Reviewed-by: Hannes Reinecke <[email protected]> Signed-off-by: Kashyap Desai <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent af18309 commit 9e4bec5

File tree

4 files changed

+123
-11
lines changed

4 files changed

+123
-11
lines changed

drivers/scsi/megaraid/megaraid_sas.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2214,6 +2214,7 @@ struct megasas_irq_context {
22142214
struct irq_poll irqpoll;
22152215
bool irq_poll_scheduled;
22162216
bool irq_line_enable;
2217+
atomic_t in_used;
22172218
};
22182219

22192220
struct MR_DRV_SYSTEM_INFO {
@@ -2448,6 +2449,7 @@ struct megasas_instance {
24482449
bool support_pci_lane_margining;
24492450
u8 low_latency_index_start;
24502451
int perf_mode;
2452+
int iopoll_q_count;
24512453
};
24522454

24532455
struct MR_LD_VF_MAP {
@@ -2728,5 +2730,6 @@ void megasas_init_debugfs(void);
27282730
void megasas_exit_debugfs(void);
27292731
void megasas_setup_debugfs(struct megasas_instance *instance);
27302732
void megasas_destroy_debugfs(struct megasas_instance *instance);
2733+
int megasas_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num);
27312734

27322735
#endif /*LSI_MEGARAID_SAS_H */

drivers/scsi/megaraid/megaraid_sas_base.c

Lines changed: 77 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,15 @@ unsigned int enable_sdev_max_qd;
114114
module_param(enable_sdev_max_qd, int, 0444);
115115
MODULE_PARM_DESC(enable_sdev_max_qd, "Enable sdev max qd as can_queue. Default: 0");
116116

117+
int poll_queues;
118+
module_param(poll_queues, int, 0444);
119+
MODULE_PARM_DESC(poll_queues, "Number of queues to be use for io_uring poll mode.\n\t\t"
120+
"This parameter is effective only if host_tagset_enable=1 &\n\t\t"
121+
"It is not applicable for MFI_SERIES. &\n\t\t"
122+
"Driver will work in latency mode. &\n\t\t"
123+
"High iops queues are not allocated &\n\t\t"
124+
);
125+
117126
int host_tagset_enable = 1;
118127
module_param(host_tagset_enable, int, 0444);
119128
MODULE_PARM_DESC(host_tagset_enable, "Shared host tagset enable/disable Default: enable(1)");
@@ -207,6 +216,7 @@ static bool support_pci_lane_margining;
207216
static spinlock_t poll_aen_lock;
208217

209218
extern struct dentry *megasas_debugfs_root;
219+
extern int megasas_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num);
210220

211221
void
212222
megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
@@ -3127,14 +3137,37 @@ megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev,
31273137
static int megasas_map_queues(struct Scsi_Host *shost)
31283138
{
31293139
struct megasas_instance *instance;
3140+
int qoff = 0, offset;
3141+
struct blk_mq_queue_map *map;
31303142

31313143
instance = (struct megasas_instance *)shost->hostdata;
31323144

31333145
if (shost->nr_hw_queues == 1)
31343146
return 0;
31353147

3136-
return blk_mq_pci_map_queues(&shost->tag_set.map[HCTX_TYPE_DEFAULT],
3137-
instance->pdev, instance->low_latency_index_start);
3148+
offset = instance->low_latency_index_start;
3149+
3150+
/* Setup Default hctx */
3151+
map = &shost->tag_set.map[HCTX_TYPE_DEFAULT];
3152+
map->nr_queues = instance->msix_vectors - offset;
3153+
map->queue_offset = 0;
3154+
blk_mq_pci_map_queues(map, instance->pdev, offset);
3155+
qoff += map->nr_queues;
3156+
offset += map->nr_queues;
3157+
3158+
/* Setup Poll hctx */
3159+
map = &shost->tag_set.map[HCTX_TYPE_POLL];
3160+
map->nr_queues = instance->iopoll_q_count;
3161+
if (map->nr_queues) {
3162+
/*
3163+
* The poll queue(s) doesn't have an IRQ (and hence IRQ
3164+
* affinity), so use the regular blk-mq cpu mapping
3165+
*/
3166+
map->queue_offset = qoff;
3167+
blk_mq_map_queues(map);
3168+
}
3169+
3170+
return 0;
31383171
}
31393172

31403173
static void megasas_aen_polling(struct work_struct *work);
@@ -3446,6 +3479,7 @@ static struct scsi_host_template megasas_template = {
34463479
.shost_attrs = megaraid_host_attrs,
34473480
.bios_param = megasas_bios_param,
34483481
.map_queues = megasas_map_queues,
3482+
.mq_poll = megasas_blk_mq_poll,
34493483
.change_queue_depth = scsi_change_queue_depth,
34503484
.max_segment_size = 0xffffffff,
34513485
};
@@ -5834,13 +5868,16 @@ __megasas_alloc_irq_vectors(struct megasas_instance *instance)
58345868
irq_flags = PCI_IRQ_MSIX;
58355869

58365870
if (instance->smp_affinity_enable)
5837-
irq_flags |= PCI_IRQ_AFFINITY;
5871+
irq_flags |= PCI_IRQ_AFFINITY | PCI_IRQ_ALL_TYPES;
58385872
else
58395873
descp = NULL;
58405874

5875+
/* Do not allocate msix vectors for poll_queues.
5876+
* msix_vectors is always within a range of FW supported reply queue.
5877+
*/
58415878
i = pci_alloc_irq_vectors_affinity(instance->pdev,
58425879
instance->low_latency_index_start,
5843-
instance->msix_vectors, irq_flags, descp);
5880+
instance->msix_vectors - instance->iopoll_q_count, irq_flags, descp);
58445881

58455882
return i;
58465883
}
@@ -5856,10 +5893,30 @@ megasas_alloc_irq_vectors(struct megasas_instance *instance)
58565893
int i;
58575894
unsigned int num_msix_req;
58585895

5896+
instance->iopoll_q_count = 0;
5897+
if ((instance->adapter_type != MFI_SERIES) &&
5898+
poll_queues) {
5899+
5900+
instance->perf_mode = MR_LATENCY_PERF_MODE;
5901+
instance->low_latency_index_start = 1;
5902+
5903+
/* reserve for default and non-mananged pre-vector. */
5904+
if (instance->msix_vectors > (poll_queues + 2))
5905+
instance->iopoll_q_count = poll_queues;
5906+
else
5907+
instance->iopoll_q_count = 0;
5908+
5909+
num_msix_req = num_online_cpus() + instance->low_latency_index_start;
5910+
instance->msix_vectors = min(num_msix_req,
5911+
instance->msix_vectors);
5912+
5913+
}
5914+
58595915
i = __megasas_alloc_irq_vectors(instance);
58605916

5861-
if ((instance->perf_mode == MR_BALANCED_PERF_MODE) &&
5862-
(i != instance->msix_vectors)) {
5917+
if (((instance->perf_mode == MR_BALANCED_PERF_MODE)
5918+
|| instance->iopoll_q_count) &&
5919+
(i != (instance->msix_vectors - instance->iopoll_q_count))) {
58635920
if (instance->msix_vectors)
58645921
pci_free_irq_vectors(instance->pdev);
58655922
/* Disable Balanced IOPS mode and try realloc vectors */
@@ -5870,12 +5927,15 @@ megasas_alloc_irq_vectors(struct megasas_instance *instance)
58705927
instance->msix_vectors = min(num_msix_req,
58715928
instance->msix_vectors);
58725929

5930+
instance->iopoll_q_count = 0;
58735931
i = __megasas_alloc_irq_vectors(instance);
58745932

58755933
}
58765934

58775935
dev_info(&instance->pdev->dev,
5878-
"requested/available msix %d/%d\n", instance->msix_vectors, i);
5936+
"requested/available msix %d/%d poll_queue %d\n",
5937+
instance->msix_vectors - instance->iopoll_q_count,
5938+
i, instance->iopoll_q_count);
58795939

58805940
if (i > 0)
58815941
instance->msix_vectors = i;
@@ -6841,12 +6901,18 @@ static int megasas_io_attach(struct megasas_instance *instance)
68416901
instance->smp_affinity_enable) {
68426902
host->host_tagset = 1;
68436903
host->nr_hw_queues = instance->msix_vectors -
6844-
instance->low_latency_index_start;
6904+
instance->low_latency_index_start + instance->iopoll_q_count;
6905+
if (instance->iopoll_q_count)
6906+
host->nr_maps = 3;
6907+
} else {
6908+
instance->iopoll_q_count = 0;
68456909
}
68466910

68476911
dev_info(&instance->pdev->dev,
6848-
"Max firmware commands: %d shared with nr_hw_queues = %d\n",
6849-
instance->max_fw_cmds, host->nr_hw_queues);
6912+
"Max firmware commands: %d shared with default "
6913+
"hw_queues = %d poll_queues %d\n", instance->max_fw_cmds,
6914+
host->nr_hw_queues - instance->iopoll_q_count,
6915+
instance->iopoll_q_count);
68506916
/*
68516917
* Notify the mid-layer about the new controller
68526918
*/
@@ -8859,6 +8925,7 @@ static int __init megasas_init(void)
88598925
msix_vectors = 1;
88608926
rdpq_enable = 0;
88618927
dual_qdepth_disable = 1;
8928+
poll_queues = 0;
88628929
}
88638930

88648931
/*

drivers/scsi/megaraid/megaraid_sas_fusion.c

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,8 @@ megasas_alloc_reply_fusion(struct megasas_instance *instance)
713713
fusion = instance->ctrl_context;
714714

715715
count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
716+
count += instance->iopoll_q_count;
717+
716718
fusion->reply_frames_desc_pool =
717719
dma_pool_create("mr_reply", &instance->pdev->dev,
718720
fusion->reply_alloc_sz * count, 16, 0);
@@ -807,6 +809,7 @@ megasas_alloc_rdpq_fusion(struct megasas_instance *instance)
807809
}
808810

809811
msix_count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
812+
msix_count += instance->iopoll_q_count;
810813

811814
fusion->reply_frames_desc_pool = dma_pool_create("mr_rdpq",
812815
&instance->pdev->dev,
@@ -1157,7 +1160,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
11571160
MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE : 0;
11581161
IOCInitMessage->SystemRequestFrameBaseAddress = cpu_to_le64(fusion->io_request_frames_phys);
11591162
IOCInitMessage->SenseBufferAddressHigh = cpu_to_le32(upper_32_bits(fusion->sense_phys_addr));
1160-
IOCInitMessage->HostMSIxVectors = instance->msix_vectors;
1163+
IOCInitMessage->HostMSIxVectors = instance->msix_vectors + instance->iopoll_q_count;
11611164
IOCInitMessage->HostPageSize = MR_DEFAULT_NVME_PAGE_SHIFT;
11621165

11631166
time = ktime_get_real();
@@ -1851,6 +1854,8 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
18511854
sizeof(union MPI2_SGE_IO_UNION))/16;
18521855

18531856
count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
1857+
count += instance->iopoll_q_count;
1858+
18541859
for (i = 0 ; i < count; i++)
18551860
fusion->last_reply_idx[i] = 0;
18561861

@@ -1863,6 +1868,9 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
18631868
MEGASAS_FUSION_IOCTL_CMDS);
18641869
sema_init(&instance->ioctl_sem, MEGASAS_FUSION_IOCTL_CMDS);
18651870

1871+
for (i = 0; i < MAX_MSIX_QUEUES_FUSION; i++)
1872+
atomic_set(&fusion->busy_mq_poll[i], 0);
1873+
18661874
if (megasas_alloc_ioc_init_frame(instance))
18671875
return 1;
18681876

@@ -3530,6 +3538,9 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex,
35303538
if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
35313539
return IRQ_NONE;
35323540

3541+
if (irq_context && !atomic_add_unless(&irq_context->in_used, 1, 1))
3542+
return 0;
3543+
35333544
num_completed = 0;
35343545

35353546
while (d_val.u.low != cpu_to_le32(UINT_MAX) &&
@@ -3644,6 +3655,7 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex,
36443655
irq_context->irq_line_enable = true;
36453656
irq_poll_sched(&irq_context->irqpoll);
36463657
}
3658+
atomic_dec(&irq_context->in_used);
36473659
return num_completed;
36483660
}
36493661
}
@@ -3661,9 +3673,35 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex,
36613673
instance->reply_post_host_index_addr[0]);
36623674
megasas_check_and_restore_queue_depth(instance);
36633675
}
3676+
3677+
if (irq_context)
3678+
atomic_dec(&irq_context->in_used);
3679+
36643680
return num_completed;
36653681
}
36663682

3683+
int megasas_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num)
3684+
{
3685+
3686+
struct megasas_instance *instance;
3687+
int num_entries = 0;
3688+
struct fusion_context *fusion;
3689+
3690+
instance = (struct megasas_instance *)shost->hostdata;
3691+
3692+
fusion = instance->ctrl_context;
3693+
3694+
queue_num = queue_num + instance->low_latency_index_start;
3695+
3696+
if (!atomic_add_unless(&fusion->busy_mq_poll[queue_num], 1, 1))
3697+
return 0;
3698+
3699+
num_entries = complete_cmd_fusion(instance, queue_num, NULL);
3700+
atomic_dec(&fusion->busy_mq_poll[queue_num]);
3701+
3702+
return num_entries;
3703+
}
3704+
36673705
/**
36683706
* megasas_enable_irq_poll() - enable irqpoll
36693707
* @instance: Adapter soft state
@@ -4194,6 +4232,8 @@ void megasas_reset_reply_desc(struct megasas_instance *instance)
41944232

41954233
fusion = instance->ctrl_context;
41964234
count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
4235+
count += instance->iopoll_q_count;
4236+
41974237
for (i = 0 ; i < count ; i++) {
41984238
fusion->last_reply_idx[i] = 0;
41994239
reply_desc = fusion->reply_frames_desc[i];

drivers/scsi/megaraid/megaraid_sas_fusion.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,6 +1303,8 @@ struct fusion_context {
13031303
u8 *sense;
13041304
dma_addr_t sense_phys_addr;
13051305

1306+
atomic_t busy_mq_poll[MAX_MSIX_QUEUES_FUSION];
1307+
13061308
dma_addr_t reply_frames_desc_phys[MAX_MSIX_QUEUES_FUSION];
13071309
union MPI2_REPLY_DESCRIPTORS_UNION *reply_frames_desc[MAX_MSIX_QUEUES_FUSION];
13081310
struct rdpq_alloc_detail rdpq_tracker[RDPQ_MAX_CHUNK_COUNT];

0 commit comments

Comments
 (0)