diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 75dc25f78336..c199070f04b4 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -709,7 +709,8 @@ struct MR_TARGET_PROPERTIES { u32 max_io_size_kb; u32 device_qdepth; u32 sector_size; - u8 reserved[500]; + u8 reset_tmo; + u8 reserved[499]; } __packed; /* @@ -1400,6 +1401,19 @@ struct megasas_ctrl_info { #endif } adapter_operations4; u8 pad[0x800 - 0x7FE]; /* 0x7FE pad to 2K for expansion */ + + u32 size; + u32 pad1; + + u8 reserved6[64]; + + u32 rsvdForAdptOp[64]; + + u8 reserved7[3]; + + u8 TaskAbortTO; /* Timeout value in seconds used by Abort Task TM */ + u8 MaxResetTO; /* Max Supported Reset timeout in seconds. */ + u8 reserved8[3]; } __packed; /* @@ -1472,6 +1486,7 @@ enum FW_BOOT_CONTEXT { #define MEGASAS_DEFAULT_CMD_TIMEOUT 90 #define MEGASAS_THROTTLE_QUEUE_DEPTH 16 #define MEGASAS_BLOCKED_CMD_TIMEOUT 60 +#define MEGASAS_DEFAULT_TM_TIMEOUT 50 /* * FW reports the maximum of number of commands that it can accept (maximum * commands that can be outstanding) at any time. The driver must report a @@ -1915,7 +1930,9 @@ struct MR_PRIV_DEVICE { bool is_tm_capable; bool tm_busy; atomic_t r1_ldio_hint; - u8 interface_type; + u8 interface_type; + u8 task_abort_tmo; + u8 target_reset_tmo; }; struct megasas_cmd; @@ -2291,6 +2308,8 @@ struct megasas_instance { u8 adapter_type; bool consistent_mask_64bit; bool support_nvme_passthru; + u8 task_abort_tmo; + u8 max_reset_tmo; }; struct MR_LD_VF_MAP { u32 size; @@ -2512,7 +2531,11 @@ int megasas_get_ctrl_info(struct megasas_instance *instance); /* PD sequence */ int megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend); -void megasas_set_dynamic_target_properties(struct scsi_device *sdev); +void megasas_set_dynamic_target_properties(struct scsi_device *sdev, + bool is_target_prop); +int megasas_get_target_prop(struct megasas_instance *instance, + struct scsi_device *sdev); + int megasas_set_crash_dump_params(struct megasas_instance *instance, u8 crash_buf_state); void megasas_free_host_crash_buffer(struct megasas_instance *instance); diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index fd2ce75b4d73..e6ba02793610 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -120,8 +120,7 @@ static int megasas_register_aen(struct megasas_instance *instance, u32 seq_num, u32 class_locale_word); static void megasas_get_pd_info(struct megasas_instance *instance, struct scsi_device *sdev); -static int megasas_get_target_prop(struct megasas_instance *instance, - struct scsi_device *sdev); + /* * PCI ID table for all supported controllers */ @@ -1794,7 +1793,8 @@ static struct megasas_instance *megasas_lookup_instance(u16 host_no) * * Returns void */ -void megasas_set_dynamic_target_properties(struct scsi_device *sdev) +void megasas_set_dynamic_target_properties(struct scsi_device *sdev, + bool is_target_prop) { u16 pd_index = 0, ld; u32 device_id; @@ -1834,6 +1834,22 @@ void megasas_set_dynamic_target_properties(struct scsi_device *sdev) mr_device_priv_data->is_tm_capable = pd_sync->seq[pd_index].capability.tmCapable; } + + if (is_target_prop && instance->tgt_prop->reset_tmo) { + /* + * If FW provides a target reset timeout value, driver will use + * it. If not set, fallback to default values. + */ + mr_device_priv_data->target_reset_tmo = + min_t(u8, instance->max_reset_tmo, + instance->tgt_prop->reset_tmo); + mr_device_priv_data->task_abort_tmo = instance->task_abort_tmo; + } else { + mr_device_priv_data->target_reset_tmo = + MEGASAS_DEFAULT_TM_TIMEOUT; + mr_device_priv_data->task_abort_tmo = + MEGASAS_DEFAULT_TM_TIMEOUT; + } } /* @@ -1967,10 +1983,10 @@ static int megasas_slave_configure(struct scsi_device *sdev) is_target_prop = (ret_target_prop == DCMD_SUCCESS) ? true : false; megasas_set_static_target_properties(sdev, is_target_prop); - mutex_unlock(&instance->reset_mutex); - /* This sdev property may change post OCR */ - megasas_set_dynamic_target_properties(sdev); + megasas_set_dynamic_target_properties(sdev, is_target_prop); + + mutex_unlock(&instance->reset_mutex); return 0; } @@ -4720,6 +4736,8 @@ megasas_get_ctrl_info(struct megasas_instance *instance) ci->adapter_operations4.support_pd_map_target_id; instance->support_nvme_passthru = ci->adapter_operations4.support_nvme_passthru; + instance->task_abort_tmo = ci->TaskAbortTO; + instance->max_reset_tmo = ci->MaxResetTO; /*Check whether controller is iMR or MR */ instance->is_imr = (ci->memory_size ? 0 : 1); @@ -4738,6 +4756,10 @@ megasas_get_ctrl_info(struct megasas_instance *instance) instance->secure_jbod_support ? "Yes" : "No"); dev_info(&instance->pdev->dev, "NVMe passthru support\t: %s\n", instance->support_nvme_passthru ? "Yes" : "No"); + dev_info(&instance->pdev->dev, + "FW provided TM TaskAbort/Reset timeout\t: %d secs/%d secs\n", + instance->task_abort_tmo, instance->max_reset_tmo); + break; case DCMD_TIMEOUT: @@ -5832,7 +5854,7 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num, * * Returns 0 on success non-zero on failure. */ -static int +int megasas_get_target_prop(struct megasas_instance *instance, struct scsi_device *sdev) { diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 94c23ad51179..c7f95bace353 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -4108,7 +4108,8 @@ megasas_tm_response_code(struct megasas_instance *instance, */ static int megasas_issue_tm(struct megasas_instance *instance, u16 device_handle, - uint channel, uint id, u16 smid_task, u8 type) + uint channel, uint id, u16 smid_task, u8 type, + struct MR_PRIV_DEVICE *mr_device_priv_data) { struct MR_TASK_MANAGE_REQUEST *mr_request; struct MPI2_SCSI_TASK_MANAGE_REQUEST *mpi_request; @@ -4119,6 +4120,7 @@ megasas_issue_tm(struct megasas_instance *instance, u16 device_handle, struct fusion_context *fusion = NULL; struct megasas_cmd_fusion *scsi_lookup; int rc; + int timeout = MEGASAS_DEFAULT_TM_TIMEOUT; struct MPI2_SCSI_TASK_MANAGE_REPLY *mpi_reply; fusion = instance->ctrl_context; @@ -4170,7 +4172,16 @@ megasas_issue_tm(struct megasas_instance *instance, u16 device_handle, init_completion(&cmd_fusion->done); megasas_fire_cmd_fusion(instance, req_desc); - timeleft = wait_for_completion_timeout(&cmd_fusion->done, 50 * HZ); + switch (type) { + case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK: + timeout = mr_device_priv_data->task_abort_tmo; + break; + case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET: + timeout = mr_device_priv_data->target_reset_tmo; + break; + } + + timeleft = wait_for_completion_timeout(&cmd_fusion->done, timeout * HZ); if (!timeleft) { dev_err(&instance->pdev->dev, @@ -4363,7 +4374,8 @@ int megasas_task_abort_fusion(struct scsi_cmnd *scmd) mr_device_priv_data->tm_busy = 1; ret = megasas_issue_tm(instance, devhandle, scmd->device->channel, scmd->device->id, smid, - MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK); + MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, + mr_device_priv_data); mr_device_priv_data->tm_busy = 0; mutex_unlock(&instance->reset_mutex); @@ -4435,7 +4447,8 @@ int megasas_reset_target_fusion(struct scsi_cmnd *scmd) mr_device_priv_data->tm_busy = 1; ret = megasas_issue_tm(instance, devhandle, scmd->device->channel, scmd->device->id, 0, - MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET); + MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, + mr_device_priv_data); mr_device_priv_data->tm_busy = 0; mutex_unlock(&instance->reset_mutex); out: @@ -4490,6 +4503,8 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason) u32 io_timeout_in_crash_mode = 0; struct scsi_cmnd *scmd_local = NULL; struct scsi_device *sdev; + int ret_target_prop = DCMD_FAILED; + bool is_target_prop = false; instance = (struct megasas_instance *)shost->hostdata; fusion = instance->ctrl_context; @@ -4661,9 +4676,6 @@ transition_to_ready: megasas_setup_jbod_map(instance); - shost_for_each_device(sdev, shost) - megasas_set_dynamic_target_properties(sdev); - /* reset stream detection array */ if (instance->adapter_type == VENTURA_SERIES) { for (j = 0; j < MAX_LOGICAL_DRIVES_EXT; ++j) { @@ -4677,6 +4689,16 @@ transition_to_ready: clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); instance->instancet->enable_intr(instance); + + shost_for_each_device(sdev, shost) { + if ((instance->tgt_prop) && + (instance->nvme_page_size)) + ret_target_prop = megasas_get_target_prop(instance, sdev); + + is_target_prop = (ret_target_prop == DCMD_SUCCESS) ? true : false; + megasas_set_dynamic_target_properties(sdev, is_target_prop); + } + atomic_set(&instance->adprecovery, MEGASAS_HBA_OPERATIONAL); dev_info(&instance->pdev->dev, "Interrupts are enabled and"