diff options
Diffstat (limited to 'drivers/scsi/megaraid/megaraid_sas_fusion.c')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_fusion.c | 676 |
1 files changed, 498 insertions, 178 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 3c399e7b3fe1..65dc4fea6352 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -93,8 +93,37 @@ extern unsigned int resetwaittime; extern unsigned int dual_qdepth_disable; static void megasas_free_rdpq_fusion(struct megasas_instance *instance); static void megasas_free_reply_fusion(struct megasas_instance *instance); +static inline +void megasas_configure_queue_sizes(struct megasas_instance *instance); +/** + * megasas_check_same_4gb_region - check if allocation + * crosses same 4GB boundary or not + * @instance - adapter's soft instance + * start_addr - start address of DMA allocation + * size - size of allocation in bytes + * return - true : allocation does not cross same + * 4GB boundary + * false: allocation crosses same + * 4GB boundary + */ +static inline bool megasas_check_same_4gb_region + (struct megasas_instance *instance, dma_addr_t start_addr, size_t size) +{ + dma_addr_t end_addr; + + end_addr = start_addr + size; + if (upper_32_bits(start_addr) != upper_32_bits(end_addr)) { + dev_err(&instance->pdev->dev, + "Failed to get same 4GB boundary: start_addr: 0x%llx end_addr: 0x%llx\n", + (unsigned long long)start_addr, + (unsigned long long)end_addr); + return false; + } + + return true; +} /** * megasas_enable_intr_fusion - Enables interrupts @@ -197,7 +226,7 @@ static void megasas_fire_cmd_fusion(struct megasas_instance *instance, union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc) { - if (instance->is_ventura) + if (instance->adapter_type == VENTURA_SERIES) writel(le32_to_cpu(req_desc->u.low), &instance->reg_set->inbound_single_queue_port); else { @@ -240,7 +269,7 @@ megasas_fusion_update_can_queue(struct megasas_instance *instance, int fw_boot_c reg_set = instance->reg_set; /* ventura FW does not fill outbound_scratch_pad_3 with queue depth */ - if (!instance->is_ventura) + if (instance->adapter_type < VENTURA_SERIES) cur_max_fw_cmds = readl(&instance->reg_set->outbound_scratch_pad_3) & 0x00FFFF; @@ -251,8 +280,8 @@ megasas_fusion_update_can_queue(struct megasas_instance *instance, int fw_boot_c (instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF) - MEGASAS_FUSION_IOCTL_CMDS; dev_info(&instance->pdev->dev, - "Current firmware maximum commands: %d\t LDIO threshold: %d\n", - cur_max_fw_cmds, ldio_threshold); + "Current firmware supports maximum commands: %d\t LDIO threshold: %d\n", + cur_max_fw_cmds, ldio_threshold); if (fw_boot_context == OCR_CONTEXT) { cur_max_fw_cmds = cur_max_fw_cmds - 1; @@ -267,10 +296,6 @@ megasas_fusion_update_can_queue(struct megasas_instance *instance, int fw_boot_c instance->max_fw_cmds = cur_max_fw_cmds; instance->ldio_threshold = ldio_threshold; - if (!instance->is_rdpq) - instance->max_fw_cmds = - min_t(u16, instance->max_fw_cmds, 1024); - if (reset_devices) instance->max_fw_cmds = min(instance->max_fw_cmds, (u16)MEGASAS_KDUMP_QUEUE_DEPTH); @@ -280,19 +305,7 @@ megasas_fusion_update_can_queue(struct megasas_instance *instance, int fw_boot_c * does not exceed max cmds that the FW can support */ instance->max_fw_cmds = instance->max_fw_cmds-1; - - instance->max_scsi_cmds = instance->max_fw_cmds - - (MEGASAS_FUSION_INTERNAL_CMDS + - MEGASAS_FUSION_IOCTL_CMDS); - instance->cur_can_queue = instance->max_scsi_cmds; - instance->host->can_queue = instance->cur_can_queue; } - - if (instance->is_ventura) - instance->max_mpt_cmds = - instance->max_fw_cmds * RAID_1_PEER_CMDS; - else - instance->max_mpt_cmds = instance->max_fw_cmds; } /** * megasas_free_cmds_fusion - Free all the cmds in the free cmd pool @@ -305,17 +318,23 @@ megasas_free_cmds_fusion(struct megasas_instance *instance) struct fusion_context *fusion = instance->ctrl_context; struct megasas_cmd_fusion *cmd; - /* SG, Sense */ - for (i = 0; i < instance->max_mpt_cmds; i++) { - cmd = fusion->cmd_list[i]; - if (cmd) { - if (cmd->sg_frame) - dma_pool_free(fusion->sg_dma_pool, cmd->sg_frame, - cmd->sg_frame_phys_addr); - if (cmd->sense) - dma_pool_free(fusion->sense_dma_pool, cmd->sense, - cmd->sense_phys_addr); + if (fusion->sense) + dma_pool_free(fusion->sense_dma_pool, fusion->sense, + fusion->sense_phys_addr); + + /* SG */ + if (fusion->cmd_list) { + for (i = 0; i < instance->max_mpt_cmds; i++) { + cmd = fusion->cmd_list[i]; + if (cmd) { + if (cmd->sg_frame) + dma_pool_free(fusion->sg_dma_pool, + cmd->sg_frame, + cmd->sg_frame_phys_addr); + } + kfree(cmd); } + kfree(fusion->cmd_list); } if (fusion->sg_dma_pool) { @@ -347,13 +366,6 @@ megasas_free_cmds_fusion(struct megasas_instance *instance) dma_pool_destroy(fusion->io_request_frames_pool); fusion->io_request_frames_pool = NULL; } - - - /* cmd_list */ - for (i = 0; i < instance->max_mpt_cmds; i++) - kfree(fusion->cmd_list[i]); - - kfree(fusion->cmd_list); } /** @@ -367,10 +379,12 @@ static int megasas_create_sg_sense_fusion(struct megasas_instance *instance) u16 max_cmd; struct fusion_context *fusion; struct megasas_cmd_fusion *cmd; + int sense_sz; + u32 offset; fusion = instance->ctrl_context; max_cmd = instance->max_fw_cmds; - + sense_sz = instance->max_mpt_cmds * SCSI_SENSE_BUFFERSIZE; fusion->sg_dma_pool = dma_pool_create("mr_sg", &instance->pdev->dev, @@ -379,7 +393,7 @@ static int megasas_create_sg_sense_fusion(struct megasas_instance *instance) /* SCSI_SENSE_BUFFERSIZE = 96 bytes */ fusion->sense_dma_pool = dma_pool_create("mr_sense", &instance->pdev->dev, - SCSI_SENSE_BUFFERSIZE, 64, 0); + sense_sz, 64, 0); if (!fusion->sense_dma_pool || !fusion->sg_dma_pool) { dev_err(&instance->pdev->dev, @@ -387,6 +401,51 @@ static int megasas_create_sg_sense_fusion(struct megasas_instance *instance) return -ENOMEM; } + fusion->sense = dma_pool_alloc(fusion->sense_dma_pool, + GFP_KERNEL, &fusion->sense_phys_addr); + if (!fusion->sense) { + dev_err(&instance->pdev->dev, + "failed from %s %d\n", __func__, __LINE__); + return -ENOMEM; + } + + /* sense buffer, request frame and reply desc pool requires to be in + * same 4 gb region. Below function will check this. + * In case of failure, new pci pool will be created with updated + * alignment. + * Older allocation and pool will be destroyed. + * Alignment will be used such a way that next allocation if success, + * will always meet same 4gb region requirement. + * Actual requirement is not alignment, but we need start and end of + * DMA address must have same upper 32 bit address. + */ + + if (!megasas_check_same_4gb_region(instance, fusion->sense_phys_addr, + sense_sz)) { + dma_pool_free(fusion->sense_dma_pool, fusion->sense, + fusion->sense_phys_addr); + fusion->sense = NULL; + dma_pool_destroy(fusion->sense_dma_pool); + + fusion->sense_dma_pool = + dma_pool_create("mr_sense_align", &instance->pdev->dev, + sense_sz, roundup_pow_of_two(sense_sz), + 0); + if (!fusion->sense_dma_pool) { + dev_err(&instance->pdev->dev, + "Failed from %s %d\n", __func__, __LINE__); + return -ENOMEM; + } + fusion->sense = dma_pool_alloc(fusion->sense_dma_pool, + GFP_KERNEL, + &fusion->sense_phys_addr); + if (!fusion->sense) { + dev_err(&instance->pdev->dev, + "failed from %s %d\n", __func__, __LINE__); + return -ENOMEM; + } + } + /* * Allocate and attach a frame to each of the commands in cmd_list */ @@ -395,9 +454,11 @@ static int megasas_create_sg_sense_fusion(struct megasas_instance *instance) cmd->sg_frame = dma_pool_alloc(fusion->sg_dma_pool, GFP_KERNEL, &cmd->sg_frame_phys_addr); - cmd->sense = dma_pool_alloc(fusion->sense_dma_pool, - GFP_KERNEL, &cmd->sense_phys_addr); - if (!cmd->sg_frame || !cmd->sense) { + offset = SCSI_SENSE_BUFFERSIZE * i; + cmd->sense = (u8 *)fusion->sense + offset; + cmd->sense_phys_addr = fusion->sense_phys_addr + offset; + + if (!cmd->sg_frame) { dev_err(&instance->pdev->dev, "Failed from %s %d\n", __func__, __LINE__); return -ENOMEM; @@ -407,13 +468,10 @@ static int megasas_create_sg_sense_fusion(struct megasas_instance *instance) /* create sense buffer for the raid 1/10 fp */ for (i = max_cmd; i < instance->max_mpt_cmds; i++) { cmd = fusion->cmd_list[i]; - cmd->sense = dma_pool_alloc(fusion->sense_dma_pool, - GFP_KERNEL, &cmd->sense_phys_addr); - if (!cmd->sense) { - dev_err(&instance->pdev->dev, - "Failed from %s %d\n", __func__, __LINE__); - return -ENOMEM; - } + offset = SCSI_SENSE_BUFFERSIZE * i; + cmd->sense = (u8 *)fusion->sense + offset; + cmd->sense_phys_addr = fusion->sense_phys_addr + offset; + } return 0; @@ -465,16 +523,7 @@ megasas_alloc_request_fusion(struct megasas_instance *instance) 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); - if (!fusion->req_frames_desc) { - dev_err(&instance->pdev->dev, - "Failed from %s %d\n", __func__, __LINE__); - return -ENOMEM; - } - +retry_alloc: fusion->io_request_frames_pool = dma_pool_create("mr_ioreq", &instance->pdev->dev, fusion->io_frames_alloc_sz, 16, 0); @@ -489,10 +538,62 @@ megasas_alloc_request_fusion(struct megasas_instance *instance) dma_pool_alloc(fusion->io_request_frames_pool, GFP_KERNEL, &fusion->io_request_frames_phys); if (!fusion->io_request_frames) { + if (instance->max_fw_cmds >= (MEGASAS_REDUCE_QD_COUNT * 2)) { + instance->max_fw_cmds -= MEGASAS_REDUCE_QD_COUNT; + dma_pool_destroy(fusion->io_request_frames_pool); + megasas_configure_queue_sizes(instance); + goto retry_alloc; + } else { + dev_err(&instance->pdev->dev, + "Failed from %s %d\n", __func__, __LINE__); + return -ENOMEM; + } + } + + if (!megasas_check_same_4gb_region(instance, + fusion->io_request_frames_phys, + fusion->io_frames_alloc_sz)) { + dma_pool_free(fusion->io_request_frames_pool, + fusion->io_request_frames, + fusion->io_request_frames_phys); + fusion->io_request_frames = NULL; + dma_pool_destroy(fusion->io_request_frames_pool); + + fusion->io_request_frames_pool = + dma_pool_create("mr_ioreq_align", + &instance->pdev->dev, + fusion->io_frames_alloc_sz, + roundup_pow_of_two(fusion->io_frames_alloc_sz), + 0); + + if (!fusion->io_request_frames_pool) { + dev_err(&instance->pdev->dev, + "Failed from %s %d\n", __func__, __LINE__); + return -ENOMEM; + } + + fusion->io_request_frames = + dma_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; + } + } + + fusion->req_frames_desc = + dma_alloc_coherent(&instance->pdev->dev, + fusion->request_alloc_sz, + &fusion->req_frames_desc_phys, GFP_KERNEL); + if (!fusion->req_frames_desc) { dev_err(&instance->pdev->dev, "Failed from %s %d\n", __func__, __LINE__); return -ENOMEM; } + return 0; } @@ -523,6 +624,41 @@ megasas_alloc_reply_fusion(struct megasas_instance *instance) "Failed from %s %d\n", __func__, __LINE__); return -ENOMEM; } + + if (!megasas_check_same_4gb_region(instance, + fusion->reply_frames_desc_phys[0], + (fusion->reply_alloc_sz * count))) { + dma_pool_free(fusion->reply_frames_desc_pool, + fusion->reply_frames_desc[0], + fusion->reply_frames_desc_phys[0]); + fusion->reply_frames_desc[0] = NULL; + dma_pool_destroy(fusion->reply_frames_desc_pool); + + fusion->reply_frames_desc_pool = + dma_pool_create("mr_reply_align", + &instance->pdev->dev, + fusion->reply_alloc_sz * count, + roundup_pow_of_two(fusion->reply_alloc_sz * count), + 0); + + if (!fusion->reply_frames_desc_pool) { + dev_err(&instance->pdev->dev, + "Failed from %s %d\n", __func__, __LINE__); + return -ENOMEM; + } + + fusion->reply_frames_desc[0] = + dma_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[0]; for (i = 0; i < fusion->reply_q_depth * count; i++, reply_desc++) reply_desc->Words = cpu_to_le64(ULLONG_MAX); @@ -541,52 +677,124 @@ megasas_alloc_reply_fusion(struct megasas_instance *instance) int megasas_alloc_rdpq_fusion(struct megasas_instance *instance) { - int i, j, count; + int i, j, k, msix_count; struct fusion_context *fusion; union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc; + union MPI2_REPLY_DESCRIPTORS_UNION *rdpq_chunk_virt[RDPQ_MAX_CHUNK_COUNT]; + dma_addr_t rdpq_chunk_phys[RDPQ_MAX_CHUNK_COUNT]; + u8 dma_alloc_count, abs_index; + u32 chunk_size, array_size, offset; fusion = instance->ctrl_context; + chunk_size = fusion->reply_alloc_sz * RDPQ_MAX_INDEX_IN_ONE_CHUNK; + array_size = sizeof(struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY) * + MAX_MSIX_QUEUES_FUSION; - fusion->rdpq_virt = pci_alloc_consistent(instance->pdev, - sizeof(struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY) * MAX_MSIX_QUEUES_FUSION, - &fusion->rdpq_phys); + fusion->rdpq_virt = pci_alloc_consistent(instance->pdev, array_size, + &fusion->rdpq_phys); if (!fusion->rdpq_virt) { dev_err(&instance->pdev->dev, "Failed from %s %d\n", __func__, __LINE__); return -ENOMEM; } - 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; + memset(fusion->rdpq_virt, 0, array_size); + msix_count = instance->msix_vectors > 0 ? instance->msix_vectors : 1; + fusion->reply_frames_desc_pool = dma_pool_create("mr_rdpq", &instance->pdev->dev, - fusion->reply_alloc_sz, - 16, 0); - - if (!fusion->reply_frames_desc_pool) { + chunk_size, 16, 0); + fusion->reply_frames_desc_pool_align = + dma_pool_create("mr_rdpq_align", + &instance->pdev->dev, + chunk_size, + roundup_pow_of_two(chunk_size), + 0); + + if (!fusion->reply_frames_desc_pool || + !fusion->reply_frames_desc_pool_align) { dev_err(&instance->pdev->dev, "Failed from %s %d\n", __func__, __LINE__); return -ENOMEM; } - for (i = 0; i < count; i++) { - fusion->reply_frames_desc[i] = - dma_pool_alloc(fusion->reply_frames_desc_pool, - GFP_KERNEL, &fusion->reply_frames_desc_phys[i]); - if (!fusion->reply_frames_desc[i]) { +/* + * For INVADER_SERIES each set of 8 reply queues(0-7, 8-15, ..) and + * VENTURA_SERIES each set of 16 reply queues(0-15, 16-31, ..) should be + * within 4GB boundary and also reply queues in a set must have same + * upper 32-bits in their memory address. so here driver is allocating the + * DMA'able memory for reply queues according. Driver uses limitation of + * VENTURA_SERIES to manage INVADER_SERIES as well. + */ + dma_alloc_count = DIV_ROUND_UP(msix_count, RDPQ_MAX_INDEX_IN_ONE_CHUNK); + + for (i = 0; i < dma_alloc_count; i++) { + rdpq_chunk_virt[i] = + dma_pool_alloc(fusion->reply_frames_desc_pool, + GFP_KERNEL, &rdpq_chunk_phys[i]); + if (!rdpq_chunk_virt[i]) { dev_err(&instance->pdev->dev, "Failed from %s %d\n", __func__, __LINE__); return -ENOMEM; } + /* reply desc pool requires to be in same 4 gb region. + * Below function will check this. + * In case of failure, new pci pool will be created with updated + * alignment. + * For RDPQ buffers, driver always allocate two separate pci pool. + * Alignment will be used such a way that next allocation if + * success, will always meet same 4gb region requirement. + * rdpq_tracker keep track of each buffer's physical, + * virtual address and pci pool descriptor. It will help driver + * while freeing the resources. + * + */ + if (!megasas_check_same_4gb_region(instance, rdpq_chunk_phys[i], + chunk_size)) { + dma_pool_free(fusion->reply_frames_desc_pool, + rdpq_chunk_virt[i], + rdpq_chunk_phys[i]); - fusion->rdpq_virt[i].RDPQBaseAddress = - cpu_to_le64(fusion->reply_frames_desc_phys[i]); + rdpq_chunk_virt[i] = + dma_pool_alloc(fusion->reply_frames_desc_pool_align, + GFP_KERNEL, &rdpq_chunk_phys[i]); + if (!rdpq_chunk_virt[i]) { + dev_err(&instance->pdev->dev, + "Failed from %s %d\n", + __func__, __LINE__); + return -ENOMEM; + } + fusion->rdpq_tracker[i].dma_pool_ptr = + fusion->reply_frames_desc_pool_align; + } else { + fusion->rdpq_tracker[i].dma_pool_ptr = + fusion->reply_frames_desc_pool; + } - 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); + fusion->rdpq_tracker[i].pool_entry_phys = rdpq_chunk_phys[i]; + fusion->rdpq_tracker[i].pool_entry_virt = rdpq_chunk_virt[i]; } + + for (k = 0; k < dma_alloc_count; k++) { + for (i = 0; i < RDPQ_MAX_INDEX_IN_ONE_CHUNK; i++) { + abs_index = (k * RDPQ_MAX_INDEX_IN_ONE_CHUNK) + i; + + if (abs_index == msix_count) + break; + offset = fusion->reply_alloc_sz * i; + fusion->rdpq_virt[abs_index].RDPQBaseAddress = + cpu_to_le64(rdpq_chunk_phys[k] + offset); + fusion->reply_frames_desc_phys[abs_index] = + rdpq_chunk_phys[k] + offset; + fusion->reply_frames_desc[abs_index] = + (union MPI2_REPLY_DESCRIPTORS_UNION *)((u8 *)rdpq_chunk_virt[k] + offset); + + reply_desc = fusion->reply_frames_desc[abs_index]; + for (j = 0; j < fusion->reply_q_depth; j++, reply_desc++) + reply_desc->Words = ULLONG_MAX; + } + } + return 0; } @@ -598,15 +806,18 @@ megasas_free_rdpq_fusion(struct megasas_instance *instance) { fusion = instance->ctrl_context; - for (i = 0; i < MAX_MSIX_QUEUES_FUSION; i++) { - if (fusion->reply_frames_desc[i]) - dma_pool_free(fusion->reply_frames_desc_pool, - fusion->reply_frames_desc[i], - fusion->reply_frames_desc_phys[i]); + for (i = 0; i < RDPQ_MAX_CHUNK_COUNT; i++) { + if (fusion->rdpq_tracker[i].pool_entry_virt) + dma_pool_free(fusion->rdpq_tracker[i].dma_pool_ptr, + fusion->rdpq_tracker[i].pool_entry_virt, + fusion->rdpq_tracker[i].pool_entry_phys); + } if (fusion->reply_frames_desc_pool) dma_pool_destroy(fusion->reply_frames_desc_pool); + if (fusion->reply_frames_desc_pool_align) + dma_pool_destroy(fusion->reply_frames_desc_pool_align); if (fusion->rdpq_virt) pci_free_consistent(instance->pdev, @@ -661,9 +872,6 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance) fusion = instance->ctrl_context; - if (megasas_alloc_cmdlist_fusion(instance)) - goto fail_exit; - if (megasas_alloc_request_fusion(instance)) goto fail_exit; @@ -674,6 +882,11 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance) if (megasas_alloc_reply_fusion(instance)) goto fail_exit; + if (megasas_alloc_cmdlist_fusion(instance)) + goto fail_exit; + + dev_info(&instance->pdev->dev, "Configured max firmware commands: %d\n", + instance->max_fw_cmds); /* 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; @@ -770,22 +983,34 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) MFI_CAPABILITIES *drv_ops; u32 scratch_pad_2; unsigned long flags; + struct timeval tv; + bool cur_fw_64bit_dma_capable; fusion = instance->ctrl_context; - cmd = megasas_get_cmd(instance); + ioc_init_handle = fusion->ioc_init_request_phys; + IOCInitMessage = fusion->ioc_init_request; - if (!cmd) { - dev_err(&instance->pdev->dev, "Could not allocate cmd for INIT Frame\n"); - ret = 1; - goto fail_get_cmd; - } + cmd = fusion->ioc_init_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->adapter_type == INVADER_SERIES) { + cur_fw_64bit_dma_capable = + (scratch_pad_2 & MR_CAN_HANDLE_64_BIT_DMA_OFFSET) ? true : false; + + if (instance->consistent_mask_64bit && !cur_fw_64bit_dma_capable) { + dev_err(&instance->pdev->dev, "Driver was operating on 64bit " + "DMA mask, but upcoming FW does not support 64bit DMA mask\n"); + megaraid_sas_kill_hba(instance); + ret = 1; + goto fail_fw_init; + } + } + if (instance->is_rdpq && !cur_rdpq_mode) { dev_err(&instance->pdev->dev, "Firmware downgrade *NOT SUPPORTED*" " from RDPQ mode to non RDPQ mode\n"); @@ -798,18 +1023,6 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) dev_info(&instance->pdev->dev, "FW supports sync cache\t: %s\n", instance->fw_sync_cache_support ? "Yes" : "No"); - IOCInitMessage = - dma_alloc_coherent(&instance->pdev->dev, - sizeof(struct MPI2_IOC_INIT_REQUEST), - &ioc_init_handle, GFP_KERNEL); - - if (!IOCInitMessage) { - dev_err(&instance->pdev->dev, "Could not allocate memory for " - "IOCInitMessage\n"); - ret = 1; - goto fail_fw_init; - } - memset(IOCInitMessage, 0, sizeof(struct MPI2_IOC_INIT_REQUEST)); IOCInitMessage->Function = MPI2_FUNCTION_IOC_INIT; @@ -825,8 +1038,15 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) IOCInitMessage->MsgFlags = instance->is_rdpq ? MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE : 0; IOCInitMessage->SystemRequestFrameBaseAddress = cpu_to_le64(fusion->io_request_frames_phys); + IOCInitMessage->SenseBufferAddressHigh = cpu_to_le32(upper_32_bits(fusion->sense_phys_addr)); IOCInitMessage->HostMSIxVectors = instance->msix_vectors; IOCInitMessage->HostPageSize = MR_DEFAULT_NVME_PAGE_SHIFT; + + do_gettimeofday(&tv); + /* Convert to milliseconds as per FW requirement */ + IOCInitMessage->TimeStamp = cpu_to_le64((tv.tv_sec * 1000) + + (tv.tv_usec / 1000)); + init_frame = (struct megasas_init_frame *)cmd->frame; memset(init_frame, 0, MEGAMFI_FRAME_SIZE); @@ -842,7 +1062,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) drv_ops = (MFI_CAPABILITIES *) &(init_frame->driver_operations); /* driver support Extended MSIX */ - if (fusion->adapter_type >= INVADER_SERIES) + if (instance->adapter_type >= INVADER_SERIES) drv_ops->mfi_capabilities.support_additional_msix = 1; /* driver supports HA / Remote LUN over Fast Path interface */ drv_ops->mfi_capabilities.support_fp_remote_lun = 1; @@ -860,6 +1080,10 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) drv_ops->mfi_capabilities.support_qd_throttling = 1; drv_ops->mfi_capabilities.support_pd_map_target_id = 1; + + if (instance->consistent_mask_64bit) + drv_ops->mfi_capabilities.support_64bit_mode = 1; + /* Convert capability to LE32 */ cpu_to_le32s((u32 *)&init_frame->driver_operations.mfi_capabilities); @@ -869,8 +1093,8 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) strlen(sys_info) > 64 ? 64 : strlen(sys_info)); instance->system_info_buf->systemIdLength = strlen(sys_info) > 64 ? 64 : strlen(sys_info); - init_frame->system_info_lo = instance->system_info_h; - init_frame->system_info_hi = 0; + init_frame->system_info_lo = cpu_to_le32(lower_32_bits(instance->system_info_h)); + init_frame->system_info_hi = cpu_to_le32(upper_32_bits(instance->system_info_h)); } init_frame->queue_info_new_phys_addr_hi = @@ -917,12 +1141,6 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) ret = 0; fail_fw_init: - megasas_return_cmd(instance, cmd); - if (IOCInitMessage) - dma_free_coherent(&instance->pdev->dev, - sizeof(struct MPI2_IOC_INIT_REQUEST), - IOCInitMessage, ioc_init_handle); -fail_get_cmd: dev_err(&instance->pdev->dev, "Init cmd return status %s for SCSI host %d\n", ret ? "FAILED" : "SUCCESS", instance->host->host_no); @@ -967,6 +1185,15 @@ megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend) { memset(pd_sync, 0, pd_seq_map_sz); memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + if (pend) { + dcmd->mbox.b[0] = MEGASAS_DCMD_MBOX_PEND_FLAG; + dcmd->flags = MFI_FRAME_DIR_WRITE; + instance->jbod_seq_cmd = cmd; + } else { + dcmd->flags = MFI_FRAME_DIR_READ; + } + dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd_status = 0xFF; dcmd->sge_count = 1; @@ -974,21 +1201,16 @@ megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend) { dcmd->pad_0 = 0; dcmd->data_xfer_len = cpu_to_le32(pd_seq_map_sz); dcmd->opcode = cpu_to_le32(MR_DCMD_SYSTEM_PD_MAP_GET_INFO); - dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(pd_seq_h); - dcmd->sgl.sge32[0].length = cpu_to_le32(pd_seq_map_sz); + + megasas_set_dma_settings(instance, dcmd, pd_seq_h, pd_seq_map_sz); if (pend) { - dcmd->mbox.b[0] = MEGASAS_DCMD_MBOX_PEND_FLAG; - dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_WRITE); - instance->jbod_seq_cmd = cmd; instance->instancet->issue_dcmd(instance, cmd); return 0; } - dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ); - /* Below code is only for non pended DCMD */ - if (instance->ctrl_context && !instance->mask_interrupts) + if (!instance->mask_interrupts) ret = megasas_issue_blocked_cmd(instance, cmd, MFI_IO_TIMEOUT_SECS); else @@ -1001,7 +1223,7 @@ megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend) { ret = -EINVAL; } - if (ret == DCMD_TIMEOUT && instance->ctrl_context) + if (ret == DCMD_TIMEOUT) megaraid_sas_kill_hba(instance); if (ret == DCMD_SUCCESS) @@ -1069,21 +1291,21 @@ megasas_get_ld_map_info(struct megasas_instance *instance) dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd_status = 0xFF; dcmd->sge_count = 1; - dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ); + dcmd->flags = MFI_FRAME_DIR_READ; dcmd->timeout = 0; dcmd->pad_0 = 0; dcmd->data_xfer_len = cpu_to_le32(size_map_info); dcmd->opcode = cpu_to_le32(MR_DCMD_LD_MAP_GET_INFO); - dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(ci_h); - dcmd->sgl.sge32[0].length = cpu_to_le32(size_map_info); - if (instance->ctrl_context && !instance->mask_interrupts) + megasas_set_dma_settings(instance, dcmd, ci_h, size_map_info); + + if (!instance->mask_interrupts) ret = megasas_issue_blocked_cmd(instance, cmd, MFI_IO_TIMEOUT_SECS); else ret = megasas_issue_polled(instance, cmd); - if (ret == DCMD_TIMEOUT && instance->ctrl_context) + if (ret == DCMD_TIMEOUT) megaraid_sas_kill_hba(instance); megasas_return_cmd(instance, cmd); @@ -1173,15 +1395,15 @@ megasas_sync_map_info(struct megasas_instance *instance) dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd_status = 0xFF; dcmd->sge_count = 1; - dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_WRITE); + dcmd->flags = MFI_FRAME_DIR_WRITE; dcmd->timeout = 0; dcmd->pad_0 = 0; dcmd->data_xfer_len = cpu_to_le32(size_map_info); dcmd->mbox.b[0] = num_lds; dcmd->mbox.b[1] = MEGASAS_DCMD_MBOX_PEND_FLAG; dcmd->opcode = cpu_to_le32(MR_DCMD_LD_MAP_GET_INFO); - dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(ci_h); - dcmd->sgl.sge32[0].length = cpu_to_le32(size_map_info); + + megasas_set_dma_settings(instance, dcmd, ci_h, size_map_info); instance->map_update_cmd = cmd; @@ -1337,6 +1559,94 @@ ld_drv_map_alloc_fail: } /** + * megasas_configure_queue_sizes - Calculate size of request desc queue, + * reply desc queue, + * IO request frame queue, set can_queue. + * @instance: Adapter soft state + * @return: void + */ +static inline +void megasas_configure_queue_sizes(struct megasas_instance *instance) +{ + struct fusion_context *fusion; + u16 max_cmd; + + fusion = instance->ctrl_context; + max_cmd = instance->max_fw_cmds; + + if (instance->adapter_type == VENTURA_SERIES) + instance->max_mpt_cmds = instance->max_fw_cmds * RAID_1_PEER_CMDS; + else + instance->max_mpt_cmds = instance->max_fw_cmds; + + instance->max_scsi_cmds = instance->max_fw_cmds - + (MEGASAS_FUSION_INTERNAL_CMDS + + MEGASAS_FUSION_IOCTL_CMDS); + instance->cur_can_queue = instance->max_scsi_cmds; + instance->host->can_queue = instance->cur_can_queue; + + fusion->reply_q_depth = 2 * ((max_cmd + 1 + 15) / 16) * 16; + + fusion->request_alloc_sz = sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) * + instance->max_mpt_cmds; + fusion->reply_alloc_sz = sizeof(union MPI2_REPLY_DESCRIPTORS_UNION) * + (fusion->reply_q_depth); + fusion->io_frames_alloc_sz = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE + + (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE + * (instance->max_mpt_cmds + 1)); /* Extra 1 for SMID 0 */ +} + +static int megasas_alloc_ioc_init_frame(struct megasas_instance *instance) +{ + struct fusion_context *fusion; + struct megasas_cmd *cmd; + + fusion = instance->ctrl_context; + + cmd = kmalloc(sizeof(struct megasas_cmd), GFP_KERNEL); + + if (!cmd) { + dev_err(&instance->pdev->dev, "Failed from func: %s line: %d\n", + __func__, __LINE__); + return -ENOMEM; + } + + cmd->frame = dma_alloc_coherent(&instance->pdev->dev, + IOC_INIT_FRAME_SIZE, + &cmd->frame_phys_addr, GFP_KERNEL); + + if (!cmd->frame) { + dev_err(&instance->pdev->dev, "Failed from func: %s line: %d\n", + __func__, __LINE__); + kfree(cmd); + return -ENOMEM; + } + + fusion->ioc_init_cmd = cmd; + return 0; +} + +/** + * megasas_free_ioc_init_cmd - Free IOC INIT command frame + * @instance: Adapter soft state + */ +static inline void megasas_free_ioc_init_cmd(struct megasas_instance *instance) +{ + struct fusion_context *fusion; + + fusion = instance->ctrl_context; + + if (fusion->ioc_init_cmd && fusion->ioc_init_cmd->frame) + dma_free_coherent(&instance->pdev->dev, + IOC_INIT_FRAME_SIZE, + fusion->ioc_init_cmd->frame, + fusion->ioc_init_cmd->frame_phys_addr); + + if (fusion->ioc_init_cmd) + kfree(fusion->ioc_init_cmd); +} + +/** * megasas_init_adapter_fusion - Initializes the FW * @instance: Adapter soft state * @@ -1347,7 +1657,6 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) { struct megasas_register_set __iomem *reg_set; struct fusion_context *fusion; - u16 max_cmd; u32 scratch_pad_2; int i = 0, count; @@ -1363,17 +1672,7 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) instance->max_mfi_cmds = MEGASAS_FUSION_INTERNAL_CMDS + MEGASAS_FUSION_IOCTL_CMDS; - max_cmd = instance->max_fw_cmds; - - fusion->reply_q_depth = 2 * (((max_cmd + 1 + 15)/16)*16); - - fusion->request_alloc_sz = - sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) * instance->max_mpt_cmds; - fusion->reply_alloc_sz = sizeof(union MPI2_REPLY_DESCRIPTORS_UNION) - *(fusion->reply_q_depth); - fusion->io_frames_alloc_sz = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE + - (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE - * (instance->max_mpt_cmds + 1)); /* Extra 1 for SMID 0 */ + megasas_configure_queue_sizes(instance); scratch_pad_2 = readl(&instance->reg_set->outbound_scratch_pad_2); /* If scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK is set, @@ -1431,6 +1730,9 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) MEGASAS_FUSION_IOCTL_CMDS); sema_init(&instance->ioctl_sem, MEGASAS_FUSION_IOCTL_CMDS); + if (megasas_alloc_ioc_init_frame(instance)) + return 1; + /* * Allocate memory for descriptors * Create a pool of commands @@ -1468,6 +1770,7 @@ fail_ioc_init: fail_alloc_cmds: megasas_free_cmds(instance); fail_alloc_mfi_cmds: + megasas_free_ioc_init_cmd(instance); return 1; } @@ -1800,7 +2103,7 @@ megasas_make_sgl_fusion(struct megasas_instance *instance, fusion = instance->ctrl_context; - if (fusion->adapter_type >= INVADER_SERIES) { + if (instance->adapter_type >= INVADER_SERIES) { struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end = sgl_ptr; sgl_ptr_end += fusion->max_sge_in_main_msg - 1; sgl_ptr_end->Flags = 0; @@ -1810,7 +2113,7 @@ megasas_make_sgl_fusion(struct megasas_instance *instance, sgl_ptr->Length = cpu_to_le32(sg_dma_len(os_sgl)); sgl_ptr->Address = cpu_to_le64(sg_dma_address(os_sgl)); sgl_ptr->Flags = 0; - if (fusion->adapter_type >= INVADER_SERIES) + if (instance->adapter_type >= INVADER_SERIES) if (i == sge_count - 1) sgl_ptr->Flags = IEEE_SGE_FLAGS_END_OF_LIST; sgl_ptr++; @@ -1820,7 +2123,7 @@ megasas_make_sgl_fusion(struct megasas_instance *instance, (sge_count > fusion->max_sge_in_main_msg)) { struct MPI25_IEEE_SGE_CHAIN64 *sg_chain; - if (fusion->adapter_type >= INVADER_SERIES) { + if (instance->adapter_type >= INVADER_SERIES) { if ((le16_to_cpu(cmd->io_request->IoFlags) & MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) != MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) @@ -1836,7 +2139,7 @@ megasas_make_sgl_fusion(struct megasas_instance *instance, sg_chain = sgl_ptr; /* Prepare chain element */ sg_chain->NextChainOffset = 0; - if (fusion->adapter_type >= INVADER_SERIES) + if (instance->adapter_type >= INVADER_SERIES) sg_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT; else sg_chain->Flags = @@ -2360,7 +2663,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, praid_context = &io_request->RaidContext; - if (instance->is_ventura) { + if (instance->adapter_type == VENTURA_SERIES) { spin_lock_irqsave(&instance->stream_lock, spinlock_flags); megasas_stream_detect(instance, cmd, &io_info); spin_unlock_irqrestore(&instance->stream_lock, spinlock_flags); @@ -2413,7 +2716,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, cmd->request_desc->SCSIIO.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_FP_IO << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); - if (fusion->adapter_type == INVADER_SERIES) { + if (instance->adapter_type == INVADER_SERIES) { if (io_request->RaidContext.raid_context.reg_lock_flags == REGION_TYPE_UNUSED) cmd->request_desc->SCSIIO.RequestFlags = @@ -2426,7 +2729,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, io_request->RaidContext.raid_context.reg_lock_flags |= (MR_RL_FLAGS_GRANT_DESTINATION_CUDA | MR_RL_FLAGS_SEQ_NUM_ENABLE); - } else if (instance->is_ventura) { + } else if (instance->adapter_type == VENTURA_SERIES) { io_request->RaidContext.raid_context_g35.nseg_type |= (1 << RAID_CONTEXT_NSEG_SHIFT); io_request->RaidContext.raid_context_g35.nseg_type |= @@ -2445,7 +2748,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, &io_info, local_map_ptr); scp->SCp.Status |= MEGASAS_LOAD_BALANCE_FLAG; cmd->pd_r1_lb = io_info.pd_after_lb; - if (instance->is_ventura) + if (instance->adapter_type == VENTURA_SERIES) io_request->RaidContext.raid_context_g35.span_arm = io_info.span_arm; else @@ -2455,7 +2758,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, } else scp->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG; - if (instance->is_ventura) + if (instance->adapter_type == VENTURA_SERIES) cmd->r1_alt_dev_handle = io_info.r1_alt_dev_handle; else cmd->r1_alt_dev_handle = MR_DEVHANDLE_INVALID; @@ -2478,7 +2781,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, cmd->request_desc->SCSIIO.RequestFlags = (MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); - if (fusion->adapter_type == INVADER_SERIES) { + if (instance->adapter_type == INVADER_SERIES) { if (io_info.do_fp_rlbypass || (io_request->RaidContext.raid_context.reg_lock_flags == REGION_TYPE_UNUSED)) @@ -2491,7 +2794,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, (MR_RL_FLAGS_GRANT_DESTINATION_CPU0 | MR_RL_FLAGS_SEQ_NUM_ENABLE); io_request->RaidContext.raid_context.nseg = 0x1; - } else if (instance->is_ventura) { + } else if (instance->adapter_type == VENTURA_SERIES) { io_request->RaidContext.raid_context_g35.routing_flags |= (1 << MR_RAID_CTX_ROUTINGFLAGS_SQN_SHIFT); io_request->RaidContext.raid_context_g35.nseg_type |= @@ -2566,7 +2869,7 @@ static void megasas_build_ld_nonrw_fusion(struct megasas_instance *instance, /* set RAID context values */ pRAID_Context->config_seq_num = raid->seqNum; - if (!instance->is_ventura) + if (instance->adapter_type != VENTURA_SERIES) pRAID_Context->reg_lock_flags = REGION_TYPE_SHARED_READ; pRAID_Context->timeout_value = cpu_to_le16(raid->fpIoTimeoutForLd); @@ -2651,7 +2954,7 @@ megasas_build_syspd_fusion(struct megasas_instance *instance, cpu_to_le16(device_id + (MAX_PHYSICAL_DEVICES - 1)); pRAID_Context->config_seq_num = pd_sync->seq[pd_index].seqNum; io_request->DevHandle = pd_sync->seq[pd_index].devHandle; - if (instance->is_ventura) { + if (instance->adapter_type == VENTURA_SERIES) { io_request->RaidContext.raid_context_g35.routing_flags |= (1 << MR_RAID_CTX_ROUTINGFLAGS_SQN_SHIFT); io_request->RaidContext.raid_context_g35.nseg_type |= @@ -2699,7 +3002,7 @@ megasas_build_syspd_fusion(struct megasas_instance *instance, pRAID_Context->timeout_value = cpu_to_le16((os_timeout_value > timeout_limit) ? timeout_limit : os_timeout_value); - if (fusion->adapter_type >= INVADER_SERIES) + if (instance->adapter_type >= INVADER_SERIES) io_request->IoFlags |= cpu_to_le16(MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH); @@ -2782,7 +3085,7 @@ megasas_build_io_fusion(struct megasas_instance *instance, return 1; } - if (instance->is_ventura) { + if (instance->adapter_type == VENTURA_SERIES) { set_num_sge(&io_request->RaidContext.raid_context_g35, sge_count); cpu_to_le16s(&io_request->RaidContext.raid_context_g35.routing_flags); cpu_to_le16s(&io_request->RaidContext.raid_context_g35.nseg_type); @@ -2805,7 +3108,8 @@ megasas_build_io_fusion(struct megasas_instance *instance, io_request->SGLOffset0 = offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL) / 4; - io_request->SenseBufferLowAddress = cpu_to_le32(cmd->sense_phys_addr); + io_request->SenseBufferLowAddress = + cpu_to_le32(lower_32_bits(cmd->sense_phys_addr)); io_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE; cmd->scmd = scp; @@ -2846,7 +3150,7 @@ void megasas_prepare_secondRaid1_IO(struct megasas_instance *instance, (fusion->max_sge_in_main_msg * sizeof(union MPI2_SGE_IO_UNION))); /*sense buffer is different for r1 command*/ r1_cmd->io_request->SenseBufferLowAddress = - cpu_to_le32(r1_cmd->sense_phys_addr); + cpu_to_le32(lower_32_bits(r1_cmd->sense_phys_addr)); r1_cmd->scmd = cmd->scmd; req_desc2 = megasas_get_request_descriptor(instance, (r1_cmd->index - 1)); @@ -3312,7 +3616,7 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance, io_req = cmd->io_request; - if (fusion->adapter_type >= INVADER_SERIES) { + if (instance->adapter_type >= INVADER_SERIES) { struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end = (struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL; sgl_ptr_end += fusion->max_sge_in_main_msg - 1; @@ -3386,6 +3690,7 @@ megasas_issue_dcmd_fusion(struct megasas_instance *instance, void megasas_release_fusion(struct megasas_instance *instance) { + megasas_free_ioc_init_cmd(instance); megasas_free_cmds(instance); megasas_free_cmds_fusion(instance); @@ -4244,7 +4549,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason) for (i = 0 ; i < instance->max_scsi_cmds; i++) { cmd_fusion = fusion->cmd_list[i]; /*check for extra commands issued by driver*/ - if (instance->is_ventura) { + if (instance->adapter_type == VENTURA_SERIES) { r1_cmd = fusion->cmd_list[i + instance->max_fw_cmds]; megasas_return_cmd_fusion(instance, r1_cmd); } @@ -4345,7 +4650,7 @@ transition_to_ready: megasas_set_dynamic_target_properties(sdev); /* reset stream detection array */ - if (instance->is_ventura) { + if (instance->adapter_type == VENTURA_SERIES) { for (j = 0; j < MAX_LOGICAL_DRIVES_EXT; ++j) { memset(fusion->stream_detect_by_ld[j], 0, sizeof(struct LD_STREAM_DETECT)); @@ -4493,20 +4798,31 @@ megasas_alloc_fusion_context(struct megasas_instance *instance) { struct fusion_context *fusion; - instance->ctrl_context_pages = get_order(sizeof(struct fusion_context)); - instance->ctrl_context = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, - instance->ctrl_context_pages); + instance->ctrl_context = kzalloc(sizeof(struct fusion_context), + GFP_KERNEL); if (!instance->ctrl_context) { - /* fall back to using vmalloc for fusion_context */ - instance->ctrl_context = vzalloc(sizeof(struct fusion_context)); - if (!instance->ctrl_context) { - dev_err(&instance->pdev->dev, "Failed from %s %d\n", __func__, __LINE__); - return -ENOMEM; - } + dev_err(&instance->pdev->dev, "Failed from %s %d\n", + __func__, __LINE__); + return -ENOMEM; } fusion = instance->ctrl_context; + fusion->log_to_span_pages = get_order(MAX_LOGICAL_DRIVES_EXT * + sizeof(LD_SPAN_INFO)); + fusion->log_to_span = + (PLD_SPAN_INFO)__get_free_pages(GFP_KERNEL | __GFP_ZERO, + fusion->log_to_span_pages); + if (!fusion->log_to_span) { + fusion->log_to_span = vzalloc(MAX_LOGICAL_DRIVES_EXT * + sizeof(LD_SPAN_INFO)); + if (!fusion->log_to_span) { + dev_err(&instance->pdev->dev, "Failed from %s %d\n", + __func__, __LINE__); + return -ENOMEM; + } + } + fusion->load_balance_info_pages = get_order(MAX_LOGICAL_DRIVES_EXT * sizeof(struct LD_LOAD_BALANCE_INFO)); fusion->load_balance_info = @@ -4537,11 +4853,15 @@ megasas_free_fusion_context(struct megasas_instance *instance) fusion->load_balance_info_pages); } - if (is_vmalloc_addr(fusion)) - vfree(fusion); - else - free_pages((ulong)fusion, - instance->ctrl_context_pages); + if (fusion->log_to_span) { + if (is_vmalloc_addr(fusion->log_to_span)) + vfree(fusion->log_to_span); + else + free_pages((ulong)fusion->log_to_span, + fusion->log_to_span_pages); + } + + kfree(fusion); } } |