diff options
author | Kevin Barnett <kevin.barnett@hpe.com> | 2017-05-03 18:52:46 -0500 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2017-06-12 20:48:02 -0400 |
commit | 162d7753fce9a00719c09dfebd9fee3855e27fbe (patch) | |
tree | f126532ee1c17e44e3aabcc5781b8146591f9222 | |
parent | 5b0fba0f408777113eff93bd18ab0b9f80760fb7 (diff) | |
download | linux-162d7753fce9a00719c09dfebd9fee3855e27fbe.tar.bz2 |
scsi: smartpqi: ensure controller is in SIS mode at init
put in SIS mode during initialization.
support kexec/kdump
Reviewed-by: Scott Benesh <scott.benesh@microsemi.com>
Reviewed-by: Scott Teel <scott.teel@microsemi.com>
Signed-off-by: Kevin Barnett <kevin.barnett@microsemi.com>
Signed-off-by: Don Brace <don.brace@microsemi.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r-- | drivers/scsi/smartpqi/smartpqi.h | 2 | ||||
-rw-r--r-- | drivers/scsi/smartpqi/smartpqi_init.c | 60 | ||||
-rw-r--r-- | drivers/scsi/smartpqi/smartpqi_sis.c | 6 | ||||
-rw-r--r-- | 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 73754caa0161..62045c1990c7 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 14d74e157eb5..5a5b9abe501f 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -5245,38 +5245,50 @@ out: 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 c7d9ea10b02a..c5325a4d0f0f 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 7f7b68ca0bd2..157768d939a9 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); |