mbox series

[v3,00/24] Introducing mpi3mr driver

Message ID 20210419110156.1786882-1-kashyap.desai@broadcom.com
Headers show
Series Introducing mpi3mr driver | expand

Message

Kashyap Desai April 19, 2021, 11:01 a.m. UTC
v2->v3
 - further removed unused pointer typedef from mpi30_type.h
 - Add Tomas Henzl's reviewed-tag to appropriate patches
 - Fix added which is Reported-by kernel test robot <lkp@intel.com>
 - Removed .eh_abort_handler suggested by Hannes.

v1->v2
 - removed undefined entries from mpi30_type.h
 - removed DRV_CMD_CALLBACK typedef
 - Use IRQF_SHARED  instead of IRQF_ONESHOT
 - Use READ_ONCE, WRITE_ONCE while accessing operational request
   queue consumer index 
 - removed in_interrup()
 - remove pr_cont.
 - move some code from error handling to device handling patch.
 - used direct values instead of macro MPI3_SECTOR_SIZE_XYZ
 - Add Hannes's reviewed-tag to appropriate patches
 - Add Reported-by kernel test robot <lkp@intel.com> to appropriate
   patches.


This patch series covers logical patches of the new device driver for the
MPI3MR high performance storage I/O & RAID controllers (Avenger series).
The mpi3mr has true multiple h/w queue interfacing like nvme.

See more info -
https://www.spinics.net/lists/linux-scsi/msg147868.html

The controllers managed by the mpi3mr driver are capable of reaching a
very high performance numbers compared to existing controller due to the
new hardware architectures. This Driver is tested with the internal
versions of the MPI3MR I/O & RAID controllers.

Patches are logical split mainly for better code review. Full patch set is
required for functional stability of this new driver.

You can find the source at - 
https://github.com/kadesai16/mpi3mr_v1
https://github.com/kadesai16/mpi3mr_v2
https://github.com/kadesai16/mpi3mr_v3


Kashyap Desai (24):
  mpi3mr: add mpi30 Rev-R headers and Kconfig
  mpi3mr: base driver code
  mpi3mr: create operational request and reply queue pair
  mpi3mr: add support of queue command processing
  mpi3mr: add support of internal watchdog thread
  mpi3mr: add support of event handling part-1
  mpi3mr: add support of event handling pcie devices part-2
  mpi3mr: add support of event handling part-3
  mpi3mr: add support for recovering controller
  mpi3mr: add support of timestamp sync with firmware
  mpi3mr: print ioc info for debugging
  mpi3mr: add bios_param shost template hook
  mpi3mr: implement scsi error handler hooks
  mpi3mr: add change queue depth support
  mpi3mr: allow certain commands during pci-remove hook
  mpi3mr: hardware workaround for UNMAP commands to nvme drives
  mpi3mr: add support of threaded isr
  mpi3mr: add complete support of soft reset
  mpi3mr: print pending host ios for debug
  mpi3mr: wait for pending IO completions upon detection of VD IO
    timeout
  mpi3mr: add support of PM suspend and resume
  mpi3mr: add support of DSN secure fw check
  mpi3mr: add eedp dif dix support
  mpi3mr: add event handling debug prints

 drivers/scsi/Kconfig                      |    1 +
 drivers/scsi/Makefile                     |    1 +
 drivers/scsi/mpi3mr/Kconfig               |    7 +
 drivers/scsi/mpi3mr/Makefile              |    4 +
 drivers/scsi/mpi3mr/mpi/mpi30_api.h       |   23 +
 drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h      | 2721 ++++++++++++++
 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_sas.h       |   46 +
 drivers/scsi/mpi3mr/mpi/mpi30_transport.h |  675 ++++
 drivers/scsi/mpi3mr/mpi/mpi30_type.h      |   20 +
 drivers/scsi/mpi3mr/mpi3mr.h              |  895 +++++
 drivers/scsi/mpi3mr/mpi3mr_debug.h        |   60 +
 drivers/scsi/mpi3mr/mpi3mr_fw.c           | 3971 ++++++++++++++++++++
 drivers/scsi/mpi3mr/mpi3mr_os.c           | 4146 +++++++++++++++++++++
 16 files changed, 14494 insertions(+)
 create mode 100644 drivers/scsi/mpi3mr/Kconfig
 create mode 100644 drivers/scsi/mpi3mr/Makefile
 create mode 100644 drivers/scsi/mpi3mr/mpi/mpi30_api.h
 create mode 100644 drivers/scsi/mpi3mr/mpi/mpi30_cnfg.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_sas.h
 create mode 100644 drivers/scsi/mpi3mr/mpi/mpi30_transport.h
 create mode 100644 drivers/scsi/mpi3mr/mpi/mpi30_type.h
 create mode 100644 drivers/scsi/mpi3mr/mpi3mr.h
 create mode 100644 drivers/scsi/mpi3mr/mpi3mr_debug.h
 create mode 100644 drivers/scsi/mpi3mr/mpi3mr_fw.c
 create mode 100644 drivers/scsi/mpi3mr/mpi3mr_os.c

Comments

Kashyap Desai April 21, 2021, 6:49 a.m. UTC | #1
> > @@ -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
Himanshu Madhani April 21, 2021, 5:05 p.m. UTC | #2
> 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
Himanshu Madhani April 21, 2021, 6:57 p.m. UTC | #3
> 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
Himanshu Madhani April 21, 2021, 8:25 p.m. UTC | #4
> 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
Himanshu Madhani April 21, 2021, 8:35 p.m. UTC | #5
> 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
Himanshu Madhani April 22, 2021, 2:24 a.m. UTC | #6
> 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
Himanshu Madhani April 22, 2021, 3:42 p.m. UTC | #7
> 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
Himanshu Madhani April 22, 2021, 3:48 p.m. UTC | #8
> 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
Himanshu Madhani April 22, 2021, 5:08 p.m. UTC | #9
> 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
Himanshu Madhani April 22, 2021, 5:17 p.m. UTC | #10
> 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
Himanshu Madhani April 22, 2021, 5:24 p.m. UTC | #11
> 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
Himanshu Madhani April 22, 2021, 5:42 p.m. UTC | #12
> 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
Hannes Reinecke April 23, 2021, 1:02 p.m. UTC | #13
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
Kashyap Desai April 23, 2021, 1:14 p.m. UTC | #14
> > +#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
Hannes Reinecke April 26, 2021, 2:22 p.m. UTC | #15
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)
Hannes Reinecke April 26, 2021, 4:05 p.m. UTC | #16
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)
Hannes Reinecke April 26, 2021, 4:06 p.m. UTC | #17
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)
Hannes Reinecke April 26, 2021, 4:10 p.m. UTC | #18
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)
Kashyap Desai April 27, 2021, 4:56 p.m. UTC | #19
> > +/**

> > + * 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)
Kashyap Desai May 11, 2021, 6:34 p.m. UTC | #20
> > @@ -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)
Kashyap Desai May 11, 2021, 6:35 p.m. UTC | #21
> > +

> > +	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)