@@ -4797,6 +4797,42 @@ _base_update_ioc_page1_inlinewith_perf_mode(struct MPT3SAS_ADAPTER *ioc)
}
}
+/**
+ * _base_get_master_diag_triggers - get master diag trigger values from
+ * persistent pages
+ * @ioc : per adapter object
+ *
+ * Return nothing.
+ */
+static void
+_base_get_master_diag_triggers(struct MPT3SAS_ADAPTER *ioc)
+{
+ Mpi26DriverTriggerPage1_t trigger_pg1;
+ Mpi2ConfigReply_t mpi_reply;
+ int r;
+ u16 ioc_status;
+
+ r = mpt3sas_config_get_driver_trigger_pg1(ioc, &mpi_reply,
+ &trigger_pg1);
+ if (r)
+ return;
+
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ dinitprintk(ioc,
+ ioc_err(ioc,
+ "%s: Failed to get trigger pg1, ioc_status(0x%04x)\n",
+ __func__, ioc_status));
+ return;
+ }
+
+ if (le16_to_cpu(trigger_pg1.NumMasterTrigger))
+ ioc->diag_trigger_master.MasterData |=
+ le32_to_cpu(
+ trigger_pg1.MasterTriggers[0].MasterTriggerFlags);
+}
+
/**
* _base_check_for_trigger_pages_support - checks whether HBA FW supports
* driver trigger pages or not
@@ -4843,10 +4879,20 @@ _base_get_diag_triggers(struct MPT3SAS_ADAPTER *ioc)
*/
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;
+
+ /*
+ * Retrieve master diag trigger values from driver trigger pg1
+ * if master trigger bit enabled in TriggerFlags.
+ */
+ if ((u16)trigger_flags &
+ MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID)
+ _base_get_master_diag_triggers(ioc);
}
/**
@@ -1822,6 +1822,9 @@ int mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc,
int
mpt3sas_config_get_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page);
+int
+mpt3sas_config_get_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
+ Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page);
/* ctl shared API */
extern struct device_attribute *mpt3sas_host_attrs[];
@@ -1876,6 +1876,157 @@ mpt3sas_config_update_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
return 0;
}
+/**
+ * mpt3sas_config_get_driver_trigger_pg1 - obtain driver trigger page 1
+ * @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_pg1(struct MPT3SAS_ADAPTER *ioc,
+ Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_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 = 1;
+ mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE1_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_pg1 - write driver trigger page 1
+ * @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
+_config_set_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
+ Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_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 = 1;
+ mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE1_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_pg1 - update driver trigger page 1
+ * @ioc: per adapter object
+ * @trigger_flags: trigger type bit map
+ * @set: set ot clear trigger values
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_update_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
+ struct SL_WH_MASTER_TRIGGER_T *master_tg, bool set)
+{
+ Mpi26DriverTriggerPage1_t tg_pg1;
+ Mpi2ConfigReply_t mpi_reply;
+ int rc;
+ u16 ioc_status;
+
+ rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
+ MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID, set);
+ if (rc)
+ return rc;
+
+ rc = mpt3sas_config_get_driver_trigger_pg1(ioc, &mpi_reply, &tg_pg1);
+ if (rc)
+ goto out;
+
+ 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 pg1, ioc_status(0x%04x)\n",
+ __func__, ioc_status));
+ rc = -EFAULT;
+ goto out;
+ }
+
+ if (set) {
+ tg_pg1.NumMasterTrigger = cpu_to_le16(1);
+ tg_pg1.MasterTriggers[0].MasterTriggerFlags = cpu_to_le32(
+ master_tg->MasterData);
+ } else {
+ tg_pg1.NumMasterTrigger = 0;
+ tg_pg1.MasterTriggers[0].MasterTriggerFlags = 0;
+ }
+
+ rc = _config_set_driver_trigger_pg1(ioc, &mpi_reply, &tg_pg1);
+ if (rc)
+ goto out;
+
+ 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 pg1, ioc_status(0x%04x)\n",
+ __func__, ioc_status));
+ rc = -EFAULT;
+ goto out;
+ }
+
+ return 0;
+
+out:
+ mpt3sas_config_update_driver_trigger_pg0(ioc,
+ MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID, !set);
+
+ return rc;
+}
+
/**
* mpt3sas_config_get_volume_handle - returns volume handle for give hidden
* raid components
Description: Trigger Page 1 is used store information about master triggers. Below are the master triggers conditions. Bit[3] Trigger condition for Device Removal event Bit[2] Trigger condition for TM command issued by driver Bit[1] Trigger condition for Adapter reset issued by driver Bit[0] Trigger condition for IOC Fault state During driver load: If Master trigger type bit is enabled in the Persistent Trigger Page0 then read the Persistent Trigger Page1 and update the ioc instances diag_trigger_master.MasterData with Persistent Trigger Page1's MasterTriggerFlags. This will restores the Master trigger type's triggers which are enabled before. When user modifies the Master trigger type triggers: When user sets/clears the Master trigger type triggers then driver fisrt checks whether IOC firmware supports trigger pages support or not. if firmware supports these pages then driver enables the Master trigger type bit in Persistent Trigger Page0 (if it was not enabled before) and updates the user provided trigger values in Persistent Trigger Page1. Signed-off-by: Suganath Prabu S <suganath-prabu.subramani@broadcom.com> --- drivers/scsi/mpt3sas/mpt3sas_base.c | 46 ++++++++ drivers/scsi/mpt3sas/mpt3sas_base.h | 3 + drivers/scsi/mpt3sas/mpt3sas_config.c | 151 ++++++++++++++++++++++++++ 3 files changed, 200 insertions(+)