RE: [PATCH 07/15] megaraid_sas: Reply Descriptor Post Queue(RDPQ) support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Tomas,
This reply was stuck in my outbox(was not sent). Just realized now this
when reworking on patches to accommodate your feedback. Apologies for late
reply.

Thanks,
Sumit

> -----Original Message-----
> From: Tomas Henzl [mailto:thenzl@xxxxxxxxxx]
> Sent: Thursday, January 14, 2016 11:09 PM
> To: Sumit Saxena; jbottomley@xxxxxxxxxxxxx; hch@xxxxxxxxxxxxx;
> martin.petersen@xxxxxxxxxx
> Cc: linux-scsi@xxxxxxxxxxxxxxx; kashyap.desai@xxxxxxxxxxxxx
> Subject: Re: [PATCH 07/15] megaraid_sas: Reply Descriptor Post
Queue(RDPQ)
> support
>
> On 18.12.2015 14:27, Sumit Saxena wrote:
> > This patch will create reply queue pool for each MSI-x index and will
> > provide array of all reply queue base address instead of single base
> > address of legacy mode. Using this new interface Driver can support
higher
> Queue depth allocating more reply queue as scattered DMA pool.
> >
> > If array mode is not supported driver will fall back to legacy method
of
> allocation reply pool.
> > This method fall back controller queue depth to 1K max. To enable more
> > than 1K QD, driver expect FW to support Array mode and scratch_pad3
should
> provide new queue depth value.
> >
> > Using this method, Firmware should not allow downgrade (OFU) if latest
driver
> and latest FW report 4K QD and Array mode reply queue.
> > This type of FW upgrade may cause firmware fault and it should not be
> > supported. Upgrade of FW will work, but queue depth of the controller
will be
> unchanged until reboot/driver reload.
> >
> > Signed-off-by: Kashyap Desai <kashyap.desai@xxxxxxxxxxxxx>
> > Signed-off-by: Sumit Saxena <sumit.saxena@xxxxxxxxxxxxx>
> > ---
> >  drivers/scsi/megaraid/megaraid_sas.h        |    6 +-
> >  drivers/scsi/megaraid/megaraid_sas_base.c   |    9 +
> >  drivers/scsi/megaraid/megaraid_sas_fusion.c |  543
+++++++++++++++--------
> ----
> >  drivers/scsi/megaraid/megaraid_sas_fusion.h |   12 +-
> >  4 files changed, 330 insertions(+), 240 deletions(-)
> >
> > diff --git a/drivers/scsi/megaraid/megaraid_sas.h
> > b/drivers/scsi/megaraid/megaraid_sas.h
> > index 01135be..c539516 100644
> > --- a/drivers/scsi/megaraid/megaraid_sas.h
> > +++ b/drivers/scsi/megaraid/megaraid_sas.h
> > @@ -152,6 +152,7 @@
> >  #define MFI_RESET_FLAGS				MFI_INIT_READY| \
> >  						MFI_INIT_MFIMODE| \
> >  						MFI_INIT_ABORT
> > +#define MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE    (0x01)
> >
> >  /*
> >   * MFI frame flags
> > @@ -1416,6 +1417,7 @@ enum DCMD_TIMEOUT_ACTION {
> >  #define MR_MAX_REPLY_QUEUES_EXT_OFFSET          0X003FC000
> >  #define MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT    14
> >  #define MR_MAX_MSIX_REG_ARRAY                   16
> > +#define MR_RDPQ_MODE_OFFSET			0X00800000
> >  /*
> >  * register set for both 1068 and 1078 controllers
> >  * structure extended for 1078 registers @@ -1455,8 +1457,9 @@ struct
> > megasas_register_set {
> >
> >  	u32 	outbound_scratch_pad ;		/*00B0h*/
> >  	u32	outbound_scratch_pad_2;         /*00B4h*/
> > +	u32	outbound_scratch_pad_3;         /*00B8h*/
> >
> > -	u32	reserved_4[2];			/*00B8h*/
> > +	u32	reserved_4;			/*00BCh*/
> >
> >  	u32 	inbound_low_queue_port ;	/*00C0h*/
> >
> > @@ -2117,6 +2120,7 @@ struct megasas_instance {
> >  	u8 mask_interrupts;
> >  	u16 max_chain_frame_sz;
> >  	u8 is_imr;
> > +	u8 is_rdpq;
> >  	bool dev_handle;
> >  };
> >  struct MR_LD_VF_MAP {
> > diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c
> > b/drivers/scsi/megaraid/megaraid_sas_base.c
> > index df93fa1..a3b63fa 100644
> > --- a/drivers/scsi/megaraid/megaraid_sas_base.c
> > +++ b/drivers/scsi/megaraid/megaraid_sas_base.c
> > @@ -92,6 +92,10 @@ int smp_affinity_enable = 1;
> > module_param(smp_affinity_enable, int, S_IRUGO);
> > MODULE_PARM_DESC(smp_affinity_enable, "SMP affinity feature
> > enable/disbale Default: enable(1)");
> >
> > +int rdpq_enable = 1;
> > +module_param(rdpq_enable, int, S_IRUGO);
> > +MODULE_PARM_DESC(rdpq_enable, " Allocate reply queue in chunks for
> > +large queue depth enable/disbale Default: disable(0)");
>
> Is it enabled or disabled by default (-> int rdpq_enable = 1;) ? also
fix 'disbale'

It's enabled by default. I will fix typo.
>
> > +
> >  MODULE_LICENSE("GPL");
> >  MODULE_VERSION(MEGASAS_VERSION);
> >  MODULE_AUTHOR("megaraidlinux.pdl@xxxxxxxxxxxxx");
> > @@ -5081,6 +5085,9 @@ static int megasas_init_fw(struct
megasas_instance
> *instance)
> >  				instance->msix_vectors = ((scratch_pad_2
> >  					&
> MR_MAX_REPLY_QUEUES_EXT_OFFSET)
> >  					>>
> MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT) + 1;
> > +				if (rdpq_enable)
> > +					instance->is_rdpq = (scratch_pad_2
&
> MR_RDPQ_MODE_OFFSET) ?
> > +								1 : 0;
> >  				fw_msix_count = instance->msix_vectors;
> >  				/* Save 1-15 reply post index address to
local
> memory
> >  				 * Index 0 is already saved from reg
offset @@
> -5117,6 +5124,8 @@
> > static int megasas_init_fw(struct megasas_instance *instance)
> >  	dev_info(&instance->pdev->dev,
> >  		"current msix/online cpus\t: (%d/%d)\n",
> >  		instance->msix_vectors, (unsigned int)num_online_cpus());
> > +	dev_info(&instance->pdev->dev,
> > +		"firmware supports rdpq mode\t: (%d)\n",
instance->is_rdpq);
>
> just a nit, but is_rdpq depends also on rdpq_enable, so the text is not
precise


I will modify text to reflect the correct information.
>
> >
> >  	tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
> >  		(unsigned long)instance);
> > diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c
> > b/drivers/scsi/megaraid/megaraid_sas_fusion.c
> > index e8730ef..aca0cd3 100644
> > --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
> > +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
> > @@ -92,6 +92,8 @@ void megasas_start_timer(struct megasas_instance
> *instance,
> >  			 void *fn, unsigned long interval);  extern struct
> > megasas_mgmt_info megasas_mgmt_info;  extern int resetwaittime;
> > +static void megasas_free_rdpq_fusion(struct megasas_instance
> > +*instance); static void megasas_free_reply_fusion(struct
> > +megasas_instance *instance);
> >
> >
> >
> > @@ -205,112 +207,71 @@ megasas_fire_cmd_fusion(struct
> megasas_instance
> > *instance,  #endif  }
> >
> > -
> >  /**
> > - * megasas_teardown_frame_pool_fusion -	Destroy the cmd frame DMA
> pool
> > - * @instance:				Adapter soft state
> > + * megasas_free_cmds_fusion -	Free all the cmds in the free cmd
pool
> > + * @instance:		Adapter soft state
> >   */
> > -static void megasas_teardown_frame_pool_fusion(
> > -	struct megasas_instance *instance)
> > +void
> > +megasas_free_cmds_fusion(struct megasas_instance *instance)
> >  {
> >  	int i;
> >  	struct fusion_context *fusion = instance->ctrl_context;
> > -
> > -	u16 max_cmd = instance->max_fw_cmds;
> > -
> >  	struct megasas_cmd_fusion *cmd;
> >
> > -	if (!fusion->sg_dma_pool || !fusion->sense_dma_pool) {
> > -		dev_err(&instance->pdev->dev, "dma pool is null. SG Pool
%p, "
> > -		       "sense pool : %p\n", fusion->sg_dma_pool,
> > -		       fusion->sense_dma_pool);
> > -		return;
> > -	}
> > -
> > -	/*
> > -	 * Return all frames to pool
> > -	 */
> > -	for (i = 0; i < max_cmd; i++) {
> > -
> > +	/* SG, Sense */
> > +	for (i = 0; i < instance->max_fw_cmds; i++) {
> >  		cmd = fusion->cmd_list[i];
>
> cmd might be NULL here, add a test please

Cmd cannot be NULL. If I am missing, do you see any instance where cmd
might be NULL?
>
> > -
> >  		if (cmd->sg_frame)
> >  			pci_pool_free(fusion->sg_dma_pool, cmd->sg_frame,
> > -				      cmd->sg_frame_phys_addr);
> > -
> > +			      cmd->sg_frame_phys_addr);
> >  		if (cmd->sense)
> >  			pci_pool_free(fusion->sense_dma_pool, cmd->sense,
> > -				      cmd->sense_phys_addr);
> > +			      cmd->sense_phys_addr);
> >  	}
> >
> > -	/*
> > -	 * Now destroy the pool itself
> > -	 */
> > -	pci_pool_destroy(fusion->sg_dma_pool);
> > -	pci_pool_destroy(fusion->sense_dma_pool);
> > -
> > -	fusion->sg_dma_pool = NULL;
> > -	fusion->sense_dma_pool = NULL;
> > -}
> > -
> > -/**
> > - * megasas_free_cmds_fusion -	Free all the cmds in the free cmd
pool
> > - * @instance:		Adapter soft state
> > - */
> > -void
> > -megasas_free_cmds_fusion(struct megasas_instance *instance) -{
> > -	int i;
> > -	struct fusion_context *fusion = instance->ctrl_context;
> > -
> > -	u32 max_cmds, req_sz, reply_sz, io_frames_sz;
> > -
> > +	if (fusion->sg_dma_pool) {
> > +		pci_pool_destroy(fusion->sg_dma_pool);
> > +		fusion->sg_dma_pool = NULL;
> > +	}
> > +	if (fusion->sense_dma_pool) {
> > +		pci_pool_destroy(fusion->sense_dma_pool);
> > +		fusion->sense_dma_pool = NULL;
>
> If this is needed (fusion->sense_dma_pool = NULL;), why don't we need it
few
> lines below for example for fusion->io_request_frames_pool ?
> (there should be some consistency here)
>
Agree.. will add (fusion->io_request_frames_pool=NULL).
>
> > +	}
> >
> > -	req_sz = fusion->request_alloc_sz;
> > -	reply_sz = fusion->reply_alloc_sz;
> > -	io_frames_sz = fusion->io_frames_alloc_sz;
> >
> > -	max_cmds = instance->max_fw_cmds;
> > +	/* Reply Frame, Desc*/
> > +	if (instance->is_rdpq)
> > +		megasas_free_rdpq_fusion(instance);
> > +	else
> > +		megasas_free_reply_fusion(instance);
> >
> > -	/* Free descriptors and request Frames memory */
> > +	/* Request Frame, Desc*/
> >  	if (fusion->req_frames_desc)
> > -		dma_free_coherent(&instance->pdev->dev, req_sz,
> > -				  fusion->req_frames_desc,
> > -				  fusion->req_frames_desc_phys);
> > -
> > -	if (fusion->reply_frames_desc) {
> > -		pci_pool_free(fusion->reply_frames_desc_pool,
> > -			      fusion->reply_frames_desc,
> > -			      fusion->reply_frames_desc_phys);
> > -		pci_pool_destroy(fusion->reply_frames_desc_pool);
> > -	}
> > -
> > -	if (fusion->io_request_frames) {
> > +		dma_free_coherent(&instance->pdev->dev,
> > +			fusion->request_alloc_sz, fusion->req_frames_desc,
> > +			fusion->req_frames_desc_phys);
> > +	if (fusion->io_request_frames)
> >  		pci_pool_free(fusion->io_request_frames_pool,
> > -			      fusion->io_request_frames,
> > -			      fusion->io_request_frames_phys);
> > +			fusion->io_request_frames,
> > +			fusion->io_request_frames_phys);
> > +	if (fusion->io_request_frames_pool)
> >  		pci_pool_destroy(fusion->io_request_frames_pool);
> > -	}
> >
> > -	/* Free the Fusion frame pool */
> > -	megasas_teardown_frame_pool_fusion(instance);
> >
> > -	/* Free all the commands in the cmd_list */
> > -	for (i = 0; i < max_cmds; i++)
> > +	/* cmd_list */
> > +	for (i = 0; i < instance->max_fw_cmds; i++)
> >  		kfree(fusion->cmd_list[i]);
> >
> > -	/* Free the cmd_list buffer itself */
> >  	kfree(fusion->cmd_list);
> >  	fusion->cmd_list = NULL;
>
> It is a good idea to set (fusion->cmd_list = NULL;), but a test to the
kfree should
> be added
Kfree returns void. What test is needed here? Please clarify if you mean
something elase.
>
> > -
> >  }
> >
> >  /**
> > - * megasas_create_frame_pool_fusion -	Creates DMA pool for cmd
> frames
> > + * megasas_create_sg_sense_fusion -	Creates DMA pool for cmd
frames
> >   * @instance:			Adapter soft state
> >   *
> >   */
> > -static int megasas_create_frame_pool_fusion(struct megasas_instance
> > *instance)
> > +static int megasas_create_sg_sense_fusion(struct megasas_instance
> > +*instance)
> >  {
> >  	int i;
> >  	u32 max_cmd;
> > @@ -321,186 +282,299 @@ static int
> megasas_create_frame_pool_fusion(struct megasas_instance *instance)
> >  	max_cmd = instance->max_fw_cmds;
> >
> >
> > -	/*
> > -	 * Use DMA pool facility provided by PCI layer
> > -	 */
> > -
> > -	fusion->sg_dma_pool = pci_pool_create("sg_pool_fusion", instance-
> >pdev,
> > -						instance-
> >max_chain_frame_sz,
> > -						4, 0);
> > -	if (!fusion->sg_dma_pool) {
> > -		dev_printk(KERN_DEBUG, &instance->pdev->dev, "failed to
> setup request pool fusion\n");
> > -		return -ENOMEM;
> > -	}
> > -	fusion->sense_dma_pool = pci_pool_create("sense pool fusion",
> > -						 instance->pdev,
> > -						 SCSI_SENSE_BUFFERSIZE,
64,
> 0);
> > +	fusion->sg_dma_pool =
> > +			pci_pool_create("mr_sg", instance->pdev,
> > +				instance->max_chain_frame_sz, 4, 0);
> > +	/* SCSI_SENSE_BUFFERSIZE  = 96 bytes */
> > +	fusion->sense_dma_pool =
> > +			pci_pool_create("mr_sense", instance->pdev,
> > +				SCSI_SENSE_BUFFERSIZE, 64, 0);
> >
> > -	if (!fusion->sense_dma_pool) {
> > -		dev_printk(KERN_DEBUG, &instance->pdev->dev, "failed to
> setup sense pool fusion\n");
> > -		pci_pool_destroy(fusion->sg_dma_pool);
> > -		fusion->sg_dma_pool = NULL;
> > -		return -ENOMEM;
> > -	}
> > +	if (!fusion->sense_dma_pool || !fusion->sg_dma_pool)
> > +		dev_err(&instance->pdev->dev,
> > +			"Failed from %s %d\n",  __func__, __LINE__);
>
> Allocation failed - I don't think we can ignore it.
Agreed..Will rectify this.
>
> >
> >  	/*
> >  	 * Allocate and attach a frame to each of the commands in cmd_list
> >  	 */
> >  	for (i = 0; i < max_cmd; i++) {
> > -
> >  		cmd = fusion->cmd_list[i];
> > -
> >  		cmd->sg_frame = pci_pool_alloc(fusion->sg_dma_pool,
> > -					       GFP_KERNEL,
> > -					       &cmd->sg_frame_phys_addr);
> > +					GFP_KERNEL, &cmd-
> >sg_frame_phys_addr);
> >
> >  		cmd->sense = pci_pool_alloc(fusion->sense_dma_pool,
> > -					    GFP_KERNEL, &cmd-
> >sense_phys_addr);
> > -		/*
> > -		 * megasas_teardown_frame_pool_fusion() takes care of
> freeing
> > -		 * whatever has been allocated
> > -		 */
> > +					GFP_KERNEL, &cmd-
> >sense_phys_addr);
> >  		if (!cmd->sg_frame || !cmd->sense) {
> > -			dev_printk(KERN_DEBUG, &instance->pdev->dev,
> "pci_pool_alloc failed\n");
> > -			megasas_teardown_frame_pool_fusion(instance);
> > +			dev_err(&instance->pdev->dev,
> > +				"Failed from %s %d\n",  __func__,
__LINE__);
> >  			return -ENOMEM;
> >  		}
> >  	}
> >  	return 0;
> >  }
> >
> > -/**
> > - * megasas_alloc_cmds_fusion -	Allocates the command packets
> > - * @instance:		Adapter soft state
> > - *
> > - *
> > - * Each frame has a 32-bit field called context. This context is used
> > to get
> > - * back the megasas_cmd_fusion from the frame when a frame gets
> > completed
> > - * In this driver, the 32 bit values are the indices into an array
cmd_list.
> > - * This array is used only to look up the megasas_cmd_fusion given
the
> context.
> > - * The free commands themselves are maintained in a linked list
called
> cmd_pool.
> > - *
> > - * cmds are formed in the io_request and sg_frame members of the
> > - * megasas_cmd_fusion. The context field is used to get a request
> > descriptor
> > - * and is used as SMID of the cmd.
> > - * SMID value range is from 1 to max_fw_cmds.
> > - */
> >  int
> > -megasas_alloc_cmds_fusion(struct megasas_instance *instance)
> > +megasas_alloc_cmdlist_fusion(struct megasas_instance *instance)
> >  {
> > -	int i, j, count;
> > -	u32 max_cmd, io_frames_sz;
> > +	u32 max_cmd, i;
> >  	struct fusion_context *fusion;
> > -	struct megasas_cmd_fusion *cmd;
> > -	union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
> > -	u32 offset;
> > -	dma_addr_t io_req_base_phys;
> > -	u8 *io_req_base;
> >
> >  	fusion = instance->ctrl_context;
> >
> >  	max_cmd = instance->max_fw_cmds;
> >
> > +	/*
> > +	 * fusion->cmd_list is an array of struct megasas_cmd_fusion
pointers.
> > +	 * Allocate the dynamic array first and then allocate individual
> > +	 * commands.
> > +	 */
> > +	fusion->cmd_list = kmalloc(sizeof(struct megasas_cmd_fusion *) *
> max_cmd,
> > +						GFP_KERNEL);
> > +	if (!fusion->cmd_list) {
> > +		dev_err(&instance->pdev->dev,
> > +			"Failed from %s %d\n",  __func__, __LINE__);
> > +		return -ENOMEM;
> > +	}
> > +	memset(fusion->cmd_list, 0,
> > +		sizeof(struct megasas_cmd_fusion *) * max_cmd);
> > +
> > +	for (i = 0; i < max_cmd; i++) {
> > +		fusion->cmd_list[i] = kmalloc(sizeof(struct
> megasas_cmd_fusion),
> > +					      GFP_KERNEL);
>
> kzalloc here and there, as the kbuild script already wrote
>
> > +		if (!fusion->cmd_list[i]) {
> > +			dev_err(&instance->pdev->dev,
> > +				"Failed from %s %d\n",  __func__,
__LINE__);
> > +			return -ENOMEM;
> > +		}
> > +		memset(fusion->cmd_list[i], 0, sizeof(struct
> megasas_cmd_fusion));
> > +	}
> > +	return 0;
> > +}
> > +int
> > +megasas_alloc_request_fusion(struct megasas_instance *instance) {
> > +	struct fusion_context *fusion;
> > +
> > +	fusion = instance->ctrl_context;
> > +
> >  	fusion->req_frames_desc =
> >  		dma_alloc_coherent(&instance->pdev->dev,
> > -				   fusion->request_alloc_sz,
> > -				   &fusion->req_frames_desc_phys,
> GFP_KERNEL);
> > -
> > +			fusion->request_alloc_sz,
> > +			&fusion->req_frames_desc_phys, GFP_KERNEL);
> >  	if (!fusion->req_frames_desc) {
> > -		dev_err(&instance->pdev->dev, "Could not allocate memory
for
> "
> > -		       "request_frames\n");
> > -		goto fail_req_desc;
> > +		dev_err(&instance->pdev->dev,
> > +			"Failed from %s %d\n",  __func__, __LINE__);
> > +		return -ENOMEM;
> > +	}
> > +
> > +	fusion->io_request_frames_pool =
> > +			pci_pool_create("mr_ioreq", instance->pdev,
> > +				fusion->io_frames_alloc_sz, 16, 0);
>
> Why do you need a pool, you just allocate once a single region, or not?
> Please turn it into a dma_alloc_coherent.

There are some places where dma_alloc_coherent can be used instead of PCI
APIs. If you are OK with ignoring this for now,
I will be sending followup patch to address all such issues.
>
> > +
> > +	if (!fusion->io_request_frames_pool) {
> > +		dev_err(&instance->pdev->dev,
> > +			"Failed from %s %d\n",  __func__, __LINE__);
> > +		return -ENOMEM;
> > +	}
> > +
> > +	fusion->io_request_frames =
> > +			pci_pool_alloc(fusion->io_request_frames_pool,
> > +				GFP_KERNEL, &fusion-
> >io_request_frames_phys);
> > +	if (!fusion->io_request_frames) {
> > +		dev_err(&instance->pdev->dev,
> > +			"Failed from %s %d\n",  __func__, __LINE__);
> > +		return -ENOMEM;
> >  	}
> > +	return 0;
> > +}
> > +
> > +int
> > +megasas_alloc_reply_fusion(struct megasas_instance *instance) {
> > +	int i, count;
> > +	struct fusion_context *fusion;
> > +	union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
> > +	fusion = instance->ctrl_context;
> >
> >  	count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
> >  	fusion->reply_frames_desc_pool =
> > -		pci_pool_create("reply_frames pool", instance->pdev,
> > +			pci_pool_create("mr_reply", instance->pdev,
> >  				fusion->reply_alloc_sz * count, 16, 0);
> >
> >  	if (!fusion->reply_frames_desc_pool) {
> > -		dev_err(&instance->pdev->dev, "Could not allocate memory
for
> "
> > -		       "reply_frame pool\n");
> > -		goto fail_reply_desc;
> > +		dev_err(&instance->pdev->dev,
> > +			"Failed from %s %d\n",  __func__, __LINE__);
> > +		return -ENOMEM;
> >  	}
>
> Same here, I could understand it if the code were merged with
> megasas_alloc_rdpq_fusion but it is not. Why a pool?
Same reason for this..
>
> >
> > -	fusion->reply_frames_desc =
> > -		pci_pool_alloc(fusion->reply_frames_desc_pool, GFP_KERNEL,
> > -			       &fusion->reply_frames_desc_phys);
> > -	if (!fusion->reply_frames_desc) {
> > -		dev_err(&instance->pdev->dev, "Could not allocate memory
for
> "
> > -		       "reply_frame pool\n");
> > -		pci_pool_destroy(fusion->reply_frames_desc_pool);
> > -		goto fail_reply_desc;
> > +	fusion->reply_frames_desc[0] =
> > +		pci_pool_alloc(fusion->reply_frames_desc_pool,
> > +			GFP_KERNEL, &fusion->reply_frames_desc_phys[0]);
> > +	if (!fusion->reply_frames_desc[0]) {
> > +		dev_err(&instance->pdev->dev,
> > +			"Failed from %s %d\n",  __func__, __LINE__);
> > +		return -ENOMEM;
> >  	}
> > -
> > -	reply_desc = fusion->reply_frames_desc;
> > +	reply_desc = fusion->reply_frames_desc[0];
> >  	for (i = 0; i < fusion->reply_q_depth * count; i++, reply_desc++)
> > -		reply_desc->Words = cpu_to_le64(ULLONG_MAX);
> > +		reply_desc->Words = ULLONG_MAX;
>
> The megasas_reset_reply_desc function seems to be used for this kind of
> resetting, could it be used here ? (and in megasas_alloc_rdpq_fusion)
There you
> also kept the cpu_to_le64(..) that doesn't matter, but again for
consistency...

I will take care of all this in next patchset.
>
> >
> > -	io_frames_sz = fusion->io_frames_alloc_sz;
> > +	/* This is not a rdpq mode, but driver still populate
> > +	 * reply_frame_desc array to use same msix index in ISR path.
> > +	 */
> > +	for (i = 0; i < (count - 1); i++)
> > +		fusion->reply_frames_desc[i + 1] =
> > +			fusion->reply_frames_desc[i] +
> > +			(fusion->reply_alloc_sz)/sizeof(union
> > +MPI2_REPLY_DESCRIPTORS_UNION);
> >
> > -	fusion->io_request_frames_pool =
> > -		pci_pool_create("io_request_frames pool", instance->pdev,
> > -				fusion->io_frames_alloc_sz, 16, 0);
> > +	return 0;
> > +}
> >
> > -	if (!fusion->io_request_frames_pool) {
> > -		dev_err(&instance->pdev->dev, "Could not allocate memory
for
> "
> > -		       "io_request_frame pool\n");
> > -		goto fail_io_frames;
> > +int
> > +megasas_alloc_rdpq_fusion(struct megasas_instance *instance) {
> > +	int i, j, count;
> > +	struct fusion_context *fusion;
> > +	union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
> > +
> > +	fusion = instance->ctrl_context;
> > +
> > +	fusion->rdpq_virt = pci_alloc_consistent(instance->pdev,
> > +				sizeof(struct
> MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY) *
> > +MAX_MSIX_QUEUES_FUSION,
>
> is dma_alloc_coherent possible here?
>
> > +				&fusion->rdpq_phys);
> > +	if (!fusion->rdpq_virt) {
> > +		dev_err(&instance->pdev->dev,
> > +			"Failed from %s %d\n",  __func__, __LINE__);
> > +		return -ENOMEM;
> >  	}
> >
> > -	fusion->io_request_frames =
> > -		pci_pool_alloc(fusion->io_request_frames_pool, GFP_KERNEL,
> > -			       &fusion->io_request_frames_phys);
> > -	if (!fusion->io_request_frames) {
> > -		dev_err(&instance->pdev->dev, "Could not allocate memory
for
> "
> > -		       "io_request_frames frames\n");
> > -		pci_pool_destroy(fusion->io_request_frames_pool);
> > -		goto fail_io_frames;
> > +	memset(fusion->rdpq_virt, 0,
> > +			sizeof(struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY) *
> MAX_MSIX_QUEUES_FUSION);
> > +	count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
> > +	fusion->reply_frames_desc_pool = pci_pool_create("mr_rdpq",
> > +							 instance->pdev,
> fusion->reply_alloc_sz, 16, 0);
> > +
> > +	if (!fusion->reply_frames_desc_pool) {
> > +		dev_err(&instance->pdev->dev,
> > +			"Failed from %s %d\n",  __func__, __LINE__);
> > +		return -ENOMEM;
> >  	}
> >
> > -	/*
> > -	 * fusion->cmd_list is an array of struct megasas_cmd_fusion
pointers.
> > -	 * Allocate the dynamic array first and then allocate individual
> > -	 * commands.
> > -	 */
> > -	fusion->cmd_list = kzalloc(sizeof(struct megasas_cmd_fusion *)
> > -				   * max_cmd, GFP_KERNEL);
> > +	for (i = 0; i < count; i++) {
> > +		fusion->reply_frames_desc[i] =
> > +				pci_pool_alloc(fusion-
> >reply_frames_desc_pool,
> > +					GFP_KERNEL, &fusion-
> >reply_frames_desc_phys[i]);
> > +		if (!fusion->reply_frames_desc[i]) {
> > +			dev_err(&instance->pdev->dev,
> > +				"Failed from %s %d\n",  __func__,
__LINE__);
> > +			return -ENOMEM;
> > +		}
> >
> > -	if (!fusion->cmd_list) {
> > -		dev_printk(KERN_DEBUG, &instance->pdev->dev, "out of
> memory. Could not alloc "
> > -		       "memory for cmd_list_fusion\n");
> > -		goto fail_cmd_list;
> > +		fusion->rdpq_virt[i].RDPQBaseAddress =
> > +			fusion->reply_frames_desc_phys[i];
> > +
> > +		reply_desc = fusion->reply_frames_desc[i];
> > +		for (j = 0; j < fusion->reply_q_depth; j++, reply_desc++)
> > +			reply_desc->Words = ULLONG_MAX;
> >  	}
> > +	return 0;
> > +}
> >
> > -	max_cmd = instance->max_fw_cmds;
> > -	for (i = 0; i < max_cmd; i++) {
> > -		fusion->cmd_list[i] = kmalloc(sizeof(struct
> megasas_cmd_fusion),
> > -					      GFP_KERNEL);
> > -		if (!fusion->cmd_list[i]) {
> > -			dev_err(&instance->pdev->dev, "Could not alloc cmd
> list fusion\n");
> > +static void
> > +megasas_free_rdpq_fusion(struct megasas_instance *instance) {
> >
> > -			for (j = 0; j < i; j++)
> > -				kfree(fusion->cmd_list[j]);
> > +	int i;
> > +	struct fusion_context *fusion;
> >
> > -			kfree(fusion->cmd_list);
> > -			fusion->cmd_list = NULL;
> > -			goto fail_cmd_list;
> > -		}
> > +	fusion = instance->ctrl_context;
> > +
> > +	for (i = 0; i < MAX_MSIX_QUEUES_FUSION; i++) {
> > +		if (fusion->reply_frames_desc[i])
> > +			pci_pool_free(fusion->reply_frames_desc_pool,
> > +				fusion->reply_frames_desc[i],
> > +				fusion->reply_frames_desc_phys[i]);
> >  	}
> >
> > -	/* The first 256 bytes (SMID 0) is not used. Don't add to cmd list
*/
> > -	io_req_base = fusion->io_request_frames +
> > -		MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
> > -	io_req_base_phys = fusion->io_request_frames_phys +
> > -		MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
> > +	if (fusion->reply_frames_desc_pool)
> > +		pci_pool_destroy(fusion->reply_frames_desc_pool);
> > +
> > +	if (fusion->rdpq_virt)
> > +		pci_free_consistent(instance->pdev,
> > +			sizeof(struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY) *
> MAX_MSIX_QUEUES_FUSION,
> > +			fusion->rdpq_virt, fusion->rdpq_phys); }
> > +
> > +static void
> > +megasas_free_reply_fusion(struct megasas_instance *instance) {
> > +
> > +	struct fusion_context *fusion;
> > +
> > +	fusion = instance->ctrl_context;
> > +
> > +	if (fusion->reply_frames_desc[0])
> > +		pci_pool_free(fusion->reply_frames_desc_pool,
> > +			fusion->reply_frames_desc[0],
> > +			fusion->reply_frames_desc_phys[0]);
> > +
> > +	if (fusion->reply_frames_desc_pool)
> > +		pci_pool_destroy(fusion->reply_frames_desc_pool);
> > +
> > +}
> > +
> > +
> > +/**
> > + * megasas_alloc_cmds_fusion -	Allocates the command packets
> > + * @instance:		Adapter soft state
> > + *
> > + *
> > + * Each frame has a 32-bit field called context. This context is used
> > +to get
> > + * back the megasas_cmd_fusion from the frame when a frame gets
> > +completed
> > + * In this driver, the 32 bit values are the indices into an array
cmd_list.
> > + * This array is used only to look up the megasas_cmd_fusion given
the
> context.
> > + * The free commands themselves are maintained in a linked list
called
> cmd_pool.
> > + *
> > + * cmds are formed in the io_request and sg_frame members of the
> > + * megasas_cmd_fusion. The context field is used to get a request
> > +descriptor
> > + * and is used as SMID of the cmd.
> > + * SMID value range is from 1 to max_fw_cmds.
> > + */
> > +int
> > +megasas_alloc_cmds_fusion(struct megasas_instance *instance) {
> > +	int i;
> > +	struct fusion_context *fusion;
> > +	struct megasas_cmd_fusion *cmd;
> > +	u32 offset;
> > +	dma_addr_t io_req_base_phys;
> > +	u8 *io_req_base;
> > +
> > +
> > +	fusion = instance->ctrl_context;
> > +
> > +	if (megasas_alloc_cmdlist_fusion(instance))
>
> We may need to call megasas_free_cmds_fusion here too (to free fusion-
> >cmd_list)
I will work on all error condition handling stuff..
>
> > +		return -ENOMEM;
> > +
> > +	if (megasas_alloc_request_fusion(instance))
> > +		goto fail_exit;
> > +
> > +	if (instance->is_rdpq) {
> > +		if (megasas_alloc_rdpq_fusion(instance))
> > +			goto fail_exit;
> > +	} else
> > +		if (megasas_alloc_reply_fusion(instance))
> > +			goto fail_exit;
> > +
> > +
> > +	/* The first 256 bytes (SMID 0) is not used. Don't add to the cmd
list */
> > +	io_req_base = fusion->io_request_frames +
> MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
> > +	io_req_base_phys = fusion->io_request_frames_phys +
> > +MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
> >
> >  	/*
> >  	 * Add all the commands to command pool (fusion->cmd_pool)
> >  	 */
> >
> >  	/* SMID 0 is reserved. Set SMID/index from 1 */
> > -	for (i = 0; i < max_cmd; i++) {
> > +	for (i = 0; i < instance->max_fw_cmds; i++) {
> >  		cmd = fusion->cmd_list[i];
> >  		offset = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * i;
> >  		memset(cmd, 0, sizeof(struct megasas_cmd_fusion));
>
> That memset was already done in megasas_alloc_cmdlist_fusion
Will use kzalloc instead of kmalloc to avoid all memset to zero
instructions.
>
> > @@ -518,35 +592,13 @@ megasas_alloc_cmds_fusion(struct
> megasas_instance *instance)
> >  		cmd->io_request_phys_addr = io_req_base_phys + offset;
> >  	}/
> >
> > -	/*
> > -	 * Create a frame pool and assign one frame to each cmd
> > -	 */
> > -	if (megasas_create_frame_pool_fusion(instance)) {
> > -		dev_printk(KERN_DEBUG, &instance->pdev->dev, "Error
> creating frame DMA pool\n");
> > -		megasas_free_cmds_fusion(instance);
> > -		goto fail_req_desc;
> > -	}
> > +	if (megasas_create_sg_sense_fusion(instance))
> > +		goto fail_exit;
> >
> >  	return 0;
> >
> > -fail_cmd_list:
> > -	pci_pool_free(fusion->io_request_frames_pool, fusion-
> >io_request_frames,
> > -		      fusion->io_request_frames_phys);
> > -	pci_pool_destroy(fusion->io_request_frames_pool);
> > -fail_io_frames:
> > -	dma_free_coherent(&instance->pdev->dev, fusion->request_alloc_sz,
> > -			  fusion->reply_frames_desc,
> > -			  fusion->reply_frames_desc_phys);
> > -	pci_pool_free(fusion->reply_frames_desc_pool,
> > -		      fusion->reply_frames_desc,
> > -		      fusion->reply_frames_desc_phys);
> > -	pci_pool_destroy(fusion->reply_frames_desc_pool);
> > -
> > -fail_reply_desc:
> > -	dma_free_coherent(&instance->pdev->dev, fusion->request_alloc_sz,
> > -			  fusion->req_frames_desc,
> > -			  fusion->req_frames_desc_phys);
> > -fail_req_desc:
> > +fail_exit:
> > +	megasas_free_cmds_fusion(instance);
> >  	return -ENOMEM;
> >  }
> >
> > @@ -594,16 +646,17 @@ int
> >  megasas_ioc_init_fusion(struct megasas_instance *instance)  {
> >  	struct megasas_init_frame *init_frame;
> > -	struct MPI2_IOC_INIT_REQUEST *IOCInitMessage;
> > +	struct MPI2_IOC_INIT_REQUEST *IOCInitMessage = NULL;
> >  	dma_addr_t	ioc_init_handle;
> >  	struct megasas_cmd *cmd;
> > -	u8 ret;
> > +	u8 ret, cur_rdpq_mode;
> >  	struct fusion_context *fusion;
> >  	union MEGASAS_REQUEST_DESCRIPTOR_UNION req_desc;
> >  	int i;
> >  	struct megasas_header *frame_hdr;
> >  	const char *sys_info;
> >  	MFI_CAPABILITIES *drv_ops;
> > +	u32 scratch_pad_2;
> >
> >  	fusion = instance->ctrl_context;
> >
> > @@ -615,6 +668,18 @@ megasas_ioc_init_fusion(struct megasas_instance
> *instance)
> >  		goto fail_get_cmd;
> >  	}
> >
> > +	scratch_pad_2 = readl
> > +		(&instance->reg_set->outbound_scratch_pad_2);
> > +
> > +	cur_rdpq_mode = (scratch_pad_2 & MR_RDPQ_MODE_OFFSET) ? 1 : 0;
> > +
> > +	if (instance->is_rdpq && !cur_rdpq_mode) {
> > +		dev_err(&instance->pdev->dev, "Firmware downgrade *NOT
> SUPPORTED*"
> > +			" from RDPQ mode to non RDPQ mode\n");
>
> How does this work ? is_rdpq is set in megasas_init_fw only when the fw
> supports it, why do you test it here again ? I think I'm miss something.

"is_rdpq" stores the capability of firmware flashed during driver load and
"cur_rdpq_mode" tells capability of upgraded/downgraded firmware(OFU)
without reloading driver.
This condition is just to ensure that firmware downgrade from RDPQ mode to
non RDPQ mode should not be allowed.
>
> Tomas
>
> > +		ret = 1;
> > +		goto fail_fw_init;
> > +	}
> > +
> >  	IOCInitMessage =
> >  	  dma_alloc_coherent(&instance->pdev->dev,
> >  			     sizeof(struct MPI2_IOC_INIT_REQUEST), @@
-636,7
> +701,11 @@
> > megasas_ioc_init_fusion(struct megasas_instance *instance)
> >  	IOCInitMessage->SystemRequestFrameSize =
> > cpu_to_le16(MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE / 4);
> >
> >  	IOCInitMessage->ReplyDescriptorPostQueueDepth =
> cpu_to_le16(fusion->reply_q_depth);
> > -	IOCInitMessage->ReplyDescriptorPostQueueAddress	=
> cpu_to_le64(fusion->reply_frames_desc_phys);
> > +	IOCInitMessage->ReplyDescriptorPostQueueAddress = instance-
> >is_rdpq ?
> > +			cpu_to_le64(fusion->rdpq_phys) :
> > +			cpu_to_le64(fusion->reply_frames_desc_phys[0]);
> > +	IOCInitMessage->MsgFlags = instance->is_rdpq ?
> > +			MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE : 0;
> >  	IOCInitMessage->SystemRequestFrameBaseAddress =
> cpu_to_le64(fusion->io_request_frames_phys);
> >  	IOCInitMessage->HostMSIxVectors = instance->msix_vectors;
> >  	init_frame = (struct megasas_init_frame *)cmd->frame; @@ -1087,7
> > +1156,10 @@ megasas_init_adapter_fusion(struct megasas_instance
> *instance)
> >  	 */
> >  	instance->max_fw_cmds =
> >  		instance->instancet->read_fw_status_reg(reg_set) &
0x00FFFF;
> > -	instance->max_fw_cmds = min(instance->max_fw_cmds, (u16)1008);
> > +	dev_info(&instance->pdev->dev,
> > +		"firmware support max fw cmd\t: (%d)\n", instance-
> >max_fw_cmds);
> > +	if (!instance->is_rdpq)
> > +		instance->max_fw_cmds = min_t(u16, instance-
> >max_fw_cmds, 1024);
> >
> >  	/*
> >  	 * Reduce the max supported cmds by 1. This is to ensure that the
@@
> > -2110,10 +2182,8 @@ complete_cmd_fusion(struct megasas_instance
> *instance, u32 MSIxIndex)
> >  	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
> >  		return IRQ_HANDLED;
> >
> > -	desc = fusion->reply_frames_desc;
> > -	desc += ((MSIxIndex * fusion->reply_alloc_sz)/
> > -		 sizeof(union MPI2_REPLY_DESCRIPTORS_UNION)) +
> > -		fusion->last_reply_idx[MSIxIndex];
> > +	desc = fusion->reply_frames_desc[MSIxIndex] +
> > +				fusion->last_reply_idx[MSIxIndex];
> >
> >  	reply_desc = (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR
> *)desc;
> >
> > @@ -2208,9 +2278,7 @@ complete_cmd_fusion(struct megasas_instance
> > *instance, u32 MSIxIndex)
> >
> >  		/* Get the next reply descriptor */
> >  		if (!fusion->last_reply_idx[MSIxIndex])
> > -			desc = fusion->reply_frames_desc +
> > -				((MSIxIndex * fusion->reply_alloc_sz)/
> > -				 sizeof(union
> MPI2_REPLY_DESCRIPTORS_UNION));
> > +			desc = fusion->reply_frames_desc[MSIxIndex];
> >  		else
> >  			desc++;
> >
> > @@ -2688,17 +2756,18 @@ out:
> >
> >  void  megasas_reset_reply_desc(struct megasas_instance *instance)  {
> > -	int i, count;
> > +	int i, j, count;
> >  	struct fusion_context *fusion;
> >  	union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
> >
> >  	fusion = instance->ctrl_context;
> >  	count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
> > -	for (i = 0 ; i < count ; i++)
> > +	for (i = 0 ; i < count ; i++) {
> >  		fusion->last_reply_idx[i] = 0;
> > -	reply_desc = fusion->reply_frames_desc;
> > -	for (i = 0 ; i < fusion->reply_q_depth * count; i++, reply_desc++)
> > -		reply_desc->Words = cpu_to_le64(ULLONG_MAX);
> > +		reply_desc = fusion->reply_frames_desc[i];
> > +		for (j = 0 ; j < fusion->reply_q_depth; j++, reply_desc++)
> > +			reply_desc->Words = cpu_to_le64(ULLONG_MAX);
> > +	}
> >  }
> >
> >  /*
> > diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h
> > b/drivers/scsi/megaraid/megaraid_sas_fusion.h
> > index db0978d..80eaee2 100644
> > --- a/drivers/scsi/megaraid/megaraid_sas_fusion.h
> > +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h
> > @@ -928,6 +928,12 @@ struct MR_PD_CFG_SEQ_NUM_SYNC {
> >  	struct MR_PD_CFG_SEQ seq[1];
> >  } __packed;
> >
> > +struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY {
> > +	u64 RDPQBaseAddress;
> > +	u32 Reserved1;
> > +	u32 Reserved2;
> > +};
> > +
> >  struct fusion_context {
> >  	struct megasas_cmd_fusion **cmd_list;
> >  	dma_addr_t req_frames_desc_phys;
> > @@ -940,8 +946,8 @@ struct fusion_context {
> >  	struct dma_pool *sg_dma_pool;
> >  	struct dma_pool *sense_dma_pool;
> >
> > -	dma_addr_t reply_frames_desc_phys;
> > -	union MPI2_REPLY_DESCRIPTORS_UNION *reply_frames_desc;
> > +	dma_addr_t reply_frames_desc_phys[MAX_MSIX_QUEUES_FUSION];
> > +	union MPI2_REPLY_DESCRIPTORS_UNION
> > +*reply_frames_desc[MAX_MSIX_QUEUES_FUSION];
> >  	struct dma_pool *reply_frames_desc_pool;
> >
> >  	u16 last_reply_idx[MAX_MSIX_QUEUES_FUSION];
> > @@ -951,6 +957,8 @@ struct fusion_context {
> >  	u32 reply_alloc_sz;
> >  	u32 io_frames_alloc_sz;
> >
> > +	struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY *rdpq_virt;
> > +	dma_addr_t rdpq_phys;
> >  	u16	max_sge_in_main_msg;
> >  	u16	max_sge_in_chain;
> >
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux