Skip to content

Commit afd3a57

Browse files
sreekanthbrcmmartinkpetersen
authored andcommitted
scsi: mpi3mr: Add io_uring interface support in I/O-polled mode
Add support for the io_uring interface in I/O-polled mode. This feature is disabled in the driver by default. To enable the feature, a module parameter "poll_queues" has to be set with the desired number of polling queues. When the feature is enabled, the driver reserves a certain number of operational queue pairs for the poll_queues either from the available queue pairs or creates additional queue pairs based on the operational queue availability. The Polling queues will have corresponding IRQ and ISR functions as similar to default queues. However, the IRQ line is disabled by the driver for poll_queues. Link: https://lore.kernel.org/r/20211220141159.16117-22-sreekanth.reddy@broadcom.com Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 95cca8d commit afd3a57

3 files changed

Lines changed: 210 additions & 38 deletions

File tree

drivers/scsi/mpi3mr/mpi3mr.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,12 @@ enum mpi3mr_reset_reason {
220220
MPI3MR_RESET_FROM_FIRMWARE = 27,
221221
};
222222

223+
/* Queue type definitions */
224+
enum queue_type {
225+
MPI3MR_DEFAULT_QUEUE = 0,
226+
MPI3MR_POLL_QUEUE,
227+
};
228+
223229
/**
224230
* struct mpi3mr_compimg_ver - replica of component image
225231
* version defined in mpi30_image.h in host endianness
@@ -331,6 +337,7 @@ struct op_req_qinfo {
331337
* @pend_ios: Number of IOs pending in HW for this queue
332338
* @enable_irq_poll: Flag to indicate polling is enabled
333339
* @in_use: Queue is handled by poll/ISR
340+
* @qtype: Type of queue (types defined in enum queue_type)
334341
*/
335342
struct op_reply_qinfo {
336343
u16 ci;
@@ -345,6 +352,7 @@ struct op_reply_qinfo {
345352
atomic_t pend_ios;
346353
bool enable_irq_poll;
347354
atomic_t in_use;
355+
enum queue_type qtype;
348356
};
349357

350358
/**
@@ -703,6 +711,9 @@ struct scmd_priv {
703711
* @driver_info: Driver, Kernel, OS information to firmware
704712
* @change_count: Topology change count
705713
* @op_reply_q_offset: Operational reply queue offset with MSIx
714+
* @default_qcount: Total Default queues
715+
* @active_poll_qcount: Currently active poll queue count
716+
* @requested_poll_qcount: User requested poll queue count
706717
*/
707718
struct mpi3mr_ioc {
708719
struct list_head list;
@@ -839,6 +850,10 @@ struct mpi3mr_ioc {
839850
struct mpi3_driver_info_layout driver_info;
840851
u16 change_count;
841852
u16 op_reply_q_offset;
853+
854+
u16 default_qcount;
855+
u16 active_poll_qcount;
856+
u16 requested_poll_qcount;
842857
};
843858

844859
/**
@@ -940,5 +955,8 @@ void mpi3mr_flush_delayed_cmd_lists(struct mpi3mr_ioc *mrioc);
940955
void mpi3mr_check_rh_fault_ioc(struct mpi3mr_ioc *mrioc, u32 reason_code);
941956
void mpi3mr_print_fault_info(struct mpi3mr_ioc *mrioc);
942957
void mpi3mr_check_rh_fault_ioc(struct mpi3mr_ioc *mrioc, u32 reason_code);
958+
int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc,
959+
struct op_reply_qinfo *op_reply_q);
960+
int mpi3mr_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num);
943961

944962
#endif /*MPI3MR_H_INCLUDED*/

drivers/scsi/mpi3mr/mpi3mr_fw.c

Lines changed: 151 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ static int mpi3mr_setup_admin_qpair(struct mpi3mr_ioc *mrioc);
1616
static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc,
1717
struct mpi3_ioc_facts_data *facts_data);
1818

19+
static int poll_queues;
20+
module_param(poll_queues, int, 0444);
21+
MODULE_PARM_DESC(poll_queues, "Number of queues for io_uring poll mode. (Range 1 - 126)");
22+
1923
#if defined(writeq) && defined(CONFIG_64BIT)
2024
static inline void mpi3mr_writeq(__u64 b, volatile void __iomem *addr)
2125
{
@@ -461,10 +465,21 @@ mpi3mr_get_reply_desc(struct op_reply_qinfo *op_reply_q, u32 reply_ci)
461465
return reply_desc;
462466
}
463467

464-
static int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc,
465-
struct mpi3mr_intr_info *intr_info)
468+
/**
469+
* mpi3mr_process_op_reply_q - Operational reply queue handler
470+
* @mrioc: Adapter instance reference
471+
* @op_reply_q: Operational reply queue info
472+
*
473+
* Checks the specific operational reply queue and drains the
474+
* reply queue entries until the queue is empty and process the
475+
* individual reply descriptors.
476+
*
477+
* Return: 0 if queue is already processed,or number of reply
478+
* descriptors processed.
479+
*/
480+
int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc,
481+
struct op_reply_qinfo *op_reply_q)
466482
{
467-
struct op_reply_qinfo *op_reply_q = intr_info->op_reply_q;
468483
struct op_req_qinfo *op_req_q;
469484
u32 exp_phase;
470485
u32 reply_ci;
@@ -515,7 +530,7 @@ static int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc,
515530
* Ensure remaining completion happens from threaded ISR.
516531
*/
517532
if (num_op_reply > mrioc->max_host_ios) {
518-
intr_info->op_reply_q->enable_irq_poll = true;
533+
op_reply_q->enable_irq_poll = true;
519534
break;
520535
}
521536

@@ -530,6 +545,34 @@ static int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc,
530545
return num_op_reply;
531546
}
532547

548+
/**
549+
* mpi3mr_blk_mq_poll - Operational reply queue handler
550+
* @shost: SCSI Host reference
551+
* @queue_num: Request queue number (w.r.t OS it is hardware context number)
552+
*
553+
* Checks the specific operational reply queue and drains the
554+
* reply queue entries until the queue is empty and process the
555+
* individual reply descriptors.
556+
*
557+
* Return: 0 if queue is already processed,or number of reply
558+
* descriptors processed.
559+
*/
560+
int mpi3mr_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num)
561+
{
562+
int num_entries = 0;
563+
struct mpi3mr_ioc *mrioc;
564+
565+
mrioc = (struct mpi3mr_ioc *)shost->hostdata;
566+
567+
if ((mrioc->reset_in_progress || mrioc->prepare_for_reset))
568+
return 0;
569+
570+
num_entries = mpi3mr_process_op_reply_q(mrioc,
571+
&mrioc->op_reply_qinfo[queue_num]);
572+
573+
return num_entries;
574+
}
575+
533576
static irqreturn_t mpi3mr_isr_primary(int irq, void *privdata)
534577
{
535578
struct mpi3mr_intr_info *intr_info = privdata;
@@ -550,7 +593,8 @@ static irqreturn_t mpi3mr_isr_primary(int irq, void *privdata)
550593
if (!midx)
551594
num_admin_replies = mpi3mr_process_admin_reply_q(mrioc);
552595
if (intr_info->op_reply_q)
553-
num_op_reply = mpi3mr_process_op_reply_q(mrioc, intr_info);
596+
num_op_reply = mpi3mr_process_op_reply_q(mrioc,
597+
intr_info->op_reply_q);
554598

555599
if (num_admin_replies || num_op_reply)
556600
return IRQ_HANDLED;
@@ -621,9 +665,10 @@ static irqreturn_t mpi3mr_isr_poll(int irq, void *privdata)
621665
mpi3mr_process_admin_reply_q(mrioc);
622666
if (intr_info->op_reply_q)
623667
num_op_reply +=
624-
mpi3mr_process_op_reply_q(mrioc, intr_info);
668+
mpi3mr_process_op_reply_q(mrioc,
669+
intr_info->op_reply_q);
625670

626-
usleep_range(mrioc->irqpoll_sleep, 10 * mrioc->irqpoll_sleep);
671+
usleep_range(MPI3MR_IRQ_POLL_SLEEP, 10 * MPI3MR_IRQ_POLL_SLEEP);
627672

628673
} while (atomic_read(&intr_info->op_reply_q->pend_ios) &&
629674
(num_op_reply < mrioc->max_host_ios));
@@ -667,6 +712,25 @@ static inline int mpi3mr_request_irq(struct mpi3mr_ioc *mrioc, u16 index)
667712
return retval;
668713
}
669714

715+
static void mpi3mr_calc_poll_queues(struct mpi3mr_ioc *mrioc, u16 max_vectors)
716+
{
717+
if (!mrioc->requested_poll_qcount)
718+
return;
719+
720+
/* Reserved for Admin and Default Queue */
721+
if (max_vectors > 2 &&
722+
(mrioc->requested_poll_qcount < max_vectors - 2)) {
723+
ioc_info(mrioc,
724+
"enabled polled queues (%d) msix (%d)\n",
725+
mrioc->requested_poll_qcount, max_vectors);
726+
} else {
727+
ioc_info(mrioc,
728+
"disabled polled queues (%d) msix (%d) because of no resources for default queue\n",
729+
mrioc->requested_poll_qcount, max_vectors);
730+
mrioc->requested_poll_qcount = 0;
731+
}
732+
}
733+
670734
/**
671735
* mpi3mr_setup_isr - Setup ISR for the controller
672736
* @mrioc: Adapter instance reference
@@ -679,51 +743,72 @@ static inline int mpi3mr_request_irq(struct mpi3mr_ioc *mrioc, u16 index)
679743
static int mpi3mr_setup_isr(struct mpi3mr_ioc *mrioc, u8 setup_one)
680744
{
681745
unsigned int irq_flags = PCI_IRQ_MSIX;
682-
int max_vectors;
746+
int max_vectors, min_vec;
683747
int retval;
684748
int i;
685-
struct irq_affinity desc = { .pre_vectors = 1};
749+
struct irq_affinity desc = { .pre_vectors = 1, .post_vectors = 1 };
686750

687751
if (mrioc->is_intr_info_set)
688752
return 0;
689753

690754
mpi3mr_cleanup_isr(mrioc);
691755

692-
if (setup_one || reset_devices)
756+
if (setup_one || reset_devices) {
693757
max_vectors = 1;
694-
else {
758+
retval = pci_alloc_irq_vectors(mrioc->pdev,
759+
1, max_vectors, irq_flags);
760+
if (retval < 0) {
761+
ioc_err(mrioc, "cannot allocate irq vectors, ret %d\n",
762+
retval);
763+
goto out_failed;
764+
}
765+
} else {
695766
max_vectors =
696-
min_t(int, mrioc->cpu_count + 1, mrioc->msix_count);
767+
min_t(int, mrioc->cpu_count + 1 +
768+
mrioc->requested_poll_qcount, mrioc->msix_count);
769+
770+
mpi3mr_calc_poll_queues(mrioc, max_vectors);
697771

698772
ioc_info(mrioc,
699773
"MSI-X vectors supported: %d, no of cores: %d,",
700774
mrioc->msix_count, mrioc->cpu_count);
701775
ioc_info(mrioc,
702-
"MSI-x vectors requested: %d\n", max_vectors);
703-
}
776+
"MSI-x vectors requested: %d poll_queues %d\n",
777+
max_vectors, mrioc->requested_poll_qcount);
778+
779+
desc.post_vectors = mrioc->requested_poll_qcount;
780+
min_vec = desc.pre_vectors + desc.post_vectors;
781+
irq_flags |= PCI_IRQ_AFFINITY | PCI_IRQ_ALL_TYPES;
782+
783+
retval = pci_alloc_irq_vectors_affinity(mrioc->pdev,
784+
min_vec, max_vectors, irq_flags, &desc);
785+
786+
if (retval < 0) {
787+
ioc_err(mrioc, "cannot allocate irq vectors, ret %d\n",
788+
retval);
789+
goto out_failed;
790+
}
704791

705-
irq_flags |= PCI_IRQ_AFFINITY | PCI_IRQ_ALL_TYPES;
706792

707-
mrioc->op_reply_q_offset = (max_vectors > 1) ? 1 : 0;
708-
retval = pci_alloc_irq_vectors_affinity(mrioc->pdev,
709-
1, max_vectors, irq_flags, &desc);
710-
if (retval < 0) {
711-
ioc_err(mrioc, "Cannot alloc irq vectors\n");
712-
goto out_failed;
713-
}
714-
if (retval != max_vectors) {
715-
ioc_info(mrioc,
716-
"allocated vectors (%d) are less than configured (%d)\n",
717-
retval, max_vectors);
718793
/*
719794
* If only one MSI-x is allocated, then MSI-x 0 will be shared
720795
* between Admin queue and operational queue
721796
*/
722-
if (retval == 1)
797+
if (retval == min_vec)
723798
mrioc->op_reply_q_offset = 0;
799+
else if (retval != (max_vectors)) {
800+
ioc_info(mrioc,
801+
"allocated vectors (%d) are less than configured (%d)\n",
802+
retval, max_vectors);
803+
}
724804

725805
max_vectors = retval;
806+
mrioc->op_reply_q_offset = (max_vectors > 1) ? 1 : 0;
807+
808+
mpi3mr_calc_poll_queues(mrioc, max_vectors);
809+
726810
}
811+
727812
mrioc->intr_info = kzalloc(sizeof(struct mpi3mr_intr_info) * max_vectors,
728813
GFP_KERNEL);
729814
if (!mrioc->intr_info) {
@@ -1511,10 +1596,11 @@ static void mpi3mr_free_op_reply_q_segments(struct mpi3mr_ioc *mrioc, u16 q_idx)
15111596
static int mpi3mr_delete_op_reply_q(struct mpi3mr_ioc *mrioc, u16 qidx)
15121597
{
15131598
struct mpi3_delete_reply_queue_request delq_req;
1599+
struct op_reply_qinfo *op_reply_q = mrioc->op_reply_qinfo + qidx;
15141600
int retval = 0;
15151601
u16 reply_qid = 0, midx;
15161602

1517-
reply_qid = mrioc->op_reply_qinfo[qidx].qid;
1603+
reply_qid = op_reply_q->qid;
15181604

15191605
midx = REPLY_QUEUE_IDX_TO_MSIX_IDX(qidx, mrioc->op_reply_q_offset);
15201606

@@ -1524,6 +1610,9 @@ static int mpi3mr_delete_op_reply_q(struct mpi3mr_ioc *mrioc, u16 qidx)
15241610
goto out;
15251611
}
15261612

1613+
(op_reply_q->qtype == MPI3MR_DEFAULT_QUEUE) ? mrioc->default_qcount-- :
1614+
mrioc->active_poll_qcount--;
1615+
15271616
memset(&delq_req, 0, sizeof(delq_req));
15281617
mutex_lock(&mrioc->init_cmds.mutex);
15291618
if (mrioc->init_cmds.state & MPI3MR_CMD_PENDING) {
@@ -1748,8 +1837,26 @@ static int mpi3mr_create_op_reply_q(struct mpi3mr_ioc *mrioc, u16 qidx)
17481837
create_req.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_INITCMDS);
17491838
create_req.function = MPI3_FUNCTION_CREATE_REPLY_QUEUE;
17501839
create_req.queue_id = cpu_to_le16(reply_qid);
1751-
create_req.flags = MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_ENABLE;
1752-
create_req.msix_index = cpu_to_le16(mrioc->intr_info[midx].msix_index);
1840+
1841+
if (midx < (mrioc->intr_info_count - mrioc->requested_poll_qcount))
1842+
op_reply_q->qtype = MPI3MR_DEFAULT_QUEUE;
1843+
else
1844+
op_reply_q->qtype = MPI3MR_POLL_QUEUE;
1845+
1846+
if (op_reply_q->qtype == MPI3MR_DEFAULT_QUEUE) {
1847+
create_req.flags =
1848+
MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_ENABLE;
1849+
create_req.msix_index =
1850+
cpu_to_le16(mrioc->intr_info[midx].msix_index);
1851+
} else {
1852+
create_req.msix_index = cpu_to_le16(mrioc->intr_info_count - 1);
1853+
ioc_info(mrioc, "create reply queue(polled): for qid(%d), midx(%d)\n",
1854+
reply_qid, midx);
1855+
if (!mrioc->active_poll_qcount)
1856+
disable_irq_nosync(pci_irq_vector(mrioc->pdev,
1857+
mrioc->intr_info_count - 1));
1858+
}
1859+
17531860
if (mrioc->enable_segqueue) {
17541861
create_req.flags |=
17551862
MPI3_CREATE_REQUEST_QUEUE_FLAGS_SEGMENTED_SEGMENTED;
@@ -1790,6 +1897,9 @@ static int mpi3mr_create_op_reply_q(struct mpi3mr_ioc *mrioc, u16 qidx)
17901897
if (midx < mrioc->intr_info_count)
17911898
mrioc->intr_info[midx].op_reply_q = op_reply_q;
17921899

1900+
(op_reply_q->qtype == MPI3MR_DEFAULT_QUEUE) ? mrioc->default_qcount++ :
1901+
mrioc->active_poll_qcount++;
1902+
17931903
out_unlock:
17941904
mrioc->init_cmds.state = MPI3MR_CMD_NOTUSED;
17951905
mutex_unlock(&mrioc->init_cmds.mutex);
@@ -1970,8 +2080,10 @@ static int mpi3mr_create_op_queues(struct mpi3mr_ioc *mrioc)
19702080
goto out_failed;
19712081
}
19722082
mrioc->num_op_reply_q = mrioc->num_op_req_q = i;
1973-
ioc_info(mrioc, "Successfully created %d Operational Q pairs\n",
1974-
mrioc->num_op_reply_q);
2083+
ioc_info(mrioc,
2084+
"successfully created %d operational queue pairs(default/polled) queue = (%d/%d)\n",
2085+
mrioc->num_op_reply_q, mrioc->default_qcount,
2086+
mrioc->active_poll_qcount);
19752087

19762088
return retval;
19772089
out_failed:
@@ -2019,7 +2131,7 @@ int mpi3mr_op_request_post(struct mpi3mr_ioc *mrioc,
20192131
if (mpi3mr_check_req_qfull(op_req_q)) {
20202132
midx = REPLY_QUEUE_IDX_TO_MSIX_IDX(
20212133
reply_qidx, mrioc->op_reply_q_offset);
2022-
mpi3mr_process_op_reply_q(mrioc, &mrioc->intr_info[midx]);
2134+
mpi3mr_process_op_reply_q(mrioc, mrioc->intr_info[midx].op_reply_q);
20232135

20242136
if (mpi3mr_check_req_qfull(op_req_q)) {
20252137
retval = -EAGAIN;
@@ -3465,6 +3577,10 @@ int mpi3mr_setup_resources(struct mpi3mr_ioc *mrioc)
34653577
mrioc->sysif_regs, memap_sz);
34663578
ioc_info(mrioc, "Number of MSI-X vectors found in capabilities: (%d)\n",
34673579
mrioc->msix_count);
3580+
3581+
if (!reset_devices && poll_queues > 0)
3582+
mrioc->requested_poll_qcount = min_t(int, poll_queues,
3583+
mrioc->msix_count - 2);
34683584
return retval;
34693585

34703586
out_failed:
@@ -3826,6 +3942,8 @@ void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc)
38263942
u16 i;
38273943

38283944
mrioc->change_count = 0;
3945+
mrioc->active_poll_qcount = 0;
3946+
mrioc->default_qcount = 0;
38293947
if (mrioc->admin_req_base)
38303948
memset(mrioc->admin_req_base, 0, mrioc->admin_req_q_sz);
38313949
if (mrioc->admin_reply_base)

0 commit comments

Comments
 (0)