Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  scsi_pm.c   Copyright (C) 2010 Alan Stern
0004  *
0005  *  SCSI dynamic Power Management
0006  *      Initial version: Alan Stern <stern@rowland.harvard.edu>
0007  */
0008 
0009 #include <linux/pm_runtime.h>
0010 #include <linux/export.h>
0011 #include <linux/blk-pm.h>
0012 
0013 #include <scsi/scsi.h>
0014 #include <scsi/scsi_device.h>
0015 #include <scsi/scsi_driver.h>
0016 #include <scsi/scsi_host.h>
0017 
0018 #include "scsi_priv.h"
0019 
0020 #ifdef CONFIG_PM_SLEEP
0021 
0022 static int do_scsi_suspend(struct device *dev, const struct dev_pm_ops *pm)
0023 {
0024     return pm && pm->suspend ? pm->suspend(dev) : 0;
0025 }
0026 
0027 static int do_scsi_freeze(struct device *dev, const struct dev_pm_ops *pm)
0028 {
0029     return pm && pm->freeze ? pm->freeze(dev) : 0;
0030 }
0031 
0032 static int do_scsi_poweroff(struct device *dev, const struct dev_pm_ops *pm)
0033 {
0034     return pm && pm->poweroff ? pm->poweroff(dev) : 0;
0035 }
0036 
0037 static int do_scsi_resume(struct device *dev, const struct dev_pm_ops *pm)
0038 {
0039     return pm && pm->resume ? pm->resume(dev) : 0;
0040 }
0041 
0042 static int do_scsi_thaw(struct device *dev, const struct dev_pm_ops *pm)
0043 {
0044     return pm && pm->thaw ? pm->thaw(dev) : 0;
0045 }
0046 
0047 static int do_scsi_restore(struct device *dev, const struct dev_pm_ops *pm)
0048 {
0049     return pm && pm->restore ? pm->restore(dev) : 0;
0050 }
0051 
0052 static int scsi_dev_type_suspend(struct device *dev,
0053         int (*cb)(struct device *, const struct dev_pm_ops *))
0054 {
0055     const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
0056     int err;
0057 
0058     err = scsi_device_quiesce(to_scsi_device(dev));
0059     if (err == 0) {
0060         err = cb(dev, pm);
0061         if (err)
0062             scsi_device_resume(to_scsi_device(dev));
0063     }
0064     dev_dbg(dev, "scsi suspend: %d\n", err);
0065     return err;
0066 }
0067 
0068 static int
0069 scsi_bus_suspend_common(struct device *dev,
0070         int (*cb)(struct device *, const struct dev_pm_ops *))
0071 {
0072     if (!scsi_is_sdev_device(dev))
0073         return 0;
0074 
0075     return scsi_dev_type_suspend(dev, cb);
0076 }
0077 
0078 static int scsi_bus_resume_common(struct device *dev,
0079         int (*cb)(struct device *, const struct dev_pm_ops *))
0080 {
0081     const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
0082     int err;
0083 
0084     if (!scsi_is_sdev_device(dev))
0085         return 0;
0086 
0087     err = cb(dev, pm);
0088     scsi_device_resume(to_scsi_device(dev));
0089     dev_dbg(dev, "scsi resume: %d\n", err);
0090 
0091     return err;
0092 }
0093 
0094 static int scsi_bus_prepare(struct device *dev)
0095 {
0096     if (scsi_is_host_device(dev)) {
0097         /* Wait until async scanning is finished */
0098         scsi_complete_async_scans();
0099     }
0100     return 0;
0101 }
0102 
0103 static int scsi_bus_suspend(struct device *dev)
0104 {
0105     return scsi_bus_suspend_common(dev, do_scsi_suspend);
0106 }
0107 
0108 static int scsi_bus_resume(struct device *dev)
0109 {
0110     return scsi_bus_resume_common(dev, do_scsi_resume);
0111 }
0112 
0113 static int scsi_bus_freeze(struct device *dev)
0114 {
0115     return scsi_bus_suspend_common(dev, do_scsi_freeze);
0116 }
0117 
0118 static int scsi_bus_thaw(struct device *dev)
0119 {
0120     return scsi_bus_resume_common(dev, do_scsi_thaw);
0121 }
0122 
0123 static int scsi_bus_poweroff(struct device *dev)
0124 {
0125     return scsi_bus_suspend_common(dev, do_scsi_poweroff);
0126 }
0127 
0128 static int scsi_bus_restore(struct device *dev)
0129 {
0130     return scsi_bus_resume_common(dev, do_scsi_restore);
0131 }
0132 
0133 #else /* CONFIG_PM_SLEEP */
0134 
0135 #define scsi_bus_prepare        NULL
0136 #define scsi_bus_suspend        NULL
0137 #define scsi_bus_resume         NULL
0138 #define scsi_bus_freeze         NULL
0139 #define scsi_bus_thaw           NULL
0140 #define scsi_bus_poweroff       NULL
0141 #define scsi_bus_restore        NULL
0142 
0143 #endif /* CONFIG_PM_SLEEP */
0144 
0145 static int sdev_runtime_suspend(struct device *dev)
0146 {
0147     const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
0148     struct scsi_device *sdev = to_scsi_device(dev);
0149     int err = 0;
0150 
0151     err = blk_pre_runtime_suspend(sdev->request_queue);
0152     if (err)
0153         return err;
0154     if (pm && pm->runtime_suspend)
0155         err = pm->runtime_suspend(dev);
0156     blk_post_runtime_suspend(sdev->request_queue, err);
0157 
0158     return err;
0159 }
0160 
0161 static int scsi_runtime_suspend(struct device *dev)
0162 {
0163     int err = 0;
0164 
0165     dev_dbg(dev, "scsi_runtime_suspend\n");
0166     if (scsi_is_sdev_device(dev))
0167         err = sdev_runtime_suspend(dev);
0168 
0169     /* Insert hooks here for targets, hosts, and transport classes */
0170 
0171     return err;
0172 }
0173 
0174 static int sdev_runtime_resume(struct device *dev)
0175 {
0176     struct scsi_device *sdev = to_scsi_device(dev);
0177     const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
0178     int err = 0;
0179 
0180     blk_pre_runtime_resume(sdev->request_queue);
0181     if (pm && pm->runtime_resume)
0182         err = pm->runtime_resume(dev);
0183     blk_post_runtime_resume(sdev->request_queue);
0184 
0185     return err;
0186 }
0187 
0188 static int scsi_runtime_resume(struct device *dev)
0189 {
0190     int err = 0;
0191 
0192     dev_dbg(dev, "scsi_runtime_resume\n");
0193     if (scsi_is_sdev_device(dev))
0194         err = sdev_runtime_resume(dev);
0195 
0196     /* Insert hooks here for targets, hosts, and transport classes */
0197 
0198     return err;
0199 }
0200 
0201 static int scsi_runtime_idle(struct device *dev)
0202 {
0203     dev_dbg(dev, "scsi_runtime_idle\n");
0204 
0205     /* Insert hooks here for targets, hosts, and transport classes */
0206 
0207     if (scsi_is_sdev_device(dev)) {
0208         pm_runtime_mark_last_busy(dev);
0209         pm_runtime_autosuspend(dev);
0210         return -EBUSY;
0211     }
0212 
0213     return 0;
0214 }
0215 
0216 int scsi_autopm_get_device(struct scsi_device *sdev)
0217 {
0218     int err;
0219 
0220     err = pm_runtime_get_sync(&sdev->sdev_gendev);
0221     if (err < 0 && err !=-EACCES)
0222         pm_runtime_put_sync(&sdev->sdev_gendev);
0223     else
0224         err = 0;
0225     return err;
0226 }
0227 EXPORT_SYMBOL_GPL(scsi_autopm_get_device);
0228 
0229 void scsi_autopm_put_device(struct scsi_device *sdev)
0230 {
0231     pm_runtime_put_sync(&sdev->sdev_gendev);
0232 }
0233 EXPORT_SYMBOL_GPL(scsi_autopm_put_device);
0234 
0235 void scsi_autopm_get_target(struct scsi_target *starget)
0236 {
0237     pm_runtime_get_sync(&starget->dev);
0238 }
0239 
0240 void scsi_autopm_put_target(struct scsi_target *starget)
0241 {
0242     pm_runtime_put_sync(&starget->dev);
0243 }
0244 
0245 int scsi_autopm_get_host(struct Scsi_Host *shost)
0246 {
0247     int err;
0248 
0249     err = pm_runtime_get_sync(&shost->shost_gendev);
0250     if (err < 0 && err !=-EACCES)
0251         pm_runtime_put_sync(&shost->shost_gendev);
0252     else
0253         err = 0;
0254     return err;
0255 }
0256 
0257 void scsi_autopm_put_host(struct Scsi_Host *shost)
0258 {
0259     pm_runtime_put_sync(&shost->shost_gendev);
0260 }
0261 
0262 const struct dev_pm_ops scsi_bus_pm_ops = {
0263     .prepare =      scsi_bus_prepare,
0264     .suspend =      scsi_bus_suspend,
0265     .resume =       scsi_bus_resume,
0266     .freeze =       scsi_bus_freeze,
0267     .thaw =         scsi_bus_thaw,
0268     .poweroff =     scsi_bus_poweroff,
0269     .restore =      scsi_bus_restore,
0270     .runtime_suspend =  scsi_runtime_suspend,
0271     .runtime_resume =   scsi_runtime_resume,
0272     .runtime_idle =     scsi_runtime_idle,
0273 };