Message ID | 20210419110156.1786882-1-kashyap.desai@broadcom.com |
---|---|
Headers | show |
Series | Introducing mpi3mr driver | expand |
> > @@ -1924,6 +1931,12 @@ static int mpi3mr_alloc_reply_sense_bufs(struct > mpi3mr_ioc *mrioc) > > if (!mrioc->init_cmds.reply) > > goto out_failed; > > > > + for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { > > + mrioc->dev_rmhs_cmds[i].reply = kzalloc(mrioc- > >facts.reply_sz, > > + GFP_KERNEL); > > + if (!mrioc->dev_rmhs_cmds[i].reply) > > + goto out_failed; > > + } > > As I wrote in V2, the above allocation chunk ends up in twice in > mpi3mr_alloc_reply_sense_bufs. Please fix it (probably in 13/24). I missed this. Both allocation and free part of "dev_rmhs_cmds " end up in twice. I will fix it in 13/24. Kashyap
> On Apr 19, 2021, at 6:01 AM, Kashyap Desai <kashyap.desai@broadcom.com> wrote: > > 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 h/w 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 set <ephase> bit and IOC invert the value of this bit on each pass. > > Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> > Reviewed-by: Hannes Reinecke <hare@suse.de> > Reviewed-by: Tomas Henzl <thenzl@redhat.com> > > Cc: sathya.prakash@broadcom.com > --- > drivers/scsi/mpi3mr/mpi3mr.h | 56 +++ > drivers/scsi/mpi3mr/mpi3mr_fw.c | 601 ++++++++++++++++++++++++++++++++ > drivers/scsi/mpi3mr/mpi3mr_os.c | 4 +- > 3 files changed, 660 insertions(+), 1 deletion(-) > > diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h > index cf1cfea19826..c26105b23759 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr.h > +++ b/drivers/scsi/mpi3mr/mpi3mr.h > @@ -71,6 +71,12 @@ extern struct list_head mrioc_list; > #define MPI3MR_ADMIN_REQ_FRAME_SZ 128 > #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 */ > #define MPI3MR_HOSTTAG_INVALID 0xFFFF > @@ -132,6 +138,9 @@ extern struct list_head mrioc_list; > (MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM | \ > 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 */ > enum mpi3mr_iocstate { > MRIOC_STATE_READY = 1, > @@ -222,15 +231,45 @@ struct mpi3mr_ioc_facts { > 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 > * > * @ci: consumer 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 { > u16 ci; > 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; > }; > > /** > @@ -238,10 +277,24 @@ struct op_req_qinfo { > * > * @ci: consumer index > * @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 { > u16 ci; > 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; > }; > > /** > @@ -401,6 +454,7 @@ struct scmd_priv { > * @current_event: Firmware event currently in process > * @driver_info: Driver, Kernel, OS information to firmware > * @change_count: Topology change count > + * @op_reply_q_offset: Operational reply queue offset with MSIx > */ > struct mpi3mr_ioc { > struct list_head list; > @@ -408,6 +462,7 @@ struct mpi3mr_ioc { > struct Scsi_Host *shost; > u8 id; > int cpu_count; > + bool enable_segqueue; > > char name[MPI3MR_NAME_LENGTH]; > char driver_name[MPI3MR_NAME_LENGTH]; > @@ -494,6 +549,7 @@ struct mpi3mr_ioc { > struct mpi3mr_fwevt *current_event; > Mpi3DriverInfoLayout_t driver_info; > u16 change_count; > + u16 op_reply_q_offset; > }; > > int mpi3mr_setup_resources(struct mpi3mr_ioc *mrioc); > diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c > index 330f675444e9..694e54bbb07c 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c > @@ -405,6 +405,8 @@ static int mpi3mr_setup_isr(struct mpi3mr_ioc *mrioc, u8 setup_one) > > irq_flags |= PCI_IRQ_AFFINITY | PCI_IRQ_ALL_TYPES; > > + mrioc->op_reply_q_offset = (max_vectors > 1) ? 1 : 0; > + > i = pci_alloc_irq_vectors_affinity(mrioc->pdev, > 1, max_vectors, irq_flags, &desc); > if (i <= 0) { > @@ -415,6 +417,12 @@ static int mpi3mr_setup_isr(struct mpi3mr_ioc *mrioc, u8 setup_one) > ioc_info(mrioc, > "allocated vectors (%d) are less than configured (%d)\n", > i, max_vectors); > + /* > + * If only one MSI-x is allocated, then MSI-x 0 will be shared > + * between Admin queue and operational queue > + */ > + if (i == 1) > + mrioc->op_reply_q_offset = 0; > > max_vectors = i; > } > @@ -723,6 +731,586 @@ int mpi3mr_admin_request_post(struct mpi3mr_ioc *mrioc, void *admin_req, > return retval; > } > > +/** > + * mpi3mr_free_op_req_q_segments - free request memory segments > + * @mrioc: Adapter instance reference > + * @q_idx: operational request queue index > + * > + * Free memory segments allocated for operational request queue > + * > + * Return: Nothing. > + */ > +static void mpi3mr_free_op_req_q_segments(struct mpi3mr_ioc *mrioc, u16 q_idx) > +{ > + u16 j; > + int size; > + struct segments *segments; > + > + segments = mrioc->req_qinfo[q_idx].q_segments; > + if (!segments) > + return; > + > + if (mrioc->enable_segqueue) { > + size = MPI3MR_OP_REQ_Q_SEG_SIZE; > + if (mrioc->req_qinfo[q_idx].q_segment_list) { > + dma_free_coherent(&mrioc->pdev->dev, > + MPI3MR_MAX_SEG_LIST_SIZE, > + mrioc->req_qinfo[q_idx].q_segment_list, > + mrioc->req_qinfo[q_idx].q_segment_list_dma); > + mrioc->op_reply_qinfo[q_idx].q_segment_list = NULL; > + } > + } else > + size = mrioc->req_qinfo[q_idx].num_requests * > + mrioc->facts.op_req_sz; > + > + for (j = 0; j < mrioc->req_qinfo[q_idx].num_segments; j++) { > + if (!segments[j].segment) > + continue; > + dma_free_coherent(&mrioc->pdev->dev, > + size, segments[j].segment, segments[j].segment_dma); > + segments[j].segment = NULL; > + } > + kfree(mrioc->req_qinfo[q_idx].q_segments); > + mrioc->req_qinfo[q_idx].q_segments = NULL; > + mrioc->req_qinfo[q_idx].qid = 0; > +} > + > +/** > + * mpi3mr_free_op_reply_q_segments - free reply memory segments > + * @mrioc: Adapter instance reference > + * @q_idx: operational reply queue index > + * > + * Free memory segments allocated for operational reply queue > + * > + * Return: Nothing. > + */ > +static void mpi3mr_free_op_reply_q_segments(struct mpi3mr_ioc *mrioc, u16 q_idx) > +{ > + u16 j; > + int size; > + struct segments *segments; > + > + segments = mrioc->op_reply_qinfo[q_idx].q_segments; > + if (!segments) > + return; > + > + if (mrioc->enable_segqueue) { > + size = MPI3MR_OP_REP_Q_SEG_SIZE; > + if (mrioc->op_reply_qinfo[q_idx].q_segment_list) { > + dma_free_coherent(&mrioc->pdev->dev, > + MPI3MR_MAX_SEG_LIST_SIZE, > + mrioc->op_reply_qinfo[q_idx].q_segment_list, > + mrioc->op_reply_qinfo[q_idx].q_segment_list_dma); > + mrioc->op_reply_qinfo[q_idx].q_segment_list = NULL; > + } > + } else > + size = mrioc->op_reply_qinfo[q_idx].segment_qd * > + mrioc->op_reply_desc_sz; > + > + for (j = 0; j < mrioc->op_reply_qinfo[q_idx].num_segments; j++) { > + if (!segments[j].segment) > + continue; > + dma_free_coherent(&mrioc->pdev->dev, > + size, segments[j].segment, segments[j].segment_dma); > + segments[j].segment = NULL; > + } > + > + kfree(mrioc->op_reply_qinfo[q_idx].q_segments); > + mrioc->op_reply_qinfo[q_idx].q_segments = NULL; > + mrioc->op_reply_qinfo[q_idx].qid = 0; > +} > + > +/** > + * mpi3mr_delete_op_reply_q - delete operational reply queue > + * @mrioc: Adapter instance reference > + * @qidx: operational reply queue index > + * > + * Delete operatinal reply queue by issuing MPI request > + * through admin queue. > + * > + * Return: 0 on success, non-zero on failure. > + */ > +static int mpi3mr_delete_op_reply_q(struct mpi3mr_ioc *mrioc, u16 qidx) > +{ > + Mpi3DeleteReplyQueueRequest_t delq_req; > + int retval = 0; > + u16 reply_qid = 0, midx; > + > + reply_qid = mrioc->op_reply_qinfo[qidx].qid; > + > + midx = REPLY_QUEUE_IDX_TO_MSIX_IDX(qidx, mrioc->op_reply_q_offset); > + > + if (!reply_qid) { > + retval = -1; > + ioc_err(mrioc, "Issue DelRepQ: called with invalid ReqQID\n"); > + goto out; > + } > + > + memset(&delq_req, 0, sizeof(delq_req)); > + mutex_lock(&mrioc->init_cmds.mutex); > + if (mrioc->init_cmds.state & MPI3MR_CMD_PENDING) { > + retval = -1; > + ioc_err(mrioc, "Issue DelRepQ: Init command is in use\n"); > + mutex_unlock(&mrioc->init_cmds.mutex); > + goto out; > + } > + mrioc->init_cmds.state = MPI3MR_CMD_PENDING; > + mrioc->init_cmds.is_waiting = 1; > + mrioc->init_cmds.callback = NULL; > + delq_req.HostTag = cpu_to_le16(MPI3MR_HOSTTAG_INITCMDS); > + delq_req.Function = MPI3_FUNCTION_DELETE_REPLY_QUEUE; > + delq_req.QueueID = cpu_to_le16(reply_qid); > + > + init_completion(&mrioc->init_cmds.done); > + retval = mpi3mr_admin_request_post(mrioc, &delq_req, sizeof(delq_req), > + 1); > + if (retval) { > + ioc_err(mrioc, "Issue DelRepQ: Admin Post failed\n"); > + goto out_unlock; > + } > + wait_for_completion_timeout(&mrioc->init_cmds.done, > + (MPI3MR_INTADMCMD_TIMEOUT * HZ)); > + if (!(mrioc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { > + ioc_err(mrioc, "Issue DelRepQ: command timed out\n"); > + mpi3mr_set_diagsave(mrioc); > + mpi3mr_issue_reset(mrioc, > + MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, > + MPI3MR_RESET_FROM_DELREPQ_TIMEOUT); > + mrioc->unrecoverable = 1; > + > + retval = -1; > + goto out_unlock; > + } > + if ((mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) > + != MPI3_IOCSTATUS_SUCCESS) { > + ioc_err(mrioc, > + "Issue DelRepQ: Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n", > + (mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), > + mrioc->init_cmds.ioc_loginfo); > + retval = -1; > + goto out_unlock; > + } > + mrioc->intr_info[midx].op_reply_q = NULL; > + > + mpi3mr_free_op_reply_q_segments(mrioc, qidx); > +out_unlock: > + mrioc->init_cmds.state = MPI3MR_CMD_NOTUSED; > + mutex_unlock(&mrioc->init_cmds.mutex); > +out: > + > + return retval; > +} > + > +/** > + * mpi3mr_alloc_op_reply_q_segments -Alloc segmented reply pool > + * @mrioc: Adapter instance reference > + * @qidx: request queue index > + * > + * Allocate segmented memory pools for operational reply > + * queue. > + * > + * Return: 0 on success, non-zero on failure. > + */ > +static int mpi3mr_alloc_op_reply_q_segments(struct mpi3mr_ioc *mrioc, u16 qidx) > +{ > + struct op_reply_qinfo *op_reply_q = mrioc->op_reply_qinfo + qidx; > + int i, size; > + u64 *q_segment_list_entry = NULL; > + struct segments *segments; > + > + if (mrioc->enable_segqueue) { > + op_reply_q->segment_qd = > + MPI3MR_OP_REP_Q_SEG_SIZE / mrioc->op_reply_desc_sz; > + > + size = MPI3MR_OP_REP_Q_SEG_SIZE; > + > + op_reply_q->q_segment_list = dma_alloc_coherent(&mrioc->pdev->dev, > + MPI3MR_MAX_SEG_LIST_SIZE, &op_reply_q->q_segment_list_dma, > + GFP_KERNEL); > + if (!op_reply_q->q_segment_list) > + return -ENOMEM; > + q_segment_list_entry = (u64 *)op_reply_q->q_segment_list; > + } else { > + op_reply_q->segment_qd = op_reply_q->num_replies; > + size = op_reply_q->num_replies * mrioc->op_reply_desc_sz; > + } > + > + op_reply_q->num_segments = DIV_ROUND_UP(op_reply_q->num_replies, > + op_reply_q->segment_qd); > + > + op_reply_q->q_segments = kcalloc(op_reply_q->num_segments, > + sizeof(struct segments), GFP_KERNEL); > + if (!op_reply_q->q_segments) > + return -ENOMEM; > + > + segments = op_reply_q->q_segments; > + for (i = 0; i < op_reply_q->num_segments; i++) { > + segments[i].segment = > + dma_alloc_coherent(&mrioc->pdev->dev, > + size, &segments[i].segment_dma, GFP_KERNEL); > + if (!segments[i].segment) > + return -ENOMEM; > + if (mrioc->enable_segqueue) > + q_segment_list_entry[i] = > + (unsigned long)segments[i].segment_dma; > + } > + > + return 0; > +} > + > +/** > + * mpi3mr_alloc_op_req_q_segments - Alloc segmented req pool. > + * @mrioc: Adapter instance reference > + * @qidx: request queue index > + * > + * Allocate segmented memory pools for operational request > + * queue. > + * > + * Return: 0 on success, non-zero on failure. > + */ > +static int mpi3mr_alloc_op_req_q_segments(struct mpi3mr_ioc *mrioc, u16 qidx) > +{ > + struct op_req_qinfo *op_req_q = mrioc->req_qinfo + qidx; > + int i, size; > + u64 *q_segment_list_entry = NULL; > + struct segments *segments; > + > + if (mrioc->enable_segqueue) { > + op_req_q->segment_qd = > + MPI3MR_OP_REQ_Q_SEG_SIZE / mrioc->facts.op_req_sz; > + > + size = MPI3MR_OP_REQ_Q_SEG_SIZE; > + > + op_req_q->q_segment_list = dma_alloc_coherent(&mrioc->pdev->dev, > + MPI3MR_MAX_SEG_LIST_SIZE, &op_req_q->q_segment_list_dma, > + GFP_KERNEL); > + if (!op_req_q->q_segment_list) > + return -ENOMEM; > + q_segment_list_entry = (u64 *)op_req_q->q_segment_list; > + > + } else { > + op_req_q->segment_qd = op_req_q->num_requests; > + size = op_req_q->num_requests * mrioc->facts.op_req_sz; > + } > + > + op_req_q->num_segments = DIV_ROUND_UP(op_req_q->num_requests, > + op_req_q->segment_qd); > + > + op_req_q->q_segments = kcalloc(op_req_q->num_segments, > + sizeof(struct segments), GFP_KERNEL); > + if (!op_req_q->q_segments) > + return -ENOMEM; > + > + segments = op_req_q->q_segments; > + for (i = 0; i < op_req_q->num_segments; i++) { > + segments[i].segment = > + dma_alloc_coherent(&mrioc->pdev->dev, > + size, &segments[i].segment_dma, GFP_KERNEL); > + if (!segments[i].segment) > + return -ENOMEM; > + if (mrioc->enable_segqueue) > + q_segment_list_entry[i] = > + (unsigned long)segments[i].segment_dma; > + } > + > + return 0; > +} > + > +/** > + * mpi3mr_create_op_reply_q - create operational reply queue > + * @mrioc: Adapter instance reference > + * @qidx: operational reply queue index > + * > + * Create operatinal reply queue by issuing MPI request > + * through admin queue. > + * > + * Return: 0 on success, non-zero on failure. > + */ > +static int mpi3mr_create_op_reply_q(struct mpi3mr_ioc *mrioc, u16 qidx) > +{ > + Mpi3CreateReplyQueueRequest_t create_req; > + struct op_reply_qinfo *op_reply_q = mrioc->op_reply_qinfo + qidx; > + int retval = 0; > + u16 reply_qid = 0, midx; > + > + > + reply_qid = op_reply_q->qid; > + > + midx = REPLY_QUEUE_IDX_TO_MSIX_IDX(qidx, mrioc->op_reply_q_offset); > + > + if (reply_qid) { > + retval = -1; > + ioc_err(mrioc, "CreateRepQ: called for duplicate qid %d\n", > + reply_qid); > + > + return retval; > + } > + > + reply_qid = qidx + 1; > + op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD; > + op_reply_q->ci = 0; > + op_reply_q->ephase = 1; > + > + if (!op_reply_q->q_segments) { > + retval = mpi3mr_alloc_op_reply_q_segments(mrioc, qidx); > + if (retval) { > + mpi3mr_free_op_reply_q_segments(mrioc, qidx); > + goto out; > + } > + } > + > + memset(&create_req, 0, sizeof(create_req)); > + mutex_lock(&mrioc->init_cmds.mutex); > + if (mrioc->init_cmds.state & MPI3MR_CMD_PENDING) { > + retval = -1; > + ioc_err(mrioc, "CreateRepQ: Init command is in use\n"); > + goto out; > + } > + mrioc->init_cmds.state = MPI3MR_CMD_PENDING; > + mrioc->init_cmds.is_waiting = 1; > + mrioc->init_cmds.callback = NULL; > + create_req.HostTag = cpu_to_le16(MPI3MR_HOSTTAG_INITCMDS); > + create_req.Function = MPI3_FUNCTION_CREATE_REPLY_QUEUE; > + create_req.QueueID = cpu_to_le16(reply_qid); > + create_req.Flags = MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_ENABLE; > + create_req.MSIxIndex = cpu_to_le16(mrioc->intr_info[midx].msix_index); > + if (mrioc->enable_segqueue) { > + create_req.Flags |= > + MPI3_CREATE_REQUEST_QUEUE_FLAGS_SEGMENTED_SEGMENTED; > + create_req.BaseAddress = cpu_to_le64( > + op_reply_q->q_segment_list_dma); > + } else > + create_req.BaseAddress = cpu_to_le64( > + op_reply_q->q_segments[0].segment_dma); > + > + create_req.Size = cpu_to_le16(op_reply_q->num_replies); > + > + init_completion(&mrioc->init_cmds.done); > + retval = mpi3mr_admin_request_post(mrioc, &create_req, > + sizeof(create_req), 1); > + if (retval) { > + ioc_err(mrioc, "CreateRepQ: Admin Post failed\n"); > + goto out_unlock; > + } > + wait_for_completion_timeout(&mrioc->init_cmds.done, > + (MPI3MR_INTADMCMD_TIMEOUT * HZ)); > + if (!(mrioc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { > + ioc_err(mrioc, "CreateRepQ: command timed out\n"); > + mpi3mr_set_diagsave(mrioc); > + mpi3mr_issue_reset(mrioc, > + MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, > + MPI3MR_RESET_FROM_CREATEREPQ_TIMEOUT); > + mrioc->unrecoverable = 1; > + retval = -1; > + goto out_unlock; > + } > + if ((mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) > + != MPI3_IOCSTATUS_SUCCESS) { > + ioc_err(mrioc, > + "CreateRepQ: Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n", > + (mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), > + mrioc->init_cmds.ioc_loginfo); > + retval = -1; > + goto out_unlock; > + } > + op_reply_q->qid = reply_qid; > + mrioc->intr_info[midx].op_reply_q = op_reply_q; > + > +out_unlock: > + mrioc->init_cmds.state = MPI3MR_CMD_NOTUSED; > + mutex_unlock(&mrioc->init_cmds.mutex); > +out: > + > + return retval; > +} > + > +/** > + * mpi3mr_create_op_req_q - create operational request queue > + * @mrioc: Adapter instance reference > + * @idx: operational request queue index > + * @reply_qid: Reply queue ID > + * > + * Create operatinal request queue by issuing MPI request > + * through admin queue. > + * > + * Return: 0 on success, non-zero on failure. > + */ > +static int mpi3mr_create_op_req_q(struct mpi3mr_ioc *mrioc, u16 idx, > + u16 reply_qid) > +{ > + Mpi3CreateRequestQueueRequest_t create_req; > + struct op_req_qinfo *op_req_q = mrioc->req_qinfo + idx; > + int retval = 0; > + u16 req_qid = 0; > + > + > + req_qid = op_req_q->qid; > + > + if (req_qid) { > + retval = -1; > + ioc_err(mrioc, "CreateReqQ: called for duplicate qid %d\n", > + req_qid); > + > + return retval; > + } > + req_qid = idx + 1; > + > + op_req_q->num_requests = MPI3MR_OP_REQ_Q_QD; > + op_req_q->ci = 0; > + op_req_q->pi = 0; > + op_req_q->reply_qid = reply_qid; > + spin_lock_init(&op_req_q->q_lock); > + > + if (!op_req_q->q_segments) { > + retval = mpi3mr_alloc_op_req_q_segments(mrioc, idx); > + if (retval) { > + mpi3mr_free_op_req_q_segments(mrioc, idx); > + goto out; > + } > + } > + > + memset(&create_req, 0, sizeof(create_req)); > + mutex_lock(&mrioc->init_cmds.mutex); > + if (mrioc->init_cmds.state & MPI3MR_CMD_PENDING) { > + retval = -1; > + ioc_err(mrioc, "CreateReqQ: Init command is in use\n"); > + goto out; > + } > + mrioc->init_cmds.state = MPI3MR_CMD_PENDING; > + mrioc->init_cmds.is_waiting = 1; > + mrioc->init_cmds.callback = NULL; > + create_req.HostTag = cpu_to_le16(MPI3MR_HOSTTAG_INITCMDS); > + create_req.Function = MPI3_FUNCTION_CREATE_REQUEST_QUEUE; > + create_req.QueueID = cpu_to_le16(req_qid); > + if (mrioc->enable_segqueue) { > + create_req.Flags = > + MPI3_CREATE_REQUEST_QUEUE_FLAGS_SEGMENTED_SEGMENTED; > + create_req.BaseAddress = cpu_to_le64( > + op_req_q->q_segment_list_dma); > + } else > + create_req.BaseAddress = cpu_to_le64( > + op_req_q->q_segments[0].segment_dma); > + create_req.ReplyQueueID = cpu_to_le16(reply_qid); > + create_req.Size = cpu_to_le16(op_req_q->num_requests); > + > + init_completion(&mrioc->init_cmds.done); > + retval = mpi3mr_admin_request_post(mrioc, &create_req, > + sizeof(create_req), 1); > + if (retval) { > + ioc_err(mrioc, "CreateReqQ: Admin Post failed\n"); > + goto out_unlock; > + } > + wait_for_completion_timeout(&mrioc->init_cmds.done, > + (MPI3MR_INTADMCMD_TIMEOUT * HZ)); > + if (!(mrioc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { > + ioc_err(mrioc, "CreateReqQ: command timed out\n"); > + mpi3mr_set_diagsave(mrioc); > + if (mpi3mr_issue_reset(mrioc, > + MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, > + MPI3MR_RESET_FROM_CREATEREQQ_TIMEOUT)) > + mrioc->unrecoverable = 1; > + retval = -1; > + goto out_unlock; > + } > + if ((mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) > + != MPI3_IOCSTATUS_SUCCESS) { > + ioc_err(mrioc, > + "CreateReqQ: Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n", > + (mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), > + mrioc->init_cmds.ioc_loginfo); > + retval = -1; > + goto out_unlock; > + } > + op_req_q->qid = req_qid; > + > +out_unlock: > + mrioc->init_cmds.state = MPI3MR_CMD_NOTUSED; > + mutex_unlock(&mrioc->init_cmds.mutex); > +out: > + > + return retval; > +} > + > +/** > + * mpi3mr_create_op_queues - create operational queue pairs > + * @mrioc: Adapter instance reference > + * > + * Allocate memory for operational queue meta data and call > + * create request and reply queue functions. > + * > + * Return: 0 on success, non-zero on failures. > + */ > +static int mpi3mr_create_op_queues(struct mpi3mr_ioc *mrioc) > +{ > + int retval = 0; > + u16 num_queues = 0, i = 0, msix_count_op_q = 1; > + > + num_queues = min_t(int, mrioc->facts.max_op_reply_q, > + mrioc->facts.max_op_req_q); > + > + msix_count_op_q = > + mrioc->intr_info_count - mrioc->op_reply_q_offset; > + if (!mrioc->num_queues) > + mrioc->num_queues = min_t(int, num_queues, msix_count_op_q); > + num_queues = mrioc->num_queues; > + ioc_info(mrioc, "Trying to create %d Operational Q pairs\n", > + num_queues); > + > + if (!mrioc->req_qinfo) { > + mrioc->req_qinfo = kcalloc(num_queues, > + sizeof(struct op_req_qinfo), GFP_KERNEL); > + if (!mrioc->req_qinfo) { > + retval = -1; > + goto out_failed; > + } > + > + mrioc->op_reply_qinfo = kzalloc(sizeof(struct op_reply_qinfo) * > + num_queues, GFP_KERNEL); > + if (!mrioc->op_reply_qinfo) { > + retval = -1; > + goto out_failed; > + } > + } > + > + if (mrioc->enable_segqueue) > + ioc_info(mrioc, > + "allocating operational queues through segmented queues\n"); > + > + for (i = 0; i < num_queues; i++) { > + if (mpi3mr_create_op_reply_q(mrioc, i)) { > + ioc_err(mrioc, "Cannot create OP RepQ %d\n", i); > + break; > + } > + if (mpi3mr_create_op_req_q(mrioc, i, > + mrioc->op_reply_qinfo[i].qid)) { > + ioc_err(mrioc, "Cannot create OP ReqQ %d\n", i); > + mpi3mr_delete_op_reply_q(mrioc, i); > + break; > + } > + } > + > + if (i == 0) { > + /* Not even one queue is created successfully*/ > + retval = -1; > + goto out_failed; > + } > + mrioc->num_op_reply_q = mrioc->num_op_req_q = i; > + ioc_info(mrioc, "Successfully created %d Operational Q pairs\n", > + mrioc->num_op_reply_q); > + > + > + return retval; > +out_failed: > + kfree(mrioc->req_qinfo); > + mrioc->req_qinfo = NULL; > + > + kfree(mrioc->op_reply_qinfo); > + mrioc->op_reply_qinfo = NULL; > + > + > + return retval; > +} > + > > /** > * mpi3mr_setup_admin_qpair - Setup admin queue pair > @@ -1598,6 +2186,13 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc) > goto out_failed; > } > > + retval = mpi3mr_create_op_queues(mrioc); > + if (retval) { > + ioc_err(mrioc, "Failed to create OpQueues error %d\n", > + retval); > + goto out_failed; > + } > + > return retval; > > out_failed: > @@ -1654,6 +2249,12 @@ static void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc) > mrioc->reply_free_q_pool = NULL; > } > > + for (i = 0; i < mrioc->num_op_req_q; i++) > + mpi3mr_free_op_req_q_segments(mrioc, i); > + > + for (i = 0; i < mrioc->num_op_reply_q; i++) > + mpi3mr_free_op_reply_q_segments(mrioc, i); > + > for (i = 0; i < mrioc->intr_info_count; i++) { > intr_info = mrioc->intr_info + i; > if (intr_info) > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c > index c31ec9883152..3cf0be63842f 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > @@ -41,7 +41,7 @@ static int mpi3mr_map_queues(struct Scsi_Host *shost) > struct mpi3mr_ioc *mrioc = shost_priv(shost); > > return blk_mq_pci_map_queues(&shost->tag_set.map[HCTX_TYPE_DEFAULT], > - mrioc->pdev, 0); > + mrioc->pdev, mrioc->op_reply_q_offset); > } > > /** > @@ -220,6 +220,8 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) > spin_lock_init(&mrioc->sbq_lock); > > mpi3mr_init_drv_cmd(&mrioc->init_cmds, MPI3MR_HOSTTAG_INITCMDS); > + if (pdev->revision) > + mrioc->enable_segqueue = true; > > mrioc->logging_level = logging_level; > mrioc->shost = shost; > -- > 2.18.1 > Looks Good. Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> -- Himanshu Madhani Oracle Linux Engineering
> On Apr 19, 2021, at 6:01 AM, Kashyap Desai <kashyap.desai@broadcom.com> wrote: > > Watchdog thread is driver's internal thread which does few things like > detecting FW fault and reset the controller, Timestamp sync etc. > > Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> > Reviewed-by: Hannes Reinecke <hare@suse.de> > Reviewed-by: Tomas Henzl <thenzl@redhat.com> > > Cc: sathya.prakash@broadcom.com > --- > drivers/scsi/mpi3mr/mpi3mr.h | 11 +++ > drivers/scsi/mpi3mr/mpi3mr_fw.c | 125 ++++++++++++++++++++++++++++++++ > drivers/scsi/mpi3mr/mpi3mr_os.c | 3 + > 3 files changed, 139 insertions(+) > > diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h > index 00a1b63a6e16..7769ba16c9bc 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr.h > +++ b/drivers/scsi/mpi3mr/mpi3mr.h > @@ -478,6 +478,10 @@ struct scmd_priv { > * @sense_buf_q_dma: Sense buffer queue DMA address > * @sbq_lock: Sense buffer queue lock > * @sbq_host_index: Sense buffer queuehost index > + * @watchdog_work_q_name: Fault watchdog worker thread name > + * @watchdog_work_q: Fault watchdog worker thread > + * @watchdog_work: Fault watchdog work > + * @watchdog_lock: Fault watchdog lock > * @is_driver_loading: Is driver still loading > * @scan_started: Async scan started > * @scan_failed: Asycn scan failed > @@ -491,6 +495,7 @@ struct scmd_priv { > * @chain_buf_lock: Chain buffer list lock > * @reset_in_progress: Reset in progress flag > * @unrecoverable: Controller unrecoverable flag > + * @diagsave_timeout: Diagnostic information save timeout > * @logging_level: Controller debug logging level > * @current_event: Firmware event currently in process > * @driver_info: Driver, Kernel, OS information to firmware > @@ -572,6 +577,11 @@ struct mpi3mr_ioc { > spinlock_t sbq_lock; > u32 sbq_host_index; > > + char watchdog_work_q_name[20]; > + struct workqueue_struct *watchdog_work_q; > + struct delayed_work watchdog_work; > + spinlock_t watchdog_lock; > + > u8 is_driver_loading; > u8 scan_started; > u16 scan_failed; > @@ -589,6 +599,7 @@ struct mpi3mr_ioc { > u8 reset_in_progress; > u8 unrecoverable; > > + u16 diagsave_timeout; > int logging_level; > > struct mpi3mr_fwevt *current_event; > diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c > index 787483fc60eb..4c45e12154d6 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c > @@ -1475,6 +1475,129 @@ int mpi3mr_op_request_post(struct mpi3mr_ioc *mrioc, > return retval; > } > > +/** > + * mpi3mr_watchdog_work - watchdog thread to monitor faults > + * @work: work struct > + * > + * Watch dog work periodically executed (1 second interval) to > + * monitor firmware fault and to issue periodic timer sync to > + * the firmware. > + * > + * Return: Nothing. > + */ > +static void mpi3mr_watchdog_work(struct work_struct *work) > +{ > + struct mpi3mr_ioc *mrioc = > + container_of(work, struct mpi3mr_ioc, watchdog_work.work); > + unsigned long flags; > + enum mpi3mr_iocstate ioc_state; > + u32 fault, host_diagnostic; > + > + /*Check for fault state every one second and issue Soft reset*/ > + ioc_state = mpi3mr_get_iocstate(mrioc); > + if (ioc_state == MRIOC_STATE_FAULT) { > + fault = readl(&mrioc->sysif_regs->Fault) & > + MPI3_SYSIF_FAULT_CODE_MASK; > + host_diagnostic = readl(&mrioc->sysif_regs->HostDiagnostic); > + if (host_diagnostic & MPI3_SYSIF_HOST_DIAG_SAVE_IN_PROGRESS) { > + if (!mrioc->diagsave_timeout) { > + mpi3mr_print_fault_info(mrioc); > + ioc_warn(mrioc, "Diag save in progress\n"); > + } > + if ((mrioc->diagsave_timeout++) <= > + MPI3_SYSIF_DIAG_SAVE_TIMEOUT) > + goto schedule_work; > + } else > + mpi3mr_print_fault_info(mrioc); > + mrioc->diagsave_timeout = 0; > + > + if (fault == MPI3_SYSIF_FAULT_CODE_FACTORY_RESET) { > + ioc_info(mrioc, > + "Factory Reset Fault occurred marking controller as unrecoverable" > + ); > + mrioc->unrecoverable = 1; > + goto out; > + } > + > + if ((fault == MPI3_SYSIF_FAULT_CODE_DIAG_FAULT_RESET) > + || (fault == MPI3_SYSIF_FAULT_CODE_SOFT_RESET_IN_PROGRESS) > + || (mrioc->reset_in_progress)) > + goto out; > + if (fault == MPI3_SYSIF_FAULT_CODE_CI_ACTIVATION_RESET) > + mpi3mr_soft_reset_handler(mrioc, > + MPI3MR_RESET_FROM_CIACTIV_FAULT, 0); > + else > + mpi3mr_soft_reset_handler(mrioc, > + MPI3MR_RESET_FROM_FAULT_WATCH, 0); > + } > + > +schedule_work: > + spin_lock_irqsave(&mrioc->watchdog_lock, flags); > + if (mrioc->watchdog_work_q) > + queue_delayed_work(mrioc->watchdog_work_q, > + &mrioc->watchdog_work, > + msecs_to_jiffies(MPI3MR_WATCHDOG_INTERVAL)); > + spin_unlock_irqrestore(&mrioc->watchdog_lock, flags); > +out: > + return; > +} > + > +/** > + * mpi3mr_start_watchdog - Start watchdog > + * @mrioc: Adapter instance reference > + * > + * Create and start the watchdog thread to monitor controller > + * faults. > + * > + * Return: Nothing. > + */ > +void mpi3mr_start_watchdog(struct mpi3mr_ioc *mrioc) > +{ > + if (mrioc->watchdog_work_q) > + return; > + > + INIT_DELAYED_WORK(&mrioc->watchdog_work, mpi3mr_watchdog_work); > + snprintf(mrioc->watchdog_work_q_name, > + sizeof(mrioc->watchdog_work_q_name), "watchdog_%s%d", mrioc->name, > + mrioc->id); > + mrioc->watchdog_work_q = > + create_singlethread_workqueue(mrioc->watchdog_work_q_name); > + if (!mrioc->watchdog_work_q) { > + ioc_err(mrioc, "%s: failed (line=%d)\n", __func__, __LINE__); > + return; > + } > + > + if (mrioc->watchdog_work_q) > + queue_delayed_work(mrioc->watchdog_work_q, > + &mrioc->watchdog_work, > + msecs_to_jiffies(MPI3MR_WATCHDOG_INTERVAL)); > +} > + > +/** > + * mpi3mr_stop_watchdog - Stop watchdog > + * @mrioc: Adapter instance reference > + * > + * Stop the watchdog thread created to monitor controller > + * faults. > + * > + * Return: Nothing. > + */ > +void mpi3mr_stop_watchdog(struct mpi3mr_ioc *mrioc) > +{ > + unsigned long flags; > + struct workqueue_struct *wq; > + > + spin_lock_irqsave(&mrioc->watchdog_lock, flags); > + wq = mrioc->watchdog_work_q; > + mrioc->watchdog_work_q = NULL; > + spin_unlock_irqrestore(&mrioc->watchdog_lock, flags); > + if (wq) { > + if (!cancel_delayed_work_sync(&mrioc->watchdog_work)) > + flush_workqueue(wq); > + destroy_workqueue(wq); > + } > +} > + > > /** > * mpi3mr_setup_admin_qpair - Setup admin queue pair > @@ -2631,6 +2754,8 @@ void mpi3mr_cleanup_ioc(struct mpi3mr_ioc *mrioc) > { > enum mpi3mr_iocstate ioc_state; > > + mpi3mr_stop_watchdog(mrioc); > + > mpi3mr_ioc_disable_intr(mrioc); > > ioc_state = mpi3mr_get_iocstate(mrioc); > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c > index 01be5f337826..7b0d52481929 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > @@ -570,6 +570,7 @@ static int mpi3mr_scan_finished(struct Scsi_Host *shost, > if (mrioc->scan_started) > return 0; > ioc_info(mrioc, "%s :port enable: SUCCESS\n", __func__); > + mpi3mr_start_watchdog(mrioc); > mrioc->is_driver_loading = 0; > > return 1; > @@ -856,9 +857,11 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) > spin_lock_init(&mrioc->admin_req_lock); > spin_lock_init(&mrioc->reply_free_queue_lock); > spin_lock_init(&mrioc->sbq_lock); > + spin_lock_init(&mrioc->watchdog_lock); > spin_lock_init(&mrioc->chain_buf_lock); > > mpi3mr_init_drv_cmd(&mrioc->init_cmds, MPI3MR_HOSTTAG_INITCMDS); > + > if (pdev->revision) > mrioc->enable_segqueue = true; > > -- > 2.18.1 > Looks Good. Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> -- Himanshu Madhani Oracle Linux Engineering
> On Apr 19, 2021, at 6:01 AM, Kashyap Desai <kashyap.desai@broadcom.com> wrote: > > Firmware can report various MPI Events. > Support for certain Events (as listed below) are enabled in the driver > and their processing in driver is covered in this patch. > > MPI3_EVENT_DEVICE_ADDED > MPI3_EVENT_DEVICE_INFO_CHANGED > MPI3_EVENT_DEVICE_STATUS_CHANGE > MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE > MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST > MPI3_EVENT_SAS_DISCOVERY > MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR > > Key support in this patch is device add/removal. > > Fix some compilation warning reported by kernel test robot. > > Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> > Reported-by: kernel test robot <lkp@intel.com> > Reviewed-by: Tomas Henzl <thenzl@redhat.com> > > Cc: sathya.prakash@broadcom.com > --- > drivers/scsi/mpi3mr/mpi/mpi30_api.h | 2 + > drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h | 2721 ++++++++++++++++++++++++++ > drivers/scsi/mpi3mr/mpi/mpi30_sas.h | 46 + > drivers/scsi/mpi3mr/mpi3mr.h | 202 ++ > drivers/scsi/mpi3mr/mpi3mr_fw.c | 195 +- > drivers/scsi/mpi3mr/mpi3mr_os.c | 1454 +++++++++++++- > 6 files changed, 4618 insertions(+), 2 deletions(-) > create mode 100644 drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h > create mode 100644 drivers/scsi/mpi3mr/mpi/mpi30_sas.h > > diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_api.h b/drivers/scsi/mpi3mr/mpi/mpi30_api.h > index 46dd30ccb5f9..40409e22b268 100644 > --- a/drivers/scsi/mpi3mr/mpi/mpi30_api.h > +++ b/drivers/scsi/mpi3mr/mpi/mpi30_api.h > @@ -14,8 +14,10 @@ > > #include "mpi30_type.h" > #include "mpi30_transport.h" > +#include "mpi30_cnfg.h" > #include "mpi30_image.h" > #include "mpi30_init.h" > #include "mpi30_ioc.h" > +#include "mpi30_sas.h" > > #endif /* MPI30_API_H */ > diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h b/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h > new file mode 100644 > index 000000000000..3badb1bb85b1 > --- /dev/null > +++ b/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h > @@ -0,0 +1,2721 @@ > +/* > + * Copyright 2017-2020 Broadcom Inc. All rights reserved. > + * > + * Name: mpi30_cnfg.h > + * Description: Contains definitions for Configuration messages and pages > + * Creation Date: 03/15/2017 > + * Version: 03.00.00 > + */ > +#ifndef MPI30_CNFG_H > +#define MPI30_CNFG_H 1 > + > +/***************************************************************************** > + * Configuration Page Types * > + ****************************************************************************/ > +#define MPI3_CONFIG_PAGETYPE_IO_UNIT (0x00) > +#define MPI3_CONFIG_PAGETYPE_MANUFACTURING (0x01) > +#define MPI3_CONFIG_PAGETYPE_IOC (0x02) > +#define MPI3_CONFIG_PAGETYPE_UEFI_BSD (0x03) > +#define MPI3_CONFIG_PAGETYPE_SECURITY (0x04) > +#define MPI3_CONFIG_PAGETYPE_ENCLOSURE (0x11) > +#define MPI3_CONFIG_PAGETYPE_DEVICE (0x12) > +#define MPI3_CONFIG_PAGETYPE_SAS_IO_UNIT (0x20) > +#define MPI3_CONFIG_PAGETYPE_SAS_EXPANDER (0x21) > +#define MPI3_CONFIG_PAGETYPE_SAS_PHY (0x23) > +#define MPI3_CONFIG_PAGETYPE_SAS_PORT (0x24) > +#define MPI3_CONFIG_PAGETYPE_PCIE_IO_UNIT (0x30) > +#define MPI3_CONFIG_PAGETYPE_PCIE_SWITCH (0x31) > +#define MPI3_CONFIG_PAGETYPE_PCIE_LINK (0x33) > + > +/***************************************************************************** > + * Configuration Page Attributes * > + ****************************************************************************/ > +#define MPI3_CONFIG_PAGEATTR_MASK (0xF0) > +#define MPI3_CONFIG_PAGEATTR_READ_ONLY (0x00) > +#define MPI3_CONFIG_PAGEATTR_CHANGEABLE (0x10) > +#define MPI3_CONFIG_PAGEATTR_PERSISTENT (0x20) > + > +/***************************************************************************** > + * Configuration Page Actions * > + ****************************************************************************/ > +#define MPI3_CONFIG_ACTION_PAGE_HEADER (0x00) > +#define MPI3_CONFIG_ACTION_READ_DEFAULT (0x01) > +#define MPI3_CONFIG_ACTION_READ_CURRENT (0x02) > +#define MPI3_CONFIG_ACTION_WRITE_CURRENT (0x03) > +#define MPI3_CONFIG_ACTION_READ_PERSISTENT (0x04) > +#define MPI3_CONFIG_ACTION_WRITE_PERSISTENT (0x05) > + > +/***************************************************************************** > + * Configuration Page Addressing * > + ****************************************************************************/ > + > +/**** Device PageAddress Format ****/ > +#define MPI3_DEVICE_PGAD_FORM_MASK (0xF0000000) > +#define MPI3_DEVICE_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) > +#define MPI3_DEVICE_PGAD_FORM_HANDLE (0x20000000) > +#define MPI3_DEVICE_PGAD_HANDLE_MASK (0x0000FFFF) > + > +/**** SAS Expander PageAddress Format ****/ > +#define MPI3_SAS_EXPAND_PGAD_FORM_MASK (0xF0000000) > +#define MPI3_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) > +#define MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM (0x10000000) > +#define MPI3_SAS_EXPAND_PGAD_FORM_HANDLE (0x20000000) > +#define MPI3_SAS_EXPAND_PGAD_PHYNUM_MASK (0x00FF0000) > +#define MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT (16) > +#define MPI3_SAS_EXPAND_PGAD_HANDLE_MASK (0x0000FFFF) > + > +/**** SAS Phy PageAddress Format ****/ > +#define MPI3_SAS_PHY_PGAD_FORM_MASK (0xF0000000) > +#define MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER (0x00000000) > +#define MPI3_SAS_PHY_PGAD_PHY_NUMBER_MASK (0x000000FF) > + > +/**** SAS Port PageAddress Format ****/ > +#define MPI3_SASPORT_PGAD_FORM_MASK (0xF0000000) > +#define MPI3_SASPORT_PGAD_FORM_GET_NEXT_PORT (0x00000000) > +#define MPI3_SASPORT_PGAD_FORM_PORT_NUM (0x10000000) > +#define MPI3_SASPORT_PGAD_PORT_NUMBER_MASK (0x000000FF) > + > +/**** Enclosure PageAddress Format ****/ > +#define MPI3_ENCLOS_PGAD_FORM_MASK (0xF0000000) > +#define MPI3_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) > +#define MPI3_ENCLOS_PGAD_FORM_HANDLE (0x10000000) > +#define MPI3_ENCLOS_PGAD_HANDLE_MASK (0x0000FFFF) > + > +/**** PCIe Switch PageAddress Format ****/ > +#define MPI3_PCIE_SWITCH_PGAD_FORM_MASK (0xF0000000) > +#define MPI3_PCIE_SWITCH_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) > +#define MPI3_PCIE_SWITCH_PGAD_FORM_HANDLE_PORT_NUM (0x10000000) > +#define MPI3_PCIE_SWITCH_PGAD_FORM_HANDLE (0x20000000) > +#define MPI3_PCIE_SWITCH_PGAD_PORTNUM_MASK (0x00FF0000) > +#define MPI3_PCIE_SWITCH_PGAD_PORTNUM_SHIFT (16) > +#define MPI3_PCIE_SWITCH_PGAD_HANDLE_MASK (0x0000FFFF) > + > +/**** PCIe Link PageAddress Format ****/ > +#define MPI3_PCIE_LINK_PGAD_FORM_MASK (0xF0000000) > +#define MPI3_PCIE_LINK_PGAD_FORM_GET_NEXT_LINK (0x00000000) > +#define MPI3_PCIE_LINK_PGAD_FORM_LINK_NUM (0x10000000) > +#define MPI3_PCIE_LINK_PGAD_LINKNUM_MASK (0x000000FF) > + > +/**** Security PageAddress Format ****/ > +#define MPI3_SECURITY_PGAD_FORM_MASK (0xF0000000) > +#define MPI3_SECURITY_PGAD_FORM_GET_NEXT_SLOT (0x00000000) > +#define MPI3_SECURITY_PGAD_FORM_SOT_NUM (0x10000000) > +#define MPI3_SECURITY_PGAD_SLOT_GROUP_MASK (0x0000FF00) > +#define MPI3_SECURITY_PGAD_SLOT_MASK (0x000000FF) > + > +/***************************************************************************** > + * Configuration Request Message * > + ****************************************************************************/ > +typedef struct _MPI3_CONFIG_REQUEST { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U16 Reserved0A; /* 0x0A */ > + U8 PageVersion; /* 0x0C */ > + U8 PageNumber; /* 0x0D */ > + U8 PageType; /* 0x0E */ > + U8 Action; /* 0x0F */ > + U32 PageAddress; /* 0x10 */ > + U16 PageLength; /* 0x14 */ > + U16 Reserved16; /* 0x16 */ > + U32 Reserved18[2]; /* 0x18 */ > + MPI3_SGE_UNION SGL; /* 0x20 */ > +} MPI3_CONFIG_REQUEST, MPI3_POINTER PTR_MPI3_CONFIG_REQUEST, > + Mpi3ConfigRequest_t, MPI3_POINTER pMpi3ConfigRequest_t; > + > +/***************************************************************************** > + * Configuration Pages * > + ****************************************************************************/ > + > +/***************************************************************************** > + * Configuration Page Header * > + ****************************************************************************/ > +typedef struct _MPI3_CONFIG_PAGE_HEADER { > + U8 PageVersion; /* 0x00 */ > + U8 Reserved01; /* 0x01 */ > + U8 PageNumber; /* 0x02 */ > + U8 PageAttribute; /* 0x03 */ > + U16 PageLength; /* 0x04 */ > + U8 PageType; /* 0x06 */ > + U8 Reserved07; /* 0x07 */ > +} MPI3_CONFIG_PAGE_HEADER, MPI3_POINTER PTR_MPI3_CONFIG_PAGE_HEADER, > + Mpi3ConfigPageHeader_t, MPI3_POINTER pMpi3ConfigPageHeader_t; > + > +/***************************************************************************** > + * Common definitions used by Configuration Pages * > + ****************************************************************************/ > + > +/**** Defines for Negotiated Link Rates ****/ > +#define MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK (0xF0) > +#define MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT (4) > +#define MPI3_SAS_NEG_LINK_RATE_PHYSICAL_MASK (0x0F) > +#define MPI3_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE (0x00) > +#define MPI3_SAS_NEG_LINK_RATE_PHY_DISABLED (0x01) > +#define MPI3_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED (0x02) > +#define MPI3_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE (0x03) > +#define MPI3_SAS_NEG_LINK_RATE_PORT_SELECTOR (0x04) > +#define MPI3_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS (0x05) > +#define MPI3_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY (0x06) > +#define MPI3_SAS_NEG_LINK_RATE_1_5 (0x08) > +#define MPI3_SAS_NEG_LINK_RATE_3_0 (0x09) > +#define MPI3_SAS_NEG_LINK_RATE_6_0 (0x0A) > +#define MPI3_SAS_NEG_LINK_RATE_12_0 (0x0B) > +#define MPI3_SAS_NEG_LINK_RATE_22_5 (0x0C) > + > +/**** Defines for the AttachedPhyInfo field ****/ > +#define MPI3_SAS_APHYINFO_INSIDE_ZPSDS_PERSISTENT (0x00000040) > +#define MPI3_SAS_APHYINFO_REQUESTED_INSIDE_ZPSDS (0x00000020) > +#define MPI3_SAS_APHYINFO_BREAK_REPLY_CAPABLE (0x00000010) > + > +#define MPI3_SAS_APHYINFO_REASON_MASK (0x0000000F) > +#define MPI3_SAS_APHYINFO_REASON_UNKNOWN (0x00000000) > +#define MPI3_SAS_APHYINFO_REASON_POWER_ON (0x00000001) > +#define MPI3_SAS_APHYINFO_REASON_HARD_RESET (0x00000002) > +#define MPI3_SAS_APHYINFO_REASON_SMP_PHY_CONTROL (0x00000003) > +#define MPI3_SAS_APHYINFO_REASON_LOSS_OF_SYNC (0x00000004) > +#define MPI3_SAS_APHYINFO_REASON_MULTIPLEXING_SEQ (0x00000005) > +#define MPI3_SAS_APHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00000006) > +#define MPI3_SAS_APHYINFO_REASON_BREAK_TIMEOUT (0x00000007) > +#define MPI3_SAS_APHYINFO_REASON_PHY_TEST_STOPPED (0x00000008) > +#define MPI3_SAS_APHYINFO_REASON_EXP_REDUCED_FUNC (0x00000009) > + > +/**** Defines for the PhyInfo field ****/ > +#define MPI3_SAS_PHYINFO_STATUS_MASK (0xC0000000) > +#define MPI3_SAS_PHYINFO_STATUS_SHIFT (30) > +#define MPI3_SAS_PHYINFO_STATUS_ACCESSIBLE (0x00000000) > +#define MPI3_SAS_PHYINFO_STATUS_NOT_EXIST (0x40000000) > +#define MPI3_SAS_PHYINFO_STATUS_VACANT (0x80000000) > + > +#define MPI3_SAS_PHYINFO_PHY_POWER_CONDITION_MASK (0x18000000) > +#define MPI3_SAS_PHYINFO_PHY_POWER_CONDITION_ACTIVE (0x00000000) > +#define MPI3_SAS_PHYINFO_PHY_POWER_CONDITION_PARTIAL (0x08000000) > +#define MPI3_SAS_PHYINFO_PHY_POWER_CONDITION_SLUMBER (0x10000000) > + > +#define MPI3_SAS_PHYINFO_REASON_MASK (0x000F0000) > +#define MPI3_SAS_PHYINFO_REASON_UNKNOWN (0x00000000) > +#define MPI3_SAS_PHYINFO_REASON_POWER_ON (0x00010000) > +#define MPI3_SAS_PHYINFO_REASON_HARD_RESET (0x00020000) > +#define MPI3_SAS_PHYINFO_REASON_SMP_PHY_CONTROL (0x00030000) > +#define MPI3_SAS_PHYINFO_REASON_LOSS_OF_SYNC (0x00040000) > +#define MPI3_SAS_PHYINFO_REASON_MULTIPLEXING_SEQ (0x00050000) > +#define MPI3_SAS_PHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00060000) > +#define MPI3_SAS_PHYINFO_REASON_BREAK_TIMEOUT (0x00070000) > +#define MPI3_SAS_PHYINFO_REASON_PHY_TEST_STOPPED (0x00080000) > +#define MPI3_SAS_PHYINFO_REASON_EXP_REDUCED_FUNC (0x00090000) > + > +#define MPI3_SAS_PHYINFO_SATA_PORT_ACTIVE (0x00004000) > +#define MPI3_SAS_PHYINFO_SATA_PORT_SELECTOR_PRESENT (0x00002000) > +#define MPI3_SAS_PHYINFO_VIRTUAL_PHY (0x00001000) > + > +#define MPI3_SAS_PHYINFO_PARTIAL_PATHWAY_TIME_MASK (0x00000F00) > +#define MPI3_SAS_PHYINFO_PARTIAL_PATHWAY_TIME_SHIFT (8) > + > +#define MPI3_SAS_PHYINFO_ROUTING_ATTRIBUTE_MASK (0x000000F0) > +#define MPI3_SAS_PHYINFO_ROUTING_ATTRIBUTE_DIRECT (0x00000000) > +#define MPI3_SAS_PHYINFO_ROUTING_ATTRIBUTE_SUBTRACTIVE (0x00000010) > +#define MPI3_SAS_PHYINFO_ROUTING_ATTRIBUTE_TABLE (0x00000020) > + > +/**** Defines for the ProgrammedLinkRate field ****/ > +#define MPI3_SAS_PRATE_MAX_RATE_MASK (0xF0) > +#define MPI3_SAS_PRATE_MAX_RATE_NOT_PROGRAMMABLE (0x00) > +#define MPI3_SAS_PRATE_MAX_RATE_1_5 (0x80) > +#define MPI3_SAS_PRATE_MAX_RATE_3_0 (0x90) > +#define MPI3_SAS_PRATE_MAX_RATE_6_0 (0xA0) > +#define MPI3_SAS_PRATE_MAX_RATE_12_0 (0xB0) > +#define MPI3_SAS_PRATE_MAX_RATE_22_5 (0xC0) > +#define MPI3_SAS_PRATE_MIN_RATE_MASK (0x0F) > +#define MPI3_SAS_PRATE_MIN_RATE_NOT_PROGRAMMABLE (0x00) > +#define MPI3_SAS_PRATE_MIN_RATE_1_5 (0x08) > +#define MPI3_SAS_PRATE_MIN_RATE_3_0 (0x09) > +#define MPI3_SAS_PRATE_MIN_RATE_6_0 (0x0A) > +#define MPI3_SAS_PRATE_MIN_RATE_12_0 (0x0B) > +#define MPI3_SAS_PRATE_MIN_RATE_22_5 (0x0C) > + > +/**** Defines for the HwLinkRate field ****/ > +#define MPI3_SAS_HWRATE_MAX_RATE_MASK (0xF0) > +#define MPI3_SAS_HWRATE_MAX_RATE_1_5 (0x80) > +#define MPI3_SAS_HWRATE_MAX_RATE_3_0 (0x90) > +#define MPI3_SAS_HWRATE_MAX_RATE_6_0 (0xA0) > +#define MPI3_SAS_HWRATE_MAX_RATE_12_0 (0xB0) > +#define MPI3_SAS_HWRATE_MAX_RATE_22_5 (0xC0) > +#define MPI3_SAS_HWRATE_MIN_RATE_MASK (0x0F) > +#define MPI3_SAS_HWRATE_MIN_RATE_1_5 (0x08) > +#define MPI3_SAS_HWRATE_MIN_RATE_3_0 (0x09) > +#define MPI3_SAS_HWRATE_MIN_RATE_6_0 (0x0A) > +#define MPI3_SAS_HWRATE_MIN_RATE_12_0 (0x0B) > +#define MPI3_SAS_HWRATE_MIN_RATE_22_5 (0x0C) > + > +/**** Defines for the Slot field ****/ > +#define MPI3_SLOT_INVALID (0xFFFF) > + > +/**** Defines for the SlotIndex field ****/ > +#define MPI3_SLOT_INDEX_INVALID (0xFFFF) > + > +/***************************************************************************** > + * Manufacturing Configuration Pages * > + ****************************************************************************/ > + > +/***************************************************************************** > + * Manufacturing Page 0 * > + ****************************************************************************/ > +typedef struct _MPI3_MAN_PAGE0 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U8 ChipRevision[8]; /* 0x08 */ > + U8 ChipName[32]; /* 0x10 */ > + U8 BoardName[32]; /* 0x30 */ > + U8 BoardAssembly[32]; /* 0x50 */ > + U8 BoardTracerNumber[32]; /* 0x70 */ > + U32 BoardPower; /* 0x90 */ > + U32 Reserved94; /* 0x94 */ > + U32 Reserved98; /* 0x98 */ > + U8 OEM; /* 0x9C */ > + U8 SubOEM; /* 0x9D */ > + U16 Reserved9E; /* 0x9E */ > + U8 BoardMfgDay; /* 0xA0 */ > + U8 BoardMfgMonth; /* 0xA1 */ > + U16 BoardMfgYear; /* 0xA2 */ > + U8 BoardReworkDay; /* 0xA4 */ > + U8 BoardReworkMonth; /* 0xA5 */ > + U16 BoardReworkYear; /* 0xA6 */ > + U64 BoardRevision; /* 0xA8 */ > + U8 EPackFRU[16]; /* 0xB0 */ > + U8 ProductName[256]; /* 0xC0 */ > +} MPI3_MAN_PAGE0, MPI3_POINTER PTR_MPI3_MAN_PAGE0, > + Mpi3ManPage0_t, MPI3_POINTER pMpi3ManPage0_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_MAN0_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * Manufacturing Page 1 * > + ****************************************************************************/ > + > +#define MPI3_MAN1_VPD_SIZE (512) > + > +typedef struct _MPI3_MAN_PAGE1 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08[2]; /* 0x08 */ > + U8 VPD[MPI3_MAN1_VPD_SIZE]; /* 0x10 */ > +} MPI3_MAN_PAGE1, MPI3_POINTER PTR_MPI3_MAN_PAGE1, > + Mpi3ManPage1_t, MPI3_POINTER pMpi3ManPage1_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_MAN1_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * Manufacturing Page 5 * > + ****************************************************************************/ > +typedef struct _MPI3_MAN5_PHY_ENTRY { > + U64 IOC_WWID; /* 0x00 */ > + U64 DeviceName; /* 0x08 */ > + U64 SATA_WWID; /* 0x10 */ > +} MPI3_MAN5_PHY_ENTRY, MPI3_POINTER PTR_MPI3_MAN5_PHY_ENTRY, > + Mpi3Man5PhyEntry_t, MPI3_POINTER pMpi3Man5PhyEntry_t; > + > +#ifndef MPI3_MAN5_PHY_MAX > +#define MPI3_MAN5_PHY_MAX (1) > +#endif /* MPI3_MAN5_PHY_MAX */ > + > +typedef struct _MPI3_MAN_PAGE5 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U8 NumPhys; /* 0x08 */ > + U8 Reserved09[3]; /* 0x09 */ > + U32 Reserved0C; /* 0x0C */ > + MPI3_MAN5_PHY_ENTRY Phy[MPI3_MAN5_PHY_MAX]; /* 0x10 */ > +} MPI3_MAN_PAGE5, MPI3_POINTER PTR_MPI3_MAN_PAGE5, > + Mpi3ManPage5_t, MPI3_POINTER pMpi3ManPage5_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_MAN5_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * Manufacturing Page 6 * > + ****************************************************************************/ > +typedef struct _MPI3_MAN6_GPIO_ENTRY { > + U8 FunctionCode; /* 0x00 */ > + U8 Reserved01; /* 0x01 */ > + U16 Flags; /* 0x02 */ > + U8 Param1; /* 0x04 */ > + U8 Param2; /* 0x05 */ > + U16 Reserved06; /* 0x06 */ > + U32 Param3; /* 0x08 */ > +} MPI3_MAN6_GPIO_ENTRY, MPI3_POINTER PTR_MPI3_MAN6_GPIO_ENTRY, > + Mpi3Man6GpioEntry_t, MPI3_POINTER pMpi3Man6GpioEntry_t; > + > +/**** Defines for the FunctionCode field ****/ > +#define MPI3_MAN6_GPIO_FUNCTION_GENERIC (0x00) > +#define MPI3_MAN6_GPIO_FUNCTION_ALTERNATE (0x01) > +#define MPI3_MAN6_GPIO_FUNCTION_EXT_INTERRUPT (0x02) > +#define MPI3_MAN6_GPIO_FUNCTION_GLOBAL_ACTIVITY (0x03) > +#define MPI3_MAN6_GPIO_FUNCTION_OVER_TEMPERATURE (0x04) > +#define MPI3_MAN6_GPIO_FUNCTION_PORT_STATUS_GREEN (0x05) > +#define MPI3_MAN6_GPIO_FUNCTION_PORT_STATUS_YELLOW (0x06) > +#define MPI3_MAN6_GPIO_FUNCTION_CABLE_MANAGEMENT (0x07) > +#define MPI3_MAN6_GPIO_FUNCTION_BKPLANE_MGMT_TYPE (0x08) > +#define MPI3_MAN6_GPIO_FUNCTION_ISTWI_MUX_RESET (0x09) > +#define MPI3_MAN6_GPIO_FUNCTION_ISTWI_RESET (0x0A) > +#define MPI3_MAN6_GPIO_FUNCTION_BACKEND_PCIE_RESET (0x0B) > +#define MPI3_MAN6_GPIO_FUNCTION_GLOBAL_FAULT (0x0C) > +#define MPI3_MAN6_GPIO_FUNCTION_EPACK_ATTN (0x0D) > +#define MPI3_MAN6_GPIO_FUNCTION_EPACK_ONLINE (0x0E) > +#define MPI3_MAN6_GPIO_FUNCTION_EPACK_FAULT (0x0F) > +#define MPI3_MAN6_GPIO_FUNCTION_CTRL_TYPE (0x10) > +#define MPI3_MAN6_GPIO_FUNCTION_LICENSE (0x11) > +#define MPI3_MAN6_GPIO_FUNCTION_REFCLK_CONTROL (0x12) > + > +/**** Defines for Param1 (Flags) when FunctionCode is EXT_INTERRUPT ****/ > +#define MPI3_MAN6_GPIO_EXTINT_PARAM1_FLAGS_SOURCE_MASK (0xF0) > +#define MPI3_MAN6_GPIO_EXTINT_PARAM1_FLAGS_SOURCE_GENERIC (0x00) > +#define MPI3_MAN6_GPIO_EXTINT_PARAM1_FLAGS_SOURCE_CABLE_MGMT (0x10) > +#define MPI3_MAN6_GPIO_EXTINT_PARAM1_FLAGS_SOURCE_ACTIVE_CABLE_OVERCURRENT (0x20) > + > +#define MPI3_MAN6_GPIO_EXTINT_PARAM1_FLAGS_TRIGGER_MASK (0x01) > +#define MPI3_MAN6_GPIO_EXTINT_PARAM1_FLAGS_TRIGGER_EDGE (0x00) > +#define MPI3_MAN6_GPIO_EXTINT_PARAM1_FLAGS_TRIGGER_LEVEL (0x01) > + > +/**** Defines for Param1 (PHY STATE) when FunctionCode is PORT_STATUS_GREEN ****/ > +#define MPI3_MAN6_GPIO_PORT_GREEN_PARAM1_PHY_STATUS_ALL_UP (0x00) > +#define MPI3_MAN6_GPIO_PORT_GREEN_PARAM1_PHY_STATUS_ONE_OR_MORE_UP (0x01) > + > +/**** Defines for Param1 (INTERFACE_SIGNAL) when FunctionCode is CABLE_MANAGEMENT ****/ > +#define MPI3_MAN6_GPIO_CABLE_MGMT_PARAM1_INTERFACE_MODULE_PRESENT (0x00) > +#define MPI3_MAN6_GPIO_CABLE_MGMT_PARAM1_INTERFACE_ACTIVE_CABLE_ENABLE (0x01) > +#define MPI3_MAN6_GPIO_CABLE_MGMT_PARAM1_INTERFACE_CABLE_MGMT_ENABLE (0x02) > + > +/**** Defines for Param2 (ISTWI RESET) when FunctionCode is ISTWI_MUX_RESET ****/ > +#define MPI3_MAN6_GPIO_ISTWI_MUX_RESET_PARAM2_SPEC_MUX (0x00) > +#define MPI3_MAN6_GPIO_ISTWI_MUX_RESET_PARAM2_ALL_MUXES (0x01) > + > +/**** Defines for Param1 (LECENSE_TYPE) when FunctionCode is LICENSE ****/ > +#define MPI3_MAN6_GPIO_LICENSE_PARAM1_TYPE_IBUTTON (0x00) > + > + > +/**** Defines for the Flags field ****/ > +#define MPI3_MAN6_GPIO_FLAGS_SLEW_RATE_MASK (0x0100) > +#define MPI3_MAN6_GPIO_FLAGS_SLEW_RATE_FAST_EDGE (0x0100) > +#define MPI3_MAN6_GPIO_FLAGS_SLEW_RATE_SLOW_EDGE (0x0000) > +#define MPI3_MAN6_GPIO_FLAGS_DRIVE_STRENGTH_MASK (0x00C0) > +#define MPI3_MAN6_GPIO_FLAGS_DRIVE_STRENGTH_100OHM (0x0000) > +#define MPI3_MAN6_GPIO_FLAGS_DRIVE_STRENGTH_66OHM (0x0040) > +#define MPI3_MAN6_GPIO_FLAGS_DRIVE_STRENGTH_50OHM (0x0080) > +#define MPI3_MAN6_GPIO_FLAGS_DRIVE_STRENGTH_33OHM (0x00C0) > +#define MPI3_MAN6_GPIO_FLAGS_ALT_DATA_SEL_MASK (0x0030) > +#define MPI3_MAN6_GPIO_FLAGS_ALT_DATA_SEL_SHIFT (4) > +#define MPI3_MAN6_GPIO_FLAGS_ACTIVE_HIGH (0x0008) > +#define MPI3_MAN6_GPIO_FLAGS_BI_DIR_ENABLED (0x0004) > +#define MPI3_MAN6_GPIO_FLAGS_DIRECTION_MASK (0x0003) > +#define MPI3_MAN6_GPIO_FLAGS_DIRECTION_INPUT (0x0000) > +#define MPI3_MAN6_GPIO_FLAGS_DIRECTION_OPEN_DRAIN_OUTPUT (0x0001) > +#define MPI3_MAN6_GPIO_FLAGS_DIRECTION_OPEN_SOURCE_OUTPUT (0x0002) > +#define MPI3_MAN6_GPIO_FLAGS_DIRECTION_PUSH_PULL_OUTPUT (0x0003) > + > +#ifndef MPI3_MAN6_GPIO_MAX > +#define MPI3_MAN6_GPIO_MAX (1) > +#endif /* MPI3_MAN6_GPIO_MAX */ > + > +typedef struct _MPI3_MAN_PAGE6 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U16 Flags; /* 0x08 */ > + U16 Reserved0A; /* 0x0A */ > + U8 NumGPIO; /* 0x0C */ > + U8 Reserved0D[3]; /* 0x0D */ > + MPI3_MAN6_GPIO_ENTRY GPIO[MPI3_MAN6_GPIO_MAX]; /* 0x10 */ > +} MPI3_MAN_PAGE6, MPI3_POINTER PTR_MPI3_MAN_PAGE6, > + Mpi3ManPage6_t, MPI3_POINTER pMpi3ManPage6_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_MAN6_PAGEVERSION (0x00) > + > +/**** Defines for the Flags field ****/ > +#define MPI3_MAN6_FLAGS_HEARTBEAT_LED_DISABLED (0x0001) > + > +/***************************************************************************** > + * Manufacturing Page 7 * > + ****************************************************************************/ > +typedef struct _MPI3_MAN7_RECEPTACLE_INFO { > + U32 Name[4]; /* 0x00 */ > + U8 Location; /* 0x10 */ > + U8 ConnectorType; /* 0x11 */ > + U8 PEDClk; /* 0x12 */ > + U8 ConnectorID; /* 0x13 */ > + U32 Reserved14; /* 0x14 */ > +} MPI3_MAN7_RECEPTACLE_INFO, MPI3_POINTER PTR_MPI3_MAN7_RECEPTACLE_INFO, > + Mpi3Man7ReceptacleInfo_t, MPI3_POINTER pMpi3Man7ReceptacleInfo_t; > + > +/**** Defines for Location field ****/ > +#define MPI3_MAN7_LOCATION_UNKNOWN (0x00) > +#define MPI3_MAN7_LOCATION_INTERNAL (0x01) > +#define MPI3_MAN7_LOCATION_EXTERNAL (0x02) > +#define MPI3_MAN7_LOCATION_VIRTUAL (0x03) > + > +/**** Defines for ConnectorType - Use definitions from SES-4 ****/ > + > +/**** Defines for PEDClk field ****/ > +#define MPI3_MAN7_PEDCLK_ROUTING_MASK (0x10) > +#define MPI3_MAN7_PEDCLK_ROUTING_DIRECT (0x00) > +#define MPI3_MAN7_PEDCLK_ROUTING_CLOCK_BUFFER (0x10) > +#define MPI3_MAN7_PEDCLK_ID_MASK (0x0F) > + > +#ifndef MPI3_MAN7_RECEPTACLE_INFO_MAX > +#define MPI3_MAN7_RECEPTACLE_INFO_MAX (1) > +#endif /* MPI3_MAN7_RECEPTACLE_INFO_MAX */ > + > +typedef struct _MPI3_MAN_PAGE7 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Flags; /* 0x08 */ > + U8 NumReceptacles; /* 0x0C */ > + U8 Reserved0D[3]; /* 0x0D */ > + U32 EnclosureName[4]; /* 0x10 */ > + MPI3_MAN7_RECEPTACLE_INFO ReceptacleInfo[MPI3_MAN7_RECEPTACLE_INFO_MAX]; /* 0x20 */ /* variable length array */ > +} MPI3_MAN_PAGE7, MPI3_POINTER PTR_MPI3_MAN_PAGE7, > + Mpi3ManPage7_t, MPI3_POINTER pMpi3ManPage7_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_MAN7_PAGEVERSION (0x00) > + > +/**** Defines for Flags field ****/ > +#define MPI3_MAN7_FLAGS_BASE_ENCLOSURE_LEVEL_MASK (0x01) > +#define MPI3_MAN7_FLAGS_BASE_ENCLOSURE_LEVEL_0 (0x00) > +#define MPI3_MAN7_FLAGS_BASE_ENCLOSURE_LEVEL_1 (0x01) > + > + > +/***************************************************************************** > + * Manufacturing Page 8 * > + ****************************************************************************/ > + > +typedef struct _MPI3_MAN8_PHY_INFO { > + U8 ReceptacleID; /* 0x00 */ > + U8 ConnectorLane; /* 0x01 */ > + U16 Reserved02; /* 0x02 */ > + U16 Slotx1; /* 0x04 */ > + U16 Slotx2; /* 0x06 */ > + U16 Slotx4; /* 0x08 */ > + U16 Reserved0A; /* 0x0A */ > + U32 Reserved0C; /* 0x0C */ > +} MPI3_MAN8_PHY_INFO, MPI3_POINTER PTR_MPI3_MAN8_PHY_INFO, > + Mpi3Man8PhyInfo_t, MPI3_POINTER pMpi3Man8PhyInfo_t; > + > +#ifndef MPI3_MAN8_PHY_INFO_MAX > +#define MPI3_MAN8_PHY_INFO_MAX (1) > +#endif /* MPI3_MAN8_PHY_INFO_MAX */ > + > +typedef struct _MPI3_MAN_PAGE8 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08; /* 0x08 */ > + U8 NumPhys; /* 0x0C */ > + U8 Reserved0D[3]; /* 0x0D */ > + MPI3_MAN8_PHY_INFO PhyInfo[MPI3_MAN8_PHY_INFO_MAX]; /* 0x10 */ /* variable length array */ > +} MPI3_MAN_PAGE8, MPI3_POINTER PTR_MPI3_MAN_PAGE8, > + Mpi3ManPage8_t, MPI3_POINTER pMpi3ManPage8_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_MAN8_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * Manufacturing Page 9 * > + ****************************************************************************/ > +typedef struct _MPI3_MAN9_RSRC_ENTRY { > + U32 Maximum; /* 0x00 */ > + U32 Decrement; /* 0x04 */ > + U32 Minimum; /* 0x08 */ > + U32 Actual; /* 0x0C */ > +} MPI3_MAN9_RSRC_ENTRY, MPI3_POINTER PTR_MPI3_MAN9_RSRC_ENTRY, > + Mpi3Man9RsrcEntry_t, MPI3_POINTER pMpi3Man9RsrcEntry_t; > + > +typedef enum _MPI3_MAN9_RESOURCES { > + MPI3_MAN9_RSRC_OUTSTANDING_REQS = 0, > + MPI3_MAN9_RSRC_TARGET_CMDS = 1, > + MPI3_MAN9_RSRC_SAS_TARGETS = 2, > + MPI3_MAN9_RSRC_PCIE_TARGETS = 3, > + MPI3_MAN9_RSRC_INITIATORS = 4, > + MPI3_MAN9_RSRC_VDS = 5, > + MPI3_MAN9_RSRC_ENCLOSURES = 6, > + MPI3_MAN9_RSRC_ENCLOSURE_PHYS = 7, > + MPI3_MAN9_RSRC_EXPANDERS = 8, > + MPI3_MAN9_RSRC_PCIE_SWITCHES = 9, > + MPI3_MAN9_RSRC_PDS = 10, > + MPI3_MAN9_RSRC_HOST_PDS = 11, > + MPI3_MAN9_RSRC_ADV_HOST_PDS = 12, > + MPI3_MAN9_RSRC_RAID_PDS = 13, > + MPI3_MAN9_RSRC_NUM_RESOURCES > +} MPI3_MAN9_RESOURCES; > + > +#define MPI3_MAN9_MIN_OUTSTANDING_REQS (1) > +#define MPI3_MAN9_MAX_OUTSTANDING_REQS (65000) > + > +#define MPI3_MAN9_MIN_TARGET_CMDS (0) > +#define MPI3_MAN9_MAX_TARGET_CMDS (65535) > + > +#define MPI3_MAN9_MIN_SAS_TARGETS (0) > +#define MPI3_MAN9_MAX_SAS_TARGETS (65535) > + > +#define MPI3_MAN9_MIN_PCIE_TARGETS (0) > +/* Max PCIe Targets is product specific */ > + > +#define MPI3_MAN9_MIN_INITIATORS (0) > +#define MPI3_MAN9_MAX_INITIATORS (65535) > + > +#define MPI3_MAN9_MIN_ENCLOSURES (0) > +#define MPI3_MAN9_MAX_ENCLOSURES (65535) > + > +#define MPI3_MAN9_MIN_ENCLOSURE_PHYS (0) > +/* > + * Max Enclosure Phys depends on the largest enclosure > + * i.e. the enclosure with the largest number of phys. > + */ > + > +#define MPI3_MAN9_MIN_EXPANDERS (0) > +#define MPI3_MAN9_MAX_EXPANDERS (65535) > + > +#define MPI3_MAN9_MIN_PCIE_SWITCHES (0) > +/* Max PCIe Switches is product specific */ > + > +typedef struct _MPI3_MAN_PAGE9 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U8 NumResources; /* 0x08 */ > + U8 Reserved09; /* 0x09 */ > + U16 Reserved0A; /* 0x0A */ > + U32 Reserved0C; /* 0x0C */ > + U32 Reserved10; /* 0x10 */ > + U32 Reserved14; /* 0x14 */ > + U32 Reserved18; /* 0x18 */ > + U32 Reserved1C; /* 0x1C */ > + MPI3_MAN9_RSRC_ENTRY Resource[MPI3_MAN9_RSRC_NUM_RESOURCES]; /* 0x20 */ > +} MPI3_MAN_PAGE9, MPI3_POINTER PTR_MPI3_MAN_PAGE9, > + Mpi3ManPage9_t, MPI3_POINTER pMpi3ManPage9_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_MAN9_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * Manufacturing Page 10 * > + ****************************************************************************/ > +typedef struct _MPI3_MAN10_ISTWI_CTRLR_ENTRY { > + U16 SlaveAddress; /* 0x00 */ > + U16 Flags; /* 0x02 */ > + U32 Reserved04; /* 0x04 */ > +} MPI3_MAN10_ISTWI_CTRLR_ENTRY, MPI3_POINTER PTR_MPI3_MAN10_ISTWI_CTRLR_ENTRY, > + Mpi3Man10IstwiCtrlrEntry_t, MPI3_POINTER pMpi3Man10IstwiCtrlrEntry_t; > + > +/**** Defines for the Flags field ****/ > +#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_SLAVE_ENABLED (0x0002) > +#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_MASTER_ENABLED (0x0001) > + > +#ifndef MPI3_MAN10_ISTWI_CTRLR_MAX > +#define MPI3_MAN10_ISTWI_CTRLR_MAX (1) > +#endif /* MPI3_MAN10_ISTWI_CTRLR_MAX */ > + > +typedef struct _MPI3_MAN_PAGE10 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08; /* 0x08 */ > + U8 NumISTWICtrl; /* 0x0C */ > + U8 Reserved0D[3]; /* 0x0D */ > + MPI3_MAN10_ISTWI_CTRLR_ENTRY ISTWIController[MPI3_MAN10_ISTWI_CTRLR_MAX]; /* 0x10 */ > +} MPI3_MAN_PAGE10, MPI3_POINTER PTR_MPI3_MAN_PAGE10, > + Mpi3ManPage10_t, MPI3_POINTER pMpi3ManPage10_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_MAN10_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * Manufacturing Page 11 * > + ****************************************************************************/ > +typedef struct _MPI3_MAN11_MUX_DEVICE_FORMAT { > + U8 MaxChannel; /* 0x00 */ > + U8 Reserved01[3]; /* 0x01 */ > + U32 Reserved04; /* 0x04 */ > +} MPI3_MAN11_MUX_DEVICE_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_MUX_DEVICE_FORMAT, > + Mpi3Man11MuxDeviceFormat_t, MPI3_POINTER pMpi3Man11MuxDeviceFormat_t; > + > +typedef struct _MPI3_MAN11_TEMP_SENSOR_DEVICE_FORMAT { > + U8 Type; /* 0x00 */ > + U8 Reserved01[3]; /* 0x01 */ > + U8 TempChannel[4]; /* 0x04 */ > +} MPI3_MAN11_TEMP_SENSOR_DEVICE_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_TEMP_SENSOR_DEVICE_FORMAT, > + Mpi3Man11TempSensorDeviceFormat_t, MPI3_POINTER pMpi3Man11TempSensorDeviceFormat_t; > + > +/**** Defines for the Type field ****/ > +#define MPI3_MAN11_TEMP_SENSOR_TYPE_MAX6654 (0x00) > +#define MPI3_MAN11_TEMP_SENSOR_TYPE_EMC1442 (0x01) > +#define MPI3_MAN11_TEMP_SENSOR_TYPE_ADT7476 (0x02) > + > +/**** Define for the TempChannel field ****/ > +#define MPI3_MAN11_TEMP_SENSOR_CHANNEL_ENABLED (0x01) > + > +typedef struct _MPI3_MAN11_SEEPROM_DEVICE_FORMAT { > + U8 Size; /* 0x00 */ > + U8 PageWriteSize; /* 0x01 */ > + U16 Reserved02; /* 0x02 */ > + U32 Reserved04; /* 0x04 */ > +} MPI3_MAN11_SEEPROM_DEVICE_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_SEEPROM_DEVICE_FORMAT, > + Mpi3Man11SeepromDeviceFormat_t, MPI3_POINTER pMpi3Man11SeepromDeviceFormat_t; > + > +/**** Defines for the Size field ****/ > +#define MPI3_MAN11_SEEPROM_SIZE_1KBITS (0x01) > +#define MPI3_MAN11_SEEPROM_SIZE_2KBITS (0x02) > +#define MPI3_MAN11_SEEPROM_SIZE_4KBITS (0x03) > +#define MPI3_MAN11_SEEPROM_SIZE_8KBITS (0x04) > +#define MPI3_MAN11_SEEPROM_SIZE_16KBITS (0x05) > +#define MPI3_MAN11_SEEPROM_SIZE_32KBITS (0x06) > +#define MPI3_MAN11_SEEPROM_SIZE_64KBITS (0x07) > +#define MPI3_MAN11_SEEPROM_SIZE_128KBITS (0x08) > + > +typedef struct _MPI3_MAN11_DDR_SPD_DEVICE_FORMAT { > + U8 Channel; /* 0x00 */ > + U8 Reserved01[3]; /* 0x01 */ > + U32 Reserved04; /* 0x04 */ > +} MPI3_MAN11_DDR_SPD_DEVICE_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_DDR_SPD_DEVICE_FORMAT, > + Mpi3Man11DdrSpdDeviceFormat_t, MPI3_POINTER pMpi3Man11DdrSpdDeviceFormat_t; > + > +typedef struct _MPI3_MAN11_CABLE_MGMT_DEVICE_FORMAT { > + U8 Type; /* 0x00 */ > + U8 ReceptacleID; /* 0x01 */ > + U16 Reserved02; /* 0x02 */ > + U32 Reserved04; /* 0x04 */ > +} MPI3_MAN11_CABLE_MGMT_DEVICE_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_CABLE_MGMT_DEVICE_FORMAT, > + Mpi3Man11CableMgmtDeviceFormat_t, MPI3_POINTER pMpi3Man11CableMgmtDeviceFormat_t; > + > +/**** Defines for the Type field ****/ > +#define MPI3_MAN11_CABLE_MGMT_TYPE_SFF_8636 (0x00) > + > +typedef struct _MPI3_MAN11_BKPLANE_SPEC_UBM_FORMAT { > + U16 Flags; /* 0x00 */ > + U16 Reserved02; /* 0x02 */ > +} MPI3_MAN11_BKPLANE_SPEC_UBM_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_BKPLANE_SPEC_UBM_FORMAT, > + Mpi3Man11BkplaneSpecUBMFormat, MPI3_POINTER pMpi3Man11BkplaneSpecUBMFormat; > + > +#define MPI3_MAN11_BKPLANE_UBM_FLAGS_REFCLK_POLICY_ALWAYS_ENABLED (0x0200) > +#define MPI3_MAN11_BKPLANE_UBM_FLAGS_FORCE_POLLING (0x0100) > +#define MPI3_MAN11_BKPLANE_UBM_FLAGS_MAX_FRU_MASK (0x00F0) > +#define MPI3_MAN11_BKPLANE_UBM_FLAGS_MAX_FRU_SHIFT (4) > +#define MPI3_MAN11_BKPLANE_UBM_FLAGS_POLL_INTERVAL_MASK (0x000F) > +#define MPI3_MAN11_BKPLANE_UBM_FLAGS_POLL_INTERVAL_SHIFT (0) > + > +typedef struct _MPI3_MAN11_BKPLANE_SPEC_VPP_FORMAT { > + U16 Flags; /* 0x00 */ > + U16 Reserved02; /* 0x02 */ > +} MPI3_MAN11_BKPLANE_SPEC_VPP_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_BKPLANE_SPEC_VPP_FORMAT, > + Mpi3Man11BkplaneSpecVPPFormat, MPI3_POINTER pMpi3Man11BkplaneSpecVPPFormat; > + > +#define MPI3_MAN11_BKPLANE_VPP_FLAGS_REFCLK_POLICY_ALWAYS_ENABLED (0x0040) > +#define MPI3_MAN11_BKPLANE_VPP_FLAGS_PRESENCE_DETECT_MASK (0x0030) > +#define MPI3_MAN11_BKPLANE_VPP_FLAGS_PRESENCE_DETECT_GPIO (0x0000) > +#define MPI3_MAN11_BKPLANE_VPP_FLAGS_PRESENCE_DETECT_REG (0x0010) > +#define MPI3_MAN11_BKPLANE_VPP_FLAGS_POLL_INTERVAL_MASK (0x000F) > +#define MPI3_MAN11_BKPLANE_VPP_FLAGS_POLL_INTERVAL_SHIFT (0) > + > + > +typedef union _MPI3_MAN11_BKPLANE_SPEC_FORMAT { > + MPI3_MAN11_BKPLANE_SPEC_UBM_FORMAT Ubm; > + MPI3_MAN11_BKPLANE_SPEC_VPP_FORMAT Vpp; > +} MPI3_MAN11_BKPLANE_SPEC_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_BKPLANE_SPEC_FORMAT, > + Mpi3Man11BkplaneSpecFormat, MPI3_POINTER pMpi3Man11BkplaneSpecFormat; > + > +typedef struct _MPI3_MAN11_BKPLANE_MGMT_DEVICE_FORMAT { > + U8 Type; /* 0x00 */ > + U8 ReceptacleID; /* 0x01 */ > + U16 Reserved02; /* 0x02 */ > + MPI3_MAN11_BKPLANE_SPEC_FORMAT BackplaneMgmtSpecific; /* 0x04 */ > +} MPI3_MAN11_BKPLANE_MGMT_DEVICE_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_BKPLANE_MGMT_DEVICE_FORMAT, > + Mpi3Man11BkplaneMgmtDeviceFormat_t, MPI3_POINTER pMpi3Man11BkplaneMgmtDeviceFormat_t; > + > +/**** Defines for the Type field ****/ > +#define MPI3_MAN11_BKPLANE_MGMT_TYPE_UBM (0x00) > +#define MPI3_MAN11_BKPLANE_MGMT_TYPE_VPP (0x01) > + > +typedef struct _MPI3_MAN11_GAS_GAUGE_DEVICE_FORMAT { > + U8 Type; /* 0x00 */ > + U8 Reserved01[3]; /* 0x01 */ > + U32 Reserved04; /* 0x04 */ > +} MPI3_MAN11_GAS_GAUGE_DEVICE_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_GAS_GAUGE_DEVICE_FORMAT, > + Mpi3Man11GasGaugeDeviceFormat_t, MPI3_POINTER pMpi3Man11GasGaugeDeviceFormat_t; > + > +/**** Defines for the Type field ****/ > +#define MPI3_MAN11_GAS_GAUGE_TYPE_STANDARD (0x00) > + > +typedef union _MPI3_MAN11_DEVICE_SPECIFIC_FORMAT { > + MPI3_MAN11_MUX_DEVICE_FORMAT Mux; > + MPI3_MAN11_TEMP_SENSOR_DEVICE_FORMAT TempSensor; > + MPI3_MAN11_SEEPROM_DEVICE_FORMAT Seeprom; > + MPI3_MAN11_DDR_SPD_DEVICE_FORMAT DdrSpd; > + MPI3_MAN11_CABLE_MGMT_DEVICE_FORMAT CableMgmt; > + MPI3_MAN11_BKPLANE_MGMT_DEVICE_FORMAT BkplaneMgmt; > + MPI3_MAN11_GAS_GAUGE_DEVICE_FORMAT GasGauge; > + U32 Words[2]; > +} MPI3_MAN11_DEVICE_SPECIFIC_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_DEVICE_SPECIFIC_FORMAT, > + Mpi3Man11DeviceSpecificFormat_t, MPI3_POINTER pMpi3Man11DeviceSpecificFormat_t; > + > +typedef struct _MPI3_MAN11_ISTWI_DEVICE_FORMAT { > + U8 DeviceType; /* 0x00 */ > + U8 Controller; /* 0x01 */ > + U8 Reserved02; /* 0x02 */ > + U8 Flags; /* 0x03 */ > + U16 DeviceAddress; /* 0x04 */ > + U8 MuxChannel; /* 0x06 */ > + U8 MuxIndex; /* 0x07 */ > + MPI3_MAN11_DEVICE_SPECIFIC_FORMAT DeviceSpecific; /* 0x08 */ > +} MPI3_MAN11_ISTWI_DEVICE_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_ISTWI_DEVICE_FORMAT, > + Mpi3Man11IstwiDeviceFormat_t, MPI3_POINTER pMpi3Man11IstwiDeviceFormat_t; > + > +/**** Defines for the DeviceType field ****/ > +#define MPI3_MAN11_ISTWI_DEVTYPE_MUX (0x00) > +#define MPI3_MAN11_ISTWI_DEVTYPE_TEMP_SENSOR (0x01) > +#define MPI3_MAN11_ISTWI_DEVTYPE_SEEPROM (0x02) > +#define MPI3_MAN11_ISTWI_DEVTYPE_DDR_SPD (0x03) > +#define MPI3_MAN11_ISTWI_DEVTYPE_CABLE_MGMT (0x04) > +#define MPI3_MAN11_ISTWI_DEVTYPE_BACKPLANE_MGMT (0x05) > +#define MPI3_MAN11_ISTWI_DEVTYPE_GAS_GAUGE (0x06) > + > +/**** Defines for the Flags field ****/ > +#define MPI3_MAN11_ISTWI_FLAGS_MUX_PRESENT (0x01) > +#define MPI3_MAN11_ISTWI_FLAGS_BUS_SPEED_MASK (0x06) > +#define MPI3_MAN11_ISTWI_FLAGS_BUS_SPEED_100KHZ (0x00) > +#define MPI3_MAN11_ISTWI_FLAGS_BUS_SPEED_400KHZ (0x02) > + > +#ifndef MPI3_MAN11_ISTWI_DEVICE_MAX > +#define MPI3_MAN11_ISTWI_DEVICE_MAX (1) > +#endif /* MPI3_MAN11_ISTWI_DEVICE_MAX */ > + > +typedef struct _MPI3_MAN_PAGE11 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08; /* 0x08 */ > + U8 NumISTWIDev; /* 0x0C */ > + U8 Reserved0D[3]; /* 0x0D */ > + MPI3_MAN11_ISTWI_DEVICE_FORMAT ISTWIDevice[MPI3_MAN11_ISTWI_DEVICE_MAX]; /* 0x10 */ > +} MPI3_MAN_PAGE11, MPI3_POINTER PTR_MPI3_MAN_PAGE11, > + Mpi3ManPage11_t, MPI3_POINTER pMpi3ManPage11_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_MAN11_PAGEVERSION (0x00) > + > + > +/***************************************************************************** > + * Manufacturing Page 12 * > + ****************************************************************************/ > +#ifndef MPI3_MAN12_NUM_SGPIO_MAX > +#define MPI3_MAN12_NUM_SGPIO_MAX (1) > +#endif /* MPI3_MAN12_NUM_SGPIO_MAX */ > + > +typedef struct _MPI3_MAN12_SGPIO_INFO { > + U8 SlotCount; /* 0x00 */ > + U8 Reserved01[3]; /* 0x01 */ > + U32 Reserved04; /* 0x04 */ > + U8 PhyOrder[32]; /* 0x08 */ > +} MPI3_MAN12_SGPIO_INFO, MPI3_POINTER PTR_MPI3_MAN12_SGPIO_INFO, > + Mpi3Man12SGPIOInfo, MPI3_POINTER pMpi3Man12SGPIOInfo; > + > +typedef struct _MPI3_MAN_PAGE12 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Flags; /* 0x08 */ > + U32 SClockFreq; /* 0x0C */ > + U32 ActivityModulation; /* 0x10 */ > + U8 NumSGPIO; /* 0x14 */ > + U8 Reserved15[3]; /* 0x15 */ > + U32 Reserved18; /* 0x18 */ > + U32 Reserved1C; /* 0x1C */ > + U32 Pattern[8]; /* 0x20 */ > + MPI3_MAN12_SGPIO_INFO SGPIOInfo[MPI3_MAN12_NUM_SGPIO_MAX]; /* 0x40 */ /* variable length */ > +} MPI3_MAN_PAGE12, MPI3_POINTER PTR_MPI3_MAN_PAGE12, > + Mpi3ManPage12_t, MPI3_POINTER pMpi3ManPage12_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_MAN12_PAGEVERSION (0x00) > + > +/**** Defines for the Flags field ****/ > +#define MPI3_MAN12_FLAGS_ERROR_PRESENCE_ENABLED (0x0400) > +#define MPI3_MAN12_FLAGS_ACTIVITY_INVERT_ENABLED (0x0200) > +#define MPI3_MAN12_FLAGS_GROUP_ID_DISABLED (0x0100) > +#define MPI3_MAN12_FLAGS_SIO_CLK_FILTER_ENABLED (0x0004) > +#define MPI3_MAN12_FLAGS_SCLOCK_SLOAD_TYPE_MASK (0x0002) > +#define MPI3_MAN12_FLAGS_SCLOCK_SLOAD_TYPE_PUSH_PULL (0x0000) > +#define MPI3_MAN12_FLAGS_SCLOCK_SLOAD_TYPE_OPEN_DRAIN (0x0002) > +#define MPI3_MAN12_FLAGS_SDATAOUT_TYPE_MASK (0x0001) > +#define MPI3_MAN12_FLAGS_SDATAOUT_TYPE_PUSH_PULL (0x0000) > +#define MPI3_MAN12_FLAGS_SDATAOUT_TYPE_OPEN_DRAIN (0x0001) > + > +/**** Defines for the SioClkFreq field ****/ > +#define MPI3_MAN12_SIO_CLK_FREQ_MIN (32) /* 32 Hz min SIO Clk Freq */ > +#define MPI3_MAN12_SIO_CLK_FREQ_MAX (100000) /* 100 KHz max SIO Clk Freq */ > + > +/**** Defines for the ActivityModulation field ****/ > +#define MPI3_MAN12_ACTIVITY_MODULATION_FORCE_OFF_MASK (0x0000F000) > +#define MPI3_MAN12_ACTIVITY_MODULATION_FORCE_OFF_SHIFT (12) > +#define MPI3_MAN12_ACTIVITY_MODULATION_MAX_ON_MASK (0x00000F00) > +#define MPI3_MAN12_ACTIVITY_MODULATION_MAX_ON_SHIFT (8) > +#define MPI3_MAN12_ACTIVITY_MODULATION_STRETCH_OFF_MASK (0x000000F0) > +#define MPI3_MAN12_ACTIVITY_MODULATION_STRETCH_OFF_SHIFT (4) > +#define MPI3_MAN12_ACTIVITY_MODULATION_STRETCH_ON_MASK (0x0000000F) > +#define MPI3_MAN12_ACTIVITY_MODULATION_STRETCH_ON_SHIFT (0) > + > +/*** Defines for the Pattern field ****/ > +#define MPI3_MAN12_PATTERN_RATE_MASK (0xE0000000) > +#define MPI3_MAN12_PATTERN_RATE_2_HZ (0x00000000) > +#define MPI3_MAN12_PATTERN_RATE_4_HZ (0x20000000) > +#define MPI3_MAN12_PATTERN_RATE_8_HZ (0x40000000) > +#define MPI3_MAN12_PATTERN_RATE_16_HZ (0x60000000) > +#define MPI3_MAN12_PATTERN_RATE_10_HZ (0x80000000) > +#define MPI3_MAN12_PATTERN_RATE_20_HZ (0xA0000000) > +#define MPI3_MAN12_PATTERN_RATE_40_HZ (0xC0000000) > +#define MPI3_MAN12_PATTERN_LENGTH_MASK (0x1F000000) > +#define MPI3_MAN12_PATTERN_LENGTH_SHIFT (24) > +#define MPI3_MAN12_PATTERN_BIT_PATTERN_MASK (0x00FFFFFF) > +#define MPI3_MAN12_PATTERN_BIT_PATTERN_SHIFT (0) > + > + > +/***************************************************************************** > + * Manufacturing Page 13 * > + ****************************************************************************/ > + > +#ifndef MPI3_MAN13_NUM_TRANSLATION_MAX > +#define MPI3_MAN13_NUM_TRANSLATION_MAX (1) > +#endif /* MPI3_MAN13_NUM_TRANSLATION_MAX */ > + > +typedef struct _MPI3_MAN13_TRANSLATION_INFO { > + U32 SlotStatus; /* 0x00 */ > + U32 Mask; /* 0x04 */ > + U8 Activity; /* 0x08 */ > + U8 Locate; /* 0x09 */ > + U8 Error; /* 0x0A */ > + U8 Reserved0B; /* 0x0B */ > +} MPI3_MAN13_TRANSLATION_INFO, MPI3_POINTER PTR_MPI3_MAN13_TRANSLATION_INFO, > + Mpi3Man13TranslationInfo, MPI3_POINTER pMpi3Man13TranslationInfo; > + > +/**** Defines for the SlotStatus field ****/ > +#define MPI3_MAN13_TRANSLATION_SLOTSTATUS_FAULT (0x20000000) > +#define MPI3_MAN13_TRANSLATION_SLOTSTATUS_DEVICE_OFF (0x10000000) > +#define MPI3_MAN13_TRANSLATION_SLOTSTATUS_DEVICE_ACTIVITY (0x00800000) > +#define MPI3_MAN13_TRANSLATION_SLOTSTATUS_DO_NOT_REMOVE (0x00400000) > +#define MPI3_MAN13_TRANSLATION_SLOTSTATUS_DEVICE_MISSING (0x00100000) > +#define MPI3_MAN13_TRANSLATION_SLOTSTATUS_INSERT (0x00080000) > +#define MPI3_MAN13_TRANSLATION_SLOTSTATUS_REMOVAL (0x00040000) > +#define MPI3_MAN13_TRANSLATION_SLOTSTATUS_IDENTIFY (0x00020000) > +#define MPI3_MAN13_TRANSLATION_SLOTSTATUS_OK (0x00008000) > +#define MPI3_MAN13_TRANSLATION_SLOTSTATUS_RESERVED_DEVICE (0x00004000) > +#define MPI3_MAN13_TRANSLATION_SLOTSTATUS_HOT_SPARE (0x00002000) > +#define MPI3_MAN13_TRANSLATION_SLOTSTATUS_CONSISTENCY_CHECK (0x00001000) > +#define MPI3_MAN13_TRANSLATION_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000800) > +#define MPI3_MAN13_TRANSLATION_SLOTSTATUS_IN_FAILED_ARRAY (0x00000400) > +#define MPI3_MAN13_TRANSLATION_SLOTSTATUS_REBUILD_REMAP (0x00000200) > +#define MPI3_MAN13_TRANSLATION_SLOTSTATUS_REBUILD_REMAP_ABORT (0x00000100) > +#define MPI3_MAN13_TRANSLATION_SLOTSTATUS_PREDICTED_FAILURE (0x00000040) > + > +/**** Defines for the Mask field - use MPI3_MAN13_TRANSLATION_SLOTSTATUS_ defines ****/ > + > +/**** Defines for the Activity, Locate, and Error fields ****/ > +#define MPI3_MAN13_BLINK_PATTERN_FORCE_OFF (0x00) > +#define MPI3_MAN13_BLINK_PATTERN_FORCE_ON (0x01) > +#define MPI3_MAN13_BLINK_PATTERN_PATTERN_0 (0x02) > +#define MPI3_MAN13_BLINK_PATTERN_PATTERN_1 (0x03) > +#define MPI3_MAN13_BLINK_PATTERN_PATTERN_2 (0x04) > +#define MPI3_MAN13_BLINK_PATTERN_PATTERN_3 (0x05) > +#define MPI3_MAN13_BLINK_PATTERN_PATTERN_4 (0x06) > +#define MPI3_MAN13_BLINK_PATTERN_PATTERN_5 (0x07) > +#define MPI3_MAN13_BLINK_PATTERN_PATTERN_6 (0x08) > +#define MPI3_MAN13_BLINK_PATTERN_PATTERN_7 (0x09) > +#define MPI3_MAN13_BLINK_PATTERN_ACTIVITY (0x0A) > +#define MPI3_MAN13_BLINK_PATTERN_ACTIVITY_TRAIL (0x0B) > + > +typedef struct _MPI3_MAN_PAGE13 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U8 NumTrans; /* 0x08 */ > + U8 Reserved09[3]; /* 0x09 */ > + U32 Reserved0C; /* 0x0C */ > + MPI3_MAN13_TRANSLATION_INFO Translation[MPI3_MAN13_NUM_TRANSLATION_MAX]; /* 0x10 */ /* variable length */ > +} MPI3_MAN_PAGE13, MPI3_POINTER PTR_MPI3_MAN_PAGE13, > + Mpi3ManPage13_t, MPI3_POINTER pMpi3ManPage13_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_MAN13_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * Manufacturing Page 14 * > + ****************************************************************************/ > + > +typedef struct _MPI3_MAN_PAGE14 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U16 Flags; /* 0x08 */ > + U16 Reserved0A; /* 0x0A */ > + U8 NumSlotGroups; /* 0x0C */ > + U8 NumSlots; /* 0x0D */ > + U16 MaxCertChainLength; /* 0x0E */ > + U32 SealedSlots; /* 0x10 */ > +} MPI3_MAN_PAGE14, MPI3_POINTER PTR_MPI3_MAN_PAGE14, > + Mpi3ManPage14_t, MPI3_POINTER pMpi3ManPage14_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_MAN14_PAGEVERSION (0x00) > + > +/**** Defines for the Flags field ****/ > +#define MPI3_MAN14_FLAGS_AUTH_SESSION_REQ (0x01) > +#define MPI3_MAN14_FLAGS_AUTH_API_MASK (0x0E) > +#define MPI3_MAN14_FLAGS_AUTH_API_NONE (0x00) > +#define MPI3_MAN14_FLAGS_AUTH_API_CEREBUS (0x02) > +#define MPI3_MAN14_FLAGS_AUTH_API_DMTF_PMCI (0x04) > + > +/***************************************************************************** > + * Manufacturing Page 15 * > + ****************************************************************************/ > + > +#ifndef MPI3_MAN15_VERSION_RECORD_MAX > +#define MPI3_MAN15_VERSION_RECORD_MAX 1 > +#endif /* MPI3_MAN15_VERSION_RECORD_MAX */ > + > +typedef struct _MPI3_MAN15_VERSION_RECORD { > + U16 SPDMVersion; /* 0x00 */ > + U16 Reserved02; /* 0x02 */ > +} MPI3_MAN15_VERSION_RECORD, MPI3_POINTER PTR_MPI3_MAN15_VERSION_RECORD, > + Mpi3Man15VersionRecord_t, MPI3_POINTER pMpi3Man15VersionRecord_t; > + > +typedef struct _MPI3_MAN_PAGE15 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U8 NumVersionRecords; /* 0x08 */ > + U8 Reserved09[3]; /* 0x09 */ > + U32 Reserved0C; /* 0x0C */ > + MPI3_MAN15_VERSION_RECORD VersionRecord[MPI3_MAN15_VERSION_RECORD_MAX]; /* 0x10 */ > +} MPI3_MAN_PAGE15, MPI3_POINTER PTR_MPI3_MAN_PAGE15, > + Mpi3ManPage15_t, MPI3_POINTER pMpi3ManPage15_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_MAN15_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * Manufacturing Page 16 * > + ****************************************************************************/ > + > +#ifndef MPI3_MAN16_CERT_ALGO_MAX > +#define MPI3_MAN16_CERT_ALGO_MAX 1 > +#endif /* MPI3_MAN16_CERT_ALGO_MAX */ > + > +typedef struct _MPI3_MAN16_CERTIFICATE_ALGORITHM { > + U8 SlotGroup; /* 0x00 */ > + U8 Reserved01[3]; /* 0x01 */ > + U32 BaseAsymAlgo; /* 0x04 */ > + U32 BaseHashAlgo; /* 0x08 */ > + U32 Reserved0C[3]; /* 0x0C */ > +} MPI3_MAN16_CERTIFICATE_ALGORITHM, MPI3_POINTER PTR_MPI3_MAN16_CERTIFICATE_ALGORITHM, > + Mpi3Man16CertificateAlgorithm_t, MPI3_POINTER pMpi3Man16CertificateAlgorithm_t; > + > +typedef struct _MPI3_MAN_PAGE16 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08; /* 0x08 */ > + U8 NumCertAlgos; /* 0x0C */ > + U8 Reserved0D[3]; /* 0x0D */ > + MPI3_MAN16_CERTIFICATE_ALGORITHM CertificateAlgorithm[MPI3_MAN16_CERT_ALGO_MAX]; /* 0x10 */ > +} MPI3_MAN_PAGE16, MPI3_POINTER PTR_MPI3_MAN_PAGE16, > + Mpi3ManPage16_t, MPI3_POINTER pMpi3ManPage16_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_MAN16_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * Manufacturing Page 17 * > + ****************************************************************************/ > + > +#ifndef MPI3_MAN17_HASH_ALGORITHM_MAX > +#define MPI3_MAN17_HASH_ALGORITHM_MAX 1 > +#endif /* MPI3_MAN17_HASH_ALGORITHM_MAX */ > + > +typedef struct _MPI3_MAN17_HASH_ALGORITHM { > + U8 MeasSpecification; /* 0x00 */ > + U8 Reserved01[3]; /* 0x01 */ > + U32 MeasurementHashAlgo; /* 0x04 */ > + U32 Reserved08[2]; /* 0x08 */ > +} MPI3_MAN17_HASH_ALGORITHM, MPI3_POINTER PTR_MPI3_MAN17_HASH_ALGORITHM, > + Mpi3Man17HashAlgorithm_t, MPI3_POINTER pMpi3Man17HashAlgorithm_t; > + > +typedef struct _MPI3_MAN_PAGE17 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08; /* 0x08 */ > + U8 NumHashAlgos; /* 0x0C */ > + U8 Reserved0D[3]; /* 0x0D */ > + MPI3_MAN17_HASH_ALGORITHM HashAlgorithm[MPI3_MAN17_HASH_ALGORITHM_MAX]; /* 0x10 */ > +} MPI3_MAN_PAGE17, MPI3_POINTER PTR_MPI3_MAN_PAGE17, > + Mpi3ManPage17_t, MPI3_POINTER pMpi3ManPage17_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_MAN17_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * Manufacturing Page 20 * > + ****************************************************************************/ > + > +typedef struct _MPI3_MAN_PAGE20 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08; /* 0x08 */ > + U32 NonpremiumFeatures; /* 0x0C */ > + U8 AllowedPersonalities; /* 0x10 */ > + U8 Reserved11[3]; /* 0x11 */ > +} MPI3_MAN_PAGE20, MPI3_POINTER PTR_MPI3_MAN_PAGE20, > + Mpi3ManPage20_t, MPI3_POINTER pMpi3ManPage20_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_MAN20_PAGEVERSION (0x00) > + > +/**** Defines for the AllowedPersonalities field ****/ > +#define MPI3_MAN20_ALLOWEDPERSON_RAID_MASK (0x02) > +#define MPI3_MAN20_ALLOWEDPERSON_RAID_ALLOWED (0x02) > +#define MPI3_MAN20_ALLOWEDPERSON_RAID_NOT_ALLOWED (0x00) > +#define MPI3_MAN20_ALLOWEDPERSON_EHBA_MASK (0x01) > +#define MPI3_MAN20_ALLOWEDPERSON_EHBA_ALLOWED (0x01) > +#define MPI3_MAN20_ALLOWEDPERSON_EHBA_NOT_ALLOWED (0x00) > + > +/**** Defines for the NonpremuimFeatures field ****/ > +#define MPI3_MAN20_NONPREMUIM_DISABLE_PD_DEGRADED_MASK (0x01) > +#define MPI3_MAN20_NONPREMUIM_DISABLE_PD_DEGRADED_ENABLED (0x00) > +#define MPI3_MAN20_NONPREMUIM_DISABLE_PD_DEGRADED_DISABLED (0x01) > + > +/***************************************************************************** > + * Manufacturing Page 21 * > + ****************************************************************************/ > + > +typedef struct _MPI3_MAN_PAGE21 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08; /* 0x08 */ > + U32 Flags; /* 0x0C */ > +} MPI3_MAN_PAGE21, MPI3_POINTER PTR_MPI3_MAN_PAGE21, > + Mpi3ManPage21_t, MPI3_POINTER pMpi3ManPage21_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_MAN21_PAGEVERSION (0x00) > + > +/**** Defines for the Flags field ****/ > +#define MPI3_MAN21_FLAGS_HOST_METADATA_CAPABILITY_MASK (0x80) > +#define MPI3_MAN21_FLAGS_HOST_METADATA_CAPABILITY_ENABLED (0x80) > +#define MPI3_MAN21_FLAGS_HOST_METADATA_CAPABILITY_DISABLED (0x00) > +#define MPI3_MAN21_FLAGS_UNCERTIFIED_DRIVES_MASK (0x60) > +#define MPI3_MAN21_FLAGS_UNCERTIFIED_DRIVES_BLOCK (0x00) > +#define MPI3_MAN21_FLAGS_UNCERTIFIED_DRIVES_ALLOW (0x20) > +#define MPI3_MAN21_FLAGS_UNCERTIFIED_DRIVES_WARN (0x40) > +#define MPI3_MAN21_FLAGS_BLOCK_SSD_WR_CACHE_CHANGE_MASK (0x08) > +#define MPI3_MAN21_FLAGS_BLOCK_SSD_WR_CACHE_CHANGE_ALLOW (0x00) > +#define MPI3_MAN21_FLAGS_BLOCK_SSD_WR_CACHE_CHANGE_PREVENT (0x08) > +#define MPI3_MAN21_FLAGS_SES_VPD_ASSOC_MASK (0x01) > +#define MPI3_MAN21_FLAGS_SES_VPD_ASSOC_DEFAULT (0x00) > +#define MPI3_MAN21_FLAGS_SES_VPD_ASSOC_OEM_SPECIFIC (0x01) > + > +/***************************************************************************** > + * Manufacturing Pages 32-63 (ProductSpecific) * > + ****************************************************************************/ > +#ifndef MPI3_MAN_PROD_SPECIFIC_MAX > +#define MPI3_MAN_PROD_SPECIFIC_MAX (1) > +#endif /* MPI3_MAN_PROD_SPECIFIC_MAX */ > + > +typedef struct _MPI3_MAN_PAGE_PRODUCT_SPECIFIC { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 ProductSpecificInfo[MPI3_MAN_PROD_SPECIFIC_MAX]; /* 0x08 */ /* variable length array */ > +} MPI3_MAN_PAGE_PRODUCT_SPECIFIC, MPI3_POINTER PTR_MPI3_MAN_PAGE_PRODUCT_SPECIFIC, > + Mpi3ManPageProductSpecific_t, MPI3_POINTER pMpi3ManPageProductSpecific_t; > + > +/***************************************************************************** > + * IO Unit Configuration Pages * > + ****************************************************************************/ > + > +/***************************************************************************** > + * IO Unit Page 0 * > + ****************************************************************************/ > +typedef struct _MPI3_IO_UNIT_PAGE0 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U64 UniqueValue; /* 0x08 */ > + U32 NvdataVersionDefault; /* 0x10 */ > + U32 NvdataVersionPersistent; /* 0x14 */ > +} MPI3_IO_UNIT_PAGE0, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE0, > + Mpi3IOUnitPage0_t, MPI3_POINTER pMpi3IOUnitPage0_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_IOUNIT0_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * IO Unit Page 1 * > + ****************************************************************************/ > +typedef struct _MPI3_IO_UNIT_PAGE1 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Flags; /* 0x08 */ > + U8 DMDIoDelay; /* 0x0C */ > + U8 DMDReportPCIe; /* 0x0D */ > + U8 DMDReportSATA; /* 0x0E */ > + U8 DMDReportSAS; /* 0x0F */ > +} MPI3_IO_UNIT_PAGE1, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE1, > + Mpi3IOUnitPage1_t, MPI3_POINTER pMpi3IOUnitPage1_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_IOUNIT1_PAGEVERSION (0x00) > + > +/**** Defines for the Flags field ****/ > +#define MPI3_IOUNIT1_FLAGS_NVME_WRITE_CACHE_MASK (0x00000030) > +#define MPI3_IOUNIT1_FLAGS_NVME_WRITE_CACHE_ENABLE (0x00000000) > +#define MPI3_IOUNIT1_FLAGS_NVME_WRITE_CACHE_DISABLE (0x00000010) > +#define MPI3_IOUNIT1_FLAGS_NVME_WRITE_CACHE_NO_MODIFY (0x00000020) > +#define MPI3_IOUNIT1_FLAGS_ATA_SECURITY_FREEZE_LOCK (0x00000008) > +#define MPI3_IOUNIT1_FLAGS_WRITE_SAME_BUFFER (0x00000004) > +#define MPI3_IOUNIT1_FLAGS_SATA_WRITE_CACHE_MASK (0x00000003) > +#define MPI3_IOUNIT1_FLAGS_SATA_WRITE_CACHE_ENABLE (0x00000000) > +#define MPI3_IOUNIT1_FLAGS_SATA_WRITE_CACHE_DISABLE (0x00000001) > +#define MPI3_IOUNIT1_FLAGS_SATA_WRITE_CACHE_UNCHANGED (0x00000002) > + > +/**** Defines for the DMDReport PCIe/SATA/SAS fields ****/ > +#define MPI3_IOUNIT1_DMD_REPORT_DELAY_TIME_MASK (0x7F) > +#define MPI3_IOUNIT1_DMD_REPORT_UNIT_16_SEC (0x80) > + > +/***************************************************************************** > + * IO Unit Page 2 * > + ****************************************************************************/ > +#ifndef MPI3_IO_UNIT2_GPIO_VAL_MAX > +#define MPI3_IO_UNIT2_GPIO_VAL_MAX (1) > +#endif /* MPI3_IO_UNIT2_GPIO_VAL_MAX */ > + > +typedef struct _MPI3_IO_UNIT_PAGE2 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U8 GPIOCount; /* 0x08 */ > + U8 Reserved09[3]; /* 0x09 */ > + U16 GPIOVal[MPI3_IO_UNIT2_GPIO_VAL_MAX]; /* 0x0C */ > +} MPI3_IO_UNIT_PAGE2, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE2, > + Mpi3IOUnitPage2_t, MPI3_POINTER pMpi3IOUnitPage2_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_IOUNIT2_PAGEVERSION (0x00) > + > +/**** Define for the GPIOVal field ****/ > +#define MPI3_IOUNIT2_GPIO_FUNCTION_MASK (0xFFFC) > +#define MPI3_IOUNIT2_GPIO_FUNCTION_SHIFT (2) > +#define MPI3_IOUNIT2_GPIO_SETTING_MASK (0x0001) > +#define MPI3_IOUNIT2_GPIO_SETTING_OFF (0x0000) > +#define MPI3_IOUNIT2_GPIO_SETTING_ON (0x0001) > + > +/***************************************************************************** > + * IO Unit Page 3 * > + ****************************************************************************/ > + > +typedef struct _MPI3_IO_UNIT3_SENSOR { > + U16 Flags; /* 0x00 */ > + U16 Reserved02; /* 0x02 */ > + U16 Threshold[4]; /* 0x04 */ > + U32 Reserved0C; /* 0x0C */ > + U32 Reserved10; /* 0x10 */ > + U32 Reserved14; /* 0x14 */ > +} MPI3_IO_UNIT3_SENSOR, MPI3_POINTER PTR_MPI3_IO_UNIT3_SENSOR, > + Mpi3IOUnit3Sensor_t, MPI3_POINTER pMpi3IOUnit3Sensor_t; > + > +/**** Defines for the Flags field ****/ > +#define MPI3_IOUNIT3_SENSOR_FLAGS_T3_ENABLE (0x0008) > +#define MPI3_IOUNIT3_SENSOR_FLAGS_T2_ENABLE (0x0004) > +#define MPI3_IOUNIT3_SENSOR_FLAGS_T1_ENABLE (0x0002) > +#define MPI3_IOUNIT3_SENSOR_FLAGS_T0_ENABLE (0x0001) > + > +#ifndef MPI3_IO_UNIT3_SENSOR_MAX > +#define MPI3_IO_UNIT3_SENSOR_MAX (1) > +#endif /* MPI3_IO_UNIT3_SENSOR_MAX */ > + > +typedef struct _MPI3_IO_UNIT_PAGE3 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08; /* 0x08 */ > + U8 NumSensors; /* 0x0C */ > + U8 PollingInterval; /* 0x0D */ > + U16 Reserved0E; /* 0x0E */ > + MPI3_IO_UNIT3_SENSOR Sensor[MPI3_IO_UNIT3_SENSOR_MAX]; /* 0x10 */ > +} MPI3_IO_UNIT_PAGE3, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE3, > + Mpi3IOUnitPage3_t, MPI3_POINTER pMpi3IOUnitPage3_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_IOUNIT3_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * IO Unit Page 4 * > + ****************************************************************************/ > +typedef struct _MPI3_IO_UNIT4_SENSOR { > + U16 CurrentTemperature; /* 0x00 */ > + U16 Reserved02; /* 0x02 */ > + U8 Flags; /* 0x04 */ > + U8 Reserved05[3]; /* 0x05 */ > + U32 Reserved08; /* 0x08 */ > + U32 Reserved0C; /* 0x0C */ > +} MPI3_IO_UNIT4_SENSOR, MPI3_POINTER PTR_MPI3_IO_UNIT4_SENSOR, > + Mpi3IOUnit4Sensor_t, MPI3_POINTER pMpi3IOUnit4Sensor_t; > + > +/**** Defines for the Flags field ****/ > +#define MPI3_IOUNIT4_SENSOR_FLAGS_TEMP_VALID (0x01) > + > +#ifndef MPI3_IO_UNIT4_SENSOR_MAX > +#define MPI3_IO_UNIT4_SENSOR_MAX (1) > +#endif /* MPI3_IO_UNIT4_SENSOR_MAX */ > + > +typedef struct _MPI3_IO_UNIT_PAGE4 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08; /* 0x08 */ > + U8 NumSensors; /* 0x0C */ > + U8 Reserved0D[3]; /* 0x0D */ > + MPI3_IO_UNIT4_SENSOR Sensor[MPI3_IO_UNIT4_SENSOR_MAX]; /* 0x10 */ > +} MPI3_IO_UNIT_PAGE4, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE4, > + Mpi3IOUnitPage4_t, MPI3_POINTER pMpi3IOUnitPage4_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_IOUNIT4_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * IO Unit Page 5 * > + ****************************************************************************/ > +typedef struct _MPI3_IO_UNIT5_SPINUP_GROUP { > + U8 MaxTargetSpinup; /* 0x00 */ > + U8 SpinupDelay; /* 0x01 */ > + U8 SpinupFlags; /* 0x02 */ > + U8 Reserved03; /* 0x03 */ > +} MPI3_IO_UNIT5_SPINUP_GROUP, MPI3_POINTER PTR_MPI3_IO_UNIT5_SPINUP_GROUP, > + Mpi3IOUnit5SpinupGroup_t, MPI3_POINTER pMpi3IOUnit5SpinupGroup_t; > + > +/**** Defines for the SpinupFlags field ****/ > +#define MPI3_IOUNIT5_SPINUP_FLAGS_DISABLE (0x01) > + > +#ifndef MPI3_IO_UNIT5_PHY_MAX > +#define MPI3_IO_UNIT5_PHY_MAX (4) > +#endif /* MPI3_IO_UNIT5_PHY_MAX */ > + > +typedef struct _MPI3_IO_UNIT_PAGE5 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + MPI3_IO_UNIT5_SPINUP_GROUP SpinupGroupParameters[4]; /* 0x08 */ > + U32 Reserved18; /* 0x18 */ > + U32 Reserved1C; /* 0x1C */ > + U32 Reserved20; /* 0x20 */ > + U8 Reserved24; /* 0x24 */ > + U8 SATADeviceWaitTime; /* 0x25 */ > + U8 SpinupEnclDriveCount; /* 0x26 */ > + U8 SpinupEnclDelay; /* 0x27 */ > + U8 NumPhys; /* 0x28 */ > + U8 PEInitialSpinupDelay; /* 0x29 */ > + U8 TopologyStableTime; /* 0x2A */ > + U8 Flags; /* 0x2B */ > + U8 Phy[MPI3_IO_UNIT5_PHY_MAX]; /* 0x2C */ > +} MPI3_IO_UNIT_PAGE5, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE5, > + Mpi3IOUnitPage5_t, MPI3_POINTER pMpi3IOUnitPage5_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_IOUNIT5_PAGEVERSION (0x00) > + > +/**** Defines for the Flags field ****/ > +#define MPI3_IOUNIT5_FLAGS_POWER_CAPABLE_SPINUP (0x02) > +#define MPI3_IOUNIT5_FLAGS_AUTO_PORT_ENABLE (0x01) > + > +/**** Defines for the PHY field ****/ > +#define MPI3_IOUNIT5_PHY_SPINUP_GROUP_MASK (0x03) > + > +/***************************************************************************** > + * IO Unit Page 6 * > + ****************************************************************************/ > +typedef struct _MPI3_IO_UNIT_PAGE6 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 BoardPowerRequirement; /* 0x08 */ > + U32 PCISlotPowerAllocation; /* 0x0C */ > + U8 Flags; /* 0x10 */ > + U8 Reserved11[3]; /* 0x11 */ > +} MPI3_IO_UNIT_PAGE6, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE6, > + Mpi3IOUnitPage6_t, MPI3_POINTER pMpi3IOUnitPage6_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_IOUNIT6_PAGEVERSION (0x00) > + > +/**** Defines for the Flags field ****/ > +#define MPI3_IOUNIT6_FLAGS_ACT_CABLE_PWR_EXC (0x01) > + > +/***************************************************************************** > + * IO Unit Page 7 * > + ****************************************************************************/ > +typedef struct _MPI3_IO_UNIT_PAGE7 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08; /* 0x08 */ > +} MPI3_IO_UNIT_PAGE7, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE7, > + Mpi3IOUnitPage7_t, MPI3_POINTER pMpi3IOUnitPage7_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_IOUNIT7_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * IO Unit Page 8 * > + ****************************************************************************/ > + > +#ifndef MPI3_IOUNIT8_DIGEST_MAX > +#define MPI3_IOUNIT8_DIGEST_MAX (1) > +#endif /* MPI3_IOUNIT8_DIGEST_MAX */ > + > +typedef union _MPI3_IOUNIT8_DIGEST { > + U32 Dword[16]; > + U16 Word[32]; > + U8 Byte[64]; > +} MPI3_IOUNIT8_DIGEST, MPI3_POINTER PTR_MPI3_IOUNIT8_DIGEST, > + Mpi3IOUnit8Digest, MPI3_POINTER pMpi3IOUnit8Digest; > + > +typedef struct _MPI3_IO_UNIT_PAGE8 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U8 SBMode; /* 0x08 */ > + U8 SbState; /* 0x09 */ > + U16 Reserved0A; /* 0x0A */ > + U8 NumSlots; /* 0x0C */ > + U8 SlotsAvailable; /* 0x0D */ > + U8 CurrentKeyEncryptionAlgo; /* 0x0E */ > + U8 KeyDigestHashAlgo; /* 0x0F */ > + U32 Reserved10[2]; /* 0x10 */ > + U32 CurrentKey[128]; /* 0x18 */ > + MPI3_IOUNIT8_DIGEST Digest[MPI3_IOUNIT8_DIGEST_MAX]; /* 0x218 */ /* variable length */ > +} MPI3_IO_UNIT_PAGE8, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE8, > + Mpi3IOUnitPage8_t, MPI3_POINTER pMpi3IOUnitPage8_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_IOUNIT8_PAGEVERSION (0x00) > + > +/**** Defines for the SBMode field ****/ > +#define MPI3_IOUNIT8_SBMODE_SECURE_DEBUG (0x04) > +#define MPI3_IOUNIT8_SBMODE_HARD_SECURE (0x02) > +#define MPI3_IOUNIT8_SBMODE_CONFIG_SECURE (0x01) > + > +/**** Defines for the SBState field ****/ > +#define MPI3_IOUNIT8_SBSTATE_KEY_UPDATE_PENDING (0x02) > +#define MPI3_IOUNIT8_SBSTATE_SECURE_BOOT_ENABLED (0x01) > + > +/***************************************************************************** > + * IO Unit Page 9 * > + ****************************************************************************/ > + > +typedef struct _MPI3_IO_UNIT_PAGE9 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Flags; /* 0x08 */ > + U16 FirstDevice; /* 0x0C */ > + U16 Reserved0E; /* 0x0E */ > +} MPI3_IO_UNIT_PAGE9, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE9, > + Mpi3IOUnitPage9_t, MPI3_POINTER pMpi3IOUnitPage9_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_IOUNIT9_PAGEVERSION (0x00) > + > +/**** Defines for the Flags field ****/ > +#define MPI3_IOUNIT9_FLAGS_VDFIRST_ENABLED (0x01) > + > +/**** Defines for the FirstDevice field ****/ > +#define MPI3_IOUNIT9_FIRSTDEVICE_UNKNOWN (0xFFFF) > + > +/***************************************************************************** > + * IOC Configuration Pages * > + ****************************************************************************/ > + > +/***************************************************************************** > + * IOC Page 0 * > + ****************************************************************************/ > +typedef struct _MPI3_IOC_PAGE0 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08; /* 0x08 */ > + U16 VendorID; /* 0x0C */ > + U16 DeviceID; /* 0x0E */ > + U8 RevisionID; /* 0x10 */ > + U8 Reserved11[3]; /* 0x11 */ > + U32 ClassCode; /* 0x14 */ > + U16 SubsystemVendorID; /* 0x18 */ > + U16 SubsystemID; /* 0x1A */ > +} MPI3_IOC_PAGE0, MPI3_POINTER PTR_MPI3_IOC_PAGE0, > + Mpi3IOCPage0_t, MPI3_POINTER pMpi3IOCPage0_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_IOC0_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * IOC Page 1 * > + ****************************************************************************/ > +typedef struct _MPI3_IOC_PAGE1 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 CoalescingTimeout; /* 0x08 */ > + U8 CoalescingDepth; /* 0x0C */ > + U8 PCISlotNum; /* 0x0D */ > + U16 Reserved0E; /* 0x0E */ > +} MPI3_IOC_PAGE1, MPI3_POINTER PTR_MPI3_IOC_PAGE1, > + Mpi3IOCPage1_t, MPI3_POINTER pMpi3IOCPage1_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_IOC1_PAGEVERSION (0x00) > + > +/**** Defines for the PCISlotNum field ****/ > +#define MPI3_IOC1_PCISLOTNUM_UNKNOWN (0xFF) > + > +/***************************************************************************** > + * IOC Page 2 * > + ****************************************************************************/ > +#ifndef MPI3_IOC2_EVENTMASK_WORDS > +#define MPI3_IOC2_EVENTMASK_WORDS (4) > +#endif /* MPI3_IOC2_EVENTMASK_WORDS */ > + > +typedef struct _MPI3_IOC_PAGE2 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08; /* 0x08 */ > + U16 SASBroadcastPrimitiveMasks; /* 0x0C */ > + U16 SASNotifyPrimitiveMasks; /* 0x0E */ > + U32 EventMasks[MPI3_IOC2_EVENTMASK_WORDS]; /* 0x10 */ > +} MPI3_IOC_PAGE2, MPI3_POINTER PTR_MPI3_IOC_PAGE2, > + Mpi3IOCPage2_t, MPI3_POINTER pMpi3IOCPage2_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_IOC2_PAGEVERSION (0x00) > + > + > +/***************************************************************************** > + * UEFI BSD and HII Configuration Pages * > + ****************************************************************************/ > +typedef struct _MPI3_UEFIBSD_PAGE0 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 BSDOptions; /* 0x08 */ > + U8 SSUTimeout; /* 0x0C */ > + U8 IOTimeout; /* 0x0D */ > + U8 TURRetries; /* 0x0E */ > + U8 TURInterval; /* 0x0F */ > + U8 Reserved10; /* 0x10 */ > + U8 SecurityKeyTimeout; /* 0x11 */ > + U16 Reserved12; /* 0x12 */ > + U32 Reserved14; /* 0x14 */ > + U32 Reserved18; /* 0x18 */ > +} MPI3_UEFIBSD_PAGE0, MPI3_POINTER PTR_MPI3_UEFIBSD_PAGE0, > + Mpi3UefiBsdPage0_t, MPI3_POINTER pMpi3UefiBsdPage0_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_UEFIBSD_PAGEVERSION (0x00) > + > +/**** Defines for the BSDOptions field ****/ > +#define MPI3_UEFIBSD_BSDOPTS_REGISTRATION_MASK (0x00000003) > +#define MPI3_UEFIBSD_BSDOPTS_REGISTRATION_IOC_AND_DEVS (0x00000000) > +#define MPI3_UEFIBSD_BSDOPTS_REGISTRATION_IOC_ONLY (0x00000001) > +#define MPI3_UEFIBSD_BSDOPTS_REGISTRATION_NONE (0x00000002) > +#define MPI3_UEFIBSD_BSDOPTS_DIS_HII_CONFIG_UTIL (0x00000004) > +#define MPI3_UEFIBSD_BSDOPTS_EN_ADV_ADAPTER_CONFIG (0x00000008) > + > + > +/***************************************************************************** > + * Security Configuration Pages * > + ****************************************************************************/ > + > +typedef union _MPI3_SECURITY_MAC { > + U32 Dword[16]; > + U16 Word[32]; > + U8 Byte[64]; > +} MPI3_SECURITY_MAC, MPI3_POINTER PTR_MPI3_SECURITY_MAC, > + Mpi3SecurityMAC_t, MPI3_POINTER pMpi3SecurityMAC_t; > + > +typedef union _MPI3_SECURITY_NONCE { > + U32 Dword[16]; > + U16 Word[32]; > + U8 Byte[64]; > +} MPI3_SECURITY_NONCE, MPI3_POINTER PTR_MPI3_SECURITY_NONCE, > + Mpi3SecurityNonce_t, MPI3_POINTER pMpi3SecurityNonce_t; > + > +/***************************************************************************** > + * Security Page 0 * > + ****************************************************************************/ > + > +typedef union _MPI3_SECURITY0_CERT_CHAIN { > + U32 Dword[1024]; > + U16 Word[2048]; > + U8 Byte[4096]; > +} MPI3_SECURITY0_CERT_CHAIN, MPI3_POINTER PTR_MPI3_SECURITY0_CERT_CHAIN, > + Mpi3Security0CertChain_t, MPI3_POINTER pMpi3Security0CertChain_t; > + > +typedef struct _MPI3_SECURITY_PAGE0 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U8 SlotNumGroup; /* 0x08 */ > + U8 SlotNum; /* 0x09 */ > + U16 CertChainLength; /* 0x0A */ > + U8 CertChainFlags; /* 0x0C */ > + U8 Reserved0D[3]; /* 0x0D */ > + U32 BaseAsymAlgo; /* 0x10 */ > + U32 BaseHashAlgo; /* 0x14 */ > + U32 Reserved18[4]; /* 0x18 */ > + MPI3_SECURITY_MAC MAC; /* 0x28 */ > + MPI3_SECURITY_NONCE Nonce; /* 0x68 */ > + MPI3_SECURITY0_CERT_CHAIN CertificateChain; /* 0xA8 */ > +} MPI3_SECURITY_PAGE0, MPI3_POINTER PTR_MPI3_SECURITY_PAGE0, > + Mpi3SecurityPage0_t, MPI3_POINTER pMpi3SecurityPage0_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_SECURITY0_PAGEVERSION (0x00) > + > +/**** Defines for the CertChainFlags field ****/ > +#define MPI3_SECURITY0_CERTCHAIN_FLAGS_AUTH_API_MASK (0x0E) > +#define MPI3_SECURITY0_CERTCHAIN_FLAGS_AUTH_API_UNUSED (0x00) > +#define MPI3_SECURITY0_CERTCHAIN_FLAGS_AUTH_API_CERBERUS (0x02) > +#define MPI3_SECURITY0_CERTCHAIN_FLAGS_AUTH_API_SPDM (0x04) > +#define MPI3_SECURITY0_CERTCHAIN_FLAGS_SEALED (0x01) > + > +/***************************************************************************** > + * Security Page 1 * > + ****************************************************************************/ > + > +#ifndef MPI3_SECURITY1_KEY_RECORD_MAX > +#define MPI3_SECURITY1_KEY_RECORD_MAX 1 > +#endif /* MPI3_SECURITY1_KEY_RECORD_MAX */ > + > +#ifndef MPI3_SECURITY1_PAD_MAX > +#define MPI3_SECURITY1_PAD_MAX 1 > +#endif /* MPI3_SECURITY1_PAD_MAX */ > + > +typedef union _MPI3_SECURITY1_KEY_DATA { > + U32 Dword[128]; > + U16 Word[256]; > + U8 Byte[512]; > +} MPI3_SECURITY1_KEY_DATA, MPI3_POINTER PTR_MPI3_SECURITY1_KEY_DATA, > + Mpi3Security1KeyData_t, MPI3_POINTER pMpi3Security1KeyData_t; > + > +typedef struct _MPI3_SECURITY1_KEY_RECORD { > + U8 Flags; /* 0x00 */ > + U8 Consumer; /* 0x01 */ > + U16 KeyDataSize; /* 0x02 */ > + U32 AdditionalKeyData; /* 0x04 */ > + U32 Reserved08[2]; /* 0x08 */ > + MPI3_SECURITY1_KEY_DATA KeyData; /* 0x10 */ > +} MPI3_SECURITY1_KEY_RECORD, MPI3_POINTER PTR_MPI3_SECURITY1_KEY_RECORD, > + Mpi3Security1KeyRecord_t, MPI3_POINTER pMpi3Security1KeyRecord_t; > + > +/**** Defines for the Flags field ****/ > +#define MPI3_SECURITY1_KEY_RECORD_FLAGS_TYPE_MASK (0x1F) > +#define MPI3_SECURITY1_KEY_RECORD_FLAGS_TYPE_NOT_VALID (0x00) > +#define MPI3_SECURITY1_KEY_RECORD_FLAGS_TYPE_HMAC (0x01) > +#define MPI3_SECURITY1_KEY_RECORD_FLAGS_TYPE_AES (0x02) > +#define MPI3_SECURITY1_KEY_RECORD_FLAGS_TYPE_ECDSA_PRIVATE (0x03) > +#define MPI3_SECURITY1_KEY_RECORD_FLAGS_TYPE_ECDSA_PUBLIC (0x04) > + > +/**** Defines for the Consumer field ****/ > +#define MPI3_SECURITY1_KEY_RECORD_CONSUMER_NOT_VALID (0x00) > +#define MPI3_SECURITY1_KEY_RECORD_CONSUMER_SAFESTORE (0x01) > +#define MPI3_SECURITY1_KEY_RECORD_CONSUMER_CERT_CHAIN (0x02) > +#define MPI3_SECURITY1_KEY_RECORD_CONSUMER_AUTH_DEV_KEY (0x03) > +#define MPI3_SECURITY1_KEY_RECORD_CONSUMER_CACHE_OFFLOAD (0x04) > + > +typedef struct _MPI3_SECURITY_PAGE1 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08[2]; /* 0x08 */ > + MPI3_SECURITY_MAC MAC; /* 0x10 */ > + MPI3_SECURITY_NONCE Nonce; /* 0x50 */ > + U8 NumKeys; /* 0x90 */ > + U8 Reserved91[3]; /* 0x91 */ > + U32 Reserved94[3]; /* 0x94 */ > + MPI3_SECURITY1_KEY_RECORD KeyRecord[MPI3_SECURITY1_KEY_RECORD_MAX]; /* 0xA0 */ > + U8 Pad[MPI3_SECURITY1_PAD_MAX]; /* ?? */ > +} MPI3_SECURITY_PAGE1, MPI3_POINTER PTR_MPI3_SECURITY_PAGE1, > + Mpi3SecurityPage1_t, MPI3_POINTER pMpi3SecurityPage1_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_SECURITY1_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * SAS IO Unit Configuration Pages * > + ****************************************************************************/ > + > +/***************************************************************************** > + * SAS IO Unit Page 0 * > + ****************************************************************************/ > +typedef struct _MPI3_SAS_IO_UNIT0_PHY_DATA { > + U8 IOUnitPort; /* 0x00 */ > + U8 PortFlags; /* 0x01 */ > + U8 PhyFlags; /* 0x02 */ > + U8 NegotiatedLinkRate; /* 0x03 */ > + U16 ControllerPhyDeviceInfo; /* 0x04 */ > + U16 Reserved06; /* 0x06 */ > + U16 AttachedDevHandle; /* 0x08 */ > + U16 ControllerDevHandle; /* 0x0A */ > + U32 DiscoveryStatus; /* 0x0C */ > + U32 Reserved10; /* 0x10 */ > +} MPI3_SAS_IO_UNIT0_PHY_DATA, MPI3_POINTER PTR_MPI3_SAS_IO_UNIT0_PHY_DATA, > + Mpi3SasIOUnit0PhyData_t, MPI3_POINTER pMpi3SasIOUnit0PhyData_t; > + > +#ifndef MPI3_SAS_IO_UNIT0_PHY_MAX > +#define MPI3_SAS_IO_UNIT0_PHY_MAX (1) > +#endif /* MPI3_SAS_IO_UNIT0_PHY_MAX */ > + > +typedef struct _MPI3_SAS_IO_UNIT_PAGE0 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08; /* 0x08 */ > + U8 NumPhys; /* 0x0C */ > + U8 Reserved0D[3]; /* 0x0D */ > + MPI3_SAS_IO_UNIT0_PHY_DATA PhyData[MPI3_SAS_IO_UNIT0_PHY_MAX]; /* 0x10 */ > +} MPI3_SAS_IO_UNIT_PAGE0, MPI3_POINTER PTR_MPI3_SAS_IO_UNIT_PAGE0, > + Mpi3SasIOUnitPage0_t, MPI3_POINTER pMpi3SasIOUnitPage0_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_SASIOUNIT0_PAGEVERSION (0x00) > + > +/**** Defines for the PortFlags field ****/ > +#define MPI3_SASIOUNIT0_PORTFLAGS_DISC_IN_PROGRESS (0x08) > +#define MPI3_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG (0x01) > + > +/**** Defines for the PhyFlags field ****/ > +#define MPI3_SASIOUNIT0_PHYFLAGS_INIT_PERSIST_CONNECT (0x40) > +#define MPI3_SASIOUNIT0_PHYFLAGS_TARG_PERSIST_CONNECT (0x20) > +#define MPI3_SASIOUNIT0_PHYFLAGS_PHY_DISABLED (0x08) > + > +/**** Use MPI3_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field ****/ > + > +/**** Use MPI3_SAS_DEVICE_INFO_ defines (see mpi30_sas.h) for the ControllerPhyDeviceInfo field ****/ > + > +/**** Use MPI3_SAS_DISC_STATUS_ defines (see mpi30_ioc.h) for the DiscoveryStatus field ****/ > + > +/***************************************************************************** > + * SAS IO Unit Page 1 * > + ****************************************************************************/ > +typedef struct _MPI3_SAS_IO_UNIT1_PHY_DATA { > + U8 IOUnitPort; /* 0x00 */ > + U8 PortFlags; /* 0x01 */ > + U8 PhyFlags; /* 0x02 */ > + U8 MaxMinLinkRate; /* 0x03 */ > + U16 ControllerPhyDeviceInfo; /* 0x04 */ > + U16 MaxTargetPortConnectTime; /* 0x06 */ > + U32 Reserved08; /* 0x08 */ > +} MPI3_SAS_IO_UNIT1_PHY_DATA, MPI3_POINTER PTR_MPI3_SAS_IO_UNIT1_PHY_DATA, > + Mpi3SasIOUnit1PhyData_t, MPI3_POINTER pMpi3SasIOUnit1PhyData_t; > + > +#ifndef MPI3_SAS_IO_UNIT1_PHY_MAX > +#define MPI3_SAS_IO_UNIT1_PHY_MAX (1) > +#endif /* MPI3_SAS_IO_UNIT1_PHY_MAX */ > + > +typedef struct _MPI3_SAS_IO_UNIT_PAGE1 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U16 ControlFlags; /* 0x08 */ > + U16 SASNarrowMaxQueueDepth; /* 0x0A */ > + U16 AdditionalControlFlags; /* 0x0C */ > + U16 SASWideMaxQueueDepth; /* 0x0E */ > + U8 NumPhys; /* 0x10 */ > + U8 SATAMaxQDepth; /* 0x11 */ > + U16 Reserved12; /* 0x12 */ > + MPI3_SAS_IO_UNIT1_PHY_DATA PhyData[MPI3_SAS_IO_UNIT1_PHY_MAX]; /* 0x14 */ > +} MPI3_SAS_IO_UNIT_PAGE1, MPI3_POINTER PTR_MPI3_SAS_IO_UNIT_PAGE1, > + Mpi3SasIOUnitPage1_t, MPI3_POINTER pMpi3SasIOUnitPage1_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_SASIOUNIT1_PAGEVERSION (0x00) > + > +/**** Defines for the ControlFlags field ****/ > +#define MPI3_SASIOUNIT1_CONTROL_CONTROLLER_DEVICE_SELF_TEST (0x8000) > +#define MPI3_SASIOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000) > +#define MPI3_SASIOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080) > +#define MPI3_SASIOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040) > +#define MPI3_SASIOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020) > +#define MPI3_SASIOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010) > +#define MPI3_SASIOUNIT1_CONTROL_TABLE_SUBTRACTIVE_ILLEGAL (0x0008) > +#define MPI3_SASIOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004) > +#define MPI3_SASIOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002) > +#define MPI3_SASIOUNIT1_CONTROL_HARD_RESET_MASK (0x0001) > +#define MPI3_SASIOUNIT1_CONTROL_HARD_RESET_DEVICE_NAME (0x0000) > +#define MPI3_SASIOUNIT1_CONTROL_HARD_RESET_SAS_ADDRESS (0x0001) > + > +/**** Defines for the AdditionalControlFlags field ****/ > +#define MPI3_SASIOUNIT1_ACONTROL_DA_PERSIST_CONNECT (0x0100) > +#define MPI3_SASIOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL (0x0080) > +#define MPI3_SASIOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION (0x0040) > +#define MPI3_SASIOUNIT1_ACONTROL_INVALID_TOPOLOGY_CORRECTION (0x0020) > +#define MPI3_SASIOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET (0x0010) > +#define MPI3_SASIOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET (0x0008) > +#define MPI3_SASIOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET (0x0004) > +#define MPI3_SASIOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET (0x0002) > +#define MPI3_SASIOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE (0x0001) > + > +/**** Defines for the PortFlags field ****/ > +#define MPI3_SASIOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01) > + > +/**** Defines for the PhyFlags field ****/ > +#define MPI3_SASIOUNIT1_PHYFLAGS_INIT_PERSIST_CONNECT (0x40) > +#define MPI3_SASIOUNIT1_PHYFLAGS_TARG_PERSIST_CONNECT (0x20) > +#define MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE (0x08) > + > +/**** Defines for the MaxMinLinkRate field ****/ > +#define MPI3_SASIOUNIT1_MMLR_MAX_RATE_MASK (0xF0) > +#define MPI3_SASIOUNIT1_MMLR_MAX_RATE_SHIFT (4) > +#define MPI3_SASIOUNIT1_MMLR_MAX_RATE_6_0 (0xA0) > +#define MPI3_SASIOUNIT1_MMLR_MAX_RATE_12_0 (0xB0) > +#define MPI3_SASIOUNIT1_MMLR_MAX_RATE_22_5 (0xC0) > +#define MPI3_SASIOUNIT1_MMLR_MIN_RATE_MASK (0x0F) > +#define MPI3_SASIOUNIT1_MMLR_MIN_RATE_6_0 (0x0A) > +#define MPI3_SASIOUNIT1_MMLR_MIN_RATE_12_0 (0x0B) > +#define MPI3_SASIOUNIT1_MMLR_MIN_RATE_22_5 (0x0C) > + > +/**** Use MPI3_SAS_DEVICE_INFO_ defines (see mpi30_sas.h) for the ControllerPhyDeviceInfo field ****/ > + > +/***************************************************************************** > + * SAS IO Unit Page 2 * > + ****************************************************************************/ > +typedef struct _MPI3_SAS_IO_UNIT2_PHY_PM_SETTINGS { > + U8 ControlFlags; /* 0x00 */ > + U8 Reserved01; /* 0x01 */ > + U16 InactivityTimerExponent; /* 0x02 */ > + U8 SATAPartialTimeout; /* 0x04 */ > + U8 Reserved05; /* 0x05 */ > + U8 SATASlumberTimeout; /* 0x06 */ > + U8 Reserved07; /* 0x07 */ > + U8 SASPartialTimeout; /* 0x08 */ > + U8 Reserved09; /* 0x09 */ > + U8 SASSlumberTimeout; /* 0x0A */ > + U8 Reserved0B; /* 0x0B */ > +} MPI3_SAS_IO_UNIT2_PHY_PM_SETTINGS, MPI3_POINTER PTR_MPI3_SAS_IO_UNIT2_PHY_PM_SETTINGS, > + Mpi3SasIOUnit2PhyPmSettings_t, MPI3_POINTER pMpi3SasIOUnit2PhyPmSettings_t; > + > +#ifndef MPI3_SAS_IO_UNIT2_PHY_MAX > +#define MPI3_SAS_IO_UNIT2_PHY_MAX (1) > +#endif /* MPI3_SAS_IO_UNIT2_PHY_MAX */ > + > +typedef struct _MPI3_SAS_IO_UNIT_PAGE2 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U8 NumPhys; /* 0x08 */ > + U8 Reserved09[3]; /* 0x09 */ > + U32 Reserved0C; /* 0x0C */ > + MPI3_SAS_IO_UNIT2_PHY_PM_SETTINGS SASPhyPowerManagementSettings[MPI3_SAS_IO_UNIT2_PHY_MAX]; /* 0x10 */ > +} MPI3_SAS_IO_UNIT_PAGE2, MPI3_POINTER PTR_MPI3_SAS_IO_UNIT_PAGE2, > + Mpi3SasIOUnitPage2_t, MPI3_POINTER pMpi3SasIOUnitPage2_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_SASIOUNIT2_PAGEVERSION (0x00) > + > +/**** Defines for the ControlFlags field ****/ > +#define MPI3_SASIOUNIT2_CONTROL_SAS_SLUMBER_ENABLE (0x08) > +#define MPI3_SASIOUNIT2_CONTROL_SAS_PARTIAL_ENABLE (0x04) > +#define MPI3_SASIOUNIT2_CONTROL_SATA_SLUMBER_ENABLE (0x02) > +#define MPI3_SASIOUNIT2_CONTROL_SATA_PARTIAL_ENABLE (0x01) > + > +/**** Defines for the InactivityTimerExponent field ****/ > +#define MPI3_SASIOUNIT2_ITE_SAS_SLUMBER_MASK (0x7000) > +#define MPI3_SASIOUNIT2_ITE_SAS_SLUMBER_SHIFT (12) > +#define MPI3_SASIOUNIT2_ITE_SAS_PARTIAL_MASK (0x0700) > +#define MPI3_SASIOUNIT2_ITE_SAS_PARTIAL_SHIFT (8) > +#define MPI3_SASIOUNIT2_ITE_SATA_SLUMBER_MASK (0x0070) > +#define MPI3_SASIOUNIT2_ITE_SATA_SLUMBER_SHIFT (4) > +#define MPI3_SASIOUNIT2_ITE_SATA_PARTIAL_MASK (0x0007) > +#define MPI3_SASIOUNIT2_ITE_SATA_PARTIAL_SHIFT (0) > + > +#define MPI3_SASIOUNIT2_ITE_EXP_TEN_SECONDS (7) > +#define MPI3_SASIOUNIT2_ITE_EXP_ONE_SECOND (6) > +#define MPI3_SASIOUNIT2_ITE_EXP_HUNDRED_MILLISECONDS (5) > +#define MPI3_SASIOUNIT2_ITE_EXP_TEN_MILLISECONDS (4) > +#define MPI3_SASIOUNIT2_ITE_EXP_ONE_MILLISECOND (3) > +#define MPI3_SASIOUNIT2_ITE_EXP_HUNDRED_MICROSECONDS (2) > +#define MPI3_SASIOUNIT2_ITE_EXP_TEN_MICROSECONDS (1) > +#define MPI3_SASIOUNIT2_ITE_EXP_ONE_MICROSECOND (0) > + > +/***************************************************************************** > + * SAS IO Unit Page 3 * > + ****************************************************************************/ > +typedef struct _MPI3_SAS_IO_UNIT_PAGE3 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08; /* 0x08 */ > + U32 PowerManagementCapabilities; /* 0x0C */ > +} MPI3_SAS_IO_UNIT_PAGE3, MPI3_POINTER PTR_MPI3_SAS_IO_UNIT_PAGE3, > + Mpi3SasIOUnitPage3_t, MPI3_POINTER pMpi3SasIOUnitPage3_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_SASIOUNIT3_PAGEVERSION (0x00) > + > +/**** Defines for the PowerManagementCapabilities field ****/ > +#define MPI3_SASIOUNIT3_PM_HOST_SAS_SLUMBER_MODE (0x00000800) > +#define MPI3_SASIOUNIT3_PM_HOST_SAS_PARTIAL_MODE (0x00000400) > +#define MPI3_SASIOUNIT3_PM_HOST_SATA_SLUMBER_MODE (0x00000200) > +#define MPI3_SASIOUNIT3_PM_HOST_SATA_PARTIAL_MODE (0x00000100) > +#define MPI3_SASIOUNIT3_PM_IOUNIT_SAS_SLUMBER_MODE (0x00000008) > +#define MPI3_SASIOUNIT3_PM_IOUNIT_SAS_PARTIAL_MODE (0x00000004) > +#define MPI3_SASIOUNIT3_PM_IOUNIT_SATA_SLUMBER_MODE (0x00000002) > +#define MPI3_SASIOUNIT3_PM_IOUNIT_SATA_PARTIAL_MODE (0x00000001) > + > + > +/***************************************************************************** > + * SAS Expander Configuration Pages * > + ****************************************************************************/ > + > +/***************************************************************************** > + * SAS Expander Page 0 * > + ****************************************************************************/ > +typedef struct _MPI3_SAS_EXPANDER_PAGE0 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U8 IOUnitPort; /* 0x08 */ > + U8 ReportGenLength; /* 0x09 */ > + U16 EnclosureHandle; /* 0x0A */ > + U32 Reserved0C; /* 0x0C */ > + U64 SASAddress; /* 0x10 */ > + U32 DiscoveryStatus; /* 0x18 */ > + U16 DevHandle; /* 0x1C */ > + U16 ParentDevHandle; /* 0x1E */ > + U16 ExpanderChangeCount; /* 0x20 */ > + U16 ExpanderRouteIndexes; /* 0x22 */ > + U8 NumPhys; /* 0x24 */ > + U8 SASLevel; /* 0x25 */ > + U16 Flags; /* 0x26 */ > + U16 STPBusInactivityTimeLimit; /* 0x28 */ > + U16 STPMaxConnectTimeLimit; /* 0x2A */ > + U16 STP_SMP_NexusLossTime; /* 0x2C */ > + U16 MaxNumRoutedSASAddresses; /* 0x2E */ > + U64 ActiveZoneManagerSASAddress; /* 0x30 */ > + U16 ZoneLockInactivityLimit; /* 0x38 */ > + U16 Reserved3A; /* 0x3A */ > + U8 TimeToReducedFunc; /* 0x3C */ > + U8 InitialTimeToReducedFunc; /* 0x3D */ > + U8 MaxReducedFuncTime; /* 0x3E */ > + U8 ExpStatus; /* 0x3F */ > +} MPI3_SAS_EXPANDER_PAGE0, MPI3_POINTER PTR_MPI3_SAS_EXPANDER_PAGE0, > + Mpi3SasExpanderPage0_t, MPI3_POINTER pMpi3SasExpanderPage0_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_SASEXPANDER0_PAGEVERSION (0x00) > + > +/**** Use MPI3_SAS_DISC_STATUS_ defines (see mpi30_ioc.h) for the DiscoveryStatus field ****/ > + > +/**** Defines for the Flags field ****/ > +#define MPI3_SASEXPANDER0_FLAGS_REDUCED_FUNCTIONALITY (0x2000) > +#define MPI3_SASEXPANDER0_FLAGS_ZONE_LOCKED (0x1000) > +#define MPI3_SASEXPANDER0_FLAGS_SUPPORTED_PHYSICAL_PRES (0x0800) > +#define MPI3_SASEXPANDER0_FLAGS_ASSERTED_PHYSICAL_PRES (0x0400) > +#define MPI3_SASEXPANDER0_FLAGS_ZONING_SUPPORT (0x0200) > +#define MPI3_SASEXPANDER0_FLAGS_ENABLED_ZONING (0x0100) > +#define MPI3_SASEXPANDER0_FLAGS_TABLE_TO_TABLE_SUPPORT (0x0080) > +#define MPI3_SASEXPANDER0_FLAGS_CONNECTOR_END_DEVICE (0x0010) > +#define MPI3_SASEXPANDER0_FLAGS_OTHERS_CONFIG (0x0004) > +#define MPI3_SASEXPANDER0_FLAGS_CONFIG_IN_PROGRESS (0x0002) > +#define MPI3_SASEXPANDER0_FLAGS_ROUTE_TABLE_CONFIG (0x0001) > + > +/**** Defines for the ExpStatus field ****/ > +#define MPI3_SASEXPANDER0_ES_NOT_RESPONDING (0x02) > +#define MPI3_SASEXPANDER0_ES_RESPONDING (0x03) > +#define MPI3_SASEXPANDER0_ES_DELAY_NOT_RESPONDING (0x04) > + > +/***************************************************************************** > + * SAS Expander Page 1 * > + ****************************************************************************/ > +typedef struct _MPI3_SAS_EXPANDER_PAGE1 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U8 IOUnitPort; /* 0x08 */ > + U8 Reserved09[3]; /* 0x09 */ > + U8 NumPhys; /* 0x0C */ > + U8 Phy; /* 0x0D */ > + U16 NumTableEntriesProgrammed; /* 0x0E */ > + U8 ProgrammedLinkRate; /* 0x10 */ > + U8 HwLinkRate; /* 0x11 */ > + U16 AttachedDevHandle; /* 0x12 */ > + U32 PhyInfo; /* 0x14 */ > + U16 AttachedDeviceInfo; /* 0x18 */ > + U16 Reserved1A; /* 0x1A */ > + U16 ExpanderDevHandle; /* 0x1C */ > + U8 ChangeCount; /* 0x1E */ > + U8 NegotiatedLinkRate; /* 0x1F */ > + U8 PhyIdentifier; /* 0x20 */ > + U8 AttachedPhyIdentifier; /* 0x21 */ > + U8 Reserved22; /* 0x22 */ > + U8 DiscoveryInfo; /* 0x23 */ > + U32 AttachedPhyInfo; /* 0x24 */ > + U8 ZoneGroup; /* 0x28 */ > + U8 SelfConfigStatus; /* 0x29 */ > + U16 Reserved2A; /* 0x2A */ > + U16 Slot; /* 0x2C */ > + U16 SlotIndex; /* 0x2E */ > +} MPI3_SAS_EXPANDER_PAGE1, MPI3_POINTER PTR_MPI3_SAS_EXPANDER_PAGE1, > + Mpi3SasExpanderPage1_t, MPI3_POINTER pMpi3SasExpanderPage1_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_SASEXPANDER1_PAGEVERSION (0x00) > + > +/**** Defines for the ProgrammedLinkRate field - use MPI3_SAS_PRATE_ defines ****/ > + > +/**** Defines for the HwLinkRate field - use MPI3_SAS_HWRATE_ defines ****/ > + > +/**** Defines for the PhyInfo field - use MPI3_SAS_PHYINFO_ defines ****/ > + > +/**** Defines for the AttachedDeviceInfo field - use MPI3_SAS_DEVICE_INFO_ defines ****/ > + > +/**** Defines for the NegotiatedLinkRate field - use MPI3_SAS_NEG_LINK_RATE_ defines ****/ > + > +/**** Defines for the DiscoveryInfo field ****/ > +#define MPI3_SASEXPANDER1_DISCINFO_BAD_PHY_DISABLED (0x04) > +#define MPI3_SASEXPANDER1_DISCINFO_LINK_STATUS_CHANGE (0x02) > +#define MPI3_SASEXPANDER1_DISCINFO_NO_ROUTING_ENTRIES (0x01) > + > +/**** Defines for the AttachedPhyInfo field - use MPI3_SAS_APHYINFO_ defines ****/ > + > +/**** Defines for the Slot field - use MPI3_SLOT_ defines ****/ > + > +/**** Defines for the SlotIndex field - use MPI3_SLOT_INDEX_ ****/ > + > + > +/***************************************************************************** > + * SAS Port Configuration Pages * > + ****************************************************************************/ > + > +/***************************************************************************** > + * SAS Port Page 0 * > + ****************************************************************************/ > +typedef struct _MPI3_SAS_PORT_PAGE0 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U8 PortNumber; /* 0x08 */ > + U8 Reserved09; /* 0x09 */ > + U8 PortWidth; /* 0x0A */ > + U8 Reserved0B; /* 0x0B */ > + U8 ZoneGroup; /* 0x0C */ > + U8 Reserved0D[3]; /* 0x0D */ > + U64 SASAddress; /* 0x10 */ > + U16 DeviceInfo; /* 0x18 */ > + U16 Reserved1A; /* 0x1A */ > + U32 Reserved1C; /* 0x1C */ > +} MPI3_SAS_PORT_PAGE0, MPI3_POINTER PTR_MPI3_SAS_PORT_PAGE0, > + Mpi3SasPortPage0, MPI3_POINTER pMpi3SasPortPage0; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_SASPORT0_PAGEVERSION (0x00) > + > +/**** Defines for the DeviceInfo field - use MPI3_SAS_DEVICE_INFO_ defines ****/ > + > +/***************************************************************************** > + * SAS PHY Configuration Pages * > + ****************************************************************************/ > + > +/***************************************************************************** > + * SAS PHY Page 0 * > + ****************************************************************************/ > +typedef struct _MPI3_SAS_PHY_PAGE0 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U16 OwnerDevHandle; /* 0x08 */ > + U16 Reserved0A; /* 0x0A */ > + U16 AttachedDevHandle; /* 0x0C */ > + U8 AttachedPhyIdentifier; /* 0x0E */ > + U8 Reserved0F; /* 0x0F */ > + U32 AttachedPhyInfo; /* 0x10 */ > + U8 ProgrammedLinkRate; /* 0x14 */ > + U8 HwLinkRate; /* 0x15 */ > + U8 ChangeCount; /* 0x16 */ > + U8 Flags; /* 0x17 */ > + U32 PhyInfo; /* 0x18 */ > + U8 NegotiatedLinkRate; /* 0x1C */ > + U8 Reserved1D[3]; /* 0x1D */ > + U16 Slot; /* 0x20 */ > + U16 SlotIndex; /* 0x22 */ > +} MPI3_SAS_PHY_PAGE0, MPI3_POINTER PTR_MPI3_SAS_PHY_PAGE0, > + Mpi3SasPhyPage0_t, MPI3_POINTER pMpi3SasPhyPage0_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_SASPHY0_PAGEVERSION (0x00) > + > +/**** Defines for the AttachedPhyInfo field - use MPI3_SAS_APHYINFO_ defines ****/ > + > +/**** Defines for the ProgrammedLinkRate field - use MPI3_SAS_PRATE_ defines ****/ > + > +/**** Defines for the HwLinkRate field - use MPI3_SAS_HWRATE_ defines ****/ > + > +/**** Defines for the Flags field ****/ > +#define MPI3_SASPHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC (0x01) > + > +/**** Defines for the PhyInfo field - use MPI3_SAS_PHYINFO_ defines ****/ > + > +/**** Defines for the NegotiatedLinkRate field - use MPI3_SAS_NEG_LINK_RATE_ defines ****/ > + > +/**** Defines for the Slot field - use MPI3_SLOT_ defines ****/ > + > +/**** Defines for the SlotIndex field - use MPI3_SLOT_INDEX_ ****/ > + > +/***************************************************************************** > + * SAS PHY Page 1 * > + ****************************************************************************/ > +typedef struct _MPI3_SAS_PHY_PAGE1 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08; /* 0x08 */ > + U32 InvalidDwordCount; /* 0x0C */ > + U32 RunningDisparityErrorCount; /* 0x10 */ > + U32 LossDwordSynchCount; /* 0x14 */ > + U32 PhyResetProblemCount; /* 0x18 */ > +} MPI3_SAS_PHY_PAGE1, MPI3_POINTER PTR_MPI3_SAS_PHY_PAGE1, > + Mpi3SasPhyPage1_t, MPI3_POINTER pMpi3SasPhyPage1_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_SASPHY1_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * SAS PHY Page 2 * > + ****************************************************************************/ > +typedef struct _MPI3_SAS_PHY2_PHY_EVENT { > + U8 PhyEventCode; /* 0x00 */ > + U8 Reserved01[3]; /* 0x01 */ > + U32 PhyEventInfo; /* 0x04 */ > +} MPI3_SAS_PHY2_PHY_EVENT, MPI3_POINTER PTR_MPI3_SAS_PHY2_PHY_EVENT, > + Mpi3SasPhy2PhyEvent_t, MPI3_POINTER pMpi3SasPhy2PhyEvent_t; > + > +/**** Defines for the PhyEventCode field - use MPI3_SASPHY3_EVENT_CODE_ defines */ > + > +#ifndef MPI3_SAS_PHY2_PHY_EVENT_MAX > +#define MPI3_SAS_PHY2_PHY_EVENT_MAX (1) > +#endif /* MPI3_SAS_PHY2_PHY_EVENT_MAX */ > + > +typedef struct _MPI3_SAS_PHY_PAGE2 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08; /* 0x08 */ > + U8 NumPhyEvents; /* 0x0C */ > + U8 Reserved0D[3]; /* 0x0D */ > + MPI3_SAS_PHY2_PHY_EVENT PhyEvent[MPI3_SAS_PHY2_PHY_EVENT_MAX]; /* 0x10 */ > +} MPI3_SAS_PHY_PAGE2, MPI3_POINTER PTR_MPI3_SAS_PHY_PAGE2, > + Mpi3SasPhyPage2_t, MPI3_POINTER pMpi3SasPhyPage2_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_SASPHY2_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * SAS PHY Page 3 * > + ****************************************************************************/ > +typedef struct _MPI3_SAS_PHY3_PHY_EVENT_CONFIG { > + U8 PhyEventCode; /* 0x00 */ > + U8 Reserved01[3]; /* 0x01 */ > + U8 CounterType; /* 0x04 */ > + U8 ThresholdWindow; /* 0x05 */ > + U8 TimeUnits; /* 0x06 */ > + U8 Reserved07; /* 0x07 */ > + U32 EventThreshold; /* 0x08 */ > + U16 ThresholdFlags; /* 0x0C */ > + U16 Reserved0E; /* 0x0E */ > +} MPI3_SAS_PHY3_PHY_EVENT_CONFIG, MPI3_POINTER PTR_MPI3_SAS_PHY3_PHY_EVENT_CONFIG, > + Mpi3SasPhy3PhyEventConfig_t, MPI3_POINTER pMpi3SasPhy3PhyEventConfig_t; > + > +/**** Defines for the PhyEventCode field ****/ > +#define MPI3_SASPHY3_EVENT_CODE_NO_EVENT (0x00) > +#define MPI3_SASPHY3_EVENT_CODE_INVALID_DWORD (0x01) > +#define MPI3_SASPHY3_EVENT_CODE_RUNNING_DISPARITY_ERROR (0x02) > +#define MPI3_SASPHY3_EVENT_CODE_LOSS_DWORD_SYNC (0x03) > +#define MPI3_SASPHY3_EVENT_CODE_PHY_RESET_PROBLEM (0x04) > +#define MPI3_SASPHY3_EVENT_CODE_ELASTICITY_BUF_OVERFLOW (0x05) > +#define MPI3_SASPHY3_EVENT_CODE_RX_ERROR (0x06) > +#define MPI3_SASPHY3_EVENT_CODE_INV_SPL_PACKETS (0x07) > +#define MPI3_SASPHY3_EVENT_CODE_LOSS_SPL_PACKET_SYNC (0x08) > +#define MPI3_SASPHY3_EVENT_CODE_RX_ADDR_FRAME_ERROR (0x20) > +#define MPI3_SASPHY3_EVENT_CODE_TX_AC_OPEN_REJECT (0x21) > +#define MPI3_SASPHY3_EVENT_CODE_RX_AC_OPEN_REJECT (0x22) > +#define MPI3_SASPHY3_EVENT_CODE_TX_RC_OPEN_REJECT (0x23) > +#define MPI3_SASPHY3_EVENT_CODE_RX_RC_OPEN_REJECT (0x24) > +#define MPI3_SASPHY3_EVENT_CODE_RX_AIP_PARTIAL_WAITING_ON (0x25) > +#define MPI3_SASPHY3_EVENT_CODE_RX_AIP_CONNECT_WAITING_ON (0x26) > +#define MPI3_SASPHY3_EVENT_CODE_TX_BREAK (0x27) > +#define MPI3_SASPHY3_EVENT_CODE_RX_BREAK (0x28) > +#define MPI3_SASPHY3_EVENT_CODE_BREAK_TIMEOUT (0x29) > +#define MPI3_SASPHY3_EVENT_CODE_CONNECTION (0x2A) > +#define MPI3_SASPHY3_EVENT_CODE_PEAKTX_PATHWAY_BLOCKED (0x2B) > +#define MPI3_SASPHY3_EVENT_CODE_PEAKTX_ARB_WAIT_TIME (0x2C) > +#define MPI3_SASPHY3_EVENT_CODE_PEAK_ARB_WAIT_TIME (0x2D) > +#define MPI3_SASPHY3_EVENT_CODE_PEAK_CONNECT_TIME (0x2E) > +#define MPI3_SASPHY3_EVENT_CODE_PERSIST_CONN (0x2F) > +#define MPI3_SASPHY3_EVENT_CODE_TX_SSP_FRAMES (0x40) > +#define MPI3_SASPHY3_EVENT_CODE_RX_SSP_FRAMES (0x41) > +#define MPI3_SASPHY3_EVENT_CODE_TX_SSP_ERROR_FRAMES (0x42) > +#define MPI3_SASPHY3_EVENT_CODE_RX_SSP_ERROR_FRAMES (0x43) > +#define MPI3_SASPHY3_EVENT_CODE_TX_CREDIT_BLOCKED (0x44) > +#define MPI3_SASPHY3_EVENT_CODE_RX_CREDIT_BLOCKED (0x45) > +#define MPI3_SASPHY3_EVENT_CODE_TX_SATA_FRAMES (0x50) > +#define MPI3_SASPHY3_EVENT_CODE_RX_SATA_FRAMES (0x51) > +#define MPI3_SASPHY3_EVENT_CODE_SATA_OVERFLOW (0x52) > +#define MPI3_SASPHY3_EVENT_CODE_TX_SMP_FRAMES (0x60) > +#define MPI3_SASPHY3_EVENT_CODE_RX_SMP_FRAMES (0x61) > +#define MPI3_SASPHY3_EVENT_CODE_RX_SMP_ERROR_FRAMES (0x63) > +#define MPI3_SASPHY3_EVENT_CODE_HOTPLUG_TIMEOUT (0xD0) > +#define MPI3_SASPHY3_EVENT_CODE_MISALIGNED_MUX_PRIMITIVE (0xD1) > +#define MPI3_SASPHY3_EVENT_CODE_RX_AIP (0xD2) > +#define MPI3_SASPHY3_EVENT_CODE_LCARB_WAIT_TIME (0xD3) > +#define MPI3_SASPHY3_EVENT_CODE_RCVD_CONN_RESP_WAIT_TIME (0xD4) > +#define MPI3_SASPHY3_EVENT_CODE_LCCONN_TIME (0xD5) > +#define MPI3_SASPHY3_EVENT_CODE_SSP_TX_START_TRANSMIT (0xD6) > +#define MPI3_SASPHY3_EVENT_CODE_SATA_TX_START (0xD7) > +#define MPI3_SASPHY3_EVENT_CODE_SMP_TX_START_TRANSMT (0xD8) > +#define MPI3_SASPHY3_EVENT_CODE_TX_SMP_BREAK_CONN (0xD9) > +#define MPI3_SASPHY3_EVENT_CODE_SSP_RX_START_RECEIVE (0xDA) > +#define MPI3_SASPHY3_EVENT_CODE_SATA_RX_START_RECEIVE (0xDB) > +#define MPI3_SASPHY3_EVENT_CODE_SMP_RX_START_RECEIVE (0xDC) > + > +/**** Defines for the CounterType field ****/ > +#define MPI3_SASPHY3_COUNTER_TYPE_WRAPPING (0x00) > +#define MPI3_SASPHY3_COUNTER_TYPE_SATURATING (0x01) > +#define MPI3_SASPHY3_COUNTER_TYPE_PEAK_VALUE (0x02) > + > +/**** Defines for the TimeUnits field ****/ > +#define MPI3_SASPHY3_TIME_UNITS_10_MICROSECONDS (0x00) > +#define MPI3_SASPHY3_TIME_UNITS_100_MICROSECONDS (0x01) > +#define MPI3_SASPHY3_TIME_UNITS_1_MILLISECOND (0x02) > +#define MPI3_SASPHY3_TIME_UNITS_10_MILLISECONDS (0x03) > + > +/**** Defines for the ThresholdFlags field ****/ > +#define MPI3_SASPHY3_TFLAGS_PHY_RESET (0x0002) > +#define MPI3_SASPHY3_TFLAGS_EVENT_NOTIFY (0x0001) > + > +#ifndef MPI3_SAS_PHY3_PHY_EVENT_MAX > +#define MPI3_SAS_PHY3_PHY_EVENT_MAX (1) > +#endif /* MPI3_SAS_PHY3_PHY_EVENT_MAX */ > + > +typedef struct _MPI3_SAS_PHY_PAGE3 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08; /* 0x08 */ > + U8 NumPhyEvents; /* 0x0C */ > + U8 Reserved0D[3]; /* 0x0D */ > + MPI3_SAS_PHY3_PHY_EVENT_CONFIG PhyEventConfig[MPI3_SAS_PHY3_PHY_EVENT_MAX]; /* 0x10 */ > +} MPI3_SAS_PHY_PAGE3, MPI3_POINTER PTR_MPI3_SAS_PHY_PAGE3, > + Mpi3SasPhyPage3_t, MPI3_POINTER pMpi3SasPhyPage3_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_SASPHY3_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * SAS PHY Page 4 * > + ****************************************************************************/ > +typedef struct _MPI3_SAS_PHY_PAGE4 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U8 Reserved08[3]; /* 0x08 */ > + U8 Flags; /* 0x0B */ > + U8 InitialFrame[28]; /* 0x0C */ > +} MPI3_SAS_PHY_PAGE4, MPI3_POINTER PTR_MPI3_SAS_PHY_PAGE4, > + Mpi3SasPhyPage4_t, MPI3_POINTER pMpi3SasPhyPage4_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_SASPHY4_PAGEVERSION (0x00) > + > +/**** Defines for the Flags field ****/ > +#define MPI3_SASPHY4_FLAGS_FRAME_VALID (0x02) > +#define MPI3_SASPHY4_FLAGS_SATA_FRAME (0x01) > + > + > +/***************************************************************************** > + * Common definitions used by PCIe Configuration Pages * > + ****************************************************************************/ > + > +/**** Defines for Negotiated Link Rates ****/ > +#define MPI3_PCIE_LINK_RETIMERS_MASK (0x30) > +#define MPI3_PCIE_LINK_RETIMERS_SHIFT (4) > +#define MPI3_PCIE_NEG_LINK_RATE_MASK (0x0F) > +#define MPI3_PCIE_NEG_LINK_RATE_UNKNOWN (0x00) > +#define MPI3_PCIE_NEG_LINK_RATE_PHY_DISABLED (0x01) > +#define MPI3_PCIE_NEG_LINK_RATE_2_5 (0x02) > +#define MPI3_PCIE_NEG_LINK_RATE_5_0 (0x03) > +#define MPI3_PCIE_NEG_LINK_RATE_8_0 (0x04) > +#define MPI3_PCIE_NEG_LINK_RATE_16_0 (0x05) > +#define MPI3_PCIE_NEG_LINK_RATE_32_0 (0x06) > + > +/***************************************************************************** > + * PCIe IO Unit Configuration Pages * > + ****************************************************************************/ > + > +/***************************************************************************** > + * PCIe IO Unit Page 0 * > + ****************************************************************************/ > +typedef struct _MPI3_PCIE_IO_UNIT0_PHY_DATA { > + U8 Link; /* 0x00 */ > + U8 LinkFlags; /* 0x01 */ > + U8 PhyFlags; /* 0x02 */ > + U8 NegotiatedLinkRate; /* 0x03 */ > + U16 AttachedDevHandle; /* 0x04 */ > + U16 ControllerDevHandle; /* 0x06 */ > + U32 EnumerationStatus; /* 0x08 */ > + U8 IOUnitPort; /* 0x0C */ > + U8 Reserved0D[3]; /* 0x0D */ > +} MPI3_PCIE_IO_UNIT0_PHY_DATA, MPI3_POINTER PTR_MPI3_PCIE_IO_UNIT0_PHY_DATA, > + Mpi3PcieIOUnit0PhyData_t, MPI3_POINTER pMpi3PcieIOUnit0PhyData_t; > + > +/**** Defines for the LinkFlags field ****/ > +#define MPI3_PCIEIOUNIT0_LINKFLAGS_CONFIG_SOURCE_MASK (0x10) > +#define MPI3_PCIEIOUNIT0_LINKFLAGS_CONFIG_SOURCE_IOUNIT1 (0x00) > +#define MPI3_PCIEIOUNIT0_LINKFLAGS_CONFIG_SOURCE_BKPLANE (0x10) > +#define MPI3_PCIEIOUNIT0_LINKFLAGS_ENUM_IN_PROGRESS (0x08) > + > +/**** Defines for the PhyFlags field ****/ > +#define MPI3_PCIEIOUNIT0_PHYFLAGS_PHY_DISABLED (0x08) > +#define MPI3_PCIEIOUNIT0_PHYFLAGS_HOST_PHY (0x01) > + > +/**** Defines for the NegotiatedLinkRate field - use MPI3_PCIE_NEG_LINK_RATE_ defines ****/ > + > +/**** Defines for the EnumerationStatus field ****/ > +#define MPI3_PCIEIOUNIT0_ES_MAX_SWITCH_DEPTH_EXCEEDED (0x80000000) > +#define MPI3_PCIEIOUNIT0_ES_MAX_SWITCHES_EXCEEDED (0x40000000) > +#define MPI3_PCIEIOUNIT0_ES_MAX_ENDPOINTS_EXCEEDED (0x20000000) > +#define MPI3_PCIEIOUNIT0_ES_INSUFFICIENT_RESOURCES (0x10000000) > + > +#ifndef MPI3_PCIE_IO_UNIT0_PHY_MAX > +#define MPI3_PCIE_IO_UNIT0_PHY_MAX (1) > +#endif /* MPI3_PCIE_IO_UNIT0_PHY_MAX */ > + > +typedef struct _MPI3_PCIE_IO_UNIT_PAGE0 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 Reserved08; /* 0x08 */ > + U8 NumPhys; /* 0x0C */ > + U8 InitStatus; /* 0x0D */ > + U16 Reserved0E; /* 0x0E */ > + MPI3_PCIE_IO_UNIT0_PHY_DATA PhyData[MPI3_PCIE_IO_UNIT0_PHY_MAX]; /* 0x10 */ > +} MPI3_PCIE_IO_UNIT_PAGE0, MPI3_POINTER PTR_MPI3_PCIE_IO_UNIT_PAGE0, > + Mpi3PcieIOUnitPage0_t, MPI3_POINTER pMpi3PcieIOUnitPage0_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_PCIEIOUNIT0_PAGEVERSION (0x00) > + > +/**** Defines for the InitStatus field ****/ > +#define MPI3_PCIEIOUNIT0_INITSTATUS_NO_ERRORS (0x00) > +#define MPI3_PCIEIOUNIT0_INITSTATUS_NEEDS_INITIALIZATION (0x01) > +#define MPI3_PCIEIOUNIT0_INITSTATUS_NO_TARGETS_ALLOCATED (0x02) > +#define MPI3_PCIEIOUNIT0_INITSTATUS_RESOURCE_ALLOC_FAILED (0x03) > +#define MPI3_PCIEIOUNIT0_INITSTATUS_BAD_NUM_PHYS (0x04) > +#define MPI3_PCIEIOUNIT0_INITSTATUS_UNSUPPORTED_CONFIG (0x05) > +#define MPI3_PCIEIOUNIT0_INITSTATUS_HOST_PORT_MISMATCH (0x06) > +#define MPI3_PCIEIOUNIT0_INITSTATUS_PHYS_NOT_CONSECUTIVE (0x07) > +#define MPI3_PCIEIOUNIT0_INITSTATUS_BAD_CLOCKING_MODE (0x08) > +#define MPI3_PCIEIOUNIT0_INITSTATUS_PROD_SPEC_START (0xF0) > +#define MPI3_PCIEIOUNIT0_INITSTATUS_PROD_SPEC_END (0xFF) > + > +/***************************************************************************** > + * PCIe IO Unit Page 1 * > + ****************************************************************************/ > +typedef struct _MPI3_PCIE_IO_UNIT1_PHY_DATA { > + U8 Link; /* 0x00 */ > + U8 LinkFlags; /* 0x01 */ > + U8 PhyFlags; /* 0x02 */ > + U8 MaxMinLinkRate; /* 0x03 */ > + U32 Reserved04; /* 0x04 */ > + U32 Reserved08; /* 0x08 */ > +} MPI3_PCIE_IO_UNIT1_PHY_DATA, MPI3_POINTER PTR_MPI3_PCIE_IO_UNIT1_PHY_DATA, > + Mpi3PcieIOUnit1PhyData_t, MPI3_POINTER pMpi3PcieIOUnit1PhyData_t; > + > +/**** Defines for the LinkFlags field ****/ > +#define MPI3_PCIEIOUNIT1_LINKFLAGS_PCIE_CLK_MODE_MASK (0x03) > +#define MPI3_PCIEIOUNIT1_LINKFLAGS_PCIE_CLK_MODE_DIS_SEPARATE_REFCLK (0x00) > +#define MPI3_PCIEIOUNIT1_LINKFLAGS_PCIE_CLK_MODE_EN_SRIS (0x01) > +#define MPI3_PCIEIOUNIT1_LINKFLAGS_PCIE_CLK_MODE_EN_SRNS (0x02) > + > +/**** Defines for the PhyFlags field ****/ > +#define MPI3_PCIEIOUNIT1_PHYFLAGS_PHY_DISABLE (0x08) > + > +/**** Defines for the MaxMinLinkRate ****/ > +#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_MASK (0xF0) > +#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_SHIFT (4) > +#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_2_5 (0x20) > +#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_5_0 (0x30) > +#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_8_0 (0x40) > +#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_16_0 (0x50) > +#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_32_0 (0x60) > + > +#ifndef MPI3_PCIE_IO_UNIT1_PHY_MAX > +#define MPI3_PCIE_IO_UNIT1_PHY_MAX (1) > +#endif /* MPI3_PCIE_IO_UNIT1_PHY_MAX */ > + > +typedef struct _MPI3_PCIE_IO_UNIT_PAGE1 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U32 ControlFlags; /* 0x08 */ > + U32 Reserved0C; /* 0x0C */ > + U8 NumPhys; /* 0x10 */ > + U8 Reserved11; /* 0x11 */ > + U16 Reserved12; /* 0x12 */ > + MPI3_PCIE_IO_UNIT1_PHY_DATA PhyData[MPI3_PCIE_IO_UNIT1_PHY_MAX]; /* 0x14 */ > +} MPI3_PCIE_IO_UNIT_PAGE1, MPI3_POINTER PTR_MPI3_PCIE_IO_UNIT_PAGE1, > + Mpi3PcieIOUnitPage1_t, MPI3_POINTER pMpi3PcieIOUnitPage1_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_PCIEIOUNIT1_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * PCIe IO Unit Page 2 * > + ****************************************************************************/ > +typedef struct _MPI3_PCIE_IO_UNIT_PAGE2 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U16 NVMeMaxQueueDepth; /* 0x08 */ > + U16 Reserved0A; /* 0x0A */ > + U8 NVMeAbortTO; /* 0x0C */ > + U8 Reserved0D; /* 0x0D */ > + U16 Reserved0E; /* 0x0E */ > +} MPI3_PCIE_IO_UNIT_PAGE2, MPI3_POINTER PTR_MPI3_PCIE_IO_UNIT_PAGE2, > + Mpi3PcieIOUnitPage2_t, MPI3_POINTER pMpi3PcieIOUnitPage2_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_PCIEIOUNIT2_PAGEVERSION (0x00) > + > +/***************************************************************************** > + * PCIe Switch Configuration Pages * > + ****************************************************************************/ > + > +/***************************************************************************** > + * PCIe Switch Page 0 * > + ****************************************************************************/ > +typedef struct _MPI3_PCIE_SWITCH_PAGE0 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U8 IOUnitPort; /* 0x08 */ > + U8 SwitchStatus; /* 0x09 */ > + U8 Reserved0A[2]; /* 0x0A */ > + U16 DevHandle; /* 0x0C */ > + U16 ParentDevHandle; /* 0x0E */ > + U8 NumPorts; /* 0x10 */ > + U8 PCIeLevel; /* 0x11 */ > + U16 Reserved12; /* 0x12 */ > + U32 Reserved14; /* 0x14 */ > + U32 Reserved18; /* 0x18 */ > + U32 Reserved1C; /* 0x1C */ > +} MPI3_PCIE_SWITCH_PAGE0, MPI3_POINTER PTR_MPI3_PCIE_SWITCH_PAGE0, > + Mpi3PcieSwitchPage0_t, MPI3_POINTER pMpi3PcieSwitchPage0_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_PCIESWITCH0_PAGEVERSION (0x00) > + > +/**** Defines for the SwitchStatus field ****/ > +#define MPI3_PCIESWITCH0_SS_NOT_RESPONDING (0x02) > +#define MPI3_PCIESWITCH0_SS_RESPONDING (0x03) > +#define MPI3_PCIESWITCH0_SS_DELAY_NOT_RESPONDING (0x04) > + > +/***************************************************************************** > + * PCIe Switch Page 1 * > + ****************************************************************************/ > +typedef struct _MPI3_PCIE_SWITCH_PAGE1 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U8 IOUnitPort; /* 0x08 */ > + U8 Reserved09[3]; /* 0x09 */ > + U8 NumPorts; /* 0x0C */ > + U8 PortNum; /* 0x0D */ > + U16 AttachedDevHandle; /* 0x0E */ > + U16 SwitchDevHandle; /* 0x10 */ > + U8 NegotiatedPortWidth; /* 0x12 */ > + U8 NegotiatedLinkRate; /* 0x13 */ > + U16 Slot; /* 0x14 */ > + U16 SlotIndex; /* 0x16 */ > + U32 Reserved18; /* 0x18 */ > +} MPI3_PCIE_SWITCH_PAGE1, MPI3_POINTER PTR_MPI3_PCIE_SWITCH_PAGE1, > + Mpi3PcieSwitchPage1_t, MPI3_POINTER pMpi3PcieSwitchPage1_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_PCIESWITCH1_PAGEVERSION (0x00) > + > +/**** Defines for the NegotiatedLinkRate field - use MPI3_PCIE_NEG_LINK_RATE_ defines ****/ > + > +/**** Defines for the Slot field - use MPI3_SLOT_ defines ****/ > + > +/**** Defines for the SlotIndex field - use MPI3_SLOT_INDEX_ ****/ > + > +/***************************************************************************** > + * PCIe Link Configuration Pages * > + ****************************************************************************/ > +typedef struct _MPI3_PCIE_LINK_PAGE0 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U8 Link; /* 0x08 */ > + U8 Reserved09[3]; /* 0x09 */ > + U32 CorrectableErrorCount; /* 0x0C */ > + U16 NFatalErrorCount; /* 0x10 */ > + U16 Reserved12; /* 0x12 */ > + U16 FatalErrorCount; /* 0x14 */ > + U16 Reserved16; /* 0x16 */ > +} MPI3_PCIE_LINK_PAGE0, MPI3_POINTER PTR_MPI3_PCIE_LINK_PAGE0, > + Mpi3PcieLinkPage0_t, MPI3_POINTER pMpi3PcieLinkPage0_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_PCIELINK0_PAGEVERSION (0x00) > + > + > +/***************************************************************************** > + * Enclosure Configuration Pages * > + ****************************************************************************/ > + > +/***************************************************************************** > + * Enclosure Page 0 * > + ****************************************************************************/ > +typedef struct _MPI3_ENCLOSURE_PAGE0 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U64 EnclosureLogicalID; /* 0x08 */ > + U16 Flags; /* 0x10 */ > + U16 EnclosureHandle; /* 0x12 */ > + U16 NumSlots; /* 0x14 */ > + U16 StartSlot; /* 0x16 */ > + U8 IOUnitPort; /* 0x18 */ > + U8 EnclosureLevel; /* 0x19 */ > + U16 SEPDevHandle; /* 0x1A */ > + U32 Reserved1C; /* 0x1C */ > +} MPI3_ENCLOSURE_PAGE0, MPI3_POINTER PTR_MPI3_ENCLOSURE_PAGE0, > + Mpi3EnclosurePage0_t, MPI3_POINTER pMpi3EnclosurePage0_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_ENCLOSURE0_PAGEVERSION (0x00) > + > +/**** Defines for the Flags field ****/ > +#define MPI3_ENCLS0_FLAGS_ENCL_TYPE_MASK (0xC000) > +#define MPI3_ENCLS0_FLAGS_ENCL_TYPE_VIRTUAL (0x0000) > +#define MPI3_ENCLS0_FLAGS_ENCL_TYPE_SAS (0x4000) > +#define MPI3_ENCLS0_FLAGS_ENCL_TYPE_PCIE (0x8000) > +#define MPI3_ENCLS0_FLAGS_ENCL_DEV_PRESENT_MASK (0x0010) > +#define MPI3_ENCLS0_FLAGS_ENCL_DEV_NOT_FOUND (0x0000) > +#define MPI3_ENCLS0_FLAGS_ENCL_DEV_PRESENT (0x0010) > +#define MPI3_ENCLS0_FLAGS_MNG_MASK (0x000F) > +#define MPI3_ENCLS0_FLAGS_MNG_UNKNOWN (0x0000) > +#define MPI3_ENCLS0_FLAGS_MNG_IOC_SES (0x0001) > +#define MPI3_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0002) > + > +/**** Defines for the PhysicalPort field - use MPI3_DEVICE0_PHYPORT_ defines ****/ > + > +/***************************************************************************** > + * Device Configuration Pages * > + ****************************************************************************/ > + > +/***************************************************************************** > + * Common definitions used by Device Configuration Pages * > + ****************************************************************************/ > + > +/**** Defines for the DeviceForm field ****/ > +#define MPI3_DEVICE_DEVFORM_SAS_SATA (0x00) > +#define MPI3_DEVICE_DEVFORM_PCIE (0x01) > +#define MPI3_DEVICE_DEVFORM_VD (0x02) > + > +/***************************************************************************** > + * Device Page 0 * > + ****************************************************************************/ > +typedef struct _MPI3_DEVICE0_SAS_SATA_FORMAT { > + U64 SASAddress; /* 0x00 */ > + U16 Flags; /* 0x08 */ > + U16 DeviceInfo; /* 0x0A */ > + U8 PhyNum; /* 0x0C */ > + U8 AttachedPhyIdentifier; /* 0x0D */ > + U8 MaxPortConnections; /* 0x0E */ > + U8 ZoneGroup; /* 0x0F */ > +} MPI3_DEVICE0_SAS_SATA_FORMAT, MPI3_POINTER PTR_MPI3_DEVICE0_SAS_SATA_FORMAT, > + Mpi3Device0SasSataFormat_t, MPI3_POINTER pMpi3Device0SasSataFormat_t; > + > +/**** Defines for the Flags field ****/ > +#define MPI3_DEVICE0_SASSATA_FLAGS_SLUMBER_CAP (0x0200) > +#define MPI3_DEVICE0_SASSATA_FLAGS_PARTIAL_CAP (0x0100) > +#define MPI3_DEVICE0_SASSATA_FLAGS_ASYNC_NOTIFY (0x0080) > +#define MPI3_DEVICE0_SASSATA_FLAGS_SW_PRESERVE (0x0040) > +#define MPI3_DEVICE0_SASSATA_FLAGS_UNSUPP_DEV (0x0020) > +#define MPI3_DEVICE0_SASSATA_FLAGS_48BIT_LBA (0x0010) > +#define MPI3_DEVICE0_SASSATA_FLAGS_SMART_SUPP (0x0008) > +#define MPI3_DEVICE0_SASSATA_FLAGS_NCQ_SUPP (0x0004) > +#define MPI3_DEVICE0_SASSATA_FLAGS_FUA_SUPP (0x0002) > +#define MPI3_DEVICE0_SASSATA_FLAGS_PERSIST_CAP (0x0001) > + > +/**** Defines for the DeviceInfo field - use MPI3_SAS_DEVICE_INFO_ defines (see mpi30_sas.h) ****/ > + > +typedef struct _MPI3_DEVICE0_PCIE_FORMAT { > + U8 SupportedLinkRates; /* 0x00 */ > + U8 MaxPortWidth; /* 0x01 */ > + U8 NegotiatedPortWidth; /* 0x02 */ > + U8 NegotiatedLinkRate; /* 0x03 */ > + U8 PortNum; /* 0x04 */ > + U8 ControllerResetTO; /* 0x05 */ > + U16 DeviceInfo; /* 0x06 */ > + U32 MaximumDataTransferSize; /* 0x08 */ > + U32 Capabilities; /* 0x0C */ > + U16 NOIOB; /* 0x10 */ > + U8 NVMeAbortTO; /* 0x12 */ > + U8 PageSize; /* 0x13 */ > + U16 ShutdownLatency; /* 0x14 */ > + U16 Reserved16; /* 0x16 */ > +} MPI3_DEVICE0_PCIE_FORMAT, MPI3_POINTER PTR_MPI3_DEVICE0_PCIE_FORMAT, > + Mpi3Device0PcieFormat_t, MPI3_POINTER pMpi3Device0PcieFormat_t; > + > +/**** Defines for the SupportedLinkRates field ****/ > +#define MPI3_DEVICE0_PCIE_LINK_RATE_32_0_SUPP (0x10) > +#define MPI3_DEVICE0_PCIE_LINK_RATE_16_0_SUPP (0x08) > +#define MPI3_DEVICE0_PCIE_LINK_RATE_8_0_SUPP (0x04) > +#define MPI3_DEVICE0_PCIE_LINK_RATE_5_0_SUPP (0x02) > +#define MPI3_DEVICE0_PCIE_LINK_RATE_2_5_SUPP (0x01) > + > +/**** Defines for the NegotiatedLinkRate field - use MPI3_PCIE_NEG_LINK_RATE_ defines ****/ > + > +/**** Defines for DeviceInfo bitfield ****/ > +#define MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK (0x0003) > +#define MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_NO_DEVICE (0x0000) > +#define MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_NVME_DEVICE (0x0001) > +#define MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_SWITCH_DEVICE (0x0002) > +#define MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_SCSI_DEVICE (0x0003) > + > +/**** Defines for the Capabilities field ****/ > +#define MPI3_DEVICE0_PCIE_CAP_METADATA_SEPARATED (0x00000010) > +#define MPI3_DEVICE0_PCIE_CAP_SGL_DWORD_ALIGN_REQUIRED (0x00000008) > +#define MPI3_DEVICE0_PCIE_CAP_NVME_SGL_ENABLED (0x00000004) > +#define MPI3_DEVICE0_PCIE_CAP_BIT_BUCKET_SGL_SUPP (0x00000002) > +#define MPI3_DEVICE0_PCIE_CAP_SGL_SUPP (0x00000001) > + > +typedef struct _MPI3_DEVICE0_VD_FORMAT { > + U8 VdState; /* 0x00 */ > + U8 RAIDLevel; /* 0x01 */ > + U16 DeviceInfo; /* 0x02 */ > + U16 Flags; /* 0x04 */ > + U16 Reserved06; /* 0x06 */ > + U32 Reserved08[2]; /* 0x08 */ > +} MPI3_DEVICE0_VD_FORMAT, MPI3_POINTER PTR_MPI3_DEVICE0_VD_FORMAT, > + Mpi3Device0VdFormat_t, MPI3_POINTER pMpi3Device0VdFormat_t; > + > +/**** Defines for the VdState field ****/ > +#define MPI3_DEVICE0_VD_STATE_OFFLINE (0x00) > +#define MPI3_DEVICE0_VD_STATE_PARTIALLY_DEGRADED (0x01) > +#define MPI3_DEVICE0_VD_STATE_DEGRADED (0x02) > +#define MPI3_DEVICE0_VD_STATE_OPTIMAL (0x03) > + > +/**** Defines for RAIDLevel field ****/ > +#define MPI3_DEVICE0_VD_RAIDLEVEL_RAID_0 (0) > +#define MPI3_DEVICE0_VD_RAIDLEVEL_RAID_1 (1) > +#define MPI3_DEVICE0_VD_RAIDLEVEL_RAID_5 (5) > +#define MPI3_DEVICE0_VD_RAIDLEVEL_RAID_6 (6) > +#define MPI3_DEVICE0_VD_RAIDLEVEL_RAID_10 (10) > +#define MPI3_DEVICE0_VD_RAIDLEVEL_RAID_50 (50) > +#define MPI3_DEVICE0_VD_RAIDLEVEL_RAID_60 (60) > + > +/**** Defines for DeviceInfo field ****/ > +#define MPI3_DEVICE0_VD_DEVICE_INFO_HDD (0x0010) > +#define MPI3_DEVICE0_VD_DEVICE_INFO_SSD (0x0008) > +#define MPI3_DEVICE0_VD_DEVICE_INFO_NVME (0x0004) > +#define MPI3_DEVICE0_VD_DEVICE_INFO_SATA (0x0002) > +#define MPI3_DEVICE0_VD_DEVICE_INFO_SAS (0x0001) > + > +/**** Defines for the Flags field ****/ > +#define MPI3_DEVICE0_VD_FLAGS_METADATA_MODE_MASK (0x0003) > +#define MPI3_DEVICE0_VD_FLAGS_METADATA_MODE_NONE (0x0000) > +#define MPI3_DEVICE0_VD_FLAGS_METADATA_MODE_HOST (0x0001) > +#define MPI3_DEVICE0_VD_FLAGS_METADATA_MODE_IOC (0x0002) > + > +typedef union _MPI3_DEVICE0_DEV_SPEC_FORMAT { > + MPI3_DEVICE0_SAS_SATA_FORMAT SasSataFormat; > + MPI3_DEVICE0_PCIE_FORMAT PcieFormat; > + MPI3_DEVICE0_VD_FORMAT VdFormat; > +} MPI3_DEVICE0_DEV_SPEC_FORMAT, MPI3_POINTER PTR_MPI3_DEVICE0_DEV_SPEC_FORMAT, > + Mpi3Device0DevSpecFormat_t, MPI3_POINTER pMpi3Device0DevSpecFormat_t; > + > +typedef struct _MPI3_DEVICE_PAGE0 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U16 DevHandle; /* 0x08 */ > + U16 ParentDevHandle; /* 0x0A */ > + U16 Slot; /* 0x0C */ > + U16 EnclosureHandle; /* 0x0E */ > + U64 WWID; /* 0x10 */ > + U16 PersistentID; /* 0x18 */ > + U8 IOUnitPort; /* 0x1A */ > + U8 AccessStatus; /* 0x1B */ > + U16 Flags; /* 0x1C */ > + U16 Reserved1E; /* 0x1E */ > + U16 SlotIndex; /* 0x20 */ > + U16 QueueDepth; /* 0x22 */ > + U8 Reserved24[3]; /* 0x24 */ > + U8 DeviceForm; /* 0x27 */ > + MPI3_DEVICE0_DEV_SPEC_FORMAT DeviceSpecific; /* 0x28 */ > +} MPI3_DEVICE_PAGE0, MPI3_POINTER PTR_MPI3_DEVICE_PAGE0, > + Mpi3DevicePage0_t, MPI3_POINTER pMpi3DevicePage0_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_DEVICE0_PAGEVERSION (0x00) > + > +/**** Defines for the Slot field - use MPI3_SLOT_ defines ****/ > + > +/**** Defines for the WWID field ****/ > +#define MPI3_DEVICE0_WWID_INVALID (0xFFFFFFFFFFFFFFFF) > + > +/**** Defines for the PersistentID field ****/ > +#define MPI3_DEVICE0_PERSISTENTID_INVALID (0xFFFF) > + > +/**** Defines for the IOUnitPort field ****/ > +#define MPI3_DEVICE0_IOUNITPORT_INVALID (0xFF) > + > +/**** Defines for the AccessStatus field ****/ > +/* Generic Access Status Codes */ > +#define MPI3_DEVICE0_ASTATUS_NO_ERRORS (0x00) > +#define MPI3_DEVICE0_ASTATUS_NEEDS_INITIALIZATION (0x01) > +#define MPI3_DEVICE0_ASTATUS_CAP_UNSUPPORTED (0x02) > +#define MPI3_DEVICE0_ASTATUS_DEVICE_BLOCKED (0x03) > +#define MPI3_DEVICE0_ASTATUS_UNAUTHORIZED (0x04) > +#define MPI3_DEVICE0_ASTATUS_DEVICE_MISSING_DELAY (0x05) > +/* SAS Access Status Codes */ > +#define MPI3_DEVICE0_ASTATUS_SAS_UNKNOWN (0x10) > +#define MPI3_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE (0x11) > +#define MPI3_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE (0x12) > +/* SATA Access Status Codes */ > +#define MPI3_DEVICE0_ASTATUS_SIF_UNKNOWN (0x20) > +#define MPI3_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT (0x21) > +#define MPI3_DEVICE0_ASTATUS_SIF_DIAG (0x22) > +#define MPI3_DEVICE0_ASTATUS_SIF_IDENTIFICATION (0x23) > +#define MPI3_DEVICE0_ASTATUS_SIF_CHECK_POWER (0x24) > +#define MPI3_DEVICE0_ASTATUS_SIF_PIO_SN (0x25) > +#define MPI3_DEVICE0_ASTATUS_SIF_MDMA_SN (0x26) > +#define MPI3_DEVICE0_ASTATUS_SIF_UDMA_SN (0x27) > +#define MPI3_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION (0x28) > +#define MPI3_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE (0x29) > +#define MPI3_DEVICE0_ASTATUS_SIF_MAX (0x2F) > +/* PCIe Access Status Codes */ > +#define MPI3_DEVICE0_ASTATUS_PCIE_UNKNOWN (0x30) > +#define MPI3_DEVICE0_ASTATUS_PCIE_MEM_SPACE_ACCESS (0x31) > +#define MPI3_DEVICE0_ASTATUS_PCIE_UNSUPPORTED (0x32) > +#define MPI3_DEVICE0_ASTATUS_PCIE_MSIX_REQUIRED (0x33) > +/* NVMe Access Status Codes */ > +#define MPI3_DEVICE0_ASTATUS_NVME_UNKNOWN (0x40) > +#define MPI3_DEVICE0_ASTATUS_NVME_READY_TIMEOUT (0x41) > +#define MPI3_DEVICE0_ASTATUS_NVME_DEVCFG_UNSUPPORTED (0x42) > +#define MPI3_DEVICE0_ASTATUS_NVME_IDENTIFY_FAILED (0x43) > +#define MPI3_DEVICE0_ASTATUS_NVME_QCONFIG_FAILED (0x44) > +#define MPI3_DEVICE0_ASTATUS_NVME_QCREATION_FAILED (0x45) > +#define MPI3_DEVICE0_ASTATUS_NVME_EVENTCFG_FAILED (0x46) > +#define MPI3_DEVICE0_ASTATUS_NVME_GET_FEATURE_STAT_FAILED (0x47) > +#define MPI3_DEVICE0_ASTATUS_NVME_IDLE_TIMEOUT (0x48) > +#define MPI3_DEVICE0_ASTATUS_NVME_CTRL_FAILURE_STATUS (0x49) > +/* Virtual Device Access Status Codes */ > +#define MPI3_DEVICE0_ASTATUS_VD_UNKNOWN (0x50) > + > +/**** Defines for the Flags field ****/ > +#define MPI3_DEVICE0_FLAGS_CONTROLLER_DEV_HANDLE (0x0080) > +#define MPI3_DEVICE0_FLAGS_HIDDEN (0x0008) > +#define MPI3_DEVICE0_FLAGS_ATT_METHOD_MASK (0x0006) > +#define MPI3_DEVICE0_FLAGS_ATT_METHOD_NOT_DIR_ATTACHED (0x0000) > +#define MPI3_DEVICE0_FLAGS_ATT_METHOD_DIR_ATTACHED (0x0002) > +#define MPI3_DEVICE0_FLAGS_ATT_METHOD_VIRTUAL (0x0004) > +#define MPI3_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001) > + > +/**** Defines for the SlotIndex field - use MPI3_SLOT_INDEX_ defines ****/ > + > +/**** Defines for the DeviceForm field - use MPI3_DEVICE_DEVFORM_ defines ****/ > + > +/**** Defines for the QueueDepth field ****/ > +#define MPI3_DEVICE0_QUEUE_DEPTH_NOT_APPLICABLE (0x0000) > + > + > +/***************************************************************************** > + * Device Page 1 * > + ****************************************************************************/ > +typedef struct _MPI3_DEVICE1_SAS_SATA_FORMAT { > + U32 Reserved00; /* 0x00 */ > +} MPI3_DEVICE1_SAS_SATA_FORMAT, MPI3_POINTER PTR_MPI3_DEVICE1_SAS_SATA_FORMAT, > + Mpi3Device1SasSataFormat_t, MPI3_POINTER pMpi3Device1SasSataFormat_t; > + > +typedef struct _MPI3_DEVICE1_PCIE_FORMAT { > + U16 VendorID; /* 0x00 */ > + U16 DeviceID; /* 0x02 */ > + U16 SubsystemVendorID; /* 0x04 */ > + U16 SubsystemID; /* 0x06 */ > + U32 Reserved08; /* 0x08 */ > + U8 RevisionID; /* 0x0C */ > + U8 Reserved0D; /* 0x0D */ > + U16 PCIParameters; /* 0x0E */ > +} MPI3_DEVICE1_PCIE_FORMAT, MPI3_POINTER PTR_MPI3_DEVICE1_PCIE_FORMAT, > + Mpi3Device1PcieFormat_t, MPI3_POINTER pMpi3Device1PcieFormat_t; > + > +/**** Defines for the PCIParameters field ****/ > +#define MPI3_DEVICE1_PCIE_PARAMS_DATA_SIZE_128B (0x0) > +#define MPI3_DEVICE1_PCIE_PARAMS_DATA_SIZE_256B (0x1) > +#define MPI3_DEVICE1_PCIE_PARAMS_DATA_SIZE_512B (0x2) > +#define MPI3_DEVICE1_PCIE_PARAMS_DATA_SIZE_1024B (0x3) > +#define MPI3_DEVICE1_PCIE_PARAMS_DATA_SIZE_2048B (0x4) > +#define MPI3_DEVICE1_PCIE_PARAMS_DATA_SIZE_4096B (0x5) > + > +/*** MaxReadRequestSize, CurrentMaxPayloadSize, and MaxPayloadSizeSupported ***/ > +/*** all use the size definitions above - shifted to the proper position ***/ > +#define MPI3_DEVICE1_PCIE_PARAMS_MAX_READ_REQ_MASK (0x01C0) > +#define MPI3_DEVICE1_PCIE_PARAMS_MAX_READ_REQ_SHIFT (6) > +#define MPI3_DEVICE1_PCIE_PARAMS_CURR_MAX_PAYLOAD_MASK (0x0038) > +#define MPI3_DEVICE1_PCIE_PARAMS_CURR_MAX_PAYLOAD_SHIFT (3) > +#define MPI3_DEVICE1_PCIE_PARAMS_SUPP_MAX_PAYLOAD_MASK (0x0007) > +#define MPI3_DEVICE1_PCIE_PARAMS_SUPP_MAX_PAYLOAD_SHIFT (0) > + > +typedef struct _MPI3_DEVICE1_VD_FORMAT { > + U32 Reserved00; /* 0x00 */ > +} MPI3_DEVICE1_VD_FORMAT, MPI3_POINTER PTR_MPI3_DEVICE1_VD_FORMAT, > + Mpi3Device1VdFormat_t, MPI3_POINTER pMpi3Device1VdFormat_t; > + > +typedef union _MPI3_DEVICE1_DEV_SPEC_FORMAT { > + MPI3_DEVICE1_SAS_SATA_FORMAT SasSataFormat; > + MPI3_DEVICE1_PCIE_FORMAT PcieFormat; > + MPI3_DEVICE1_VD_FORMAT VdFormat; > +} MPI3_DEVICE1_DEV_SPEC_FORMAT, MPI3_POINTER PTR_MPI3_DEVICE1_DEV_SPEC_FORMAT, > + Mpi3Device1DevSpecFormat_t, MPI3_POINTER pMpi3Device1DevSpecFormat_t; > + > +typedef struct _MPI3_DEVICE_PAGE1 { > + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ > + U16 DevHandle; /* 0x08 */ > + U16 Reserved0A; /* 0x0A */ > + U32 Reserved0C[12]; /* 0x0C */ > + U8 Reserved3C[3]; /* 0x3C */ > + U8 DeviceForm; /* 0x3F */ > + MPI3_DEVICE1_DEV_SPEC_FORMAT DeviceSpecific; /* 0x40 */ > +} MPI3_DEVICE_PAGE1, MPI3_POINTER PTR_MPI3_DEVICE_PAGE1, > + Mpi3DevicePage1_t, MPI3_POINTER pMpi3DevicePage1_t; > + > +/**** Defines for the PageVersion field ****/ > +#define MPI3_DEVICE1_PAGEVERSION (0x00) > + > +/**** Defines for the DeviceForm field - use MPI3_DEVICE_DEVFORM_ defines ****/ > + > +#endif /* MPI30_CNFG_H */ > diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_sas.h b/drivers/scsi/mpi3mr/mpi/mpi30_sas.h > new file mode 100644 > index 000000000000..b60a5899437e > --- /dev/null > +++ b/drivers/scsi/mpi3mr/mpi/mpi30_sas.h > @@ -0,0 +1,46 @@ > +/* > + * Copyright 2016-2020 Broadcom Inc. All rights reserved. > + * > + * Name: mpi30_sas.h > + * Description: Contains MPI Serial Attached SCSI structures and definitions > + * Creation Date: 12/08/2016 > + * Version: 03.00.00 > + */ > +#ifndef MPI30_SAS_H > +#define MPI30_SAS_H 1 > + > +/***************************************************************************** > + * SAS Device Info Definitions * > + ****************************************************************************/ > +#define MPI3_SAS_DEVICE_INFO_SSP_TARGET (0x00000100) > +#define MPI3_SAS_DEVICE_INFO_STP_SATA_TARGET (0x00000080) > +#define MPI3_SAS_DEVICE_INFO_SMP_TARGET (0x00000040) > +#define MPI3_SAS_DEVICE_INFO_SSP_INITIATOR (0x00000020) > +#define MPI3_SAS_DEVICE_INFO_STP_INITIATOR (0x00000010) > +#define MPI3_SAS_DEVICE_INFO_SMP_INITIATOR (0x00000008) > +#define MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK (0x00000007) > +#define MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_NO_DEVICE (0x00000000) > +#define MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE (0x00000001) > +#define MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER (0x00000002) > + > +/***************************************************************************** > + * SMP Passthrough Request Message * > + ****************************************************************************/ > +typedef struct _MPI3_SMP_PASSTHROUGH_REQUEST { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U8 Reserved0A; /* 0x0A */ > + U8 IOUnitPort; /* 0x0B */ > + U32 Reserved0C[3]; /* 0x0C */ > + U64 SASAddress; /* 0x18 */ > + MPI3_SGE_SIMPLE RequestSGE; /* 0x20 */ > + MPI3_SGE_SIMPLE ResponseSGE; /* 0x30 */ > +} MPI3_SMP_PASSTHROUGH_REQUEST, MPI3_POINTER PTR_MPI3_SMP_PASSTHROUGH_REQUEST, > + Mpi3SmpPassthroughRequest_t, MPI3_POINTER pMpi3SmpPassthroughRequest_t; > + > +#endif /* MPI30_SAS_H */ > diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h > index 7769ba16c9bc..063877f1bc37 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr.h > +++ b/drivers/scsi/mpi3mr/mpi3mr.h > @@ -134,6 +134,10 @@ extern struct list_head mrioc_list; > #define MPI3MR_RSP_IO_QUEUED_ON_IOC \ > MPI3_SCSITASKMGMT_RSPCODE_IO_QUEUED_ON_IOC > > +#define MPI3MR_DEFAULT_MDTS (128 * 1024) > +/* Command retry count definitions */ > +#define MPI3MR_DEV_RMHS_RETRY_COUNT 3 > + > /* SGE Flag definition */ > #define MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST \ > (MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM | \ > @@ -313,6 +317,126 @@ struct mpi3mr_intr_info { > char name[MPI3MR_NAME_LENGTH]; > }; > > +/** > + * struct tgt_dev_sas_sata - SAS/SATA device specific > + * information cached from firmware given data > + * > + * @sas_address: World wide unique SAS address > + * @dev_info: Device information bits > + */ > +struct tgt_dev_sas_sata { > + u64 sas_address; > + u16 dev_info; > +}; > + > +/** > + * struct tgt_dev_pcie - PCIe device specific information cached > + * from firmware given data > + * > + * @mdts: Maximum data transfer size > + * @capb: Device capabilities > + * @pgsz: Device page size > + * @abort_to: Timeout for abort TM > + * @reset_to: Timeout for Target/LUN reset TM > + */ > +struct tgt_dev_pcie { > + u32 mdts; > + u16 capb; > + u8 pgsz; > + u8 abort_to; > + u8 reset_to; > +}; > + > +/** > + * struct tgt_dev_volume - virtual device specific information > + * cached from firmware given data > + * > + * @state: State of the VD > + */ > +struct tgt_dev_volume { > + u8 state; > +}; > + > +/** > + * union _form_spec_inf - union of device specific information > + */ > +union _form_spec_inf { > + struct tgt_dev_sas_sata sas_sata_inf; > + struct tgt_dev_pcie pcie_inf; > + struct tgt_dev_volume vol_inf; > +}; > + > + > + > +/** > + * struct mpi3mr_tgt_dev - target device data structure > + * > + * @list: List pointer > + * @starget: Scsi_target pointer > + * @dev_handle: FW device handle > + * @parent_handle: FW parent device handle > + * @slot: Slot number > + * @encl_handle: FW enclosure handle > + * @perst_id: FW assigned Persistent ID > + * @dev_type: SAS/SATA/PCIE device type > + * @is_hidden: Should be exposed to upper layers or not > + * @host_exposed: Already exposed to host or not > + * @q_depth: Device specific Queue Depth > + * @wwid: World wide ID > + * @dev_spec: Device type specific information > + * @ref_count: Reference count > + */ > +struct mpi3mr_tgt_dev { > + struct list_head list; > + struct scsi_target *starget; > + u16 dev_handle; > + u16 parent_handle; > + u16 slot; > + u16 encl_handle; > + u16 perst_id; > + u8 dev_type; > + u8 is_hidden; > + u8 host_exposed; > + u16 q_depth; > + u64 wwid; > + union _form_spec_inf dev_spec; > + struct kref ref_count; > +}; > + > +/** > + * mpi3mr_tgtdev_get - k reference incrementor > + * @s: Target device reference > + * > + * Increment target device reference count. > + */ > +static inline void mpi3mr_tgtdev_get(struct mpi3mr_tgt_dev *s) > +{ > + kref_get(&s->ref_count); > +} > + > +/** > + * mpi3mr_free_tgtdev - target device memory dealloctor > + * @r: k reference pointer of the target device > + * > + * Free target device memory when no reference. > + */ > +static inline void mpi3mr_free_tgtdev(struct kref *r) > +{ > + kfree(container_of(r, struct mpi3mr_tgt_dev, ref_count)); > +} > + > +/** > + * mpi3mr_tgtdev_put - k reference decrementor > + * @s: Target device reference > + * > + * Decrement target device reference count. > + */ > +static inline void mpi3mr_tgtdev_put(struct mpi3mr_tgt_dev *s) > +{ > + kref_put(&s->ref_count, mpi3mr_free_tgtdev); > +} > + > + > /** > * struct mpi3mr_stgt_priv_data - SCSI target private structure > * > @@ -358,6 +482,7 @@ struct mpi3mr_sdev_priv_data { > * @done: Completeor for wakeup > * @reply: Firmware reply for internal commands > * @sensebuf: Sensebuf for SCSI IO commands > + * @iou_rc: IO Unit control reason code > * @state: Command State > * @dev_handle: Firmware handle for device specific commands > * @ioc_status: IOC status from the firmware > @@ -372,6 +497,7 @@ struct mpi3mr_drv_cmd { > struct completion done; > void *reply; > u8 *sensebuf; > + u8 iou_rc; > u16 state; > u16 dev_handle; > u16 ioc_status; > @@ -478,6 +604,11 @@ struct scmd_priv { > * @sense_buf_q_dma: Sense buffer queue DMA address > * @sbq_lock: Sense buffer queue lock > * @sbq_host_index: Sense buffer queuehost index > + * @event_masks: Event mask bitmap > + * @fwevt_worker_name: Firmware event worker thread name > + * @fwevt_worker_thread: Firmware event worker thread > + * @fwevt_lock: Firmware event lock > + * @fwevt_list: Firmware event list > * @watchdog_work_q_name: Fault watchdog worker thread name > * @watchdog_work_q: Fault watchdog worker thread > * @watchdog_work: Fault watchdog work > @@ -493,6 +624,12 @@ struct scmd_priv { > * @chain_bitmap_sz: Chain buffer allocator bitmap size > * @chain_bitmap: Chain buffer allocator bitmap > * @chain_buf_lock: Chain buffer list lock > + * @dev_rmhs_cmds: Command tracker for device removal commands > + * @devrem_bitmap_sz: Device removal bitmap size > + * @devrem_bitmap: Device removal bitmap > + * @dev_handle_bitmap_sz: Device handle bitmap size > + * @removepend_bitmap: Remove pending bitmap > + * @delayed_rmhs_list: Delayed device removal list > * @reset_in_progress: Reset in progress flag > * @unrecoverable: Controller unrecoverable flag > * @diagsave_timeout: Diagnostic information save timeout > @@ -576,6 +713,12 @@ struct mpi3mr_ioc { > dma_addr_t sense_buf_q_dma; > spinlock_t sbq_lock; > u32 sbq_host_index; > + u32 event_masks[MPI3_EVENT_NOTIFY_EVENTMASK_WORDS]; > + > + char fwevt_worker_name[MPI3MR_NAME_LENGTH]; > + struct workqueue_struct *fwevt_worker_thread; > + spinlock_t fwevt_lock; > + struct list_head fwevt_list; > > char watchdog_work_q_name[20]; > struct workqueue_struct *watchdog_work_q; > @@ -588,6 +731,8 @@ struct mpi3mr_ioc { > u8 stop_drv_processing; > > u16 max_host_ios; > + spinlock_t tgtdev_lock; > + struct list_head tgtdev_list; > > u32 chain_buf_count; > struct dma_pool *chain_buf_pool; > @@ -596,6 +741,13 @@ struct mpi3mr_ioc { > void *chain_bitmap; > spinlock_t chain_buf_lock; > > + struct mpi3mr_drv_cmd dev_rmhs_cmds[MPI3MR_NUM_DEVRMCMD]; > + u16 devrem_bitmap_sz; > + void *devrem_bitmap; > + u16 dev_handle_bitmap_sz; > + void *removepend_bitmap; > + struct list_head delayed_rmhs_list; > + > u8 reset_in_progress; > u8 unrecoverable; > > @@ -608,6 +760,45 @@ struct mpi3mr_ioc { > u16 op_reply_q_offset; > }; > > +/** > + * struct mpi3mr_fwevt - Firmware event structure. > + * > + * @list: list head > + * @work: Work structure > + * @mrioc: Adapter instance reference > + * @event_id: MPI3 firmware event ID > + * @send_ack: Event acknowledgment required or not > + * @process_evt: Bottomhalf processing required or not > + * @evt_ctx: Event context to send in Ack > + * @ref_count: kref count > + * @event_data: Actual MPI3 event data > + */ > +struct mpi3mr_fwevt { > + struct list_head list; > + struct work_struct work; > + struct mpi3mr_ioc *mrioc; > + u16 event_id; > + bool send_ack; > + bool process_evt; > + u32 evt_ctx; > + struct kref ref_count; > + char event_data[0] __aligned(4); > +}; > + > + > +/** > + * struct delayed_dev_rmhs_node - Delayed device removal node > + * > + * @list: list head > + * @handle: Device handle > + * @iou_rc: IO Unit Control Reason Code > + */ > +struct delayed_dev_rmhs_node { > + struct list_head list; > + u16 handle; > + u8 iou_rc; > +}; > + > int mpi3mr_setup_resources(struct mpi3mr_ioc *mrioc); > void mpi3mr_cleanup_resources(struct mpi3mr_ioc *mrioc); > int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc); > @@ -627,6 +818,8 @@ void *mpi3mr_get_reply_virt_addr(struct mpi3mr_ioc *mrioc, > void mpi3mr_repost_sense_buf(struct mpi3mr_ioc *mrioc, > u64 sense_buf_dma); > > +void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc, > + Mpi3EventNotificationReply_t *event_reply); > void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc, > Mpi3DefaultReplyDescriptor_t *reply_desc, > u64 *reply_dma, u16 qidx); > @@ -639,5 +832,14 @@ void mpi3mr_ioc_disable_intr(struct mpi3mr_ioc *mrioc); > void mpi3mr_ioc_enable_intr(struct mpi3mr_ioc *mrioc); > > enum mpi3mr_iocstate mpi3mr_get_iocstate(struct mpi3mr_ioc *mrioc); > +int mpi3mr_send_event_ack(struct mpi3mr_ioc *mrioc, u8 event, > + u32 event_ctx); > + > +void mpi3mr_wait_for_host_io(struct mpi3mr_ioc *mrioc, u32 timeout); > +void mpi3mr_cleanup_fwevt_list(struct mpi3mr_ioc *mrioc); > +void mpi3mr_flush_host_io(struct mpi3mr_ioc *mrioc); > +void mpi3mr_invalidate_devhandles(struct mpi3mr_ioc *mrioc); > +void mpi3mr_rfresh_tgtdevs(struct mpi3mr_ioc *mrioc); > +void mpi3mr_flush_delayed_rmhs_list(struct mpi3mr_ioc *mrioc); > > #endif /*MPI3MR_H_INCLUDED*/ > diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c > index 4c45e12154d6..f275fbd287f2 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c > @@ -161,12 +161,14 @@ static void mpi3mr_handle_events(struct mpi3mr_ioc *mrioc, > (Mpi3EventNotificationReply_t *)def_reply; > > mrioc->change_count = le16_to_cpu(event_reply->IOCChangeCount); > + mpi3mr_os_handle_events(mrioc, event_reply); > } > > static struct mpi3mr_drv_cmd * > mpi3mr_get_drv_cmd(struct mpi3mr_ioc *mrioc, u16 host_tag, > Mpi3DefaultReply_t *def_reply) > { > + u16 idx; > switch (host_tag) { > case MPI3MR_HOSTTAG_INITCMDS: > return &mrioc->init_cmds; > @@ -178,6 +180,11 @@ mpi3mr_get_drv_cmd(struct mpi3mr_ioc *mrioc, u16 host_tag, > default: > break; > } > + if (host_tag >= MPI3MR_HOSTTAG_DEVRMCMD_MIN && > + host_tag <= MPI3MR_HOSTTAG_DEVRMCMD_MAX) { > + idx = host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN; > + return &mrioc->dev_rmhs_cmds[idx]; > + } > > return NULL; > } > @@ -1924,6 +1931,12 @@ static int mpi3mr_alloc_reply_sense_bufs(struct mpi3mr_ioc *mrioc) > if (!mrioc->init_cmds.reply) > goto out_failed; > > + for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { > + mrioc->dev_rmhs_cmds[i].reply = kzalloc(mrioc->facts.reply_sz, > + GFP_KERNEL); > + if (!mrioc->dev_rmhs_cmds[i].reply) > + goto out_failed; > + } > > mrioc->num_reply_bufs = mrioc->facts.max_reqs + MPI3MR_NUM_EVT_REPLIES; > mrioc->reply_free_qsz = mrioc->num_reply_bufs + 1; > @@ -2134,6 +2147,163 @@ static int mpi3mr_issue_iocinit(struct mpi3mr_ioc *mrioc) > return retval; > } > > +/** > + * mpi3mr_unmask_events - Unmask events in event mask bitmap > + * @mrioc: Adapter instance reference > + * @event: MPI event ID > + * > + * Un mask the specific event by resetting the event_mask > + * bitmap. > + * > + * Return: 0 on success, non-zero on failures. > + */ > +static void mpi3mr_unmask_events(struct mpi3mr_ioc *mrioc, u16 event) > +{ > + u32 desired_event; > + u8 word; > + > + if (event >= 128) > + return; > + > + desired_event = (1 << (event % 32)); > + word = event / 32; > + > + mrioc->event_masks[word] &= ~desired_event; > +} > + > +/** > + * mpi3mr_issue_event_notification - Send event notification > + * @mrioc: Adapter instance reference > + * > + * Issue event notification MPI request through admin queue and > + * wait for the completion of it or time out. > + * > + * Return: 0 on success, non-zero on failures. > + */ > +static int mpi3mr_issue_event_notification(struct mpi3mr_ioc *mrioc) > +{ > + Mpi3EventNotificationRequest_t evtnotify_req; > + int retval = 0; > + u8 i; > + > + memset(&evtnotify_req, 0, sizeof(evtnotify_req)); > + mutex_lock(&mrioc->init_cmds.mutex); > + if (mrioc->init_cmds.state & MPI3MR_CMD_PENDING) { > + retval = -1; > + ioc_err(mrioc, "Issue EvtNotify: Init command is in use\n"); > + mutex_unlock(&mrioc->init_cmds.mutex); > + goto out; > + } > + mrioc->init_cmds.state = MPI3MR_CMD_PENDING; > + mrioc->init_cmds.is_waiting = 1; > + mrioc->init_cmds.callback = NULL; > + evtnotify_req.HostTag = cpu_to_le16(MPI3MR_HOSTTAG_INITCMDS); > + evtnotify_req.Function = MPI3_FUNCTION_EVENT_NOTIFICATION; > + for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++) > + evtnotify_req.EventMasks[i] = > + cpu_to_le32(mrioc->event_masks[i]); > + init_completion(&mrioc->init_cmds.done); > + retval = mpi3mr_admin_request_post(mrioc, &evtnotify_req, > + sizeof(evtnotify_req), 1); > + if (retval) { > + ioc_err(mrioc, "Issue EvtNotify: Admin Post failed\n"); > + goto out_unlock; > + } > + wait_for_completion_timeout(&mrioc->init_cmds.done, > + (MPI3MR_INTADMCMD_TIMEOUT * HZ)); > + if (!(mrioc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { > + ioc_err(mrioc, "Issue EvtNotify: command timed out\n"); > + mpi3mr_set_diagsave(mrioc); > + mpi3mr_issue_reset(mrioc, > + MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, > + MPI3MR_RESET_FROM_EVTNOTIFY_TIMEOUT); > + mrioc->unrecoverable = 1; > + retval = -1; > + goto out_unlock; > + } > + if ((mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) > + != MPI3_IOCSTATUS_SUCCESS) { > + ioc_err(mrioc, > + "Issue EvtNotify: Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n", > + (mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), > + mrioc->init_cmds.ioc_loginfo); > + retval = -1; > + goto out_unlock; > + } > + > +out_unlock: > + mrioc->init_cmds.state = MPI3MR_CMD_NOTUSED; > + mutex_unlock(&mrioc->init_cmds.mutex); > +out: > + return retval; > +} > + > +/** > + * mpi3mr_send_event_ack - Send event acknowledgment > + * @mrioc: Adapter instance reference > + * @event: MPI3 event ID > + * @event_ctx: Event context > + * > + * Send event acknowledgment through admin queue and wait for > + * it to complete. > + * > + * Return: 0 on success, non-zero on failures. > + */ > +int mpi3mr_send_event_ack(struct mpi3mr_ioc *mrioc, u8 event, > + u32 event_ctx) > +{ > + Mpi3EventAckRequest_t evtack_req; > + int retval = 0; > + > + memset(&evtack_req, 0, sizeof(evtack_req)); > + mutex_lock(&mrioc->init_cmds.mutex); > + if (mrioc->init_cmds.state & MPI3MR_CMD_PENDING) { > + retval = -1; > + ioc_err(mrioc, "Send EvtAck: Init command is in use\n"); > + mutex_unlock(&mrioc->init_cmds.mutex); > + goto out; > + } > + mrioc->init_cmds.state = MPI3MR_CMD_PENDING; > + mrioc->init_cmds.is_waiting = 1; > + mrioc->init_cmds.callback = NULL; > + evtack_req.HostTag = cpu_to_le16(MPI3MR_HOSTTAG_INITCMDS); > + evtack_req.Function = MPI3_FUNCTION_EVENT_ACK; > + evtack_req.Event = event; > + evtack_req.EventContext = cpu_to_le32(event_ctx); > + > + init_completion(&mrioc->init_cmds.done); > + retval = mpi3mr_admin_request_post(mrioc, &evtack_req, > + sizeof(evtack_req), 1); > + if (retval) { > + ioc_err(mrioc, "Send EvtAck: Admin Post failed\n"); > + goto out_unlock; > + } > + wait_for_completion_timeout(&mrioc->init_cmds.done, > + (MPI3MR_INTADMCMD_TIMEOUT * HZ)); > + if (!(mrioc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { > + ioc_err(mrioc, "Issue EvtNotify: command timed out\n"); > + mpi3mr_soft_reset_handler(mrioc, > + MPI3MR_RESET_FROM_EVTACK_TIMEOUT, 1); > + retval = -1; > + goto out_unlock; > + } > + if ((mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) > + != MPI3_IOCSTATUS_SUCCESS) { > + ioc_err(mrioc, > + "Send EvtAck: Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n", > + (mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), > + mrioc->init_cmds.ioc_loginfo); > + retval = -1; > + goto out_unlock; > + } > + > +out_unlock: > + mrioc->init_cmds.state = MPI3MR_CMD_NOTUSED; > + mutex_unlock(&mrioc->init_cmds.mutex); > +out: > + return retval; > +} > + > > /** > * mpi3mr_alloc_chain_bufs - Allocate chain buffers > @@ -2415,7 +2585,7 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc) > enum mpi3mr_iocstate ioc_state; > u64 base_info; > u32 timeout; > - u32 ioc_status, ioc_config; > + u32 ioc_status, ioc_config, i; > Mpi3IOCFactsData_t facts_data; > > mrioc->change_count = 0; > @@ -2565,6 +2735,24 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc) > goto out_failed; > } > > + for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++) > + mrioc->event_masks[i] = -1; > + > + mpi3mr_unmask_events(mrioc, MPI3_EVENT_DEVICE_ADDED); > + mpi3mr_unmask_events(mrioc, MPI3_EVENT_DEVICE_INFO_CHANGED); > + mpi3mr_unmask_events(mrioc, MPI3_EVENT_DEVICE_STATUS_CHANGE); > + mpi3mr_unmask_events(mrioc, MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE); > + mpi3mr_unmask_events(mrioc, MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST); > + mpi3mr_unmask_events(mrioc, MPI3_EVENT_SAS_DISCOVERY); > + mpi3mr_unmask_events(mrioc, MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR); > + > + retval = mpi3mr_issue_event_notification(mrioc); > + if (retval) { > + ioc_err(mrioc, "Failed to issue event notification %d\n", > + retval); > + goto out_failed; > + } > + > return retval; > > out_failed: > @@ -2647,6 +2835,11 @@ static void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc) > kfree(mrioc->chain_bitmap); > mrioc->chain_bitmap = NULL; > > + for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { > + kfree(mrioc->dev_rmhs_cmds[i].reply); > + mrioc->dev_rmhs_cmds[i].reply = NULL; > + } > + > if (mrioc->chain_buf_pool) { > for (i = 0; i < mrioc->chain_buf_count; i++) { > if (mrioc->chain_sgl_list[i].addr) { > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c > index 7b0d52481929..d13e8c89892b 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > @@ -125,6 +125,1280 @@ static void mpi3mr_clear_scmd_priv(struct mpi3mr_ioc *mrioc, > } > } > > +static void mpi3mr_dev_rmhs_send_tm(struct mpi3mr_ioc *mrioc, u16 handle, > + struct mpi3mr_drv_cmd *cmdparam, u8 iou_rc); > +static void mpi3mr_fwevt_worker(struct work_struct *work); > + > + > +/** > + * mpi3mr_fwevt_free - firmware event memory dealloctor > + * @r: k reference pointer of the firmware event > + * > + * Free firmware event memory when no reference. > + */ > +static void mpi3mr_fwevt_free(struct kref *r) > +{ > + kfree(container_of(r, struct mpi3mr_fwevt, ref_count)); > +} > + > +/** > + * mpi3mr_fwevt_get - k reference incrementor > + * @fwevt: Firmware event reference > + * > + * Increment firmware event reference count. > + */ > +static void mpi3mr_fwevt_get(struct mpi3mr_fwevt *fwevt) > +{ > + kref_get(&fwevt->ref_count); > +} > + > +/** > + * mpi3mr_fwevt_put - k reference decrementor > + * @fwevt: Firmware event reference > + * > + * Decrement firmware event reference count. > + */ > +static void mpi3mr_fwevt_put(struct mpi3mr_fwevt *fwevt) > +{ > + kref_put(&fwevt->ref_count, mpi3mr_fwevt_free); > +} > + > +/** > + * mpi3mr_alloc_fwevt - Allocate firmware event > + * @len: Length of firmware event data to allocate > + * > + * Allocate firmware event with required length and initialize > + * the reference counter. > + * > + * Return: firmware event reference. > + */ > +static struct mpi3mr_fwevt *mpi3mr_alloc_fwevt(int len) > +{ > + struct mpi3mr_fwevt *fwevt; > + > + fwevt = kzalloc(sizeof(*fwevt) + len, GFP_ATOMIC); > + if (!fwevt) > + return NULL; > + > + kref_init(&fwevt->ref_count); > + return fwevt; > +} > + > +/** > + * mpi3mr_fwevt_add_to_list - Add firmware event to the list > + * @mrioc: Adapter instance reference > + * @fwevt: Firmware event reference > + * > + * Add the given firmware event to the firmware event list. > + * > + * Return: Nothing. > + */ > +static void mpi3mr_fwevt_add_to_list(struct mpi3mr_ioc *mrioc, > + struct mpi3mr_fwevt *fwevt) > +{ > + unsigned long flags; > + > + if (mrioc->fwevt_worker_thread == NULL) > + return; > + > + spin_lock_irqsave(&mrioc->fwevt_lock, flags); > + /* get fwevt reference count while adding it to fwevt_list */ > + mpi3mr_fwevt_get(fwevt); > + INIT_LIST_HEAD(&fwevt->list); > + list_add_tail(&fwevt->list, &mrioc->fwevt_list); > + INIT_WORK(&fwevt->work, mpi3mr_fwevt_worker); > + /* get fwevt reference count while enqueueing it to worker queue */ > + mpi3mr_fwevt_get(fwevt); > + queue_work(mrioc->fwevt_worker_thread, &fwevt->work); > + spin_unlock_irqrestore(&mrioc->fwevt_lock, flags); > +} > + > +/** > + * mpi3mr_fwevt_del_from_list - Delete firmware event from list > + * @mrioc: Adapter instance reference > + * @fwevt: Firmware event reference > + * > + * Delete the given firmware event from the firmware event list. > + * > + * Return: Nothing. > + */ > +static void mpi3mr_fwevt_del_from_list(struct mpi3mr_ioc *mrioc, > + struct mpi3mr_fwevt *fwevt) > +{ > + unsigned long flags; > + > + spin_lock_irqsave(&mrioc->fwevt_lock, flags); > + if (!list_empty(&fwevt->list)) { > + list_del_init(&fwevt->list); > + /* > + * Put fwevt reference count after > + * removing it from fwevt_list > + */ > + mpi3mr_fwevt_put(fwevt); > + } > + spin_unlock_irqrestore(&mrioc->fwevt_lock, flags); > +} > + > +/** > + * mpi3mr_dequeue_fwevt - Dequeue firmware event from the list > + * @mrioc: Adapter instance reference > + * > + * Dequeue a firmware event from the firmware event list. > + * > + * Return: firmware event. > + */ > +static struct mpi3mr_fwevt *mpi3mr_dequeue_fwevt( > + struct mpi3mr_ioc *mrioc) > +{ > + unsigned long flags; > + struct mpi3mr_fwevt *fwevt = NULL; > + > + spin_lock_irqsave(&mrioc->fwevt_lock, flags); > + if (!list_empty(&mrioc->fwevt_list)) { > + fwevt = list_first_entry(&mrioc->fwevt_list, > + struct mpi3mr_fwevt, list); > + list_del_init(&fwevt->list); > + /* > + * Put fwevt reference count after > + * removing it from fwevt_list > + */ > + mpi3mr_fwevt_put(fwevt); > + } > + spin_unlock_irqrestore(&mrioc->fwevt_lock, flags); > + > + return fwevt; > +} > + > +/** > + * mpi3mr_cleanup_fwevt_list - Cleanup firmware event list > + * @mrioc: Adapter instance reference > + * > + * Flush all pending firmware events from the firmware event > + * list. > + * > + * Return: Nothing. > + */ > +void mpi3mr_cleanup_fwevt_list(struct mpi3mr_ioc *mrioc) > +{ > + struct mpi3mr_fwevt *fwevt = NULL; > + > + if ((list_empty(&mrioc->fwevt_list) && !mrioc->current_event) || > + !mrioc->fwevt_worker_thread) > + return; > + > + while ((fwevt = mpi3mr_dequeue_fwevt(mrioc)) || > + (fwevt = mrioc->current_event)) { > + /* > + * Wait on the fwevt to complete. If this returns 1, then > + * the event was never executed, and we need a put for the > + * reference the work had on the fwevt. > + * > + * If it did execute, we wait for it to finish, and the put will > + * happen from mpi3mr_process_fwevt() > + */ > + if (cancel_work_sync(&fwevt->work)) { > + /* > + * Put fwevt reference count after > + * dequeuing it from worker queue > + */ > + mpi3mr_fwevt_put(fwevt); > + /* > + * Put fwevt reference count to neutralize > + * kref_init increment > + */ > + mpi3mr_fwevt_put(fwevt); > + } > + } > +} > + > +/** > + * mpi3mr_alloc_tgtdev - target device allocator > + * > + * Allocate target device instance and initialize the reference > + * count > + * > + * Return: target device instance. > + */ > +static struct mpi3mr_tgt_dev *mpi3mr_alloc_tgtdev(void) > +{ > + struct mpi3mr_tgt_dev *tgtdev; > + > + tgtdev = kzalloc(sizeof(*tgtdev), GFP_ATOMIC); > + if (!tgtdev) > + return NULL; > + kref_init(&tgtdev->ref_count); > + return tgtdev; > +} > + > +/** > + * mpi3mr_tgtdev_add_to_list -Add tgtdevice to the list > + * @mrioc: Adapter instance reference > + * @tgtdev: Target device > + * > + * Add the target device to the target device list > + * > + * Return: Nothing. > + */ > +static void mpi3mr_tgtdev_add_to_list(struct mpi3mr_ioc *mrioc, > + struct mpi3mr_tgt_dev *tgtdev) > +{ > + unsigned long flags; > + > + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); > + mpi3mr_tgtdev_get(tgtdev); > + INIT_LIST_HEAD(&tgtdev->list); > + list_add_tail(&tgtdev->list, &mrioc->tgtdev_list); > + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); > +} > + > +/** > + * mpi3mr_tgtdev_del_from_list -Delete tgtdevice from the list > + * @mrioc: Adapter instance reference > + * @tgtdev: Target device > + * > + * Remove the target device from the target device list > + * > + * Return: Nothing. > + */ > +static void mpi3mr_tgtdev_del_from_list(struct mpi3mr_ioc *mrioc, > + struct mpi3mr_tgt_dev *tgtdev) > +{ > + unsigned long flags; > + > + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); > + if (!list_empty(&tgtdev->list)) { > + list_del_init(&tgtdev->list); > + mpi3mr_tgtdev_put(tgtdev); > + } > + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); > +} > + > +/** > + * __mpi3mr_get_tgtdev_by_handle -Get tgtdev from device handle > + * @mrioc: Adapter instance reference > + * @handle: Device handle > + * > + * Accessor to retrieve target device from the device handle. > + * Non Lock version > + * > + * Return: Target device reference. > + */ > +static struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_handle( > + struct mpi3mr_ioc *mrioc, u16 handle) > +{ > + struct mpi3mr_tgt_dev *tgtdev; > + > + assert_spin_locked(&mrioc->tgtdev_lock); > + list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list) > + if (tgtdev->dev_handle == handle) > + goto found_tgtdev; > + return NULL; > + > +found_tgtdev: > + mpi3mr_tgtdev_get(tgtdev); > + return tgtdev; > +} > + > +/** > + * mpi3mr_get_tgtdev_by_handle -Get tgtdev from device handle > + * @mrioc: Adapter instance reference > + * @handle: Device handle > + * > + * Accessor to retrieve target device from the device handle. > + * Lock version > + * > + * Return: Target device reference. > + */ > +static struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_handle( > + struct mpi3mr_ioc *mrioc, u16 handle) > +{ > + struct mpi3mr_tgt_dev *tgtdev; > + unsigned long flags; > + > + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); > + tgtdev = __mpi3mr_get_tgtdev_by_handle(mrioc, handle); > + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); > + return tgtdev; > +} > + > +/** > + * __mpi3mr_get_tgtdev_by_perst_id -Get tgtdev from persist ID > + * @mrioc: Adapter instance reference > + * @persist_id: Persistent ID > + * > + * Accessor to retrieve target device from the Persistent ID. > + * Non Lock version > + * > + * Return: Target device reference. > + */ > +static struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_perst_id( > + struct mpi3mr_ioc *mrioc, u16 persist_id) > +{ > + struct mpi3mr_tgt_dev *tgtdev; > + > + assert_spin_locked(&mrioc->tgtdev_lock); > + list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list) > + if (tgtdev->perst_id == persist_id) > + goto found_tgtdev; > + return NULL; > + > +found_tgtdev: > + mpi3mr_tgtdev_get(tgtdev); > + return tgtdev; > +} > + > +/** > + * mpi3mr_get_tgtdev_by_perst_id -Get tgtdev from persistent ID > + * @mrioc: Adapter instance reference > + * @persist_id: Persistent ID > + * > + * Accessor to retrieve target device from the Persistent ID. > + * Lock version > + * > + * Return: Target device reference. > + */ > +static struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_perst_id( > + struct mpi3mr_ioc *mrioc, u16 persist_id) > +{ > + struct mpi3mr_tgt_dev *tgtdev; > + unsigned long flags; > + > + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); > + tgtdev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, persist_id); > + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); > + return tgtdev; > +} > + > + > +/** > + * __mpi3mr_get_tgtdev_from_tgtpriv -Get tgtdev from tgt private > + * @mrioc: Adapter instance reference > + * @tgt_priv: Target private data > + * > + * Accessor to return target device from the target private > + * data. Non Lock version > + * > + * Return: Target device reference. > + */ > +static struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_from_tgtpriv( > + struct mpi3mr_ioc *mrioc, struct mpi3mr_stgt_priv_data *tgt_priv) > +{ > + struct mpi3mr_tgt_dev *tgtdev; > + > + assert_spin_locked(&mrioc->tgtdev_lock); > + tgtdev = tgt_priv->tgt_dev; > + if (tgtdev) > + mpi3mr_tgtdev_get(tgtdev); > + return tgtdev; > +} > + > +/** > + * mpi3mr_remove_tgtdev_from_host - Remove dev from upper layers > + * @mrioc: Adapter instance reference > + * @tgtdev: Target device structure > + * > + * Checks whether the device is exposed to upper layers and if it > + * is then remove the device from upper layers by calling > + * scsi_remove_target(). > + * > + * Return: 0 on success, non zero on failure. > + */ > +static void mpi3mr_remove_tgtdev_from_host(struct mpi3mr_ioc *mrioc, > + struct mpi3mr_tgt_dev *tgtdev) > +{ > + struct mpi3mr_stgt_priv_data *tgt_priv; > + > + > + ioc_info(mrioc, "%s :Removing handle(0x%04x), wwid(0x%016llx)\n", > + __func__, tgtdev->dev_handle, (unsigned long long) tgtdev->wwid); > + if (tgtdev->starget && tgtdev->starget->hostdata) { > + tgt_priv = tgtdev->starget->hostdata; > + tgt_priv->dev_handle = MPI3MR_INVALID_DEV_HANDLE; > + } > + > + if (tgtdev->starget) { > + scsi_remove_target(&tgtdev->starget->dev); > + tgtdev->host_exposed = 0; > + } > + ioc_info(mrioc, "%s :Removed handle(0x%04x), wwid(0x%016llx)\n", > + __func__, tgtdev->dev_handle, (unsigned long long) tgtdev->wwid); > +} > + > + > +/** > + * mpi3mr_report_tgtdev_to_host - Expose device to upper layers > + * @mrioc: Adapter instance reference > + * @perst_id: Persistent ID of the device > + * > + * Checks whether the device can be exposed to upper layers and > + * if it is not then expose the device to upper layers by > + * calling scsi_scan_target(). > + * > + * Return: 0 on success, non zero on failure. > + */ > +static int mpi3mr_report_tgtdev_to_host(struct mpi3mr_ioc *mrioc, > + u16 perst_id) > +{ > + int retval = 0; > + struct mpi3mr_tgt_dev *tgtdev; > + > + tgtdev = mpi3mr_get_tgtdev_by_perst_id(mrioc, perst_id); > + if (!tgtdev) { > + retval = -1; > + goto out; > + } > + if (tgtdev->is_hidden) { > + retval = -1; > + goto out; > + } > + if (!tgtdev->host_exposed && !mrioc->reset_in_progress) { > + tgtdev->host_exposed = 1; > + scsi_scan_target(&mrioc->shost->shost_gendev, 0, > + tgtdev->perst_id, > + SCAN_WILD_CARD, SCSI_SCAN_INITIAL); > + if (!tgtdev->starget) > + tgtdev->host_exposed = 0; > + } > +out: > + if (tgtdev) > + mpi3mr_tgtdev_put(tgtdev); > + > + return retval; > +} > + > +/** > + * mpi3mr_rfresh_tgtdevs - Refresh target device exposure > + * @mrioc: Adapter instance reference > + * > + * This is executed post controller reset to identify any > + * missing devices during reset and remove from the upper layers > + * or expose any newly detected device to the upper layers. > + * > + * Return: Nothing. > + */ > + > +void mpi3mr_rfresh_tgtdevs(struct mpi3mr_ioc *mrioc) > +{ > + struct mpi3mr_tgt_dev *tgtdev, *tgtdev_next; > + > + list_for_each_entry_safe(tgtdev, tgtdev_next, &mrioc->tgtdev_list, > + list) { > + if ((tgtdev->dev_handle == MPI3MR_INVALID_DEV_HANDLE) && > + tgtdev->host_exposed) { > + mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); > + mpi3mr_tgtdev_del_from_list(mrioc, tgtdev); > + mpi3mr_tgtdev_put(tgtdev); > + } > + } > + > + tgtdev = NULL; > + list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list) { > + if ((tgtdev->dev_handle != MPI3MR_INVALID_DEV_HANDLE) && > + !tgtdev->is_hidden && !tgtdev->host_exposed) > + mpi3mr_report_tgtdev_to_host(mrioc, tgtdev->perst_id); > + } > +} > + > +/** > + * mpi3mr_update_tgtdev - DevStatusChange evt bottomhalf > + * @mrioc: Adapter instance reference > + * @tgtdev: Target device internal structure > + * @dev_pg0: New device page0 > + * > + * Update the information from the device page0 into the driver > + * cached target device structure. > + * > + * Return: Nothing. > + */ > +static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc, > + struct mpi3mr_tgt_dev *tgtdev, Mpi3DevicePage0_t *dev_pg0) > +{ > + u16 flags = 0; > + struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data; > + > + tgtdev->perst_id = le16_to_cpu(dev_pg0->PersistentID); > + tgtdev->dev_handle = le16_to_cpu(dev_pg0->DevHandle); > + tgtdev->dev_type = dev_pg0->DeviceForm; > + tgtdev->encl_handle = le16_to_cpu(dev_pg0->EnclosureHandle); > + tgtdev->parent_handle = le16_to_cpu(dev_pg0->ParentDevHandle); > + tgtdev->slot = le16_to_cpu(dev_pg0->Slot); > + tgtdev->q_depth = le16_to_cpu(dev_pg0->QueueDepth); > + tgtdev->wwid = le64_to_cpu(dev_pg0->WWID); > + > + flags = le16_to_cpu(dev_pg0->Flags); > + tgtdev->is_hidden = (flags & MPI3_DEVICE0_FLAGS_HIDDEN); > + > + if (tgtdev->starget && tgtdev->starget->hostdata) { > + scsi_tgt_priv_data = (struct mpi3mr_stgt_priv_data *) > + tgtdev->starget->hostdata; > + scsi_tgt_priv_data->perst_id = tgtdev->perst_id; > + scsi_tgt_priv_data->dev_handle = tgtdev->dev_handle; > + scsi_tgt_priv_data->dev_type = tgtdev->dev_type; > + } > + > + switch (tgtdev->dev_type) { > + case MPI3_DEVICE_DEVFORM_SAS_SATA: > + { > + Mpi3Device0SasSataFormat_t *sasinf = > + &dev_pg0->DeviceSpecific.SasSataFormat; > + u16 dev_info = le16_to_cpu(sasinf->DeviceInfo); > + > + tgtdev->dev_spec.sas_sata_inf.dev_info = dev_info; > + tgtdev->dev_spec.sas_sata_inf.sas_address = > + le64_to_cpu(sasinf->SASAddress); > + if ((dev_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) != > + MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE) > + tgtdev->is_hidden = 1; > + else if (!(dev_info & (MPI3_SAS_DEVICE_INFO_STP_SATA_TARGET | > + MPI3_SAS_DEVICE_INFO_SSP_TARGET))) > + tgtdev->is_hidden = 1; > + break; > + } > + case MPI3_DEVICE_DEVFORM_VD: > + { > + Mpi3Device0VdFormat_t *vdinf = > + &dev_pg0->DeviceSpecific.VdFormat; > + > + tgtdev->dev_spec.vol_inf.state = vdinf->VdState; > + if (vdinf->VdState == MPI3_DEVICE0_VD_STATE_OFFLINE) > + tgtdev->is_hidden = 1; > + break; > + } > + default: > + break; > + } > +} > + > +/** > + * mpi3mr_devstatuschg_evt_bh - DevStatusChange evt bottomhalf > + * @mrioc: Adapter instance reference > + * @fwevt: Firmware event information. > + * > + * Process Device Status Change event and based on device's new > + * information, either expose the device to the upper layers, or > + * remove the device from upper layers. > + * > + * Return: Nothing. > + */ > +static void mpi3mr_devstatuschg_evt_bh(struct mpi3mr_ioc *mrioc, > + struct mpi3mr_fwevt *fwevt) > +{ > + u16 dev_handle = 0; > + u8 uhide = 0, delete = 0, cleanup = 0; > + struct mpi3mr_tgt_dev *tgtdev = NULL; > + Mpi3EventDataDeviceStatusChange_t *evtdata = > + (Mpi3EventDataDeviceStatusChange_t *)fwevt->event_data; > + > + > + dev_handle = le16_to_cpu(evtdata->DevHandle); > + ioc_info(mrioc, > + "%s :device status change: handle(0x%04x): reason code(0x%x)\n", > + __func__, dev_handle, evtdata->ReasonCode); > + switch (evtdata->ReasonCode) { > + case MPI3_EVENT_DEV_STAT_RC_HIDDEN: > + delete = 1; > + break; > + case MPI3_EVENT_DEV_STAT_RC_NOT_HIDDEN: > + uhide = 1; > + break; > + case MPI3_EVENT_DEV_STAT_RC_VD_NOT_RESPONDING: > + delete = 1; > + cleanup = 1; > + break; > + default: > + ioc_info(mrioc, "%s :Unhandled reason code(0x%x)\n", __func__, > + evtdata->ReasonCode); > + break; > + } > + > + tgtdev = mpi3mr_get_tgtdev_by_handle(mrioc, dev_handle); > + if (!tgtdev) > + goto out; > + if (uhide) { > + tgtdev->is_hidden = 0; > + if (!tgtdev->host_exposed) > + mpi3mr_report_tgtdev_to_host(mrioc, tgtdev->perst_id); > + } > + if (tgtdev->starget && tgtdev->starget->hostdata) { > + if (delete) > + mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); > + } > + if (cleanup) { > + mpi3mr_tgtdev_del_from_list(mrioc, tgtdev); > + mpi3mr_tgtdev_put(tgtdev); > + } > + > +out: > + if (tgtdev) > + mpi3mr_tgtdev_put(tgtdev); > + > +} > + > +/** > + * mpi3mr_devinfochg_evt_bh - DeviceInfoChange evt bottomhalf > + * @mrioc: Adapter instance reference > + * @dev_pg0: New device page0 > + * > + * Process Device Info Change event and based on device's new > + * information, either expose the device to the upper layers, or > + * remove the device from upper layers or update the details of > + * the device. > + * > + * Return: Nothing. > + */ > +static void mpi3mr_devinfochg_evt_bh(struct mpi3mr_ioc *mrioc, > + Mpi3DevicePage0_t *dev_pg0) > +{ > + struct mpi3mr_tgt_dev *tgtdev = NULL; > + u16 dev_handle = 0, perst_id = 0; > + > + perst_id = le16_to_cpu(dev_pg0->PersistentID); > + dev_handle = le16_to_cpu(dev_pg0->DevHandle); > + ioc_info(mrioc, > + "%s :Device info change: handle(0x%04x): persist_id(0x%x)\n", > + __func__, dev_handle, perst_id); > + tgtdev = mpi3mr_get_tgtdev_by_handle(mrioc, dev_handle); > + if (!tgtdev) > + goto out; > + mpi3mr_update_tgtdev(mrioc, tgtdev, dev_pg0); > + if (!tgtdev->is_hidden && !tgtdev->host_exposed) > + mpi3mr_report_tgtdev_to_host(mrioc, perst_id); > + if (tgtdev->is_hidden && tgtdev->host_exposed) > + mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); > +out: > + if (tgtdev) > + mpi3mr_tgtdev_put(tgtdev); > + > +} > + > +/** > + * mpi3mr_sastopochg_evt_bh - SASTopologyChange evt bottomhalf > + * @mrioc: Adapter instance reference > + * @fwevt: Firmware event reference > + * > + * Prints information about the SAS topology change event and > + * for "not responding" event code, removes the device from the > + * upper layers. > + * > + * Return: Nothing. > + */ > +static void mpi3mr_sastopochg_evt_bh(struct mpi3mr_ioc *mrioc, > + struct mpi3mr_fwevt *fwevt) > +{ > + Mpi3EventDataSasTopologyChangeList_t *event_data = > + (Mpi3EventDataSasTopologyChangeList_t *)fwevt->event_data; > + int i; > + u16 handle; > + u8 reason_code; > + struct mpi3mr_tgt_dev *tgtdev = NULL; > + > + for (i = 0; i < event_data->NumEntries; i++) { > + handle = le16_to_cpu(event_data->PhyEntry[i].AttachedDevHandle); > + if (!handle) > + continue; > + tgtdev = mpi3mr_get_tgtdev_by_handle(mrioc, handle); > + if (!tgtdev) > + continue; > + > + reason_code = event_data->PhyEntry[i].Status & > + MPI3_EVENT_SAS_TOPO_PHY_RC_MASK; > + > + switch (reason_code) { > + case MPI3_EVENT_SAS_TOPO_PHY_RC_TARG_NOT_RESPONDING: > + if (tgtdev->host_exposed) > + mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); > + mpi3mr_tgtdev_del_from_list(mrioc, tgtdev); > + mpi3mr_tgtdev_put(tgtdev); > + break; > + default: > + break; > + } > + if (tgtdev) > + mpi3mr_tgtdev_put(tgtdev); > + } > +} > + > +/** > + * mpi3mr_fwevt_bh - Firmware event bottomhalf handler > + * @mrioc: Adapter instance reference > + * @fwevt: Firmware event reference > + * > + * Identifies the firmware event and calls corresponding bottomg > + * half handler and sends event acknowledgment if required. > + * > + * Return: Nothing. > + */ > +static void mpi3mr_fwevt_bh(struct mpi3mr_ioc *mrioc, > + struct mpi3mr_fwevt *fwevt) > +{ > + mrioc->current_event = fwevt; > + mpi3mr_fwevt_del_from_list(mrioc, fwevt); > + > + if (mrioc->stop_drv_processing) > + goto out; > + > + if (!fwevt->process_evt) > + goto evt_ack; > + > + switch (fwevt->event_id) { > + case MPI3_EVENT_DEVICE_ADDED: > + { > + Mpi3DevicePage0_t *dev_pg0 = > + (Mpi3DevicePage0_t *) fwevt->event_data; > + mpi3mr_report_tgtdev_to_host(mrioc, > + le16_to_cpu(dev_pg0->PersistentID)); > + break; > + } > + case MPI3_EVENT_DEVICE_INFO_CHANGED: > + { > + mpi3mr_devinfochg_evt_bh(mrioc, > + (Mpi3DevicePage0_t *) fwevt->event_data); > + break; > + } > + case MPI3_EVENT_DEVICE_STATUS_CHANGE: > + { > + mpi3mr_devstatuschg_evt_bh(mrioc, fwevt); > + break; > + } > + case MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST: > + { > + mpi3mr_sastopochg_evt_bh(mrioc, fwevt); > + break; > + } > + default: > + break; > + } > + > +evt_ack: > + if (fwevt->send_ack) > + mpi3mr_send_event_ack(mrioc, fwevt->event_id, > + fwevt->evt_ctx); > +out: > + /* Put fwevt reference count to neutralize kref_init increment */ > + mpi3mr_fwevt_put(fwevt); > + mrioc->current_event = NULL; > + > +} > + > +/** > + * mpi3mr_fwevt_worker - Firmware event worker > + * @work: Work struct containing firmware event > + * > + * Extracts the firmware event and calls mpi3mr_fwevt_bh. > + * > + * Return: Nothing. > + */ > +static void mpi3mr_fwevt_worker(struct work_struct *work) > +{ > + struct mpi3mr_fwevt *fwevt = container_of(work, struct mpi3mr_fwevt, > + work); > + mpi3mr_fwevt_bh(fwevt->mrioc, fwevt); > + /* > + * Put fwevt reference count after > + * dequeuing it from worker queue > + */ > + mpi3mr_fwevt_put(fwevt); > +} > + > + > +/** > + * mpi3mr_create_tgtdev - Create and add a target device > + * @mrioc: Adapter instance reference > + * @dev_pg0: Device Page 0 data > + * > + * If the device specified by the device page 0 data is not > + * present in the driver's internal list, allocate the memory > + * for the device, populate the data and add to the list, else > + * update the device data. The key is persistent ID. > + * > + * Return: 0 on success, -ENOMEM on memory allocation failure > + */ > +static int mpi3mr_create_tgtdev(struct mpi3mr_ioc *mrioc, > + Mpi3DevicePage0_t *dev_pg0) > +{ > + int retval = 0; > + struct mpi3mr_tgt_dev *tgtdev = NULL; > + u16 perst_id = 0; > + > + perst_id = le16_to_cpu(dev_pg0->PersistentID); > + tgtdev = mpi3mr_get_tgtdev_by_perst_id(mrioc, perst_id); > + if (tgtdev) { > + mpi3mr_update_tgtdev(mrioc, tgtdev, dev_pg0); > + mpi3mr_tgtdev_put(tgtdev); > + } else { > + tgtdev = mpi3mr_alloc_tgtdev(); > + if (!tgtdev) > + return -ENOMEM; > + mpi3mr_update_tgtdev(mrioc, tgtdev, dev_pg0); > + mpi3mr_tgtdev_add_to_list(mrioc, tgtdev); > + } > + > + return retval; > +} > + > +/** > + * mpi3mr_flush_delayed_rmhs_list - Flush pending commands > + * @mrioc: Adapter instance reference > + * > + * Flush pending commands in the delayed removal handshake list > + * due to a controller reset or driver removal as a cleanup. > + * > + * Return: Nothing > + */ > +void mpi3mr_flush_delayed_rmhs_list(struct mpi3mr_ioc *mrioc) > +{ > + struct delayed_dev_rmhs_node *_rmhs_node; > + > + while (!list_empty(&mrioc->delayed_rmhs_list)) { > + _rmhs_node = list_entry(mrioc->delayed_rmhs_list.next, > + struct delayed_dev_rmhs_node, list); > + list_del(&_rmhs_node->list); > + kfree(_rmhs_node); > + } > +} > + > +/** > + * mpi3mr_dev_rmhs_complete_iou - Device removal IOUC completion > + * @mrioc: Adapter instance reference > + * @drv_cmd: Internal command tracker > + * > + * Issues a target reset TM to the firmware from the device > + * removal TM pend list or retry the removal handshake sequence > + * based on the IOU control request IOC status. > + * > + * Return: Nothing > + */ > +static void mpi3mr_dev_rmhs_complete_iou(struct mpi3mr_ioc *mrioc, > + struct mpi3mr_drv_cmd *drv_cmd) > +{ > + u16 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN; > + struct delayed_dev_rmhs_node *delayed_dev_rmhs = NULL; > + > + ioc_info(mrioc, > + "%s :dev_rmhs_iouctrl_complete:handle(0x%04x), ioc_status(0x%04x), loginfo(0x%08x)\n", > + __func__, drv_cmd->dev_handle, drv_cmd->ioc_status, > + drv_cmd->ioc_loginfo); > + if (drv_cmd->ioc_status != MPI3_IOCSTATUS_SUCCESS) { > + if (drv_cmd->retry_count < MPI3MR_DEV_RMHS_RETRY_COUNT) { > + drv_cmd->retry_count++; > + ioc_info(mrioc, > + "%s :dev_rmhs_iouctrl_complete: handle(0x%04x)retrying handshake retry=%d\n", > + __func__, drv_cmd->dev_handle, > + drv_cmd->retry_count); > + mpi3mr_dev_rmhs_send_tm(mrioc, drv_cmd->dev_handle, > + drv_cmd, drv_cmd->iou_rc); > + return; > + } > + ioc_err(mrioc, > + "%s :dev removal handshake failed after all retries: handle(0x%04x)\n", > + __func__, drv_cmd->dev_handle); > + } else { > + ioc_info(mrioc, > + "%s :dev removal handshake completed successfully: handle(0x%04x)\n", > + __func__, drv_cmd->dev_handle); > + clear_bit(drv_cmd->dev_handle, mrioc->removepend_bitmap); > + } > + > + if (!list_empty(&mrioc->delayed_rmhs_list)) { > + delayed_dev_rmhs = list_entry(mrioc->delayed_rmhs_list.next, > + struct delayed_dev_rmhs_node, list); > + drv_cmd->dev_handle = delayed_dev_rmhs->handle; > + drv_cmd->retry_count = 0; > + drv_cmd->iou_rc = delayed_dev_rmhs->iou_rc; > + ioc_info(mrioc, > + "%s :dev_rmhs_iouctrl_complete: processing delayed TM: handle(0x%04x)\n", > + __func__, drv_cmd->dev_handle); > + mpi3mr_dev_rmhs_send_tm(mrioc, drv_cmd->dev_handle, drv_cmd, > + drv_cmd->iou_rc); > + list_del(&delayed_dev_rmhs->list); > + kfree(delayed_dev_rmhs); > + return; > + } > + drv_cmd->state = MPI3MR_CMD_NOTUSED; > + drv_cmd->callback = NULL; > + drv_cmd->retry_count = 0; > + drv_cmd->dev_handle = MPI3MR_INVALID_DEV_HANDLE; > + clear_bit(cmd_idx, mrioc->devrem_bitmap); > +} > + > +/** > + * mpi3mr_dev_rmhs_complete_tm - Device removal TM completion > + * @mrioc: Adapter instance reference > + * @drv_cmd: Internal command tracker > + * > + * Issues a target reset TM to the firmware from the device > + * removal TM pend list or issue IO Unit control request as > + * part of device removal or hidden acknowledgment handshake. > + * > + * Return: Nothing > + */ > +static void mpi3mr_dev_rmhs_complete_tm(struct mpi3mr_ioc *mrioc, > + struct mpi3mr_drv_cmd *drv_cmd) > +{ > + Mpi3IoUnitControlRequest_t iou_ctrl; > + u16 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN; > + Mpi3SCSITaskMgmtReply_t *tm_reply = NULL; > + int retval; > + > + if (drv_cmd->state & MPI3MR_CMD_REPLY_VALID) > + tm_reply = (Mpi3SCSITaskMgmtReply_t *)drv_cmd->reply; > + > + if (tm_reply) > + pr_info(IOCNAME > + "dev_rmhs_tr_complete:handle(0x%04x), ioc_status(0x%04x), loginfo(0x%08x), term_count(%d)\n", > + mrioc->name, drv_cmd->dev_handle, drv_cmd->ioc_status, > + drv_cmd->ioc_loginfo, > + le32_to_cpu(tm_reply->TerminationCount)); > + > + pr_info(IOCNAME "Issuing IOU CTL: handle(0x%04x) dev_rmhs idx(%d)\n", > + mrioc->name, drv_cmd->dev_handle, cmd_idx); > + > + memset(&iou_ctrl, 0, sizeof(iou_ctrl)); > + > + drv_cmd->state = MPI3MR_CMD_PENDING; > + drv_cmd->is_waiting = 0; > + drv_cmd->callback = mpi3mr_dev_rmhs_complete_iou; > + iou_ctrl.Operation = drv_cmd->iou_rc; > + iou_ctrl.Param16[0] = cpu_to_le16(drv_cmd->dev_handle); > + iou_ctrl.HostTag = cpu_to_le16(drv_cmd->host_tag); > + iou_ctrl.Function = MPI3_FUNCTION_IO_UNIT_CONTROL; > + > + retval = mpi3mr_admin_request_post(mrioc, &iou_ctrl, sizeof(iou_ctrl), > + 1); > + if (retval) { > + pr_err(IOCNAME "Issue DevRmHsTMIOUCTL: Admin post failed\n", > + mrioc->name); > + goto out_failed; > + } > + > + return; > +out_failed: > + drv_cmd->state = MPI3MR_CMD_NOTUSED; > + drv_cmd->callback = NULL; > + drv_cmd->dev_handle = MPI3MR_INVALID_DEV_HANDLE; > + drv_cmd->retry_count = 0; > + clear_bit(cmd_idx, mrioc->devrem_bitmap); > +} > + > +/** > + * mpi3mr_dev_rmhs_send_tm - Issue TM for device removal > + * @mrioc: Adapter instance reference > + * @handle: Device handle > + * @cmdparam: Internal command tracker > + * @iou_rc: IO Unit reason code > + * > + * Issues a target reset TM to the firmware or add it to a pend > + * list as part of device removal or hidden acknowledgment > + * handshake. > + * > + * Return: Nothing > + */ > +static void mpi3mr_dev_rmhs_send_tm(struct mpi3mr_ioc *mrioc, u16 handle, > + struct mpi3mr_drv_cmd *cmdparam, u8 iou_rc) > +{ > + Mpi3SCSITaskMgmtRequest_t tm_req; > + int retval = 0; > + u16 cmd_idx = MPI3MR_NUM_DEVRMCMD; > + u8 retrycount = 5; > + struct mpi3mr_drv_cmd *drv_cmd = cmdparam; > + struct delayed_dev_rmhs_node *delayed_dev_rmhs = NULL; > + > + if (drv_cmd) > + goto issue_cmd; > + do { > + cmd_idx = find_first_zero_bit(mrioc->devrem_bitmap, > + MPI3MR_NUM_DEVRMCMD); > + if (cmd_idx < MPI3MR_NUM_DEVRMCMD) { > + if (!test_and_set_bit(cmd_idx, mrioc->devrem_bitmap)) > + break; > + cmd_idx = MPI3MR_NUM_DEVRMCMD; > + } > + } while (retrycount--); > + > + if (cmd_idx >= MPI3MR_NUM_DEVRMCMD) { > + delayed_dev_rmhs = kzalloc(sizeof(*delayed_dev_rmhs), > + GFP_ATOMIC); > + if (!delayed_dev_rmhs) > + return; > + INIT_LIST_HEAD(&delayed_dev_rmhs->list); > + delayed_dev_rmhs->handle = handle; > + delayed_dev_rmhs->iou_rc = iou_rc; > + list_add_tail(&delayed_dev_rmhs->list, > + &mrioc->delayed_rmhs_list); > + ioc_info(mrioc, "%s :DevRmHs: tr:handle(0x%04x) is postponed\n", > + __func__, handle); > + return; > + } > + drv_cmd = &mrioc->dev_rmhs_cmds[cmd_idx]; > + > +issue_cmd: > + cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN; > + ioc_info(mrioc, > + "%s :Issuing TR TM: for devhandle 0x%04x with dev_rmhs %d\n", > + __func__, handle, cmd_idx); > + > + memset(&tm_req, 0, sizeof(tm_req)); > + if (drv_cmd->state & MPI3MR_CMD_PENDING) { > + ioc_err(mrioc, "%s :Issue TM: Command is in use\n", __func__); > + goto out; > + } > + drv_cmd->state = MPI3MR_CMD_PENDING; > + drv_cmd->is_waiting = 0; > + drv_cmd->callback = mpi3mr_dev_rmhs_complete_tm; > + drv_cmd->dev_handle = handle; > + drv_cmd->iou_rc = iou_rc; > + tm_req.DevHandle = cpu_to_le16(handle); > + tm_req.TaskType = MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET; > + tm_req.HostTag = cpu_to_le16(drv_cmd->host_tag); > + tm_req.TaskHostTag = cpu_to_le16(MPI3MR_HOSTTAG_INVALID); > + tm_req.Function = MPI3_FUNCTION_SCSI_TASK_MGMT; > + > + set_bit(handle, mrioc->removepend_bitmap); > + retval = mpi3mr_admin_request_post(mrioc, &tm_req, sizeof(tm_req), 1); > + if (retval) { > + ioc_err(mrioc, "%s :Issue DevRmHsTM: Admin Post failed\n", > + __func__); > + goto out_failed; > + } > +out: > + return; > +out_failed: > + drv_cmd->state = MPI3MR_CMD_NOTUSED; > + drv_cmd->callback = NULL; > + drv_cmd->dev_handle = MPI3MR_INVALID_DEV_HANDLE; > + drv_cmd->retry_count = 0; > + clear_bit(cmd_idx, mrioc->devrem_bitmap); > +} > + > +/** > + * mpi3mr_sastopochg_evt_th - SASTopologyChange evt tophalf > + * @mrioc: Adapter instance reference > + * @event_reply: Event data > + * > + * Checks for the reason code and based on that either block I/O > + * to device, or unblock I/O to the device, or start the device > + * removal handshake with reason as remove with the firmware for > + * SAS/SATA devices. > + * > + * Return: Nothing > + */ > +static void mpi3mr_sastopochg_evt_th(struct mpi3mr_ioc *mrioc, > + Mpi3EventNotificationReply_t *event_reply) > +{ > + Mpi3EventDataSasTopologyChangeList_t *topo_evt = > + (Mpi3EventDataSasTopologyChangeList_t *)event_reply->EventData; > + int i; > + u16 handle; > + u8 reason_code; > + struct mpi3mr_tgt_dev *tgtdev = NULL; > + struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data = NULL; > + > + for (i = 0; i < topo_evt->NumEntries; i++) { > + handle = le16_to_cpu(topo_evt->PhyEntry[i].AttachedDevHandle); > + if (!handle) > + continue; > + reason_code = topo_evt->PhyEntry[i].Status & > + MPI3_EVENT_SAS_TOPO_PHY_RC_MASK; > + scsi_tgt_priv_data = NULL; > + tgtdev = mpi3mr_get_tgtdev_by_handle(mrioc, handle); > + if (tgtdev && tgtdev->starget && tgtdev->starget->hostdata) > + scsi_tgt_priv_data = (struct mpi3mr_stgt_priv_data *) > + tgtdev->starget->hostdata; > + switch (reason_code) { > + case MPI3_EVENT_SAS_TOPO_PHY_RC_TARG_NOT_RESPONDING: > + if (scsi_tgt_priv_data) { > + scsi_tgt_priv_data->dev_removed = 1; > + scsi_tgt_priv_data->dev_removedelay = 0; > + atomic_set(&scsi_tgt_priv_data->block_io, 0); > + } > + mpi3mr_dev_rmhs_send_tm(mrioc, handle, NULL, > + MPI3_CTRL_OP_REMOVE_DEVICE); > + break; > + case MPI3_EVENT_SAS_TOPO_PHY_RC_DELAY_NOT_RESPONDING: > + if (scsi_tgt_priv_data) { > + scsi_tgt_priv_data->dev_removedelay = 1; > + atomic_inc(&scsi_tgt_priv_data->block_io); > + } > + break; > + case MPI3_EVENT_SAS_TOPO_PHY_RC_RESPONDING: > + if (scsi_tgt_priv_data && > + scsi_tgt_priv_data->dev_removedelay) { > + scsi_tgt_priv_data->dev_removedelay = 0; > + atomic_dec_if_positive > + (&scsi_tgt_priv_data->block_io); > + } > + case MPI3_EVENT_SAS_TOPO_PHY_RC_PHY_CHANGED: > + default: > + break; > + } > + if (tgtdev) > + mpi3mr_tgtdev_put(tgtdev); > + } > + > +} > + > +/** > + * mpi3mr_devstatuschg_evt_th - DeviceStatusChange evt tophalf > + * @mrioc: Adapter instance reference > + * @event_reply: Event data > + * > + * Checks for the reason code and based on that either block I/O > + * to device, or unblock I/O to the device, or start the device > + * removal handshake with reason as remove/hide acknowledgment > + * with the firmware. > + * > + * Return: Nothing > + */ > +static void mpi3mr_devstatuschg_evt_th(struct mpi3mr_ioc *mrioc, > + Mpi3EventNotificationReply_t *event_reply) > +{ > + u16 dev_handle = 0; > + u8 ublock = 0, block = 0, hide = 0, delete = 0, remove = 0; > + struct mpi3mr_tgt_dev *tgtdev = NULL; > + struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data = NULL; > + Mpi3EventDataDeviceStatusChange_t *evtdata = > + (Mpi3EventDataDeviceStatusChange_t *) event_reply->EventData; > + > + if (mrioc->stop_drv_processing) > + goto out; > + > + dev_handle = le16_to_cpu(evtdata->DevHandle); > + > + switch (evtdata->ReasonCode) { > + case MPI3_EVENT_DEV_STAT_RC_INT_DEVICE_RESET_STRT: > + case MPI3_EVENT_DEV_STAT_RC_INT_IT_NEXUS_RESET_STRT: > + block = 1; > + break; > + case MPI3_EVENT_DEV_STAT_RC_HIDDEN: > + delete = 1; > + hide = 1; > + break; > + case MPI3_EVENT_DEV_STAT_RC_VD_NOT_RESPONDING: > + delete = 1; > + remove = 1; > + break; > + case MPI3_EVENT_DEV_STAT_RC_INT_DEVICE_RESET_CMP: > + case MPI3_EVENT_DEV_STAT_RC_INT_IT_NEXUS_RESET_CMP: > + ublock = 1; > + break; > + default: > + break; > + } > + > + tgtdev = mpi3mr_get_tgtdev_by_handle(mrioc, dev_handle); > + if (!tgtdev) > + goto out; > + if (hide) > + tgtdev->is_hidden = hide; > + if (tgtdev->starget && tgtdev->starget->hostdata) { > + scsi_tgt_priv_data = (struct mpi3mr_stgt_priv_data *) > + tgtdev->starget->hostdata; > + if (block) > + atomic_inc(&scsi_tgt_priv_data->block_io); > + if (delete) > + scsi_tgt_priv_data->dev_removed = 1; > + if (ublock) > + atomic_dec_if_positive(&scsi_tgt_priv_data->block_io); > + } > + if (remove) > + mpi3mr_dev_rmhs_send_tm(mrioc, dev_handle, NULL, > + MPI3_CTRL_OP_REMOVE_DEVICE); > + if (hide) > + mpi3mr_dev_rmhs_send_tm(mrioc, dev_handle, NULL, > + MPI3_CTRL_OP_HIDDEN_ACK); > + > +out: > + if (tgtdev) > + mpi3mr_tgtdev_put(tgtdev); > + > +} > + > +/** > + * mpi3mr_os_handle_events - Firmware event handler > + * @mrioc: Adapter instance reference > + * @event_reply: Event data > + * > + * Identify whteher the event has to handled and acknowledged > + * and either process the event in the tophalf and/or schedule a > + * bottom half through mpi3mr_fwevt_worker. > + * > + * Return: Nothing > + */ > +void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc, > + Mpi3EventNotificationReply_t *event_reply) > +{ > + u16 evt_type, sz; > + struct mpi3mr_fwevt *fwevt = NULL; > + bool ack_req = 0, process_evt_bh = 0; > + > + if (mrioc->stop_drv_processing) > + return; > + > + if ((event_reply->MsgFlags & MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_MASK) > + == MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_REQUIRED) > + ack_req = 1; > + > + evt_type = event_reply->Event; > + > + switch (evt_type) { > + case MPI3_EVENT_DEVICE_ADDED: > + { > + Mpi3DevicePage0_t *dev_pg0 = > + (Mpi3DevicePage0_t *) event_reply->EventData; > + if (mpi3mr_create_tgtdev(mrioc, dev_pg0)) > + ioc_err(mrioc, > + "%s :Failed to add device in the device add event\n", > + __func__); > + else > + process_evt_bh = 1; > + break; > + } > + case MPI3_EVENT_DEVICE_STATUS_CHANGE: > + { > + process_evt_bh = 1; > + mpi3mr_devstatuschg_evt_th(mrioc, event_reply); > + break; > + } > + case MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST: > + { > + process_evt_bh = 1; > + mpi3mr_sastopochg_evt_th(mrioc, event_reply); > + break; > + } > + case MPI3_EVENT_DEVICE_INFO_CHANGED: > + { > + process_evt_bh = 1; > + break; > + } > + case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE: > + case MPI3_EVENT_SAS_DISCOVERY: > + case MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR: > + break; > + default: > + ioc_info(mrioc, "%s :Event 0x%02x is not handled\n", > + __func__, evt_type); > + break; > + } > + if (process_evt_bh || ack_req) { > + sz = event_reply->EventDataLength * 4; > + fwevt = mpi3mr_alloc_fwevt(sz); > + if (!fwevt) { > + ioc_info(mrioc, "%s :failure at %s:%d/%s()!\n", > + __func__, __FILE__, __LINE__, __func__); > + return; > + } > + > + memcpy(fwevt->event_data, event_reply->EventData, sz); > + fwevt->mrioc = mrioc; > + fwevt->event_id = evt_type; > + fwevt->send_ack = ack_req; > + fwevt->process_evt = process_evt_bh; > + fwevt->evt_ctx = le32_to_cpu(event_reply->EventContext); > + mpi3mr_fwevt_add_to_list(mrioc, fwevt); > + } > + > +} > + > /** > * mpi3mr_process_op_reply_desc - reply descriptor handler > * @mrioc: Adapter instance reference > @@ -587,6 +1861,33 @@ static int mpi3mr_scan_finished(struct Scsi_Host *shost, > */ > static void mpi3mr_slave_destroy(struct scsi_device *sdev) > { > + struct Scsi_Host *shost; > + struct mpi3mr_ioc *mrioc; > + struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data; > + struct mpi3mr_tgt_dev *tgt_dev; > + unsigned long flags; > + struct scsi_target *starget; > + > + if (!sdev->hostdata) > + return; > + > + starget = scsi_target(sdev); > + shost = dev_to_shost(&starget->dev); > + mrioc = shost_priv(shost); > + scsi_tgt_priv_data = starget->hostdata; > + > + scsi_tgt_priv_data->num_luns--; > + > + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); > + tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id); > + if (tgt_dev && (!scsi_tgt_priv_data->num_luns)) > + tgt_dev->starget = NULL; > + if (tgt_dev) > + mpi3mr_tgtdev_put(tgt_dev); > + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); > + > + kfree(sdev->hostdata); > + sdev->hostdata = NULL; > } > > /** > @@ -599,6 +1900,35 @@ static void mpi3mr_slave_destroy(struct scsi_device *sdev) > */ > static void mpi3mr_target_destroy(struct scsi_target *starget) > { > + struct Scsi_Host *shost; > + struct mpi3mr_ioc *mrioc; > + struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data; > + struct mpi3mr_tgt_dev *tgt_dev; > + unsigned long flags; > + > + if (!starget->hostdata) > + return; > + > + shost = dev_to_shost(&starget->dev); > + mrioc = shost_priv(shost); > + scsi_tgt_priv_data = starget->hostdata; > + > + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); > + tgt_dev = __mpi3mr_get_tgtdev_from_tgtpriv(mrioc, scsi_tgt_priv_data); > + if (tgt_dev && (tgt_dev->starget == starget) && > + (tgt_dev->perst_id == starget->id)) > + tgt_dev->starget = NULL; > + if (tgt_dev) { > + scsi_tgt_priv_data->tgt_dev = NULL; > + scsi_tgt_priv_data->perst_id = 0; > + mpi3mr_tgtdev_put(tgt_dev); > + mpi3mr_tgtdev_put(tgt_dev); > + } > + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); > + > + kfree(starget->hostdata); > + starget->hostdata = NULL; > + > } > > /** > @@ -612,7 +1942,25 @@ static void mpi3mr_target_destroy(struct scsi_target *starget) > */ > static int mpi3mr_slave_configure(struct scsi_device *sdev) > { > + struct scsi_target *starget; > + struct Scsi_Host *shost; > + struct mpi3mr_ioc *mrioc; > + struct mpi3mr_tgt_dev *tgt_dev; > + unsigned long flags; > int retval = 0; > + > + starget = scsi_target(sdev); > + shost = dev_to_shost(&starget->dev); > + mrioc = shost_priv(shost); > + > + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); > + tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id); > + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); > + if (!tgt_dev) > + return retval; > + > + mpi3mr_tgtdev_put(tgt_dev); > + > return retval; > } > > @@ -626,7 +1974,37 @@ static int mpi3mr_slave_configure(struct scsi_device *sdev) > */ > static int mpi3mr_slave_alloc(struct scsi_device *sdev) > { > + struct Scsi_Host *shost; > + struct mpi3mr_ioc *mrioc; > + struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data; > + struct mpi3mr_tgt_dev *tgt_dev; > + struct mpi3mr_sdev_priv_data *scsi_dev_priv_data; > + unsigned long flags; > + struct scsi_target *starget; > int retval = 0; > + > + starget = scsi_target(sdev); > + shost = dev_to_shost(&starget->dev); > + mrioc = shost_priv(shost); > + scsi_tgt_priv_data = starget->hostdata; > + > + scsi_dev_priv_data = kzalloc(sizeof(*scsi_dev_priv_data), GFP_KERNEL); > + if (!scsi_dev_priv_data) > + return -ENOMEM; > + > + scsi_dev_priv_data->lun_id = sdev->lun; > + scsi_dev_priv_data->tgt_priv_data = scsi_tgt_priv_data; > + sdev->hostdata = scsi_dev_priv_data; > + > + scsi_tgt_priv_data->num_luns++; > + > + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); > + tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id); > + if (tgt_dev && (tgt_dev->starget == NULL)) > + tgt_dev->starget = starget; > + if (tgt_dev) > + mpi3mr_tgtdev_put(tgt_dev); > + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); > return retval; > } > > @@ -640,7 +2018,33 @@ static int mpi3mr_slave_alloc(struct scsi_device *sdev) > */ > static int mpi3mr_target_alloc(struct scsi_target *starget) > { > + struct Scsi_Host *shost = dev_to_shost(&starget->dev); > + struct mpi3mr_ioc *mrioc = shost_priv(shost); > + struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data; > + struct mpi3mr_tgt_dev *tgt_dev; > + unsigned long flags; > int retval = -ENODEV; > + > + scsi_tgt_priv_data = kzalloc(sizeof(*scsi_tgt_priv_data), GFP_KERNEL); > + if (!scsi_tgt_priv_data) > + return -ENOMEM; > + > + starget->hostdata = scsi_tgt_priv_data; > + scsi_tgt_priv_data->starget = starget; > + scsi_tgt_priv_data->dev_handle = MPI3MR_INVALID_DEV_HANDLE; > + > + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); > + tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id); > + if (tgt_dev && !tgt_dev->is_hidden) { > + scsi_tgt_priv_data->dev_handle = tgt_dev->dev_handle; > + scsi_tgt_priv_data->perst_id = tgt_dev->perst_id; > + scsi_tgt_priv_data->dev_type = tgt_dev->dev_type; > + scsi_tgt_priv_data->tgt_dev = tgt_dev; > + tgt_dev->starget = starget; > + atomic_set(&scsi_tgt_priv_data->block_io, 0); > + retval = 0; > + } > + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); > return retval; > } > > @@ -836,7 +2240,7 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) > { > struct mpi3mr_ioc *mrioc = NULL; > struct Scsi_Host *shost = NULL; > - int retval = 0; > + int retval = 0, i; > > shost = scsi_host_alloc(&mpi3mr_driver_template, > sizeof(struct mpi3mr_ioc)); > @@ -857,11 +2261,21 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) > spin_lock_init(&mrioc->admin_req_lock); > spin_lock_init(&mrioc->reply_free_queue_lock); > spin_lock_init(&mrioc->sbq_lock); > + spin_lock_init(&mrioc->fwevt_lock); > + spin_lock_init(&mrioc->tgtdev_lock); > spin_lock_init(&mrioc->watchdog_lock); > spin_lock_init(&mrioc->chain_buf_lock); > > + INIT_LIST_HEAD(&mrioc->fwevt_list); > + INIT_LIST_HEAD(&mrioc->tgtdev_list); > + INIT_LIST_HEAD(&mrioc->delayed_rmhs_list); > + > mpi3mr_init_drv_cmd(&mrioc->init_cmds, MPI3MR_HOSTTAG_INITCMDS); > > + for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) > + mpi3mr_init_drv_cmd(&mrioc->dev_rmhs_cmds[i], > + MPI3MR_HOSTTAG_DEVRMCMD_MIN + i); > + > if (pdev->revision) > mrioc->enable_segqueue = true; > > @@ -877,6 +2291,17 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) > shost->max_channel = 1; > shost->max_id = 0xFFFFFFFF; > > + snprintf(mrioc->fwevt_worker_name, sizeof(mrioc->fwevt_worker_name), > + "%s%d_fwevt_wrkr", mrioc->driver_name, mrioc->id); > + mrioc->fwevt_worker_thread = alloc_ordered_workqueue( > + mrioc->fwevt_worker_name, WQ_MEM_RECLAIM); > + if (!mrioc->fwevt_worker_thread) { > + ioc_err(mrioc, "failure at %s:%d/%s()!\n", > + __FILE__, __LINE__, __func__); > + retval = -ENODEV; > + goto out_fwevtthread_failed; > + } > + > mrioc->is_driver_loading = 1; > if (mpi3mr_init_ioc(mrioc)) { > ioc_err(mrioc, "failure at %s:%d/%s()!\n", > @@ -903,6 +2328,8 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) > addhost_failed: > mpi3mr_cleanup_ioc(mrioc); > out_iocinit_failed: > + destroy_workqueue(mrioc->fwevt_worker_thread); > +out_fwevtthread_failed: > spin_lock(&mrioc_list_lock); > list_del(&mrioc->list); > spin_unlock(&mrioc_list_lock); > @@ -924,14 +2351,30 @@ static void mpi3mr_remove(struct pci_dev *pdev) > { > struct Scsi_Host *shost = pci_get_drvdata(pdev); > struct mpi3mr_ioc *mrioc; > + struct workqueue_struct *wq; > + unsigned long flags; > + struct mpi3mr_tgt_dev *tgtdev, *tgtdev_next; > > mrioc = shost_priv(shost); > while (mrioc->reset_in_progress || mrioc->is_driver_loading) > ssleep(1); > > mrioc->stop_drv_processing = 1; > + mpi3mr_cleanup_fwevt_list(mrioc); > + spin_lock_irqsave(&mrioc->fwevt_lock, flags); > + wq = mrioc->fwevt_worker_thread; > + mrioc->fwevt_worker_thread = NULL; > + spin_unlock_irqrestore(&mrioc->fwevt_lock, flags); > + if (wq) > + destroy_workqueue(wq); > > scsi_remove_host(shost); > + list_for_each_entry_safe(tgtdev, tgtdev_next, &mrioc->tgtdev_list, > + list) { > + mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); > + mpi3mr_tgtdev_del_from_list(mrioc, tgtdev); > + mpi3mr_tgtdev_put(tgtdev); > + } > > mpi3mr_cleanup_ioc(mrioc); > > @@ -955,6 +2398,8 @@ static void mpi3mr_shutdown(struct pci_dev *pdev) > { > struct Scsi_Host *shost = pci_get_drvdata(pdev); > struct mpi3mr_ioc *mrioc; > + struct workqueue_struct *wq; > + unsigned long flags; > > if (!shost) > return; > @@ -963,6 +2408,13 @@ static void mpi3mr_shutdown(struct pci_dev *pdev) > while (mrioc->reset_in_progress || mrioc->is_driver_loading) > ssleep(1); > mrioc->stop_drv_processing = 1; > + mpi3mr_cleanup_fwevt_list(mrioc); > + spin_lock_irqsave(&mrioc->fwevt_lock, flags); > + wq = mrioc->fwevt_worker_thread; > + mrioc->fwevt_worker_thread = NULL; > + spin_unlock_irqrestore(&mrioc->fwevt_lock, flags); > + if (wq) > + destroy_workqueue(wq); > > mpi3mr_cleanup_ioc(mrioc); > > > 2.18.1 > Patch itself looks good other than comment by Tom earlier for double allocation of mpi3mr_alloc_reply_sense_bufs. Once fixed please add my Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> -- Himanshu Madhani Oracle Linux Engineering
> On Apr 19, 2021, at 6:01 AM, Kashyap Desai <kashyap.desai@broadcom.com> wrote: > > Firmware can report various MPI Events. > Support for certain Events (as listed below) are enabled in the driver > and their processing in driver is covered in this patch. > > MPI3_EVENT_SAS_BROADCAST_PRIMITIVE > MPI3_EVENT_CABLE_MGMT > MPI3_EVENT_ENERGY_PACK_CHANGE > > Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> > Reviewed-by: Hannes Reinecke <hare@suse.de> > Reviewed-by: Tomas Henzl <thenzl@redhat.com> > > Cc: sathya.prakash@broadcom.com > --- > drivers/scsi/mpi3mr/mpi3mr_fw.c | 3 +++ > drivers/scsi/mpi3mr/mpi3mr_os.c | 37 +++++++++++++++++++++++++++++++++ > 2 files changed, 40 insertions(+) > > diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c > index 7f3b553e5b86..00c3996de032 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c > @@ -2745,8 +2745,11 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc) > mpi3mr_unmask_events(mrioc, MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST); > mpi3mr_unmask_events(mrioc, MPI3_EVENT_SAS_DISCOVERY); > mpi3mr_unmask_events(mrioc, MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR); > + mpi3mr_unmask_events(mrioc, MPI3_EVENT_SAS_BROADCAST_PRIMITIVE); > mpi3mr_unmask_events(mrioc, MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST); > mpi3mr_unmask_events(mrioc, MPI3_EVENT_PCIE_ENUMERATION); > + mpi3mr_unmask_events(mrioc, MPI3_EVENT_CABLE_MGMT); > + mpi3mr_unmask_events(mrioc, MPI3_EVENT_ENERGY_PACK_CHANGE); > > retval = mpi3mr_issue_event_notification(mrioc); > if (retval) { > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c > index 3d78c558fe2a..3629184f68f9 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > @@ -1496,6 +1496,36 @@ static void mpi3mr_devstatuschg_evt_th(struct mpi3mr_ioc *mrioc, > > } > > +/** > + * mpi3mr_energypackchg_evt_th - Energy pack change evt tophalf > + * @mrioc: Adapter instance reference > + * @event_reply: Event data > + * > + * Identifies the new shutdown timeout value and update. > + * > + * Return: Nothing > + */ > +static void mpi3mr_energypackchg_evt_th(struct mpi3mr_ioc *mrioc, > + Mpi3EventNotificationReply_t *event_reply) > +{ > + Mpi3EventDataEnergyPackChange_t *evtdata = > + (Mpi3EventDataEnergyPackChange_t *)event_reply->EventData; > + u16 shutdown_timeout = le16_to_cpu(evtdata->ShutdownTimeout); > + > + if (shutdown_timeout <= 0) { > + ioc_warn(mrioc, > + "%s :Invalid Shutdown Timeout received = %d\n", > + __func__, shutdown_timeout); > + return; > + } > + > + ioc_info(mrioc, > + "%s :Previous Shutdown Timeout Value = %d New Shutdown Timeout Value = %d\n", > + __func__, mrioc->facts.shutdown_timeout, shutdown_timeout); > + mrioc->facts.shutdown_timeout = shutdown_timeout; > +} > + > + > /** > * mpi3mr_os_handle_events - Firmware event handler > * @mrioc: Adapter instance reference > @@ -1559,9 +1589,16 @@ void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc, > process_evt_bh = 1; > break; > } > + case MPI3_EVENT_ENERGY_PACK_CHANGE: > + { > + mpi3mr_energypackchg_evt_th(mrioc, event_reply); > + break; > + } > case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE: > case MPI3_EVENT_SAS_DISCOVERY: > + case MPI3_EVENT_CABLE_MGMT: > case MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR: > + case MPI3_EVENT_SAS_BROADCAST_PRIMITIVE: > case MPI3_EVENT_PCIE_ENUMERATION: > break; > default: > -- > 2.18.1 > Looks Good. Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> -- Himanshu Madhani Oracle Linux Engineering
> On Apr 19, 2021, at 6:01 AM, Kashyap Desai <kashyap.desai@broadcom.com> wrote: > > Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> > Reviewed-by: Tomas Henzl <thenzl@redhat.com> > > Cc: sathya.prakash@broadcom.com > --- > drivers/scsi/mpi3mr/mpi3mr_fw.c | 80 +++++++++++++++++++++++++++++++++ > drivers/scsi/mpi3mr/mpi3mr_os.c | 1 + > 2 files changed, 81 insertions(+) > > diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c > index 4e28a0efb082..3df689410c8f 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c > @@ -2550,6 +2550,85 @@ int mpi3mr_issue_port_enable(struct mpi3mr_ioc *mrioc, u8 async) > return retval; > } > > +/* Protocol type to name mapper structure*/ > +static const struct { > + u8 protocol; > + char *name; > +} mpi3mr_protocols[] = { > + { MPI3_IOCFACTS_PROTOCOL_SCSI_INITIATOR, "Initiator" }, > + { MPI3_IOCFACTS_PROTOCOL_SCSI_TARGET, "Target" }, > + { MPI3_IOCFACTS_PROTOCOL_NVME, "NVMe attachment" }, > +}; > + > +/* Capability to name mapper structure*/ > +static const struct { > + u32 capability; > + char *name; > +} mpi3mr_capabilities[] = { > + { MPI3_IOCFACTS_CAPABILITY_RAID_CAPABLE, "RAID" }, > +}; > + > +/** > + * mpi3mr_print_ioc_info - Display controller information > + * @mrioc: Adapter instance reference > + * > + * Display controller personalit, capability, supported > + * protocols etc. > + * > + * Return: Nothing > + */ > +static void > +mpi3mr_print_ioc_info(struct mpi3mr_ioc *mrioc) > +{ > + int i = 0; > + char personality[16]; > + char protocol[50] = {0}; > + char capabilities[100] = {0}; > + bool is_string_nonempty = false; > + struct mpi3mr_compimg_ver *fwver = &mrioc->facts.fw_ver; > + > + switch (mrioc->facts.personality) { > + case MPI3_IOCFACTS_FLAGS_PERSONALITY_EHBA: > + strcpy(personality, "Enhanced HBA"); > + break; > + case MPI3_IOCFACTS_FLAGS_PERSONALITY_RAID_DDR: > + strcpy(personality, "RAID"); > + break; > + default: > + strcpy(personality, "Unknown"); > + break; > + } > + > + ioc_info(mrioc, "Running in %s Personality", personality); > + > + ioc_info(mrioc, "FW Version(%d.%d.%d.%d.%d.%d)\n", > + fwver->gen_major, fwver->gen_minor, fwver->ph_major, > + fwver->ph_minor, fwver->cust_id, fwver->build_num); > + > + for (i = 0; i < ARRAY_SIZE(mpi3mr_protocols); i++) { > + if (mrioc->facts.protocol_flags & > + mpi3mr_protocols[i].protocol) { > + if (is_string_nonempty) > + strcat(protocol, ","); > + strcat(protocol, mpi3mr_protocols[i].name); > + is_string_nonempty = true; > + } > + } > + > + is_string_nonempty = false; > + for (i = 0; i < ARRAY_SIZE(mpi3mr_capabilities); i++) { > + if (mrioc->facts.protocol_flags & > + mpi3mr_capabilities[i].capability) { > + if (is_string_nonempty) > + strcat(capabilities, ","); > + strcat(capabilities, mpi3mr_capabilities[i].name); > + is_string_nonempty = true; > + } > + } > + > + ioc_info(mrioc, "Protocol=(%s), Capabilities=(%s)\n", > + protocol, capabilities); > +} > > /** > * mpi3mr_cleanup_resources - Free PCI resources > @@ -2808,6 +2887,7 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 re_init) > } > > } > + mpi3mr_print_ioc_info(mrioc); > > retval = mpi3mr_alloc_reply_sense_bufs(mrioc); > if (retval) { > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c > index d82581ec73e1..39928e2997ba 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > @@ -339,6 +339,7 @@ void mpi3mr_invalidate_devhandles(struct mpi3mr_ioc *mrioc) > * mpi3mr_flush_scmd - Flush individual SCSI command > * @rq: Block request > * @data: Adapter instance reference > + * @reserved: N/A. Currently not used > * > * Return the SCSI command to the upper layers if it is in LLD > * scope. > -- > 2.18.1 > Looks Good. Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> -- Himanshu Madhani Oracle Linux Engineering
> On Apr 19, 2021, at 6:01 AM, Kashyap Desai <kashyap.desai@broadcom.com> wrote: > > SCSI EH hook is added. > Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> > > Cc: sathya.prakash@broadcom.com > Cc: hare@suse.de > Cc: thenzl@redhat.com > > --- > drivers/scsi/mpi3mr/mpi3mr.h | 3 + > drivers/scsi/mpi3mr/mpi3mr_fw.c | 45 ++++ > drivers/scsi/mpi3mr/mpi3mr_os.c | 349 ++++++++++++++++++++++++++++++++ > 3 files changed, 397 insertions(+) > > diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h > index 801612c9eb2a..fe6c815b918a 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr.h > +++ b/drivers/scsi/mpi3mr/mpi3mr.h > @@ -97,6 +97,7 @@ extern struct list_head mrioc_list; > /* command/controller interaction timeout definitions in seconds */ > #define MPI3MR_INTADMCMD_TIMEOUT 10 > #define MPI3MR_PORTENABLE_TIMEOUT 300 > +#define MPI3MR_ABORTTM_TIMEOUT 30 > #define MPI3MR_RESETTM_TIMEOUT 30 > #define MPI3MR_RESET_HOST_IOWAIT_TIMEOUT 5 > #define MPI3MR_TSUPDATE_INTERVAL 900 > @@ -626,6 +627,7 @@ struct scmd_priv { > * @chain_bitmap_sz: Chain buffer allocator bitmap size > * @chain_bitmap: Chain buffer allocator bitmap > * @chain_buf_lock: Chain buffer list lock > + * @host_tm_cmds: Command tracker for task management commands > * @dev_rmhs_cmds: Command tracker for device removal commands > * @devrem_bitmap_sz: Device removal bitmap size > * @devrem_bitmap: Device removal bitmap > @@ -748,6 +750,7 @@ struct mpi3mr_ioc { > void *chain_bitmap; > spinlock_t chain_buf_lock; > > + struct mpi3mr_drv_cmd host_tm_cmds; > struct mpi3mr_drv_cmd dev_rmhs_cmds[MPI3MR_NUM_DEVRMCMD]; > u16 devrem_bitmap_sz; > void *devrem_bitmap; > diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c > index 3df689410c8f..c25e96f008d7 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c > @@ -172,6 +172,8 @@ mpi3mr_get_drv_cmd(struct mpi3mr_ioc *mrioc, u16 host_tag, > switch (host_tag) { > case MPI3MR_HOSTTAG_INITCMDS: > return &mrioc->init_cmds; > + case MPI3MR_HOSTTAG_BLK_TMS: > + return &mrioc->host_tm_cmds; > case MPI3MR_HOSTTAG_INVALID: > if (def_reply && def_reply->Function == > MPI3_FUNCTION_EVENT_NOTIFICATION) > @@ -2045,6 +2047,32 @@ static int mpi3mr_alloc_reply_sense_bufs(struct mpi3mr_ioc *mrioc) > goto out_failed; > } > > + mrioc->host_tm_cmds.reply = kzalloc(mrioc->facts.reply_sz, GFP_KERNEL); > + if (!mrioc->host_tm_cmds.reply) > + goto out_failed; > + > + for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { > + mrioc->dev_rmhs_cmds[i].reply = kzalloc(mrioc->facts.reply_sz, > + GFP_KERNEL); > + if (!mrioc->dev_rmhs_cmds[i].reply) > + goto out_failed; > + } > + mrioc->dev_handle_bitmap_sz = mrioc->facts.max_devhandle / 8; > + if (mrioc->facts.max_devhandle % 8) > + mrioc->dev_handle_bitmap_sz++; > + mrioc->removepend_bitmap = kzalloc(mrioc->dev_handle_bitmap_sz, > + GFP_KERNEL); > + if (!mrioc->removepend_bitmap) > + goto out_failed; > + > + mrioc->devrem_bitmap_sz = MPI3MR_NUM_DEVRMCMD / 8; > + if (MPI3MR_NUM_DEVRMCMD % 8) > + mrioc->devrem_bitmap_sz++; > + mrioc->devrem_bitmap = kzalloc(mrioc->devrem_bitmap_sz, > + GFP_KERNEL); > + if (!mrioc->devrem_bitmap) > + goto out_failed; > + > mrioc->num_reply_bufs = mrioc->facts.max_reqs + MPI3MR_NUM_EVT_REPLIES; > mrioc->reply_free_qsz = mrioc->num_reply_bufs + 1; > mrioc->num_sense_bufs = mrioc->facts.max_reqs / MPI3MR_SENSEBUF_FACTOR; > @@ -3048,6 +3076,8 @@ static void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc) > memset(mrioc->admin_reply_base, 0, mrioc->admin_reply_q_sz); > > memset(mrioc->init_cmds.reply, 0, sizeof(*mrioc->init_cmds.reply)); > + memset(mrioc->host_tm_cmds.reply, 0, > + sizeof(*mrioc->host_tm_cmds.reply)); > for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) > memset(mrioc->dev_rmhs_cmds[i].reply, 0, > sizeof(*mrioc->dev_rmhs_cmds[i].reply)); > @@ -3141,6 +3171,19 @@ static void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc) > kfree(mrioc->init_cmds.reply); > mrioc->init_cmds.reply = NULL; > > + kfree(mrioc->host_tm_cmds.reply); > + mrioc->host_tm_cmds.reply = NULL; > + > + for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { > + kfree(mrioc->dev_rmhs_cmds[i].reply); > + mrioc->dev_rmhs_cmds[i].reply = NULL; > + } > + kfree(mrioc->removepend_bitmap); > + mrioc->removepend_bitmap = NULL; > + > + kfree(mrioc->devrem_bitmap); > + mrioc->devrem_bitmap = NULL; > + > kfree(mrioc->chain_bitmap); > mrioc->chain_bitmap = NULL; > > @@ -3321,6 +3364,8 @@ static void mpi3mr_flush_drv_cmds(struct mpi3mr_ioc *mrioc) > > cmdptr = &mrioc->init_cmds; > mpi3mr_drv_cmd_comp_reset(mrioc, cmdptr); > + cmdptr = &mrioc->host_tm_cmds; > + mpi3mr_drv_cmd_comp_reset(mrioc, cmdptr); > > for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { > cmdptr = &mrioc->dev_rmhs_cmds[i]; > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c > index 946a62610b55..fd5fdc61169e 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > @@ -2075,6 +2075,212 @@ static int mpi3mr_build_sg_scmd(struct mpi3mr_ioc *mrioc, > return ret; > } > > +/** > + * mpi3mr_print_response_code - print TM response as a string > + * @mrioc: Adapter instance reference > + * @resp_code: TM response code > + * > + * Print TM response code as a readable string. > + * > + * Return: Nothing. > + */ > +static void mpi3mr_print_response_code(struct mpi3mr_ioc *mrioc, u8 resp_code) > +{ > + char *desc; > + > + switch (resp_code) { > + case MPI3MR_RSP_TM_COMPLETE: > + desc = "task management request completed"; > + break; > + case MPI3MR_RSP_INVALID_FRAME: > + desc = "invalid frame"; > + break; > + case MPI3MR_RSP_TM_NOT_SUPPORTED: > + desc = "task management request not supported"; > + break; > + case MPI3MR_RSP_TM_FAILED: > + desc = "task management request failed"; > + break; > + case MPI3MR_RSP_TM_SUCCEEDED: > + desc = "task management request succeeded"; > + break; > + case MPI3MR_RSP_TM_INVALID_LUN: > + desc = "invalid lun"; > + break; > + case MPI3MR_RSP_TM_OVERLAPPED_TAG: > + desc = "overlapped tag attempted"; > + break; > + case MPI3MR_RSP_IO_QUEUED_ON_IOC: > + desc = "task queued, however not sent to target"; > + break; > + default: > + desc = "unknown"; > + break; > + } > + ioc_info(mrioc, "%s :response_code(0x%01x): %s\n", __func__, > + resp_code, desc); > +} > + > +/** > + * mpi3mr_issue_tm - Issue Task Management request > + * @mrioc: Adapter instance reference > + * @tm_type: Task Management type > + * @handle: Device handle > + * @lun: LUN ID > + * @htag: Host tag of the TM request > + * @drv_cmd: Internal command tracker > + * @resp_code: Response code place holder > + * @cmd_priv: SCSI command private data > + * > + * Issues a Task Management Request to the controller for a > + * specified target, LUN and command and wait for its completion > + * and check TM response. Recover the TM if it timed out by > + * issuing controller reset. > + * > + * Return: 0 on success, non-zero on errors > + */ > +static int mpi3mr_issue_tm(struct mpi3mr_ioc *mrioc, u8 tm_type, > + u16 handle, uint lun, u16 htag, ulong timeout, > + struct mpi3mr_drv_cmd *drv_cmd, > + u8 *resp_code, struct scmd_priv *cmd_priv) > +{ > + Mpi3SCSITaskMgmtRequest_t tm_req; > + Mpi3SCSITaskMgmtReply_t *tm_reply = NULL; > + int retval = 0; > + struct mpi3mr_tgt_dev *tgtdev = NULL; > + struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data = NULL; > + struct op_req_qinfo *op_req_q = NULL; > + > + ioc_info(mrioc, "%s :Issue TM: TM Type (0x%x) for devhandle 0x%04x\n", > + __func__, tm_type, handle); > + if (mrioc->unrecoverable) { > + retval = -1; > + ioc_err(mrioc, "%s :Issue TM: Unrecoverable controller\n", > + __func__); > + goto out; > + } > + > + memset(&tm_req, 0, sizeof(tm_req)); > + mutex_lock(&drv_cmd->mutex); > + if (drv_cmd->state & MPI3MR_CMD_PENDING) { > + retval = -1; > + ioc_err(mrioc, "%s :Issue TM: Command is in use\n", __func__); > + mutex_unlock(&drv_cmd->mutex); > + goto out; > + } > + if (mrioc->reset_in_progress) { > + retval = -1; > + ioc_err(mrioc, "%s :Issue TM: Reset in progress\n", __func__); > + mutex_unlock(&drv_cmd->mutex); > + goto out; > + } > + > + drv_cmd->state = MPI3MR_CMD_PENDING; > + drv_cmd->is_waiting = 1; > + drv_cmd->callback = NULL; > + tm_req.DevHandle = cpu_to_le16(handle); > + tm_req.TaskType = tm_type; > + tm_req.HostTag = cpu_to_le16(htag); > + > + int_to_scsilun(lun, (struct scsi_lun *)tm_req.LUN); > + tm_req.Function = MPI3_FUNCTION_SCSI_TASK_MGMT; > + > + tgtdev = mpi3mr_get_tgtdev_by_handle(mrioc, handle); > + if (tgtdev && tgtdev->starget && tgtdev->starget->hostdata) { > + scsi_tgt_priv_data = (struct mpi3mr_stgt_priv_data *) > + tgtdev->starget->hostdata; > + atomic_inc(&scsi_tgt_priv_data->block_io); > + } > + if (cmd_priv) { > + op_req_q = &mrioc->req_qinfo[cmd_priv->req_q_idx]; > + tm_req.TaskHostTag = cpu_to_le16(cmd_priv->host_tag); > + tm_req.TaskRequestQueueID = cpu_to_le16(op_req_q->qid); > + } > + if (tgtdev && (tgtdev->dev_type == MPI3_DEVICE_DEVFORM_PCIE)) { > + if (cmd_priv && tgtdev->dev_spec.pcie_inf.abort_to) > + timeout = tgtdev->dev_spec.pcie_inf.abort_to; > + else if (!cmd_priv && tgtdev->dev_spec.pcie_inf.reset_to) > + timeout = tgtdev->dev_spec.pcie_inf.reset_to; > + } > + > + init_completion(&drv_cmd->done); > + retval = mpi3mr_admin_request_post(mrioc, &tm_req, sizeof(tm_req), 1); > + if (retval) { > + ioc_err(mrioc, "%s :Issue TM: Admin Post failed\n", __func__); > + goto out_unlock; > + } > + wait_for_completion_timeout(&drv_cmd->done, (timeout * HZ)); > + > + if (!(drv_cmd->state & MPI3MR_CMD_COMPLETE)) { > + ioc_err(mrioc, "%s :Issue TM: command timed out\n", __func__); > + drv_cmd->is_waiting = 0; > + retval = -1; > + mpi3mr_soft_reset_handler(mrioc, > + MPI3MR_RESET_FROM_TM_TIMEOUT, 1); > + goto out_unlock; > + } > + > + if (drv_cmd->state & MPI3MR_CMD_REPLY_VALID) > + tm_reply = (Mpi3SCSITaskMgmtReply_t *)drv_cmd->reply; > + > + if (drv_cmd->ioc_status != MPI3_IOCSTATUS_SUCCESS) { > + ioc_err(mrioc, > + "%s :Issue TM: handle(0x%04x) Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n", > + __func__, handle, drv_cmd->ioc_status, > + drv_cmd->ioc_loginfo); > + retval = -1; > + goto out_unlock; > + } > + > + if (!tm_reply) { > + ioc_err(mrioc, "%s :Issue TM: No TM Reply message\n", __func__); > + retval = -1; > + goto out_unlock; > + } > + > + *resp_code = le32_to_cpu(tm_reply->ResponseData) & > + MPI3MR_RI_MASK_RESPCODE; > + switch (*resp_code) { > + case MPI3MR_RSP_TM_SUCCEEDED: > + case MPI3MR_RSP_TM_COMPLETE: > + break; > + case MPI3MR_RSP_IO_QUEUED_ON_IOC: > + if (tm_type != MPI3_SCSITASKMGMT_TASKTYPE_QUERY_TASK) > + retval = -1; > + break; > + default: > + retval = -1; > + break; > + } > + > + ioc_info(mrioc, > + "%s :Issue TM: Completed TM Type (0x%x) handle(0x%04x) ", > + __func__, tm_type, handle); > + ioc_info(mrioc, > + "with ioc_status(0x%04x), loginfo(0x%08x), term_count(0x%08x)\n", > + drv_cmd->ioc_status, drv_cmd->ioc_loginfo, > + le32_to_cpu(tm_reply->TerminationCount)); > + mpi3mr_print_response_code(mrioc, *resp_code); > + > +out_unlock: > + drv_cmd->state = MPI3MR_CMD_NOTUSED; > + mutex_unlock(&drv_cmd->mutex); > + if (scsi_tgt_priv_data) > + atomic_dec_if_positive(&scsi_tgt_priv_data->block_io); > + if (tgtdev) > + mpi3mr_tgtdev_put(tgtdev); > + if (!retval) { > + /* > + * Flush all IRQ handlers by calling synchronize_irq(). > + * mpi3mr_ioc_disable_intr() takes care of it. > + */ > + mpi3mr_ioc_disable_intr(mrioc); > + mpi3mr_ioc_enable_intr(mrioc); > + } > +out: > + return retval; > +} > + > /** > * mpi3mr_bios_param - BIOS param callback > * @sdev: SCSI device reference > @@ -2132,6 +2338,145 @@ static int mpi3mr_map_queues(struct Scsi_Host *shost) > mrioc->pdev, mrioc->op_reply_q_offset); > } > > +/** > + * mpi3mr_eh_host_reset - Host reset error handling callback > + * @scmd: SCSI command reference > + * > + * Issue controller reset if the scmd is for a Physical Device, > + * if the scmd is for RAID volume, then wait for > + * MPI3MR_RAID_ERRREC_RESET_TIMEOUT and checke whether any > + * pending I/Os prior to issuing reset to the controller. > + * > + * Return: SUCCESS of successful reset else FAILED > + */ > +static int mpi3mr_eh_host_reset(struct scsi_cmnd *scmd) > +{ > + struct mpi3mr_ioc *mrioc = shost_priv(scmd->device->host); > + int retval = FAILED, ret; > + > + > + ret = mpi3mr_soft_reset_handler(mrioc, > + MPI3MR_RESET_FROM_EH_HOS, 1); > + if (ret) > + goto out; > + > + retval = SUCCESS; > +out: > + sdev_printk(KERN_INFO, scmd->device, > + "Host reset is %s for scmd(%p)\n", > + ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); > + > + return retval; > +} > + > +/** > + * mpi3mr_eh_target_reset - Target reset error handling callback > + * @scmd: SCSI command reference > + * > + * Issue Target reset Task Management and verify the scmd is > + * terminated successfully and return status accordingly. > + * > + * Return: SUCCESS of successful termination of the scmd else > + * FAILED > + */ > +static int mpi3mr_eh_target_reset(struct scsi_cmnd *scmd) > +{ > + struct mpi3mr_ioc *mrioc = shost_priv(scmd->device->host); > + struct mpi3mr_stgt_priv_data *stgt_priv_data; > + struct mpi3mr_sdev_priv_data *sdev_priv_data; > + u16 dev_handle; > + u8 resp_code = 0; > + int retval = FAILED, ret = 0; > + > + > + sdev_printk(KERN_INFO, scmd->device, > + "Attempting Target Reset! scmd(%p)\n", scmd); > + scsi_print_command(scmd); > + > + sdev_priv_data = scmd->device->hostdata; > + if (!sdev_priv_data || !sdev_priv_data->tgt_priv_data) { > + sdev_printk(KERN_INFO, scmd->device, > + "SCSI device is not available\n"); > + retval = SUCCESS; > + goto out; > + } > + > + stgt_priv_data = sdev_priv_data->tgt_priv_data; > + dev_handle = stgt_priv_data->dev_handle; > + sdev_printk(KERN_INFO, scmd->device, > + "Target Reset is issued to handle(0x%04x)\n", > + dev_handle); > + > + ret = mpi3mr_issue_tm(mrioc, > + MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET, dev_handle, > + sdev_priv_data->lun_id, MPI3MR_HOSTTAG_BLK_TMS, > + MPI3MR_RESETTM_TIMEOUT, &mrioc->host_tm_cmds, &resp_code, NULL); > + > + if (ret) > + goto out; > + > + retval = SUCCESS; > +out: > + sdev_printk(KERN_INFO, scmd->device, > + "Target reset is %s for scmd(%p)\n", > + ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); > + > + return retval; > +} > + > +/** > + * mpi3mr_eh_dev_reset- Device reset error handling callback > + * @scmd: SCSI command reference > + * > + * Issue LUN reset Task Management and verify the scmd is > + * terminated successfully and return status accordingly. > + * > + * Return: SUCCESS of successful termination of the scmd else > + * FAILED > + */ > +static int mpi3mr_eh_dev_reset(struct scsi_cmnd *scmd) > +{ > + struct mpi3mr_ioc *mrioc = shost_priv(scmd->device->host); > + struct mpi3mr_stgt_priv_data *stgt_priv_data; > + struct mpi3mr_sdev_priv_data *sdev_priv_data; > + u16 dev_handle; > + u8 resp_code = 0; > + int retval = FAILED, ret = 0; > + > + sdev_printk(KERN_INFO, scmd->device, > + "Attempting Device(LUN) Reset! scmd(%p)\n", scmd); > + scsi_print_command(scmd); > + > + sdev_priv_data = scmd->device->hostdata; > + if (!sdev_priv_data || !sdev_priv_data->tgt_priv_data) { > + sdev_printk(KERN_INFO, scmd->device, > + "SCSI device is not available\n"); > + retval = SUCCESS; > + goto out; > + } > + > + stgt_priv_data = sdev_priv_data->tgt_priv_data; > + dev_handle = stgt_priv_data->dev_handle; > + sdev_printk(KERN_INFO, scmd->device, > + "Device(LUN) Reset is issued to handle(0x%04x)\n", dev_handle); > + > + ret = mpi3mr_issue_tm(mrioc, > + MPI3_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, dev_handle, > + sdev_priv_data->lun_id, MPI3MR_HOSTTAG_BLK_TMS, > + MPI3MR_RESETTM_TIMEOUT, &mrioc->host_tm_cmds, &resp_code, NULL); > + > + if (ret) > + goto out; > + > + retval = SUCCESS; > +out: > + sdev_printk(KERN_INFO, scmd->device, > + "Device(LUN) reset is %s for scmd(%p)\n", > + ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); > + > + return retval; > +} > + > /** > * mpi3mr_scan_start - Scan start callback handler > * @shost: SCSI host reference > @@ -2547,6 +2892,9 @@ static struct scsi_host_template mpi3mr_driver_template = { > .slave_destroy = mpi3mr_slave_destroy, > .scan_finished = mpi3mr_scan_finished, > .scan_start = mpi3mr_scan_start, > + .eh_device_reset_handler = mpi3mr_eh_dev_reset, > + .eh_target_reset_handler = mpi3mr_eh_target_reset, > + .eh_host_reset_handler = mpi3mr_eh_host_reset, > .bios_param = mpi3mr_bios_param, > .map_queues = mpi3mr_map_queues, > .no_write_same = 1, > @@ -2634,6 +2982,7 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) > > mutex_init(&mrioc->reset_mutex); > mpi3mr_init_drv_cmd(&mrioc->init_cmds, MPI3MR_HOSTTAG_INITCMDS); > + mpi3mr_init_drv_cmd(&mrioc->host_tm_cmds, MPI3MR_HOSTTAG_BLK_TMS); > > for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) > mpi3mr_init_drv_cmd(&mrioc->dev_rmhs_cmds[i], > -- > 2.18.1 > Looks Good. Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> -- Himanshu Madhani Oracle Linux Engineering
> On Apr 19, 2021, at 6:01 AM, Kashyap Desai <kashyap.desai@broadcom.com> wrote: > > Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> > Reviewed-by: Hannes Reinecke <hare@suse.de> > Reviewed-by: Tomas Henzl <thenzl@redhat.com> > > Cc: sathya.prakash@broadcom.com > --- > drivers/scsi/mpi3mr/mpi3mr.h | 3 +++ > drivers/scsi/mpi3mr/mpi3mr_os.c | 35 ++++++++++++++++++++++++++++++++- > 2 files changed, 37 insertions(+), 1 deletion(-) > > diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h > index fe6c815b918a..e3ce54f877fa 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr.h > +++ b/drivers/scsi/mpi3mr/mpi3mr.h > @@ -141,6 +141,9 @@ extern struct list_head mrioc_list; > /* Command retry count definitions */ > #define MPI3MR_DEV_RMHS_RETRY_COUNT 3 > > +/* Default target device queue depth */ > +#define MPI3MR_DEFAULT_SDEV_QD 32 > + > /* SGE Flag definition */ > #define MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST \ > (MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM | \ > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c > index fd5fdc61169e..99a60e6777d5 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > @@ -649,6 +649,34 @@ static int mpi3mr_report_tgtdev_to_host(struct mpi3mr_ioc *mrioc, > return retval; > } > > +/** > + * mpi3mr_change_queue_depth- Change QD callback handler > + * @sdev: SCSI device reference > + * @q_depth: Queue depth > + * > + * Validate and limit QD and call scsi_change_queue_depth. > + * > + * Return: return value of scsi_change_queue_depth > + */ > +static int mpi3mr_change_queue_depth(struct scsi_device *sdev, > + int q_depth) > +{ > + struct scsi_target *starget = scsi_target(sdev); > + struct Scsi_Host *shost = dev_to_shost(&starget->dev); > + int retval = 0; > + > + if (!sdev->tagged_supported) > + q_depth = 1; > + if (q_depth > shost->can_queue) > + q_depth = shost->can_queue; > + else if (!q_depth) > + q_depth = MPI3MR_DEFAULT_SDEV_QD; > + retval = scsi_change_queue_depth(sdev, q_depth); > + > + return retval; > +} > + > + > /** > * mpi3mr_update_sdev - Update SCSI device information > * @sdev: SCSI device reference > @@ -669,6 +697,7 @@ mpi3mr_update_sdev(struct scsi_device *sdev, void *data) > if (!tgtdev) > return; > > + mpi3mr_change_queue_depth(sdev, tgtdev->q_depth); > switch (tgtdev->dev_type) { > case MPI3_DEVICE_DEVFORM_PCIE: > /*The block layer hw sector size = 512*/ > @@ -2650,9 +2679,12 @@ static int mpi3mr_slave_configure(struct scsi_device *sdev) > spin_lock_irqsave(&mrioc->tgtdev_lock, flags); > tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id); > spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); > - if (!tgt_dev) > + if (!tgt_dev) { > + mpi3mr_change_queue_depth(sdev, MPI3MR_DEFAULT_SDEV_QD); > return retval; > + } > > + mpi3mr_change_queue_depth(sdev, tgt_dev->q_depth); > switch (tgt_dev->dev_type) { > case MPI3_DEVICE_DEVFORM_PCIE: > /*The block layer hw sector size = 512*/ > @@ -2892,6 +2924,7 @@ static struct scsi_host_template mpi3mr_driver_template = { > .slave_destroy = mpi3mr_slave_destroy, > .scan_finished = mpi3mr_scan_finished, > .scan_start = mpi3mr_scan_start, > + .change_queue_depth = mpi3mr_change_queue_depth, > .eh_device_reset_handler = mpi3mr_eh_dev_reset, > .eh_target_reset_handler = mpi3mr_eh_target_reset, > .eh_host_reset_handler = mpi3mr_eh_host_reset, > -- > 2.18.1 > Looks Good. Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> -- Himanshu Madhani Oracle Linux Engineering
> On Apr 19, 2021, at 6:01 AM, Kashyap Desai <kashyap.desai@broadcom.com> wrote: > > Register driver for threaded interrupt. > > By default, driver will attempt io completion from interrupt context > (primary handler). Since driver tracks per reply queue outstanding ios, > it will schedule threaded ISR if there are any outstanding IOs expected > on that particular reply queue. Threaded ISR (secondary handler) will loop > for IO completion as long as there are outstanding IOs > (speculative method using same per reply queue outstanding counter) > or it has completed some X amount of commands (something like budget). > > Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> > Reviewed-by: Hannes Reinecke <hare@suse.de> > Reviewed-by: Tomas Henzl <thenzl@redhat.com> > > Cc: sathya.prakash@broadcom.com > --- > drivers/scsi/mpi3mr/mpi3mr.h | 12 +++++ > drivers/scsi/mpi3mr/mpi3mr_fw.c | 79 +++++++++++++++++++++++++++++++-- > 2 files changed, 88 insertions(+), 3 deletions(-) > > diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h > index e3ce54f877fa..3ac7b0f119bb 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr.h > +++ b/drivers/scsi/mpi3mr/mpi3mr.h > @@ -144,6 +144,10 @@ extern struct list_head mrioc_list; > /* Default target device queue depth */ > #define MPI3MR_DEFAULT_SDEV_QD 32 > > +/* Definitions for Threaded IRQ poll*/ > +#define MPI3MR_IRQ_POLL_SLEEP 2 > +#define MPI3MR_IRQ_POLL_TRIGGER_IOCOUNT 8 > + > /* SGE Flag definition */ > #define MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST \ > (MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM | \ > @@ -295,6 +299,9 @@ struct op_req_qinfo { > * @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 > + * @pend_ios: Number of IOs pending in HW for this queue > + * @enable_irq_poll: Flag to indicate polling is enabled > + * @in_use: Queue is handled by poll/ISR > */ > struct op_reply_qinfo { > u16 ci; > @@ -306,6 +313,9 @@ struct op_reply_qinfo { > void *q_segment_list; > dma_addr_t q_segment_list_dma; > u8 ephase; > + atomic_t pend_ios; > + bool enable_irq_poll; > + atomic_t in_use; > }; > > /** > @@ -557,6 +567,7 @@ struct scmd_priv { > * @shost: Scsi_Host pointer > * @id: Controller ID > * @cpu_count: Number of online CPUs > + * @irqpoll_sleep: usleep unit used in threaded isr irqpoll > * @name: Controller ASCII name > * @driver_name: Driver ASCII name > * @sysif_regs: System interface registers virtual address > @@ -658,6 +669,7 @@ struct mpi3mr_ioc { > u8 id; > int cpu_count; > bool enable_segqueue; > + u32 irqpoll_sleep; > > char name[MPI3MR_NAME_LENGTH]; > char driver_name[MPI3MR_NAME_LENGTH]; > diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c > index c25e96f008d7..76e4c87c0426 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c > @@ -346,12 +346,16 @@ static int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc, > > reply_qidx = op_reply_q->qid - 1; > > + if (!atomic_add_unless(&op_reply_q->in_use, 1, 1)) > + return 0; > + > exp_phase = op_reply_q->ephase; > reply_ci = op_reply_q->ci; > > reply_desc = mpi3mr_get_reply_desc(op_reply_q, reply_ci); > if ((le16_to_cpu(reply_desc->ReplyFlags) & > MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) { > + atomic_dec(&op_reply_q->in_use); > return 0; > } > > @@ -362,6 +366,7 @@ static int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc, > WRITE_ONCE(op_req_q->ci, le16_to_cpu(reply_desc->RequestQueueCI)); > mpi3mr_process_op_reply_desc(mrioc, reply_desc, &reply_dma, > reply_qidx); > + atomic_dec(&op_reply_q->pend_ios); > if (reply_dma) > mpi3mr_repost_reply_buf(mrioc, reply_dma); > num_op_reply++; > @@ -376,6 +381,14 @@ static int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc, > if ((le16_to_cpu(reply_desc->ReplyFlags) & > MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) > break; > + /* > + * Exit completion loop to avoid CPU lockup > + * Ensure remaining completion happens from threaded ISR. > + */ > + if (num_op_reply > mrioc->max_host_ios) { > + intr_info->op_reply_q->enable_irq_poll = true; > + break; > + } > > } while (1); > > @@ -384,6 +397,7 @@ static int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc, > &mrioc->sysif_regs->OperQueueIndexes[reply_qidx].ConsumerIndex); > op_reply_q->ci = reply_ci; > op_reply_q->ephase = exp_phase; > + atomic_dec(&op_reply_q->in_use); > > return num_op_reply; > } > @@ -393,7 +407,7 @@ static irqreturn_t mpi3mr_isr_primary(int irq, void *privdata) > struct mpi3mr_intr_info *intr_info = privdata; > struct mpi3mr_ioc *mrioc; > u16 midx; > - u32 num_admin_replies = 0; > + u32 num_admin_replies = 0, num_op_reply = 0; > > if (!intr_info) > return IRQ_NONE; > @@ -407,8 +421,10 @@ static irqreturn_t mpi3mr_isr_primary(int irq, void *privdata) > > if (!midx) > num_admin_replies = mpi3mr_process_admin_reply_q(mrioc); > + if (intr_info->op_reply_q) > + num_op_reply = mpi3mr_process_op_reply_q(mrioc, intr_info); > > - if (num_admin_replies) > + if (num_admin_replies || num_op_reply) > return IRQ_HANDLED; > else > return IRQ_NONE; > @@ -417,15 +433,32 @@ static irqreturn_t mpi3mr_isr_primary(int irq, void *privdata) > static irqreturn_t mpi3mr_isr(int irq, void *privdata) > { > struct mpi3mr_intr_info *intr_info = privdata; > + struct mpi3mr_ioc *mrioc; > + u16 midx; > int ret; > > if (!intr_info) > return IRQ_NONE; > > + mrioc = intr_info->mrioc; > + midx = intr_info->msix_index; > /* Call primary ISR routine */ > ret = mpi3mr_isr_primary(irq, privdata); > > - return ret; > + /* > + * If more IOs are expected, schedule IRQ polling thread. > + * Otherwise exit from ISR. > + */ > + if (!intr_info->op_reply_q) > + return ret; > + > + if (!intr_info->op_reply_q->enable_irq_poll || > + !atomic_read(&intr_info->op_reply_q->pend_ios)) > + return ret; > + > + disable_irq_nosync(pci_irq_vector(mrioc->pdev, midx)); > + > + return IRQ_WAKE_THREAD; > } > > /** > @@ -440,6 +473,36 @@ static irqreturn_t mpi3mr_isr(int irq, void *privdata) > */ > static irqreturn_t mpi3mr_isr_poll(int irq, void *privdata) > { > + struct mpi3mr_intr_info *intr_info = privdata; > + struct mpi3mr_ioc *mrioc; > + u16 midx; > + u32 num_op_reply = 0; > + > + if (!intr_info || !intr_info->op_reply_q) > + return IRQ_NONE; > + > + mrioc = intr_info->mrioc; > + midx = intr_info->msix_index; > + > + /* Poll for pending IOs completions */ > + do { > + if (!mrioc->intr_enabled) > + break; > + > + if (!midx) > + mpi3mr_process_admin_reply_q(mrioc); > + if (intr_info->op_reply_q) > + num_op_reply += > + mpi3mr_process_op_reply_q(mrioc, intr_info); > + > + usleep_range(mrioc->irqpoll_sleep, 10 * mrioc->irqpoll_sleep); > + > + } while (atomic_read(&intr_info->op_reply_q->pend_ios) && > + (num_op_reply < mrioc->max_host_ios)); > + > + intr_info->op_reply_q->enable_irq_poll = false; > + enable_irq(pci_irq_vector(mrioc->pdev, midx)); > + > return IRQ_HANDLED; > } > > @@ -1155,6 +1218,9 @@ static int mpi3mr_create_op_reply_q(struct mpi3mr_ioc *mrioc, u16 qidx) > op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD; > op_reply_q->ci = 0; > op_reply_q->ephase = 1; > + atomic_set(&op_reply_q->pend_ios, 0); > + atomic_set(&op_reply_q->in_use, 0); > + op_reply_q->enable_irq_poll = false; > > if (!op_reply_q->q_segments) { > retval = mpi3mr_alloc_op_reply_q_segments(mrioc, qidx); > @@ -1476,6 +1542,10 @@ int mpi3mr_op_request_post(struct mpi3mr_ioc *mrioc, > pi = 0; > op_req_q->pi = pi; > > + if (atomic_inc_return(&mrioc->op_reply_qinfo[reply_qidx].pend_ios) > + > MPI3MR_IRQ_POLL_TRIGGER_IOCOUNT) > + mrioc->op_reply_qinfo[reply_qidx].enable_irq_poll = true; > + > writel(op_req_q->pi, > &mrioc->sysif_regs->OperQueueIndexes[reply_qidx].ProducerIndex); > > @@ -2804,6 +2874,7 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 re_init) > u32 ioc_status, ioc_config, i; > Mpi3IOCFactsData_t facts_data; > > + mrioc->irqpoll_sleep = MPI3MR_IRQ_POLL_SLEEP; > mrioc->change_count = 0; > if (!re_init) { > mrioc->cpu_count = num_online_cpus(); > @@ -3089,6 +3160,8 @@ static void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc) > mrioc->op_reply_qinfo[i].ci = 0; > mrioc->op_reply_qinfo[i].num_replies = 0; > mrioc->op_reply_qinfo[i].ephase = 0; > + atomic_set(&mrioc->op_reply_qinfo[i].pend_ios, 0); > + atomic_set(&mrioc->op_reply_qinfo[i].in_use, 0); > mpi3mr_memset_op_reply_q_buffers(mrioc, i); > > mrioc->req_qinfo[i].ci = 0; > -- > 2.18.1 > Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> -- Himanshu Madhani Oracle Linux Engineering
> On Apr 19, 2021, at 6:01 AM, Kashyap Desai <kashyap.desai@broadcom.com> wrote: > > Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> > Reviewed-by: Tomas Henzl <thenzl@redhat.com> > Reviewed-by: Hannes Reinecke <hare@suse.de> > Cc: sathya.prakash@broadcom.com > --- > drivers/scsi/mpi3mr/mpi3mr_os.c | 69 +++++++++++++++++++++++++++++++++ > 1 file changed, 69 insertions(+) > > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c > index 01b82bd2e8df..56f1e59e86cc 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > @@ -334,6 +334,37 @@ void mpi3mr_invalidate_devhandles(struct mpi3mr_ioc *mrioc) > } > } > > +/** > + * mpi3mr_print_scmd - print individual SCSI command > + * @rq: Block request > + * @data: Adapter instance reference > + * @reserved: N/A. Currently not used > + * > + * Print the SCSI command details if it is in LLD scope. > + * > + * Return: true always. > + */ > +static bool mpi3mr_print_scmd(struct request *rq, > + void *data, bool reserved) > +{ > + struct mpi3mr_ioc *mrioc = (struct mpi3mr_ioc *)data; > + struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq); > + struct scmd_priv *priv = NULL; > + > + if (scmd) { > + priv = scsi_cmd_priv(scmd); > + if (!priv->in_lld_scope) > + goto out; > + > + ioc_info(mrioc, "%s :Host Tag = %d, qid = %d\n", > + __func__, priv->host_tag, priv->req_q_idx + 1); > + scsi_print_command(scmd); > + } > + > +out: > + return(true); > +} > + > > /** > * mpi3mr_flush_scmd - Flush individual SCSI command > @@ -2367,6 +2398,43 @@ static int mpi3mr_map_queues(struct Scsi_Host *shost) > mrioc->pdev, mrioc->op_reply_q_offset); > } > > +/** > + * mpi3mr_get_fw_pending_ios - Calculate pending I/O count > + * @mrioc: Adapter instance reference > + * > + * Calculate the pending I/Os for the controller and return. > + * > + * Return: Number of pending I/Os > + */ > +static inline int mpi3mr_get_fw_pending_ios(struct mpi3mr_ioc *mrioc) > +{ > + u16 i; > + uint pend_ios = 0; > + > + for (i = 0; i < mrioc->num_op_reply_q; i++) > + pend_ios += atomic_read(&mrioc->op_reply_qinfo[i].pend_ios); > + return pend_ios; > +} > + > +/** > + * mpi3mr_print_pending_host_io - print pending I/Os > + * @mrioc: Adapter instance reference > + * > + * Print number of pending I/Os and each I/O details prior to > + * reset for debug purpose. > + * > + * Return: Nothing > + */ > +static void mpi3mr_print_pending_host_io(struct mpi3mr_ioc *mrioc) > +{ > + struct Scsi_Host *shost = mrioc->shost; > + > + ioc_info(mrioc, "%s :Pending commands prior to reset: %d\n", > + __func__, mpi3mr_get_fw_pending_ios(mrioc)); > + blk_mq_tagset_busy_iter(&shost->tag_set, > + mpi3mr_print_scmd, (void *)mrioc); > +} > + > /** > * mpi3mr_eh_host_reset - Host reset error handling callback > * @scmd: SCSI command reference > @@ -2384,6 +2452,7 @@ static int mpi3mr_eh_host_reset(struct scsi_cmnd *scmd) > int retval = FAILED, ret; > > > + mpi3mr_print_pending_host_io(mrioc); > ret = mpi3mr_soft_reset_handler(mrioc, > MPI3MR_RESET_FROM_EH_HOS, 1); > if (ret) > -- > 2.18.1 > Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> -- Himanshu Madhani Oracle Linux Engineering
> On Apr 19, 2021, at 6:01 AM, Kashyap Desai <kashyap.desai@broadcom.com> wrote: > > Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> > Reviewed-by: Hannes Reinecke <hare@suse.de> > Reviewed-by: Tomas Henzl <thenzl@redhat.com> > > Cc: sathya.prakash@broadcom.com > --- > drivers/scsi/mpi3mr/mpi3mr_os.c | 85 +++++++++++++++++++++++++++++++++ > 1 file changed, 85 insertions(+) > > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c > index ccee3e7359ec..05473b0f3c9e 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > @@ -3409,6 +3409,87 @@ static void mpi3mr_shutdown(struct pci_dev *pdev) > > } > > +#ifdef CONFIG_PM > +/** > + * mpi3mr_suspend - PCI power management suspend callback > + * @pdev: PCI device instance > + * @state: New power state > + * > + * Change the power state to the given value and cleanup the IOC > + * by issuing MUR and shutdown notification > + * > + * Return: 0 always. > + */ > +static int mpi3mr_suspend(struct pci_dev *pdev, pm_message_t state) > +{ > + struct Scsi_Host *shost = pci_get_drvdata(pdev); > + struct mpi3mr_ioc *mrioc; > + pci_power_t device_state; > + > + if (!shost) > + return 0; > + > + mrioc = shost_priv(shost); > + while (mrioc->reset_in_progress || mrioc->is_driver_loading) > + ssleep(1); > + mrioc->stop_drv_processing = 1; > + mpi3mr_cleanup_fwevt_list(mrioc); > + scsi_block_requests(shost); > + mpi3mr_stop_watchdog(mrioc); > + mpi3mr_cleanup_ioc(mrioc, 1); > + > + device_state = pci_choose_state(pdev, state); > + ioc_info(mrioc, "pdev=0x%p, slot=%s, entering operating state [D%d]\n", > + pdev, pci_name(pdev), device_state); > + pci_save_state(pdev); > + pci_set_power_state(pdev, device_state); > + mpi3mr_cleanup_resources(mrioc); > + > + return 0; > +} > + > +/** > + * mpi3mr_resume - PCI power management resume callback > + * @pdev: PCI device instance > + * > + * Restore the power state to D0 and reinitialize the controller > + * and resume I/O operations to the target devices > + * > + * Return: 0 on success, non-zero on failure > + */ > +static int mpi3mr_resume(struct pci_dev *pdev) > +{ > + struct Scsi_Host *shost = pci_get_drvdata(pdev); > + struct mpi3mr_ioc *mrioc; > + pci_power_t device_state = pdev->current_state; > + int r; > + > + mrioc = shost_priv(shost); > + > + ioc_info(mrioc, "pdev=0x%p, slot=%s, previous operating state [D%d]\n", > + pdev, pci_name(pdev), device_state); > + pci_set_power_state(pdev, PCI_D0); > + pci_enable_wake(pdev, PCI_D0, 0); > + pci_restore_state(pdev); > + mrioc->pdev = pdev; > + mrioc->cpu_count = num_online_cpus(); > + r = mpi3mr_setup_resources(mrioc); > + if (r) { > + ioc_info(mrioc, "%s: Setup resources failed[%d]\n", > + __func__, r); > + return r; > + } > + > + mrioc->stop_drv_processing = 0; > + mpi3mr_init_ioc(mrioc, 1); > + scsi_unblock_requests(shost); > + mpi3mr_start_watchdog(mrioc); > + > + return 0; > +} > +#endif > + > + > static const struct pci_device_id mpi3mr_pci_id_table[] = { > { > PCI_DEVICE_SUB(PCI_VENDOR_ID_LSI_LOGIC, 0x00A5, > @@ -3424,6 +3505,10 @@ static struct pci_driver mpi3mr_pci_driver = { > .probe = mpi3mr_probe, > .remove = mpi3mr_remove, > .shutdown = mpi3mr_shutdown, > +#ifdef CONFIG_PM > + .suspend = mpi3mr_suspend, > + .resume = mpi3mr_resume, > +#endif > }; > > static int __init mpi3mr_init(void) > -- > 2.18.1 > Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> -- Himanshu Madhani Oracle Linux Engineering
> On Apr 19, 2021, at 6:01 AM, Kashyap Desai <kashyap.desai@broadcom.com> wrote: > > Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> > Reviewed-by: Hannes Reinecke <hare@suse.de> > Reviewed-by: Tomas Henzl <thenzl@redhat.com> > > Cc: sathya.prakash@broadcom.com > --- > drivers/scsi/mpi3mr/mpi3mr.h | 7 +- > drivers/scsi/mpi3mr/mpi3mr_fw.c | 7 + > drivers/scsi/mpi3mr/mpi3mr_os.c | 303 +++++++++++++++++++++++++++++++- > 3 files changed, 311 insertions(+), 6 deletions(-) > > diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h > index db9cb11db3bf..6e5d83f8685a 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr.h > +++ b/drivers/scsi/mpi3mr/mpi3mr.h > @@ -118,6 +118,7 @@ extern struct list_head mrioc_list; > #define MPI3MR_SENSEBUF_SZ 256 > #define MPI3MR_SENSEBUF_FACTOR 3 > #define MPI3MR_CHAINBUF_FACTOR 3 > +#define MPI3MR_CHAINBUFDIX_FACTOR 2 > > /* Invalid target device handle */ > #define MPI3MR_INVALID_DEV_HANDLE 0xFFFF > @@ -557,17 +558,21 @@ struct chain_element { > * > * @host_tag: Host tag specific to operational queue > * @in_lld_scope: Command in LLD scope or not > + * @meta_sg_valid: DIX command with meta data SGL or not > * @scmd: SCSI Command pointer > - * @req_q_idx: Operational request queue index > + * @req_q_idx: Operational request queue undex > * @chain_idx: Chain frame index > + * @meta_chain_idx: Chain frame index of meta data SGL > * @mpi3mr_scsiio_req: MPI SCSI IO request > */ > struct scmd_priv { > u16 host_tag; > u8 in_lld_scope; > + u8 meta_sg_valid; > struct scsi_cmnd *scmd; > u16 req_q_idx; > int chain_idx; > + int meta_chain_idx; > u8 mpi3mr_scsiio_req[MPI3MR_ADMIN_REQ_FRAME_SZ]; > }; > > diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c > index 488fc3eac9dc..ee20d63f6061 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c > @@ -9,6 +9,7 @@ > > #include "mpi3mr.h" > #include <linux/io-64-nonatomic-lo-hi.h> > +extern int prot_mask; > > #if defined(writeq) && defined(CONFIG_64BIT) > static inline void mpi3mr_writeq(__u64 b, volatile void __iomem *addr) > @@ -2767,6 +2768,12 @@ static int mpi3mr_alloc_chain_bufs(struct mpi3mr_ioc *mrioc) > > num_chains = mrioc->max_host_ios/MPI3MR_CHAINBUF_FACTOR; > > + if (prot_mask & (SHOST_DIX_TYPE0_PROTECTION > + | SHOST_DIX_TYPE1_PROTECTION > + | SHOST_DIX_TYPE2_PROTECTION > + | SHOST_DIX_TYPE3_PROTECTION)) > + num_chains += (num_chains / MPI3MR_CHAINBUFDIX_FACTOR); > + > mrioc->chain_buf_count = num_chains; > sz = sizeof(struct chain_element) * num_chains; > mrioc->chain_sgl_list = kzalloc(sz, GFP_KERNEL); > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c > index 836005ce6999..9a189fb32ab0 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > @@ -21,6 +21,13 @@ MODULE_LICENSE(MPI3MR_DRIVER_LICENSE); > MODULE_VERSION(MPI3MR_DRIVER_VERSION); > > /* Module parameters*/ > +int prot_mask = -1; > +module_param(prot_mask, int, 0); > +MODULE_PARM_DESC(prot_mask, "Host protection capabilities mask, def=0x07"); > + I don’t really get this. Parameter description says "def=0x7" but you are initializing it to -1? > +int prot_guard_mask = 3; > +module_param(prot_guard_mask, int, 0); > +MODULE_PARM_DESC(prot_guard_mask, " Host protection guard mask, def=3"); > int logging_level; > module_param(logging_level, int, 0); > MODULE_PARM_DESC(logging_level, > @@ -59,7 +66,9 @@ static u16 mpi3mr_host_tag_for_scmd(struct mpi3mr_ioc *mrioc, > priv->scmd = scmd; > priv->in_lld_scope = 1; > priv->req_q_idx = hw_queue; > + priv->meta_chain_idx = -1; > priv->chain_idx = -1; > + priv->meta_sg_valid = 0; > return priv->host_tag; > } > > @@ -119,10 +128,15 @@ static void mpi3mr_clear_scmd_priv(struct mpi3mr_ioc *mrioc, > priv->req_q_idx = 0xFFFF; > priv->scmd = NULL; > priv->in_lld_scope = 0; > + priv->meta_sg_valid = 0; > if (priv->chain_idx >= 0) { > clear_bit(priv->chain_idx, mrioc->chain_bitmap); > priv->chain_idx = -1; > } > + if (priv->meta_chain_idx >= 0) { > + clear_bit(priv->meta_chain_idx, mrioc->chain_bitmap); > + priv->meta_chain_idx = -1; > + } > } > > static void mpi3mr_dev_rmhs_send_tm(struct mpi3mr_ioc *mrioc, u16 handle, > @@ -390,6 +404,9 @@ static bool mpi3mr_flush_scmd(struct request *rq, > if (!priv->in_lld_scope) > goto out; > > + if (priv->meta_sg_valid) > + dma_unmap_sg(&mrioc->pdev->dev, scsi_prot_sglist(scmd), > + scsi_prot_sg_count(scmd), scmd->sc_data_direction); > mpi3mr_clear_scmd_priv(mrioc, scmd); > scsi_dma_unmap(scmd); > scmd->result = DID_RESET << 16; > @@ -792,6 +809,7 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc, > { > u16 flags = 0; > struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data; > + u8 prot_mask = 0; > > tgtdev->perst_id = le16_to_cpu(dev_pg0->PersistentID); > tgtdev->dev_handle = le16_to_cpu(dev_pg0->DevHandle); > @@ -856,6 +874,15 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc, > if ((dev_info & MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK) != > MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_NVME_DEVICE) > tgtdev->is_hidden = 1; > + if (mrioc->shost) > + prot_mask = scsi_host_get_prot(mrioc->shost); > + if (prot_mask & SHOST_DIX_TYPE0_PROTECTION) { > + scsi_host_set_prot(mrioc->shost, prot_mask & 0x77); > + ioc_info(mrioc, > + "%s : Disabling DIX0 prot capability\n", __func__); > + ioc_info(mrioc, > + "because HBA does not support DIX0 operation on NVME drives\n"); > + } > break; > } > case MPI3_DEVICE_DEVFORM_VD: > @@ -1769,6 +1796,195 @@ void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc, > > } > > +/** > + * mpi3mr_setup_eedp - Setup EEDP information in MPI3 SCSI IO > + * @mrioc: Adapter instance reference > + * @scmd: SCSI command reference > + * @scsiio_req: MPI3 SCSI IO request > + * > + * Identifies the protection information flags from the SCSI > + * command and set appropriate flags in the MPI3 SCSI IO > + * request. > + * > + * Return: Nothing > + */ > +static void mpi3mr_setup_eedp(struct mpi3mr_ioc *mrioc, > + struct scsi_cmnd *scmd, Mpi3SCSIIORequest_t *scsiio_req) > +{ > + u16 eedp_flags = 0; > + unsigned char prot_op = scsi_get_prot_op(scmd); > + unsigned char prot_type = scsi_get_prot_type(scmd); > + > + switch (prot_op) { > + case SCSI_PROT_NORMAL: > + return; > + case SCSI_PROT_READ_STRIP: > + eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_CHECK_REMOVE; > + break; > + case SCSI_PROT_WRITE_INSERT: > + eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_INSERT; > + break; > + case SCSI_PROT_READ_INSERT: > + eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_INSERT; > + scsiio_req->MsgFlags |= MPI3_SCSIIO_MSGFLAGS_METASGL_VALID; > + break; > + case SCSI_PROT_WRITE_STRIP: > + eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_CHECK_REMOVE; > + scsiio_req->MsgFlags |= MPI3_SCSIIO_MSGFLAGS_METASGL_VALID; > + break; > + case SCSI_PROT_READ_PASS: > + eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_CHECK | > + MPI3_EEDPFLAGS_CHK_REF_TAG | MPI3_EEDPFLAGS_CHK_APP_TAG | > + MPI3_EEDPFLAGS_CHK_GUARD; > + scsiio_req->MsgFlags |= MPI3_SCSIIO_MSGFLAGS_METASGL_VALID; > + break; > + case SCSI_PROT_WRITE_PASS: > + if (scsi_host_get_guard(scmd->device->host) > + & SHOST_DIX_GUARD_IP) { > + eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_CHECK_REGEN | > + MPI3_EEDPFLAGS_CHK_APP_TAG | > + MPI3_EEDPFLAGS_CHK_GUARD | > + MPI3_EEDPFLAGS_INCR_PRI_REF_TAG; > + scsiio_req->SGL[0].Eedp.ApplicationTagTranslationMask > + = 0xffff; > + } else { > + eedp_flags = MPI3_EEDPFLAGS_EEDP_OP_CHECK | > + MPI3_EEDPFLAGS_CHK_REF_TAG | > + MPI3_EEDPFLAGS_CHK_APP_TAG | > + MPI3_EEDPFLAGS_CHK_GUARD; > + } > + scsiio_req->MsgFlags |= MPI3_SCSIIO_MSGFLAGS_METASGL_VALID; > + break; > + default: > + return; > + } > + > + if (scsi_host_get_guard(scmd->device->host) & SHOST_DIX_GUARD_IP) > + eedp_flags |= MPI3_EEDPFLAGS_HOST_GUARD_IP_CHKSUM; > + > + switch (prot_type) { > + case SCSI_PROT_DIF_TYPE0: > + eedp_flags |= MPI3_EEDPFLAGS_INCR_PRI_REF_TAG; > + scsiio_req->CDB.EEDP32.PrimaryReferenceTag = > + cpu_to_be32(t10_pi_ref_tag(scmd->request)); > + break; > + case SCSI_PROT_DIF_TYPE1: > + case SCSI_PROT_DIF_TYPE2: > + eedp_flags |= MPI3_EEDPFLAGS_INCR_PRI_REF_TAG | > + MPI3_EEDPFLAGS_ESC_MODE_APPTAG_DISABLE | > + MPI3_EEDPFLAGS_CHK_GUARD; > + scsiio_req->CDB.EEDP32.PrimaryReferenceTag = > + cpu_to_be32(t10_pi_ref_tag(scmd->request)); > + break; > + case SCSI_PROT_DIF_TYPE3: > + eedp_flags |= MPI3_EEDPFLAGS_CHK_GUARD | > + MPI3_EEDPFLAGS_ESC_MODE_APPTAG_DISABLE; > + break; > + > + default: > + scsiio_req->MsgFlags &= ~(MPI3_SCSIIO_MSGFLAGS_METASGL_VALID); > + return; > + } > + > + switch (scmd->device->sector_size) { > + case 512: > + scsiio_req->SGL[0].Eedp.UserDataSize = MPI3_EEDP_UDS_512; > + break; > + case 520: > + scsiio_req->SGL[0].Eedp.UserDataSize = MPI3_EEDP_UDS_520; > + break; > + case 4080: > + scsiio_req->SGL[0].Eedp.UserDataSize = MPI3_EEDP_UDS_4080; > + break; > + case 4088: > + scsiio_req->SGL[0].Eedp.UserDataSize = MPI3_EEDP_UDS_4088; > + break; > + case 4096: > + scsiio_req->SGL[0].Eedp.UserDataSize = MPI3_EEDP_UDS_4096; > + break; > + case 4104: > + scsiio_req->SGL[0].Eedp.UserDataSize = MPI3_EEDP_UDS_4104; > + break; > + case 4160: > + scsiio_req->SGL[0].Eedp.UserDataSize = MPI3_EEDP_UDS_4160; > + break; > + default: > + break; > + } > + > + scsiio_req->SGL[0].Eedp.EEDPFlags = cpu_to_le16(eedp_flags); > + scsiio_req->SGL[0].Eedp.Flags = MPI3_SGE_FLAGS_ELEMENT_TYPE_EXTENDED; > +} > + > + > + > +/** > + * mpi3mr_build_sense_buffer - Map sense information > + * @desc: Sense type > + * @buf: Sense buffer to populate > + * @key: Sense key > + * @asc: Additional sense code > + * @ascq: Additional sense code qualifier > + * > + * Maps the given sense information into either descriptor or > + * fixed format sense data. > + * > + * Return: Nothing > + */ > +static inline void mpi3mr_build_sense_buffer(int desc, u8 *buf, u8 key, > + u8 asc, u8 ascq) > +{ > + if (desc) { > + buf[0] = 0x72; /* descriptor, current */ > + buf[1] = key; > + buf[2] = asc; > + buf[3] = ascq; > + buf[7] = 0; > + } else { > + buf[0] = 0x70; /* fixed, current */ > + buf[2] = key; > + buf[7] = 0xa; > + buf[12] = asc; > + buf[13] = ascq; > + } > +} > + > +/** > + * mpi3mr_map_eedp_error - Map EEDP errors from IOC status > + * @scmd: SCSI command reference > + * @ioc_status: Status of MPI3 request > + * > + * Maps the EEDP error status of the SCSI IO request to sense > + * data. > + * > + * Return: Nothing > + */ > +static void mpi3mr_map_eedp_error(struct scsi_cmnd *scmd, > + u16 ioc_status) > +{ > + u8 ascq = 0; > + > + switch (ioc_status) { > + case MPI3_IOCSTATUS_EEDP_GUARD_ERROR: > + ascq = 0x01; > + break; > + case MPI3_IOCSTATUS_EEDP_APP_TAG_ERROR: > + ascq = 0x02; > + break; > + case MPI3_IOCSTATUS_EEDP_REF_TAG_ERROR: > + ascq = 0x03; > + break; > + default: > + ascq = 0x00; > + break; > + } > + > + mpi3mr_build_sense_buffer(0, scmd->sense_buffer, ILLEGAL_REQUEST, > + 0x10, ascq); > + scmd->result = DRIVER_SENSE << 24 | (DID_ABORT << 16) | > + SAM_STAT_CHECK_CONDITION; > +} > + > /** > * mpi3mr_process_op_reply_desc - reply descriptor handler > * @mrioc: Adapter instance reference > @@ -1931,6 +2147,11 @@ void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc, > else if (scsi_state & MPI3_SCSI_STATE_TERMINATED) > scmd->result = DID_RESET << 16; > break; > + case MPI3_IOCSTATUS_EEDP_GUARD_ERROR: > + case MPI3_IOCSTATUS_EEDP_REF_TAG_ERROR: > + case MPI3_IOCSTATUS_EEDP_APP_TAG_ERROR: > + mpi3mr_map_eedp_error(scmd, ioc_status); > + break; > case MPI3_IOCSTATUS_SCSI_PROTOCOL_ERROR: > case MPI3_IOCSTATUS_INVALID_FUNCTION: > case MPI3_IOCSTATUS_INVALID_SGL: > @@ -1966,6 +2187,10 @@ void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc, > } > } > out_success: > + if (priv->meta_sg_valid) { > + dma_unmap_sg(&mrioc->pdev->dev, scsi_prot_sglist(scmd), > + scsi_prot_sg_count(scmd), scmd->sc_data_direction); > + } > mpi3mr_clear_scmd_priv(mrioc, scmd); > scsi_dma_unmap(scmd); > scmd->scsi_done(scmd); > @@ -2029,6 +2254,8 @@ static int mpi3mr_prepare_sg_scmd(struct mpi3mr_ioc *mrioc, > u8 last_chain_sgl_flags; > struct chain_element *chain_req; > struct scmd_priv *priv = NULL; > + u32 meta_sg = le32_to_cpu(scsiio_req->Flags) & > + MPI3_SCSIIO_FLAGS_DMAOPERATION_HOST_PI; > > priv = scsi_cmd_priv(scmd); > > @@ -2039,15 +2266,27 @@ static int mpi3mr_prepare_sg_scmd(struct mpi3mr_ioc *mrioc, > last_chain_sgl_flags = MPI3_SGE_FLAGS_ELEMENT_TYPE_LAST_CHAIN | > MPI3_SGE_FLAGS_DLAS_SYSTEM; > > - sg_local = &scsiio_req->SGL; > + if (meta_sg) > + sg_local = &scsiio_req->SGL[MPI3_SCSIIO_METASGL_INDEX]; > + else > + sg_local = &scsiio_req->SGL; > > - if (!scsiio_req->DataLength) { > + if (!scsiio_req->DataLength && !meta_sg) { > mpi3mr_build_zero_len_sge(sg_local); > return 0; > } > > - sg_scmd = scsi_sglist(scmd); > - sges_left = scsi_dma_map(scmd); > + if (meta_sg) { > + sg_scmd = scsi_prot_sglist(scmd); > + sges_left = dma_map_sg(&mrioc->pdev->dev, > + scsi_prot_sglist(scmd), > + scsi_prot_sg_count(scmd), > + scmd->sc_data_direction); > + priv->meta_sg_valid = 1; /* To unmap meta sg DMA */ > + } else { > + sg_scmd = scsi_sglist(scmd); > + sges_left = scsi_dma_map(scmd); > + } > > if (sges_left < 0) { > sdev_printk(KERN_ERR, scmd->device, > @@ -2065,6 +2304,22 @@ static int mpi3mr_prepare_sg_scmd(struct mpi3mr_ioc *mrioc, > sges_in_segment = (mrioc->facts.op_req_sz - > offsetof(Mpi3SCSIIORequest_t, SGL))/sizeof(Mpi3SGESimple_t); > > + if (scsiio_req->SGL[0].Eedp.Flags == > + MPI3_SGE_FLAGS_ELEMENT_TYPE_EXTENDED && !meta_sg) { > + sg_local += sizeof(Mpi3SGEUnion_t); > + sges_in_segment--; > + /* Reserve 1st segment (scsiio_req->SGL[0]) for eedp */ > + } > + > + if (scsiio_req->MsgFlags == > + MPI3_SCSIIO_MSGFLAGS_METASGL_VALID && !meta_sg) { > + sges_in_segment--; > + /* Reserve last segment (scsiio_req->SGL[3]) for meta sg */ > + } > + > + if (meta_sg) > + sges_in_segment = 1; > + > if (sges_left <= sges_in_segment) > goto fill_in_last_segment; > > @@ -2082,7 +2337,10 @@ static int mpi3mr_prepare_sg_scmd(struct mpi3mr_ioc *mrioc, > if (chain_idx < 0) > return -1; > chain_req = &mrioc->chain_sgl_list[chain_idx]; > - priv->chain_idx = chain_idx; > + if (meta_sg) > + priv->meta_chain_idx = chain_idx; > + else > + priv->chain_idx = chain_idx; > > chain = chain_req->addr; > chain_dma = chain_req->dma_addr; > @@ -2132,6 +2390,13 @@ static int mpi3mr_build_sg_scmd(struct mpi3mr_ioc *mrioc, > if (ret) > return ret; > > + if (scsiio_req->MsgFlags == MPI3_SCSIIO_MSGFLAGS_METASGL_VALID) { > + /* There is a valid meta sg */ > + scsiio_req->Flags |= > + cpu_to_le32(MPI3_SCSIIO_FLAGS_DMAOPERATION_HOST_PI); > + ret = mpi3mr_prepare_sg_scmd(mrioc, scmd, scsiio_req); > + } > + > return ret; > } > > @@ -3130,6 +3395,8 @@ static int mpi3mr_qcmd(struct Scsi_Host *shost, > scsiio_req->Function = MPI3_FUNCTION_SCSI_IO; > scsiio_req->HostTag = cpu_to_le16(host_tag); > > + mpi3mr_setup_eedp(mrioc, scmd, scsiio_req); > + > memcpy(scsiio_req->CDB.CDB32, scmd->cmnd, scmd->cmd_len); > scsiio_req->DataLength = cpu_to_le32(scsi_bufflen(scmd)); > scsiio_req->DevHandle = cpu_to_le16(dev_handle); > @@ -3354,6 +3621,32 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) > shost->max_channel = 1; > shost->max_id = 0xFFFFFFFF; > > + if (prot_mask >= 0) > + scsi_host_set_prot(shost, prot_mask); > + else { > + prot_mask = SHOST_DIF_TYPE1_PROTECTION > + | SHOST_DIF_TYPE2_PROTECTION > + | SHOST_DIF_TYPE3_PROTECTION; > + scsi_host_set_prot(shost, prot_mask); > + > + } > + > + ioc_info(mrioc, > + "%s :host protection capabilities enabled %s%s%s%s%s%s%s\n", > + __func__, > + (prot_mask & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "", > + (prot_mask & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "", > + (prot_mask & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "", > + (prot_mask & SHOST_DIX_TYPE0_PROTECTION) ? " DIX0" : "", > + (prot_mask & SHOST_DIX_TYPE1_PROTECTION) ? " DIX1" : "", > + (prot_mask & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "", > + (prot_mask & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : ""); > + > + if (prot_guard_mask) > + scsi_host_set_guard(shost, (prot_guard_mask & 3)); > + else > + scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC); > + > snprintf(mrioc->fwevt_worker_name, sizeof(mrioc->fwevt_worker_name), > "%s%d_fwevt_wrkr", mrioc->driver_name, mrioc->id); > mrioc->fwevt_worker_thread = alloc_ordered_workqueue( > -- > 2.18.1 > -- Himanshu Madhani Oracle Linux Engineering
On 4/19/21 1:01 PM, Kashyap Desai wrote: > This adds the Kconfig and mpi30 headers. > > Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> > > Cc: sathya.prakash@broadcom.com > Cc: bvanassche@acm.org > Cc: thenzl@redhat.com > Cc: hare@suse.de > --- > drivers/scsi/Kconfig | 1 + > drivers/scsi/Makefile | 1 + > drivers/scsi/mpi3mr/Kconfig | 7 + > drivers/scsi/mpi3mr/mpi/mpi30_api.h | 21 + > drivers/scsi/mpi3mr/mpi/mpi30_image.h | 285 +++++ > drivers/scsi/mpi3mr/mpi/mpi30_init.h | 216 ++++ > drivers/scsi/mpi3mr/mpi/mpi30_ioc.h | 1423 +++++++++++++++++++++ > drivers/scsi/mpi3mr/mpi/mpi30_transport.h | 675 ++++++++++ > drivers/scsi/mpi3mr/mpi/mpi30_type.h | 20 + > 9 files changed, 2649 insertions(+) > create mode 100644 drivers/scsi/mpi3mr/Kconfig > create mode 100644 drivers/scsi/mpi3mr/mpi/mpi30_api.h > create mode 100644 drivers/scsi/mpi3mr/mpi/mpi30_image.h > create mode 100644 drivers/scsi/mpi3mr/mpi/mpi30_init.h > create mode 100644 drivers/scsi/mpi3mr/mpi/mpi30_ioc.h > create mode 100644 drivers/scsi/mpi3mr/mpi/mpi30_transport.h > create mode 100644 drivers/scsi/mpi3mr/mpi/mpi30_type.h > > diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig > index 06b87c7f6bab..1f06811740a7 100644 > --- a/drivers/scsi/Kconfig > +++ b/drivers/scsi/Kconfig > @@ -482,6 +482,7 @@ config SCSI_ARCMSR > source "drivers/scsi/esas2r/Kconfig" > source "drivers/scsi/megaraid/Kconfig.megaraid" > source "drivers/scsi/mpt3sas/Kconfig" > +source "drivers/scsi/mpi3mr/Kconfig" > source "drivers/scsi/smartpqi/Kconfig" > source "drivers/scsi/ufs/Kconfig" > > diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile > index bc3882f5cc69..06f2d5fab899 100644 > --- a/drivers/scsi/Makefile > +++ b/drivers/scsi/Makefile > @@ -99,6 +99,7 @@ obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o > obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/ > obj-$(CONFIG_MEGARAID_SAS) += megaraid/ > obj-$(CONFIG_SCSI_MPT3SAS) += mpt3sas/ > +obj-$(CONFIG_SCSI_MPI3MR) += mpi3mr/ > obj-$(CONFIG_SCSI_UFSHCD) += ufs/ > obj-$(CONFIG_SCSI_ACARD) += atp870u.o > obj-$(CONFIG_SCSI_SUNESP) += esp_scsi.o sun_esp.o > diff --git a/drivers/scsi/mpi3mr/Kconfig b/drivers/scsi/mpi3mr/Kconfig > new file mode 100644 > index 000000000000..2d0568dd176a > --- /dev/null > +++ b/drivers/scsi/mpi3mr/Kconfig > @@ -0,0 +1,7 @@ > +# SPDX-License-Identifier: GPL-2.0-or-later > + > +config SCSI_MPI3MR > + tristate "Broadcom MPI3 Storage Controller Device Driver" > + depends on PCI && SCSI > + help > + This driver supports Broadcom's Unified MPI3 based Storage & RAID Controllers. > diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_api.h b/drivers/scsi/mpi3mr/mpi/mpi30_api.h > new file mode 100644 > index 000000000000..46dd30ccb5f9 > --- /dev/null > +++ b/drivers/scsi/mpi3mr/mpi/mpi30_api.h > @@ -0,0 +1,21 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * Copyright 2019-2020 Broadcom Inc. All rights reserved. > + * > + * Name: mpi30_api.h > + * Description: Root header that include all other MPI 3.0 headers > + * Developers need to only include this header to gain > + * access to the full MPI3.0 API definitions. > + * Creation Date: 04/15/2019 > + * Version: 03.00.00 > + */ > +#ifndef MPI30_API_H > +#define MPI30_API_H 1 > + > +#include "mpi30_type.h" > +#include "mpi30_transport.h" > +#include "mpi30_image.h" > +#include "mpi30_init.h" > +#include "mpi30_ioc.h" > + > +#endif /* MPI30_API_H */ > diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_image.h b/drivers/scsi/mpi3mr/mpi/mpi30_image.h > new file mode 100644 > index 000000000000..430662d3a43b > --- /dev/null > +++ b/drivers/scsi/mpi3mr/mpi/mpi30_image.h > @@ -0,0 +1,285 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * Copyright 2018-2020 Broadcom Inc. All rights reserved. > + * > + * Name: mpi30_image.h > + * Description: Contains definitions for firmware and other component images. > + * Creation Date: 04/02/2018 > + * Version: 03.00.00 > + */ > +#ifndef MPI30_IMAGE_H > +#define MPI30_IMAGE_H 1 > + > +/* Component Image Version */ > +typedef struct _MPI3_COMP_IMAGE_VERSION { > + U16 BuildNum; /* 0x00 */ > + U16 CustomerID; /* 0x02 */ > + U8 PhaseMinor; /* 0x04 */ > + U8 PhaseMajor; /* 0x05 */ > + U8 GenMinor; /* 0x06 */ > + U8 GenMajor; /* 0x07 */ > +} MPI3_COMP_IMAGE_VERSION, MPI3_POINTER PTR_MPI3_COMP_IMAGE_VERSION, > + Mpi3CompImageVersion, MPI3_POINTER pMpi3CompImageVersion; > + Oh, please. _Four_ different names for one structure? And two are just uppercase versions of the others? Please, reconsider. I could live with have two names (the normal and the pointer one), but four? Please, don't. > +/* Hash Exclusion Format */ > +typedef struct _MPI3_HASH_EXCLUSION_FORMAT { > + U32 Offset; /* 0x00 */ > + U32 Size; /* 0x04 */ > +} MPI3_HASH_EXCLUSION_FORMAT, MPI3_POINTER PTR_MPI3_HASH_EXCLUSION_FORMAT, > +Mpi3HashSxclusionFormat_t, MPI3_POINTER pMpi3HashExclusionFormat_t; > + > +#define MPI3_IMAGE_HASH_EXCUSION_NUM (4) > + > +/* FW Image Header */ > +typedef struct _MPI3_COMPONENT_IMAGE_HEADER { > + U32 Signature0; /* 0x00 */ > + U32 LoadAddress; /* 0x04 */ > + U32 DataSize; /* 0x08 */ > + U32 StartOffset; /* 0x0C */ > + U32 Signature1; /* 0x10 */ > + U32 FlashOffset; /* 0x14 */ > + U32 ImageSize; /* 0x18 */ > + U32 VersionStringOffset; /* 0x1C */ > + U32 BuildDateStringOffset; /* 0x20 */ > + U32 BuildTimeStringOffset; /* 0x24 */ > + U32 EnvironmentVariableOffset; /* 0x28 */ > + U32 ApplicationSpecific; /* 0x2C */ > + U32 Signature2; /* 0x30 */ > + U32 HeaderSize; /* 0x34 */ > + U32 Crc; /* 0x38 */ > + U32 Flags; /* 0x3C */ > + U32 SecondaryFlashOffset; /* 0x40 */ > + U32 ETPOffset; /* 0x44 */ > + U32 ETPSize; /* 0x48 */ > + MPI3_VERSION_UNION RMCInterfaceVersion; /* 0x4C */ > + MPI3_VERSION_UNION ETPInterfaceVersion; /* 0x50 */ > + MPI3_COMP_IMAGE_VERSION ComponentImageVersion; /* 0x54 */ > + MPI3_HASH_EXCLUSION_FORMAT HashExclusion[MPI3_IMAGE_HASH_EXCUSION_NUM]; /* 0x5C */ > + U32 NextImageHeaderOffset; /* 0x7C */ > + MPI3_VERSION_UNION SecurityVersion; /* 0x80 */ > + U32 Reserved84[31]; /* 0x84 -- 0xFC */ > +} MPI3_COMPONENT_IMAGE_HEADER, MPI3_POINTER PTR_MPI3_COMPONENT_IMAGE_HEADER, > + Mpi3ComponentImageHeader_t, MPI3_POINTER pMpi3ComponentImageHeader_t; > + > + > +/**** Definitions for Signature0 field ****/ > +#define MPI3_IMAGE_HEADER_SIGNATURE0_MPI3 (0xEB00003E) > + > +/**** Definitions for LoadAddress field ****/ > +#define MPI3_IMAGE_HEADER_LOAD_ADDRESS_INVALID (0x00000000) > + > +/**** Definitions for Signature1 field ****/ > +#define MPI3_IMAGE_HEADER_SIGNATURE1_APPLICATION (0x20505041) /* string "APP " */ > +#define MPI3_IMAGE_HEADER_SIGNATURE1_FIRST_MUTABLE (0x20434D46) /* string "FMC " */ > +#define MPI3_IMAGE_HEADER_SIGNATURE1_BSP (0x20505342) /* string "BSP " */ > +#define MPI3_IMAGE_HEADER_SIGNATURE1_ROM_BIOS (0x534F4942) /* string "BIOS" */ > +#define MPI3_IMAGE_HEADER_SIGNATURE1_HII_X64 (0x4D494948) /* string "HIIM" */ > +#define MPI3_IMAGE_HEADER_SIGNATURE1_HII_ARM (0x41494948) /* string "HIIA" */ > +#define MPI3_IMAGE_HEADER_SIGNATURE1_CPLD (0x444C5043) /* string "CPLD" */ > +#define MPI3_IMAGE_HEADER_SIGNATURE1_SPD (0x20445053) /* string "SPD " */ > +#define MPI3_IMAGE_HEADER_SIGNATURE1_GAS_GAUGE (0x20534147) /* string "GAS " */ > +#define MPI3_IMAGE_HEADER_SIGNATURE1_PBLP (0x504C4250) /* string "PBLP" */ > + > +/**** Definitions for Signature2 field ****/ > +#define MPI3_IMAGE_HEADER_SIGNATURE2_VALUE (0x50584546) > + > +/**** Definitions for Flags field ****/ > +#define MPI3_IMAGE_HEADER_FLAGS_DEVICE_KEY_BASIS_MASK (0x00000030) > +#define MPI3_IMAGE_HEADER_FLAGS_DEVICE_KEY_BASIS_CDI (0x00000000) > +#define MPI3_IMAGE_HEADER_FLAGS_DEVICE_KEY_BASIS_DI (0x00000010) > +#define MPI3_IMAGE_HEADER_FLAGS_SIGNED_NVDATA (0x00000008) > +#define MPI3_IMAGE_HEADER_FLAGS_REQUIRES_ACTIVATION (0x00000004) > +#define MPI3_IMAGE_HEADER_FLAGS_COMPRESSED (0x00000002) > +#define MPI3_IMAGE_HEADER_FLAGS_FLASH (0x00000001) > + > + > +/**** Offsets for Image Header Fields ****/ > +#define MPI3_IMAGE_HEADER_SIGNATURE0_OFFSET (0x00) > +#define MPI3_IMAGE_HEADER_LOAD_ADDRESS_OFFSET (0x04) > +#define MPI3_IMAGE_HEADER_DATA_SIZE_OFFSET (0x08) > +#define MPI3_IMAGE_HEADER_START_OFFSET_OFFSET (0x0C) > +#define MPI3_IMAGE_HEADER_SIGNATURE1_OFFSET (0x10) > +#define MPI3_IMAGE_HEADER_FLASH_OFFSET_OFFSET (0x14) > +#define MPI3_IMAGE_HEADER_FLASH_SIZE_OFFSET (0x18) > +#define MPI3_IMAGE_HEADER_VERSION_STRING_OFFSET_OFFSET (0x1C) > +#define MPI3_IMAGE_HEADER_BUILD_DATE_STRING_OFFSET_OFFSET (0x20) > +#define MPI3_IMAGE_HEADER_BUILD_TIME_OFFSET_OFFSET (0x24) > +#define MPI3_IMAGE_HEADER_ENVIROMENT_VAR_OFFSET_OFFSET (0x28) > +#define MPI3_IMAGE_HEADER_APPLICATION_SPECIFIC_OFFSET (0x2C) > +#define MPI3_IMAGE_HEADER_SIGNATURE2_OFFSET (0x30) > +#define MPI3_IMAGE_HEADER_HEADER_SIZE_OFFSET (0x34) > +#define MPI3_IMAGE_HEADER_CRC_OFFSET (0x38) > +#define MPI3_IMAGE_HEADER_FLAGS_OFFSET (0x3C) > +#define MPI3_IMAGE_HEADER_SECONDARY_FLASH_OFFSET_OFFSET (0x40) > +#define MPI3_IMAGE_HEADER_ETP_OFFSET_OFFSET (0x44) > +#define MPI3_IMAGE_HEADER_ETP_SIZE_OFFSET (0x48) > +#define MPI3_IMAGE_HEADER_RMC_INTERFACE_VER_OFFSET (0x4C) > +#define MPI3_IMAGE_HEADER_ETP_INTERFACE_VER_OFFSET (0x50) > +#define MPI3_IMAGE_HEADER_COMPONENT_IMAGE_VER_OFFSET (0x54) > +#define MPI3_IMAGE_HEADER_HASH_EXCLUSION_OFFSET (0x5C) > +#define MPI3_IMAGE_HEADER_NEXT_IMAGE_HEADER_OFFSET_OFFSET (0x7C) > + > + > +#define MPI3_IMAGE_HEADER_SIZE (0x100) > + > + > +/* Extended Image Header */ > +typedef struct _MPI3_EXTENDED_IMAGE_HEADER { > + U8 ImageType; /* 0x00 */ > + U8 Reserved01[3]; /* 0x01 */ > + U32 Checksum; /* 0x04 */ > + U32 ImageSize; /* 0x08 */ > + U32 NextImageHeaderOffset; /* 0x0C */ > + U32 Reserved10[4]; /* 0x10 */ > + U32 IdentifyString[8]; /* 0x20 */ > +} MPI3_EXTENDED_IMAGE_HEADER, MPI3_POINTER PTR_MPI3_EXTENDED_IMAGE_HEADER, > + Mpi3ExtendedImageHeader_t, MPI3_POINTER pMpi3ExtendedImageHeader_t; > + > +/* useful offsets */ > +#define MPI3_EXT_IMAGE_IMAGETYPE_OFFSET (0x00) > +#define MPI3_EXT_IMAGE_IMAGESIZE_OFFSET (0x08) > +#define MPI3_EXT_IMAGE_NEXTIMAGE_OFFSET (0x0C) > + > +#define MPI3_EXT_IMAGE_HEADER_SIZE (0x40) > + > +/* defines for the ImageType field */ > +#define MPI3_EXT_IMAGE_TYPE_UNSPECIFIED (0x00) > +#define MPI3_EXT_IMAGE_TYPE_NVDATA (0x03) > +#define MPI3_EXT_IMAGE_TYPE_SUPPORTED_DEVICES (0x07) > +#define MPI3_EXT_IMAGE_TYPE_ENCRYPTED_HASH (0x09) > +#define MPI3_EXT_IMAGE_TYPE_RDE (0x0A) > +#define MPI3_EXT_IMAGE_TYPE_AUXILIARY_PROCESSOR (0x0B) > +#define MPI3_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC (0x80) > +#define MPI3_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC (0xFF) > + > + > +/* Supported Device Data Format */ > +typedef struct _MPI3_SUPPORTED_DEVICE { > + U16 DeviceID; /* 0x00 */ > + U16 VendorID; /* 0x02 */ > + U16 DeviceIDMask; /* 0x04 */ > + U16 Reserved06; /* 0x06 */ > + U8 LowPCIRev; /* 0x08 */ > + U8 HighPCIRev; /* 0x09 */ > + U16 Reserved0A; /* 0x0A */ > + U32 Reserved0C; /* 0x0C */ > +} MPI3_SUPPORTED_DEVICE, MPI3_POINTER PTR_MPI3_SUPPORTED_DEVICE, > + Mpi3SupportedDevice_t, MPI3_POINTER pMpi3SupportedDevice_t; > + > +#ifndef MPI3_SUPPORTED_DEVICE_MAX > +#define MPI3_SUPPORTED_DEVICE_MAX (1) > +#endif /* MPI3_SUPPORTED_DEVICE_MAX */ > + > +/* Supported Devices Extended Image Data */ > +typedef struct _MPI3_SUPPORTED_DEVICES_DATA { > + U8 ImageVersion; /* 0x00 */ > + U8 Reserved01; /* 0x01 */ > + U8 NumDevices; /* 0x02 */ > + U8 Reserved03; /* 0x03 */ > + U32 Reserved04; /* 0x04 */ > + MPI3_SUPPORTED_DEVICE SupportedDevice[MPI3_SUPPORTED_DEVICE_MAX]; /* 0x08 */ /* variable length */ > +} MPI3_SUPPORTED_DEVICES_DATA, MPI3_POINTER PTR_MPI3_SUPPORTED_DEVICES_DATA, > + Mpi3SupportedDevicesData_t, MPI3_POINTER pMpi3SupportedDevicesData_t; > + > +#ifndef MPI3_ENCRYPTED_HASH_MAX > +#define MPI3_ENCRYPTED_HASH_MAX (1) > +#endif /* MPI3_ENCRYPTED_HASH_MAX */ > + > +/* Encrypted Hash Entry Format */ > +typedef struct _MPI3_ENCRYPTED_HASH_ENTRY { > + U8 HashImageType; /* 0x00 */ > + U8 HashAlgorithm; /* 0x01 */ > + U8 EncryptionAlgorithm; /* 0x02 */ > + U8 Reserved03; /* 0x03 */ > + U32 Reserved04; /* 0x04 */ > + U32 EncryptedHash[MPI3_ENCRYPTED_HASH_MAX]; /* 0x08 */ /* variable length */ > +} MPI3_ENCRYPTED_HASH_ENTRY, MPI3_POINTER PTR_MPI3_ENCRYPTED_HASH_ENTRY, > + Mpi3EncryptedHashEntry_t, MPI3_POINTER pMpi3EncryptedHashEntry_t; > + > + > +/* defines for the HashImageType field */ > +#define MPI3_HASH_IMAGE_TYPE_KEY_WITH_SIGNATURE (0x03) > + > +/* defines for the HashAlgorithm field */ > +#define MPI3_HASH_ALGORITHM_VERSION_MASK (0xE0) > +#define MPI3_HASH_ALGORITHM_VERSION_NONE (0x00) > +#define MPI3_HASH_ALGORITHM_VERSION_SHA1 (0x20) /* Obsolete */ > +#define MPI3_HASH_ALGORITHM_VERSION_SHA2 (0x40) > +#define MPI3_HASH_ALGORITHM_VERSION_SHA3 (0x60) > + > +#define MPI3_HASH_ALGORITHM_SIZE_MASK (0x1F) > +#define MPI3_HASH_ALGORITHM_SIZE_UNUSED (0x00) > +#define MPI3_HASH_ALGORITHM_SIZE_SHA256 (0x01) > +#define MPI3_HASH_ALGORITHM_SIZE_SHA512 (0x02) > + > +/* defines for the EncryptionAlgorithm field */ > +#define MPI3_ENCRYPTION_ALGORITHM_UNUSED (0x00) > +#define MPI3_ENCRYPTION_ALGORITHM_RSA256 (0x01) /* Obsolete */ > +#define MPI3_ENCRYPTION_ALGORITHM_RSA512 (0x02) /* Obsolete */ > +#define MPI3_ENCRYPTION_ALGORITHM_RSA1024 (0x03) /* Obsolete */ > +#define MPI3_ENCRYPTION_ALGORITHM_RSA2048 (0x04) > +#define MPI3_ENCRYPTION_ALGORITHM_RSA4096 (0x05) > +#define MPI3_ENCRYPTION_ALGORITHM_RSA3072 (0x06) > + > + > +#ifndef MPI3_PUBLIC_KEY_MAX > +#define MPI3_PUBLIC_KEY_MAX (1) > +#endif /* MPI3_PUBLIC_KEY_MAX */ > + > +/* Encrypted Key with Hash Entry Format */ > +typedef struct _MPI3_ENCRYPTED_KEY_WITH_HASH_ENTRY { > + U8 HashImageType; /* 0x00 */ > + U8 HashAlgorithm; /* 0x01 */ > + U8 EncryptionAlgorithm; /* 0x02 */ > + U8 Reserved03; /* 0x03 */ > + U32 Reserved04; /* 0x04 */ > + U32 PublicKey[MPI3_PUBLIC_KEY_MAX]; /* 0x08 */ /* variable length */ > + U32 EncryptedHash[MPI3_ENCRYPTED_HASH_MAX]; /* 0x0C */ /* variable length */ > +} MPI3_ENCRYPTED_KEY_WITH_HASH_ENTRY, MPI3_POINTER PTR_MPI3_ENCRYPTED_KEY_WITH_HASH_ENTRY, > + Mpi3EncryptedKeyWithHashEntry_t, MPI3_POINTER pMpi3EncryptedKeyWithHashEntry_t; > + > +#ifndef MPI3_ENCRYPTED_HASH_ENTRY_MAX > +#define MPI3_ENCRYPTED_HASH_ENTRY_MAX (1) > +#endif /* MPI3_ENCRYPTED_HASH_ENTRY_MAX */ > + > +/* Encrypted Hash Image Data */ > +typedef struct _MPI3_ENCRYPTED_HASH_DATA { > + U8 ImageVersion; /* 0x00 */ > + U8 NumHash; /* 0x01 */ > + U16 Reserved02; /* 0x02 */ > + U32 Reserved04; /* 0x04 */ > + MPI3_ENCRYPTED_HASH_ENTRY EncryptedHashEntry[MPI3_ENCRYPTED_HASH_ENTRY_MAX]; /* 0x08 */ /* variable length */ > +} MPI3_ENCRYPTED_HASH_DATA, MPI3_POINTER PTR_MPI3_ENCRYPTED_HASH_DATA, > + Mpi3EncryptedHashData_t, MPI3_POINTER pMpi3EncryptedHashData_t; > + > + > +#ifndef MPI3_AUX_PROC_DATA_MAX > +#define MPI3_AUX_PROC_DATA_MAX (1) > +#endif /* MPI3_ENCRYPTED_HASH_ENTRY_MAX */ > + > +/* Auxiliary Processor Extended Image Data */ > +typedef struct _MPI3_AUX_PROCESSOR_DATA { > + U8 BootMethod; /* 0x00 */ > + U8 NumLoadAddr; /* 0x01 */ > + U8 Reserved02; /* 0x02 */ > + U8 Type; /* 0x03 */ > + U32 Version; /* 0x04 */ > + U32 LoadAddress[8]; /* 0x08 */ > + U32 Reserved28[22]; /* 0x28 */ > + U32 AuxProcessorData[MPI3_AUX_PROC_DATA_MAX]; /* 0x80 */ /* variable length */ > +} MPI3_AUX_PROCESSOR_DATA, MPI3_POINTER PTR_MPI3_AUX_PROCESSOR_DATA, > + Mpi3AuxProcessorData_t, MPI3_POINTER pMpi3AuxProcessorData_t; > + > +#define MPI3_AUX_PROC_DATA_OFFSET (0x80) > + > +/* defines for the BootMethod field */ > +#define MPI3_AUXPROCESSOR_BOOT_METHOD_MO_MSG (0x00) > +#define MPI3_AUXPROCESSOR_BOOT_METHOD_MO_DOORBELL (0x01) > +#define MPI3_AUXPROCESSOR_BOOT_METHOD_COMPONENT (0x02) > + > +/* defines for the Type field */ > +#define MPI3_AUXPROCESSOR_TYPE_ARM_A15 (0x00) > +#define MPI3_AUXPROCESSOR_TYPE_ARM_M0 (0x01) > +#define MPI3_AUXPROCESSOR_TYPE_ARM_R4 (0x02) > + > +#endif /* MPI30_IMAGE_H */ > diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_init.h b/drivers/scsi/mpi3mr/mpi/mpi30_init.h > new file mode 100644 > index 000000000000..a0222f0fc9a8 > --- /dev/null > +++ b/drivers/scsi/mpi3mr/mpi/mpi30_init.h > @@ -0,0 +1,216 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * Copyright 2016-2020 Broadcom Inc. All rights reserved. > + * > + * Name: mpi30_init.h > + * Description: Contains definitions for SCSI initiator mode messages and structures. > + * Creation Date: 10/27/2016 > + * Version: 03.00.00 > + */ > +#ifndef MPI30_INIT_H > +#define MPI30_INIT_H 1 > + > +/***************************************************************************** > + * SCSI Initiator Messages * > + ****************************************************************************/ > + > +/***************************************************************************** > + * SCSI IO Request Message * > + ****************************************************************************/ > +typedef struct _MPI3_SCSI_IO_CDB_EEDP32 { > + U8 CDB[20]; /* 0x00 */ > + __be32 PrimaryReferenceTag; /* 0x14 */ > + U16 PrimaryApplicationTag; /* 0x18 */ > + U16 PrimaryApplicationTagMask; /* 0x1A */ > + U32 TransferLength; /* 0x1C */ > +} MPI3_SCSI_IO_CDB_EEDP32, MPI3_POINTER PTR_MPI3_SCSI_IO_CDB_EEDP32, > + Mpi3ScsiIoCdbEedp32_t, MPI3_POINTER pMpi3ScsiIoCdbEedp32_t; > + > +typedef union _MPI3_SCSO_IO_CDB_UNION { > + U8 CDB32[32]; > + MPI3_SCSI_IO_CDB_EEDP32 EEDP32; > + MPI3_SGE_SIMPLE SGE; > +} MPI3_SCSO_IO_CDB_UNION, MPI3_POINTER PTR_MPI3_SCSO_IO_CDB_UNION, > + Mpi3ScsiIoCdb_t, MPI3_POINTER pMpi3ScsiIoCdb_t; > + > +typedef struct _MPI3_SCSI_IO_REQUEST { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U16 DevHandle; /* 0x0A */ > + U32 Flags; /* 0x0C */ > + U32 SkipCount; /* 0x10 */ > + U32 DataLength; /* 0x14 */ > + U8 LUN[8]; /* 0x18 */ > + MPI3_SCSO_IO_CDB_UNION CDB; /* 0x20 */ > + MPI3_SGE_UNION SGL[4]; /* 0x40 */ > +} MPI3_SCSI_IO_REQUEST, MPI3_POINTER PTR_MPI3_SCSI_IO_REQUEST, > + Mpi3SCSIIORequest_t, MPI3_POINTER pMpi3SCSIIORequest_t; > + > +/**** Defines for the MsgFlags field ****/ > +#define MPI3_SCSIIO_MSGFLAGS_METASGL_VALID (0x80) > + > +/**** Defines for the Flags field ****/ > +#define MPI3_SCSIIO_FLAGS_LARGE_CDB (0x60000000) > +#define MPI3_SCSIIO_FLAGS_CDB_16_OR_LESS (0x00000000) > +#define MPI3_SCSIIO_FLAGS_CDB_GREATER_THAN_16 (0x20000000) > +#define MPI3_SCSIIO_FLAGS_CDB_IN_SEPARATE_BUFFER (0x40000000) > +#define MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_MASK (0x07000000) > +#define MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_SIMPLEQ (0x00000000) > +#define MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_HEADOFQ (0x01000000) > +#define MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_ORDEREDQ (0x02000000) > +#define MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_ACAQ (0x04000000) > +#define MPI3_SCSIIO_FLAGS_CMDPRI_MASK (0x00F00000) > +#define MPI3_SCSIIO_FLAGS_CMDPRI_SHIFT (20) > +#define MPI3_SCSIIO_FLAGS_DATADIRECTION_MASK (0x000C0000) > +#define MPI3_SCSIIO_FLAGS_DATADIRECTION_NO_DATA_TRANSFER (0x00000000) > +#define MPI3_SCSIIO_FLAGS_DATADIRECTION_WRITE (0x00040000) > +#define MPI3_SCSIIO_FLAGS_DATADIRECTION_READ (0x00080000) > +#define MPI3_SCSIIO_FLAGS_DMAOPERATION_MASK (0x00030000) > +#define MPI3_SCSIIO_FLAGS_DMAOPERATION_HOST_PI (0x00010000) > + > +/**** Defines for the SGL field ****/ > +#define MPI3_SCSIIO_METASGL_INDEX (3) > + > +/***************************************************************************** > + * SCSI IO Error Reply Message * > + ****************************************************************************/ > +typedef struct _MPI3_SCSI_IO_REPLY { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 IOCUseOnly08; /* 0x08 */ > + U16 IOCStatus; /* 0x0A */ > + U32 IOCLogInfo; /* 0x0C */ > + U8 SCSIStatus; /* 0x10 */ > + U8 SCSIState; /* 0x11 */ > + U16 DevHandle; /* 0x12 */ > + U32 TransferCount; /* 0x14 */ > + U32 SenseCount; /* 0x18 */ > + U32 ResponseData; /* 0x1C */ > + U16 TaskTag; /* 0x20 */ > + U16 SCSIStatusQualifier; /* 0x22 */ > + U32 EEDPErrorOffset; /* 0x24 */ > + U16 EEDPObservedAppTag; /* 0x28 */ > + U16 EEDPObservedGuard; /* 0x2A */ > + U32 EEDPObservedRefTag; /* 0x2C */ > + U64 SenseDataBufferAddress; /* 0x30 */ > +} MPI3_SCSI_IO_REPLY, MPI3_POINTER PTR_MPI3_SCSI_IO_REPLY, > + Mpi3SCSIIOReply_t, MPI3_POINTER pMpi3SCSIIOReply_t; > + > +/**** Defines for the MsgFlags field ****/ > +#define MPI3_SCSIIO_REPLY_MSGFLAGS_REFTAG_OBSERVED_VALID (0x01) > +#define MPI3_SCSIIO_REPLY_MSGFLAGS_APPTAG_OBSERVED_VALID (0x02) > +#define MPI3_SCSIIO_REPLY_MSGFLAGS_GUARD_OBSERVED_VALID (0x04) > + > +/**** Defines for the SCSIStatus field ****/ > +#define MPI3_SCSI_STATUS_GOOD (0x00) > +#define MPI3_SCSI_STATUS_CHECK_CONDITION (0x02) > +#define MPI3_SCSI_STATUS_CONDITION_MET (0x04) > +#define MPI3_SCSI_STATUS_BUSY (0x08) > +#define MPI3_SCSI_STATUS_INTERMEDIATE (0x10) > +#define MPI3_SCSI_STATUS_INTERMEDIATE_CONDMET (0x14) > +#define MPI3_SCSI_STATUS_RESERVATION_CONFLICT (0x18) > +#define MPI3_SCSI_STATUS_COMMAND_TERMINATED (0x22) > +#define MPI3_SCSI_STATUS_TASK_SET_FULL (0x28) > +#define MPI3_SCSI_STATUS_ACA_ACTIVE (0x30) > +#define MPI3_SCSI_STATUS_TASK_ABORTED (0x40) > + > +/**** Defines for the SCSIState field ****/ > +#define MPI3_SCSI_STATE_SENSE_MASK (0x03) > +#define MPI3_SCSI_STATE_SENSE_VALID (0x00) > +#define MPI3_SCSI_STATE_SENSE_FAILED (0x01) > +#define MPI3_SCSI_STATE_SENSE_BUFF_Q_EMPTY (0x02) > +#define MPI3_SCSI_STATE_SENSE_NOT_AVAILABLE (0x03) > +#define MPI3_SCSI_STATE_NO_SCSI_STATUS (0x04) > +#define MPI3_SCSI_STATE_TERMINATED (0x08) > +#define MPI3_SCSI_STATE_RESPONSE_DATA_VALID (0x10) > + > +/**** Defines for the ResponseData field ****/ > +#define MPI3_SCSI_RSP_RESPONSECODE_MASK (0x000000FF) > +#define MPI3_SCSI_RSP_RESPONSECODE_SHIFT (0) > +#define MPI3_SCSI_RSP_ARI2_MASK (0x0000FF00) > +#define MPI3_SCSI_RSP_ARI2_SHIFT (8) > +#define MPI3_SCSI_RSP_ARI1_MASK (0x00FF0000) > +#define MPI3_SCSI_RSP_ARI1_SHIFT (16) > +#define MPI3_SCSI_RSP_ARI0_MASK (0xFF000000) > +#define MPI3_SCSI_RSP_ARI0_SHIFT (24) > + > +/**** Defines for the TaskTag field ****/ > +#define MPI3_SCSI_TASKTAG_UNKNOWN (0xFFFF) > + > + > +/***************************************************************************** > + * SCSI Task Management Request Message * > + ****************************************************************************/ > +typedef struct _MPI3_SCSI_TASK_MGMT_REQUEST { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U16 DevHandle; /* 0x0A */ > + U16 TaskHostTag; /* 0x0C */ > + U8 TaskType; /* 0x0E */ > + U8 Reserved0F; /* 0x0F */ > + U16 TaskRequestQueueID; /* 0x10 */ > + U16 Reserved12; /* 0x12 */ > + U32 Reserved14; /* 0x14 */ > + U8 LUN[8]; /* 0x18 */ > +} MPI3_SCSI_TASK_MGMT_REQUEST, MPI3_POINTER PTR_MPI3_SCSI_TASK_MGMT_REQUEST, > + Mpi3SCSITaskMgmtRequest_t, MPI3_POINTER pMpi3SCSITaskMgmtRequest_t; > + > +/**** Defines for the MsgFlags field ****/ > +#define MPI3_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU (0x08) > + > +/**** Defines for the TaskType field ****/ > +#define MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK (0x01) > +#define MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK_SET (0x02) > +#define MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET (0x03) > +#define MPI3_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05) > +#define MPI3_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06) > +#define MPI3_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07) > +#define MPI3_SCSITASKMGMT_TASKTYPE_CLEAR_ACA (0x08) > +#define MPI3_SCSITASKMGMT_TASKTYPE_QUERY_TASK_SET (0x09) > +#define MPI3_SCSITASKMGMT_TASKTYPE_QUERY_ASYNC_EVENT (0x0A) > +#define MPI3_SCSITASKMGMT_TASKTYPE_I_T_NEXUS_RESET (0x0B) > + > + > +/***************************************************************************** > + * SCSI Task Management Reply Message * > + ****************************************************************************/ > +typedef struct _MPI3_SCSI_TASK_MGMT_REPLY { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 IOCUseOnly08; /* 0x08 */ > + U16 IOCStatus; /* 0x0A */ > + U32 IOCLogInfo; /* 0x0C */ > + U32 TerminationCount; /* 0x10 */ > + U32 ResponseData; /* 0x14 */ > + U32 Reserved18; /* 0x18 */ > +} MPI3_SCSI_TASK_MGMT_REPLY, MPI3_POINTER PTR_MPI3_SCSI_TASK_MGMT_REPLY, > + Mpi3SCSITaskMgmtReply_t, MPI3_POINTER pMpi3SCSITaskMgmtReply_t; > + > +/**** Defines for the ResponseData field - use MPI3_SCSI_RSP_ defines ****/ > +/* > + * Values for the ResponseCode (byte 0 of ResponseData) is normally obtained > + * from the SSP Response frame. A value of 0x80 may be returned by the IOC > + * for a TaskType of Query Task indicating the specified TaskHostTag I/O is > + * currently queued on the IOC and has not been sent to the target device yet. > + */ > +#define MPI3_SCSITASKMGMT_RSPCODE_IO_QUEUED_ON_IOC (0x80) > + > +#endif /* MPI30_INIT_H */ > diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h > new file mode 100644 > index 000000000000..880d717000f6 > --- /dev/null > +++ b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h > @@ -0,0 +1,1423 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * Copyright 2016-2020 Broadcom Inc. All rights reserved. > + * > + * Name: mpi30_ioc.h > + * Description: Contains definitions for IOC messages such as IOC Init, IOC Facts, Port Enable, > + * Events, FW Download, and FW Upload. > + * Creation Date: 10/24/2016 > + * Version: 03.00.00 > + */ > +#ifndef MPI30_IOC_H > +#define MPI30_IOC_H 1 > + > +/***************************************************************************** > + * IOC Messages * > + ****************************************************************************/ > + > +/***************************************************************************** > + * IOCInit Request Message * > + ****************************************************************************/ > +typedef struct _MPI3_IOC_INIT_REQUEST { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U16 Reserved0A; /* 0x0A */ > + MPI3_VERSION_UNION MPIVersion; /* 0x0C */ > + U64 TimeStamp; /* 0x10 */ > + U8 Reserved18; /* 0x18 */ > + U8 WhoInit; /* 0x19 */ > + U16 Reserved1A; /* 0x1A */ > + U16 ReplyFreeQueueDepth; /* 0x1C */ > + U16 Reserved1E; /* 0x1E */ > + U64 ReplyFreeQueueAddress; /* 0x20 */ > + U32 Reserved28; /* 0x28 */ > + U16 SenseBufferFreeQueueDepth; /* 0x2C */ > + U16 SenseBufferLength; /* 0x2E */ > + U64 SenseBufferFreeQueueAddress; /* 0x30 */ > + U64 DriverInformationAddress; /* 0x38 */ > +} MPI3_IOC_INIT_REQUEST, MPI3_POINTER PTR_MPI3_IOC_INIT_REQUEST, > + Mpi3IOCInitRequest_t, MPI3_POINTER pMpi3IOCInitRequest_t; > + > + > +/**** Defines for the WhoInit field ****/ > +#define MPI3_WHOINIT_NOT_INITIALIZED (0x00) > +#define MPI3_WHOINIT_ROM_BIOS (0x02) > +#define MPI3_WHOINIT_HOST_DRIVER (0x03) > +#define MPI3_WHOINIT_MANUFACTURER (0x04) > + > +/**** Defines for the DriverInformationAddress field */ > +typedef struct _MPI3_DRIVER_INFO_LAYOUT { > + U32 InformationLength; /* 0x00 */ > + U8 DriverSignature[12]; /* 0x04 */ > + U8 OsName[16]; /* 0x10 */ > + U8 OsVersion[12]; /* 0x20 */ > + U8 DriverName[20]; /* 0x2C */ > + U8 DriverVersion[32]; /* 0x40 */ > + U8 DriverReleaseDate[20]; /* 0x60 */ > + U32 DriverCapabilities; /* 0x74 */ > +} MPI3_DRIVER_INFO_LAYOUT, MPI3_POINTER PTR_MPI3_DRIVER_INFO_LAYOUT, > + Mpi3DriverInfoLayout_t, MPI3_POINTER pMpi3DriverInfoLayout_t; > + > +/***************************************************************************** > + * IOCFacts Request Message * > + ****************************************************************************/ > +typedef struct _MPI3_IOC_FACTS_REQUEST { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U16 Reserved0A; /* 0x0A */ > + U32 Reserved0C; /* 0x0C */ > + MPI3_SGE_UNION SGL; /* 0x10 */ > +} MPI3_IOC_FACTS_REQUEST, MPI3_POINTER PTR_MPI3_IOC_FACTS_REQUEST, > + Mpi3IOCFactsRequest_t, MPI3_POINTER pMpi3IOCFactsRequest_t; > + > +/***************************************************************************** > + * IOCFacts Data * > + ****************************************************************************/ > +typedef struct _MPI3_IOC_FACTS_DATA { > + U16 IOCFactsDataLength; /* 0x00 */ > + U16 Reserved02; /* 0x02 */ > + MPI3_VERSION_UNION MPIVersion; /* 0x04 */ > + MPI3_COMP_IMAGE_VERSION FWVersion; /* 0x08 */ > + U32 IOCCapabilities; /* 0x10 */ > + U8 IOCNumber; /* 0x14 */ > + U8 WhoInit; /* 0x15 */ > + U16 MaxMSIxVectors; /* 0x16 */ > + U16 MaxOutstandingRequest; /* 0x18 */ > + U16 ProductID; /* 0x1A */ > + U16 IOCRequestFrameSize; /* 0x1C */ > + U16 ReplyFrameSize; /* 0x1E */ > + U16 IOCExceptions; /* 0x20 */ > + U16 MaxPersistentID; /* 0x22 */ > + U8 SGEModifierMask; /* 0x24 */ > + U8 SGEModifierValue; /* 0x25 */ > + U8 SGEModifierShift; /* 0x26 */ > + U8 ProtocolFlags; /* 0x27 */ > + U16 MaxSASInitiators; /* 0x28 */ > + U16 MaxSASTargets; /* 0x2A */ > + U16 MaxSASExpanders; /* 0x2C */ > + U16 MaxEnclosures; /* 0x2E */ > + U16 MinDevHandle; /* 0x30 */ > + U16 MaxDevHandle; /* 0x32 */ > + U16 MaxPCIeSwitches; /* 0x34 */ > + U16 MaxNVMe; /* 0x36 */ > + U16 MaxPDs; /* 0x38 */ > + U16 MaxVDs; /* 0x3A */ > + U16 MaxHostPDs; /* 0x3C */ > + U16 MaxAdvancedHostPDs; /* 0x3E */ > + U16 MaxRAIDPDs; /* 0x40 */ > + U16 MaxPostedCmdBuffers; /* 0x42 */ > + U32 Flags; /* 0x44 */ > + U16 MaxOperationalRequestQueues; /* 0x48 */ > + U16 MaxOperationalReplyQueues; /* 0x4A */ > + U16 ShutdownTimeout; /* 0x4C */ > + U16 Reserved4E; /* 0x4E */ > + U32 DiagTraceSize; /* 0x50 */ > + U32 DiagFwSize; /* 0x54 */ > +} MPI3_IOC_FACTS_DATA, MPI3_POINTER PTR_MPI3_IOC_FACTS_DATA, > + Mpi3IOCFactsData_t, MPI3_POINTER pMpi3IOCFactsData_t; > + > +/**** Defines for the IOCCapabilities field ****/ > +#define MPI3_IOCFACTS_CAPABILITY_ADVANCED_HOST_PD (0x00000010) > +#define MPI3_IOCFACTS_CAPABILITY_RAID_CAPABLE (0x00000008) > +#define MPI3_IOCFACTS_CAPABILITY_COALESCE_CTRL_GRAN_MASK (0x00000001) > +#define MPI3_IOCFACTS_CAPABILITY_COALESCE_CTRL_IOC_GRAN (0x00000000) > +#define MPI3_IOCFACTS_CAPABILITY_COALESCE_CTRL_REPLY_Q_GRAN (0x00000001) > + > +/**** WhoInit values are defined under IOCInit Request Message definition ****/ > + > +/**** Defines for the ProductID field ****/ > +#define MPI3_IOCFACTS_PID_TYPE_MASK (0xF000) > +#define MPI3_IOCFACTS_PID_TYPE_SHIFT (12) > +#define MPI3_IOCFACTS_PID_PRODUCT_MASK (0x0F00) > +#define MPI3_IOCFACTS_PID_PRODUCT_SHIFT (8) > +#define MPI3_IOCFACTS_PID_FAMILY_MASK (0x00FF) > +#define MPI3_IOCFACTS_PID_FAMILY_SHIFT (0) > + > +/**** Defines for the IOCExceptions field ****/ > +#define MPI3_IOCFACTS_EXCEPT_SAFE_MODE (0x0800) > +#define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_MASK (0x0700) > +#define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_NONE (0x0000) > +#define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_LOCAL_VIA_RAID (0x0100) > +#define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_LOCAL_VIA_OOB (0x0200) > +#define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_EXT_VIA_RAID (0x0300) > +#define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_EXT_VIA_OOB (0x0400) > +#define MPI3_IOCFACTS_EXCEPT_PCIE_DISABLED (0x0080) > +#define MPI3_IOCFACTS_EXCEPT_PARTIAL_MEMORY_FAILURE (0x0040) > +#define MPI3_IOCFACTS_EXCEPT_MANUFACT_CHECKSUM_FAIL (0x0020) > +#define MPI3_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0010) > +#define MPI3_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0008) > +#define MPI3_IOCFACTS_EXCEPT_BOOTSTAT_MASK (0x0001) > +#define MPI3_IOCFACTS_EXCEPT_BOOTSTAT_PRIMARY (0x0000) > +#define MPI3_IOCFACTS_EXCEPT_BOOTSTAT_SECONDARY (0x0001) > + > +/**** Defines for the ProtocolFlags field ****/ > +#define MPI3_IOCFACTS_PROTOCOL_SAS (0x0010) > +#define MPI3_IOCFACTS_PROTOCOL_SATA (0x0008) > +#define MPI3_IOCFACTS_PROTOCOL_NVME (0x0004) > +#define MPI3_IOCFACTS_PROTOCOL_SCSI_INITIATOR (0x0002) > +#define MPI3_IOCFACTS_PROTOCOL_SCSI_TARGET (0x0001) > + > +/**** Defines for the Flags field ****/ > +#define MPI3_IOCFACTS_FLAGS_SIGNED_NVDATA_REQUIRED (0x00010000) > +#define MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK (0x0000FF00) > +#define MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT (8) > +#define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_MASK (0x00000030) > +#define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_NOT_STARTED (0x00000000) > +#define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_IN_PROGRESS (0x00000010) > +#define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_COMPLETE (0x00000020) > +#define MPI3_IOCFACTS_FLAGS_PERSONALITY_MASK (0x0000000F) > +#define MPI3_IOCFACTS_FLAGS_PERSONALITY_EHBA (0x00000000) > +#define MPI3_IOCFACTS_FLAGS_PERSONALITY_RAID_DDR (0x00000002) > + > + > +/***************************************************************************** > + * Management Passthrough Request Message * > + ****************************************************************************/ > +typedef struct _MPI3_MGMT_PASSTHROUGH_REQUEST { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U16 Reserved0A; /* 0x0A */ > + U32 Reserved0C[5]; /* 0x0C */ > + MPI3_SGE_UNION CommandSGL; /* 0x20 */ > + MPI3_SGE_UNION ResponseSGL; /* 0x30 */ > +} MPI3_MGMT_PASSTHROUGH_REQUEST, MPI3_POINTER PTR_MPI3_MGMT_PASSTHROUGH_REQUEST, > + Mpi3MgmtPassthroughRequest_t, MPI3_POINTER pMpi3MgmtPassthroughRequest_t; > + > +/***************************************************************************** > + * CreateRequestQueue Request Message * > + ****************************************************************************/ > +typedef struct _MPI3_CREATE_REQUEST_QUEUE_REQUEST { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U8 Flags; /* 0x0A */ > + U8 Burst; /* 0x0B */ > + U16 Size; /* 0x0C */ > + U16 QueueID; /* 0x0E */ > + U16 ReplyQueueID; /* 0x10 */ > + U16 Reserved12; /* 0x12 */ > + U32 Reserved14; /* 0x14 */ > + U64 BaseAddress; /* 0x18 */ > +} MPI3_CREATE_REQUEST_QUEUE_REQUEST, MPI3_POINTER PTR_MPI3_CREATE_REQUEST_QUEUE_REQUEST, > + Mpi3CreateRequestQueueRequest_t, MPI3_POINTER pMpi3CreateRequestQueueRequest_t; > + > +/**** Defines for the Flags field ****/ > +#define MPI3_CREATE_REQUEST_QUEUE_FLAGS_SEGMENTED_MASK (0x80) > +#define MPI3_CREATE_REQUEST_QUEUE_FLAGS_SEGMENTED_SEGMENTED (0x80) > +#define MPI3_CREATE_REQUEST_QUEUE_FLAGS_SEGMENTED_CONTIGUOUS (0x00) > + > + > +/***************************************************************************** > + * DeleteRequestQueue Request Message * > + ****************************************************************************/ > +typedef struct _MPI3_DELETE_REQUEST_QUEUE_REQUEST { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U16 QueueID; /* 0x0A */ > +} MPI3_DELETE_REQUEST_QUEUE_REQUEST, MPI3_POINTER PTR_MPI3_DELETE_REQUEST_QUEUE_REQUEST, > + Mpi3DeleteRequestQueueRequest_t, MPI3_POINTER pMpi3DeleteRequestQueueRequest_t; > + > + > +/***************************************************************************** > + * CreateReplyQueue Request Message * > + ****************************************************************************/ > +typedef struct _MPI3_CREATE_REPLY_QUEUE_REQUEST { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U8 Flags; /* 0x0A */ > + U8 Reserved0B; /* 0x0B */ > + U16 Size; /* 0x0C */ > + U16 QueueID; /* 0x0E */ > + U16 MSIxIndex; /* 0x10 */ > + U16 Reserved12; /* 0x12 */ > + U32 Reserved14; /* 0x14 */ > + U64 BaseAddress; /* 0x18 */ > +} MPI3_CREATE_REPLY_QUEUE_REQUEST, MPI3_POINTER PTR_MPI3_CREATE_REPLY_QUEUE_REQUEST, > + Mpi3CreateReplyQueueRequest_t, MPI3_POINTER pMpi3CreateReplyQueueRequest_t; > + > +/**** Defines for the Flags field ****/ > +#define MPI3_CREATE_REPLY_QUEUE_FLAGS_SEGMENTED_MASK (0x80) > +#define MPI3_CREATE_REPLY_QUEUE_FLAGS_SEGMENTED_SEGMENTED (0x80) > +#define MPI3_CREATE_REPLY_QUEUE_FLAGS_SEGMENTED_CONTIGUOUS (0x00) > +#define MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_MASK (0x01) > +#define MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_DISABLE (0x00) > +#define MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_ENABLE (0x01) > + > + > +/***************************************************************************** > + * DeleteReplyQueue Request Message * > + ****************************************************************************/ > +typedef struct _MPI3_DELETE_REPLY_QUEUE_REQUEST { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U16 QueueID; /* 0x0A */ > +} MPI3_DELETE_REPLY_QUEUE_REQUEST, MPI3_POINTER PTR_MPI3_DELETE_REPLY_QUEUE_REQUEST, > + Mpi3DeleteReplyQueueRequest_t, MPI3_POINTER pMpi3DeleteReplyQueueRequest_t; > + > + > +/***************************************************************************** > + * PortEnable Request Message * > + ****************************************************************************/ > +typedef struct _MPI3_PORT_ENABLE_REQUEST { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U16 Reserved0A; /* 0x0A */ > +} MPI3_PORT_ENABLE_REQUEST, MPI3_POINTER PTR_MPI3_PORT_ENABLE_REQUEST, > + Mpi3PortEnableRequest_t, MPI3_POINTER pMpi3PortEnableRequest_t; > + > + > +/***************************************************************************** > + * IOC Events and Event Management * > + ****************************************************************************/ > +#define MPI3_EVENT_LOG_DATA (0x01) > +#define MPI3_EVENT_CHANGE (0x02) > +#define MPI3_EVENT_GPIO_INTERRUPT (0x04) > +#define MPI3_EVENT_TEMP_THRESHOLD (0x05) > +#define MPI3_EVENT_CABLE_MGMT (0x06) > +#define MPI3_EVENT_DEVICE_ADDED (0x07) > +#define MPI3_EVENT_DEVICE_INFO_CHANGED (0x08) > +#define MPI3_EVENT_PREPARE_FOR_RESET (0x09) > +#define MPI3_EVENT_COMP_IMAGE_ACT_START (0x0A) > +#define MPI3_EVENT_ENCL_DEVICE_ADDED (0x0B) > +#define MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE (0x0C) > +#define MPI3_EVENT_DEVICE_STATUS_CHANGE (0x0D) > +#define MPI3_EVENT_ENERGY_PACK_CHANGE (0x0E) > +#define MPI3_EVENT_SAS_DISCOVERY (0x11) > +#define MPI3_EVENT_SAS_BROADCAST_PRIMITIVE (0x12) > +#define MPI3_EVENT_SAS_NOTIFY_PRIMITIVE (0x13) > +#define MPI3_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x14) > +#define MPI3_EVENT_SAS_INIT_TABLE_OVERFLOW (0x15) > +#define MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST (0x16) > +#define MPI3_EVENT_SAS_PHY_COUNTER (0x18) > +#define MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR (0x19) > +#define MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST (0x20) > +#define MPI3_EVENT_PCIE_ENUMERATION (0x22) > +#define MPI3_EVENT_HARD_RESET_RECEIVED (0x40) > +#define MPI3_EVENT_MIN_PRODUCT_SPECIFIC (0x60) > +#define MPI3_EVENT_MAX_PRODUCT_SPECIFIC (0x7F) > + > + > +/***************************************************************************** > + * Event Notification Request Message * > + ****************************************************************************/ > +#define MPI3_EVENT_NOTIFY_EVENTMASK_WORDS (4) > + > +typedef struct _MPI3_EVENT_NOTIFICATION_REQUEST { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U16 Reserved0A; /* 0x0A */ > + U16 SASBroadcastPrimitiveMasks; /* 0x0C */ > + U16 SASNotifyPrimitiveMasks; /* 0x0E */ > + U32 EventMasks[MPI3_EVENT_NOTIFY_EVENTMASK_WORDS]; /* 0x10 */ > +} MPI3_EVENT_NOTIFICATION_REQUEST, MPI3_POINTER PTR_MPI3_EVENT_NOTIFICATION_REQUEST, > + Mpi3EventNotificationRequest_t, MPI3_POINTER pMpi3EventNotificationRequest_t; > + > +/**** Defines for the SASBroadcastPrimitiveMasks field - use MPI3_EVENT_PRIMITIVE_ values ****/ > + > +/**** Defines for the SASNotifyPrimitiveMasks field - use MPI3_EVENT_NOTIFY_ values ****/ > + > +/**** Defines for the EventMasks field - use MPI3_EVENT_ values ****/ > + > +/***************************************************************************** > + * Event Notification Reply Message * > + ****************************************************************************/ > +typedef struct _MPI3_EVENT_NOTIFICATION_REPLY { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 IOCUseOnly08; /* 0x08 */ > + U16 IOCStatus; /* 0x0A */ > + U32 IOCLogInfo; /* 0x0C */ > + U8 EventDataLength; /* 0x10 */ > + U8 Event; /* 0x11 */ > + U16 IOCChangeCount; /* 0x12 */ > + U32 EventContext; /* 0x14 */ > + U32 EventData[1]; /* 0x18 */ > +} MPI3_EVENT_NOTIFICATION_REPLY, MPI3_POINTER PTR_MPI3_EVENT_NOTIFICATION_REPLY, > + Mpi3EventNotificationReply_t, MPI3_POINTER pMpi3EventNotificationReply_t; > + > +/**** Defines for the MsgFlags field ****/ > +#define MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_MASK (0x01) > +#define MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_REQUIRED (0x01) > +#define MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_NOT_REQUIRED (0x00) > +#define MPI3_EVENT_NOTIFY_MSGFLAGS_EVENT_ORIGINALITY_MASK (0x02) > +#define MPI3_EVENT_NOTIFY_MSGFLAGS_EVENT_ORIGINALITY_ORIGINAL (0x00) > +#define MPI3_EVENT_NOTIFY_MSGFLAGS_EVENT_ORIGINALITY_REPLAY (0x02) > + > +/**** Defines for the Event field - use MPI3_EVENT_ values ****/ > + > + > +/***************************************************************************** > + * GPIO Interrupt Event * > + ****************************************************************************/ > +typedef struct _MPI3_EVENT_DATA_GPIO_INTERRUPT { > + U8 GPIONum; /* 0x00 */ > + U8 Reserved01[3]; /* 0x01 */ > +} MPI3_EVENT_DATA_GPIO_INTERRUPT, MPI3_POINTER PTR_MPI3_EVENT_DATA_GPIO_INTERRUPT, > + Mpi3EventDataGpioInterrupt_t, MPI3_POINTER pMpi3EventDataGpioInterrupt_t; > + > + > +/***************************************************************************** > + * Temperature Threshold Event * > + ****************************************************************************/ > +typedef struct _MPI3_EVENT_DATA_TEMP_THRESHOLD { > + U16 Status; /* 0x00 */ > + U8 SensorNum; /* 0x02 */ > + U8 Reserved03; /* 0x03 */ > + U16 CurrentTemperature; /* 0x04 */ > + U16 Reserved06; /* 0x06 */ > + U32 Reserved08; /* 0x08 */ > + U32 Reserved0C; /* 0x0C */ > +} MPI3_EVENT_DATA_TEMP_THRESHOLD, MPI3_POINTER PTR_MPI3_EVENT_DATA_TEMP_THRESHOLD, > + Mpi3EventDataTempThreshold_t, MPI3_POINTER pMpi3EventDataTempThreshold_t; > + > +/**** Defines for the Status field ****/ > +#define MPI3_EVENT_TEMP_THRESHOLD_STATUS_THRESHOLD3_EXCEEDED (0x0008) > +#define MPI3_EVENT_TEMP_THRESHOLD_STATUS_THRESHOLD2_EXCEEDED (0x0004) > +#define MPI3_EVENT_TEMP_THRESHOLD_STATUS_THRESHOLD1_EXCEEDED (0x0002) > +#define MPI3_EVENT_TEMP_THRESHOLD_STATUS_THRESHOLD0_EXCEEDED (0x0001) > + > + > +/***************************************************************************** > + * Cable Management Event * > + ****************************************************************************/ > +typedef struct _MPI3_EVENT_DATA_CABLE_MANAGEMENT { > + U32 ActiveCablePowerRequirement; /* 0x00 */ > + U8 Status; /* 0x04 */ > + U8 ReceptacleID; /* 0x05 */ > + U16 Reserved06; /* 0x06 */ > +} MPI3_EVENT_DATA_CABLE_MANAGEMENT, MPI3_POINTER PTR_MPI3_EVENT_DATA_CABLE_MANAGEMENT, > + Mpi3EventDataCableManagement_t, MPI3_POINTER pMpi3EventDataCableManagement_t; > + > +/**** Defines for the ActiveCablePowerRequirement field ****/ > +#define MPI3_EVENT_CABLE_MGMT_ACT_CABLE_PWR_INVALID (0xFFFFFFFF) > + > +/**** Defines for the Status field ****/ > +#define MPI3_EVENT_CABLE_MGMT_STATUS_INSUFFICIENT_POWER (0x00) > +#define MPI3_EVENT_CABLE_MGMT_STATUS_PRESENT (0x01) > +#define MPI3_EVENT_CABLE_MGMT_STATUS_DEGRADED (0x02) > + > + > +/***************************************************************************** > + * Event Ack Request Message * > + ****************************************************************************/ > +typedef struct _MPI3_EVENT_ACK_REQUEST { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U16 Reserved0A; /* 0x0A */ > + U8 Event; /* 0x0C */ > + U8 Reserved0D[3]; /* 0x0D */ > + U32 EventContext; /* 0x10 */ > +} MPI3_EVENT_ACK_REQUEST, MPI3_POINTER PTR_MPI3_EVENT_ACK_REQUEST, > + Mpi3EventAckRequest_t, MPI3_POINTER pMpi3EventAckRequest_t; > + > +/**** Defines for the Event field - use MPI3_EVENT_ values ****/ > + > + > +/***************************************************************************** > + * Prepare for Reset Event * > + ****************************************************************************/ > +typedef struct _MPI3_EVENT_DATA_PREPARE_FOR_RESET { > + U8 ReasonCode; /* 0x00 */ > + U8 Reserved01; /* 0x01 */ > + U16 Reserved02; /* 0x02 */ > +} MPI3_EVENT_DATA_PREPARE_FOR_RESET, MPI3_POINTER PTR_MPI3_EVENT_DATA_PREPARE_FOR_RESET, > + Mpi3EventDataPrepareForReset_t, MPI3_POINTER pMpi3EventDataPrepareForReset_t; > + > +/**** Defines for the ReasonCode field ****/ > +#define MPI3_EVENT_PREPARE_RESET_RC_START (0x01) > +#define MPI3_EVENT_PREPARE_RESET_RC_ABORT (0x02) > + > + > +/***************************************************************************** > + * Component Image Activation Start Event * > + ****************************************************************************/ > +typedef struct _MPI3_EVENT_DATA_COMP_IMAGE_ACTIVATION { > + U32 Reserved00; /* 0x00 */ > +} MPI3_EVENT_DATA_COMP_IMAGE_ACTIVATION, MPI3_POINTER PTR_MPI3_EVENT_DATA_COMP_IMAGE_ACTIVATION, > + Mpi3EventDataCompImageActivation, MPI3_POINTER pMpi3EventDataCompImageActivation; > + > +/***************************************************************************** > + * Device Added Event * > + ****************************************************************************/ > +/* > + * The Device Added Event Data is exactly the same as Device Page 0 data > + * (including the Configuration Page header). So, please use/refer to > + * MPI3_DEVICE_PAGE0 structure for Device Added Event data. > + */ > + > +/**************************************************************************** > + * Device Info Changed Event * > + ****************************************************************************/ > +/* > + * The Device Info Changed Event Data is exactly the same as Device Page 0 data > + * (including the Configuration Page header). So, please use/refer to > + * MPI3_DEVICE_PAGE0 structure for Device Added Event data. > + */ > + > +/***************************************************************************** > + * Device Status Change Event * > + ****************************************************************************/ > +typedef struct _MPI3_EVENT_DATA_DEVICE_STATUS_CHANGE { > + U16 TaskTag; /* 0x00 */ > + U8 ReasonCode; /* 0x02 */ > + U8 IOUnitPort; /* 0x03 */ > + U16 ParentDevHandle; /* 0x04 */ > + U16 DevHandle; /* 0x06 */ > + U64 WWID; /* 0x08 */ > + U8 LUN[8]; /* 0x10 */ > +} MPI3_EVENT_DATA_DEVICE_STATUS_CHANGE, MPI3_POINTER PTR_MPI3_EVENT_DATA_DEVICE_STATUS_CHANGE, > + Mpi3EventDataDeviceStatusChange_t, MPI3_POINTER pMpi3EventDataDeviceStatusChange_t; > + > +/**** Defines for the ReasonCode field ****/ > +#define MPI3_EVENT_DEV_STAT_RC_MOVED (0x01) > +#define MPI3_EVENT_DEV_STAT_RC_HIDDEN (0x02) > +#define MPI3_EVENT_DEV_STAT_RC_NOT_HIDDEN (0x03) > +#define MPI3_EVENT_DEV_STAT_RC_ASYNC_NOTIFICATION (0x04) > +#define MPI3_EVENT_DEV_STAT_RC_INT_DEVICE_RESET_STRT (0x20) > +#define MPI3_EVENT_DEV_STAT_RC_INT_DEVICE_RESET_CMP (0x21) > +#define MPI3_EVENT_DEV_STAT_RC_INT_TASK_ABORT_STRT (0x22) > +#define MPI3_EVENT_DEV_STAT_RC_INT_TASK_ABORT_CMP (0x23) > +#define MPI3_EVENT_DEV_STAT_RC_INT_IT_NEXUS_RESET_STRT (0x24) > +#define MPI3_EVENT_DEV_STAT_RC_INT_IT_NEXUS_RESET_CMP (0x25) > +#define MPI3_EVENT_DEV_STAT_RC_PCIE_HOT_RESET_FAILED (0x30) > +#define MPI3_EVENT_DEV_STAT_RC_EXPANDER_REDUCED_FUNC_STRT (0x40) > +#define MPI3_EVENT_DEV_STAT_RC_EXPANDER_REDUCED_FUNC_CMP (0x41) > +#define MPI3_EVENT_DEV_STAT_RC_VD_NOT_RESPONDING (0x50) > + > +/***************************************************************************** > + * Energy Pack Change Event * > + ****************************************************************************/ > +typedef struct _MPI3_EVENT_DATA_ENERGY_PACK_CHANGE { > + U32 Reserved00; /* 0x00 */ > + U16 ShutdownTimeout; /* 0x04 */ > + U16 Reserved06; /* 0x06 */ > +} MPI3_EVENT_DATA_ENERGY_PACK_CHANGE, MPI3_POINTER PTR_MPI3_EVENT_DATA_ENERGY_PACK_CHANGE, > + Mpi3EventDataEnergyPackChange_t, MPI3_POINTER pMpi3EventDataEnergyPackChange_t; > + > +/***************************************************************************** > + * SAS Discovery Event * > + ****************************************************************************/ > +typedef struct _MPI3_EVENT_DATA_SAS_DISCOVERY { > + U8 Flags; /* 0x00 */ > + U8 ReasonCode; /* 0x01 */ > + U8 IOUnitPort; /* 0x02 */ > + U8 Reserved03; /* 0x03 */ > + U32 DiscoveryStatus; /* 0x04 */ > +} MPI3_EVENT_DATA_SAS_DISCOVERY, MPI3_POINTER PTR_MPI3_EVENT_DATA_SAS_DISCOVERY, > + Mpi3EventDataSasDiscovery_t, MPI3_POINTER pMpi3EventDataSasDiscovery_t; > + > +/**** Defines for the Flags field ****/ > +#define MPI3_EVENT_SAS_DISC_FLAGS_DEVICE_CHANGE (0x02) > +#define MPI3_EVENT_SAS_DISC_FLAGS_IN_PROGRESS (0x01) > + > +/**** Defines for the ReasonCode field ****/ > +#define MPI3_EVENT_SAS_DISC_RC_STARTED (0x01) > +#define MPI3_EVENT_SAS_DISC_RC_COMPLETED (0x02) > + > +/**** Defines for the DiscoveryStatus field ****/ > +#define MPI3_SAS_DISC_STATUS_MAX_ENCLOSURES_EXCEED (0x80000000) > +#define MPI3_SAS_DISC_STATUS_MAX_EXPANDERS_EXCEED (0x40000000) > +#define MPI3_SAS_DISC_STATUS_MAX_DEVICES_EXCEED (0x20000000) > +#define MPI3_SAS_DISC_STATUS_MAX_TOPO_PHYS_EXCEED (0x10000000) > +#define MPI3_SAS_DISC_STATUS_MULTIPLE_DEVICES_IN_SLOT (0x00004000) > +#define MPI3_SAS_DISC_STATUS_SLOT_COUNT_MISMATCH (0x00002000) > +#define MPI3_SAS_DISC_STATUS_TOO_MANY_SLOTS (0x00001000) > +#define MPI3_SAS_DISC_STATUS_EXP_MULTI_SUBTRACTIVE (0x00000800) > +#define MPI3_SAS_DISC_STATUS_MULTI_PORT_DOMAIN (0x00000400) > +#define MPI3_SAS_DISC_STATUS_TABLE_TO_SUBTRACTIVE_LINK (0x00000200) > +#define MPI3_SAS_DISC_STATUS_UNSUPPORTED_DEVICE (0x00000100) > +#define MPI3_SAS_DISC_STATUS_TABLE_LINK (0x00000080) > +#define MPI3_SAS_DISC_STATUS_SUBTRACTIVE_LINK (0x00000040) > +#define MPI3_SAS_DISC_STATUS_SMP_CRC_ERROR (0x00000020) > +#define MPI3_SAS_DISC_STATUS_SMP_FUNCTION_FAILED (0x00000010) > +#define MPI3_SAS_DISC_STATUS_SMP_TIMEOUT (0x00000008) > +#define MPI3_SAS_DISC_STATUS_MULTIPLE_PORTS (0x00000004) > +#define MPI3_SAS_DISC_STATUS_INVALID_SAS_ADDRESS (0x00000002) > +#define MPI3_SAS_DISC_STATUS_LOOP_DETECTED (0x00000001) > + > + > +/***************************************************************************** > + * SAS Broadcast Primitive Event * > + ****************************************************************************/ > +typedef struct _MPI3_EVENT_DATA_SAS_BROADCAST_PRIMITIVE { > + U8 PhyNum; /* 0x00 */ > + U8 IOUnitPort; /* 0x01 */ > + U8 PortWidth; /* 0x02 */ > + U8 Primitive; /* 0x03 */ > +} MPI3_EVENT_DATA_SAS_BROADCAST_PRIMITIVE, MPI3_POINTER PTR_MPI3_EVENT_DATA_SAS_BROADCAST_PRIMITIVE, > + Mpi3EventDataSasBroadcastPrimitive_t, MPI3_POINTER pMpi3EventDataSasBroadcastPrimitive_t; > + > +/**** Defines for the Primitive field ****/ > +#define MPI3_EVENT_BROADCAST_PRIMITIVE_CHANGE (0x01) > +#define MPI3_EVENT_BROADCAST_PRIMITIVE_SES (0x02) > +#define MPI3_EVENT_BROADCAST_PRIMITIVE_EXPANDER (0x03) > +#define MPI3_EVENT_BROADCAST_PRIMITIVE_ASYNCHRONOUS_EVENT (0x04) > +#define MPI3_EVENT_BROADCAST_PRIMITIVE_RESERVED3 (0x05) > +#define MPI3_EVENT_BROADCAST_PRIMITIVE_RESERVED4 (0x06) > +#define MPI3_EVENT_BROADCAST_PRIMITIVE_CHANGE0_RESERVED (0x07) > +#define MPI3_EVENT_BROADCAST_PRIMITIVE_CHANGE1_RESERVED (0x08) > + > + > +/***************************************************************************** > + * SAS Notify Primitive Event * > + ****************************************************************************/ > +typedef struct _MPI3_EVENT_DATA_SAS_NOTIFY_PRIMITIVE { > + U8 PhyNum; /* 0x00 */ > + U8 IOUnitPort; /* 0x01 */ > + U8 Reserved02; /* 0x02 */ > + U8 Primitive; /* 0x03 */ > +} MPI3_EVENT_DATA_SAS_NOTIFY_PRIMITIVE, MPI3_POINTER PTR_MPI3_EVENT_DATA_SAS_NOTIFY_PRIMITIVE, > + Mpi3EventDataSasNotifyPrimitive_t, MPI3_POINTER pMpi3EventDataSasNotifyPrimitive_t; > + > +/**** Defines for the Primitive field ****/ > +#define MPI3_EVENT_NOTIFY_PRIMITIVE_ENABLE_SPINUP (0x01) > +#define MPI3_EVENT_NOTIFY_PRIMITIVE_POWER_LOSS_EXPECTED (0x02) > +#define MPI3_EVENT_NOTIFY_PRIMITIVE_RESERVED1 (0x03) > +#define MPI3_EVENT_NOTIFY_PRIMITIVE_RESERVED2 (0x04) > + > + > +/***************************************************************************** > + * SAS Topology Change List Event * > + ****************************************************************************/ > +#ifndef MPI3_EVENT_SAS_TOPO_PHY_COUNT > +#define MPI3_EVENT_SAS_TOPO_PHY_COUNT (1) > +#endif /* MPI3_EVENT_SAS_TOPO_PHY_COUNT */ > + Huh? What's this? Compile-time defaults? If so, please don't hide it in common header files; compile-time variables should be located in the actual C source files (where one has a chance of finding them...) > +typedef struct _MPI3_EVENT_SAS_TOPO_PHY_ENTRY { > + U16 AttachedDevHandle; /* 0x00 */ > + U8 LinkRate; /* 0x02 */ > + U8 Status; /* 0x03 */ > +} MPI3_EVENT_SAS_TOPO_PHY_ENTRY, MPI3_POINTER PTR_MPI3_EVENT_SAS_TOPO_PHY_ENTRY, > + Mpi3EventSasTopoPhyEntry_t, MPI3_POINTER pMpi3EventSasTopoPhyEntry_t; > + > +/**** Defines for the LinkRate field ****/ > +#define MPI3_EVENT_SAS_TOPO_LR_CURRENT_MASK (0xF0) > +#define MPI3_EVENT_SAS_TOPO_LR_CURRENT_SHIFT (4) > +#define MPI3_EVENT_SAS_TOPO_LR_PREV_MASK (0x0F) > +#define MPI3_EVENT_SAS_TOPO_LR_PREV_SHIFT (0) > +#define MPI3_EVENT_SAS_TOPO_LR_UNKNOWN_LINK_RATE (0x00) > +#define MPI3_EVENT_SAS_TOPO_LR_PHY_DISABLED (0x01) > +#define MPI3_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED (0x02) > +#define MPI3_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE (0x03) > +#define MPI3_EVENT_SAS_TOPO_LR_PORT_SELECTOR (0x04) > +#define MPI3_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS (0x05) > +#define MPI3_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY (0x06) > +#define MPI3_EVENT_SAS_TOPO_LR_RATE_6_0 (0x0A) > +#define MPI3_EVENT_SAS_TOPO_LR_RATE_12_0 (0x0B) > +#define MPI3_EVENT_SAS_TOPO_LR_RATE_22_5 (0x0C) > + > +/**** Defines for the PhyStatus field ****/ > +#define MPI3_EVENT_SAS_TOPO_PHY_STATUS_MASK (0xC0) > +#define MPI3_EVENT_SAS_TOPO_PHY_STATUS_SHIFT (6) > +#define MPI3_EVENT_SAS_TOPO_PHY_STATUS_ACCESSIBLE (0x00) > +#define MPI3_EVENT_SAS_TOPO_PHY_STATUS_NO_EXIST (0x40) > +#define MPI3_EVENT_SAS_TOPO_PHY_STATUS_VACANT (0x80) > +#define MPI3_EVENT_SAS_TOPO_PHY_RC_MASK (0x0F) > +#define MPI3_EVENT_SAS_TOPO_PHY_RC_TARG_NOT_RESPONDING (0x02) > +#define MPI3_EVENT_SAS_TOPO_PHY_RC_PHY_CHANGED (0x03) > +#define MPI3_EVENT_SAS_TOPO_PHY_RC_NO_CHANGE (0x04) > +#define MPI3_EVENT_SAS_TOPO_PHY_RC_DELAY_NOT_RESPONDING (0x05) > +#define MPI3_EVENT_SAS_TOPO_PHY_RC_RESPONDING (0x06) > + > + > +typedef struct _MPI3_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST { > + U16 EnclosureHandle; /* 0x00 */ > + U16 ExpanderDevHandle; /* 0x02 */ > + U8 NumPhys; /* 0x04 */ > + U8 Reserved05[3]; /* 0x05 */ > + U8 NumEntries; /* 0x08 */ > + U8 StartPhyNum; /* 0x09 */ > + U8 ExpStatus; /* 0x0A */ > + U8 IOUnitPort; /* 0x0B */ > + MPI3_EVENT_SAS_TOPO_PHY_ENTRY PhyEntry[MPI3_EVENT_SAS_TOPO_PHY_COUNT]; /* 0x0C */ > +} MPI3_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST, MPI3_POINTER PTR_MPI3_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST, > + Mpi3EventDataSasTopologyChangeList_t, MPI3_POINTER pMpi3EventDataSasTopologyChangeList_t; > + > +/**** Defines for the ExpStatus field ****/ > +#define MPI3_EVENT_SAS_TOPO_ES_NO_EXPANDER (0x00) > +#define MPI3_EVENT_SAS_TOPO_ES_NOT_RESPONDING (0x02) > +#define MPI3_EVENT_SAS_TOPO_ES_RESPONDING (0x03) > +#define MPI3_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING (0x04) > + > +/***************************************************************************** > + * SAS PHY Counter Event * > + ****************************************************************************/ > +typedef struct _MPI3_EVENT_DATA_SAS_PHY_COUNTER { > + U64 TimeStamp; /* 0x00 */ > + U32 Reserved08; /* 0x08 */ > + U8 PhyEventCode; /* 0x0C */ > + U8 PhyNum; /* 0x0D */ > + U16 Reserved0E; /* 0x0E */ > + U32 PhyEventInfo; /* 0x10 */ > + U8 CounterType; /* 0x14 */ > + U8 ThresholdWindow; /* 0x15 */ > + U8 TimeUnits; /* 0x16 */ > + U8 Reserved17; /* 0x17 */ > + U32 EventThreshold; /* 0x18 */ > + U16 ThresholdFlags; /* 0x1C */ > + U16 Reserved1E; /* 0x1E */ > +} MPI3_EVENT_DATA_SAS_PHY_COUNTER, MPI3_POINTER PTR_MPI3_EVENT_DATA_SAS_PHY_COUNTER, > + Mpi3EventDataSasPhyCounter_t, MPI3_POINTER pMpi3EventDataSasPhyCounter_t; > + > +/**** Defines for the PhyEventCode field - use MPI3_SASPHY3_EVENT_CODE_ defines ****/ > + > +/**** Defines for the CounterType field - use MPI3_SASPHY3_COUNTER_TYPE_ defines ****/ > + > +/**** Defines for the TimeUnits field - use MPI3_SASPHY3_TIME_UNITS_ defines ****/ > + > +/**** Defines for the ThresholdFlags field - use MPI3_SASPHY3_TFLAGS_ defines ****/ > + I do hope these gets filled in later ... > + > +/***************************************************************************** > + * SAS Device Discovery Error Event * > + ****************************************************************************/ > +typedef struct _MPI3_EVENT_DATA_SAS_DEVICE_DISC_ERR { > + U16 DevHandle; /* 0x00 */ > + U8 ReasonCode; /* 0x02 */ > + U8 IOUnitPort; /* 0x03 */ > + U32 Reserved04; /* 0x04 */ > + U64 SASAddress; /* 0x08 */ > +} MPI3_EVENT_DATA_SAS_DEVICE_DISC_ERR, MPI3_POINTER PTR_MPI3_EVENT_DATA_SAS_DEVICE_DISC_ERR, > + Mpi3EventDataSasDeviceDiscErr_t, MPI3_POINTER pMpi3EventDataSasDeviceDiscErr_t; > + > +/**** Defines for the ReasonCode field ****/ > +#define MPI3_EVENT_SAS_DISC_ERR_RC_SMP_FAILED (0x01) > +#define MPI3_EVENT_SAS_DISC_ERR_RC_SMP_TIMEOUT (0x02) > + > +/***************************************************************************** > + * PCIe Enumeration Event * > + ****************************************************************************/ > +typedef struct _MPI3_EVENT_DATA_PCIE_ENUMERATION { > + U8 Flags; /* 0x00 */ > + U8 ReasonCode; /* 0x01 */ > + U8 IOUnitPort; /* 0x02 */ > + U8 Reserved03; /* 0x03 */ > + U32 EnumerationStatus; /* 0x04 */ > +} MPI3_EVENT_DATA_PCIE_ENUMERATION, MPI3_POINTER PTR_MPI3_EVENT_DATA_PCIE_ENUMERATION, > + Mpi3EventDataPcieEnumeration_t, MPI3_POINTER pMpi3EventDataPcieEnumeration_t; > + > +/**** Defines for the Flags field ****/ > +#define MPI3_EVENT_PCIE_ENUM_FLAGS_DEVICE_CHANGE (0x02) > +#define MPI3_EVENT_PCIE_ENUM_FLAGS_IN_PROGRESS (0x01) > + > +/**** Defines for the ReasonCode field ****/ > +#define MPI3_EVENT_PCIE_ENUM_RC_STARTED (0x01) > +#define MPI3_EVENT_PCIE_ENUM_RC_COMPLETED (0x02) > + > +/**** Defines for the EnumerationStatus field ****/ > +#define MPI3_EVENT_PCIE_ENUM_ES_MAX_SWITCH_DEPTH_EXCEED (0x80000000) > +#define MPI3_EVENT_PCIE_ENUM_ES_MAX_SWITCHES_EXCEED (0x40000000) > +#define MPI3_EVENT_PCIE_ENUM_ES_MAX_DEVICES_EXCEED (0x20000000) > +#define MPI3_EVENT_PCIE_ENUM_ES_RESOURCES_EXHAUSTED (0x10000000) > + > + > +/***************************************************************************** > + * PCIe Topology Change List Event * > + ****************************************************************************/ > +#ifndef MPI3_EVENT_PCIE_TOPO_PORT_COUNT > +#define MPI3_EVENT_PCIE_TOPO_PORT_COUNT (1) > +#endif /* MPI3_EVENT_PCIE_TOPO_PORT_COUNT */ > + > +typedef struct _MPI3_EVENT_PCIE_TOPO_PORT_ENTRY { > + U16 AttachedDevHandle; /* 0x00 */ > + U8 PortStatus; /* 0x02 */ > + U8 Reserved03; /* 0x03 */ > + U8 CurrentPortInfo; /* 0x04 */ > + U8 Reserved05; /* 0x05 */ > + U8 PreviousPortInfo; /* 0x06 */ > + U8 Reserved07; /* 0x07 */ > +} MPI3_EVENT_PCIE_TOPO_PORT_ENTRY, MPI3_POINTER PTR_MPI3_EVENT_PCIE_TOPO_PORT_ENTRY, > + Mpi3EventPcieTopoPortEntry_t, MPI3_POINTER pMpi3EventPcieTopoPortEntry_t; > + > +/**** Defines for the PortStatus field ****/ > +#define MPI3_EVENT_PCIE_TOPO_PS_NOT_RESPONDING (0x02) > +#define MPI3_EVENT_PCIE_TOPO_PS_PORT_CHANGED (0x03) > +#define MPI3_EVENT_PCIE_TOPO_PS_NO_CHANGE (0x04) > +#define MPI3_EVENT_PCIE_TOPO_PS_DELAY_NOT_RESPONDING (0x05) > +#define MPI3_EVENT_PCIE_TOPO_PS_RESPONDING (0x06) > + > +/**** Defines for the CurrentPortInfo and PreviousPortInfo field ****/ > +#define MPI3_EVENT_PCIE_TOPO_PI_LANES_MASK (0xF0) > +#define MPI3_EVENT_PCIE_TOPO_PI_LANES_UNKNOWN (0x00) > +#define MPI3_EVENT_PCIE_TOPO_PI_LANES_1 (0x10) > +#define MPI3_EVENT_PCIE_TOPO_PI_LANES_2 (0x20) > +#define MPI3_EVENT_PCIE_TOPO_PI_LANES_4 (0x30) > +#define MPI3_EVENT_PCIE_TOPO_PI_LANES_8 (0x40) > +#define MPI3_EVENT_PCIE_TOPO_PI_LANES_16 (0x50) > + > +#define MPI3_EVENT_PCIE_TOPO_PI_RATE_MASK (0x0F) > +#define MPI3_EVENT_PCIE_TOPO_PI_RATE_UNKNOWN (0x00) > +#define MPI3_EVENT_PCIE_TOPO_PI_RATE_DISABLED (0x01) > +#define MPI3_EVENT_PCIE_TOPO_PI_RATE_2_5 (0x02) > +#define MPI3_EVENT_PCIE_TOPO_PI_RATE_5_0 (0x03) > +#define MPI3_EVENT_PCIE_TOPO_PI_RATE_8_0 (0x04) > +#define MPI3_EVENT_PCIE_TOPO_PI_RATE_16_0 (0x05) > +#define MPI3_EVENT_PCIE_TOPO_PI_RATE_32_0 (0x06) > + > +typedef struct _MPI3_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST { > + U16 EnclosureHandle; /* 0x00 */ > + U16 SwitchDevHandle; /* 0x02 */ > + U8 NumPorts; /* 0x04 */ > + U8 Reserved05[3]; /* 0x05 */ > + U8 NumEntries; /* 0x08 */ > + U8 StartPortNum; /* 0x09 */ > + U8 SwitchStatus; /* 0x0A */ > + U8 IOUnitPort; /* 0x0B */ > + U32 Reserved0C; /* 0x0C */ > + MPI3_EVENT_PCIE_TOPO_PORT_ENTRY PortEntry[MPI3_EVENT_PCIE_TOPO_PORT_COUNT]; /* 0x10 */ > +} MPI3_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST, MPI3_POINTER PTR_MPI3_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST, > + Mpi3EventDataPcieTopologyChangeList_t, MPI3_POINTER pMpi3EventDataPcieTopologyChangeList_t; > + > +/**** Defines for the SwitchStatus field ****/ > +#define MPI3_EVENT_PCIE_TOPO_SS_NO_PCIE_SWITCH (0x00) > +#define MPI3_EVENT_PCIE_TOPO_SS_NOT_RESPONDING (0x02) > +#define MPI3_EVENT_PCIE_TOPO_SS_RESPONDING (0x03) > +#define MPI3_EVENT_PCIE_TOPO_SS_DELAY_NOT_RESPONDING (0x04) > + > +/**************************************************************************** > + * Enclosure Device Added Event * > + ****************************************************************************/ > +/* > + * The Enclosure Device Added Event Data is exactly the same as Enclosure > + * Page 0 data (including the Configuration Page header). So, please > + * use/refer to MPI3_ENCLOSURE_PAGE0 structure for Enclosure Device Added > + * Event data. > + */ > + > +/**************************************************************************** > + * Enclosure Device Changed Event * > + ****************************************************************************/ > +/* > + * The Enclosure Device Change Event Data is exactly the same as Enclosure > + * Page 0 data (including the Configuration Page header). So, please > + * use/refer to MPI3_ENCLOSURE_PAGE0 structure for Enclosure Device Change > + * Event data. > + */ > + > +/***************************************************************************** > + * SAS Initiator Device Status Change Event * > + ****************************************************************************/ > +typedef struct _MPI3_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE { > + U8 ReasonCode; /* 0x00 */ > + U8 IOUnitPort; /* 0x01 */ > + U16 DevHandle; /* 0x02 */ > + U32 Reserved04; /* 0x04 */ > + U64 SASAddress; /* 0x08 */ > +} MPI3_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE, MPI3_POINTER PTR_MPI3_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE, > + Mpi3EventDataSasInitDevStatusChange_t, MPI3_POINTER pMpi3EventDataSasInitDevStatusChange_t; > + > +/**** Defines for the ReasonCode field ****/ > +#define MPI3_EVENT_SAS_INIT_RC_ADDED (0x01) > +#define MPI3_EVENT_SAS_INIT_RC_NOT_RESPONDING (0x02) > + > + > +/***************************************************************************** > + * SAS Initiator Device Table Overflow Event * > + ****************************************************************************/ > +typedef struct _MPI3_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW { > + U16 MaxInit; /* 0x00 */ > + U16 CurrentInit; /* 0x02 */ > + U32 Reserved04; /* 0x04 */ > + U64 SASAddress; /* 0x08 */ > +} MPI3_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW, MPI3_POINTER PTR_MPI3_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW, > + Mpi3EventDataSasInitTableOverflow_t, MPI3_POINTER pMpi3EventDataSasInitTableOverflow_t; > + > + > +/***************************************************************************** > + * Hard Reset Received Event * > + ****************************************************************************/ > +typedef struct _MPI3_EVENT_DATA_HARD_RESET_RECEIVED { > + U8 Reserved00; /* 0x00 */ > + U8 IOUnitPort; /* 0x01 */ > + U16 Reserved02; /* 0x02 */ > +} MPI3_EVENT_DATA_HARD_RESET_RECEIVED, MPI3_POINTER PTR_MPI3_EVENT_DATA_HARD_RESET_RECEIVED, > + Mpi3EventDataHardResetReceived_t, MPI3_POINTER pMpi3EventDataHardResetReceived_t; > + > + > +/***************************************************************************** > + * Persistent Event Logs * > + ****************************************************************************/ > + > +/**** Definitions for the Locale field ****/ > +#define MPI3_PEL_LOCALE_FLAGS_NON_BLOCKING_BOOT_EVENT (0x0200) > +#define MPI3_PEL_LOCALE_FLAGS_BLOCKING_BOOT_EVENT (0x0100) > +#define MPI3_PEL_LOCALE_FLAGS_PCIE (0x0080) > +#define MPI3_PEL_LOCALE_FLAGS_CONFIGURATION (0x0040) > +#define MPI3_PEL_LOCALE_FLAGS_CONTROLER (0x0020) > +#define MPI3_PEL_LOCALE_FLAGS_SAS (0x0010) > +#define MPI3_PEL_LOCALE_FLAGS_EPACK (0x0008) > +#define MPI3_PEL_LOCALE_FLAGS_ENCLOSURE (0x0004) > +#define MPI3_PEL_LOCALE_FLAGS_PD (0x0002) > +#define MPI3_PEL_LOCALE_FLAGS_VD (0x0001) > + > +/**** Definitions for the Class field ****/ > +#define MPI3_PEL_CLASS_DEBUG (0x00) > +#define MPI3_PEL_CLASS_PROGRESS (0x01) > +#define MPI3_PEL_CLASS_INFORMATIONAL (0x02) > +#define MPI3_PEL_CLASS_WARNING (0x03) > +#define MPI3_PEL_CLASS_CRITICAL (0x04) > +#define MPI3_PEL_CLASS_FATAL (0x05) > +#define MPI3_PEL_CLASS_FAULT (0x06) > + > +/**** Definitions for the ClearType field ****/ > +#define MPI3_PEL_CLEARTYPE_CLEAR (0x00) > + > +/**** Definitions for the WaitTime field ****/ > +#define MPI3_PEL_WAITTIME_INFINITE_WAIT (0x00) > + > +/**** Definitions for the Action field ****/ > +#define MPI3_PEL_ACTION_GET_SEQNUM (0x01) > +#define MPI3_PEL_ACTION_MARK_CLEAR (0x02) > +#define MPI3_PEL_ACTION_GET_LOG (0x03) > +#define MPI3_PEL_ACTION_GET_COUNT (0x04) > +#define MPI3_PEL_ACTION_WAIT (0x05) > +#define MPI3_PEL_ACTION_ABORT (0x06) > +#define MPI3_PEL_ACTION_GET_PRINT_STRINGS (0x07) > +#define MPI3_PEL_ACTION_ACKNOWLEDGE (0x08) > + > +/**** Definitions for the LogStatus field ****/ > +#define MPI3_PEL_STATUS_SUCCESS (0x00) > +#define MPI3_PEL_STATUS_NOT_FOUND (0x01) > +#define MPI3_PEL_STATUS_ABORTED (0x02) > +#define MPI3_PEL_STATUS_NOT_READY (0x03) > + > +/**************************************************************************** > + * PEL Sequence Numbers * > + ****************************************************************************/ > +typedef struct _MPI3_PEL_SEQ { > + U32 Newest; /* 0x00 */ > + U32 Oldest; /* 0x04 */ > + U32 Clear; /* 0x08 */ > + U32 Shutdown; /* 0x0C */ > + U32 Boot; /* 0x10 */ > + U32 LastAcknowledged; /* 0x14 */ > +} MPI3_PEL_SEQ, MPI3_POINTER PTR_MPI3_PEL_SEQ, > + Mpi3PELSeq_t, MPI3_POINTER pMpi3PELSeq_t; > + > +/**************************************************************************** > + * PEL Entry * > + ****************************************************************************/ > + > +typedef struct _MPI3_PEL_ENTRY { > + U32 SequenceNumber; /* 0x00 */ > + U32 TimeStamp[2]; /* 0x04 */ > + U16 LogCode; /* 0x0C */ > + U16 ArgType; /* 0x0E */ > + U16 Locale; /* 0x10 */ > + U8 Class; /* 0x12 */ > + U8 Reserved13; /* 0x13 */ > + U8 ExtNum; /* 0x14 */ > + U8 NumExts; /* 0x15 */ > + U8 ArgDataSize; /* 0x16 */ > + U8 FixedFormatSize; /* 0x17 */ > + U32 Reserved18[2]; /* 0x18 */ > + U32 PELInfo[24]; /* 0x20 - 0x7F */ > +} MPI3_PEL_ENTRY, MPI3_POINTER PTR_MPI3_PEL_ENTRY, > + Mpi3PELEntry_t, MPI3_POINTER pMpi3PELEntry_t; > + > +/**************************************************************************** > + * PEL Event List * > + ****************************************************************************/ > +typedef struct _MPI3_PEL_LIST { > + U32 LogCount; /* 0x00 */ > + U32 Reserved04; /* 0x04 */ > + MPI3_PEL_ENTRY Entry[1]; /* 0x08 */ /* variable length */ > +} MPI3_PEL_LIST, MPI3_POINTER PTR_MPI3_PEL_LIST, > + Mpi3PELList_t, MPI3_POINTER pMpi3PELList_t; > + > +/**************************************************************************** > + * PEL Count Data * > + ****************************************************************************/ > +typedef U32 MPI3_PEL_LOG_COUNT, MPI3_POINTER PTR_MPI3_PEL_LOG_COUNT, > + Mpi3PELLogCount_t, MPI3_POINTER pMpi3PELLogCount_t; > + > +/**************************************************************************** > + * PEL Arg Map * > + ****************************************************************************/ > +typedef struct _MPI3_PEL_ARG_MAP { > + U8 ArgType; /* 0x00 */ > + U8 Length; /* 0x01 */ > + U16 StartLocation; /* 0x02 */ > +} MPI3_PEL_ARG_MAP, MPI3_POINTER PTR_MPI3_PEL_ARG_MAP, > + Mpi3PELArgMap_t, MPI3_POINTER pMpi3PELArgMap_t; > + > +/**** Definitions for the ArgType field ****/ > +#define MPI3_PEL_ARG_MAP_ARG_TYPE_APPEND_STRING (0x00) > +#define MPI3_PEL_ARG_MAP_ARG_TYPE_INTEGER (0x01) > +#define MPI3_PEL_ARG_MAP_ARG_TYPE_STRING (0x02) > +#define MPI3_PEL_ARG_MAP_ARG_TYPE_BIT_FIELD (0x03) > + > + > +/**************************************************************************** > + * PEL Print String * > + ****************************************************************************/ > +typedef struct _MPI3_PEL_PRINT_STRING { > + U16 LogCode; /* 0x00 */ > + U16 StringLength; /* 0x02 */ > + U8 NumArgMap; /* 0x04 */ > + U8 Reserved05[3]; /* 0x05 */ > + MPI3_PEL_ARG_MAP ArgMap[1]; /* 0x08 */ /* variable length */ > +} MPI3_PEL_PRINT_STRING, MPI3_POINTER PTR_MPI3_PEL_PRINT_STRING, > + Mpi3PELPrintString_t, MPI3_POINTER pMpi3PELPrintString_t; > + > +/**************************************************************************** > + * PEL Print String List * > + ****************************************************************************/ > +typedef struct _MPI3_PEL_PRINT_STRING_LIST { > + U32 NumPrintStrings; /* 0x00 */ > + U32 ResidualBytesRemain; /* 0x04 */ > + U32 Reserved08[2]; /* 0x08 */ > + MPI3_PEL_PRINT_STRING PrintString[1]; /* 0x10 */ /* variable length */ > +} MPI3_PEL_PRINT_STRING_LIST, MPI3_POINTER PTR_MPI3_PEL_PRINT_STRING_LIST, > + Mpi3PELPrintStringList_t, MPI3_POINTER pMpi3PELPrintStringList_t; > + > + > +/**************************************************************************** > + * PEL Request Msg - generic to allow header decoding * > + ****************************************************************************/ > +#ifndef MPI3_PEL_ACTION_SPECIFIC_MAX > +#define MPI3_PEL_ACTION_SPECIFIC_MAX (1) > +#endif /* MPI3_PEL_ACTION_SPECIFIC_MAX */ > + > +typedef struct _MPI3_PEL_REQUEST { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U8 Action; /* 0x0A */ > + U8 Reserved0B; /* 0x0B */ > + U32 ActionSpecific[MPI3_PEL_ACTION_SPECIFIC_MAX]; /* 0x0C */ /* variable length */ > +} MPI3_PEL_REQUEST, MPI3_POINTER PTR_MPI3_PEL_REQUEST, > + Mpi3PELRequest_t, MPI3_POINTER pMpi3PELRequest_t; > + > +/**************************************************************************** > + * PEL ACTION Get Sequence Nembers * > + ****************************************************************************/ > +typedef struct _MPI3_PEL_REQ_ACTION_GET_SEQUENCE_NUMBERS { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U8 Action; /* 0x0A */ > + U8 Reserved0B; /* 0x0B */ > + U32 Reserved0C[5]; /* 0x0C */ > + MPI3_SGE_UNION SGL; /* 0x20 */ > +} MPI3_PEL_REQ_ACTION_GET_SEQUENCE_NUMBERS, MPI3_POINTER PTR_MPI3_PEL_REQ_ACTION_GET_SEQUENCE_NUMBERS, > + Mpi3PELReqActionGetSequenceNumbers_t, MPI3_POINTER pMpi3PELReqActionGetSequenceNumbers_t; > + > +/**************************************************************************** > + * PEL ACTION Clear Log * > + ****************************************************************************/ > +typedef struct _MPI3_PEL_REQ_ACTION_CLEAR_LOG_MARKER { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U8 Action; /* 0x0A */ > + U8 Reserved0B; /* 0x0B */ > + U8 ClearType; /* 0x0C */ > + U8 Reserved0D[3]; /* 0x0D */ > +} MPI3_PEL_REQ_ACTION_CLEAR_LOG_MARKER, MPI3_POINTER PTR_MPI3_PEL_REQ_ACTION_CLEAR_LOG_MARKER, > + Mpi3PELReqActionClearLogMMarker_t, MPI3_POINTER pMpi3PELReqActionClearLogMMarker_t; > + > +/**************************************************************************** > + * PEL ACTION Get Log * > + ****************************************************************************/ > +typedef struct _MPI3_PEL_REQ_ACTION_GET_LOG { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U8 Action; /* 0x0A */ > + U8 Reserved0B; /* 0x0B */ > + U32 StartingSequenceNumber; /* 0x0C */ > + U16 Locale; /* 0x10 */ > + U8 Class; /* 0x12 */ > + U8 Reserved13; /* 0x13 */ > + U32 Reserved14[3]; /* 0x14 */ > + MPI3_SGE_UNION SGL; /* 0x20 */ > +} MPI3_PEL_REQ_ACTION_GET_LOG, MPI3_POINTER PTR_MPI3_PEL_REQ_ACTION_GET_LOG, > + Mpi3PELReqActionGetLog_t, MPI3_POINTER pMpi3PELReqActionGetLog_t; > + > +/**************************************************************************** > + * PEL ACTION Get Count * > + ****************************************************************************/ > +typedef struct _MPI3_PEL_REQ_ACTION_GET_COUNT { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U8 Action; /* 0x0A */ > + U8 Reserved0B; /* 0x0B */ > + U32 StartingSequenceNumber; /* 0x0C */ > + U16 Locale; /* 0x10 */ > + U8 Class; /* 0x12 */ > + U8 Reserved13; /* 0x13 */ > + U32 Reserved14[3]; /* 0x14 */ > + MPI3_SGE_UNION SGL; /* 0x20 */ > +} MPI3_PEL_REQ_ACTION_GET_COUNT, MPI3_POINTER PTR_MPI3_PEL_REQ_ACTION_GET_COUNT, > + Mpi3PELReqActionGetCount_t, MPI3_POINTER pMpi3PELReqActionGetCount_t; > + > +/**************************************************************************** > + * PEL ACTION Wait * > + ****************************************************************************/ > +typedef struct _MPI3_PEL_REQ_ACTION_WAIT { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U8 Action; /* 0x0A */ > + U8 Reserved0B; /* 0x0B */ > + U32 StartingSequenceNumber; /* 0x0C */ > + U16 Locale; /* 0x10 */ > + U8 Class; /* 0x12 */ > + U8 Reserved13; /* 0x13 */ > + U16 WaitTime; /* 0x14 */ > + U16 Reserved16; /* 0x16 */ > + U32 Reserved18[2]; /* 0x18 */ > +} MPI3_PEL_REQ_ACTION_WAIT, MPI3_POINTER PTR_MPI3_PEL_REQ_ACTION_WAIT, > + Mpi3PELReqActionWait_t, MPI3_POINTER pMpi3PELReqActionWait_t; > + > +/**************************************************************************** > + * PEL ACTION Abort * > + ****************************************************************************/ > +typedef struct _MPI3_PEL_REQ_ACTION_ABORT { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U8 Action; /* 0x0A */ > + U8 Reserved0B; /* 0x0B */ > + U32 Reserved0C; /* 0x0C */ > + U16 AbortHostTag; /* 0x10 */ > + U16 Reserved12; /* 0x12 */ > + U32 Reserved14; /* 0x14 */ > +} MPI3_PEL_REQ_ACTION_ABORT, MPI3_POINTER PTR_MPI3_PEL_REQ_ACTION_ABORT, > + Mpi3PELReqActionAbort_t, MPI3_POINTER pMpi3PELReqActionAbort_t; > + > +/**************************************************************************** > + * PEL ACTION Get Print Strings * > + ****************************************************************************/ > +typedef struct _MPI3_PEL_REQ_ACTION_GET_PRINT_STRINGS { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U8 Action; /* 0x0A */ > + U8 Reserved0B; /* 0x0B */ > + U32 Reserved0C; /* 0x0C */ > + U16 StartLogCode; /* 0x10 */ > + U16 Reserved12; /* 0x12 */ > + U32 Reserved14[3]; /* 0x14 */ > + MPI3_SGE_UNION SGL; /* 0x20 */ > +} MPI3_PEL_REQ_ACTION_GET_PRINT_STRINGS, MPI3_POINTER PTR_MPI3_PEL_REQ_ACTION_GET_PRINT_STRINGS, > + Mpi3PELReqActionGetPrintStrings_t, MPI3_POINTER pMpi3PELReqActionGetPrintStrings_t; > + > +/**************************************************************************** > + * PEL ACTION Acknowledge * > + ****************************************************************************/ > +typedef struct _MPI3_PEL_REQ_ACTION_ACKNOWLEDGE { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U8 Action; /* 0x0A */ > + U8 Reserved0B; /* 0x0B */ > + U32 SequenceNumber; /* 0x0C */ > + U32 Reserved10; /* 0x10 */ > +} MPI3_PEL_REQ_ACTION_ACKNOWLEDGE, MPI3_POINTER PTR_MPI3_PEL_REQ_ACTION_ACKNOWLEDGE, > + Mpi3PELReqActionAcknowledge_t, MPI3_POINTER pMpi3PELReqActionAcknowledge_t; > + > +/**** Definitions for the MsgFlags field ****/ > +#define MPI3_PELACKNOWLEDGE_MSGFLAGS_SAFE_MODE_EXIT (0x01) > + > +/**************************************************************************** > + * PEL Reply * > + ****************************************************************************/ > +typedef struct _MPI3_PEL_REPLY { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 IOCUseOnly08; /* 0x08 */ > + U16 IOCStatus; /* 0x0A */ > + U32 IOCLogInfo; /* 0x0C */ > + U8 Action; /* 0x10 */ > + U8 Reserved11; /* 0x11 */ > + U16 Reserved12; /* 0x12 */ > + U16 PELogStatus; /* 0x14 */ > + U16 Reserved16; /* 0x16 */ > + U32 TransferLength; /* 0x18 */ > +} MPI3_PEL_REPLY, MPI3_POINTER PTR_MPI3_PEL_REPLY, > + Mpi3PELReply_t, MPI3_POINTER pMpi3PELReply_t; > + > + > +/***************************************************************************** > + * Component Image Download * > + ****************************************************************************/ > +typedef struct _MPI3_CI_DOWNLOAD_REQUEST { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U8 Action; /* 0x0A */ > + U8 Reserved0B; /* 0x0B */ > + U32 Signature1; /* 0x0C */ > + U32 TotalImageSize; /* 0x10 */ > + U32 ImageOffset; /* 0x14 */ > + U32 SegmentSize; /* 0x18 */ > + U32 Reserved1C; /* 0x1C */ > + MPI3_SGE_UNION SGL; /* 0x20 */ > +} MPI3_CI_DOWNLOAD_REQUEST, MPI3_POINTER PTR_MPI3_CI_DOWNLOAD_REQUEST, > + Mpi3CIDownloadRequest_t, MPI3_POINTER pMpi3CIDownloadRequest_t; > + > +/**** Definitions for the MsgFlags field ****/ > +#define MPI3_CI_DOWNLOAD_MSGFLAGS_LAST_SEGMENT (0x80) > +#define MPI3_CI_DOWNLOAD_MSGFLAGS_FORCE_FMC_ENABLE (0x40) > +#define MPI3_CI_DOWNLOAD_MSGFLAGS_SIGNED_NVDATA (0x20) > +#define MPI3_CI_DOWNLOAD_MSGFLAGS_WRITE_CACHE_FLUSH_MASK (0x03) > +#define MPI3_CI_DOWNLOAD_MSGFLAGS_WRITE_CACHE_FLUSH_FAST (0x00) > +#define MPI3_CI_DOWNLOAD_MSGFLAGS_WRITE_CACHE_FLUSH_MEDIUM (0x01) > +#define MPI3_CI_DOWNLOAD_MSGFLAGS_WRITE_CACHE_FLUSH_SLOW (0x02) > + > +/**** Definitions for the Action field ****/ > +#define MPI3_CI_DOWNLOAD_ACTION_DOWNLOAD (0x01) > +#define MPI3_CI_DOWNLOAD_ACTION_ONLINE_ACTIVATION (0x02) > +#define MPI3_CI_DOWNLOAD_ACTION_OFFLINE_ACTIVATION (0x03) > +#define MPI3_CI_DOWNLOAD_ACTION_GET_STATUS (0x04) > + > +typedef struct _MPI3_CI_DOWNLOAD_REPLY { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 IOCUseOnly08; /* 0x08 */ > + U16 IOCStatus; /* 0x0A */ > + U32 IOCLogInfo; /* 0x0C */ > + U8 Flags; /* 0x10 */ > + U8 CacheDirty; /* 0x11 */ > + U8 PendingCount; /* 0x12 */ > + U8 Reserved13; /* 0x13 */ > +} MPI3_CI_DOWNLOAD_REPLY, MPI3_POINTER PTR_MPI3_CI_DOWNLOAD_REPLY, > + Mpi3CIDownloadReply_t, MPI3_POINTER pMpi3CIDownloadReply_t; > + > +/**** Definitions for the Flags field ****/ > +#define MPI3_CI_DOWNLOAD_FLAGS_DOWNLOAD_IN_PROGRESS (0x80) > +#define MPI3_CI_DOWNLOAD_FLAGS_KEY_UPDATE_PENDING (0x10) > +#define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_MASK (0x0E) > +#define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_NOT_NEEDED (0x00) > +#define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_AWAITING (0x02) > +#define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_ONLINE_PENDING (0x04) > +#define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_OFFLINE_PENDING (0x06) > +#define MPI3_CI_DOWNLOAD_FLAGS_COMPATIBLE (0x01) > + > +/***************************************************************************** > + * Component Image Upload * > + ****************************************************************************/ > +typedef struct _MPI3_CI_UPLOAD_REQUEST { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U16 Reserved0A; /* 0x0A */ > + U32 Signature1; /* 0x0C */ > + U32 Reserved10; /* 0x10 */ > + U32 ImageOffset; /* 0x14 */ > + U32 SegmentSize; /* 0x18 */ > + U32 Reserved1C; /* 0x1C */ > + MPI3_SGE_UNION SGL; /* 0x20 */ > +} MPI3_CI_UPLOAD_REQUEST, MPI3_POINTER PTR_MPI3_CI_UPLOAD_REQUEST, > + Mpi3CIUploadRequest_t, MPI3_POINTER pMpi3CIUploadRequest_t; > + > +/**** Defines for the MsgFlags field ****/ > +#define MPI3_CI_UPLOAD_MSGFLAGS_LOCATION_MASK (0x01) > +#define MPI3_CI_UPLOAD_MSGFLAGS_LOCATION_PRIMARY (0x00) > +#define MPI3_CI_UPLOAD_MSGFLAGS_LOCATION_SECONDARY (0x01) > +#define MPI3_CI_UPLOAD_MSGFLAGS_FORMAT_MASK (0x02) > +#define MPI3_CI_UPLOAD_MSGFLAGS_FORMAT_FLASH (0x00) > +#define MPI3_CI_UPLOAD_MSGFLAGS_FORMAT_EXECUTABLE (0x02) > + > +/**** Defines for Signature1 field - use MPI3_IMAGE_HEADER_SIGNATURE1_ defines */ > + > +/***************************************************************************** > + * IO Unit Control * > + ****************************************************************************/ > + > +/**** Definitions for the Operation field ****/ > +#define MPI3_CTRL_OP_FORCE_FULL_DISCOVERY (0x01) > +#define MPI3_CTRL_OP_LOOKUP_MAPPING (0x02) > +#define MPI3_CTRL_OP_UPDATE_TIMESTAMP (0x04) > +#define MPI3_CTRL_OP_GET_TIMESTAMP (0x05) > +#define MPI3_CTRL_OP_REMOVE_DEVICE (0x10) > +#define MPI3_CTRL_OP_CLOSE_PERSISTENT_CONNECTION (0x11) > +#define MPI3_CTRL_OP_HIDDEN_ACK (0x12) > +#define MPI3_CTRL_OP_SAS_SEND_PRIMITIVE (0x20) > +#define MPI3_CTRL_OP_SAS_CLEAR_ERROR_LOG (0x21) > +#define MPI3_CTRL_OP_PCIE_CLEAR_ERROR_LOG (0x22) > + > +/**** Depending on the Operation selected, the various ParamX fields *****/ > +/**** contain defined data values. These indexes help identify those values *****/ > +#define MPI3_CTRL_OP_LOOKUP_MAPPING_PARAM8_LOOKUP_METHOD_INDEX (0x00) > +#define MPI3_CTRL_OP_UPDATE_TIMESTAMP_PARAM64_TIMESTAMP_INDEX (0x00) > +#define MPI3_CTRL_OP_REMOVE_DEVICE_PARAM16_DEVHANDLE_INDEX (0x00) > +#define MPI3_CTRL_OP_CLOSE_PERSIST_CONN_PARAM16_DEVHANDLE_INDEX (0x00) > +#define MPI3_CTRL_OP_HIDDEN_ACK_PARAM16_DEVHANDLE_INDEX (0x00) > +#define MPI3_CTRL_OP_SAS_SEND_PRIM_PARAM8_PHY_INDEX (0x00) > +#define MPI3_CTRL_OP_SAS_SEND_PRIM_PARAM8_PRIMSEQ_INDEX (0x01) > +#define MPI3_CTRL_OP_SAS_SEND_PRIM_PARAM32_PRIMITIVE_INDEX (0x00) > +#define MPI3_CTRL_OP_SAS_CLEAR_ERR_LOG_PARAM8_PHY_INDEX (0x00) > +#define MPI3_CTRL_OP_PCIE_CLEAR_ERR_LOG_PARAM8_PHY_INDEX (0x00) > + > +/**** Definitions for the LookupMethod field ****/ > +#define MPI3_CTRL_LOOKUP_METHOD_WWID_ADDRESS (0x01) > +#define MPI3_CTRL_LOOKUP_METHOD_ENCLOSURE_SLOT (0x02) > +#define MPI3_CTRL_LOOKUP_METHOD_SAS_DEVICE_NAME (0x03) > +#define MPI3_CTRL_LOOKUP_METHOD_PERSISTENT_ID (0x04) > + > +/**** Definitions for IoUnitControl Lookup Mapping Method Parameters ****/ > +#define MPI3_CTRL_LOOKUP_METHOD_WWIDADDR_PARAM16_DEVH_INDEX (0) > +#define MPI3_CTRL_LOOKUP_METHOD_WWIDADDR_PARAM64_WWID_INDEX (0) > +#define MPI3_CTRL_LOOKUP_METHOD_ENCLSLOT_PARAM16_SLOTNUM_INDEX (0) > +#define MPI3_CTRL_LOOKUP_METHOD_ENCLSLOT_PARAM64_ENCLOSURELID_INDEX (0) > +#define MPI3_CTRL_LOOKUP_METHOD_SASDEVNAME_PARAM16_DEVH_INDEX (0) > +#define MPI3_CTRL_LOOKUP_METHOD_SASDEVNAME_PARAM64_DEVNAME_INDEX (0) > +#define MPI3_CTRL_LOOKUP_METHOD_PERSISTID_PARAM16_DEVH_INDEX (0) > +#define MPI3_CTRL_LOOKUP_METHOD_PERSISTID_PARAM16_PERSISTENT_ID_INDEX (1) > + > +/*** Definitions for IoUnitControl Reply fields ****/ > +#define MPI3_CTRL_LOOKUP_METHOD_VALUE16_DEVH_INDEX (0) > +#define MPI3_CTRL_GET_TIMESTAMP_VALUE64_TIMESTAMP_INDEX (0) > + > + > +/**** Definitions for the PrimSeq field ****/ > +#define MPI3_CTRL_PRIMFLAGS_SINGLE (0x01) > +#define MPI3_CTRL_PRIMFLAGS_TRIPLE (0x03) > +#define MPI3_CTRL_PRIMFLAGS_REDUNDANT (0x06) > + > +typedef struct _MPI3_IOUNIT_CONTROL_REQUEST { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U8 Reserved0A; /* 0x0A */ > + U8 Operation; /* 0x0B */ > + U32 Reserved0C; /* 0x0C */ > + U64 Param64[2]; /* 0x10 */ > + U32 Param32[4]; /* 0x20 */ > + U16 Param16[4]; /* 0x30 */ > + U8 Param8[8]; /* 0x38 */ > +} MPI3_IOUNIT_CONTROL_REQUEST, MPI3_POINTER PTR_MPI3_IOUNIT_CONTROL_REQUEST, > + Mpi3IoUnitControlRequest_t, MPI3_POINTER pMpi3IoUnitControlRequest_t; > + > + > +typedef struct _MPI3_IOUNIT_CONTROL_REPLY { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 IOCUseOnly08; /* 0x08 */ > + U16 IOCStatus; /* 0x0A */ > + U32 IOCLogInfo; /* 0x0C */ > + U64 Value64[2]; /* 0x10 */ > + U32 Value32[4]; /* 0x20 */ > + U16 Value16[4]; /* 0x30 */ > + U8 Value8[8]; /* 0x38 */ > +} MPI3_IOUNIT_CONTROL_REPLY, MPI3_POINTER PTR_MPI3_IOUNIT_CONTROL_REPLY, > + Mpi3IoUnitControlReply_t, MPI3_POINTER pMpi3IoUnitControlReply_t; > + > +#endif /* MPI30_IOC_H */ > diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_transport.h b/drivers/scsi/mpi3mr/mpi/mpi30_transport.h > new file mode 100644 > index 000000000000..54f821d25209 > --- /dev/null > +++ b/drivers/scsi/mpi3mr/mpi/mpi30_transport.h > @@ -0,0 +1,675 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * Copyright 2016-2020 Broadcom Inc. All rights reserved. > + * > + * Name: mpi30_transport.h > + * Description: Contains definitions for System Interface Register Set, Scatter Gather Lists etc > + * Creation Date: 08/31/2016 > + * Version: 03.00.00 > + * > + * mpi3.h Version: 03.00.00.18 > + * > + * > + * Version History > + * --------------- > + * > + * Date Version Description > + * -------- ----------- ------------------------------------------------------ > + * 11-30-18 03.00.00.08 Corresponds to Fusion-MPT MPI 3.0 Specification Rev H. > + * 02-08-19 03.00.00.09 Corresponds to Fusion-MPT MPI 3.0 Specification Rev I. > + * 05-03-19 03.00.00.10 Corresponds to Fusion-MPT MPI 3.0 Specification Rev J. > + * 08-30-19 03.00.00.12 Corresponds to Fusion-MPT MPI 3.0 Specification Rev L. > + * 11-01-19 03.00.00.13 Corresponds to Fusion-MPT MPI 3.0 Specification Rev M. > + * 12-16-19 03.00.00.14 Corresponds to Fusion-MPT MPI 3.0 Specification Rev N. > + * 02-28-20 03.00.00.15 Corresponds to Fusion-MPT MPI 3.0 Specification Rev O. > + * 05-01-20 03.00.00.16 Corresponds to Fusion-MPT MPI 3.0 Specification Rev P. > + * 06-26-20 03.00.00.17 Corresponds to Fusion-MPT MPI 3.0 Specification Rev Q. > + * 08-28-20 03.00.00.18 Corresponds to Fusion-MPT MPI 3.0 Specification Rev R. > + */ > +#ifndef MPI30_TRANSPORT_H > +#define MPI30_TRANSPORT_H 1 > + > +/***************************************************************************** > + * Common version structure/union used in * > + * messages and configuration pages * > + ****************************************************************************/ > + > +typedef struct _MPI3_VERSION_STRUCT { > + U8 Dev; /* 0x00 */ > + U8 Unit; /* 0x01 */ > + U8 Minor; /* 0x02 */ > + U8 Major; /* 0x03 */ > +} MPI3_VERSION_STRUCT, MPI3_POINTER PTR_MPI3_VERSION_STRUCT, > + Mpi3VersionStruct, MPI3_POINTER pMpi3VersionStruct; > + > +typedef union _MPI3_VERSION_UNION { > + MPI3_VERSION_STRUCT Struct; > + U32 Word; > +} MPI3_VERSION_UNION, MPI3_POINTER PTR_MPI3_VERSION_UNION, > + Mpi3VersionUnion, MPI3_POINTER pMpi3VersionUnion; > + > +/****** Version constants for this revision ****/ > +#define MPI3_VERSION_MAJOR (3) > +#define MPI3_VERSION_MINOR (0) > +#define MPI3_VERSION_UNIT (0) > +#define MPI3_VERSION_DEV (18) > + > + > +/***************************************************************************** > + * System Interface Register Definitions * > + ****************************************************************************/ > +typedef struct _MPI3_SYSIF_OPER_QUEUE_INDEXES { > + U16 ProducerIndex; /* 0x00 */ > + U16 Reserved02; /* 0x02 */ > + U16 ConsumerIndex; /* 0x04 */ > + U16 Reserved06; /* 0x06 */ > +} MPI3_SYSIF_OPER_QUEUE_INDEXES, MPI3_POINTER PTR_MPI3_SYSIF_OPER_QUEUE_INDEXES; > + Hey, you _can_ do it! So why do you need to define duplicate names for all the other structures? > +typedef volatile struct _MPI3_SYSIF_REGISTERS > +{ > + U64 IOCInformation; /* 0x00 */ > + MPI3_VERSION_UNION Version; /* 0x08 */ > + U32 Reserved0C[2]; /* 0x0C */ > + U32 IOCConfiguration; /* 0x14 */ > + U32 Reserved18; /* 0x18 */ > + U32 IOCStatus; /* 0x1C */ > + U32 Reserved20; /* 0x20 */ > + U32 AdminQueueNumEntries; /* 0x24 */ > + U64 AdminRequestQueueAddress; /* 0x28 */ > + U64 AdminReplyQueueAddress; /* 0x30 */ > + U32 Reserved38[2]; /* 0x38 */ > + U32 CoalesceControl; /* 0x40 */ > + U32 Reserved44[1007]; /* 0x44 */ > + U16 AdminRequestQueuePI; /* 0x1000 */ > + U16 Reserved1002; /* 0x1002 */ > + U16 AdminReplyQueueCI; /* 0x1004 */ > + U16 Reserved1006; /* 0x1006 */ > + MPI3_SYSIF_OPER_QUEUE_INDEXES OperQueueIndexes[383]; /* 0x1008 */ > + U32 Reserved1C00; /* 0x1C00 */ > + U32 WriteSequence; /* 0x1C04 */ > + U32 HostDiagnostic; /* 0x1C08 */ > + U32 Reserved1C0C; /* 0x1C0C */ > + U32 Fault; /* 0x1C10 */ > + U32 FaultInfo[3]; /* 0x1C14 */ > + U32 Reserved1C20[4]; /* 0x1C20 */ > + U64 HCBAddress; /* 0x1C30 */ > + U32 HCBSize; /* 0x1C38 */ > + U32 Reserved1C3C; /* 0x1C3C */ > + U32 ReplyFreeHostIndex; /* 0x1C40 */ > + U32 SenseBufferFreeHostIndex; /* 0x1C44 */ > + U32 Reserved1C48[2]; /* 0x1C48 */ > + U64 DiagRWData; /* 0x1C50 */ > + U64 DiagRWAddress; /* 0x1C58 */ > + U16 DiagRWControl; /* 0x1C60 */ > + U16 DiagRWStatus; /* 0x1C62 */ > + U32 Reserved1C64[35]; /* 0x1C64 */ > + U32 Scratchpad[4]; /* 0x1CF0 */ > + U32 Reserved1D00[192]; /* 0x1D00 */ > + U32 DeviceAssignedRegisters[2048]; /* 0x2000 */ > +} MPI3_SYSIF_REGS, MPI3_POINTER PTR_MPI3_SYSIF_REGS, > + Mpi3SysIfRegs_t, MPI3_POINTER pMpi3SysIfRegs_t; > + > +/**** Defines for the IOCInformation register ****/ > +#define MPI3_SYSIF_IOC_INFO_LOW_OFFSET (0x00000000) > +#define MPI3_SYSIF_IOC_INFO_HIGH_OFFSET (0x00000004) > +#define MPI3_SYSIF_IOC_INFO_LOW_TIMEOUT_MASK (0xFF000000) > +#define MPI3_SYSIF_IOC_INFO_LOW_TIMEOUT_SHIFT (24) > + > +/**** Defines for the IOCConfiguration register ****/ > +#define MPI3_SYSIF_IOC_CONFIG_OFFSET (0x00000014) > +#define MPI3_SYSIF_IOC_CONFIG_OPER_RPY_ENT_SZ (0x00F00000) > +#define MPI3_SYSIF_IOC_CONFIG_OPER_RPY_ENT_SZ_SHIFT (20) > +#define MPI3_SYSIF_IOC_CONFIG_OPER_REQ_ENT_SZ (0x000F0000) > +#define MPI3_SYSIF_IOC_CONFIG_OPER_REQ_ENT_SZ_SHIFT (16) > +#define MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_MASK (0x0000C000) > +#define MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NO (0x00000000) > +#define MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NORMAL (0x00004000) > +#define MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN (0x00002000) > +#define MPI3_SYSIF_IOC_CONFIG_DIAG_SAVE (0x00000010) > +#define MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC (0x00000001) > + > +/**** Defines for the IOCStatus register ****/ > +#define MPI3_SYSIF_IOC_STATUS_OFFSET (0x0000001C) > +#define MPI3_SYSIF_IOC_STATUS_RESET_HISTORY (0x00000010) > +#define MPI3_SYSIF_IOC_STATUS_SHUTDOWN_MASK (0x0000000C) > +#define MPI3_SYSIF_IOC_STATUS_SHUTDOWN_NONE (0x00000000) > +#define MPI3_SYSIF_IOC_STATUS_SHUTDOWN_IN_PROGRESS (0x00000004) > +#define MPI3_SYSIF_IOC_STATUS_SHUTDOWN_COMPLETE (0x00000008) > +#define MPI3_SYSIF_IOC_STATUS_FAULT (0x00000002) > +#define MPI3_SYSIF_IOC_STATUS_READY (0x00000001) > + > +/**** Defines for the AdminQueueNumEntries register ****/ > +#define MPI3_SYSIF_ADMIN_Q_NUM_ENTRIES_OFFSET (0x00000024) > +#define MPI3_SYSIF_ADMIN_Q_NUM_ENTRIES_REQ_MASK (0x0FFF) > +#define MPI3_SYSIF_ADMIN_Q_NUM_ENTRIES_REPLY_OFFSET (0x00000026) > +#define MPI3_SYSIF_ADMIN_Q_NUM_ENTRIES_REPLY_MASK (0x0FFF0000) > +#define MPI3_SYSIF_ADMIN_Q_NUM_ENTRIES_REPLY_SHIFT (16) > + > +/**** Defines for the AdminRequestQueueAddress register ****/ > +#define MPI3_SYSIF_ADMIN_REQ_Q_ADDR_LOW_OFFSET (0x00000028) > +#define MPI3_SYSIF_ADMIN_REQ_Q_ADDR_HIGH_OFFSET (0x0000002C) > + > +/**** Defines for the AdminReplyQueueAddress register ****/ > +#define MPI3_SYSIF_ADMIN_REPLY_Q_ADDR_LOW_OFFSET (0x00000030) > +#define MPI3_SYSIF_ADMIN_REPLY_Q_ADDR_HIGH_OFFSET (0x00000034) > + > +/**** Defines for the CoalesceControl register ****/ > +#define MPI3_SYSIF_COALESCE_CONTROL_OFFSET (0x00000040) > +#define MPI3_SYSIF_COALESCE_CONTROL_ENABLE_MASK (0xC0000000) > +#define MPI3_SYSIF_COALESCE_CONTROL_ENABLE_NO_CHANGE (0x00000000) > +#define MPI3_SYSIF_COALESCE_CONTROL_ENABLE_DISABLE (0x40000000) > +#define MPI3_SYSIF_COALESCE_CONTROL_ENABLE_ENABLE (0xC0000000) > +#define MPI3_SYSIF_COALESCE_CONTROL_VALID (0x30000000) > +#define MPI3_SYSIF_COALESCE_CONTROL_QUEUE_ID_MASK (0x00FF0000) > +#define MPI3_SYSIF_COALESCE_CONTROL_QUEUE_ID_SHIFT (16) > +#define MPI3_SYSIF_COALESCE_CONTROL_TIMEOUT_MASK (0x0000FF00) > +#define MPI3_SYSIF_COALESCE_CONTROL_TIMEOUT_SHIFT (8) > +#define MPI3_SYSIF_COALESCE_CONTROL_DEPTH_MASK (0x000000FF) > +#define MPI3_SYSIF_COALESCE_CONTROL_DEPTH_SHIFT (0) > + > +/**** Defines for the AdminRequestQueuePI register ****/ > +#define MPI3_SYSIF_ADMIN_REQ_Q_PI_OFFSET (0x00001000) > + > +/**** Defines for the AdminReplyQueueCI register ****/ > +#define MPI3_SYSIF_ADMIN_REPLY_Q_CI_OFFSET (0x00001004) > + > +/**** Defines for the OperationalRequestQueuePI register */ > +#define MPI3_SYSIF_OPER_REQ_Q_PI_OFFSET (0x00001008) > +#define MPI3_SYSIF_OPER_REQ_Q_N_PI_OFFSET(N) (MPI3_SYSIF_OPER_REQ_Q_PI_OFFSET + (((N)-1)*8)) /* N = 1, 2, 3, ..., 255 */ > + > +/**** Defines for the OperationalReplyQueueCI register */ > +#define MPI3_SYSIF_OPER_REPLY_Q_CI_OFFSET (0x0000100C) > +#define MPI3_SYSIF_OPER_REPLY_Q_N_CI_OFFSET(N) (MPI3_SYSIF_OPER_REPLY_Q_CI_OFFSET + (((N)-1)*8)) /* N = 1, 2, 3, ..., 255 */ > + > +/**** Defines for the WriteSequence register *****/ > +#define MPI3_SYSIF_WRITE_SEQUENCE_OFFSET (0x00001C04) > +#define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_MASK (0x0000000F) > +#define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_FLUSH (0x0) > +#define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_1ST (0xF) > +#define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_2ND (0x4) > +#define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_3RD (0xB) > +#define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_4TH (0x2) > +#define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_5TH (0x7) > +#define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_6TH (0xD) > + > +/**** Defines for the HostDiagnostic register *****/ > +#define MPI3_SYSIF_HOST_DIAG_OFFSET (0x00001C08) > +#define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_MASK (0x00000700) > +#define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_NO_RESET (0x00000000) > +#define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET (0x00000100) > +#define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_FLASH_RCVRY_RESET (0x00000200) > +#define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_COMPLETE_RESET (0x00000300) > +#define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT (0x00000700) > +#define MPI3_SYSIF_HOST_DIAG_SAVE_IN_PROGRESS (0x00000080) > +#define MPI3_SYSIF_HOST_DIAG_SECURE_BOOT (0x00000040) > +#define MPI3_SYSIF_HOST_DIAG_CLEAR_INVALID_FW_IMAGE (0x00000020) > +#define MPI3_SYSIF_HOST_DIAG_INVALID_FW_IMAGE (0x00000010) > +#define MPI3_SYSIF_HOST_DIAG_HCBENABLE (0x00000008) > +#define MPI3_SYSIF_HOST_DIAG_HCBMODE (0x00000004) > +#define MPI3_SYSIF_HOST_DIAG_DIAG_RW_ENABLE (0x00000002) > +#define MPI3_SYSIF_HOST_DIAG_DIAG_WRITE_ENABLE (0x00000001) > + > +/**** Defines for the Fault register ****/ > +#define MPI3_SYSIF_FAULT_OFFSET (0x00001C10) > +#define MPI3_SYSIF_FAULT_FUNC_AREA_MASK (0xFF000000) > +#define MPI3_SYSIF_FAULT_FUNC_AREA_SHIFT (24) > +#define MPI3_SYSIF_FAULT_FUNC_AREA_MPI_DEFINED (0x00000000) > +#define MPI3_SYSIF_FAULT_CODE_MASK (0x0000FFFF) > +#define MPI3_SYSIF_FAULT_CODE_DIAG_FAULT_RESET (0x0000F000) > +#define MPI3_SYSIF_FAULT_CODE_CI_ACTIVATION_RESET (0x0000F001) > +#define MPI3_SYSIF_FAULT_CODE_SOFT_RESET_IN_PROGRESS (0x0000F002) > +#define MPI3_SYSIF_FAULT_CODE_COMPLETE_RESET_NEEDED (0x0000F003) > +#define MPI3_SYSIF_FAULT_CODE_SAFE_MODE_EXIT (0x0000F004) > +#define MPI3_SYSIF_FAULT_CODE_FACTORY_RESET (0x0000F005) > + > +/**** Defines for FaultCodeAdditionalInfo registers ****/ > +#define MPI3_SYSIF_FAULT_INFO0_OFFSET (0x00001C14) > +#define MPI3_SYSIF_FAULT_INFO1_OFFSET (0x00001C18) > +#define MPI3_SYSIF_FAULT_INFO2_OFFSET (0x00001C1C) > + > +/**** Defines for HCBAddress register ****/ > +#define MPI3_SYSIF_HCB_ADDRESS_LOW_OFFSET (0x00001C30) > +#define MPI3_SYSIF_HCB_ADDRESS_HIGH_OFFSET (0x00001C34) > + > +/**** Defines for HCBSize register ****/ > +#define MPI3_SYSIF_HCB_SIZE_OFFSET (0x00001C38) > +#define MPI3_SYSIF_HCB_SIZE_SIZE_MASK (0xFFFFF000) > +#define MPI3_SYSIF_HCB_SIZE_SIZE_SHIFT (12) > +#define MPI3_SYSIF_HCB_SIZE_HCDW_ENABLE (0x00000001) > + > +/**** Defines for ReplyFreeHostIndex register ****/ > +#define MPI3_SYSIF_REPLY_FREE_HOST_INDEX_OFFSET (0x00001C40) > + > +/**** Defines for SenseBufferFreeHostIndex register ****/ > +#define MPI3_SYSIF_SENSE_BUF_FREE_HOST_INDEX_OFFSET (0x00001C44) > + > +/**** Defines for DiagRWData register ****/ > +#define MPI3_SYSIF_DIAG_RW_DATA_LOW_OFFSET (0x00001C50) > +#define MPI3_SYSIF_DIAG_RW_DATA_HIGH_OFFSET (0x00001C54) > + > +/**** Defines for DiagRWAddress ****/ > +#define MPI3_SYSIF_DIAG_RW_ADDRESS_LOW_OFFSET (0x00001C58) > +#define MPI3_SYSIF_DIAG_RW_ADDRESS_HIGH_OFFSET (0x00001C5C) > + > +/**** Defines for DiagRWControl register ****/ > +#define MPI3_SYSIF_DIAG_RW_CONTROL_OFFSET (0x00001C60) > +#define MPI3_SYSIF_DIAG_RW_CONTROL_LEN_MASK (0x00000030) > +#define MPI3_SYSIF_DIAG_RW_CONTROL_LEN_1BYTE (0x00000000) > +#define MPI3_SYSIF_DIAG_RW_CONTROL_LEN_2BYTES (0x00000010) > +#define MPI3_SYSIF_DIAG_RW_CONTROL_LEN_4BYTES (0x00000020) > +#define MPI3_SYSIF_DIAG_RW_CONTROL_LEN_8BYTES (0x00000030) > +#define MPI3_SYSIF_DIAG_RW_CONTROL_RESET (0x00000004) > +#define MPI3_SYSIF_DIAG_RW_CONTROL_DIR_MASK (0x00000002) > +#define MPI3_SYSIF_DIAG_RW_CONTROL_DIR_READ (0x00000000) > +#define MPI3_SYSIF_DIAG_RW_CONTROL_DIR_WRITE (0x00000002) > +#define MPI3_SYSIF_DIAG_RW_CONTROL_START (0x00000001) > + > +/**** Defines for DiagRWStatus register ****/ > +#define MPI3_SYSIF_DIAG_RW_STATUS_OFFSET (0x00001C62) > +#define MPI3_SYSIF_DIAG_RW_STATUS_STATUS_MASK (0x0000000E) > +#define MPI3_SYSIF_DIAG_RW_STATUS_STATUS_SUCCESS (0x00000000) > +#define MPI3_SYSIF_DIAG_RW_STATUS_STATUS_INV_ADDR (0x00000002) > +#define MPI3_SYSIF_DIAG_RW_STATUS_STATUS_ACC_ERR (0x00000004) > +#define MPI3_SYSIF_DIAG_RW_STATUS_STATUS_PAR_ERR (0x00000006) > +#define MPI3_SYSIF_DIAG_RW_STATUS_BUSY (0x00000001) > + > +/**** Defines for Scratchpad registers ****/ > +#define MPI3_SYSIF_SCRATCHPAD0_OFFSET (0x00001CF0) > +#define MPI3_SYSIF_SCRATCHPAD1_OFFSET (0x00001CF4) > +#define MPI3_SYSIF_SCRATCHPAD2_OFFSET (0x00001CF8) > +#define MPI3_SYSIF_SCRATCHPAD3_OFFSET (0x00001CFC) > + > +/**** Defines for Device Assigned registers ****/ > +#define MPI3_SYSIF_DEVICE_ASSIGNED_REGS_OFFSET (0x00002000) > + > +/**** Default Defines for Diag Save Timeout ****/ > +#define MPI3_SYSIF_DIAG_SAVE_TIMEOUT (60) /* seconds */ > + > +/***************************************************************************** > + * Reply Descriptors * > + ****************************************************************************/ > + > +/***************************************************************************** > + * Default Reply Descriptor * > + ****************************************************************************/ > +typedef struct _MPI3_DEFAULT_REPLY_DESCRIPTOR { > + U32 DescriptorTypeDependent1[2]; /* 0x00 */ > + U16 RequestQueueCI; /* 0x08 */ > + U16 RequestQueueID; /* 0x0A */ > + U16 DescriptorTypeDependent2; /* 0x0C */ > + U16 ReplyFlags; /* 0x0E */ > +} MPI3_DEFAULT_REPLY_DESCRIPTOR, MPI3_POINTER PTR_MPI3_DEFAULT_REPLY_DESCRIPTOR, > + Mpi3DefaultReplyDescriptor_t, MPI3_POINTER pMpi3DefaultReplyDescriptor_t; > + > +/**** Defines for the ReplyFlags field ****/ > +#define MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK (0x0001) > +#define MPI3_REPLY_DESCRIPT_FLAGS_TYPE_MASK (0xF000) > +#define MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY (0x0000) > +#define MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS (0x1000) > +#define MPI3_REPLY_DESCRIPT_FLAGS_TYPE_TARGET_COMMAND_BUFFER (0x2000) > +#define MPI3_REPLY_DESCRIPT_FLAGS_TYPE_STATUS (0x3000) > + > +/***************************************************************************** > + * Address Reply Descriptor * > + ****************************************************************************/ > +typedef struct _MPI3_ADDRESS_REPLY_DESCRIPTOR { > + U64 ReplyFrameAddress; /* 0x00 */ > + U16 RequestQueueCI; /* 0x08 */ > + U16 RequestQueueID; /* 0x0A */ > + U16 Reserved0C; /* 0x0C */ > + U16 ReplyFlags; /* 0x0E */ > +} MPI3_ADDRESS_REPLY_DESCRIPTOR, MPI3_POINTER PTR_MPI3_ADDRESS_REPLY_DESCRIPTOR, > + Mpi3AddressReplyDescriptor_t, MPI3_POINTER pMpi3AddressReplyDescriptor_t; > + > +/***************************************************************************** > + * Success Reply Descriptor * > + ****************************************************************************/ > +typedef struct _MPI3_SUCCESS_REPLY_DESCRIPTOR { > + U32 Reserved00[2]; /* 0x00 */ > + U16 RequestQueueCI; /* 0x08 */ > + U16 RequestQueueID; /* 0x0A */ > + U16 HostTag; /* 0x0C */ > + U16 ReplyFlags; /* 0x0E */ > +} MPI3_SUCCESS_REPLY_DESCRIPTOR, MPI3_POINTER PTR_MPI3_SUCCESS_REPLY_DESCRIPTOR, > + Mpi3SuccessReplyDescriptor_t, MPI3_POINTER pMpi3SuccessReplyDescriptor_t; > + > +/***************************************************************************** > + * Target Command Buffer Reply Descriptor * > + ****************************************************************************/ > +typedef struct _MPI3_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR { > + U32 Reserved00; /* 0x00 */ > + U16 InitiatorDevHandle; /* 0x04 */ > + U8 PhyNum; /* 0x06 */ > + U8 Reserved07; /* 0x07 */ > + U16 RequestQueueCI; /* 0x08 */ > + U16 RequestQueueID; /* 0x0A */ > + U16 IOIndex; /* 0x0C */ > + U16 ReplyFlags; /* 0x0E */ > +} MPI3_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR, MPI3_POINTER PTR_MPI3_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR, > + Mpi3TargetCommandBufferReplyDescriptor_t, MPI3_POINTER pMpi3TargetCommandBufferReplyDescriptor_t; > + > +/**** See Default Reply Descriptor Defines above for definitions in the ReplyFlags field ****/ > + > +/***************************************************************************** > + * Status Reply Descriptor * > + ****************************************************************************/ > +typedef struct _MPI3_STATUS_REPLY_DESCRIPTOR { > + U16 IOCStatus; /* 0x00 */ > + U16 Reserved02; /* 0x02 */ > + U32 IOCLogInfo; /* 0x04 */ > + U16 RequestQueueCI; /* 0x08 */ > + U16 RequestQueueID; /* 0x0A */ > + U16 HostTag; /* 0x0C */ > + U16 ReplyFlags; /* 0x0E */ > +} MPI3_STATUS_REPLY_DESCRIPTOR, MPI3_POINTER PTR_MPI3_STATUS_REPLY_DESCRIPTOR, > + Mpi3StatusReplyDescriptor_t, MPI3_POINTER pMpi3StatusReplyDescriptor_t; > + > +/**** Defines for the IOCStatus field ****/ > +#define MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL (0x8000) > +#define MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK (0x7FFF) > + > +/**** Defines for the IOCLogInfo field ****/ > +#define MPI3_REPLY_DESCRIPT_STATUS_IOCLOGINFO_TYPE_MASK (0xF0000000) > +#define MPI3_REPLY_DESCRIPT_STATUS_IOCLOGINFO_TYPE_NO_INFO (0x00000000) > +#define MPI3_REPLY_DESCRIPT_STATUS_IOCLOGINFO_TYPE_SAS (0x30000000) > +#define MPI3_REPLY_DESCRIPT_STATUS_IOCLOGINFO_DATA_MASK (0x0FFFFFFF) > + > +/***************************************************************************** > + * Union of Reply Descriptors * > + ****************************************************************************/ > +typedef union _MPI3_REPLY_DESCRIPTORS_UNION { > + MPI3_DEFAULT_REPLY_DESCRIPTOR Default; > + MPI3_ADDRESS_REPLY_DESCRIPTOR AddressReply; > + MPI3_SUCCESS_REPLY_DESCRIPTOR Success; > + MPI3_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer; > + MPI3_STATUS_REPLY_DESCRIPTOR Status; > + U32 Words[4]; > +} MPI3_REPLY_DESCRIPTORS_UNION, MPI3_POINTER PTR_MPI3_REPLY_DESCRIPTORS_UNION, > + Mpi3ReplyDescriptorsUnion_t, MPI3_POINTER pMpi3ReplyDescriptorsUnion_t; > + > + > +/***************************************************************************** > + * Scatter Gather Elements * > + ****************************************************************************/ > + > +/***************************************************************************** > + * Common structure for Simple, Chain, and Last Chain * > + * scatter gather elements * > + ****************************************************************************/ > +typedef struct _MPI3_SGE_COMMON { > + U64 Address; /* 0x00 */ > + U32 Length; /* 0x08 */ > + U8 Reserved0C[3]; /* 0x0C */ > + U8 Flags; /* 0x0F */ > +} MPI3_SGE_SIMPLE, MPI3_POINTER PTR_MPI3_SGE_SIMPLE, > + Mpi3SGESimple_t, MPI3_POINTER pMpi3SGESimple_t, > + MPI3_SGE_CHAIN, MPI3_POINTER PTR_MPI3_SGE_CHAIN, > + Mpi3SGEChain_t, MPI3_POINTER pMpi3SGEChain_t, > + MPI3_SGE_LAST_CHAIN, MPI3_POINTER PTR_MPI3_SGE_LAST_CHAIN, > + Mpi3SGELastChain_t, MPI3_POINTER pMpi3SGELastChain_t; > + ... well; 12 Names? C'mon .. > +/***************************************************************************** > + * Bit Bucket scatter gather element * > + ****************************************************************************/ > +typedef struct _MPI3_SGE_BIT_BUCKET { > + U64 Reserved00; /* 0x00 */ > + U32 Length; /* 0x08 */ > + U8 Reserved0C[3]; /* 0x0C */ > + U8 Flags; /* 0x0F */ > +} MPI3_SGE_BIT_BUCKET, MPI3_POINTER PTR_MPI3_SGE_BIT_BUCKET, > + Mpi3SGEBitBucket, MPI3_POINTER pMpi3SGEBitBucket; > + > +/***************************************************************************** > + * Extended EEDP scatter gather element * > + ****************************************************************************/ > +typedef struct _MPI3_SGE_EXTENDED_EEDP { > + U8 UserDataSize; /* 0x00 */ > + U8 Reserved01; /* 0x01 */ > + U16 EEDPFlags; /* 0x02 */ > + U32 SecondaryReferenceTag; /* 0x04 */ > + U16 SecondaryApplicationTag; /* 0x08 */ > + U16 ApplicationTagTranslationMask; /* 0x0A */ > + U16 Reserved0C; /* 0x0C */ > + U8 ExtendedOperation; /* 0x0E */ > + U8 Flags; /* 0x0F */ > +} MPI3_SGE_EXTENDED_EEDP, MPI3_POINTER PTR_MPI3_SGE_EXTENDED_EEDP, > + Mpi3SGEExtendedEEDP_t, MPI3_POINTER pMpi3SGEExtendedEEDP_t; > + > +/***************************************************************************** > + * Union of scatter gather elements * > + ****************************************************************************/ > +typedef union _MPI3_SGE_UNION { > + MPI3_SGE_SIMPLE Simple; > + MPI3_SGE_CHAIN Chain; > + MPI3_SGE_LAST_CHAIN LastChain; > + MPI3_SGE_BIT_BUCKET BitBucket; > + MPI3_SGE_EXTENDED_EEDP Eedp; > + U32 Words[4]; > +} MPI3_SGE_UNION, MPI3_POINTER PTR_MPI3_SGE_UNION, > + Mpi3SGEUnion_t, MPI3_POINTER pMpi3SGEUnion_t; > + > +/**** Definitions for the Flags field ****/ > +#define MPI3_SGE_FLAGS_ELEMENT_TYPE_MASK (0xF0) > +#define MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE (0x00) > +#define MPI3_SGE_FLAGS_ELEMENT_TYPE_BIT_BUCKET (0x10) > +#define MPI3_SGE_FLAGS_ELEMENT_TYPE_CHAIN (0x20) > +#define MPI3_SGE_FLAGS_ELEMENT_TYPE_LAST_CHAIN (0x30) > +#define MPI3_SGE_FLAGS_ELEMENT_TYPE_EXTENDED (0xF0) > +#define MPI3_SGE_FLAGS_END_OF_LIST (0x08) > +#define MPI3_SGE_FLAGS_END_OF_BUFFER (0x04) > +#define MPI3_SGE_FLAGS_DLAS_MASK (0x03) > +#define MPI3_SGE_FLAGS_DLAS_SYSTEM (0x00) > +#define MPI3_SGE_FLAGS_DLAS_IOC_DDR (0x01) > +#define MPI3_SGE_FLAGS_DLAS_IOC_CTL (0x02) > + > +/**** Definitions for the ExtendedOperation field of Extended element ****/ > +#define MPI3_SGE_EXT_OPER_EEDP (0x00) > + > +/**** Definitions for the EEDPFlags field of Extended EEDP element ****/ > +#define MPI3_EEDPFLAGS_INCR_PRI_REF_TAG (0x8000) > +#define MPI3_EEDPFLAGS_INCR_SEC_REF_TAG (0x4000) > +#define MPI3_EEDPFLAGS_INCR_PRI_APP_TAG (0x2000) > +#define MPI3_EEDPFLAGS_INCR_SEC_APP_TAG (0x1000) > +#define MPI3_EEDPFLAGS_ESC_PASSTHROUGH (0x0800) > +#define MPI3_EEDPFLAGS_CHK_REF_TAG (0x0400) > +#define MPI3_EEDPFLAGS_CHK_APP_TAG (0x0200) > +#define MPI3_EEDPFLAGS_CHK_GUARD (0x0100) > +#define MPI3_EEDPFLAGS_ESC_MODE_MASK (0x00C0) > +#define MPI3_EEDPFLAGS_ESC_MODE_DO_NOT_DISABLE (0x0040) > +#define MPI3_EEDPFLAGS_ESC_MODE_APPTAG_DISABLE (0x0080) > +#define MPI3_EEDPFLAGS_ESC_MODE_APPTAG_REFTAG_DISABLE (0x00C0) > +#define MPI3_EEDPFLAGS_HOST_GUARD_MASK (0x0030) > +#define MPI3_EEDPFLAGS_HOST_GUARD_T10_CRC (0x0000) > +#define MPI3_EEDPFLAGS_HOST_GUARD_IP_CHKSUM (0x0010) > +#define MPI3_EEDPFLAGS_HOST_GUARD_OEM_SPECIFIC (0x0020) > +#define MPI3_EEDPFLAGS_PT_REF_TAG (0x0008) > +#define MPI3_EEDPFLAGS_EEDP_OP_MASK (0x0007) > +#define MPI3_EEDPFLAGS_EEDP_OP_NOOP (0x0000) > +#define MPI3_EEDPFLAGS_EEDP_OP_CHECK (0x0001) > +#define MPI3_EEDPFLAGS_EEDP_OP_STRIP (0x0002) > +#define MPI3_EEDPFLAGS_EEDP_OP_CHECK_REMOVE (0x0003) > +#define MPI3_EEDPFLAGS_EEDP_OP_INSERT (0x0004) > +#define MPI3_EEDPFLAGS_EEDP_OP_REPLACE (0x0006) > +#define MPI3_EEDPFLAGS_EEDP_OP_CHECK_REGEN (0x0007) > + > +/**** Definitions for the UserDataSize field of Extended EEDP element ****/ > +#define MPI3_EEDP_UDS_512 (0x01) > +#define MPI3_EEDP_UDS_520 (0x02) > +#define MPI3_EEDP_UDS_4080 (0x03) > +#define MPI3_EEDP_UDS_4088 (0x04) > +#define MPI3_EEDP_UDS_4096 (0x05) > +#define MPI3_EEDP_UDS_4104 (0x06) > +#define MPI3_EEDP_UDS_4160 (0x07) > + > +/***************************************************************************** > + * Standard Message Structures * > + ****************************************************************************/ > + > +/***************************************************************************** > + * Request Message Header for all request messages * > + ****************************************************************************/ > +typedef struct _MPI3_REQUEST_HEADER { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 ChangeCount; /* 0x08 */ > + U16 FunctionDependent; /* 0x0A */ > +} MPI3_REQUEST_HEADER, MPI3_POINTER PTR_MPI3_REQUEST_HEADER, > + Mpi3RequestHeader_t, MPI3_POINTER pMpi3RequestHeader_t; > + > +/***************************************************************************** > + * Default Reply * > + ****************************************************************************/ > +typedef struct _MPI3_DEFAULT_REPLY { > + U16 HostTag; /* 0x00 */ > + U8 IOCUseOnly02; /* 0x02 */ > + U8 Function; /* 0x03 */ > + U16 IOCUseOnly04; /* 0x04 */ > + U8 IOCUseOnly06; /* 0x06 */ > + U8 MsgFlags; /* 0x07 */ > + U16 IOCUseOnly08; /* 0x08 */ > + U16 IOCStatus; /* 0x0A */ > + U32 IOCLogInfo; /* 0x0C */ > +} MPI3_DEFAULT_REPLY, MPI3_POINTER PTR_MPI3_DEFAULT_REPLY, > + Mpi3DefaultReply_t, MPI3_POINTER pMpi3DefaultReply_t; > + > +/**** Defines for the HostTag field ****/ > +#define MPI3_HOST_TAG_INVALID (0xFFFF) > + > +/**** Defines for message Function ****/ > +/* I/O Controller functions */ > +#define MPI3_FUNCTION_IOC_FACTS (0x01) /* IOC Facts */ > +#define MPI3_FUNCTION_IOC_INIT (0x02) /* IOC Init */ > +#define MPI3_FUNCTION_PORT_ENABLE (0x03) /* Port Enable */ > +#define MPI3_FUNCTION_EVENT_NOTIFICATION (0x04) /* Event Notification */ > +#define MPI3_FUNCTION_EVENT_ACK (0x05) /* Event Acknowledge */ > +#define MPI3_FUNCTION_CI_DOWNLOAD (0x06) /* Component Image Download */ > +#define MPI3_FUNCTION_CI_UPLOAD (0x07) /* Component Image Upload */ > +#define MPI3_FUNCTION_IO_UNIT_CONTROL (0x08) /* IO Unit Control */ > +#define MPI3_FUNCTION_PERSISTENT_EVENT_LOG (0x09) /* Persistent Event Log */ > +#define MPI3_FUNCTION_MGMT_PASSTHROUGH (0x0A) /* Management Passthrough */ > +#define MPI3_FUNCTION_CONFIG (0x10) /* Configuration */ > + > +/* SCSI Initiator I/O functions */ > +#define MPI3_FUNCTION_SCSI_IO (0x20) /* SCSI IO */ > +#define MPI3_FUNCTION_SCSI_TASK_MGMT (0x21) /* SCSI Task Management */ > +#define MPI3_FUNCTION_SMP_PASSTHROUGH (0x22) /* SMP Passthrough */ > +#define MPI3_FUNCTION_NVME_ENCAPSULATED (0x24) /* NVMe Encapsulated */ > + > +/* SCSI Target I/O functions */ > +#define MPI3_FUNCTION_TARGET_ASSIST (0x30) /* Target Assist */ > +#define MPI3_FUNCTION_TARGET_STATUS_SEND (0x31) /* Target Status Send */ > +#define MPI3_FUNCTION_TARGET_MODE_ABORT (0x32) /* Target Mode Abort */ > +#define MPI3_FUNCTION_TARGET_CMD_BUF_POST_BASE (0x33) /* Target Command Buffer Post Base */ > +#define MPI3_FUNCTION_TARGET_CMD_BUF_POST_LIST (0x34) /* Target Command Buffer Post List */ > + > +/* Queue Management functions */ > +#define MPI3_FUNCTION_CREATE_REQUEST_QUEUE (0x70) /* Create an operational request queue */ > +#define MPI3_FUNCTION_DELETE_REQUEST_QUEUE (0x71) /* Delete an operational request queue */ > +#define MPI3_FUNCTION_CREATE_REPLY_QUEUE (0x72) /* Create an operational reply queue */ > +#define MPI3_FUNCTION_DELETE_REPLY_QUEUE (0x73) /* Delete an operational reply queue */ > + > +/* Diagnostic Tools */ > +#define MPI3_FUNCTION_TOOLBOX (0x80) /* Toolbox */ > +#define MPI3_FUNCTION_DIAG_BUFFER_POST (0x81) /* Post a Diagnostic Buffer to the I/O Unit */ > +#define MPI3_FUNCTION_DIAG_BUFFER_MANAGE (0x82) /* Manage a Diagnostic Buffer */ > +#define MPI3_FUNCTION_DIAG_BUFFER_UPLOAD (0x83) /* Upload a Diagnostic Buffer */ > + > +/* Miscellaneous functions */ > +#define MPI3_FUNCTION_MIN_IOC_USE_ONLY (0xC0) /* Beginning of IOC Use Only range of function codes */ > +#define MPI3_FUNCTION_MAX_IOC_USE_ONLY (0xEF) /* End of IOC Use Only range of function codes */ > +#define MPI3_FUNCTION_MIN_PRODUCT_SPECIFIC (0xF0) /* Beginning of the product-specific range of function codes */ > +#define MPI3_FUNCTION_MAX_PRODUCT_SPECIFIC (0xFF) /* End of the product-specific range of function codes */ > + > +/**** Defines for IOCStatus ****/ > +#define MPI3_IOCSTATUS_LOG_INFO_AVAIL_MASK (0x8000) > +#define MPI3_IOCSTATUS_LOG_INFO_AVAILABLE (0x8000) > +#define MPI3_IOCSTATUS_STATUS_MASK (0x7FFF) > + > +/* Common IOCStatus values for all replies */ > +#define MPI3_IOCSTATUS_SUCCESS (0x0000) > +#define MPI3_IOCSTATUS_INVALID_FUNCTION (0x0001) > +#define MPI3_IOCSTATUS_BUSY (0x0002) > +#define MPI3_IOCSTATUS_INVALID_SGL (0x0003) > +#define MPI3_IOCSTATUS_INTERNAL_ERROR (0x0004) > +#define MPI3_IOCSTATUS_INSUFFICIENT_RESOURCES (0x0006) > +#define MPI3_IOCSTATUS_INVALID_FIELD (0x0007) > +#define MPI3_IOCSTATUS_INVALID_STATE (0x0008) > +#define MPI3_IOCSTATUS_INSUFFICIENT_POWER (0x000A) > +#define MPI3_IOCSTATUS_INVALID_CHANGE_COUNT (0x000B) > +#define MPI3_IOCSTATUS_FAILURE (0x001F) > + > +/* Config IOCStatus values */ > +#define MPI3_IOCSTATUS_CONFIG_INVALID_ACTION (0x0020) > +#define MPI3_IOCSTATUS_CONFIG_INVALID_TYPE (0x0021) > +#define MPI3_IOCSTATUS_CONFIG_INVALID_PAGE (0x0022) > +#define MPI3_IOCSTATUS_CONFIG_INVALID_DATA (0x0023) > +#define MPI3_IOCSTATUS_CONFIG_NO_DEFAULTS (0x0024) > +#define MPI3_IOCSTATUS_CONFIG_CANT_COMMIT (0x0025) > + > +/* SCSI IO IOCStatus values */ > +#define MPI3_IOCSTATUS_SCSI_RECOVERED_ERROR (0x0040) > +#define MPI3_IOCSTATUS_SCSI_TM_NOT_SUPPORTED (0x0041) > +#define MPI3_IOCSTATUS_SCSI_INVALID_DEVHANDLE (0x0042) > +#define MPI3_IOCSTATUS_SCSI_DEVICE_NOT_THERE (0x0043) > +#define MPI3_IOCSTATUS_SCSI_DATA_OVERRUN (0x0044) > +#define MPI3_IOCSTATUS_SCSI_DATA_UNDERRUN (0x0045) > +#define MPI3_IOCSTATUS_SCSI_IO_DATA_ERROR (0x0046) > +#define MPI3_IOCSTATUS_SCSI_PROTOCOL_ERROR (0x0047) > +#define MPI3_IOCSTATUS_SCSI_TASK_TERMINATED (0x0048) > +#define MPI3_IOCSTATUS_SCSI_RESIDUAL_MISMATCH (0x0049) > +#define MPI3_IOCSTATUS_SCSI_TASK_MGMT_FAILED (0x004A) > +#define MPI3_IOCSTATUS_SCSI_IOC_TERMINATED (0x004B) > +#define MPI3_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C) > + > +/* SCSI Initiator and SCSI Target end-to-end data protection values */ > +#define MPI3_IOCSTATUS_EEDP_GUARD_ERROR (0x004D) > +#define MPI3_IOCSTATUS_EEDP_REF_TAG_ERROR (0x004E) > +#define MPI3_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F) > + > +/* SCSI Target IOCStatus values */ > +#define MPI3_IOCSTATUS_TARGET_INVALID_IO_INDEX (0x0062) > +#define MPI3_IOCSTATUS_TARGET_ABORTED (0x0063) > +#define MPI3_IOCSTATUS_TARGET_NO_CONN_RETRYABLE (0x0064) > +#define MPI3_IOCSTATUS_TARGET_NO_CONNECTION (0x0065) > +#define MPI3_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A) > +#define MPI3_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D) > +#define MPI3_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E) > +#define MPI3_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F) > +#define MPI3_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070) > +#define MPI3_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071) > + > +/* Serial Attached SCSI IOCStatus values */ > +#define MPI3_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090) > +#define MPI3_IOCSTATUS_SAS_SMP_DATA_OVERRUN (0x0091) > + > +/* Diagnostic Buffer Post/Release IOCStatus values */ > +#define MPI3_IOCSTATUS_DIAGNOSTIC_RELEASED (0x00A0) > + > +/* Component Image Upload/Download */ > +#define MPI3_IOCSTATUS_CI_UNSUPPORTED (0x00B0) > +#define MPI3_IOCSTATUS_CI_UPDATE_SEQUENCE (0x00B1) > +#define MPI3_IOCSTATUS_CI_VALIDATION_FAILED (0x00B2) > +#define MPI3_IOCSTATUS_CI_UPDATE_PENDING (0x00B3) > + > +/* Security values */ > +#define MPI3_IOCSTATUS_SECURITY_KEY_REQUIRED (0x00C0) > + > +/* Request and Reply Queues related IOCStatus values */ > +#define MPI3_IOCSTATUS_INVALID_QUEUE_ID (0x0F00) > +#define MPI3_IOCSTATUS_INVALID_QUEUE_SIZE (0x0F01) > +#define MPI3_IOCSTATUS_INVALID_MSIX_VECTOR (0x0F02) > +#define MPI3_IOCSTATUS_INVALID_REPLY_QUEUE_ID (0x0F03) > +#define MPI3_IOCSTATUS_INVALID_QUEUE_DELETION (0x0F04) > + > +/**** Defines for IOCLogInfo ****/ > +#define MPI3_IOCLOGINFO_TYPE_MASK (0xF0000000) > +#define MPI3_IOCLOGINFO_TYPE_SHIFT (28) > +#define MPI3_IOCLOGINFO_TYPE_NONE (0x0) > +#define MPI3_IOCLOGINFO_TYPE_SAS (0x3) > +#define MPI3_IOCLOGINFO_LOG_DATA_MASK (0x0FFFFFFF) > + > +#endif /* MPI30_TRANSPORT_H */ > diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_type.h b/drivers/scsi/mpi3mr/mpi/mpi30_type.h > new file mode 100644 > index 000000000000..7108a9ced1ec > --- /dev/null > +++ b/drivers/scsi/mpi3mr/mpi/mpi30_type.h > @@ -0,0 +1,20 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * Copyright 2016-2020 Broadcom Inc. All rights reserved. > + * > + * Name: mpi30_type.h > + * Description: MPI basic type definitions > + * Creation Date: 10/07/2016 > + * Version: 03.00.00 > + */ > +#ifndef MPI30_TYPE_H > +#define MPI30_TYPE_H 1 > + > +#define MPI3_POINTER * > + > +typedef u8 U8; > +typedef __le16 U16; > +typedef __le32 U32; > +typedef __le64 U64 __aligned(4); > + > +#endif /* MPI30_TYPE_H */ > I still think that these typedefs should be dropped, but okay... Cheers, Hannes -- Dr. Hannes Reinecke Kernel Storage Architect hare@suse.de +49 911 74053 688 SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer
> > +#ifndef MPI30_TYPE_H > > +#define MPI30_TYPE_H 1 > > + > > +#define MPI3_POINTER * > > + > > +typedef u8 U8; > > +typedef __le16 U16; > > +typedef __le32 U32; > > +typedef __le64 U64 __aligned(4); > > + > > +#endif /* MPI30_TYPE_H */ > > > I still think that these typedefs should be dropped, but okay... Hannes- I had internal discussion within a Broadcom and explain the outstanding concerns from this patch series. Primary concern is MPI3 header coding standard. I am working to resolve all of them and I will be sending V4 soon. Kashyap > > Cheers, > > Hannes > -- > Dr. Hannes Reinecke Kernel Storage Architect > hare@suse.de +49 911 74053 688 > SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg > HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer
On 4/19/21 1:01 PM, Kashyap Desai wrote: > 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 h/w 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 set <ephase> bit and IOC invert the value of this bit on each pass. > > Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> > Reviewed-by: Hannes Reinecke <hare@suse.de> > Reviewed-by: Tomas Henzl <thenzl@redhat.com> > > Cc: sathya.prakash@broadcom.com > --- > drivers/scsi/mpi3mr/mpi3mr.h | 56 +++ > drivers/scsi/mpi3mr/mpi3mr_fw.c | 601 ++++++++++++++++++++++++++++++++ > drivers/scsi/mpi3mr/mpi3mr_os.c | 4 +- > 3 files changed, 660 insertions(+), 1 deletion(-) > > diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h > index cf1cfea19826..c26105b23759 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr.h > +++ b/drivers/scsi/mpi3mr/mpi3mr.h > @@ -71,6 +71,12 @@ extern struct list_head mrioc_list; > #define MPI3MR_ADMIN_REQ_FRAME_SZ 128 > #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 */ > #define MPI3MR_HOSTTAG_INVALID 0xFFFF > @@ -132,6 +138,9 @@ extern struct list_head mrioc_list; > (MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM | \ > 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 */ > enum mpi3mr_iocstate { > MRIOC_STATE_READY = 1, > @@ -222,15 +231,45 @@ struct mpi3mr_ioc_facts { > 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 > * > * @ci: consumer 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 { > u16 ci; > 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; > }; > > /** > @@ -238,10 +277,24 @@ struct op_req_qinfo { > * > * @ci: consumer index > * @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 { > u16 ci; > 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; > }; > > /** > @@ -401,6 +454,7 @@ struct scmd_priv { > * @current_event: Firmware event currently in process > * @driver_info: Driver, Kernel, OS information to firmware > * @change_count: Topology change count > + * @op_reply_q_offset: Operational reply queue offset with MSIx > */ > struct mpi3mr_ioc { > struct list_head list; > @@ -408,6 +462,7 @@ struct mpi3mr_ioc { > struct Scsi_Host *shost; > u8 id; > int cpu_count; > + bool enable_segqueue; > > char name[MPI3MR_NAME_LENGTH]; > char driver_name[MPI3MR_NAME_LENGTH]; > @@ -494,6 +549,7 @@ struct mpi3mr_ioc { > struct mpi3mr_fwevt *current_event; > Mpi3DriverInfoLayout_t driver_info; > u16 change_count; > + u16 op_reply_q_offset; > }; > > int mpi3mr_setup_resources(struct mpi3mr_ioc *mrioc); > diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c > index 330f675444e9..694e54bbb07c 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c > @@ -405,6 +405,8 @@ static int mpi3mr_setup_isr(struct mpi3mr_ioc *mrioc, u8 setup_one) > > irq_flags |= PCI_IRQ_AFFINITY | PCI_IRQ_ALL_TYPES; > > + mrioc->op_reply_q_offset = (max_vectors > 1) ? 1 : 0; > + > i = pci_alloc_irq_vectors_affinity(mrioc->pdev, > 1, max_vectors, irq_flags, &desc); > if (i <= 0) { > @@ -415,6 +417,12 @@ static int mpi3mr_setup_isr(struct mpi3mr_ioc *mrioc, u8 setup_one) > ioc_info(mrioc, > "allocated vectors (%d) are less than configured (%d)\n", > i, max_vectors); > + /* > + * If only one MSI-x is allocated, then MSI-x 0 will be shared > + * between Admin queue and operational queue > + */ > + if (i == 1) > + mrioc->op_reply_q_offset = 0; > > max_vectors = i; > } > @@ -723,6 +731,586 @@ int mpi3mr_admin_request_post(struct mpi3mr_ioc *mrioc, void *admin_req, > return retval; > } > > +/** > + * mpi3mr_free_op_req_q_segments - free request memory segments > + * @mrioc: Adapter instance reference > + * @q_idx: operational request queue index > + * > + * Free memory segments allocated for operational request queue > + * > + * Return: Nothing. > + */ > +static void mpi3mr_free_op_req_q_segments(struct mpi3mr_ioc *mrioc, u16 q_idx) > +{ > + u16 j; > + int size; > + struct segments *segments; > + > + segments = mrioc->req_qinfo[q_idx].q_segments; > + if (!segments) > + return; > + > + if (mrioc->enable_segqueue) { > + size = MPI3MR_OP_REQ_Q_SEG_SIZE; > + if (mrioc->req_qinfo[q_idx].q_segment_list) { > + dma_free_coherent(&mrioc->pdev->dev, > + MPI3MR_MAX_SEG_LIST_SIZE, > + mrioc->req_qinfo[q_idx].q_segment_list, > + mrioc->req_qinfo[q_idx].q_segment_list_dma); > + mrioc->op_reply_qinfo[q_idx].q_segment_list = NULL; > + } > + } else > + size = mrioc->req_qinfo[q_idx].num_requests * > + mrioc->facts.op_req_sz; > + > + for (j = 0; j < mrioc->req_qinfo[q_idx].num_segments; j++) { > + if (!segments[j].segment) > + continue; > + dma_free_coherent(&mrioc->pdev->dev, > + size, segments[j].segment, segments[j].segment_dma); > + segments[j].segment = NULL; > + } > + kfree(mrioc->req_qinfo[q_idx].q_segments); > + mrioc->req_qinfo[q_idx].q_segments = NULL; > + mrioc->req_qinfo[q_idx].qid = 0; > +} > + > +/** > + * mpi3mr_free_op_reply_q_segments - free reply memory segments > + * @mrioc: Adapter instance reference > + * @q_idx: operational reply queue index > + * > + * Free memory segments allocated for operational reply queue > + * > + * Return: Nothing. > + */ > +static void mpi3mr_free_op_reply_q_segments(struct mpi3mr_ioc *mrioc, u16 q_idx) > +{ > + u16 j; > + int size; > + struct segments *segments; > + > + segments = mrioc->op_reply_qinfo[q_idx].q_segments; > + if (!segments) > + return; > + > + if (mrioc->enable_segqueue) { > + size = MPI3MR_OP_REP_Q_SEG_SIZE; > + if (mrioc->op_reply_qinfo[q_idx].q_segment_list) { > + dma_free_coherent(&mrioc->pdev->dev, > + MPI3MR_MAX_SEG_LIST_SIZE, > + mrioc->op_reply_qinfo[q_idx].q_segment_list, > + mrioc->op_reply_qinfo[q_idx].q_segment_list_dma); > + mrioc->op_reply_qinfo[q_idx].q_segment_list = NULL; > + } > + } else > + size = mrioc->op_reply_qinfo[q_idx].segment_qd * > + mrioc->op_reply_desc_sz; > + > + for (j = 0; j < mrioc->op_reply_qinfo[q_idx].num_segments; j++) { > + if (!segments[j].segment) > + continue; > + dma_free_coherent(&mrioc->pdev->dev, > + size, segments[j].segment, segments[j].segment_dma); > + segments[j].segment = NULL; > + } > + > + kfree(mrioc->op_reply_qinfo[q_idx].q_segments); > + mrioc->op_reply_qinfo[q_idx].q_segments = NULL; > + mrioc->op_reply_qinfo[q_idx].qid = 0; > +} > + > +/** > + * mpi3mr_delete_op_reply_q - delete operational reply queue > + * @mrioc: Adapter instance reference > + * @qidx: operational reply queue index > + * > + * Delete operatinal reply queue by issuing MPI request > + * through admin queue. > + * > + * Return: 0 on success, non-zero on failure. > + */ > +static int mpi3mr_delete_op_reply_q(struct mpi3mr_ioc *mrioc, u16 qidx) > +{ > + Mpi3DeleteReplyQueueRequest_t delq_req; > + int retval = 0; > + u16 reply_qid = 0, midx; > + > + reply_qid = mrioc->op_reply_qinfo[qidx].qid; > + > + midx = REPLY_QUEUE_IDX_TO_MSIX_IDX(qidx, mrioc->op_reply_q_offset); > + > + if (!reply_qid) { > + retval = -1; > + ioc_err(mrioc, "Issue DelRepQ: called with invalid ReqQID\n"); > + goto out; > + } > + > + memset(&delq_req, 0, sizeof(delq_req)); > + mutex_lock(&mrioc->init_cmds.mutex); > + if (mrioc->init_cmds.state & MPI3MR_CMD_PENDING) { > + retval = -1; > + ioc_err(mrioc, "Issue DelRepQ: Init command is in use\n"); > + mutex_unlock(&mrioc->init_cmds.mutex); > + goto out; > + } > + mrioc->init_cmds.state = MPI3MR_CMD_PENDING; > + mrioc->init_cmds.is_waiting = 1; > + mrioc->init_cmds.callback = NULL; > + delq_req.HostTag = cpu_to_le16(MPI3MR_HOSTTAG_INITCMDS); > + delq_req.Function = MPI3_FUNCTION_DELETE_REPLY_QUEUE; > + delq_req.QueueID = cpu_to_le16(reply_qid); > + > + init_completion(&mrioc->init_cmds.done); > + retval = mpi3mr_admin_request_post(mrioc, &delq_req, sizeof(delq_req), > + 1); > + if (retval) { > + ioc_err(mrioc, "Issue DelRepQ: Admin Post failed\n"); > + goto out_unlock; > + } > + wait_for_completion_timeout(&mrioc->init_cmds.done, > + (MPI3MR_INTADMCMD_TIMEOUT * HZ)); > + if (!(mrioc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { > + ioc_err(mrioc, "Issue DelRepQ: command timed out\n"); > + mpi3mr_set_diagsave(mrioc); > + mpi3mr_issue_reset(mrioc, > + MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, > + MPI3MR_RESET_FROM_DELREPQ_TIMEOUT); > + mrioc->unrecoverable = 1; > + > + retval = -1; > + goto out_unlock; > + } > + if ((mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) > + != MPI3_IOCSTATUS_SUCCESS) { > + ioc_err(mrioc, > + "Issue DelRepQ: Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n", > + (mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), > + mrioc->init_cmds.ioc_loginfo); > + retval = -1; > + goto out_unlock; > + } > + mrioc->intr_info[midx].op_reply_q = NULL; > + > + mpi3mr_free_op_reply_q_segments(mrioc, qidx); > +out_unlock: > + mrioc->init_cmds.state = MPI3MR_CMD_NOTUSED; > + mutex_unlock(&mrioc->init_cmds.mutex); > +out: > + > + return retval; > +} > + > +/** > + * mpi3mr_alloc_op_reply_q_segments -Alloc segmented reply pool > + * @mrioc: Adapter instance reference > + * @qidx: request queue index > + * > + * Allocate segmented memory pools for operational reply > + * queue. > + * > + * Return: 0 on success, non-zero on failure. > + */ > +static int mpi3mr_alloc_op_reply_q_segments(struct mpi3mr_ioc *mrioc, u16 qidx) > +{ > + struct op_reply_qinfo *op_reply_q = mrioc->op_reply_qinfo + qidx; > + int i, size; > + u64 *q_segment_list_entry = NULL; > + struct segments *segments; > + > + if (mrioc->enable_segqueue) { > + op_reply_q->segment_qd = > + MPI3MR_OP_REP_Q_SEG_SIZE / mrioc->op_reply_desc_sz; > + > + size = MPI3MR_OP_REP_Q_SEG_SIZE; > + > + op_reply_q->q_segment_list = dma_alloc_coherent(&mrioc->pdev->dev, > + MPI3MR_MAX_SEG_LIST_SIZE, &op_reply_q->q_segment_list_dma, > + GFP_KERNEL); > + if (!op_reply_q->q_segment_list) > + return -ENOMEM; > + q_segment_list_entry = (u64 *)op_reply_q->q_segment_list; > + } else { > + op_reply_q->segment_qd = op_reply_q->num_replies; > + size = op_reply_q->num_replies * mrioc->op_reply_desc_sz; > + } > + > + op_reply_q->num_segments = DIV_ROUND_UP(op_reply_q->num_replies, > + op_reply_q->segment_qd); > + > + op_reply_q->q_segments = kcalloc(op_reply_q->num_segments, > + sizeof(struct segments), GFP_KERNEL); > + if (!op_reply_q->q_segments) > + return -ENOMEM; > + > + segments = op_reply_q->q_segments; > + for (i = 0; i < op_reply_q->num_segments; i++) { > + segments[i].segment = > + dma_alloc_coherent(&mrioc->pdev->dev, > + size, &segments[i].segment_dma, GFP_KERNEL); > + if (!segments[i].segment) > + return -ENOMEM; > + if (mrioc->enable_segqueue) > + q_segment_list_entry[i] = > + (unsigned long)segments[i].segment_dma; > + } > + > + return 0; > +} > + > +/** > + * mpi3mr_alloc_op_req_q_segments - Alloc segmented req pool. > + * @mrioc: Adapter instance reference > + * @qidx: request queue index > + * > + * Allocate segmented memory pools for operational request > + * queue. > + * > + * Return: 0 on success, non-zero on failure. > + */ > +static int mpi3mr_alloc_op_req_q_segments(struct mpi3mr_ioc *mrioc, u16 qidx) > +{ > + struct op_req_qinfo *op_req_q = mrioc->req_qinfo + qidx; > + int i, size; > + u64 *q_segment_list_entry = NULL; > + struct segments *segments; > + > + if (mrioc->enable_segqueue) { > + op_req_q->segment_qd = > + MPI3MR_OP_REQ_Q_SEG_SIZE / mrioc->facts.op_req_sz; > + > + size = MPI3MR_OP_REQ_Q_SEG_SIZE; > + > + op_req_q->q_segment_list = dma_alloc_coherent(&mrioc->pdev->dev, > + MPI3MR_MAX_SEG_LIST_SIZE, &op_req_q->q_segment_list_dma, > + GFP_KERNEL); > + if (!op_req_q->q_segment_list) > + return -ENOMEM; > + q_segment_list_entry = (u64 *)op_req_q->q_segment_list; > + > + } else { > + op_req_q->segment_qd = op_req_q->num_requests; > + size = op_req_q->num_requests * mrioc->facts.op_req_sz; > + } > + > + op_req_q->num_segments = DIV_ROUND_UP(op_req_q->num_requests, > + op_req_q->segment_qd); > + > + op_req_q->q_segments = kcalloc(op_req_q->num_segments, > + sizeof(struct segments), GFP_KERNEL); > + if (!op_req_q->q_segments) > + return -ENOMEM; > + > + segments = op_req_q->q_segments; > + for (i = 0; i < op_req_q->num_segments; i++) { > + segments[i].segment = > + dma_alloc_coherent(&mrioc->pdev->dev, > + size, &segments[i].segment_dma, GFP_KERNEL); > + if (!segments[i].segment) > + return -ENOMEM; > + if (mrioc->enable_segqueue) > + q_segment_list_entry[i] = > + (unsigned long)segments[i].segment_dma; > + } > + > + return 0; > +} > + > +/** > + * mpi3mr_create_op_reply_q - create operational reply queue > + * @mrioc: Adapter instance reference > + * @qidx: operational reply queue index > + * > + * Create operatinal reply queue by issuing MPI request > + * through admin queue. > + * > + * Return: 0 on success, non-zero on failure. > + */ > +static int mpi3mr_create_op_reply_q(struct mpi3mr_ioc *mrioc, u16 qidx) > +{ > + Mpi3CreateReplyQueueRequest_t create_req; > + struct op_reply_qinfo *op_reply_q = mrioc->op_reply_qinfo + qidx; > + int retval = 0; > + u16 reply_qid = 0, midx; > + > + > + reply_qid = op_reply_q->qid; > + > + midx = REPLY_QUEUE_IDX_TO_MSIX_IDX(qidx, mrioc->op_reply_q_offset); > + > + if (reply_qid) { > + retval = -1; > + ioc_err(mrioc, "CreateRepQ: called for duplicate qid %d\n", > + reply_qid); > + > + return retval; > + } > + > + reply_qid = qidx + 1; > + op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD; > + op_reply_q->ci = 0; > + op_reply_q->ephase = 1; > + > + if (!op_reply_q->q_segments) { > + retval = mpi3mr_alloc_op_reply_q_segments(mrioc, qidx); > + if (retval) { > + mpi3mr_free_op_reply_q_segments(mrioc, qidx); > + goto out; > + } > + } > + > + memset(&create_req, 0, sizeof(create_req)); > + mutex_lock(&mrioc->init_cmds.mutex); > + if (mrioc->init_cmds.state & MPI3MR_CMD_PENDING) { > + retval = -1; > + ioc_err(mrioc, "CreateRepQ: Init command is in use\n"); > + goto out; > + } > + mrioc->init_cmds.state = MPI3MR_CMD_PENDING; > + mrioc->init_cmds.is_waiting = 1; > + mrioc->init_cmds.callback = NULL; > + create_req.HostTag = cpu_to_le16(MPI3MR_HOSTTAG_INITCMDS); > + create_req.Function = MPI3_FUNCTION_CREATE_REPLY_QUEUE; > + create_req.QueueID = cpu_to_le16(reply_qid); > + create_req.Flags = MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_ENABLE; > + create_req.MSIxIndex = cpu_to_le16(mrioc->intr_info[midx].msix_index); > + if (mrioc->enable_segqueue) { > + create_req.Flags |= > + MPI3_CREATE_REQUEST_QUEUE_FLAGS_SEGMENTED_SEGMENTED; > + create_req.BaseAddress = cpu_to_le64( > + op_reply_q->q_segment_list_dma); > + } else > + create_req.BaseAddress = cpu_to_le64( > + op_reply_q->q_segments[0].segment_dma); > + > + create_req.Size = cpu_to_le16(op_reply_q->num_replies); > + > + init_completion(&mrioc->init_cmds.done); > + retval = mpi3mr_admin_request_post(mrioc, &create_req, > + sizeof(create_req), 1); > + if (retval) { > + ioc_err(mrioc, "CreateRepQ: Admin Post failed\n"); > + goto out_unlock; > + } > + wait_for_completion_timeout(&mrioc->init_cmds.done, > + (MPI3MR_INTADMCMD_TIMEOUT * HZ)); > + if (!(mrioc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { > + ioc_err(mrioc, "CreateRepQ: command timed out\n"); > + mpi3mr_set_diagsave(mrioc); > + mpi3mr_issue_reset(mrioc, > + MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, > + MPI3MR_RESET_FROM_CREATEREPQ_TIMEOUT); > + mrioc->unrecoverable = 1; > + retval = -1; > + goto out_unlock; > + } > + if ((mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) > + != MPI3_IOCSTATUS_SUCCESS) { > + ioc_err(mrioc, > + "CreateRepQ: Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n", > + (mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), > + mrioc->init_cmds.ioc_loginfo); > + retval = -1; > + goto out_unlock; > + } > + op_reply_q->qid = reply_qid; > + mrioc->intr_info[midx].op_reply_q = op_reply_q; > + > +out_unlock: > + mrioc->init_cmds.state = MPI3MR_CMD_NOTUSED; > + mutex_unlock(&mrioc->init_cmds.mutex); > +out: > + > + return retval; > +} > + > +/** > + * mpi3mr_create_op_req_q - create operational request queue > + * @mrioc: Adapter instance reference > + * @idx: operational request queue index > + * @reply_qid: Reply queue ID > + * > + * Create operatinal request queue by issuing MPI request > + * through admin queue. > + * > + * Return: 0 on success, non-zero on failure. > + */ > +static int mpi3mr_create_op_req_q(struct mpi3mr_ioc *mrioc, u16 idx, > + u16 reply_qid) > +{ > + Mpi3CreateRequestQueueRequest_t create_req; > + struct op_req_qinfo *op_req_q = mrioc->req_qinfo + idx; > + int retval = 0; > + u16 req_qid = 0; > + > + > + req_qid = op_req_q->qid; > + > + if (req_qid) { > + retval = -1; > + ioc_err(mrioc, "CreateReqQ: called for duplicate qid %d\n", > + req_qid); > + > + return retval; > + } > + req_qid = idx + 1; > + > + op_req_q->num_requests = MPI3MR_OP_REQ_Q_QD; > + op_req_q->ci = 0; > + op_req_q->pi = 0; > + op_req_q->reply_qid = reply_qid; > + spin_lock_init(&op_req_q->q_lock); > + > + if (!op_req_q->q_segments) { > + retval = mpi3mr_alloc_op_req_q_segments(mrioc, idx); > + if (retval) { > + mpi3mr_free_op_req_q_segments(mrioc, idx); > + goto out; > + } > + } > + > + memset(&create_req, 0, sizeof(create_req)); > + mutex_lock(&mrioc->init_cmds.mutex); > + if (mrioc->init_cmds.state & MPI3MR_CMD_PENDING) { > + retval = -1; > + ioc_err(mrioc, "CreateReqQ: Init command is in use\n"); > + goto out; > + } > + mrioc->init_cmds.state = MPI3MR_CMD_PENDING; > + mrioc->init_cmds.is_waiting = 1; > + mrioc->init_cmds.callback = NULL; > + create_req.HostTag = cpu_to_le16(MPI3MR_HOSTTAG_INITCMDS); > + create_req.Function = MPI3_FUNCTION_CREATE_REQUEST_QUEUE; > + create_req.QueueID = cpu_to_le16(req_qid); > + if (mrioc->enable_segqueue) { > + create_req.Flags = > + MPI3_CREATE_REQUEST_QUEUE_FLAGS_SEGMENTED_SEGMENTED; > + create_req.BaseAddress = cpu_to_le64( > + op_req_q->q_segment_list_dma); > + } else > + create_req.BaseAddress = cpu_to_le64( > + op_req_q->q_segments[0].segment_dma); > + create_req.ReplyQueueID = cpu_to_le16(reply_qid); > + create_req.Size = cpu_to_le16(op_req_q->num_requests); > + > + init_completion(&mrioc->init_cmds.done); > + retval = mpi3mr_admin_request_post(mrioc, &create_req, > + sizeof(create_req), 1); > + if (retval) { > + ioc_err(mrioc, "CreateReqQ: Admin Post failed\n"); > + goto out_unlock; > + } > + wait_for_completion_timeout(&mrioc->init_cmds.done, > + (MPI3MR_INTADMCMD_TIMEOUT * HZ)); > + if (!(mrioc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { > + ioc_err(mrioc, "CreateReqQ: command timed out\n"); > + mpi3mr_set_diagsave(mrioc); > + if (mpi3mr_issue_reset(mrioc, > + MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, > + MPI3MR_RESET_FROM_CREATEREQQ_TIMEOUT)) > + mrioc->unrecoverable = 1; > + retval = -1; > + goto out_unlock; > + } > + if ((mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) > + != MPI3_IOCSTATUS_SUCCESS) { > + ioc_err(mrioc, > + "CreateReqQ: Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n", > + (mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), > + mrioc->init_cmds.ioc_loginfo); > + retval = -1; > + goto out_unlock; > + } > + op_req_q->qid = req_qid; > + > +out_unlock: > + mrioc->init_cmds.state = MPI3MR_CMD_NOTUSED; > + mutex_unlock(&mrioc->init_cmds.mutex); > +out: > + > + return retval; > +} > + > +/** > + * mpi3mr_create_op_queues - create operational queue pairs > + * @mrioc: Adapter instance reference > + * > + * Allocate memory for operational queue meta data and call > + * create request and reply queue functions. > + * > + * Return: 0 on success, non-zero on failures. > + */ > +static int mpi3mr_create_op_queues(struct mpi3mr_ioc *mrioc) > +{ > + int retval = 0; > + u16 num_queues = 0, i = 0, msix_count_op_q = 1; > + > + num_queues = min_t(int, mrioc->facts.max_op_reply_q, > + mrioc->facts.max_op_req_q); > + > + msix_count_op_q = > + mrioc->intr_info_count - mrioc->op_reply_q_offset; > + if (!mrioc->num_queues) > + mrioc->num_queues = min_t(int, num_queues, msix_count_op_q); > + num_queues = mrioc->num_queues; > + ioc_info(mrioc, "Trying to create %d Operational Q pairs\n", > + num_queues); > + > + if (!mrioc->req_qinfo) { > + mrioc->req_qinfo = kcalloc(num_queues, > + sizeof(struct op_req_qinfo), GFP_KERNEL); > + if (!mrioc->req_qinfo) { > + retval = -1; > + goto out_failed; > + } > + > + mrioc->op_reply_qinfo = kzalloc(sizeof(struct op_reply_qinfo) * > + num_queues, GFP_KERNEL); > + if (!mrioc->op_reply_qinfo) { > + retval = -1; > + goto out_failed; > + } > + } > + > + if (mrioc->enable_segqueue) > + ioc_info(mrioc, > + "allocating operational queues through segmented queues\n"); > + > + for (i = 0; i < num_queues; i++) { > + if (mpi3mr_create_op_reply_q(mrioc, i)) { > + ioc_err(mrioc, "Cannot create OP RepQ %d\n", i); > + break; > + } > + if (mpi3mr_create_op_req_q(mrioc, i, > + mrioc->op_reply_qinfo[i].qid)) { > + ioc_err(mrioc, "Cannot create OP ReqQ %d\n", i); > + mpi3mr_delete_op_reply_q(mrioc, i); > + break; > + } > + } > + > + if (i == 0) { > + /* Not even one queue is created successfully*/ > + retval = -1; > + goto out_failed; > + } > + mrioc->num_op_reply_q = mrioc->num_op_req_q = i; > + ioc_info(mrioc, "Successfully created %d Operational Q pairs\n", > + mrioc->num_op_reply_q); > + > + > + return retval; > +out_failed: > + kfree(mrioc->req_qinfo); > + mrioc->req_qinfo = NULL; > + > + kfree(mrioc->op_reply_qinfo); > + mrioc->op_reply_qinfo = NULL; > + > + > + return retval; > +} > + > > /** > * mpi3mr_setup_admin_qpair - Setup admin queue pair > @@ -1598,6 +2186,13 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc) > goto out_failed; > } > > + retval = mpi3mr_create_op_queues(mrioc); > + if (retval) { > + ioc_err(mrioc, "Failed to create OpQueues error %d\n", > + retval); > + goto out_failed; > + } > + > return retval; > > out_failed: > @@ -1654,6 +2249,12 @@ static void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc) > mrioc->reply_free_q_pool = NULL; > } > > + for (i = 0; i < mrioc->num_op_req_q; i++) > + mpi3mr_free_op_req_q_segments(mrioc, i); > + > + for (i = 0; i < mrioc->num_op_reply_q; i++) > + mpi3mr_free_op_reply_q_segments(mrioc, i); > + > for (i = 0; i < mrioc->intr_info_count; i++) { > intr_info = mrioc->intr_info + i; > if (intr_info) > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c > index c31ec9883152..3cf0be63842f 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > @@ -41,7 +41,7 @@ static int mpi3mr_map_queues(struct Scsi_Host *shost) > struct mpi3mr_ioc *mrioc = shost_priv(shost); > > return blk_mq_pci_map_queues(&shost->tag_set.map[HCTX_TYPE_DEFAULT], > - mrioc->pdev, 0); > + mrioc->pdev, mrioc->op_reply_q_offset); > } > > /** > @@ -220,6 +220,8 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) > spin_lock_init(&mrioc->sbq_lock); > > mpi3mr_init_drv_cmd(&mrioc->init_cmds, MPI3MR_HOSTTAG_INITCMDS); > + if (pdev->revision) > + mrioc->enable_segqueue = true; > > mrioc->logging_level = logging_level; > mrioc->shost = shost; > Most unfortunate that we can't be using CMA; that would alleviate the need for implementing this segmentation stuff. But since we can't: Reviewed-by: Hannes Reinecke <hare@suse.de> Cheers, Hannes -- Dr. Hannes Reinecke Kernel Storage Architect hare@suse.de +49 911 74053 688 SUSE Software Solutions Germany GmbH, 90409 Nürnberg GF: F. Imendörffer, HRB 36809 (AG Nürnberg)
On 4/19/21 1:01 PM, Kashyap Desai wrote: > Firmware can report various MPI Events. > Support for certain Events (as listed below) are enabled in the driver > and their processing in driver is covered in this patch. > > MPI3_EVENT_DEVICE_ADDED > MPI3_EVENT_DEVICE_INFO_CHANGED > MPI3_EVENT_DEVICE_STATUS_CHANGE > MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE > MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST > MPI3_EVENT_SAS_DISCOVERY > MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR > > Key support in this patch is device add/removal. > > Fix some compilation warning reported by kernel test robot. > > Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> > Reported-by: kernel test robot <lkp@intel.com> > Reviewed-by: Tomas Henzl <thenzl@redhat.com> > > Cc: sathya.prakash@broadcom.com > --- > drivers/scsi/mpi3mr/mpi/mpi30_api.h | 2 + > drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h | 2721 ++++++++++++++++++++++++++ > drivers/scsi/mpi3mr/mpi/mpi30_sas.h | 46 + > drivers/scsi/mpi3mr/mpi3mr.h | 202 ++ > drivers/scsi/mpi3mr/mpi3mr_fw.c | 195 +- > drivers/scsi/mpi3mr/mpi3mr_os.c | 1454 +++++++++++++- > 6 files changed, 4618 insertions(+), 2 deletions(-) > create mode 100644 drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h > create mode 100644 drivers/scsi/mpi3mr/mpi/mpi30_sas.h > [ .. ] > @@ -612,7 +1942,25 @@ static void mpi3mr_target_destroy(struct scsi_target *starget) > */ > static int mpi3mr_slave_configure(struct scsi_device *sdev) > { > + struct scsi_target *starget; > + struct Scsi_Host *shost; > + struct mpi3mr_ioc *mrioc; > + struct mpi3mr_tgt_dev *tgt_dev; > + unsigned long flags; > int retval = 0; > + > + starget = scsi_target(sdev); > + shost = dev_to_shost(&starget->dev); > + mrioc = shost_priv(shost); > + > + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); > + tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id); > + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); > + if (!tgt_dev) > + return retval; > + Return '0' on unknown SCSI devices? Really? > + mpi3mr_tgtdev_put(tgt_dev); > + > return retval; > } > > @@ -626,7 +1974,37 @@ static int mpi3mr_slave_configure(struct scsi_device *sdev) > */ > static int mpi3mr_slave_alloc(struct scsi_device *sdev) > { > + struct Scsi_Host *shost; > + struct mpi3mr_ioc *mrioc; > + struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data; > + struct mpi3mr_tgt_dev *tgt_dev; > + struct mpi3mr_sdev_priv_data *scsi_dev_priv_data; > + unsigned long flags; > + struct scsi_target *starget; > int retval = 0; > + > + starget = scsi_target(sdev); > + shost = dev_to_shost(&starget->dev); > + mrioc = shost_priv(shost); > + scsi_tgt_priv_data = starget->hostdata; > + > + scsi_dev_priv_data = kzalloc(sizeof(*scsi_dev_priv_data), GFP_KERNEL); > + if (!scsi_dev_priv_data) > + return -ENOMEM; > + > + scsi_dev_priv_data->lun_id = sdev->lun; > + scsi_dev_priv_data->tgt_priv_data = scsi_tgt_priv_data; > + sdev->hostdata = scsi_dev_priv_data; > + > + scsi_tgt_priv_data->num_luns++; > + > + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); > + tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id); > + if (tgt_dev && (tgt_dev->starget == NULL)) > + tgt_dev->starget = starget; > + if (tgt_dev) > + mpi3mr_tgtdev_put(tgt_dev); > + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); > return retval; > } > Same here. I would have expected -ENXIO to be returned fi the tgt_dev is not found. And you can fold the two 'if' clauses into one eg like: if (tgt_dev) { if (tgt_dev->starget == NULL) tgt_dev = starget; mpi3mr_tgtdev_put(tgt_dev); retval = 0; } > @@ -640,7 +2018,33 @@ static int mpi3mr_slave_alloc(struct scsi_device *sdev) > */ > static int mpi3mr_target_alloc(struct scsi_target *starget) > { > + struct Scsi_Host *shost = dev_to_shost(&starget->dev); > + struct mpi3mr_ioc *mrioc = shost_priv(shost); > + struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data; > + struct mpi3mr_tgt_dev *tgt_dev; > + unsigned long flags; > int retval = -ENODEV; > + > + scsi_tgt_priv_data = kzalloc(sizeof(*scsi_tgt_priv_data), GFP_KERNEL); > + if (!scsi_tgt_priv_data) > + return -ENOMEM; > + > + starget->hostdata = scsi_tgt_priv_data; > + scsi_tgt_priv_data->starget = starget; > + scsi_tgt_priv_data->dev_handle = MPI3MR_INVALID_DEV_HANDLE; > + > + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); > + tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id); > + if (tgt_dev && !tgt_dev->is_hidden) { > + scsi_tgt_priv_data->dev_handle = tgt_dev->dev_handle; > + scsi_tgt_priv_data->perst_id = tgt_dev->perst_id; > + scsi_tgt_priv_data->dev_type = tgt_dev->dev_type; > + scsi_tgt_priv_data->tgt_dev = tgt_dev; > + tgt_dev->starget = starget; > + atomic_set(&scsi_tgt_priv_data->block_io, 0); > + retval = 0; > + } > + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); > return retval; > } > Ah, here is the correct value set. (But wasn't it ENXIO which should've been returned for unknown targets?) > @@ -836,7 +2240,7 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) > { > struct mpi3mr_ioc *mrioc = NULL; > struct Scsi_Host *shost = NULL; > - int retval = 0; > + int retval = 0, i; > > shost = scsi_host_alloc(&mpi3mr_driver_template, > sizeof(struct mpi3mr_ioc)); > @@ -857,11 +2261,21 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) > spin_lock_init(&mrioc->admin_req_lock); > spin_lock_init(&mrioc->reply_free_queue_lock); > spin_lock_init(&mrioc->sbq_lock); > + spin_lock_init(&mrioc->fwevt_lock); > + spin_lock_init(&mrioc->tgtdev_lock); > spin_lock_init(&mrioc->watchdog_lock); > spin_lock_init(&mrioc->chain_buf_lock); > > + INIT_LIST_HEAD(&mrioc->fwevt_list); > + INIT_LIST_HEAD(&mrioc->tgtdev_list); > + INIT_LIST_HEAD(&mrioc->delayed_rmhs_list); > + > mpi3mr_init_drv_cmd(&mrioc->init_cmds, MPI3MR_HOSTTAG_INITCMDS); > > + for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) > + mpi3mr_init_drv_cmd(&mrioc->dev_rmhs_cmds[i], > + MPI3MR_HOSTTAG_DEVRMCMD_MIN + i); > + > if (pdev->revision) > mrioc->enable_segqueue = true; > > @@ -877,6 +2291,17 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) > shost->max_channel = 1; > shost->max_id = 0xFFFFFFFF; > > + snprintf(mrioc->fwevt_worker_name, sizeof(mrioc->fwevt_worker_name), > + "%s%d_fwevt_wrkr", mrioc->driver_name, mrioc->id); > + mrioc->fwevt_worker_thread = alloc_ordered_workqueue( > + mrioc->fwevt_worker_name, WQ_MEM_RECLAIM); > + if (!mrioc->fwevt_worker_thread) { > + ioc_err(mrioc, "failure at %s:%d/%s()!\n", > + __FILE__, __LINE__, __func__); > + retval = -ENODEV; > + goto out_fwevtthread_failed; > + } > + > mrioc->is_driver_loading = 1; > if (mpi3mr_init_ioc(mrioc)) { > ioc_err(mrioc, "failure at %s:%d/%s()!\n", > @@ -903,6 +2328,8 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) > addhost_failed: > mpi3mr_cleanup_ioc(mrioc); > out_iocinit_failed: > + destroy_workqueue(mrioc->fwevt_worker_thread); > +out_fwevtthread_failed: > spin_lock(&mrioc_list_lock); > list_del(&mrioc->list); > spin_unlock(&mrioc_list_lock); > @@ -924,14 +2351,30 @@ static void mpi3mr_remove(struct pci_dev *pdev) > { > struct Scsi_Host *shost = pci_get_drvdata(pdev); > struct mpi3mr_ioc *mrioc; > + struct workqueue_struct *wq; > + unsigned long flags; > + struct mpi3mr_tgt_dev *tgtdev, *tgtdev_next; > > mrioc = shost_priv(shost); > while (mrioc->reset_in_progress || mrioc->is_driver_loading) > ssleep(1); > > mrioc->stop_drv_processing = 1; > + mpi3mr_cleanup_fwevt_list(mrioc); > + spin_lock_irqsave(&mrioc->fwevt_lock, flags); > + wq = mrioc->fwevt_worker_thread; > + mrioc->fwevt_worker_thread = NULL; > + spin_unlock_irqrestore(&mrioc->fwevt_lock, flags); > + if (wq) > + destroy_workqueue(wq); > > scsi_remove_host(shost); > + list_for_each_entry_safe(tgtdev, tgtdev_next, &mrioc->tgtdev_list, > + list) { > + mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); > + mpi3mr_tgtdev_del_from_list(mrioc, tgtdev); > + mpi3mr_tgtdev_put(tgtdev); > + } > > mpi3mr_cleanup_ioc(mrioc); > > @@ -955,6 +2398,8 @@ static void mpi3mr_shutdown(struct pci_dev *pdev) > { > struct Scsi_Host *shost = pci_get_drvdata(pdev); > struct mpi3mr_ioc *mrioc; > + struct workqueue_struct *wq; > + unsigned long flags; > > if (!shost) > return; > @@ -963,6 +2408,13 @@ static void mpi3mr_shutdown(struct pci_dev *pdev) > while (mrioc->reset_in_progress || mrioc->is_driver_loading) > ssleep(1); > mrioc->stop_drv_processing = 1; > + mpi3mr_cleanup_fwevt_list(mrioc); > + spin_lock_irqsave(&mrioc->fwevt_lock, flags); > + wq = mrioc->fwevt_worker_thread; > + mrioc->fwevt_worker_thread = NULL; > + spin_unlock_irqrestore(&mrioc->fwevt_lock, flags); > + if (wq) > + destroy_workqueue(wq); > > mpi3mr_cleanup_ioc(mrioc); > > Cheers, Hannes -- Dr. Hannes Reinecke Kernel Storage Architect hare@suse.de +49 911 74053 688 SUSE Software Solutions Germany GmbH, 90409 Nürnberg GF: F. Imendörffer, HRB 36809 (AG Nürnberg)
On 4/19/21 1:01 PM, Kashyap Desai wrote: > Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> > Reviewed-by: Tomas Henzl <thenzl@redhat.com> > > Cc: sathya.prakash@broadcom.com > --- > drivers/scsi/mpi3mr/mpi3mr_fw.c | 80 +++++++++++++++++++++++++++++++++ > drivers/scsi/mpi3mr/mpi3mr_os.c | 1 + > 2 files changed, 81 insertions(+) > > diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c > index 4e28a0efb082..3df689410c8f 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c > @@ -2550,6 +2550,85 @@ int mpi3mr_issue_port_enable(struct mpi3mr_ioc *mrioc, u8 async) > return retval; > } > > +/* Protocol type to name mapper structure*/ > +static const struct { > + u8 protocol; > + char *name; > +} mpi3mr_protocols[] = { > + { MPI3_IOCFACTS_PROTOCOL_SCSI_INITIATOR, "Initiator" }, > + { MPI3_IOCFACTS_PROTOCOL_SCSI_TARGET, "Target" }, > + { MPI3_IOCFACTS_PROTOCOL_NVME, "NVMe attachment" }, > +}; > + > +/* Capability to name mapper structure*/ > +static const struct { > + u32 capability; > + char *name; > +} mpi3mr_capabilities[] = { > + { MPI3_IOCFACTS_CAPABILITY_RAID_CAPABLE, "RAID" }, > +}; > + > +/** > + * mpi3mr_print_ioc_info - Display controller information > + * @mrioc: Adapter instance reference > + * > + * Display controller personalit, capability, supported > + * protocols etc. > + * > + * Return: Nothing > + */ > +static void > +mpi3mr_print_ioc_info(struct mpi3mr_ioc *mrioc) > +{ > + int i = 0; > + char personality[16]; > + char protocol[50] = {0}; > + char capabilities[100] = {0}; > + bool is_string_nonempty = false; > + struct mpi3mr_compimg_ver *fwver = &mrioc->facts.fw_ver; > + > + switch (mrioc->facts.personality) { > + case MPI3_IOCFACTS_FLAGS_PERSONALITY_EHBA: > + strcpy(personality, "Enhanced HBA"); > + break; > + case MPI3_IOCFACTS_FLAGS_PERSONALITY_RAID_DDR: > + strcpy(personality, "RAID"); > + break; > + default: > + strcpy(personality, "Unknown"); > + break; > + } > + > + ioc_info(mrioc, "Running in %s Personality", personality); > + > + ioc_info(mrioc, "FW Version(%d.%d.%d.%d.%d.%d)\n", > + fwver->gen_major, fwver->gen_minor, fwver->ph_major, > + fwver->ph_minor, fwver->cust_id, fwver->build_num); > + > + for (i = 0; i < ARRAY_SIZE(mpi3mr_protocols); i++) { > + if (mrioc->facts.protocol_flags & > + mpi3mr_protocols[i].protocol) { > + if (is_string_nonempty) > + strcat(protocol, ","); > + strcat(protocol, mpi3mr_protocols[i].name); > + is_string_nonempty = true; Please check for string overflows here. > + } > + } > + > + is_string_nonempty = false; > + for (i = 0; i < ARRAY_SIZE(mpi3mr_capabilities); i++) { > + if (mrioc->facts.protocol_flags & > + mpi3mr_capabilities[i].capability) { > + if (is_string_nonempty) > + strcat(capabilities, ","); > + strcat(capabilities, mpi3mr_capabilities[i].name); > + is_string_nonempty = true; Same here. > + } > + } > + > + ioc_info(mrioc, "Protocol=(%s), Capabilities=(%s)\n", > + protocol, capabilities); > +} > > /** > * mpi3mr_cleanup_resources - Free PCI resources > @@ -2808,6 +2887,7 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 re_init) > } > > } > + mpi3mr_print_ioc_info(mrioc); > > retval = mpi3mr_alloc_reply_sense_bufs(mrioc); > if (retval) { > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c > index d82581ec73e1..39928e2997ba 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > @@ -339,6 +339,7 @@ void mpi3mr_invalidate_devhandles(struct mpi3mr_ioc *mrioc) > * mpi3mr_flush_scmd - Flush individual SCSI command > * @rq: Block request > * @data: Adapter instance reference > + * @reserved: N/A. Currently not used > * > * Return the SCSI command to the upper layers if it is in LLD > * scope. > Cheers, Hannes -- Dr. Hannes Reinecke Kernel Storage Architect hare@suse.de +49 911 74053 688 SUSE Software Solutions Germany GmbH, 90409 Nürnberg GF: F. Imendörffer, HRB 36809 (AG Nürnberg)
On 4/19/21 1:01 PM, Kashyap Desai wrote: > SCSI EH hook is added. > Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> > > Cc: sathya.prakash@broadcom.com > Cc: hare@suse.de > Cc: thenzl@redhat.com > > --- > drivers/scsi/mpi3mr/mpi3mr.h | 3 + > drivers/scsi/mpi3mr/mpi3mr_fw.c | 45 ++++ > drivers/scsi/mpi3mr/mpi3mr_os.c | 349 ++++++++++++++++++++++++++++++++ > 3 files changed, 397 insertions(+) > > diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h > index 801612c9eb2a..fe6c815b918a 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr.h > +++ b/drivers/scsi/mpi3mr/mpi3mr.h > @@ -97,6 +97,7 @@ extern struct list_head mrioc_list; > /* command/controller interaction timeout definitions in seconds */ > #define MPI3MR_INTADMCMD_TIMEOUT 10 > #define MPI3MR_PORTENABLE_TIMEOUT 300 > +#define MPI3MR_ABORTTM_TIMEOUT 30 > #define MPI3MR_RESETTM_TIMEOUT 30 > #define MPI3MR_RESET_HOST_IOWAIT_TIMEOUT 5 > #define MPI3MR_TSUPDATE_INTERVAL 900 > @@ -626,6 +627,7 @@ struct scmd_priv { > * @chain_bitmap_sz: Chain buffer allocator bitmap size > * @chain_bitmap: Chain buffer allocator bitmap > * @chain_buf_lock: Chain buffer list lock > + * @host_tm_cmds: Command tracker for task management commands > * @dev_rmhs_cmds: Command tracker for device removal commands > * @devrem_bitmap_sz: Device removal bitmap size > * @devrem_bitmap: Device removal bitmap > @@ -748,6 +750,7 @@ struct mpi3mr_ioc { > void *chain_bitmap; > spinlock_t chain_buf_lock; > > + struct mpi3mr_drv_cmd host_tm_cmds; > struct mpi3mr_drv_cmd dev_rmhs_cmds[MPI3MR_NUM_DEVRMCMD]; > u16 devrem_bitmap_sz; > void *devrem_bitmap; > diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c > index 3df689410c8f..c25e96f008d7 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c > @@ -172,6 +172,8 @@ mpi3mr_get_drv_cmd(struct mpi3mr_ioc *mrioc, u16 host_tag, > switch (host_tag) { > case MPI3MR_HOSTTAG_INITCMDS: > return &mrioc->init_cmds; > + case MPI3MR_HOSTTAG_BLK_TMS: > + return &mrioc->host_tm_cmds; > case MPI3MR_HOSTTAG_INVALID: > if (def_reply && def_reply->Function == > MPI3_FUNCTION_EVENT_NOTIFICATION) > @@ -2045,6 +2047,32 @@ static int mpi3mr_alloc_reply_sense_bufs(struct mpi3mr_ioc *mrioc) > goto out_failed; > } > > + mrioc->host_tm_cmds.reply = kzalloc(mrioc->facts.reply_sz, GFP_KERNEL); > + if (!mrioc->host_tm_cmds.reply) > + goto out_failed; > + > + for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { > + mrioc->dev_rmhs_cmds[i].reply = kzalloc(mrioc->facts.reply_sz, > + GFP_KERNEL); > + if (!mrioc->dev_rmhs_cmds[i].reply) > + goto out_failed; > + } > + mrioc->dev_handle_bitmap_sz = mrioc->facts.max_devhandle / 8; > + if (mrioc->facts.max_devhandle % 8) > + mrioc->dev_handle_bitmap_sz++; > + mrioc->removepend_bitmap = kzalloc(mrioc->dev_handle_bitmap_sz, > + GFP_KERNEL); > + if (!mrioc->removepend_bitmap) > + goto out_failed; > + > + mrioc->devrem_bitmap_sz = MPI3MR_NUM_DEVRMCMD / 8; > + if (MPI3MR_NUM_DEVRMCMD % 8) > + mrioc->devrem_bitmap_sz++; > + mrioc->devrem_bitmap = kzalloc(mrioc->devrem_bitmap_sz, > + GFP_KERNEL); > + if (!mrioc->devrem_bitmap) > + goto out_failed; > + > mrioc->num_reply_bufs = mrioc->facts.max_reqs + MPI3MR_NUM_EVT_REPLIES; > mrioc->reply_free_qsz = mrioc->num_reply_bufs + 1; > mrioc->num_sense_bufs = mrioc->facts.max_reqs / MPI3MR_SENSEBUF_FACTOR; > @@ -3048,6 +3076,8 @@ static void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc) > memset(mrioc->admin_reply_base, 0, mrioc->admin_reply_q_sz); > > memset(mrioc->init_cmds.reply, 0, sizeof(*mrioc->init_cmds.reply)); > + memset(mrioc->host_tm_cmds.reply, 0, > + sizeof(*mrioc->host_tm_cmds.reply)); > for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) > memset(mrioc->dev_rmhs_cmds[i].reply, 0, > sizeof(*mrioc->dev_rmhs_cmds[i].reply)); > @@ -3141,6 +3171,19 @@ static void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc) > kfree(mrioc->init_cmds.reply); > mrioc->init_cmds.reply = NULL; > > + kfree(mrioc->host_tm_cmds.reply); > + mrioc->host_tm_cmds.reply = NULL; > + > + for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { > + kfree(mrioc->dev_rmhs_cmds[i].reply); > + mrioc->dev_rmhs_cmds[i].reply = NULL; > + } > + kfree(mrioc->removepend_bitmap); > + mrioc->removepend_bitmap = NULL; > + > + kfree(mrioc->devrem_bitmap); > + mrioc->devrem_bitmap = NULL; > + > kfree(mrioc->chain_bitmap); > mrioc->chain_bitmap = NULL; > > @@ -3321,6 +3364,8 @@ static void mpi3mr_flush_drv_cmds(struct mpi3mr_ioc *mrioc) > > cmdptr = &mrioc->init_cmds; > mpi3mr_drv_cmd_comp_reset(mrioc, cmdptr); > + cmdptr = &mrioc->host_tm_cmds; > + mpi3mr_drv_cmd_comp_reset(mrioc, cmdptr); > > for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { > cmdptr = &mrioc->dev_rmhs_cmds[i]; > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c > index 946a62610b55..fd5fdc61169e 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > @@ -2075,6 +2075,212 @@ static int mpi3mr_build_sg_scmd(struct mpi3mr_ioc *mrioc, > return ret; > } > > +/** > + * mpi3mr_print_response_code - print TM response as a string > + * @mrioc: Adapter instance reference > + * @resp_code: TM response code > + * > + * Print TM response code as a readable string. > + * > + * Return: Nothing. > + */ > +static void mpi3mr_print_response_code(struct mpi3mr_ioc *mrioc, u8 resp_code) > +{ > + char *desc; > + > + switch (resp_code) { > + case MPI3MR_RSP_TM_COMPLETE: > + desc = "task management request completed"; > + break; > + case MPI3MR_RSP_INVALID_FRAME: > + desc = "invalid frame"; > + break; > + case MPI3MR_RSP_TM_NOT_SUPPORTED: > + desc = "task management request not supported"; > + break; > + case MPI3MR_RSP_TM_FAILED: > + desc = "task management request failed"; > + break; > + case MPI3MR_RSP_TM_SUCCEEDED: > + desc = "task management request succeeded"; > + break; > + case MPI3MR_RSP_TM_INVALID_LUN: > + desc = "invalid lun"; > + break; > + case MPI3MR_RSP_TM_OVERLAPPED_TAG: > + desc = "overlapped tag attempted"; > + break; > + case MPI3MR_RSP_IO_QUEUED_ON_IOC: > + desc = "task queued, however not sent to target"; > + break; > + default: > + desc = "unknown"; > + break; > + } You could use a mapping structure here instead of the switch, right? > + ioc_info(mrioc, "%s :response_code(0x%01x): %s\n", __func__, > + resp_code, desc); > +} > + > +/** > + * mpi3mr_issue_tm - Issue Task Management request > + * @mrioc: Adapter instance reference > + * @tm_type: Task Management type > + * @handle: Device handle > + * @lun: LUN ID > + * @htag: Host tag of the TM request > + * @drv_cmd: Internal command tracker > + * @resp_code: Response code place holder > + * @cmd_priv: SCSI command private data > + * > + * Issues a Task Management Request to the controller for a > + * specified target, LUN and command and wait for its completion > + * and check TM response. Recover the TM if it timed out by > + * issuing controller reset. > + * > + * Return: 0 on success, non-zero on errors > + */ > +static int mpi3mr_issue_tm(struct mpi3mr_ioc *mrioc, u8 tm_type, > + u16 handle, uint lun, u16 htag, ulong timeout, > + struct mpi3mr_drv_cmd *drv_cmd, > + u8 *resp_code, struct scmd_priv *cmd_priv) > +{ > + Mpi3SCSITaskMgmtRequest_t tm_req; > + Mpi3SCSITaskMgmtReply_t *tm_reply = NULL; > + int retval = 0; > + struct mpi3mr_tgt_dev *tgtdev = NULL; > + struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data = NULL; > + struct op_req_qinfo *op_req_q = NULL; > + > + ioc_info(mrioc, "%s :Issue TM: TM Type (0x%x) for devhandle 0x%04x\n", > + __func__, tm_type, handle); > + if (mrioc->unrecoverable) { > + retval = -1; > + ioc_err(mrioc, "%s :Issue TM: Unrecoverable controller\n", > + __func__); > + goto out; > + } > + > + memset(&tm_req, 0, sizeof(tm_req)); > + mutex_lock(&drv_cmd->mutex); > + if (drv_cmd->state & MPI3MR_CMD_PENDING) { > + retval = -1; > + ioc_err(mrioc, "%s :Issue TM: Command is in use\n", __func__); > + mutex_unlock(&drv_cmd->mutex); > + goto out; > + } > + if (mrioc->reset_in_progress) { > + retval = -1; > + ioc_err(mrioc, "%s :Issue TM: Reset in progress\n", __func__); > + mutex_unlock(&drv_cmd->mutex); > + goto out; > + } > + > + drv_cmd->state = MPI3MR_CMD_PENDING; > + drv_cmd->is_waiting = 1; > + drv_cmd->callback = NULL; > + tm_req.DevHandle = cpu_to_le16(handle); > + tm_req.TaskType = tm_type; > + tm_req.HostTag = cpu_to_le16(htag); > + > + int_to_scsilun(lun, (struct scsi_lun *)tm_req.LUN); > + tm_req.Function = MPI3_FUNCTION_SCSI_TASK_MGMT; > + > + tgtdev = mpi3mr_get_tgtdev_by_handle(mrioc, handle); > + if (tgtdev && tgtdev->starget && tgtdev->starget->hostdata) { > + scsi_tgt_priv_data = (struct mpi3mr_stgt_priv_data *) > + tgtdev->starget->hostdata; > + atomic_inc(&scsi_tgt_priv_data->block_io); > + } > + if (cmd_priv) { > + op_req_q = &mrioc->req_qinfo[cmd_priv->req_q_idx]; > + tm_req.TaskHostTag = cpu_to_le16(cmd_priv->host_tag); > + tm_req.TaskRequestQueueID = cpu_to_le16(op_req_q->qid); > + } > + if (tgtdev && (tgtdev->dev_type == MPI3_DEVICE_DEVFORM_PCIE)) { > + if (cmd_priv && tgtdev->dev_spec.pcie_inf.abort_to) > + timeout = tgtdev->dev_spec.pcie_inf.abort_to; > + else if (!cmd_priv && tgtdev->dev_spec.pcie_inf.reset_to) > + timeout = tgtdev->dev_spec.pcie_inf.reset_to; > + } > + > + init_completion(&drv_cmd->done); > + retval = mpi3mr_admin_request_post(mrioc, &tm_req, sizeof(tm_req), 1); > + if (retval) { > + ioc_err(mrioc, "%s :Issue TM: Admin Post failed\n", __func__); > + goto out_unlock; > + } > + wait_for_completion_timeout(&drv_cmd->done, (timeout * HZ)); > + > + if (!(drv_cmd->state & MPI3MR_CMD_COMPLETE)) { > + ioc_err(mrioc, "%s :Issue TM: command timed out\n", __func__); > + drv_cmd->is_waiting = 0; > + retval = -1; > + mpi3mr_soft_reset_handler(mrioc, > + MPI3MR_RESET_FROM_TM_TIMEOUT, 1); > + goto out_unlock; > + } > + > + if (drv_cmd->state & MPI3MR_CMD_REPLY_VALID) > + tm_reply = (Mpi3SCSITaskMgmtReply_t *)drv_cmd->reply; > + > + if (drv_cmd->ioc_status != MPI3_IOCSTATUS_SUCCESS) { > + ioc_err(mrioc, > + "%s :Issue TM: handle(0x%04x) Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n", > + __func__, handle, drv_cmd->ioc_status, > + drv_cmd->ioc_loginfo); > + retval = -1; > + goto out_unlock; > + } > + > + if (!tm_reply) { > + ioc_err(mrioc, "%s :Issue TM: No TM Reply message\n", __func__); > + retval = -1; > + goto out_unlock; > + } > + > + *resp_code = le32_to_cpu(tm_reply->ResponseData) & > + MPI3MR_RI_MASK_RESPCODE; > + switch (*resp_code) { > + case MPI3MR_RSP_TM_SUCCEEDED: > + case MPI3MR_RSP_TM_COMPLETE: > + break; > + case MPI3MR_RSP_IO_QUEUED_ON_IOC: > + if (tm_type != MPI3_SCSITASKMGMT_TASKTYPE_QUERY_TASK) > + retval = -1; > + break; > + default: > + retval = -1; > + break; > + } > + > + ioc_info(mrioc, > + "%s :Issue TM: Completed TM Type (0x%x) handle(0x%04x) ", > + __func__, tm_type, handle); > + ioc_info(mrioc, > + "with ioc_status(0x%04x), loginfo(0x%08x), term_count(0x%08x)\n", > + drv_cmd->ioc_status, drv_cmd->ioc_loginfo, > + le32_to_cpu(tm_reply->TerminationCount)); > + mpi3mr_print_response_code(mrioc, *resp_code); > + > +out_unlock: > + drv_cmd->state = MPI3MR_CMD_NOTUSED; > + mutex_unlock(&drv_cmd->mutex); > + if (scsi_tgt_priv_data) > + atomic_dec_if_positive(&scsi_tgt_priv_data->block_io); > + if (tgtdev) > + mpi3mr_tgtdev_put(tgtdev); > + if (!retval) { > + /* > + * Flush all IRQ handlers by calling synchronize_irq(). > + * mpi3mr_ioc_disable_intr() takes care of it. > + */ > + mpi3mr_ioc_disable_intr(mrioc); > + mpi3mr_ioc_enable_intr(mrioc); > + } > +out: > + return retval; > +} > + > /** > * mpi3mr_bios_param - BIOS param callback > * @sdev: SCSI device reference > @@ -2132,6 +2338,145 @@ static int mpi3mr_map_queues(struct Scsi_Host *shost) > mrioc->pdev, mrioc->op_reply_q_offset); > } > > +/** > + * mpi3mr_eh_host_reset - Host reset error handling callback > + * @scmd: SCSI command reference > + * > + * Issue controller reset if the scmd is for a Physical Device, > + * if the scmd is for RAID volume, then wait for > + * MPI3MR_RAID_ERRREC_RESET_TIMEOUT and checke whether any > + * pending I/Os prior to issuing reset to the controller. > + * > + * Return: SUCCESS of successful reset else FAILED > + */ > +static int mpi3mr_eh_host_reset(struct scsi_cmnd *scmd) > +{ > + struct mpi3mr_ioc *mrioc = shost_priv(scmd->device->host); > + int retval = FAILED, ret; > + > + > + ret = mpi3mr_soft_reset_handler(mrioc, > + MPI3MR_RESET_FROM_EH_HOS, 1); > + if (ret) > + goto out; > + > + retval = SUCCESS; > +out: > + sdev_printk(KERN_INFO, scmd->device, > + "Host reset is %s for scmd(%p)\n", > + ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); > + > + return retval; > +} > + > +/** > + * mpi3mr_eh_target_reset - Target reset error handling callback > + * @scmd: SCSI command reference > + * > + * Issue Target reset Task Management and verify the scmd is > + * terminated successfully and return status accordingly. > + * > + * Return: SUCCESS of successful termination of the scmd else > + * FAILED > + */ > +static int mpi3mr_eh_target_reset(struct scsi_cmnd *scmd) > +{ > + struct mpi3mr_ioc *mrioc = shost_priv(scmd->device->host); > + struct mpi3mr_stgt_priv_data *stgt_priv_data; > + struct mpi3mr_sdev_priv_data *sdev_priv_data; > + u16 dev_handle; > + u8 resp_code = 0; > + int retval = FAILED, ret = 0; > + > + > + sdev_printk(KERN_INFO, scmd->device, > + "Attempting Target Reset! scmd(%p)\n", scmd); > + scsi_print_command(scmd); > + > + sdev_priv_data = scmd->device->hostdata; > + if (!sdev_priv_data || !sdev_priv_data->tgt_priv_data) { > + sdev_printk(KERN_INFO, scmd->device, > + "SCSI device is not available\n"); > + retval = SUCCESS; > + goto out; > + } > + > + stgt_priv_data = sdev_priv_data->tgt_priv_data; > + dev_handle = stgt_priv_data->dev_handle; > + sdev_printk(KERN_INFO, scmd->device, > + "Target Reset is issued to handle(0x%04x)\n", > + dev_handle); > + > + ret = mpi3mr_issue_tm(mrioc, > + MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET, dev_handle, > + sdev_priv_data->lun_id, MPI3MR_HOSTTAG_BLK_TMS, > + MPI3MR_RESETTM_TIMEOUT, &mrioc->host_tm_cmds, &resp_code, NULL); > + > + if (ret) > + goto out; > + > + retval = SUCCESS; > +out: > + sdev_printk(KERN_INFO, scmd->device, > + "Target reset is %s for scmd(%p)\n", > + ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); > + > + return retval; > +} > + > +/** > + * mpi3mr_eh_dev_reset- Device reset error handling callback > + * @scmd: SCSI command reference > + * > + * Issue LUN reset Task Management and verify the scmd is > + * terminated successfully and return status accordingly. > + * > + * Return: SUCCESS of successful termination of the scmd else > + * FAILED > + */ > +static int mpi3mr_eh_dev_reset(struct scsi_cmnd *scmd) > +{ > + struct mpi3mr_ioc *mrioc = shost_priv(scmd->device->host); > + struct mpi3mr_stgt_priv_data *stgt_priv_data; > + struct mpi3mr_sdev_priv_data *sdev_priv_data; > + u16 dev_handle; > + u8 resp_code = 0; > + int retval = FAILED, ret = 0; > + > + sdev_printk(KERN_INFO, scmd->device, > + "Attempting Device(LUN) Reset! scmd(%p)\n", scmd); > + scsi_print_command(scmd); > + > + sdev_priv_data = scmd->device->hostdata; > + if (!sdev_priv_data || !sdev_priv_data->tgt_priv_data) { > + sdev_printk(KERN_INFO, scmd->device, > + "SCSI device is not available\n"); > + retval = SUCCESS; > + goto out; > + } > + > + stgt_priv_data = sdev_priv_data->tgt_priv_data; > + dev_handle = stgt_priv_data->dev_handle; > + sdev_printk(KERN_INFO, scmd->device, > + "Device(LUN) Reset is issued to handle(0x%04x)\n", dev_handle); > + > + ret = mpi3mr_issue_tm(mrioc, > + MPI3_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, dev_handle, > + sdev_priv_data->lun_id, MPI3MR_HOSTTAG_BLK_TMS, > + MPI3MR_RESETTM_TIMEOUT, &mrioc->host_tm_cmds, &resp_code, NULL); > + > + if (ret) > + goto out; > + > + retval = SUCCESS; > +out: > + sdev_printk(KERN_INFO, scmd->device, > + "Device(LUN) reset is %s for scmd(%p)\n", > + ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); > + > + return retval; > +} > + > /** > * mpi3mr_scan_start - Scan start callback handler > * @shost: SCSI host reference > @@ -2547,6 +2892,9 @@ static struct scsi_host_template mpi3mr_driver_template = { > .slave_destroy = mpi3mr_slave_destroy, > .scan_finished = mpi3mr_scan_finished, > .scan_start = mpi3mr_scan_start, > + .eh_device_reset_handler = mpi3mr_eh_dev_reset, > + .eh_target_reset_handler = mpi3mr_eh_target_reset, > + .eh_host_reset_handler = mpi3mr_eh_host_reset, > .bios_param = mpi3mr_bios_param, > .map_queues = mpi3mr_map_queues, > .no_write_same = 1, > @@ -2634,6 +2982,7 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) > > mutex_init(&mrioc->reset_mutex); > mpi3mr_init_drv_cmd(&mrioc->init_cmds, MPI3MR_HOSTTAG_INITCMDS); > + mpi3mr_init_drv_cmd(&mrioc->host_tm_cmds, MPI3MR_HOSTTAG_BLK_TMS); > > for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) > mpi3mr_init_drv_cmd(&mrioc->dev_rmhs_cmds[i], > Otherwise: Reviewed-by: Hannes Reinecke <hare@suse.de> Cheers, Hannes -- Dr. Hannes Reinecke Kernel Storage Architect hare@suse.de +49 911 74053 688 SUSE Software Solutions Germany GmbH, 90409 Nürnberg GF: F. Imendörffer, HRB 36809 (AG Nürnberg)
> > +/** > > + * mpi3mr_print_response_code - print TM response as a string > > + * @mrioc: Adapter instance reference > > + * @resp_code: TM response code > > + * > > + * Print TM response code as a readable string. > > + * > > + * Return: Nothing. > > + */ > > +static void mpi3mr_print_response_code(struct mpi3mr_ioc *mrioc, u8 > > +resp_code) { > > + char *desc; > > + > > + switch (resp_code) { > > + case MPI3MR_RSP_TM_COMPLETE: > > + desc = "task management request completed"; > > + break; > > + case MPI3MR_RSP_INVALID_FRAME: > > + desc = "invalid frame"; > > + break; > > + case MPI3MR_RSP_TM_NOT_SUPPORTED: > > + desc = "task management request not supported"; > > + break; > > + case MPI3MR_RSP_TM_FAILED: > > + desc = "task management request failed"; > > + break; > > + case MPI3MR_RSP_TM_SUCCEEDED: > > + desc = "task management request succeeded"; > > + break; > > + case MPI3MR_RSP_TM_INVALID_LUN: > > + desc = "invalid lun"; > > + break; > > + case MPI3MR_RSP_TM_OVERLAPPED_TAG: > > + desc = "overlapped tag attempted"; > > + break; > > + case MPI3MR_RSP_IO_QUEUED_ON_IOC: > > + desc = "task queued, however not sent to target"; > > + break; > > + default: > > + desc = "unknown"; > > + break; > > + } > > You could use a mapping structure here instead of the switch, right? Hannes - I agree. Noted your feedback. We have used mapping structure for "mpi3mr_reset_reason" can do similar thing here as well. If I can accommodate relevant changes in this series I will update the change log. I have to change MPI header files (as requested by Christopher and Bart) and that is major rework for this patch series. I want to avoid any logical changes in V4 post so that I can easily review diff between V3 and V4. Kashyap > > Otherwise: > > Reviewed-by: Hannes Reinecke <hare@suse.de> > > Cheers, > > Hannes > -- > Dr. Hannes Reinecke Kernel Storage Architect > hare@suse.de +49 911 74053 688 > SUSE Software Solutions Germany GmbH, 90409 Nürnberg > GF: F. Imendörffer, HRB 36809 (AG Nürnberg)
> > @@ -612,7 +1942,25 @@ static void mpi3mr_target_destroy(struct > scsi_target *starget) > > */ > > static int mpi3mr_slave_configure(struct scsi_device *sdev) { > > + struct scsi_target *starget; > > + struct Scsi_Host *shost; > > + struct mpi3mr_ioc *mrioc; > > + struct mpi3mr_tgt_dev *tgt_dev; > > + unsigned long flags; > > int retval = 0; > > + > > + starget = scsi_target(sdev); > > + shost = dev_to_shost(&starget->dev); > > + mrioc = shost_priv(shost); > > + > > + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); > > + tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id); > > + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); > > + if (!tgt_dev) > > + return retval; > > + > > Return '0' on unknown SCSI devices? Really? Hannes - I will fix this in V4. I am planning to send V4 today. Please review. > > > + mpi3mr_tgtdev_put(tgt_dev); > > + > > return retval; > > } > > > > @@ -626,7 +1974,37 @@ static int mpi3mr_slave_configure(struct > scsi_device *sdev) > > */ > > static int mpi3mr_slave_alloc(struct scsi_device *sdev) { > > + struct Scsi_Host *shost; > > + struct mpi3mr_ioc *mrioc; > > + struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data; > > + struct mpi3mr_tgt_dev *tgt_dev; > > + struct mpi3mr_sdev_priv_data *scsi_dev_priv_data; > > + unsigned long flags; > > + struct scsi_target *starget; > > int retval = 0; > > + > > + starget = scsi_target(sdev); > > + shost = dev_to_shost(&starget->dev); > > + mrioc = shost_priv(shost); > > + scsi_tgt_priv_data = starget->hostdata; > > + > > + scsi_dev_priv_data = kzalloc(sizeof(*scsi_dev_priv_data), > GFP_KERNEL); > > + if (!scsi_dev_priv_data) > > + return -ENOMEM; > > + > > + scsi_dev_priv_data->lun_id = sdev->lun; > > + scsi_dev_priv_data->tgt_priv_data = scsi_tgt_priv_data; > > + sdev->hostdata = scsi_dev_priv_data; > > + > > + scsi_tgt_priv_data->num_luns++; > > + > > + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); > > + tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id); > > + if (tgt_dev && (tgt_dev->starget == NULL)) > > + tgt_dev->starget = starget; > > + if (tgt_dev) > > + mpi3mr_tgtdev_put(tgt_dev); > > + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); > > return retval; > > } > > > Same here. I would have expected -ENXIO to be returned fi the tgt_dev is > not > found. > And you can fold the two 'if' clauses into one eg like: This is fixed in in V4. > > if (tgt_dev) { > if (tgt_dev->starget == NULL) > tgt_dev = starget; > mpi3mr_tgtdev_put(tgt_dev); > retval = 0; > } > > > @@ -640,7 +2018,33 @@ static int mpi3mr_slave_alloc(struct scsi_device > *sdev) > > */ > > static int mpi3mr_target_alloc(struct scsi_target *starget) { > > + struct Scsi_Host *shost = dev_to_shost(&starget->dev); > > + struct mpi3mr_ioc *mrioc = shost_priv(shost); > > + struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data; > > + struct mpi3mr_tgt_dev *tgt_dev; > > + unsigned long flags; > > int retval = -ENODEV; > > + > > + scsi_tgt_priv_data = kzalloc(sizeof(*scsi_tgt_priv_data), > GFP_KERNEL); > > + if (!scsi_tgt_priv_data) > > + return -ENOMEM; > > + > > + starget->hostdata = scsi_tgt_priv_data; > > + scsi_tgt_priv_data->starget = starget; > > + scsi_tgt_priv_data->dev_handle = MPI3MR_INVALID_DEV_HANDLE; > > + > > + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); > > + tgt_dev = __mpi3mr_get_tgtdev_by_perst_id(mrioc, starget->id); > > + if (tgt_dev && !tgt_dev->is_hidden) { > > + scsi_tgt_priv_data->dev_handle = tgt_dev->dev_handle; > > + scsi_tgt_priv_data->perst_id = tgt_dev->perst_id; > > + scsi_tgt_priv_data->dev_type = tgt_dev->dev_type; > > + scsi_tgt_priv_data->tgt_dev = tgt_dev; > > + tgt_dev->starget = starget; > > + atomic_set(&scsi_tgt_priv_data->block_io, 0); > > + retval = 0; > > + } > > + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); > > return retval; > > } > > > Ah, here is the correct value set. > (But wasn't it ENXIO which should've been returned for unknown targets?) This is fixed in V4. > > > @@ -836,7 +2240,7 @@ mpi3mr_probe(struct pci_dev *pdev, const struct > > pci_device_id *id) { > > struct mpi3mr_ioc *mrioc = NULL; > > struct Scsi_Host *shost = NULL; > > - int retval = 0; > > + int retval = 0, i; > > > > shost = scsi_host_alloc(&mpi3mr_driver_template, > > sizeof(struct mpi3mr_ioc)); > > @@ -857,11 +2261,21 @@ mpi3mr_probe(struct pci_dev *pdev, const > struct pci_device_id *id) > > spin_lock_init(&mrioc->admin_req_lock); > > spin_lock_init(&mrioc->reply_free_queue_lock); > > spin_lock_init(&mrioc->sbq_lock); > > + spin_lock_init(&mrioc->fwevt_lock); > > + spin_lock_init(&mrioc->tgtdev_lock); > > spin_lock_init(&mrioc->watchdog_lock); > > spin_lock_init(&mrioc->chain_buf_lock); > > > > + INIT_LIST_HEAD(&mrioc->fwevt_list); > > + INIT_LIST_HEAD(&mrioc->tgtdev_list); > > + INIT_LIST_HEAD(&mrioc->delayed_rmhs_list); > > + > > mpi3mr_init_drv_cmd(&mrioc->init_cmds, > MPI3MR_HOSTTAG_INITCMDS); > > > > + for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) > > + mpi3mr_init_drv_cmd(&mrioc->dev_rmhs_cmds[i], > > + MPI3MR_HOSTTAG_DEVRMCMD_MIN + i); > > + > > if (pdev->revision) > > mrioc->enable_segqueue = true; > > > > @@ -877,6 +2291,17 @@ mpi3mr_probe(struct pci_dev *pdev, const struct > pci_device_id *id) > > shost->max_channel = 1; > > shost->max_id = 0xFFFFFFFF; > > > > + snprintf(mrioc->fwevt_worker_name, sizeof(mrioc- > >fwevt_worker_name), > > + "%s%d_fwevt_wrkr", mrioc->driver_name, mrioc->id); > > + mrioc->fwevt_worker_thread = alloc_ordered_workqueue( > > + mrioc->fwevt_worker_name, WQ_MEM_RECLAIM); > > + if (!mrioc->fwevt_worker_thread) { > > + ioc_err(mrioc, "failure at %s:%d/%s()!\n", > > + __FILE__, __LINE__, __func__); > > + retval = -ENODEV; > > + goto out_fwevtthread_failed; > > + } > > + > > mrioc->is_driver_loading = 1; > > if (mpi3mr_init_ioc(mrioc)) { > > ioc_err(mrioc, "failure at %s:%d/%s()!\n", @@ -903,6 +2328,8 > @@ > > mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) > > addhost_failed: > > mpi3mr_cleanup_ioc(mrioc); > > out_iocinit_failed: > > + destroy_workqueue(mrioc->fwevt_worker_thread); > > +out_fwevtthread_failed: > > spin_lock(&mrioc_list_lock); > > list_del(&mrioc->list); > > spin_unlock(&mrioc_list_lock); > > @@ -924,14 +2351,30 @@ static void mpi3mr_remove(struct pci_dev > *pdev) > > { > > struct Scsi_Host *shost = pci_get_drvdata(pdev); > > struct mpi3mr_ioc *mrioc; > > + struct workqueue_struct *wq; > > + unsigned long flags; > > + struct mpi3mr_tgt_dev *tgtdev, *tgtdev_next; > > > > mrioc = shost_priv(shost); > > while (mrioc->reset_in_progress || mrioc->is_driver_loading) > > ssleep(1); > > > > mrioc->stop_drv_processing = 1; > > + mpi3mr_cleanup_fwevt_list(mrioc); > > + spin_lock_irqsave(&mrioc->fwevt_lock, flags); > > + wq = mrioc->fwevt_worker_thread; > > + mrioc->fwevt_worker_thread = NULL; > > + spin_unlock_irqrestore(&mrioc->fwevt_lock, flags); > > + if (wq) > > + destroy_workqueue(wq); > > > > scsi_remove_host(shost); > > + list_for_each_entry_safe(tgtdev, tgtdev_next, &mrioc->tgtdev_list, > > + list) { > > + mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev); > > + mpi3mr_tgtdev_del_from_list(mrioc, tgtdev); > > + mpi3mr_tgtdev_put(tgtdev); > > + } > > > > mpi3mr_cleanup_ioc(mrioc); > > > > @@ -955,6 +2398,8 @@ static void mpi3mr_shutdown(struct pci_dev > *pdev) > > { > > struct Scsi_Host *shost = pci_get_drvdata(pdev); > > struct mpi3mr_ioc *mrioc; > > + struct workqueue_struct *wq; > > + unsigned long flags; > > > > if (!shost) > > return; > > @@ -963,6 +2408,13 @@ static void mpi3mr_shutdown(struct pci_dev > *pdev) > > while (mrioc->reset_in_progress || mrioc->is_driver_loading) > > ssleep(1); > > mrioc->stop_drv_processing = 1; > > + mpi3mr_cleanup_fwevt_list(mrioc); > > + spin_lock_irqsave(&mrioc->fwevt_lock, flags); > > + wq = mrioc->fwevt_worker_thread; > > + mrioc->fwevt_worker_thread = NULL; > > + spin_unlock_irqrestore(&mrioc->fwevt_lock, flags); > > + if (wq) > > + destroy_workqueue(wq); > > > > mpi3mr_cleanup_ioc(mrioc); > > > > > Cheers, > > Hannes > -- > Dr. Hannes Reinecke Kernel Storage Architect > hare@suse.de +49 911 74053 688 > SUSE Software Solutions Germany GmbH, 90409 Nürnberg > GF: F. Imendörffer, HRB 36809 (AG Nürnberg)
> > + > > + for (i = 0; i < ARRAY_SIZE(mpi3mr_protocols); i++) { > > + if (mrioc->facts.protocol_flags & > > + mpi3mr_protocols[i].protocol) { > > + if (is_string_nonempty) > > + strcat(protocol, ","); > > + strcat(protocol, mpi3mr_protocols[i].name); > > + is_string_nonempty = true; > > Please check for string overflows here. Hannes - This is fixed in V4. Please review V4. Planning to post V4 today. > > > + } > > + } > > + > > + is_string_nonempty = false; > > + for (i = 0; i < ARRAY_SIZE(mpi3mr_capabilities); i++) { > > + if (mrioc->facts.protocol_flags & > > + mpi3mr_capabilities[i].capability) { > > + if (is_string_nonempty) > > + strcat(capabilities, ","); > > + strcat(capabilities, mpi3mr_capabilities[i].name); > > + is_string_nonempty = true; > > Same here. > > > + } > > + } > > + > > + ioc_info(mrioc, "Protocol=(%s), Capabilities=(%s)\n", > > + protocol, capabilities); > > +} > > > > /** > > * mpi3mr_cleanup_resources - Free PCI resources @@ -2808,6 +2887,7 > > @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 re_init) > > } > > > > } > > + mpi3mr_print_ioc_info(mrioc); > > > > retval = mpi3mr_alloc_reply_sense_bufs(mrioc); > > if (retval) { > > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c > > b/drivers/scsi/mpi3mr/mpi3mr_os.c index d82581ec73e1..39928e2997ba > > 100644 > > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > > @@ -339,6 +339,7 @@ void mpi3mr_invalidate_devhandles(struct > mpi3mr_ioc *mrioc) > > * mpi3mr_flush_scmd - Flush individual SCSI command > > * @rq: Block request > > * @data: Adapter instance reference > > + * @reserved: N/A. Currently not used > > * > > * Return the SCSI command to the upper layers if it is in LLD > > * scope. > > > Cheers, > > Hannes > -- > Dr. Hannes Reinecke Kernel Storage Architect > hare@suse.de +49 911 74053 688 > SUSE Software Solutions Germany GmbH, 90409 Nürnberg > GF: F. Imendörffer, HRB 36809 (AG Nürnberg)