summaryrefslogtreecommitdiff
path: root/drivers/scsi/megaraid/megaraid_sas_fusion.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/megaraid/megaraid_sas_fusion.c')
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c216
1 files changed, 132 insertions, 84 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index 985510628f56..11bd2e698b84 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -313,20 +313,20 @@ megasas_free_cmds_fusion(struct megasas_instance *instance)
cmd = fusion->cmd_list[i];
if (cmd) {
if (cmd->sg_frame)
- pci_pool_free(fusion->sg_dma_pool, cmd->sg_frame,
+ dma_pool_free(fusion->sg_dma_pool, cmd->sg_frame,
cmd->sg_frame_phys_addr);
if (cmd->sense)
- pci_pool_free(fusion->sense_dma_pool, cmd->sense,
+ dma_pool_free(fusion->sense_dma_pool, cmd->sense,
cmd->sense_phys_addr);
}
}
if (fusion->sg_dma_pool) {
- pci_pool_destroy(fusion->sg_dma_pool);
+ dma_pool_destroy(fusion->sg_dma_pool);
fusion->sg_dma_pool = NULL;
}
if (fusion->sense_dma_pool) {
- pci_pool_destroy(fusion->sense_dma_pool);
+ dma_pool_destroy(fusion->sense_dma_pool);
fusion->sense_dma_pool = NULL;
}
@@ -343,11 +343,11 @@ megasas_free_cmds_fusion(struct megasas_instance *instance)
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,
+ dma_pool_free(fusion->io_request_frames_pool,
fusion->io_request_frames,
fusion->io_request_frames_phys);
if (fusion->io_request_frames_pool) {
- pci_pool_destroy(fusion->io_request_frames_pool);
+ dma_pool_destroy(fusion->io_request_frames_pool);
fusion->io_request_frames_pool = NULL;
}
@@ -376,12 +376,12 @@ static int megasas_create_sg_sense_fusion(struct megasas_instance *instance)
fusion->sg_dma_pool =
- pci_pool_create("mr_sg", instance->pdev,
+ dma_pool_create("mr_sg", &instance->pdev->dev,
instance->max_chain_frame_sz,
MR_DEFAULT_NVME_PAGE_SIZE, 0);
/* SCSI_SENSE_BUFFERSIZE = 96 bytes */
fusion->sense_dma_pool =
- pci_pool_create("mr_sense", instance->pdev,
+ dma_pool_create("mr_sense", &instance->pdev->dev,
SCSI_SENSE_BUFFERSIZE, 64, 0);
if (!fusion->sense_dma_pool || !fusion->sg_dma_pool) {
@@ -395,10 +395,10 @@ static int megasas_create_sg_sense_fusion(struct megasas_instance *instance)
*/
for (i = 0; i < max_cmd; i++) {
cmd = fusion->cmd_list[i];
- cmd->sg_frame = pci_pool_alloc(fusion->sg_dma_pool,
+ cmd->sg_frame = dma_pool_alloc(fusion->sg_dma_pool,
GFP_KERNEL, &cmd->sg_frame_phys_addr);
- cmd->sense = pci_pool_alloc(fusion->sense_dma_pool,
+ cmd->sense = dma_pool_alloc(fusion->sense_dma_pool,
GFP_KERNEL, &cmd->sense_phys_addr);
if (!cmd->sg_frame || !cmd->sense) {
dev_err(&instance->pdev->dev,
@@ -410,7 +410,7 @@ 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 = pci_pool_alloc(fusion->sense_dma_pool,
+ cmd->sense = dma_pool_alloc(fusion->sense_dma_pool,
GFP_KERNEL, &cmd->sense_phys_addr);
if (!cmd->sense) {
dev_err(&instance->pdev->dev,
@@ -479,7 +479,7 @@ megasas_alloc_request_fusion(struct megasas_instance *instance)
}
fusion->io_request_frames_pool =
- pci_pool_create("mr_ioreq", instance->pdev,
+ dma_pool_create("mr_ioreq", &instance->pdev->dev,
fusion->io_frames_alloc_sz, 16, 0);
if (!fusion->io_request_frames_pool) {
@@ -489,7 +489,7 @@ megasas_alloc_request_fusion(struct megasas_instance *instance)
}
fusion->io_request_frames =
- pci_pool_alloc(fusion->io_request_frames_pool,
+ 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,
@@ -509,7 +509,7 @@ megasas_alloc_reply_fusion(struct megasas_instance *instance)
count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
fusion->reply_frames_desc_pool =
- pci_pool_create("mr_reply", instance->pdev,
+ dma_pool_create("mr_reply", &instance->pdev->dev,
fusion->reply_alloc_sz * count, 16, 0);
if (!fusion->reply_frames_desc_pool) {
@@ -519,7 +519,7 @@ megasas_alloc_reply_fusion(struct megasas_instance *instance)
}
fusion->reply_frames_desc[0] =
- pci_pool_alloc(fusion->reply_frames_desc_pool,
+ 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,
@@ -562,8 +562,10 @@ megasas_alloc_rdpq_fusion(struct megasas_instance *instance)
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);
+ 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) {
dev_err(&instance->pdev->dev,
@@ -573,7 +575,7 @@ megasas_alloc_rdpq_fusion(struct megasas_instance *instance)
for (i = 0; i < count; i++) {
fusion->reply_frames_desc[i] =
- pci_pool_alloc(fusion->reply_frames_desc_pool,
+ dma_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,
@@ -601,13 +603,13 @@ megasas_free_rdpq_fusion(struct megasas_instance *instance) {
for (i = 0; i < MAX_MSIX_QUEUES_FUSION; i++) {
if (fusion->reply_frames_desc[i])
- pci_pool_free(fusion->reply_frames_desc_pool,
+ dma_pool_free(fusion->reply_frames_desc_pool,
fusion->reply_frames_desc[i],
fusion->reply_frames_desc_phys[i]);
}
if (fusion->reply_frames_desc_pool)
- pci_pool_destroy(fusion->reply_frames_desc_pool);
+ dma_pool_destroy(fusion->reply_frames_desc_pool);
if (fusion->rdpq_virt)
pci_free_consistent(instance->pdev,
@@ -623,12 +625,12 @@ megasas_free_reply_fusion(struct megasas_instance *instance) {
fusion = instance->ctrl_context;
if (fusion->reply_frames_desc[0])
- pci_pool_free(fusion->reply_frames_desc_pool,
+ dma_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);
+ dma_pool_destroy(fusion->reply_frames_desc_pool);
}
@@ -914,7 +916,6 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
ret = 1;
goto fail_fw_init;
}
- dev_info(&instance->pdev->dev, "Init cmd success\n");
ret = 0;
@@ -925,6 +926,10 @@ fail_fw_init:
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);
+
return ret;
}
@@ -1261,6 +1266,80 @@ megasas_display_intel_branding(struct megasas_instance *instance)
}
/**
+ * megasas_allocate_raid_maps - Allocate memory for RAID maps
+ * @instance: Adapter soft state
+ *
+ * return: if success: return 0
+ * failed: return -ENOMEM
+ */
+static inline int megasas_allocate_raid_maps(struct megasas_instance *instance)
+{
+ struct fusion_context *fusion;
+ int i = 0;
+
+ fusion = instance->ctrl_context;
+
+ fusion->drv_map_pages = get_order(fusion->drv_map_sz);
+
+ for (i = 0; i < 2; i++) {
+ fusion->ld_map[i] = NULL;
+
+ fusion->ld_drv_map[i] = (void *)
+ __get_free_pages(__GFP_ZERO | GFP_KERNEL,
+ fusion->drv_map_pages);
+
+ if (!fusion->ld_drv_map[i]) {
+ fusion->ld_drv_map[i] = vzalloc(fusion->drv_map_sz);
+
+ if (!fusion->ld_drv_map[i]) {
+ dev_err(&instance->pdev->dev,
+ "Could not allocate memory for local map"
+ " size requested: %d\n",
+ fusion->drv_map_sz);
+ goto ld_drv_map_alloc_fail;
+ }
+ }
+ }
+
+ for (i = 0; i < 2; i++) {
+ fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev,
+ fusion->max_map_sz,
+ &fusion->ld_map_phys[i],
+ GFP_KERNEL);
+ if (!fusion->ld_map[i]) {
+ dev_err(&instance->pdev->dev,
+ "Could not allocate memory for map info %s:%d\n",
+ __func__, __LINE__);
+ goto ld_map_alloc_fail;
+ }
+ }
+
+ return 0;
+
+ld_map_alloc_fail:
+ for (i = 0; i < 2; i++) {
+ if (fusion->ld_map[i])
+ dma_free_coherent(&instance->pdev->dev,
+ fusion->max_map_sz,
+ fusion->ld_map[i],
+ fusion->ld_map_phys[i]);
+ }
+
+ld_drv_map_alloc_fail:
+ for (i = 0; i < 2; i++) {
+ if (fusion->ld_drv_map[i]) {
+ if (is_vmalloc_addr(fusion->ld_drv_map[i]))
+ vfree(fusion->ld_drv_map[i]);
+ else
+ free_pages((ulong)fusion->ld_drv_map[i],
+ fusion->drv_map_pages);
+ }
+ }
+
+ return -ENOMEM;
+}
+
+/**
* megasas_init_adapter_fusion - Initializes the FW
* @instance: Adapter soft state
*
@@ -1379,45 +1458,14 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
instance->r1_ldio_hint_default = MR_R1_LDIO_PIGGYBACK_DEFAULT;
fusion->fast_path_io = 0;
- fusion->drv_map_pages = get_order(fusion->drv_map_sz);
- for (i = 0; i < 2; i++) {
- fusion->ld_map[i] = NULL;
- fusion->ld_drv_map[i] = (void *)__get_free_pages(GFP_KERNEL,
- fusion->drv_map_pages);
- if (!fusion->ld_drv_map[i]) {
- dev_err(&instance->pdev->dev, "Could not allocate "
- "memory for local map info for %d pages\n",
- fusion->drv_map_pages);
- if (i == 1)
- free_pages((ulong)fusion->ld_drv_map[0],
- fusion->drv_map_pages);
- goto fail_ioc_init;
- }
- memset(fusion->ld_drv_map[i], 0,
- ((1 << PAGE_SHIFT) << fusion->drv_map_pages));
- }
-
- for (i = 0; i < 2; i++) {
- fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev,
- fusion->max_map_sz,
- &fusion->ld_map_phys[i],
- GFP_KERNEL);
- if (!fusion->ld_map[i]) {
- dev_err(&instance->pdev->dev, "Could not allocate memory "
- "for map info\n");
- goto fail_map_info;
- }
- }
+ if (megasas_allocate_raid_maps(instance))
+ goto fail_ioc_init;
if (!megasas_get_map_info(instance))
megasas_sync_map_info(instance);
return 0;
-fail_map_info:
- if (i == 1)
- dma_free_coherent(&instance->pdev->dev, fusion->max_map_sz,
- fusion->ld_map[0], fusion->ld_map_phys[0]);
fail_ioc_init:
megasas_free_cmds_fusion(instance);
fail_alloc_cmds:
@@ -3287,7 +3335,7 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance,
mpi25_ieee_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT |
MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR;
- mpi25_ieee_chain->Length = cpu_to_le32(instance->max_chain_frame_sz);
+ mpi25_ieee_chain->Length = cpu_to_le32(instance->mfi_frame_size);
}
/**
@@ -3369,17 +3417,13 @@ megasas_alloc_host_crash_buffer(struct megasas_instance *instance)
{
unsigned int i;
- instance->crash_buf_pages = get_order(CRASH_DMA_BUF_SIZE);
for (i = 0; i < MAX_CRASH_DUMP_SIZE; i++) {
- instance->crash_buf[i] = (void *)__get_free_pages(GFP_KERNEL,
- instance->crash_buf_pages);
+ instance->crash_buf[i] = vzalloc(CRASH_DMA_BUF_SIZE);
if (!instance->crash_buf[i]) {
dev_info(&instance->pdev->dev, "Firmware crash dump "
"memory allocation failed at index %d\n", i);
break;
}
- memset(instance->crash_buf[i], 0,
- ((1 << PAGE_SHIFT) << instance->crash_buf_pages));
}
instance->drv_buf_alloc = i;
}
@@ -3391,12 +3435,10 @@ megasas_alloc_host_crash_buffer(struct megasas_instance *instance)
void
megasas_free_host_crash_buffer(struct megasas_instance *instance)
{
- unsigned int i
-;
+ unsigned int i;
for (i = 0; i < instance->drv_buf_alloc; i++) {
if (instance->crash_buf[i])
- free_pages((ulong)instance->crash_buf[i],
- instance->crash_buf_pages);
+ vfree(instance->crash_buf[i]);
}
instance->drv_buf_index = 0;
instance->drv_buf_alloc = 0;
@@ -3556,6 +3598,7 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance,
}
}
+ megasas_complete_cmd_dpc_fusion((unsigned long)instance);
outstanding = atomic_read(&instance->fw_outstanding);
if (!outstanding)
goto out;
@@ -3564,8 +3607,6 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance,
dev_notice(&instance->pdev->dev, "[%2d]waiting for %d "
"commands to complete for scsi%d\n", i,
outstanding, instance->host->host_no);
- megasas_complete_cmd_dpc_fusion(
- (unsigned long)instance);
}
msleep(1000);
}
@@ -3623,6 +3664,15 @@ void megasas_refire_mgmt_cmd(struct megasas_instance *instance)
if (!smid)
continue;
+
+ /* Do not refire shutdown command */
+ if (le32_to_cpu(cmd_mfi->frame->dcmd.opcode) ==
+ MR_DCMD_CTRL_SHUTDOWN) {
+ cmd_mfi->frame->dcmd.cmd_status = MFI_STAT_OK;
+ megasas_complete_cmd(instance, cmd_mfi, DID_OK);
+ continue;
+ }
+
req_desc = megasas_get_request_descriptor
(instance, smid - 1);
refire_cmd = req_desc && ((cmd_mfi->frame->dcmd.opcode !=
@@ -3750,7 +3800,7 @@ megasas_issue_tm(struct megasas_instance *instance, u16 device_handle,
struct megasas_cmd_fusion *cmd_fusion;
struct megasas_cmd *cmd_mfi;
union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
- struct fusion_context *fusion;
+ struct fusion_context *fusion = NULL;
struct megasas_cmd_fusion *scsi_lookup;
int rc;
struct MPI2_SCSI_TASK_MANAGE_REPLY *mpi_reply;
@@ -3777,8 +3827,6 @@ megasas_issue_tm(struct megasas_instance *instance, u16 device_handle,
cmd_fusion->request_desc = req_desc;
req_desc->Words = 0;
- scsi_lookup = fusion->cmd_list[smid_task - 1];
-
mr_request = (struct MR_TASK_MANAGE_REQUEST *) cmd_fusion->io_request;
memset(mr_request, 0, sizeof(struct MR_TASK_MANAGE_REQUEST));
mpi_request = (struct MPI2_SCSI_TASK_MANAGE_REQUEST *) &mr_request->TmRequest;
@@ -3825,13 +3873,13 @@ megasas_issue_tm(struct megasas_instance *instance, u16 device_handle,
rc = SUCCESS;
switch (type) {
case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
+ scsi_lookup = fusion->cmd_list[smid_task - 1];
+
if (scsi_lookup->scmd == NULL)
break;
else {
instance->instancet->disable_intr(instance);
megasas_sync_irqs((unsigned long)instance);
- megasas_complete_cmd_dpc_fusion
- ((unsigned long)instance);
instance->instancet->enable_intr(instance);
if (scsi_lookup->scmd == NULL)
break;
@@ -3843,9 +3891,7 @@ megasas_issue_tm(struct megasas_instance *instance, u16 device_handle,
if ((channel == 0xFFFFFFFF) && (id == 0xFFFFFFFF))
break;
instance->instancet->disable_intr(instance);
- msleep(1000);
- megasas_complete_cmd_dpc_fusion
- ((unsigned long)instance);
+ megasas_sync_irqs((unsigned long)instance);
rc = megasas_track_scsiio(instance, id, channel);
instance->instancet->enable_intr(instance);
@@ -4271,9 +4317,6 @@ transition_to_ready:
megasas_fusion_update_can_queue(instance, OCR_CONTEXT);
if (megasas_ioc_init_fusion(instance)) {
- dev_warn(&instance->pdev->dev,
- "megasas_ioc_init_fusion() failed! for "
- "scsi%d\n", instance->host->host_no);
if (instance->requestorId && !reason)
goto fail_kill_adapter;
else
@@ -4319,6 +4362,10 @@ transition_to_ready:
instance->instancet->enable_intr(instance);
atomic_set(&instance->adprecovery, MEGASAS_HBA_OPERATIONAL);
+ dev_info(&instance->pdev->dev, "Interrupts are enabled and"
+ " controller is OPERATIONAL for scsi:%d\n",
+ instance->host->host_no);
+
/* Restart SR-IOV heartbeat */
if (instance->requestorId) {
if (!megasas_sriov_start_heartbeat(instance, 0))
@@ -4330,11 +4377,6 @@ transition_to_ready:
instance->skip_heartbeat_timer_del = 1;
}
- /* Adapter reset completed successfully */
- dev_warn(&instance->pdev->dev, "Reset "
- "successful for scsi%d.\n",
- instance->host->host_no);
-
if (instance->crash_dump_drv_support &&
instance->crash_dump_app_support)
megasas_set_crash_dump_params(instance,
@@ -4344,6 +4386,12 @@ transition_to_ready:
MR_CRASH_BUF_TURN_OFF);
retval = SUCCESS;
+
+ /* Adapter reset completed successfully */
+ dev_warn(&instance->pdev->dev,
+ "Reset successful for scsi%d.\n",
+ instance->host->host_no);
+
goto out;
}
fail_kill_adapter: