root/drivers/scsi/scsi_pm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. do_scsi_suspend
  2. do_scsi_freeze
  3. do_scsi_poweroff
  4. do_scsi_resume
  5. do_scsi_thaw
  6. do_scsi_restore
  7. scsi_dev_type_suspend
  8. scsi_dev_type_resume
  9. scsi_bus_suspend_common
  10. async_sdev_resume
  11. async_sdev_thaw
  12. async_sdev_restore
  13. scsi_bus_resume_common
  14. scsi_bus_prepare
  15. scsi_bus_suspend
  16. scsi_bus_resume
  17. scsi_bus_freeze
  18. scsi_bus_thaw
  19. scsi_bus_poweroff
  20. scsi_bus_restore
  21. sdev_runtime_suspend
  22. scsi_runtime_suspend
  23. sdev_runtime_resume
  24. scsi_runtime_resume
  25. scsi_runtime_idle
  26. scsi_autopm_get_device
  27. scsi_autopm_put_device
  28. scsi_autopm_get_target
  29. scsi_autopm_put_target
  30. scsi_autopm_get_host
  31. scsi_autopm_put_host

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *      scsi_pm.c       Copyright (C) 2010 Alan Stern
   4  *
   5  *      SCSI dynamic Power Management
   6  *              Initial version: Alan Stern <stern@rowland.harvard.edu>
   7  */
   8 
   9 #include <linux/pm_runtime.h>
  10 #include <linux/export.h>
  11 #include <linux/async.h>
  12 #include <linux/blk-pm.h>
  13 
  14 #include <scsi/scsi.h>
  15 #include <scsi/scsi_device.h>
  16 #include <scsi/scsi_driver.h>
  17 #include <scsi/scsi_host.h>
  18 
  19 #include "scsi_priv.h"
  20 
  21 #ifdef CONFIG_PM_SLEEP
  22 
  23 static int do_scsi_suspend(struct device *dev, const struct dev_pm_ops *pm)
  24 {
  25         return pm && pm->suspend ? pm->suspend(dev) : 0;
  26 }
  27 
  28 static int do_scsi_freeze(struct device *dev, const struct dev_pm_ops *pm)
  29 {
  30         return pm && pm->freeze ? pm->freeze(dev) : 0;
  31 }
  32 
  33 static int do_scsi_poweroff(struct device *dev, const struct dev_pm_ops *pm)
  34 {
  35         return pm && pm->poweroff ? pm->poweroff(dev) : 0;
  36 }
  37 
  38 static int do_scsi_resume(struct device *dev, const struct dev_pm_ops *pm)
  39 {
  40         return pm && pm->resume ? pm->resume(dev) : 0;
  41 }
  42 
  43 static int do_scsi_thaw(struct device *dev, const struct dev_pm_ops *pm)
  44 {
  45         return pm && pm->thaw ? pm->thaw(dev) : 0;
  46 }
  47 
  48 static int do_scsi_restore(struct device *dev, const struct dev_pm_ops *pm)
  49 {
  50         return pm && pm->restore ? pm->restore(dev) : 0;
  51 }
  52 
  53 static int scsi_dev_type_suspend(struct device *dev,
  54                 int (*cb)(struct device *, const struct dev_pm_ops *))
  55 {
  56         const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
  57         int err;
  58 
  59         /* flush pending in-flight resume operations, suspend is synchronous */
  60         async_synchronize_full_domain(&scsi_sd_pm_domain);
  61 
  62         err = scsi_device_quiesce(to_scsi_device(dev));
  63         if (err == 0) {
  64                 err = cb(dev, pm);
  65                 if (err)
  66                         scsi_device_resume(to_scsi_device(dev));
  67         }
  68         dev_dbg(dev, "scsi suspend: %d\n", err);
  69         return err;
  70 }
  71 
  72 static int scsi_dev_type_resume(struct device *dev,
  73                 int (*cb)(struct device *, const struct dev_pm_ops *))
  74 {
  75         const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
  76         int err = 0;
  77 
  78         err = cb(dev, pm);
  79         scsi_device_resume(to_scsi_device(dev));
  80         dev_dbg(dev, "scsi resume: %d\n", err);
  81 
  82         if (err == 0) {
  83                 bool was_runtime_suspended;
  84 
  85                 was_runtime_suspended = pm_runtime_suspended(dev);
  86 
  87                 pm_runtime_disable(dev);
  88                 err = pm_runtime_set_active(dev);
  89                 pm_runtime_enable(dev);
  90 
  91                 /*
  92                  * Forcibly set runtime PM status of request queue to "active"
  93                  * to make sure we can again get requests from the queue
  94                  * (see also blk_pm_peek_request()).
  95                  *
  96                  * The resume hook will correct runtime PM status of the disk.
  97                  */
  98                 if (!err && scsi_is_sdev_device(dev)) {
  99                         struct scsi_device *sdev = to_scsi_device(dev);
 100                         if (was_runtime_suspended)
 101                                 blk_post_runtime_resume(sdev->request_queue, 0);
 102                         else
 103                                 blk_set_runtime_active(sdev->request_queue);
 104                 }
 105         }
 106 
 107         return err;
 108 }
 109 
 110 static int
 111 scsi_bus_suspend_common(struct device *dev,
 112                 int (*cb)(struct device *, const struct dev_pm_ops *))
 113 {
 114         int err = 0;
 115 
 116         if (scsi_is_sdev_device(dev)) {
 117                 /*
 118                  * All the high-level SCSI drivers that implement runtime
 119                  * PM treat runtime suspend, system suspend, and system
 120                  * hibernate nearly identically. In all cases the requirements
 121                  * for runtime suspension are stricter.
 122                  */
 123                 if (pm_runtime_suspended(dev))
 124                         return 0;
 125 
 126                 err = scsi_dev_type_suspend(dev, cb);
 127         }
 128 
 129         return err;
 130 }
 131 
 132 static void async_sdev_resume(void *dev, async_cookie_t cookie)
 133 {
 134         scsi_dev_type_resume(dev, do_scsi_resume);
 135 }
 136 
 137 static void async_sdev_thaw(void *dev, async_cookie_t cookie)
 138 {
 139         scsi_dev_type_resume(dev, do_scsi_thaw);
 140 }
 141 
 142 static void async_sdev_restore(void *dev, async_cookie_t cookie)
 143 {
 144         scsi_dev_type_resume(dev, do_scsi_restore);
 145 }
 146 
 147 static int scsi_bus_resume_common(struct device *dev,
 148                 int (*cb)(struct device *, const struct dev_pm_ops *))
 149 {
 150         async_func_t fn;
 151 
 152         if (!scsi_is_sdev_device(dev))
 153                 fn = NULL;
 154         else if (cb == do_scsi_resume)
 155                 fn = async_sdev_resume;
 156         else if (cb == do_scsi_thaw)
 157                 fn = async_sdev_thaw;
 158         else if (cb == do_scsi_restore)
 159                 fn = async_sdev_restore;
 160         else
 161                 fn = NULL;
 162 
 163         if (fn) {
 164                 async_schedule_domain(fn, dev, &scsi_sd_pm_domain);
 165 
 166                 /*
 167                  * If a user has disabled async probing a likely reason
 168                  * is due to a storage enclosure that does not inject
 169                  * staggered spin-ups.  For safety, make resume
 170                  * synchronous as well in that case.
 171                  */
 172                 if (strncmp(scsi_scan_type, "async", 5) != 0)
 173                         async_synchronize_full_domain(&scsi_sd_pm_domain);
 174         } else {
 175                 pm_runtime_disable(dev);
 176                 pm_runtime_set_active(dev);
 177                 pm_runtime_enable(dev);
 178         }
 179         return 0;
 180 }
 181 
 182 static int scsi_bus_prepare(struct device *dev)
 183 {
 184         if (scsi_is_host_device(dev)) {
 185                 /* Wait until async scanning is finished */
 186                 scsi_complete_async_scans();
 187         }
 188         return 0;
 189 }
 190 
 191 static int scsi_bus_suspend(struct device *dev)
 192 {
 193         return scsi_bus_suspend_common(dev, do_scsi_suspend);
 194 }
 195 
 196 static int scsi_bus_resume(struct device *dev)
 197 {
 198         return scsi_bus_resume_common(dev, do_scsi_resume);
 199 }
 200 
 201 static int scsi_bus_freeze(struct device *dev)
 202 {
 203         return scsi_bus_suspend_common(dev, do_scsi_freeze);
 204 }
 205 
 206 static int scsi_bus_thaw(struct device *dev)
 207 {
 208         return scsi_bus_resume_common(dev, do_scsi_thaw);
 209 }
 210 
 211 static int scsi_bus_poweroff(struct device *dev)
 212 {
 213         return scsi_bus_suspend_common(dev, do_scsi_poweroff);
 214 }
 215 
 216 static int scsi_bus_restore(struct device *dev)
 217 {
 218         return scsi_bus_resume_common(dev, do_scsi_restore);
 219 }
 220 
 221 #else /* CONFIG_PM_SLEEP */
 222 
 223 #define scsi_bus_prepare                NULL
 224 #define scsi_bus_suspend                NULL
 225 #define scsi_bus_resume                 NULL
 226 #define scsi_bus_freeze                 NULL
 227 #define scsi_bus_thaw                   NULL
 228 #define scsi_bus_poweroff               NULL
 229 #define scsi_bus_restore                NULL
 230 
 231 #endif /* CONFIG_PM_SLEEP */
 232 
 233 static int sdev_runtime_suspend(struct device *dev)
 234 {
 235         const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 236         struct scsi_device *sdev = to_scsi_device(dev);
 237         int err = 0;
 238 
 239         err = blk_pre_runtime_suspend(sdev->request_queue);
 240         if (err)
 241                 return err;
 242         if (pm && pm->runtime_suspend)
 243                 err = pm->runtime_suspend(dev);
 244         blk_post_runtime_suspend(sdev->request_queue, err);
 245 
 246         return err;
 247 }
 248 
 249 static int scsi_runtime_suspend(struct device *dev)
 250 {
 251         int err = 0;
 252 
 253         dev_dbg(dev, "scsi_runtime_suspend\n");
 254         if (scsi_is_sdev_device(dev))
 255                 err = sdev_runtime_suspend(dev);
 256 
 257         /* Insert hooks here for targets, hosts, and transport classes */
 258 
 259         return err;
 260 }
 261 
 262 static int sdev_runtime_resume(struct device *dev)
 263 {
 264         struct scsi_device *sdev = to_scsi_device(dev);
 265         const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 266         int err = 0;
 267 
 268         blk_pre_runtime_resume(sdev->request_queue);
 269         if (pm && pm->runtime_resume)
 270                 err = pm->runtime_resume(dev);
 271         blk_post_runtime_resume(sdev->request_queue, err);
 272 
 273         return err;
 274 }
 275 
 276 static int scsi_runtime_resume(struct device *dev)
 277 {
 278         int err = 0;
 279 
 280         dev_dbg(dev, "scsi_runtime_resume\n");
 281         if (scsi_is_sdev_device(dev))
 282                 err = sdev_runtime_resume(dev);
 283 
 284         /* Insert hooks here for targets, hosts, and transport classes */
 285 
 286         return err;
 287 }
 288 
 289 static int scsi_runtime_idle(struct device *dev)
 290 {
 291         dev_dbg(dev, "scsi_runtime_idle\n");
 292 
 293         /* Insert hooks here for targets, hosts, and transport classes */
 294 
 295         if (scsi_is_sdev_device(dev)) {
 296                 pm_runtime_mark_last_busy(dev);
 297                 pm_runtime_autosuspend(dev);
 298                 return -EBUSY;
 299         }
 300 
 301         return 0;
 302 }
 303 
 304 int scsi_autopm_get_device(struct scsi_device *sdev)
 305 {
 306         int     err;
 307 
 308         err = pm_runtime_get_sync(&sdev->sdev_gendev);
 309         if (err < 0 && err !=-EACCES)
 310                 pm_runtime_put_sync(&sdev->sdev_gendev);
 311         else
 312                 err = 0;
 313         return err;
 314 }
 315 EXPORT_SYMBOL_GPL(scsi_autopm_get_device);
 316 
 317 void scsi_autopm_put_device(struct scsi_device *sdev)
 318 {
 319         pm_runtime_put_sync(&sdev->sdev_gendev);
 320 }
 321 EXPORT_SYMBOL_GPL(scsi_autopm_put_device);
 322 
 323 void scsi_autopm_get_target(struct scsi_target *starget)
 324 {
 325         pm_runtime_get_sync(&starget->dev);
 326 }
 327 
 328 void scsi_autopm_put_target(struct scsi_target *starget)
 329 {
 330         pm_runtime_put_sync(&starget->dev);
 331 }
 332 
 333 int scsi_autopm_get_host(struct Scsi_Host *shost)
 334 {
 335         int     err;
 336 
 337         err = pm_runtime_get_sync(&shost->shost_gendev);
 338         if (err < 0 && err !=-EACCES)
 339                 pm_runtime_put_sync(&shost->shost_gendev);
 340         else
 341                 err = 0;
 342         return err;
 343 }
 344 
 345 void scsi_autopm_put_host(struct Scsi_Host *shost)
 346 {
 347         pm_runtime_put_sync(&shost->shost_gendev);
 348 }
 349 
 350 const struct dev_pm_ops scsi_bus_pm_ops = {
 351         .prepare =              scsi_bus_prepare,
 352         .suspend =              scsi_bus_suspend,
 353         .resume =               scsi_bus_resume,
 354         .freeze =               scsi_bus_freeze,
 355         .thaw =                 scsi_bus_thaw,
 356         .poweroff =             scsi_bus_poweroff,
 357         .restore =              scsi_bus_restore,
 358         .runtime_suspend =      scsi_runtime_suspend,
 359         .runtime_resume =       scsi_runtime_resume,
 360         .runtime_idle =         scsi_runtime_idle,
 361 };

/* [<][>][^][v][top][bottom][index][help] */