Commit 2f9c4d52 authored by Kashyap Desai's avatar Kashyap Desai Committed by Martin K. Petersen

scsi: mpi3mr: Add support for PM suspend and resume

Link: https://lore.kernel.org/r/20210520152545.2710479-22-kashyap.desai@broadcom.com
Cc: sathya.prakash@broadcom.com
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Reviewed-by: default avatarTomas Henzl <thenzl@redhat.com>
Reviewed-by: default avatarHimanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: default avatarKashyap Desai <kashyap.desai@broadcom.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 44dc724f
......@@ -3389,6 +3389,86 @@ static void mpi3mr_shutdown(struct pci_dev *pdev)
mpi3mr_cleanup_ioc(mrioc, 0);
}
#ifdef CONFIG_PM
/**
* mpi3mr_suspend - PCI power management suspend callback
* @pdev: PCI device instance
* @state: New power state
*
* Change the power state to the given value and cleanup the IOC
* by issuing MUR and shutdown notification
*
* Return: 0 always.
*/
static int mpi3mr_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct mpi3mr_ioc *mrioc;
pci_power_t device_state;
if (!shost)
return 0;
mrioc = shost_priv(shost);
while (mrioc->reset_in_progress || mrioc->is_driver_loading)
ssleep(1);
mrioc->stop_drv_processing = 1;
mpi3mr_cleanup_fwevt_list(mrioc);
scsi_block_requests(shost);
mpi3mr_stop_watchdog(mrioc);
mpi3mr_cleanup_ioc(mrioc, 1);
device_state = pci_choose_state(pdev, state);
ioc_info(mrioc, "pdev=0x%p, slot=%s, entering operating state [D%d]\n",
pdev, pci_name(pdev), device_state);
pci_save_state(pdev);
pci_set_power_state(pdev, device_state);
mpi3mr_cleanup_resources(mrioc);
return 0;
}
/**
* mpi3mr_resume - PCI power management resume callback
* @pdev: PCI device instance
*
* Restore the power state to D0 and reinitialize the controller
* and resume I/O operations to the target devices
*
* Return: 0 on success, non-zero on failure
*/
static int mpi3mr_resume(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct mpi3mr_ioc *mrioc;
pci_power_t device_state = pdev->current_state;
int r;
mrioc = shost_priv(shost);
ioc_info(mrioc, "pdev=0x%p, slot=%s, previous operating state [D%d]\n",
pdev, pci_name(pdev), device_state);
pci_set_power_state(pdev, PCI_D0);
pci_enable_wake(pdev, PCI_D0, 0);
pci_restore_state(pdev);
mrioc->pdev = pdev;
mrioc->cpu_count = num_online_cpus();
r = mpi3mr_setup_resources(mrioc);
if (r) {
ioc_info(mrioc, "%s: Setup resources failed[%d]\n",
__func__, r);
return r;
}
mrioc->stop_drv_processing = 0;
mpi3mr_init_ioc(mrioc, 1);
scsi_unblock_requests(shost);
mpi3mr_start_watchdog(mrioc);
return 0;
}
#endif
static const struct pci_device_id mpi3mr_pci_id_table[] = {
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_LSI_LOGIC, 0x00A5,
......@@ -3404,6 +3484,10 @@ static struct pci_driver mpi3mr_pci_driver = {
.probe = mpi3mr_probe,
.remove = mpi3mr_remove,
.shutdown = mpi3mr_shutdown,
#ifdef CONFIG_PM
.suspend = mpi3mr_suspend,
.resume = mpi3mr_resume,
#endif
};
static int __init mpi3mr_init(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment