Commit c9566231 authored by Kashyap Desai's avatar Kashyap Desai Committed by Martin K. Petersen

scsi: mpi3mr: Create operational request and reply queue pair

Create operational request and reply queue pair.

The MPI3 transport interface consists of an Administrative Request Queue,
an Administrative Reply Queue, and Operational Messaging Queues.  The
Operational Messaging Queues are the primary communication mechanism
between the host and the I/O Controller (IOC).  Request messages, allocated
in host memory, identify I/O operations to be performed by the IOC. These
operations are queued on an Operational Request Queue by the host driver.
Reply descriptors track I/O operations as they complete.  The IOC queues
these completions in an Operational Reply Queue.

To fulfil large contiguous memory requirement, driver creates multiple
segments and provide the list of segments. Each segment size should be 4K
which is a hardware requirement. An element array is contiguous or
segmented.  A contiguous element array is located in contiguous physical
memory.  A contiguous element array must be aligned on an element size
boundary.  An element's physical address within the array may be directly
calculated from the base address, the Producer/Consumer index, and the
element size.

Expected phased identifier bit is used to find out valid entry on reply
queue. Driver sets <ephase> bit and IOC inverts the value of this bit on
each pass.

Link: https://lore.kernel.org/r/20210520152545.2710479-4-kashyap.desai@broadcom.com
Cc: sathya.prakash@broadcom.com
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Reviewed-by: default avatarTomas Henzl <thenzl@redhat.com>
Reviewed-by: default avatarHimanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: default avatarKashyap Desai <kashyap.desai@broadcom.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 824a1566
...@@ -74,6 +74,12 @@ extern struct list_head mrioc_list; ...@@ -74,6 +74,12 @@ extern struct list_head mrioc_list;
#define MPI3MR_ADMIN_REQ_FRAME_SZ 128 #define MPI3MR_ADMIN_REQ_FRAME_SZ 128
#define MPI3MR_ADMIN_REPLY_FRAME_SZ 16 #define MPI3MR_ADMIN_REPLY_FRAME_SZ 16
/* Operational queue management definitions */
#define MPI3MR_OP_REQ_Q_QD 512
#define MPI3MR_OP_REP_Q_QD 4096
#define MPI3MR_OP_REQ_Q_SEG_SIZE 4096
#define MPI3MR_OP_REP_Q_SEG_SIZE 4096
#define MPI3MR_MAX_SEG_LIST_SIZE 4096
/* Reserved Host Tag definitions */ /* Reserved Host Tag definitions */
#define MPI3MR_HOSTTAG_INVALID 0xFFFF #define MPI3MR_HOSTTAG_INVALID 0xFFFF
...@@ -135,6 +141,9 @@ extern struct list_head mrioc_list; ...@@ -135,6 +141,9 @@ extern struct list_head mrioc_list;
(MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM | \ (MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM | \
MPI3_SGE_FLAGS_END_OF_LIST) MPI3_SGE_FLAGS_END_OF_LIST)
/* MSI Index from Reply Queue Index */
#define REPLY_QUEUE_IDX_TO_MSIX_IDX(qidx, offset) (qidx + offset)
/* IOC State definitions */ /* IOC State definitions */
enum mpi3mr_iocstate { enum mpi3mr_iocstate {
MRIOC_STATE_READY = 1, MRIOC_STATE_READY = 1,
...@@ -225,15 +234,45 @@ struct mpi3mr_ioc_facts { ...@@ -225,15 +234,45 @@ struct mpi3mr_ioc_facts {
u8 sge_mod_shift; u8 sge_mod_shift;
}; };
/**
* struct segments - memory descriptor structure to store
* virtual and dma addresses for operational queue segments.
*
* @segment: virtual address
* @segment_dma: dma address
*/
struct segments {
void *segment;
dma_addr_t segment_dma;
};
/** /**
* struct op_req_qinfo - Operational Request Queue Information * struct op_req_qinfo - Operational Request Queue Information
* *
* @ci: consumer index * @ci: consumer index
* @pi: producer index * @pi: producer index
* @num_request: Maximum number of entries in the queue
* @qid: Queue Id starting from 1
* @reply_qid: Associated reply queue Id
* @num_segments: Number of discontiguous memory segments
* @segment_qd: Depth of each segments
* @q_lock: Concurrent queue access lock
* @q_segments: Segment descriptor pointer
* @q_segment_list: Segment list base virtual address
* @q_segment_list_dma: Segment list base DMA address
*/ */
struct op_req_qinfo { struct op_req_qinfo {
u16 ci; u16 ci;
u16 pi; u16 pi;
u16 num_requests;
u16 qid;
u16 reply_qid;
u16 num_segments;
u16 segment_qd;
spinlock_t q_lock;
struct segments *q_segments;
void *q_segment_list;
dma_addr_t q_segment_list_dma;
}; };
/** /**
...@@ -241,10 +280,24 @@ struct op_req_qinfo { ...@@ -241,10 +280,24 @@ struct op_req_qinfo {
* *
* @ci: consumer index * @ci: consumer index
* @qid: Queue Id starting from 1 * @qid: Queue Id starting from 1
* @num_replies: Maximum number of entries in the queue
* @num_segments: Number of discontiguous memory segments
* @segment_qd: Depth of each segments
* @q_segments: Segment descriptor pointer
* @q_segment_list: Segment list base virtual address
* @q_segment_list_dma: Segment list base DMA address
* @ephase: Expected phased identifier for the reply queue
*/ */
struct op_reply_qinfo { struct op_reply_qinfo {
u16 ci; u16 ci;
u16 qid; u16 qid;
u16 num_replies;
u16 num_segments;
u16 segment_qd;
struct segments *q_segments;
void *q_segment_list;
dma_addr_t q_segment_list_dma;
u8 ephase;
}; };
/** /**
...@@ -404,6 +457,7 @@ struct scmd_priv { ...@@ -404,6 +457,7 @@ struct scmd_priv {
* @current_event: Firmware event currently in process * @current_event: Firmware event currently in process
* @driver_info: Driver, Kernel, OS information to firmware * @driver_info: Driver, Kernel, OS information to firmware
* @change_count: Topology change count * @change_count: Topology change count
* @op_reply_q_offset: Operational reply queue offset with MSIx
*/ */
struct mpi3mr_ioc { struct mpi3mr_ioc {
struct list_head list; struct list_head list;
...@@ -411,6 +465,7 @@ struct mpi3mr_ioc { ...@@ -411,6 +465,7 @@ struct mpi3mr_ioc {
struct Scsi_Host *shost; struct Scsi_Host *shost;
u8 id; u8 id;
int cpu_count; int cpu_count;
bool enable_segqueue;
char name[MPI3MR_NAME_LENGTH]; char name[MPI3MR_NAME_LENGTH];
char driver_name[MPI3MR_NAME_LENGTH]; char driver_name[MPI3MR_NAME_LENGTH];
...@@ -497,6 +552,7 @@ struct mpi3mr_ioc { ...@@ -497,6 +552,7 @@ struct mpi3mr_ioc {
struct mpi3mr_fwevt *current_event; struct mpi3mr_fwevt *current_event;
struct mpi3_driver_info_layout driver_info; struct mpi3_driver_info_layout driver_info;
u16 change_count; u16 change_count;
u16 op_reply_q_offset;
}; };
int mpi3mr_setup_resources(struct mpi3mr_ioc *mrioc); int mpi3mr_setup_resources(struct mpi3mr_ioc *mrioc);
......
This diff is collapsed.
...@@ -40,7 +40,7 @@ static int mpi3mr_map_queues(struct Scsi_Host *shost) ...@@ -40,7 +40,7 @@ static int mpi3mr_map_queues(struct Scsi_Host *shost)
struct mpi3mr_ioc *mrioc = shost_priv(shost); struct mpi3mr_ioc *mrioc = shost_priv(shost);
return blk_mq_pci_map_queues(&shost->tag_set.map[HCTX_TYPE_DEFAULT], return blk_mq_pci_map_queues(&shost->tag_set.map[HCTX_TYPE_DEFAULT],
mrioc->pdev, 0); mrioc->pdev, mrioc->op_reply_q_offset);
} }
/** /**
...@@ -218,6 +218,8 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -218,6 +218,8 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
spin_lock_init(&mrioc->sbq_lock); spin_lock_init(&mrioc->sbq_lock);
mpi3mr_init_drv_cmd(&mrioc->init_cmds, MPI3MR_HOSTTAG_INITCMDS); mpi3mr_init_drv_cmd(&mrioc->init_cmds, MPI3MR_HOSTTAG_INITCMDS);
if (pdev->revision)
mrioc->enable_segqueue = true;
mrioc->logging_level = logging_level; mrioc->logging_level = logging_level;
mrioc->shost = shost; mrioc->shost = shost;
......
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