]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
scsi: mpt3sas: Add persistent Master trigger page
authorSuganath Prabu S <suganath-prabu.subramani@broadcom.com>
Thu, 26 Nov 2020 09:43:06 +0000 (15:13 +0530)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 9 Dec 2020 16:34:19 +0000 (11:34 -0500)
Trigger Page 1 is used to store information about Master triggers.  Below
are the Master trigger 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
instance's diag_trigger_master.MasterData with Persistent Trigger Page1's
MasterTriggerFlags.

Link: https://lore.kernel.org/r/20201126094311.8686-4-suganath-prabu.subramani@broadcom.com
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subramani@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/mpt3sas/mpt3sas_base.c
drivers/scsi/mpt3sas/mpt3sas_base.h
drivers/scsi/mpt3sas/mpt3sas_config.c

index 4ccfcb36da0b2c9813304948ff0198491fba667c..332d304eefc5577237facac6a4e5ecd448499ebf 100644 (file)
@@ -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);
 }
 
 /**
index 83b630852ed3beb623777286fd2dd42b085eb843..8215b0eb5e3f9f7c3b28a223e0a440d2bad98e27 100644 (file)
@@ -1822,6 +1822,12 @@ 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);
+int
+mpt3sas_config_update_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
+       struct SL_WH_MASTER_TRIGGER_T *master_tg, bool set);
 
 /* ctl shared API */
 extern struct device_attribute *mpt3sas_host_attrs[];
index 2fa60c2e0b8e8621b855c3b94c2db177c276db4e..9eff6fd3055f77dd4da044f3c470b36472f1bdee 100644 (file)
@@ -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.
+ */
+static 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
+ * @master_tg: Master trigger 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