Commit 432bc7ca authored by Sreekanth Reddy's avatar Sreekanth Reddy Committed by Martin K. Petersen

scsi: mpt3sas: Add io_uring iopoll support

Enable the driver to work in non-IRQ mode, i.e. there will not be any MSI-X
vectors associated with queues dedicated to polling. The IOC hardware is
single submission queue and multiple reply queue. However, using the shared
host tagset support it is possible to simulate multiple hardware queues.

When poll_queues are enabled through the module parameter, the driver will
allocate extra reply queues without an MSI-X association. All I/O
completion on these queues will be done through the iopoll interface.

Link: https://lore.kernel.org/r/20210727081212.2742-1-sreekanth.reddy@broadcom.comSigned-off-by: default avatarSreekanth Reddy <sreekanth.reddy@broadcom.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent f5efd4fe
This diff is collapsed.
......@@ -354,6 +354,7 @@ struct mpt3sas_nvme_cmd {
#define MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT_G3 12
#define MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT_G35 16
#define MPT3_SUP_REPLY_POST_HOST_INDEX_REG_OFFSET (0x10)
#define MPT3_MIN_IRQS 1
/* OEM Identifiers */
#define MFG10_OEM_ID_INVALID (0x00000000)
......@@ -936,6 +937,8 @@ struct _event_ack_list {
* @os_irq: irq number
* @irqpoll: irq_poll object
* @irq_poll_scheduled: Tells whether irq poll is scheduled or not
* @is_iouring_poll_q: Tells whether reply queues is assigned
* to io uring poll queues or not
* @list: this list
*/
struct adapter_reply_queue {
......@@ -949,9 +952,22 @@ struct adapter_reply_queue {
struct irq_poll irqpoll;
bool irq_poll_scheduled;
bool irq_line_enable;
bool is_iouring_poll_q;
struct list_head list;
};
/**
* struct io_uring_poll_queue - the io uring poll queue structure
* @busy: Tells whether io uring poll queue is busy or not
* @pause: Tells whether IOs are paused on io uring poll queue or not
* @reply_q: reply queue mapped for io uring poll queue
*/
struct io_uring_poll_queue {
atomic_t busy;
atomic_t pause;
struct adapter_reply_queue *reply_q;
};
typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
/* SAS3.0 support */
......@@ -1176,6 +1192,8 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
* @schedule_dead_ioc_flush_running_cmds: callback to flush pending commands
* @thresh_hold: Max number of reply descriptors processed
* before updating Host Index
* @iopoll_q_start_index: starting index of io uring poll queues
* in reply queue list
* @drv_internal_flags: Bit map internal to driver
* @drv_support_bitmap: driver's supported feature bit map
* @use_32bit_dma: Flag to use 32 bit consistent dma mask
......@@ -1372,11 +1390,13 @@ struct MPT3SAS_ADAPTER {
bool msix_load_balance;
u16 thresh_hold;
u8 high_iops_queues;
u8 iopoll_q_start_index;
u32 drv_internal_flags;
u32 drv_support_bitmap;
u32 dma_mask;
bool enable_sdev_max_qd;
bool use_32bit_dma;
struct io_uring_poll_queue *io_uring_poll_queues;
/* internal commands, callback index */
u8 scsi_io_cb_idx;
......@@ -1730,6 +1750,9 @@ do { ioc_err(ioc, "In func: %s\n", __func__); \
status, mpi_request, sz); } while (0)
int mpt3sas_wait_for_ioc(struct MPT3SAS_ADAPTER *ioc, int wait_count);
int mpt3sas_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num);
void mpt3sas_base_pause_mq_polling(struct MPT3SAS_ADAPTER *ioc);
void mpt3sas_base_resume_mq_polling(struct MPT3SAS_ADAPTER *ioc);
/* scsih shared API */
struct scsi_cmnd *mpt3sas_scsih_scsi_lookup_get(struct MPT3SAS_ADAPTER *ioc,
......
......@@ -11178,8 +11178,10 @@ static void scsih_remove(struct pci_dev *pdev)
ioc->remove_host = 1;
if (!pci_device_is_present(pdev))
if (!pci_device_is_present(pdev)) {
mpt3sas_base_pause_mq_polling(ioc);
_scsih_flush_running_cmds(ioc);
}
_scsih_fw_event_cleanup_queue(ioc);
......@@ -11274,8 +11276,10 @@ scsih_shutdown(struct pci_dev *pdev)
ioc->remove_host = 1;
if (!pci_device_is_present(pdev))
if (!pci_device_is_present(pdev)) {
mpt3sas_base_pause_mq_polling(ioc);
_scsih_flush_running_cmds(ioc);
}
_scsih_fw_event_cleanup_queue(ioc);
......@@ -11780,12 +11784,41 @@ static int scsih_map_queues(struct Scsi_Host *shost)
{
struct MPT3SAS_ADAPTER *ioc =
(struct MPT3SAS_ADAPTER *)shost->hostdata;
struct blk_mq_queue_map *map;
int i, qoff, offset;
int nr_msix_vectors = ioc->iopoll_q_start_index;
int iopoll_q_count = ioc->reply_queue_count - nr_msix_vectors;
if (ioc->shost->nr_hw_queues == 1)
if (shost->nr_hw_queues == 1)
return 0;
return blk_mq_pci_map_queues(&shost->tag_set.map[HCTX_TYPE_DEFAULT],
ioc->pdev, ioc->high_iops_queues);
for (i = 0, qoff = 0; i < shost->nr_maps; i++) {
map = &shost->tag_set.map[i];
map->nr_queues = 0;
offset = 0;
if (i == HCTX_TYPE_DEFAULT) {
map->nr_queues =
nr_msix_vectors - ioc->high_iops_queues;
offset = ioc->high_iops_queues;
} else if (i == HCTX_TYPE_POLL)
map->nr_queues = iopoll_q_count;
if (!map->nr_queues)
BUG_ON(i == HCTX_TYPE_DEFAULT);
/*
* The poll queue(s) doesn't have an IRQ (and hence IRQ
* affinity), so use the regular blk-mq cpu mapping
*/
map->queue_offset = qoff;
if (i != HCTX_TYPE_POLL)
blk_mq_pci_map_queues(map, ioc->pdev, offset);
else
blk_mq_map_queues(map);
qoff += map->nr_queues;
}
return 0;
}
/* shost template for SAS 2.0 HBA devices */
......@@ -11856,6 +11889,7 @@ static struct scsi_host_template mpt3sas_driver_template = {
.track_queue_depth = 1,
.cmd_size = sizeof(struct scsiio_tracker),
.map_queues = scsih_map_queues,
.mq_poll = mpt3sas_blk_mq_poll,
};
/* raid transport support for SAS 3.0 HBA devices */
......@@ -11952,6 +11986,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct Scsi_Host *shost = NULL;
int rv;
u16 hba_mpi_version;
int iopoll_q_count = 0;
/* Determine in which MPI version class this pci device belongs */
hba_mpi_version = _scsih_determine_hba_mpi_version(pdev);
......@@ -12199,6 +12234,11 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_thread_fail;
}
shost->host_tagset = 0;
if (ioc->is_gen35_ioc && host_tagset_enable)
shost->host_tagset = 1;
ioc->is_driver_loading = 1;
if ((mpt3sas_base_attach(ioc))) {
ioc_err(ioc, "failure at %s:%d/%s()!\n",
......@@ -12221,16 +12261,17 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
} else
ioc->hide_drives = 0;
shost->host_tagset = 0;
shost->nr_hw_queues = 1;
if (ioc->is_gen35_ioc && ioc->reply_queue_count > 1 &&
host_tagset_enable && ioc->smp_affinity_enable) {
shost->host_tagset = 1;
if (shost->host_tagset) {
shost->nr_hw_queues =
ioc->reply_queue_count - ioc->high_iops_queues;
iopoll_q_count =
ioc->reply_queue_count - ioc->iopoll_q_start_index;
shost->nr_maps = iopoll_q_count ? 3 : 1;
dev_info(&ioc->pdev->dev,
"Max SCSIIO MPT commands: %d shared with nr_hw_queues = %d\n",
shost->can_queue, shost->nr_hw_queues);
......@@ -12354,6 +12395,7 @@ scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
/* Permanent error, prepare for device removal */
ioc->pci_error_recovery = 1;
mpt3sas_base_stop_watchdog(ioc);
mpt3sas_base_pause_mq_polling(ioc);
_scsih_flush_running_cmds(ioc);
return PCI_ERS_RESULT_DISCONNECT;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment