mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-01 10:45:49 +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_DEFAULT_HDB_MIN_SZ (2 * 1024 * 1024)
|
||||||
#define MPI3MR_MAX_NUM_HDB 2
|
#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_GLOBAL 3
|
||||||
|
#define MPI3MR_HDB_TRIGGER_TYPE_SOFT_RESET 4
|
||||||
|
#define MPI3MR_HDB_TRIGGER_TYPE_FW_RELEASED 5
|
||||||
|
|
||||||
/* SGE Flag definition */
|
/* SGE Flag definition */
|
||||||
#define MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST \
|
#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_256_BLKS 256
|
||||||
#define MPI3MR_WRITE_SAME_MAX_LEN_2048_BLKS 2048
|
#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
|
* 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_FIRMWARE = 27,
|
||||||
MPI3MR_RESET_FROM_CFG_REQ_TIMEOUT = 29,
|
MPI3MR_RESET_FROM_CFG_REQ_TIMEOUT = 29,
|
||||||
MPI3MR_RESET_FROM_SAS_TRANSPORT_TIMEOUT = 30,
|
MPI3MR_RESET_FROM_SAS_TRANSPORT_TIMEOUT = 30,
|
||||||
|
MPI3MR_RESET_FROM_TRIGGER = 31,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MPI3MR_RESET_REASON_OSTYPE_LINUX 1
|
#define MPI3MR_RESET_REASON_OSTYPE_LINUX 1
|
||||||
@ -878,6 +885,24 @@ union mpi3mr_trigger_data {
|
|||||||
union mpi3_driver2_trigger_element element;
|
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
|
* struct diag_buffer_desc - memory descriptor structure to
|
||||||
* store virtual, dma addresses, size, buffer status for host
|
* 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_chain_sge: DMA buffer descriptor for IOCTL chain
|
||||||
* @ioctl_resp_sge: DMA buffer descriptor for Mgmt cmd response
|
* @ioctl_resp_sge: DMA buffer descriptor for Mgmt cmd response
|
||||||
* @ioctl_sges_allocated: Flag for IOCTL SGEs allocated or not
|
* @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 mpi3mr_ioc {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
@ -1310,6 +1338,9 @@ struct mpi3mr_ioc {
|
|||||||
struct diag_buffer_desc diag_buffers[MPI3MR_MAX_NUM_HDB];
|
struct diag_buffer_desc diag_buffers[MPI3MR_MAX_NUM_HDB];
|
||||||
struct mpi3_driver_page2 *driver_pg2;
|
struct mpi3_driver_page2 *driver_pg2;
|
||||||
spinlock_t trigger_lock;
|
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);
|
u8 buf_type);
|
||||||
int mpi3mr_issue_diag_buf_post(struct mpi3mr_ioc *mrioc,
|
int mpi3mr_issue_diag_buf_post(struct mpi3mr_ioc *mrioc,
|
||||||
struct diag_buffer_desc *diag_buffer);
|
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*/
|
#endif /*MPI3MR_H_INCLUDED*/
|
||||||
|
@ -316,6 +316,263 @@ int mpi3mr_issue_diag_buf_release(struct mpi3mr_ioc *mrioc,
|
|||||||
return retval;
|
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
|
* mpi3mr_get_num_trigger - Gets number of HDB triggers
|
||||||
* @mrioc: Adapter instance reference
|
* @mrioc: Adapter instance reference
|
||||||
@ -449,7 +706,7 @@ void mpi3mr_release_diag_bufs(struct mpi3mr_ioc *mrioc, u8 skip_rel_action)
|
|||||||
* @type: Trigger type
|
* @type: Trigger type
|
||||||
* @data: Trigger data
|
* @data: Trigger data
|
||||||
* @force: Trigger overwrite flag
|
* @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
|
* Updates trigger type and trigger data based on parameter
|
||||||
* passed to this function
|
* 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));
|
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
|
* mpi3mr_diag_buffer_for_type - returns buffer desc for type
|
||||||
* @mrioc: Adapter instance reference
|
* @mrioc: Adapter instance reference
|
||||||
|
@ -274,6 +274,9 @@ static void mpi3mr_print_event_data(struct mpi3mr_ioc *mrioc,
|
|||||||
case MPI3_EVENT_PREPARE_FOR_RESET:
|
case MPI3_EVENT_PREPARE_FOR_RESET:
|
||||||
desc = "Prepare For Reset";
|
desc = "Prepare For Reset";
|
||||||
break;
|
break;
|
||||||
|
case MPI3_EVENT_DIAGNOSTIC_BUFFER_STATUS_CHANGE:
|
||||||
|
desc = "Diagnostic Buffer Status Change";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!desc)
|
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 reply_desc_type, host_tag = 0;
|
||||||
u16 ioc_status = MPI3_IOCSTATUS_SUCCESS;
|
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_status_reply_descriptor *status_desc;
|
||||||
struct mpi3_address_reply_descriptor *addr_desc;
|
struct mpi3_address_reply_descriptor *addr_desc;
|
||||||
struct mpi3_success_reply_descriptor *success_desc;
|
struct mpi3_success_reply_descriptor *success_desc;
|
||||||
struct mpi3_default_reply *def_reply = NULL;
|
struct mpi3_default_reply *def_reply = NULL;
|
||||||
struct mpi3mr_drv_cmd *cmdptr = NULL;
|
struct mpi3mr_drv_cmd *cmdptr = NULL;
|
||||||
struct mpi3_scsi_io_reply *scsi_reply;
|
struct mpi3_scsi_io_reply *scsi_reply;
|
||||||
|
struct scsi_sense_hdr sshdr;
|
||||||
u8 *sense_buf = NULL;
|
u8 *sense_buf = NULL;
|
||||||
|
|
||||||
*reply_dma = 0;
|
*reply_dma = 0;
|
||||||
@ -363,6 +367,7 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_ioc *mrioc,
|
|||||||
MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL)
|
MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL)
|
||||||
ioc_loginfo = le32_to_cpu(status_desc->ioc_log_info);
|
ioc_loginfo = le32_to_cpu(status_desc->ioc_log_info);
|
||||||
ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK;
|
ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK;
|
||||||
|
mpi3mr_reply_trigger(mrioc, ioc_status, ioc_loginfo);
|
||||||
break;
|
break;
|
||||||
case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY:
|
case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY:
|
||||||
addr_desc = (struct mpi3_address_reply_descriptor *)reply_desc;
|
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;
|
scsi_reply = (struct mpi3_scsi_io_reply *)def_reply;
|
||||||
sense_buf = mpi3mr_get_sensebuf_virt_addr(mrioc,
|
sense_buf = mpi3mr_get_sensebuf_virt_addr(mrioc,
|
||||||
le64_to_cpu(scsi_reply->sense_data_buffer_address));
|
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;
|
break;
|
||||||
case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS:
|
case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS:
|
||||||
success_desc = (struct mpi3_success_reply_descriptor *)reply_desc;
|
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, "sysfs invocation" },
|
||||||
{ MPI3MR_RESET_FROM_SYSFS_TIMEOUT, "sysfs TM timeout" },
|
{ 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_FIRMWARE, "firmware asynchronous reset" },
|
||||||
{ MPI3MR_RESET_FROM_CFG_REQ_TIMEOUT, "configuration request timeout"},
|
{ MPI3MR_RESET_FROM_CFG_REQ_TIMEOUT, "configuration request timeout"},
|
||||||
{ MPI3MR_RESET_FROM_SAS_TRANSPORT_TIMEOUT, "timeout of a SAS transport layer request" },
|
{ 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)
|
void mpi3mr_check_rh_fault_ioc(struct mpi3mr_ioc *mrioc, u32 reason_code)
|
||||||
{
|
{
|
||||||
u32 ioc_status, host_diagnostic, timeout;
|
u32 ioc_status, host_diagnostic, timeout;
|
||||||
|
union mpi3mr_trigger_data trigger_data;
|
||||||
|
|
||||||
if (mrioc->unrecoverable) {
|
if (mrioc->unrecoverable) {
|
||||||
ioc_err(mrioc, "controller is unrecoverable\n");
|
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");
|
ioc_err(mrioc, "controller is not present\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
memset(&trigger_data, 0, sizeof(trigger_data));
|
||||||
ioc_status = readl(&mrioc->sysif_regs->ioc_status);
|
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);
|
mpi3mr_print_fault_info(mrioc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mpi3mr_set_diagsave(mrioc);
|
mpi3mr_set_diagsave(mrioc);
|
||||||
mpi3mr_issue_reset(mrioc, MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT,
|
mpi3mr_issue_reset(mrioc, MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT,
|
||||||
reason_code);
|
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;
|
timeout = MPI3_SYSIF_DIAG_SAVE_TIMEOUT * 10;
|
||||||
do {
|
do {
|
||||||
host_diagnostic = readl(&mrioc->sysif_regs->host_diagnostic);
|
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);
|
container_of(work, struct mpi3mr_ioc, watchdog_work.work);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
enum mpi3mr_iocstate ioc_state;
|
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;
|
u16 reset_reason = MPI3MR_RESET_FROM_FAULT_WATCH;
|
||||||
|
|
||||||
if (mrioc->reset_in_progress)
|
if (mrioc->reset_in_progress)
|
||||||
@ -2618,8 +2655,11 @@ static void mpi3mr_watchdog_work(struct work_struct *work)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(&trigger_data, 0, sizeof(trigger_data));
|
||||||
ioc_status = readl(&mrioc->sysif_regs->ioc_status);
|
ioc_status = readl(&mrioc->sysif_regs->ioc_status);
|
||||||
if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) {
|
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);
|
mpi3mr_soft_reset_handler(mrioc, MPI3MR_RESET_FROM_FIRMWARE, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2629,7 +2669,9 @@ static void mpi3mr_watchdog_work(struct work_struct *work)
|
|||||||
if (ioc_state != MRIOC_STATE_FAULT)
|
if (ioc_state != MRIOC_STATE_FAULT)
|
||||||
goto schedule_work;
|
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);
|
host_diagnostic = readl(&mrioc->sysif_regs->host_diagnostic);
|
||||||
if (host_diagnostic & MPI3_SYSIF_HOST_DIAG_SAVE_IN_PROGRESS) {
|
if (host_diagnostic & MPI3_SYSIF_HOST_DIAG_SAVE_IN_PROGRESS) {
|
||||||
if (!mrioc->diagsave_timeout) {
|
if (!mrioc->diagsave_timeout) {
|
||||||
@ -2643,7 +2685,7 @@ static void mpi3mr_watchdog_work(struct work_struct *work)
|
|||||||
mpi3mr_print_fault_info(mrioc);
|
mpi3mr_print_fault_info(mrioc);
|
||||||
mrioc->diagsave_timeout = 0;
|
mrioc->diagsave_timeout = 0;
|
||||||
|
|
||||||
switch (fault) {
|
switch (trigger_data.fault) {
|
||||||
case MPI3_SYSIF_FAULT_CODE_COMPLETE_RESET_NEEDED:
|
case MPI3_SYSIF_FAULT_CODE_COMPLETE_RESET_NEEDED:
|
||||||
case MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED:
|
case MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED:
|
||||||
ioc_warn(mrioc,
|
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_PREPARE_FOR_RESET);
|
||||||
mpi3mr_unmask_events(mrioc, MPI3_EVENT_CABLE_MGMT);
|
mpi3mr_unmask_events(mrioc, MPI3_EVENT_CABLE_MGMT);
|
||||||
mpi3mr_unmask_events(mrioc, MPI3_EVENT_ENERGY_PACK_CHANGE);
|
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);
|
retval = mpi3mr_issue_event_notification(mrioc);
|
||||||
if (retval)
|
if (retval)
|
||||||
@ -4168,6 +4211,12 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc)
|
|||||||
goto out_failed;
|
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");
|
ioc_info(mrioc, "controller initialization completed successfully\n");
|
||||||
return retval;
|
return retval;
|
||||||
out_failed:
|
out_failed:
|
||||||
@ -5106,6 +5155,7 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
|
|||||||
int retval = 0, i;
|
int retval = 0, i;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
u32 host_diagnostic, timeout = MPI3_SYSIF_DIAG_SAVE_TIMEOUT * 10;
|
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*/
|
/* Block the reset handler until diag save in progress*/
|
||||||
dprint_reset(mrioc,
|
dprint_reset(mrioc,
|
||||||
@ -5138,10 +5188,13 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
|
|||||||
mrioc->reset_in_progress = 1;
|
mrioc->reset_in_progress = 1;
|
||||||
mrioc->stop_bsgs = 1;
|
mrioc->stop_bsgs = 1;
|
||||||
mrioc->prev_reset_result = -1;
|
mrioc->prev_reset_result = -1;
|
||||||
|
memset(&trigger_data, 0, sizeof(trigger_data));
|
||||||
|
|
||||||
if ((!snapdump) && (reset_reason != MPI3MR_RESET_FROM_FAULT_WATCH) &&
|
if ((!snapdump) && (reset_reason != MPI3MR_RESET_FROM_FAULT_WATCH) &&
|
||||||
(reset_reason != MPI3MR_RESET_FROM_FIRMWARE) &&
|
(reset_reason != MPI3MR_RESET_FROM_FIRMWARE) &&
|
||||||
(reset_reason != MPI3MR_RESET_FROM_CIACTIV_FAULT)) {
|
(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,
|
dprint_reset(mrioc,
|
||||||
"soft_reset_handler: releasing host diagnostic buffers\n");
|
"soft_reset_handler: releasing host diagnostic buffers\n");
|
||||||
mpi3mr_release_diag_bufs(mrioc, 0);
|
mpi3mr_release_diag_bufs(mrioc, 0);
|
||||||
@ -5161,6 +5214,8 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
|
|||||||
retval = mpi3mr_issue_reset(mrioc,
|
retval = mpi3mr_issue_reset(mrioc,
|
||||||
MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reset_reason);
|
MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reset_reason);
|
||||||
if (!retval) {
|
if (!retval) {
|
||||||
|
trigger_data.fault = (readl(&mrioc->sysif_regs->fault) &
|
||||||
|
MPI3_SYSIF_FAULT_CODE_MASK);
|
||||||
do {
|
do {
|
||||||
host_diagnostic =
|
host_diagnostic =
|
||||||
readl(&mrioc->sysif_regs->host_diagnostic);
|
readl(&mrioc->sysif_regs->host_diagnostic);
|
||||||
@ -5169,6 +5224,8 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
|
|||||||
break;
|
break;
|
||||||
msleep(100);
|
msleep(100);
|
||||||
} while (--timeout);
|
} 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_memset_buffers(mrioc);
|
||||||
mpi3mr_release_diag_bufs(mrioc, 1);
|
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);
|
retval = mpi3mr_reinit_ioc(mrioc, 0);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
pr_err(IOCNAME "reinit after soft reset failed: reason %d\n",
|
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);
|
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
|
* mpi3mr_fwevt_del_from_list - Delete firmware event from list
|
||||||
* @mrioc: Adapter instance reference
|
* @mrioc: Adapter instance reference
|
||||||
@ -898,6 +932,8 @@ void mpi3mr_remove_tgtdev_from_host(struct mpi3mr_ioc *mrioc,
|
|||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
mpi3mr_remove_tgtdev_from_sas_transport(mrioc, tgtdev);
|
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",
|
ioc_info(mrioc, "%s :Removed handle(0x%04x), wwid(0x%016llx)\n",
|
||||||
__func__, tgtdev->dev_handle, (unsigned long long)tgtdev->wwid);
|
__func__, tgtdev->dev_handle, (unsigned long long)tgtdev->wwid);
|
||||||
@ -1433,6 +1469,62 @@ struct mpi3mr_enclosure_node *mpi3mr_enclosure_find_by_handle(
|
|||||||
return r;
|
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
|
* mpi3mr_encldev_add_chg_evt_debug - debug for enclosure event
|
||||||
* @mrioc: Adapter instance reference
|
* @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");
|
"scan for non responding and newly added devices after soft reset completed\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MPI3MR_DRIVER_EVENT_PROCESS_TRIGGER:
|
||||||
|
{
|
||||||
|
mpi3mr_process_trigger_data_event_bh(mrioc,
|
||||||
|
(struct trigger_event_data *)fwevt->event_data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2857,6 +2955,7 @@ void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc,
|
|||||||
ack_req = 1;
|
ack_req = 1;
|
||||||
|
|
||||||
evt_type = event_reply->event;
|
evt_type = event_reply->event;
|
||||||
|
mpi3mr_event_trigger(mrioc, event_reply->event);
|
||||||
|
|
||||||
switch (evt_type) {
|
switch (evt_type) {
|
||||||
case MPI3_EVENT_DEVICE_ADDED:
|
case MPI3_EVENT_DEVICE_ADDED:
|
||||||
@ -2895,6 +2994,11 @@ void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc,
|
|||||||
ack_req = 0;
|
ack_req = 0;
|
||||||
break;
|
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_DEVICE_INFO_CHANGED:
|
||||||
case MPI3_EVENT_LOG_DATA:
|
case MPI3_EVENT_LOG_DATA:
|
||||||
case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE:
|
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)
|
MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL)
|
||||||
ioc_loginfo = le32_to_cpu(status_desc->ioc_log_info);
|
ioc_loginfo = le32_to_cpu(status_desc->ioc_log_info);
|
||||||
ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK;
|
ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK;
|
||||||
|
mpi3mr_reply_trigger(mrioc, ioc_status, ioc_loginfo);
|
||||||
break;
|
break;
|
||||||
case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY:
|
case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY:
|
||||||
addr_desc = (struct mpi3_address_reply_descriptor *)reply_desc;
|
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;
|
ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK;
|
||||||
if (sense_state == MPI3_SCSI_STATE_SENSE_BUFF_Q_EMPTY)
|
if (sense_state == MPI3_SCSI_STATE_SENSE_BUFF_Q_EMPTY)
|
||||||
panic("%s: Ran out of sense buffers\n", mrioc->name);
|
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;
|
break;
|
||||||
case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS:
|
case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS:
|
||||||
success_desc = (struct mpi3_success_reply_descriptor *)reply_desc;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
mpi3mr_global_trigger(mrioc,
|
||||||
|
MPI3_DRIVER2_GLOBALTRIGGER_TASK_MANAGEMENT_ENABLED);
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
drv_cmd->state = MPI3MR_CMD_NOTUSED;
|
drv_cmd->state = MPI3MR_CMD_NOTUSED;
|
||||||
|
Loading…
Reference in New Issue
Block a user