From: Kevin Barnett <kevin.barn...@hpe.com>

put in SIS mode during initialization.
support kexec/kdump

Reviewed-by: Scott Benesh <scott.ben...@microsemi.com>
Reviewed-by: Scott Teel <scott.t...@microsemi.com>
Signed-off-by: Kevin Barnett <kevin.barn...@microsemi.com>
Signed-off-by: Don Brace <don.br...@microsemi.com>
---
 drivers/scsi/smartpqi/smartpqi.h      |    2 +
 drivers/scsi/smartpqi/smartpqi_init.c |   60 +++++++++++++++++++--------------
 drivers/scsi/smartpqi/smartpqi_sis.c  |    6 +++
 drivers/scsi/smartpqi/smartpqi_sis.h  |    1 +
 4 files changed, 42 insertions(+), 27 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index 73754ca..62045c1 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -964,7 +964,7 @@ struct pqi_ctrl_info {
 };
 
 enum pqi_ctrl_mode {
-       UNKNOWN,
+       SIS_MODE = 0,
        PQI_MODE
 };
 
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 14d74e1..5a5b9ab 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -5245,38 +5245,50 @@ static int pqi_get_ctrl_firmware_version(struct 
pqi_ctrl_info *ctrl_info)
        return rc;
 }
 
-static int pqi_kdump_init(struct pqi_ctrl_info *ctrl_info)
+/* Switches the controller from PQI mode back into SIS mode. */
+
+static int pqi_revert_to_sis_mode(struct pqi_ctrl_info *ctrl_info)
+{
+       int rc;
+
+       sis_disable_msix(ctrl_info);
+       rc = pqi_reset(ctrl_info);
+       if (rc)
+               return rc;
+       sis_reenable_sis_mode(ctrl_info);
+       pqi_save_ctrl_mode(ctrl_info, SIS_MODE);
+
+       return 0;
+}
+
+/*
+ * If the controller isn't already in SIS mode, this function forces it into
+ * SIS mode.
+ */
+
+static int pqi_force_sis_mode(struct pqi_ctrl_info *ctrl_info)
 {
        if (!sis_is_firmware_running(ctrl_info))
                return -ENXIO;
 
-       if (pqi_get_ctrl_mode(ctrl_info) == PQI_MODE) {
-               sis_disable_msix(ctrl_info);
-               if (pqi_reset(ctrl_info) == 0)
-                       sis_reenable_sis_mode(ctrl_info);
+       if (pqi_get_ctrl_mode(ctrl_info) == SIS_MODE)
+               return 0;
+
+       if (sis_is_kernel_up(ctrl_info)) {
+               pqi_save_ctrl_mode(ctrl_info, SIS_MODE);
+               return 0;
        }
 
-       return 0;
+       return pqi_revert_to_sis_mode(ctrl_info);
 }
 
 static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info)
 {
        int rc;
 
-       if (reset_devices) {
-               rc = pqi_kdump_init(ctrl_info);
-               if (rc)
-                       return rc;
-       }
-
-       /*
-        * When the controller comes out of reset, it is always running
-        * in legacy SIS mode.  This is so that it can be compatible
-        * with legacy drivers shipped with OSes.  So we have to talk
-        * to it using SIS commands at first.  Once we are satisified
-        * that the controller supports PQI, we transition it into PQI
-        * mode.
-        */
+       rc = pqi_force_sis_mode(ctrl_info);
+       if (rc)
+               return rc;
 
        /*
         * Wait until the controller is ready to start accepting SIS
@@ -5594,12 +5606,8 @@ static void pqi_remove_ctrl(struct pqi_ctrl_info 
*ctrl_info)
        cancel_delayed_work_sync(&ctrl_info->update_time_work);
        pqi_remove_all_scsi_devices(ctrl_info);
        pqi_unregister_scsi(ctrl_info);
-
-       if (ctrl_info->pqi_mode_enabled) {
-               sis_disable_msix(ctrl_info);
-               if (pqi_reset(ctrl_info) == 0)
-                       sis_reenable_sis_mode(ctrl_info);
-       }
+       if (ctrl_info->pqi_mode_enabled)
+               pqi_revert_to_sis_mode(ctrl_info);
        pqi_free_ctrl_resources(ctrl_info);
 }
 
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.c 
b/drivers/scsi/smartpqi/smartpqi_sis.c
index c7d9ea1..c5325a4 100644
--- a/drivers/scsi/smartpqi/smartpqi_sis.c
+++ b/drivers/scsi/smartpqi/smartpqi_sis.c
@@ -127,6 +127,12 @@ bool sis_is_firmware_running(struct pqi_ctrl_info 
*ctrl_info)
        return running;
 }
 
+bool sis_is_kernel_up(struct pqi_ctrl_info *ctrl_info)
+{
+       return readl(&ctrl_info->registers->sis_firmware_status) &
+                               SIS_CTRL_KERNEL_UP;
+}
+
 /* used for passing command parameters/results when issuing SIS commands */
 struct sis_sync_cmd_params {
        u32     mailbox[6];     /* mailboxes 0-5 */
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.h 
b/drivers/scsi/smartpqi/smartpqi_sis.h
index 7f7b68c..157768d 100644
--- a/drivers/scsi/smartpqi/smartpqi_sis.h
+++ b/drivers/scsi/smartpqi/smartpqi_sis.h
@@ -21,6 +21,7 @@
 
 int sis_wait_for_ctrl_ready(struct pqi_ctrl_info *ctrl_info);
 bool sis_is_firmware_running(struct pqi_ctrl_info *ctrl_info);
+bool sis_is_kernel_up(struct pqi_ctrl_info *ctrl_info);
 int sis_get_ctrl_properties(struct pqi_ctrl_info *ctrl_info);
 int sis_get_pqi_capabilities(struct pqi_ctrl_info *ctrl_info);
 int sis_init_base_struct_addr(struct pqi_ctrl_info *ctrl_info);

Reply via email to