1 /* 2 * scsi_pm.c Copyright (C) 2010 Alan Stern 3 * 4 * SCSI dynamic Power Management 5 * Initial version: Alan Stern <stern@rowland.harvard.edu> 6 */ 7 8 #include <linux/pm_runtime.h> 9 #include <linux/export.h> 10 #include <linux/async.h> 11 12 #include <scsi/scsi.h> 13 #include <scsi/scsi_device.h> 14 #include <scsi/scsi_driver.h> 15 #include <scsi/scsi_host.h> 16 17 #include "scsi_priv.h" 18 19 static int scsi_dev_type_suspend(struct device *dev, int (*cb)(struct device *)) 20 { 21 int err; 22 23 err = scsi_device_quiesce(to_scsi_device(dev)); 24 if (err == 0) { 25 if (cb) { 26 err = cb(dev); 27 if (err) 28 scsi_device_resume(to_scsi_device(dev)); 29 } 30 } 31 dev_dbg(dev, "scsi suspend: %d\n", err); 32 return err; 33 } 34 35 static int scsi_dev_type_resume(struct device *dev, int (*cb)(struct device *)) 36 { 37 int err = 0; 38 39 if (cb) 40 err = cb(dev); 41 scsi_device_resume(to_scsi_device(dev)); 42 dev_dbg(dev, "scsi resume: %d\n", err); 43 return err; 44 } 45 46 #ifdef CONFIG_PM_SLEEP 47 48 static int 49 scsi_bus_suspend_common(struct device *dev, int (*cb)(struct device *)) 50 { 51 int err = 0; 52 53 if (scsi_is_sdev_device(dev)) { 54 /* 55 * All the high-level SCSI drivers that implement runtime 56 * PM treat runtime suspend, system suspend, and system 57 * hibernate identically. 58 */ 59 if (pm_runtime_suspended(dev)) 60 return 0; 61 62 err = scsi_dev_type_suspend(dev, cb); 63 } 64 65 return err; 66 } 67 68 static int 69 scsi_bus_resume_common(struct device *dev, int (*cb)(struct device *)) 70 { 71 int err = 0; 72 73 if (scsi_is_sdev_device(dev)) 74 err = scsi_dev_type_resume(dev, cb); 75 76 if (err == 0) { 77 pm_runtime_disable(dev); 78 pm_runtime_set_active(dev); 79 pm_runtime_enable(dev); 80 } 81 return err; 82 } 83 84 static int scsi_bus_prepare(struct device *dev) 85 { 86 if (scsi_is_sdev_device(dev)) { 87 /* sd probing uses async_schedule. Wait until it finishes. */ 88 async_synchronize_full_domain(&scsi_sd_probe_domain); 89 90 } else if (scsi_is_host_device(dev)) { 91 /* Wait until async scanning is finished */ 92 scsi_complete_async_scans(); 93 } 94 return 0; 95 } 96 97 static int scsi_bus_suspend(struct device *dev) 98 { 99 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 100 return scsi_bus_suspend_common(dev, pm ? pm->suspend : NULL); 101 } 102 103 static int scsi_bus_resume(struct device *dev) 104 { 105 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 106 return scsi_bus_resume_common(dev, pm ? pm->resume : NULL); 107 } 108 109 static int scsi_bus_freeze(struct device *dev) 110 { 111 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 112 return scsi_bus_suspend_common(dev, pm ? pm->freeze : NULL); 113 } 114 115 static int scsi_bus_thaw(struct device *dev) 116 { 117 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 118 return scsi_bus_resume_common(dev, pm ? pm->thaw : NULL); 119 } 120 121 static int scsi_bus_poweroff(struct device *dev) 122 { 123 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 124 return scsi_bus_suspend_common(dev, pm ? pm->poweroff : NULL); 125 } 126 127 static int scsi_bus_restore(struct device *dev) 128 { 129 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 130 return scsi_bus_resume_common(dev, pm ? pm->restore : NULL); 131 } 132 133 #else /* CONFIG_PM_SLEEP */ 134 135 #define scsi_bus_prepare NULL 136 #define scsi_bus_suspend NULL 137 #define scsi_bus_resume NULL 138 #define scsi_bus_freeze NULL 139 #define scsi_bus_thaw NULL 140 #define scsi_bus_poweroff NULL 141 #define scsi_bus_restore NULL 142 143 #endif /* CONFIG_PM_SLEEP */ 144 145 #ifdef CONFIG_PM_RUNTIME 146 147 static int sdev_blk_runtime_suspend(struct scsi_device *sdev, 148 int (*cb)(struct device *)) 149 { 150 int err; 151 152 err = blk_pre_runtime_suspend(sdev->request_queue); 153 if (err) 154 return err; 155 if (cb) 156 err = cb(&sdev->sdev_gendev); 157 blk_post_runtime_suspend(sdev->request_queue, err); 158 159 return err; 160 } 161 162 static int sdev_runtime_suspend(struct device *dev) 163 { 164 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 165 int (*cb)(struct device *) = pm ? pm->runtime_suspend : NULL; 166 struct scsi_device *sdev = to_scsi_device(dev); 167 int err; 168 169 if (sdev->request_queue->dev) 170 return sdev_blk_runtime_suspend(sdev, cb); 171 172 err = scsi_dev_type_suspend(dev, cb); 173 if (err == -EAGAIN) 174 pm_schedule_suspend(dev, jiffies_to_msecs( 175 round_jiffies_up_relative(HZ/10))); 176 return err; 177 } 178 179 static int scsi_runtime_suspend(struct device *dev) 180 { 181 int err = 0; 182 183 dev_dbg(dev, "scsi_runtime_suspend\n"); 184 if (scsi_is_sdev_device(dev)) 185 err = sdev_runtime_suspend(dev); 186 187 /* Insert hooks here for targets, hosts, and transport classes */ 188 189 return err; 190 } 191 192 static int sdev_blk_runtime_resume(struct scsi_device *sdev, 193 int (*cb)(struct device *)) 194 { 195 int err = 0; 196 197 blk_pre_runtime_resume(sdev->request_queue); 198 if (cb) 199 err = cb(&sdev->sdev_gendev); 200 blk_post_runtime_resume(sdev->request_queue, err); 201 202 return err; 203 } 204 205 static int sdev_runtime_resume(struct device *dev) 206 { 207 struct scsi_device *sdev = to_scsi_device(dev); 208 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 209 int (*cb)(struct device *) = pm ? pm->runtime_resume : NULL; 210 211 if (sdev->request_queue->dev) 212 return sdev_blk_runtime_resume(sdev, cb); 213 else 214 return scsi_dev_type_resume(dev, cb); 215 } 216 217 static int scsi_runtime_resume(struct device *dev) 218 { 219 int err = 0; 220 221 dev_dbg(dev, "scsi_runtime_resume\n"); 222 if (scsi_is_sdev_device(dev)) 223 err = sdev_runtime_resume(dev); 224 225 /* Insert hooks here for targets, hosts, and transport classes */ 226 227 return err; 228 } 229 230 static int scsi_runtime_idle(struct device *dev) 231 { 232 dev_dbg(dev, "scsi_runtime_idle\n"); 233 234 /* Insert hooks here for targets, hosts, and transport classes */ 235 236 if (scsi_is_sdev_device(dev)) { 237 struct scsi_device *sdev = to_scsi_device(dev); 238 239 if (sdev->request_queue->dev) { 240 pm_runtime_mark_last_busy(dev); 241 pm_runtime_autosuspend(dev); 242 return -EBUSY; 243 } 244 } 245 return 0; 246 } 247 248 int scsi_autopm_get_device(struct scsi_device *sdev) 249 { 250 int err; 251 252 err = pm_runtime_get_sync(&sdev->sdev_gendev); 253 if (err < 0 && err !=-EACCES) 254 pm_runtime_put_sync(&sdev->sdev_gendev); 255 else 256 err = 0; 257 return err; 258 } 259 EXPORT_SYMBOL_GPL(scsi_autopm_get_device); 260 261 void scsi_autopm_put_device(struct scsi_device *sdev) 262 { 263 pm_runtime_put_sync(&sdev->sdev_gendev); 264 } 265 EXPORT_SYMBOL_GPL(scsi_autopm_put_device); 266 267 void scsi_autopm_get_target(struct scsi_target *starget) 268 { 269 pm_runtime_get_sync(&starget->dev); 270 } 271 272 void scsi_autopm_put_target(struct scsi_target *starget) 273 { 274 pm_runtime_put_sync(&starget->dev); 275 } 276 277 int scsi_autopm_get_host(struct Scsi_Host *shost) 278 { 279 int err; 280 281 err = pm_runtime_get_sync(&shost->shost_gendev); 282 if (err < 0 && err !=-EACCES) 283 pm_runtime_put_sync(&shost->shost_gendev); 284 else 285 err = 0; 286 return err; 287 } 288 289 void scsi_autopm_put_host(struct Scsi_Host *shost) 290 { 291 pm_runtime_put_sync(&shost->shost_gendev); 292 } 293 294 #else 295 296 #define scsi_runtime_suspend NULL 297 #define scsi_runtime_resume NULL 298 #define scsi_runtime_idle NULL 299 300 #endif /* CONFIG_PM_RUNTIME */ 301 302 const struct dev_pm_ops scsi_bus_pm_ops = { 303 .prepare = scsi_bus_prepare, 304 .suspend = scsi_bus_suspend, 305 .resume = scsi_bus_resume, 306 .freeze = scsi_bus_freeze, 307 .thaw = scsi_bus_thaw, 308 .poweroff = scsi_bus_poweroff, 309 .restore = scsi_bus_restore, 310 .runtime_suspend = scsi_runtime_suspend, 311 .runtime_resume = scsi_runtime_resume, 312 .runtime_idle = scsi_runtime_idle, 313 }; 314