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>
This commit is contained in:
Kevin Barnett 2017-05-03 18:52:46 -05:00 committed by Martin K. Petersen
parent 5b0fba0f40
commit 162d7753fc
4 changed files with 42 additions and 27 deletions

View file

@ -964,7 +964,7 @@ struct pqi_ctrl_info {
};
enum pqi_ctrl_mode {
UNKNOWN,
SIS_MODE = 0,
PQI_MODE
};

View file

@ -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);
}

View file

@ -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 */

View file

@ -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);