Commit aec93e8e authored by Suganath Prabu S's avatar Suganath Prabu S Committed by Martin K. Petersen

scsi: mpt3sas: Add persistent trigger pages support

The user can set trigger values in order to collect the IOC's host trace
buffer automatically upon detecting certain conditions. However, the
trigger values that the user sets are not persistent across system reboot
or reload of the driver.

In order to make the user trigger settings persistent, these trigger values
need to be saved in the IOC's NVRAM pages:

 - Driver Persistent Trigger Page 0:
     This page is used to store list of trigger types that are enabled

 - Driver Persistent Trigger Page 1:
     This page stores the list of Master triggers that are enabled

 - Driver Persistent Trigger Page 2:
     This page stores the list of MPI Event Triggers that are enabled

 - Driver Persistent Trigger Page 3:
     This page stores the list of SCSI Sense Triggers that are enabled

 - Driver Persistent Trigger Page 4:
     This page stores the list of IOCStatus-LogInfo Triggers that are
     enabled.

Whenever user configures triggers, the driver persists the values in the
corresponding trigger pages. When the driver is subsequently reloaded, the
driver reads the values from the trigger pages and configures the triggers
accordingly.

During firmware upload operation, if the newer firmware supports the
trigger page feature, then driver persists the configured diag trigger
values to NVRAM.

Link: https://lore.kernel.org/r/20201126094311.8686-3-suganath-prabu.subramani@broadcom.comReported-by: default avatarkernel test robot <lkp@intel.com>
Signed-off-by: default avatarSuganath Prabu S <suganath-prabu.subramani@broadcom.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent f98790c0
......@@ -975,6 +975,20 @@ _base_sas_ioc_info(struct MPT3SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply,
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
return;
/*
* Older Firmware version doesn't support driver trigger pages.
* So, skip displaying 'config invalid type' type
* of error message.
*/
if (request_hdr->Function == MPI2_FUNCTION_CONFIG) {
Mpi2ConfigRequest_t *rqst = (Mpi2ConfigRequest_t *)request_hdr;
if ((rqst->ExtPageType ==
MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER) &&
!(ioc->logging_level & MPT_DEBUG_CONFIG)) {
return;
}
}
switch (ioc_status) {
......@@ -4783,6 +4797,58 @@ _base_update_ioc_page1_inlinewith_perf_mode(struct MPT3SAS_ADAPTER *ioc)
}
}
/**
* _base_check_for_trigger_pages_support - checks whether HBA FW supports
* driver trigger pages or not
* @ioc : per adapter object
*
* Returns trigger flags mask if HBA FW supports driver trigger pages,
* otherwise returns EFAULT.
*/
static int
_base_check_for_trigger_pages_support(struct MPT3SAS_ADAPTER *ioc)
{
Mpi26DriverTriggerPage0_t trigger_pg0;
int r = 0;
Mpi2ConfigReply_t mpi_reply;
u16 ioc_status;
r = mpt3sas_config_get_driver_trigger_pg0(ioc, &mpi_reply,
&trigger_pg0);
if (r)
return -EFAULT;
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
return -EFAULT;
return le16_to_cpu(trigger_pg0.TriggerFlags);
}
/**
* _base_get_diag_triggers - Retrieve diag trigger values from
* persistent pages.
* @ioc : per adapter object
*
* Return nothing.
*/
static void
_base_get_diag_triggers(struct MPT3SAS_ADAPTER *ioc)
{
u16 trigger_flags;
/*
* Default setting of master trigger.
*/
ioc->diag_trigger_master.MasterData =
(MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET);
trigger_flags = _base_check_for_trigger_pages_support(ioc);
if (trigger_flags < 0)
return;
ioc->supports_trigger_pages = 1;
}
/**
* _base_static_config_pages - static start of day config pages
* @ioc: per adapter object
......@@ -4869,6 +4935,10 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
ioc->temp_sensors_count = ioc->iounit_pg8.NumSensors;
if (ioc->is_aero_ioc)
_base_update_ioc_page1_inlinewith_perf_mode(ioc);
if (ioc->is_gen35_ioc) {
if (ioc->is_driver_loading)
_base_get_diag_triggers(ioc);
}
}
/**
......
......@@ -71,6 +71,7 @@
#include "mpt3sas_debug.h"
#include "mpt3sas_trigger_diag.h"
#include "mpt3sas_trigger_pages.h"
/* driver versioning info */
#define MPT3SAS_DRIVER_NAME "mpt3sas"
......@@ -1541,6 +1542,7 @@ struct MPT3SAS_ADAPTER {
struct SL_WH_EVENT_TRIGGERS_T diag_trigger_event;
struct SL_WH_SCSI_TRIGGERS_T diag_trigger_scsi;
struct SL_WH_MPI_TRIGGERS_T diag_trigger_mpi;
u8 supports_trigger_pages;
void *device_remove_in_progress;
u16 device_remove_in_progress_sz;
u8 is_gen35_ioc;
......@@ -1817,6 +1819,9 @@ int mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
u16 *volume_handle);
int mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc,
u16 volume_handle, u64 *wwid);
int
mpt3sas_config_get_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page);
/* ctl shared API */
extern struct device_attribute *mpt3sas_host_attrs[];
......
......@@ -1742,6 +1742,140 @@ mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
return r;
}
/**
* mpt3sas_config_get_driver_trigger_pg0 - obtain driver trigger page 0
* @ioc: per adapter object
* @mpi_reply: reply mf payload returned from firmware
* @config_page: contents of the config page
* Context: sleep.
*
* Returns 0 for success, non-zero for failure.
*/
int
mpt3sas_config_get_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page)
{
Mpi2ConfigRequest_t mpi_request;
int r;
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
mpi_request.ExtPageType =
MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
mpi_request.Header.PageNumber = 0;
mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION;
ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
r = _config_request(ioc, &mpi_request, mpi_reply,
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
if (r)
goto out;
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
r = _config_request(ioc, &mpi_request, mpi_reply,
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
sizeof(*config_page));
out:
return r;
}
/**
* mpt3sas_config_set_driver_trigger_pg0 - write driver trigger page 0
* @ioc: per adapter object
* @mpi_reply: reply mf payload returned from firmware
* @config_page: contents of the config page
* Context: sleep.
*
* Returns 0 for success, non-zero for failure.
*/
static int
_config_set_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page)
{
Mpi2ConfigRequest_t mpi_request;
int r;
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
mpi_request.ExtPageType =
MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
mpi_request.Header.PageNumber = 0;
mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION;
ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
r = _config_request(ioc, &mpi_request, mpi_reply,
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
if (r)
goto out;
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
_config_request(ioc, &mpi_request, mpi_reply,
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
sizeof(*config_page));
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
r = _config_request(ioc, &mpi_request, mpi_reply,
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
sizeof(*config_page));
out:
return r;
}
/**
* mpt3sas_config_update_driver_trigger_pg0 - update driver trigger page 0
* @ioc: per adapter object
* @trigger_flag: trigger type bit map
* @set: set ot clear trigger values
* Context: sleep.
*
* Returns 0 for success, non-zero for failure.
*/
static int
mpt3sas_config_update_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
u16 trigger_flag, bool set)
{
Mpi26DriverTriggerPage0_t tg_pg0;
Mpi2ConfigReply_t mpi_reply;
int rc;
u16 flags, ioc_status;
rc = mpt3sas_config_get_driver_trigger_pg0(ioc, &mpi_reply, &tg_pg0);
if (rc)
return rc;
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
dcprintk(ioc,
ioc_err(ioc,
"%s: Failed to get trigger pg0, ioc_status(0x%04x)\n",
__func__, ioc_status));
return -EFAULT;
}
if (set)
flags = le16_to_cpu(tg_pg0.TriggerFlags) | trigger_flag;
else
flags = le16_to_cpu(tg_pg0.TriggerFlags) & ~trigger_flag;
tg_pg0.TriggerFlags = cpu_to_le16(flags);
rc = _config_set_driver_trigger_pg0(ioc, &mpi_reply, &tg_pg0);
if (rc)
return rc;
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
dcprintk(ioc,
ioc_err(ioc,
"%s: Failed to update trigger pg0, ioc_status(0x%04x)\n",
__func__, ioc_status));
return -EFAULT;
}
return 0;
}
/**
* mpt3sas_config_get_volume_handle - returns volume handle for give hidden
* raid components
......
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* This is the Fusion MPT base driver providing common API layer interface
* to store diag trigger values into persistent driver triggers pages
* for MPT (Message Passing Technology) based controllers.
*
* Copyright (C) 2020 Broadcom Inc.
*
* Authors: Broadcom Inc.
* Sreekanth Reddy <sreekanth.reddy@broadcom.com>
*
* Send feedback to : MPT-FusionLinux.pdl@broadcom.com)
*/
#include "mpi/mpi2_cnfg.h"
#ifndef MPI2_TRIGGER_PAGES_H
#define MPI2_TRIGGER_PAGES_H
#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER (0xE0)
#define MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION (0x01)
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_0 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
U16 TriggerFlags; /* 0x08 */
U16 Reserved0xA; /* 0x0A */
U32 Reserved0xC[61]; /* 0x0C */
} _MPI26_CONFIG_PAGE_DRIVER_TIGGER_0, Mpi26DriverTriggerPage0_t;
/* Trigger Flags */
#define MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID (0x0001)
#define MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID (0x0002)
#define MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID (0x0004)
#define MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID (0x0008)
#define MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION (0x01)
typedef struct _MPI26_DRIVER_MASTER_TIGGER_ENTRY {
U32 MasterTriggerFlags;
} MPI26_DRIVER_MASTER_TIGGER_ENTRY;
#define MPI26_MAX_MASTER_TRIGGERS (1)
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_1 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
U16 NumMasterTrigger; /* 0x08 */
U16 Reserved0xA; /* 0x0A */
MPI26_DRIVER_MASTER_TIGGER_ENTRY MasterTriggers[MPI26_MAX_MASTER_TRIGGERS]; /* 0x0C */
} MPI26_CONFIG_PAGE_DRIVER_TIGGER_1, Mpi26DriverTriggerPage1_t;
#define MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION (0x01)
typedef struct _MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY {
U16 MPIEventCode; /* 0x00 */
U16 MPIEventCodeSpecific; /* 0x02 */
} MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY;
#define MPI26_MAX_MPI_EVENT_TRIGGERS (20)
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_2 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
U16 NumMPIEventTrigger; /* 0x08 */
U16 Reserved0xA; /* 0x0A */
MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY MPIEventTriggers[MPI26_MAX_MPI_EVENT_TRIGGERS]; /* 0x0C */
} MPI26_CONFIG_PAGE_DRIVER_TIGGER_2, Mpi26DriverTriggerPage2_t;
#define MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION (0x01)
typedef struct _MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY {
U8 ASCQ; /* 0x00 */
U8 ASC; /* 0x01 */
U8 SenseKey; /* 0x02 */
U8 Reserved; /* 0x03 */
} MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY;
#define MPI26_MAX_SCSI_SENSE_TRIGGERS (20)
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_3 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
U16 NumSCSISenseTrigger; /* 0x08 */
U16 Reserved0xA; /* 0x0A */
MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY SCSISenseTriggers[MPI26_MAX_SCSI_SENSE_TRIGGERS]; /* 0x0C */
} MPI26_CONFIG_PAGE_DRIVER_TIGGER_3, Mpi26DriverTriggerPage3_t;
#define MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION (0x01)
typedef struct _MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY {
U16 IOCStatus; /* 0x00 */
U16 Reserved; /* 0x02 */
U32 LogInfo; /* 0x04 */
} MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY;
#define MPI26_MAX_LOGINFO_TRIGGERS (20)
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_4 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
U16 NumIOCStatusLogInfoTrigger; /* 0x08 */
U16 Reserved0xA; /* 0x0A */
MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY IOCStatusLoginfoTriggers[MPI26_MAX_LOGINFO_TRIGGERS]; /* 0x0C */
} MPI26_CONFIG_PAGE_DRIVER_TIGGER_4, Mpi26DriverTriggerPage4_t;
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment