mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 09:16:33 +00:00
scsi: mpi3mr: Trigger support
Add functions to process automatic diag triggers. If a condition defined in the triggers is met, the driver will call appropriate controller functions to save the diagnostic information. Reported-by: kernel test robot <lkp@intel.com> Closes: https://lore.kernel.org/oe-kbuild-all/202405151955.BiAWI1SY-lkp@intel.com/ Co-developed-by: Sathya Prakash <sathya.prakash@broadcom.com> Signed-off-by: Sathya Prakash <sathya.prakash@broadcom.com> Signed-off-by: Ranjan Kumar <ranjan.kumar@broadcom.com> Link: https://lore.kernel.org/r/20240626102646.14298-3-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
fc44449411
commit
d8d08d1638
@ -193,7 +193,12 @@ extern atomic64_t event_counter;
|
||||
#define MPI3MR_DEFAULT_HDB_MIN_SZ (2 * 1024 * 1024)
|
||||
#define MPI3MR_MAX_NUM_HDB 2
|
||||
|
||||
#define MPI3MR_HDB_TRIGGER_TYPE_UNKNOWN 0
|
||||
#define MPI3MR_HDB_TRIGGER_TYPE_FAULT 1
|
||||
#define MPI3MR_HDB_TRIGGER_TYPE_ELEMENT 2
|
||||
#define MPI3MR_HDB_TRIGGER_TYPE_GLOBAL 3
|
||||
#define MPI3MR_HDB_TRIGGER_TYPE_SOFT_RESET 4
|
||||
#define MPI3MR_HDB_TRIGGER_TYPE_FW_RELEASED 5
|
||||
|
||||
/* SGE Flag definition */
|
||||
#define MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST \
|
||||
@ -218,6 +223,7 @@ extern atomic64_t event_counter;
|
||||
#define MPI3MR_WRITE_SAME_MAX_LEN_256_BLKS 256
|
||||
#define MPI3MR_WRITE_SAME_MAX_LEN_2048_BLKS 2048
|
||||
|
||||
#define MPI3MR_DRIVER_EVENT_PROCESS_TRIGGER (0xFFFD)
|
||||
|
||||
/**
|
||||
* struct mpi3mr_nvme_pt_sge - Structure to store SGEs for NVMe
|
||||
@ -303,6 +309,7 @@ enum mpi3mr_reset_reason {
|
||||
MPI3MR_RESET_FROM_FIRMWARE = 27,
|
||||
MPI3MR_RESET_FROM_CFG_REQ_TIMEOUT = 29,
|
||||
MPI3MR_RESET_FROM_SAS_TRANSPORT_TIMEOUT = 30,
|
||||
MPI3MR_RESET_FROM_TRIGGER = 31,
|
||||
};
|
||||
|
||||
#define MPI3MR_RESET_REASON_OSTYPE_LINUX 1
|
||||
@ -878,6 +885,24 @@ union mpi3mr_trigger_data {
|
||||
union mpi3_driver2_trigger_element element;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct trigger_event_data - store trigger related
|
||||
* information.
|
||||
*
|
||||
* @trace_hdb: Trace diag buffer descriptor reference
|
||||
* @fw_hdb: FW diag buffer descriptor reference
|
||||
* @trigger_type: Trigger type
|
||||
* @trigger_specific_data: Trigger specific data
|
||||
* @snapdump: Snapdump enable or disable flag
|
||||
*/
|
||||
struct trigger_event_data {
|
||||
struct diag_buffer_desc *trace_hdb;
|
||||
struct diag_buffer_desc *fw_hdb;
|
||||
u8 trigger_type;
|
||||
union mpi3mr_trigger_data trigger_specific_data;
|
||||
bool snapdump;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct diag_buffer_desc - memory descriptor structure to
|
||||
* store virtual, dma addresses, size, buffer status for host
|
||||
@ -1113,6 +1138,9 @@ struct scmd_priv {
|
||||
* @ioctl_chain_sge: DMA buffer descriptor for IOCTL chain
|
||||
* @ioctl_resp_sge: DMA buffer descriptor for Mgmt cmd response
|
||||
* @ioctl_sges_allocated: Flag for IOCTL SGEs allocated or not
|
||||
* @trace_release_trigger_active: Trace trigger active flag
|
||||
* @fw_release_trigger_active: Fw release trigger active flag
|
||||
* @snapdump_trigger_active: Snapdump trigger active flag
|
||||
*/
|
||||
struct mpi3mr_ioc {
|
||||
struct list_head list;
|
||||
@ -1310,6 +1338,9 @@ struct mpi3mr_ioc {
|
||||
struct diag_buffer_desc diag_buffers[MPI3MR_MAX_NUM_HDB];
|
||||
struct mpi3_driver_page2 *driver_pg2;
|
||||
spinlock_t trigger_lock;
|
||||
bool snapdump_trigger_active;
|
||||
bool trace_release_trigger_active;
|
||||
bool fw_release_trigger_active;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1513,4 +1544,16 @@ struct diag_buffer_desc *mpi3mr_diag_buffer_for_type(struct mpi3mr_ioc *mrioc,
|
||||
u8 buf_type);
|
||||
int mpi3mr_issue_diag_buf_post(struct mpi3mr_ioc *mrioc,
|
||||
struct diag_buffer_desc *diag_buffer);
|
||||
void mpi3mr_set_trigger_data_in_all_hdb(struct mpi3mr_ioc *mrioc,
|
||||
u8 type, union mpi3mr_trigger_data *trigger_data, bool force);
|
||||
void mpi3mr_reply_trigger(struct mpi3mr_ioc *mrioc, u16 iocstatus,
|
||||
u32 iocloginfo);
|
||||
void mpi3mr_hdb_trigger_data_event(struct mpi3mr_ioc *mrioc,
|
||||
struct trigger_event_data *event_data);
|
||||
void mpi3mr_scsisense_trigger(struct mpi3mr_ioc *mrioc, u8 senseky, u8 asc,
|
||||
u8 ascq);
|
||||
void mpi3mr_event_trigger(struct mpi3mr_ioc *mrioc, u8 event);
|
||||
void mpi3mr_global_trigger(struct mpi3mr_ioc *mrioc, u64 trigger_data);
|
||||
void mpi3mr_hdbstatuschg_evt_th(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3_event_notification_reply *event_reply);
|
||||
#endif /*MPI3MR_H_INCLUDED*/
|
||||
|
@ -316,6 +316,263 @@ int mpi3mr_issue_diag_buf_release(struct mpi3mr_ioc *mrioc,
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_process_trigger - Generic HDB Trigger handler
|
||||
* @mrioc: Adapter instance reference
|
||||
* @trigger_type: Trigger type
|
||||
* @trigger_data: Trigger data
|
||||
* @trigger_flags: Trigger flags
|
||||
*
|
||||
* This function checks validity of HDB, triggers and based on
|
||||
* trigger information, creates an event to be processed in the
|
||||
* firmware event worker thread .
|
||||
*
|
||||
* This function should be called with trigger spinlock held
|
||||
*
|
||||
* Return: Nothing
|
||||
*/
|
||||
static void mpi3mr_process_trigger(struct mpi3mr_ioc *mrioc, u8 trigger_type,
|
||||
union mpi3mr_trigger_data *trigger_data, u8 trigger_flags)
|
||||
{
|
||||
struct trigger_event_data event_data;
|
||||
struct diag_buffer_desc *trace_hdb = NULL;
|
||||
struct diag_buffer_desc *fw_hdb = NULL;
|
||||
u64 global_trigger;
|
||||
|
||||
trace_hdb = mpi3mr_diag_buffer_for_type(mrioc,
|
||||
MPI3_DIAG_BUFFER_TYPE_TRACE);
|
||||
if (trace_hdb &&
|
||||
(trace_hdb->status != MPI3MR_HDB_BUFSTATUS_POSTED_UNPAUSED) &&
|
||||
(trace_hdb->status != MPI3MR_HDB_BUFSTATUS_POSTED_PAUSED))
|
||||
trace_hdb = NULL;
|
||||
|
||||
fw_hdb = mpi3mr_diag_buffer_for_type(mrioc, MPI3_DIAG_BUFFER_TYPE_FW);
|
||||
|
||||
if (fw_hdb &&
|
||||
(fw_hdb->status != MPI3MR_HDB_BUFSTATUS_POSTED_UNPAUSED) &&
|
||||
(fw_hdb->status != MPI3MR_HDB_BUFSTATUS_POSTED_PAUSED))
|
||||
fw_hdb = NULL;
|
||||
|
||||
if (mrioc->snapdump_trigger_active || (mrioc->fw_release_trigger_active
|
||||
&& mrioc->trace_release_trigger_active) ||
|
||||
(!trace_hdb && !fw_hdb) || (!mrioc->driver_pg2) ||
|
||||
((trigger_type == MPI3MR_HDB_TRIGGER_TYPE_ELEMENT)
|
||||
&& (!mrioc->driver_pg2->num_triggers)))
|
||||
return;
|
||||
|
||||
memset(&event_data, 0, sizeof(event_data));
|
||||
event_data.trigger_type = trigger_type;
|
||||
memcpy(&event_data.trigger_specific_data, trigger_data,
|
||||
sizeof(*trigger_data));
|
||||
global_trigger = le64_to_cpu(mrioc->driver_pg2->global_trigger);
|
||||
|
||||
if (global_trigger & MPI3_DRIVER2_GLOBALTRIGGER_SNAPDUMP_ENABLED) {
|
||||
event_data.snapdump = true;
|
||||
event_data.trace_hdb = trace_hdb;
|
||||
event_data.fw_hdb = fw_hdb;
|
||||
mrioc->snapdump_trigger_active = true;
|
||||
} else if (trigger_type == MPI3MR_HDB_TRIGGER_TYPE_GLOBAL) {
|
||||
if ((trace_hdb) && (global_trigger &
|
||||
MPI3_DRIVER2_GLOBALTRIGGER_DIAG_TRACE_RELEASE) &&
|
||||
(!mrioc->trace_release_trigger_active)) {
|
||||
event_data.trace_hdb = trace_hdb;
|
||||
mrioc->trace_release_trigger_active = true;
|
||||
}
|
||||
if ((fw_hdb) && (global_trigger &
|
||||
MPI3_DRIVER2_GLOBALTRIGGER_DIAG_FW_RELEASE) &&
|
||||
(!mrioc->fw_release_trigger_active)) {
|
||||
event_data.fw_hdb = fw_hdb;
|
||||
mrioc->fw_release_trigger_active = true;
|
||||
}
|
||||
} else if (trigger_type == MPI3MR_HDB_TRIGGER_TYPE_ELEMENT) {
|
||||
if ((trace_hdb) && (trigger_flags &
|
||||
MPI3_DRIVER2_TRIGGER_FLAGS_DIAG_TRACE_RELEASE) &&
|
||||
(!mrioc->trace_release_trigger_active)) {
|
||||
event_data.trace_hdb = trace_hdb;
|
||||
mrioc->trace_release_trigger_active = true;
|
||||
}
|
||||
if ((fw_hdb) && (trigger_flags &
|
||||
MPI3_DRIVER2_TRIGGER_FLAGS_DIAG_FW_RELEASE) &&
|
||||
(!mrioc->fw_release_trigger_active)) {
|
||||
event_data.fw_hdb = fw_hdb;
|
||||
mrioc->fw_release_trigger_active = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (event_data.trace_hdb || event_data.fw_hdb)
|
||||
mpi3mr_hdb_trigger_data_event(mrioc, &event_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_global_trigger - Global HDB trigger handler
|
||||
* @mrioc: Adapter instance reference
|
||||
* @trigger_data: Trigger data
|
||||
*
|
||||
* This function checks whether the given global trigger is
|
||||
* enabled in the driver page 2 and if so calls generic trigger
|
||||
* handler to queue event for HDB release.
|
||||
*
|
||||
* Return: Nothing
|
||||
*/
|
||||
void mpi3mr_global_trigger(struct mpi3mr_ioc *mrioc, u64 trigger_data)
|
||||
{
|
||||
unsigned long flags;
|
||||
union mpi3mr_trigger_data trigger_specific_data;
|
||||
|
||||
spin_lock_irqsave(&mrioc->trigger_lock, flags);
|
||||
if (le64_to_cpu(mrioc->driver_pg2->global_trigger) & trigger_data) {
|
||||
memset(&trigger_specific_data, 0,
|
||||
sizeof(trigger_specific_data));
|
||||
trigger_specific_data.global = trigger_data;
|
||||
mpi3mr_process_trigger(mrioc, MPI3MR_HDB_TRIGGER_TYPE_GLOBAL,
|
||||
&trigger_specific_data, 0);
|
||||
}
|
||||
spin_unlock_irqrestore(&mrioc->trigger_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_scsisense_trigger - SCSI sense HDB trigger handler
|
||||
* @mrioc: Adapter instance reference
|
||||
* @sensekey: Sense Key
|
||||
* @asc: Additional Sense Code
|
||||
* @ascq: Additional Sense Code Qualifier
|
||||
*
|
||||
* This function compares SCSI sense trigger values with driver
|
||||
* page 2 values and calls generic trigger handler to release
|
||||
* HDBs if match found
|
||||
*
|
||||
* Return: Nothing
|
||||
*/
|
||||
void mpi3mr_scsisense_trigger(struct mpi3mr_ioc *mrioc, u8 sensekey, u8 asc,
|
||||
u8 ascq)
|
||||
{
|
||||
struct mpi3_driver2_trigger_scsi_sense *scsi_sense_trigger = NULL;
|
||||
u64 i = 0;
|
||||
unsigned long flags;
|
||||
u8 num_triggers, trigger_flags;
|
||||
|
||||
if (mrioc->scsisense_trigger_present) {
|
||||
spin_lock_irqsave(&mrioc->trigger_lock, flags);
|
||||
scsi_sense_trigger = (struct mpi3_driver2_trigger_scsi_sense *)
|
||||
mrioc->driver_pg2->trigger;
|
||||
num_triggers = mrioc->driver_pg2->num_triggers;
|
||||
for (i = 0; i < num_triggers; i++, scsi_sense_trigger++) {
|
||||
if (scsi_sense_trigger->type !=
|
||||
MPI3_DRIVER2_TRIGGER_TYPE_SCSI_SENSE)
|
||||
continue;
|
||||
if (!(scsi_sense_trigger->sense_key ==
|
||||
MPI3_DRIVER2_TRIGGER_SCSI_SENSE_SENSE_KEY_MATCH_ALL
|
||||
|| scsi_sense_trigger->sense_key == sensekey))
|
||||
continue;
|
||||
if (!(scsi_sense_trigger->asc ==
|
||||
MPI3_DRIVER2_TRIGGER_SCSI_SENSE_ASC_MATCH_ALL ||
|
||||
scsi_sense_trigger->asc == asc))
|
||||
continue;
|
||||
if (!(scsi_sense_trigger->ascq ==
|
||||
MPI3_DRIVER2_TRIGGER_SCSI_SENSE_ASCQ_MATCH_ALL ||
|
||||
scsi_sense_trigger->ascq == ascq))
|
||||
continue;
|
||||
trigger_flags = scsi_sense_trigger->flags;
|
||||
mpi3mr_process_trigger(mrioc,
|
||||
MPI3MR_HDB_TRIGGER_TYPE_ELEMENT,
|
||||
(union mpi3mr_trigger_data *)scsi_sense_trigger,
|
||||
trigger_flags);
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&mrioc->trigger_lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_event_trigger - MPI event HDB trigger handler
|
||||
* @mrioc: Adapter instance reference
|
||||
* @event: MPI Event
|
||||
*
|
||||
* This function compares event trigger values with driver page
|
||||
* 2 values and calls generic trigger handler to release
|
||||
* HDBs if match found.
|
||||
*
|
||||
* Return: Nothing
|
||||
*/
|
||||
void mpi3mr_event_trigger(struct mpi3mr_ioc *mrioc, u8 event)
|
||||
{
|
||||
struct mpi3_driver2_trigger_event *event_trigger = NULL;
|
||||
u64 i = 0;
|
||||
unsigned long flags;
|
||||
u8 num_triggers, trigger_flags;
|
||||
|
||||
if (mrioc->event_trigger_present) {
|
||||
spin_lock_irqsave(&mrioc->trigger_lock, flags);
|
||||
event_trigger = (struct mpi3_driver2_trigger_event *)
|
||||
mrioc->driver_pg2->trigger;
|
||||
num_triggers = mrioc->driver_pg2->num_triggers;
|
||||
|
||||
for (i = 0; i < num_triggers; i++, event_trigger++) {
|
||||
if (event_trigger->type !=
|
||||
MPI3_DRIVER2_TRIGGER_TYPE_EVENT)
|
||||
continue;
|
||||
if (event_trigger->event != event)
|
||||
continue;
|
||||
trigger_flags = event_trigger->flags;
|
||||
mpi3mr_process_trigger(mrioc,
|
||||
MPI3MR_HDB_TRIGGER_TYPE_ELEMENT,
|
||||
(union mpi3mr_trigger_data *)event_trigger,
|
||||
trigger_flags);
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&mrioc->trigger_lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_reply_trigger - MPI Reply HDB trigger handler
|
||||
* @mrioc: Adapter instance reference
|
||||
* @ioc_status: Masked value of IOC Status from MPI Reply
|
||||
* @ioc_loginfo: IOC Log Info from MPI Reply
|
||||
*
|
||||
* This function compares IOC status and IOC log info trigger
|
||||
* values with driver page 2 values and calls generic trigger
|
||||
* handler to release HDBs if match found.
|
||||
*
|
||||
* Return: Nothing
|
||||
*/
|
||||
void mpi3mr_reply_trigger(struct mpi3mr_ioc *mrioc, u16 ioc_status,
|
||||
u32 ioc_loginfo)
|
||||
{
|
||||
struct mpi3_driver2_trigger_reply *reply_trigger = NULL;
|
||||
u64 i = 0;
|
||||
unsigned long flags;
|
||||
u8 num_triggers, trigger_flags;
|
||||
|
||||
if (mrioc->reply_trigger_present) {
|
||||
spin_lock_irqsave(&mrioc->trigger_lock, flags);
|
||||
reply_trigger = (struct mpi3_driver2_trigger_reply *)
|
||||
mrioc->driver_pg2->trigger;
|
||||
num_triggers = mrioc->driver_pg2->num_triggers;
|
||||
for (i = 0; i < num_triggers; i++, reply_trigger++) {
|
||||
if (reply_trigger->type !=
|
||||
MPI3_DRIVER2_TRIGGER_TYPE_REPLY)
|
||||
continue;
|
||||
if ((le16_to_cpu(reply_trigger->ioc_status) !=
|
||||
ioc_status)
|
||||
&& (le16_to_cpu(reply_trigger->ioc_status) !=
|
||||
MPI3_DRIVER2_TRIGGER_REPLY_IOCSTATUS_MATCH_ALL))
|
||||
continue;
|
||||
if ((le32_to_cpu(reply_trigger->ioc_log_info) !=
|
||||
(le32_to_cpu(reply_trigger->ioc_log_info_mask) &
|
||||
ioc_loginfo)))
|
||||
continue;
|
||||
trigger_flags = reply_trigger->flags;
|
||||
mpi3mr_process_trigger(mrioc,
|
||||
MPI3MR_HDB_TRIGGER_TYPE_ELEMENT,
|
||||
(union mpi3mr_trigger_data *)reply_trigger,
|
||||
trigger_flags);
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&mrioc->trigger_lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_get_num_trigger - Gets number of HDB triggers
|
||||
* @mrioc: Adapter instance reference
|
||||
@ -449,7 +706,7 @@ void mpi3mr_release_diag_bufs(struct mpi3mr_ioc *mrioc, u8 skip_rel_action)
|
||||
* @type: Trigger type
|
||||
* @data: Trigger data
|
||||
* @force: Trigger overwrite flag
|
||||
* @trigger_data: pointer to trigger data information
|
||||
* @trigger_data: Pointer to trigger data information
|
||||
*
|
||||
* Updates trigger type and trigger data based on parameter
|
||||
* passed to this function
|
||||
@ -468,6 +725,84 @@ void mpi3mr_set_trigger_data_in_hdb(struct diag_buffer_desc *hdb,
|
||||
memcpy(&hdb->trigger_data, trigger_data, sizeof(*trigger_data));
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_set_trigger_data_in_all_hdb - Updates HDB trigger type
|
||||
* and trigger data for all HDB
|
||||
*
|
||||
* @mrioc: Adapter instance reference
|
||||
* @type: Trigger type
|
||||
* @data: Trigger data
|
||||
* @force: Trigger overwrite flag
|
||||
* @trigger_data: Pointer to trigger data information
|
||||
*
|
||||
* Updates trigger type and trigger data based on parameter
|
||||
* passed to this function
|
||||
*
|
||||
* Return: Nothing
|
||||
*/
|
||||
void mpi3mr_set_trigger_data_in_all_hdb(struct mpi3mr_ioc *mrioc,
|
||||
u8 type, union mpi3mr_trigger_data *trigger_data, bool force)
|
||||
{
|
||||
struct diag_buffer_desc *hdb = NULL;
|
||||
|
||||
hdb = mpi3mr_diag_buffer_for_type(mrioc, MPI3_DIAG_BUFFER_TYPE_TRACE);
|
||||
if (hdb)
|
||||
mpi3mr_set_trigger_data_in_hdb(hdb, type, trigger_data, force);
|
||||
hdb = mpi3mr_diag_buffer_for_type(mrioc, MPI3_DIAG_BUFFER_TYPE_FW);
|
||||
if (hdb)
|
||||
mpi3mr_set_trigger_data_in_hdb(hdb, type, trigger_data, force);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_hdbstatuschg_evt_th - HDB status change evt tophalf
|
||||
* @mrioc: Adapter instance reference
|
||||
* @event_reply: event data
|
||||
*
|
||||
* Modifies the status of the applicable diag buffer descriptors
|
||||
*
|
||||
* Return: Nothing
|
||||
*/
|
||||
void mpi3mr_hdbstatuschg_evt_th(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3_event_notification_reply *event_reply)
|
||||
{
|
||||
struct mpi3_event_data_diag_buffer_status_change *evtdata;
|
||||
struct diag_buffer_desc *diag_buffer;
|
||||
|
||||
evtdata = (struct mpi3_event_data_diag_buffer_status_change *)
|
||||
event_reply->event_data;
|
||||
|
||||
diag_buffer = mpi3mr_diag_buffer_for_type(mrioc, evtdata->type);
|
||||
if (!diag_buffer)
|
||||
return;
|
||||
if ((diag_buffer->status != MPI3MR_HDB_BUFSTATUS_POSTED_UNPAUSED) &&
|
||||
(diag_buffer->status != MPI3MR_HDB_BUFSTATUS_POSTED_PAUSED))
|
||||
return;
|
||||
switch (evtdata->reason_code) {
|
||||
case MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_RELEASED:
|
||||
{
|
||||
diag_buffer->status = MPI3MR_HDB_BUFSTATUS_RELEASED;
|
||||
mpi3mr_set_trigger_data_in_hdb(diag_buffer,
|
||||
MPI3MR_HDB_TRIGGER_TYPE_FW_RELEASED, NULL, 0);
|
||||
atomic64_inc(&event_counter);
|
||||
break;
|
||||
}
|
||||
case MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_RESUMED:
|
||||
{
|
||||
diag_buffer->status = MPI3MR_HDB_BUFSTATUS_POSTED_UNPAUSED;
|
||||
break;
|
||||
}
|
||||
case MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_PAUSED:
|
||||
{
|
||||
diag_buffer->status = MPI3MR_HDB_BUFSTATUS_POSTED_PAUSED;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
dprint_event_th(mrioc, "%s: unknown reason_code(%d)\n",
|
||||
__func__, evtdata->reason_code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_diag_buffer_for_type - returns buffer desc for type
|
||||
* @mrioc: Adapter instance reference
|
||||
|
@ -274,6 +274,9 @@ static void mpi3mr_print_event_data(struct mpi3mr_ioc *mrioc,
|
||||
case MPI3_EVENT_PREPARE_FOR_RESET:
|
||||
desc = "Prepare For Reset";
|
||||
break;
|
||||
case MPI3_EVENT_DIAGNOSTIC_BUFFER_STATUS_CHANGE:
|
||||
desc = "Diagnostic Buffer Status Change";
|
||||
break;
|
||||
}
|
||||
|
||||
if (!desc)
|
||||
@ -342,13 +345,14 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_ioc *mrioc,
|
||||
{
|
||||
u16 reply_desc_type, host_tag = 0;
|
||||
u16 ioc_status = MPI3_IOCSTATUS_SUCCESS;
|
||||
u32 ioc_loginfo = 0;
|
||||
u32 ioc_loginfo = 0, sense_count = 0;
|
||||
struct mpi3_status_reply_descriptor *status_desc;
|
||||
struct mpi3_address_reply_descriptor *addr_desc;
|
||||
struct mpi3_success_reply_descriptor *success_desc;
|
||||
struct mpi3_default_reply *def_reply = NULL;
|
||||
struct mpi3mr_drv_cmd *cmdptr = NULL;
|
||||
struct mpi3_scsi_io_reply *scsi_reply;
|
||||
struct scsi_sense_hdr sshdr;
|
||||
u8 *sense_buf = NULL;
|
||||
|
||||
*reply_dma = 0;
|
||||
@ -363,6 +367,7 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_ioc *mrioc,
|
||||
MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL)
|
||||
ioc_loginfo = le32_to_cpu(status_desc->ioc_log_info);
|
||||
ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK;
|
||||
mpi3mr_reply_trigger(mrioc, ioc_status, ioc_loginfo);
|
||||
break;
|
||||
case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY:
|
||||
addr_desc = (struct mpi3_address_reply_descriptor *)reply_desc;
|
||||
@ -380,7 +385,15 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_ioc *mrioc,
|
||||
scsi_reply = (struct mpi3_scsi_io_reply *)def_reply;
|
||||
sense_buf = mpi3mr_get_sensebuf_virt_addr(mrioc,
|
||||
le64_to_cpu(scsi_reply->sense_data_buffer_address));
|
||||
sense_count = le32_to_cpu(scsi_reply->sense_count);
|
||||
if (sense_buf) {
|
||||
scsi_normalize_sense(sense_buf, sense_count,
|
||||
&sshdr);
|
||||
mpi3mr_scsisense_trigger(mrioc, sshdr.sense_key,
|
||||
sshdr.asc, sshdr.ascq);
|
||||
}
|
||||
}
|
||||
mpi3mr_reply_trigger(mrioc, ioc_status, ioc_loginfo);
|
||||
break;
|
||||
case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS:
|
||||
success_desc = (struct mpi3_success_reply_descriptor *)reply_desc;
|
||||
@ -938,6 +951,14 @@ static const struct {
|
||||
},
|
||||
{ MPI3MR_RESET_FROM_SYSFS, "sysfs invocation" },
|
||||
{ MPI3MR_RESET_FROM_SYSFS_TIMEOUT, "sysfs TM timeout" },
|
||||
{
|
||||
MPI3MR_RESET_FROM_DIAG_BUFFER_POST_TIMEOUT,
|
||||
"diagnostic buffer post timeout"
|
||||
},
|
||||
{
|
||||
MPI3MR_RESET_FROM_DIAG_BUFFER_RELEASE_TIMEOUT,
|
||||
"diagnostic buffer release timeout"
|
||||
},
|
||||
{ MPI3MR_RESET_FROM_FIRMWARE, "firmware asynchronous reset" },
|
||||
{ MPI3MR_RESET_FROM_CFG_REQ_TIMEOUT, "configuration request timeout"},
|
||||
{ MPI3MR_RESET_FROM_SAS_TRANSPORT_TIMEOUT, "timeout of a SAS transport layer request" },
|
||||
@ -2387,6 +2408,7 @@ int mpi3mr_op_request_post(struct mpi3mr_ioc *mrioc,
|
||||
void mpi3mr_check_rh_fault_ioc(struct mpi3mr_ioc *mrioc, u32 reason_code)
|
||||
{
|
||||
u32 ioc_status, host_diagnostic, timeout;
|
||||
union mpi3mr_trigger_data trigger_data;
|
||||
|
||||
if (mrioc->unrecoverable) {
|
||||
ioc_err(mrioc, "controller is unrecoverable\n");
|
||||
@ -2398,16 +2420,30 @@ void mpi3mr_check_rh_fault_ioc(struct mpi3mr_ioc *mrioc, u32 reason_code)
|
||||
ioc_err(mrioc, "controller is not present\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&trigger_data, 0, sizeof(trigger_data));
|
||||
ioc_status = readl(&mrioc->sysif_regs->ioc_status);
|
||||
if ((ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) ||
|
||||
(ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT)) {
|
||||
|
||||
if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) {
|
||||
mpi3mr_set_trigger_data_in_all_hdb(mrioc,
|
||||
MPI3MR_HDB_TRIGGER_TYPE_FW_RELEASED, NULL, 0);
|
||||
return;
|
||||
} else if (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) {
|
||||
trigger_data.fault = (readl(&mrioc->sysif_regs->fault) &
|
||||
MPI3_SYSIF_FAULT_CODE_MASK);
|
||||
|
||||
mpi3mr_set_trigger_data_in_all_hdb(mrioc,
|
||||
MPI3MR_HDB_TRIGGER_TYPE_FAULT, &trigger_data, 0);
|
||||
mpi3mr_print_fault_info(mrioc);
|
||||
return;
|
||||
}
|
||||
|
||||
mpi3mr_set_diagsave(mrioc);
|
||||
mpi3mr_issue_reset(mrioc, MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT,
|
||||
reason_code);
|
||||
trigger_data.fault = (readl(&mrioc->sysif_regs->fault) &
|
||||
MPI3_SYSIF_FAULT_CODE_MASK);
|
||||
mpi3mr_set_trigger_data_in_all_hdb(mrioc, MPI3MR_HDB_TRIGGER_TYPE_FAULT,
|
||||
&trigger_data, 0);
|
||||
timeout = MPI3_SYSIF_DIAG_SAVE_TIMEOUT * 10;
|
||||
do {
|
||||
host_diagnostic = readl(&mrioc->sysif_regs->host_diagnostic);
|
||||
@ -2587,7 +2623,8 @@ static void mpi3mr_watchdog_work(struct work_struct *work)
|
||||
container_of(work, struct mpi3mr_ioc, watchdog_work.work);
|
||||
unsigned long flags;
|
||||
enum mpi3mr_iocstate ioc_state;
|
||||
u32 fault, host_diagnostic, ioc_status;
|
||||
u32 host_diagnostic, ioc_status;
|
||||
union mpi3mr_trigger_data trigger_data;
|
||||
u16 reset_reason = MPI3MR_RESET_FROM_FAULT_WATCH;
|
||||
|
||||
if (mrioc->reset_in_progress)
|
||||
@ -2618,8 +2655,11 @@ static void mpi3mr_watchdog_work(struct work_struct *work)
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&trigger_data, 0, sizeof(trigger_data));
|
||||
ioc_status = readl(&mrioc->sysif_regs->ioc_status);
|
||||
if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) {
|
||||
mpi3mr_set_trigger_data_in_all_hdb(mrioc,
|
||||
MPI3MR_HDB_TRIGGER_TYPE_FW_RELEASED, NULL, 0);
|
||||
mpi3mr_soft_reset_handler(mrioc, MPI3MR_RESET_FROM_FIRMWARE, 0);
|
||||
return;
|
||||
}
|
||||
@ -2629,7 +2669,9 @@ static void mpi3mr_watchdog_work(struct work_struct *work)
|
||||
if (ioc_state != MRIOC_STATE_FAULT)
|
||||
goto schedule_work;
|
||||
|
||||
fault = readl(&mrioc->sysif_regs->fault) & MPI3_SYSIF_FAULT_CODE_MASK;
|
||||
trigger_data.fault = readl(&mrioc->sysif_regs->fault) & MPI3_SYSIF_FAULT_CODE_MASK;
|
||||
mpi3mr_set_trigger_data_in_all_hdb(mrioc,
|
||||
MPI3MR_HDB_TRIGGER_TYPE_FAULT, &trigger_data, 0);
|
||||
host_diagnostic = readl(&mrioc->sysif_regs->host_diagnostic);
|
||||
if (host_diagnostic & MPI3_SYSIF_HOST_DIAG_SAVE_IN_PROGRESS) {
|
||||
if (!mrioc->diagsave_timeout) {
|
||||
@ -2643,7 +2685,7 @@ static void mpi3mr_watchdog_work(struct work_struct *work)
|
||||
mpi3mr_print_fault_info(mrioc);
|
||||
mrioc->diagsave_timeout = 0;
|
||||
|
||||
switch (fault) {
|
||||
switch (trigger_data.fault) {
|
||||
case MPI3_SYSIF_FAULT_CODE_COMPLETE_RESET_NEEDED:
|
||||
case MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED:
|
||||
ioc_warn(mrioc,
|
||||
@ -3990,6 +4032,7 @@ static int mpi3mr_enable_events(struct mpi3mr_ioc *mrioc)
|
||||
mpi3mr_unmask_events(mrioc, MPI3_EVENT_PREPARE_FOR_RESET);
|
||||
mpi3mr_unmask_events(mrioc, MPI3_EVENT_CABLE_MGMT);
|
||||
mpi3mr_unmask_events(mrioc, MPI3_EVENT_ENERGY_PACK_CHANGE);
|
||||
mpi3mr_unmask_events(mrioc, MPI3_EVENT_DIAGNOSTIC_BUFFER_STATUS_CHANGE);
|
||||
|
||||
retval = mpi3mr_issue_event_notification(mrioc);
|
||||
if (retval)
|
||||
@ -4168,6 +4211,12 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc)
|
||||
goto out_failed;
|
||||
}
|
||||
|
||||
retval = mpi3mr_refresh_trigger(mrioc, MPI3_CONFIG_ACTION_READ_CURRENT);
|
||||
if (retval) {
|
||||
ioc_err(mrioc, "failed to refresh triggers\n");
|
||||
goto out_failed;
|
||||
}
|
||||
|
||||
ioc_info(mrioc, "controller initialization completed successfully\n");
|
||||
return retval;
|
||||
out_failed:
|
||||
@ -5106,6 +5155,7 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
|
||||
int retval = 0, i;
|
||||
unsigned long flags;
|
||||
u32 host_diagnostic, timeout = MPI3_SYSIF_DIAG_SAVE_TIMEOUT * 10;
|
||||
union mpi3mr_trigger_data trigger_data;
|
||||
|
||||
/* Block the reset handler until diag save in progress*/
|
||||
dprint_reset(mrioc,
|
||||
@ -5138,10 +5188,13 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
|
||||
mrioc->reset_in_progress = 1;
|
||||
mrioc->stop_bsgs = 1;
|
||||
mrioc->prev_reset_result = -1;
|
||||
memset(&trigger_data, 0, sizeof(trigger_data));
|
||||
|
||||
if ((!snapdump) && (reset_reason != MPI3MR_RESET_FROM_FAULT_WATCH) &&
|
||||
(reset_reason != MPI3MR_RESET_FROM_FIRMWARE) &&
|
||||
(reset_reason != MPI3MR_RESET_FROM_CIACTIV_FAULT)) {
|
||||
mpi3mr_set_trigger_data_in_all_hdb(mrioc,
|
||||
MPI3MR_HDB_TRIGGER_TYPE_SOFT_RESET, NULL, 0);
|
||||
dprint_reset(mrioc,
|
||||
"soft_reset_handler: releasing host diagnostic buffers\n");
|
||||
mpi3mr_release_diag_bufs(mrioc, 0);
|
||||
@ -5161,6 +5214,8 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
|
||||
retval = mpi3mr_issue_reset(mrioc,
|
||||
MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reset_reason);
|
||||
if (!retval) {
|
||||
trigger_data.fault = (readl(&mrioc->sysif_regs->fault) &
|
||||
MPI3_SYSIF_FAULT_CODE_MASK);
|
||||
do {
|
||||
host_diagnostic =
|
||||
readl(&mrioc->sysif_regs->host_diagnostic);
|
||||
@ -5169,6 +5224,8 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
|
||||
break;
|
||||
msleep(100);
|
||||
} while (--timeout);
|
||||
mpi3mr_set_trigger_data_in_all_hdb(mrioc,
|
||||
MPI3MR_HDB_TRIGGER_TYPE_FAULT, &trigger_data, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5205,6 +5262,14 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
|
||||
}
|
||||
mpi3mr_memset_buffers(mrioc);
|
||||
mpi3mr_release_diag_bufs(mrioc, 1);
|
||||
mrioc->fw_release_trigger_active = false;
|
||||
mrioc->trace_release_trigger_active = false;
|
||||
mrioc->snapdump_trigger_active = false;
|
||||
mpi3mr_set_trigger_data_in_all_hdb(mrioc,
|
||||
MPI3MR_HDB_TRIGGER_TYPE_SOFT_RESET, NULL, 0);
|
||||
|
||||
dprint_reset(mrioc,
|
||||
"soft_reset_handler: reinitializing the controller\n");
|
||||
retval = mpi3mr_reinit_ioc(mrioc, 0);
|
||||
if (retval) {
|
||||
pr_err(IOCNAME "reinit after soft reset failed: reason %d\n",
|
||||
|
@ -241,6 +241,40 @@ static void mpi3mr_fwevt_add_to_list(struct mpi3mr_ioc *mrioc,
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_hdb_trigger_data_event - Add hdb trigger data event to
|
||||
* the list
|
||||
* @mrioc: Adapter instance reference
|
||||
* @event_data: Event data
|
||||
*
|
||||
* Add the given hdb trigger data event to the firmware event
|
||||
* list.
|
||||
*
|
||||
* Return: Nothing.
|
||||
*/
|
||||
void mpi3mr_hdb_trigger_data_event(struct mpi3mr_ioc *mrioc,
|
||||
struct trigger_event_data *event_data)
|
||||
{
|
||||
struct mpi3mr_fwevt *fwevt;
|
||||
u16 sz = sizeof(*event_data);
|
||||
|
||||
fwevt = mpi3mr_alloc_fwevt(sz);
|
||||
if (!fwevt) {
|
||||
ioc_warn(mrioc, "failed to queue hdb trigger data event\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fwevt->mrioc = mrioc;
|
||||
fwevt->event_id = MPI3MR_DRIVER_EVENT_PROCESS_TRIGGER;
|
||||
fwevt->send_ack = 0;
|
||||
fwevt->process_evt = 1;
|
||||
fwevt->evt_ctx = 0;
|
||||
fwevt->event_data_size = sz;
|
||||
memcpy(fwevt->event_data, event_data, sz);
|
||||
|
||||
mpi3mr_fwevt_add_to_list(mrioc, fwevt);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_fwevt_del_from_list - Delete firmware event from list
|
||||
* @mrioc: Adapter instance reference
|
||||
@ -898,6 +932,8 @@ void mpi3mr_remove_tgtdev_from_host(struct mpi3mr_ioc *mrioc,
|
||||
}
|
||||
} else
|
||||
mpi3mr_remove_tgtdev_from_sas_transport(mrioc, tgtdev);
|
||||
mpi3mr_global_trigger(mrioc,
|
||||
MPI3_DRIVER2_GLOBALTRIGGER_DEVICE_REMOVAL_ENABLED);
|
||||
|
||||
ioc_info(mrioc, "%s :Removed handle(0x%04x), wwid(0x%016llx)\n",
|
||||
__func__, tgtdev->dev_handle, (unsigned long long)tgtdev->wwid);
|
||||
@ -1433,6 +1469,62 @@ struct mpi3mr_enclosure_node *mpi3mr_enclosure_find_by_handle(
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_process_trigger_data_event_bh - Process trigger event
|
||||
* data
|
||||
* @mrioc: Adapter instance reference
|
||||
* @event_data: Event data
|
||||
*
|
||||
* This function releases diage buffers or issues diag fault
|
||||
* based on trigger conditions
|
||||
*
|
||||
* Return: Nothing
|
||||
*/
|
||||
static void mpi3mr_process_trigger_data_event_bh(struct mpi3mr_ioc *mrioc,
|
||||
struct trigger_event_data *event_data)
|
||||
{
|
||||
struct diag_buffer_desc *trace_hdb = event_data->trace_hdb;
|
||||
struct diag_buffer_desc *fw_hdb = event_data->fw_hdb;
|
||||
unsigned long flags;
|
||||
int retval = 0;
|
||||
u8 trigger_type = event_data->trigger_type;
|
||||
union mpi3mr_trigger_data *trigger_data =
|
||||
&event_data->trigger_specific_data;
|
||||
|
||||
if (event_data->snapdump) {
|
||||
if (trace_hdb)
|
||||
mpi3mr_set_trigger_data_in_hdb(trace_hdb, trigger_type,
|
||||
trigger_data, 1);
|
||||
if (fw_hdb)
|
||||
mpi3mr_set_trigger_data_in_hdb(fw_hdb, trigger_type,
|
||||
trigger_data, 1);
|
||||
mpi3mr_soft_reset_handler(mrioc,
|
||||
MPI3MR_RESET_FROM_TRIGGER, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (trace_hdb) {
|
||||
retval = mpi3mr_issue_diag_buf_release(mrioc, trace_hdb);
|
||||
if (!retval) {
|
||||
mpi3mr_set_trigger_data_in_hdb(trace_hdb, trigger_type,
|
||||
trigger_data, 1);
|
||||
}
|
||||
spin_lock_irqsave(&mrioc->trigger_lock, flags);
|
||||
mrioc->trace_release_trigger_active = false;
|
||||
spin_unlock_irqrestore(&mrioc->trigger_lock, flags);
|
||||
}
|
||||
if (fw_hdb) {
|
||||
retval = mpi3mr_issue_diag_buf_release(mrioc, fw_hdb);
|
||||
if (!retval) {
|
||||
mpi3mr_set_trigger_data_in_hdb(fw_hdb, trigger_type,
|
||||
trigger_data, 1);
|
||||
}
|
||||
spin_lock_irqsave(&mrioc->trigger_lock, flags);
|
||||
mrioc->fw_release_trigger_active = false;
|
||||
spin_unlock_irqrestore(&mrioc->trigger_lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_encldev_add_chg_evt_debug - debug for enclosure event
|
||||
* @mrioc: Adapter instance reference
|
||||
@ -2019,6 +2111,12 @@ static void mpi3mr_fwevt_bh(struct mpi3mr_ioc *mrioc,
|
||||
"scan for non responding and newly added devices after soft reset completed\n");
|
||||
break;
|
||||
}
|
||||
case MPI3MR_DRIVER_EVENT_PROCESS_TRIGGER:
|
||||
{
|
||||
mpi3mr_process_trigger_data_event_bh(mrioc,
|
||||
(struct trigger_event_data *)fwevt->event_data);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -2857,6 +2955,7 @@ void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc,
|
||||
ack_req = 1;
|
||||
|
||||
evt_type = event_reply->event;
|
||||
mpi3mr_event_trigger(mrioc, event_reply->event);
|
||||
|
||||
switch (evt_type) {
|
||||
case MPI3_EVENT_DEVICE_ADDED:
|
||||
@ -2895,6 +2994,11 @@ void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc,
|
||||
ack_req = 0;
|
||||
break;
|
||||
}
|
||||
case MPI3_EVENT_DIAGNOSTIC_BUFFER_STATUS_CHANGE:
|
||||
{
|
||||
mpi3mr_hdbstatuschg_evt_th(mrioc, event_reply);
|
||||
break;
|
||||
}
|
||||
case MPI3_EVENT_DEVICE_INFO_CHANGED:
|
||||
case MPI3_EVENT_LOG_DATA:
|
||||
case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE:
|
||||
@ -3158,6 +3262,7 @@ void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc,
|
||||
MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL)
|
||||
ioc_loginfo = le32_to_cpu(status_desc->ioc_log_info);
|
||||
ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK;
|
||||
mpi3mr_reply_trigger(mrioc, ioc_status, ioc_loginfo);
|
||||
break;
|
||||
case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY:
|
||||
addr_desc = (struct mpi3_address_reply_descriptor *)reply_desc;
|
||||
@ -3186,6 +3291,12 @@ void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc,
|
||||
ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK;
|
||||
if (sense_state == MPI3_SCSI_STATE_SENSE_BUFF_Q_EMPTY)
|
||||
panic("%s: Ran out of sense buffers\n", mrioc->name);
|
||||
if (sense_buf) {
|
||||
scsi_normalize_sense(sense_buf, sense_count, &sshdr);
|
||||
mpi3mr_scsisense_trigger(mrioc, sshdr.sense_key,
|
||||
sshdr.asc, sshdr.ascq);
|
||||
}
|
||||
mpi3mr_reply_trigger(mrioc, ioc_status, ioc_loginfo);
|
||||
break;
|
||||
case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS:
|
||||
success_desc = (struct mpi3_success_reply_descriptor *)reply_desc;
|
||||
@ -3811,6 +3922,8 @@ int mpi3mr_issue_tm(struct mpi3mr_ioc *mrioc, u8 tm_type,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mpi3mr_global_trigger(mrioc,
|
||||
MPI3_DRIVER2_GLOBALTRIGGER_TASK_MANAGEMENT_ENABLED);
|
||||
|
||||
out_unlock:
|
||||
drv_cmd->state = MPI3MR_CMD_NOTUSED;
|
||||
|
Loading…
Reference in New Issue
Block a user