From: Tomas Henzl <thenzl@redhat.com>
To: Sumit Saxena <sumit.saxena@avagotech.com>,
jbottomley@parallels.com, hch@infradead.org,
martin.petersen@oracle.com
Cc: linux-scsi@vger.kernel.org, kashyap.desai@avagotech.com
Subject: Re: [PATCH 07/15] megaraid_sas: Reply Descriptor Post Queue(RDPQ) support
Date: Thu, 14 Jan 2016 18:38:50 +0100 [thread overview]
Message-ID: <5697DD2A.1080601@redhat.com> (raw)
In-Reply-To: <1450445228-26571-8-git-send-email-Sumit.Saxena@avagotech.com>
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@avagotech.com>
> Signed-off-by: Sumit Saxena <sumit.saxena@avagotech.com>
> ---
> 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'
> +
> MODULE_LICENSE("GPL");
> MODULE_VERSION(MEGASAS_VERSION);
> MODULE_AUTHOR("megaraidlinux.pdl@avagotech.com");
> @@ -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
>
> 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
> -
> 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)
> + }
>
> - 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
> -
> }
>
> /**
> - * 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.
>
> /*
> * 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.
> +
> + 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?
>
> - 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...
>
> - 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)
> + 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
> @@ -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.
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;
>
next prev parent reply other threads:[~2016-01-14 17:38 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-12-18 13:26 [PATCH 00/15] megaraid_sas: Updates for scsi-next Sumit Saxena
2015-12-18 13:26 ` [PATCH 01/15] megaraid_sas: Do not allow PCI access during OCR Sumit Saxena
2016-01-11 17:02 ` Tomas Henzl
2015-12-18 13:26 ` [PATCH 02/15] megaraid_sas: MFI IO timeout handling Sumit Saxena
2016-01-11 17:02 ` Tomas Henzl
2015-12-18 13:26 ` [PATCH 03/15] megaraid_sas: Syncing request flags macro names with firmware Sumit Saxena
2016-01-11 17:03 ` Tomas Henzl
2015-12-18 13:26 ` [PATCH 04/15] megaraid_sas: Task management support Sumit Saxena
2016-01-11 17:03 ` Tomas Henzl
2016-01-14 12:04 ` Sumit Saxena
2015-12-18 13:26 ` [PATCH 05/15] megaraid_sas: Update device Queue depth based on interface type Sumit Saxena
2016-01-12 14:16 ` Tomas Henzl
2016-01-14 11:48 ` Sumit Saxena
2015-12-18 13:26 ` [PATCH 06/15] megaraid_sas: Fastpath region lock bypass Sumit Saxena
2016-01-12 14:44 ` Tomas Henzl
2015-12-18 13:27 ` [PATCH 07/15] megaraid_sas: Reply Descriptor Post Queue(RDPQ) support Sumit Saxena
2015-12-18 14:49 ` kbuild test robot
2015-12-18 14:49 ` [PATCH] megaraid_sas: fix kzalloc-simple.cocci warnings kbuild test robot
2016-01-14 17:38 ` Tomas Henzl [this message]
2016-01-27 18:15 ` [PATCH 07/15] megaraid_sas: Reply Descriptor Post Queue(RDPQ) support Sumit Saxena
2015-12-18 13:27 ` [PATCH 08/15] megaraid_sas: Code optimization build_and_issue_cmd return-type Sumit Saxena
2016-01-14 18:05 ` Tomas Henzl
2015-12-18 13:27 ` [PATCH 09/15] megaraid_sas: Dual Queue depth support Sumit Saxena
2016-01-19 13:34 ` Tomas Henzl
2016-01-19 13:44 ` Sumit Saxena
2016-01-20 13:55 ` Tomas Henzl
2016-01-20 14:09 ` Sumit Saxena
2016-01-20 14:16 ` Tomas Henzl
2016-01-20 15:08 ` Sumit Saxena
2016-01-20 16:00 ` Tomas Henzl
2016-01-27 2:02 ` Martin K. Petersen
2016-01-27 7:09 ` Sumit Saxena
2015-12-18 13:27 ` [PATCH 10/15] megaraid_sas: IO throttling support Sumit Saxena
2016-01-19 13:38 ` Tomas Henzl
2016-01-28 7:18 ` Sumit Saxena
2015-12-18 13:27 ` [PATCH 11/15] megaraid_sas: Make adprecovery variable atomic Sumit Saxena
2016-01-19 13:52 ` Tomas Henzl
2016-01-28 8:30 ` Sumit Saxena
2015-12-18 13:27 ` [PATCH 12/15] megaraid_sas: MFI adapter's OCR changes Sumit Saxena
2016-01-19 14:22 ` Tomas Henzl
2016-01-28 11:12 ` Sumit Saxena
2015-12-18 13:27 ` [PATCH 13/15] megaraid_sas: Introduce module parameter for SCSI command-timeout Sumit Saxena
2016-01-19 14:57 ` Tomas Henzl
2016-01-28 11:17 ` Sumit Saxena
2015-12-18 13:27 ` [PATCH 14/15] megaraid_sas: SPERC OCR changes Sumit Saxena
2016-01-19 15:14 ` Tomas Henzl
2015-12-18 13:27 ` [PATCH 15/15] megaraid_sas: SPERC boot driver reorder Sumit Saxena
2015-12-18 14:05 ` Christoph Hellwig
2016-01-08 7:07 ` Sumit Saxena
2016-01-12 5:26 ` Sumit Saxena
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5697DD2A.1080601@redhat.com \
--to=thenzl@redhat.com \
--cc=hch@infradead.org \
--cc=jbottomley@parallels.com \
--cc=kashyap.desai@avagotech.com \
--cc=linux-scsi@vger.kernel.org \
--cc=martin.petersen@oracle.com \
--cc=sumit.saxena@avagotech.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).