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 nearly identically. In all cases the requirements 58 * for runtime suspension are stricter. 59 */ 60 if (pm_runtime_suspended(dev)) 61 return 0; 62 63 err = scsi_dev_type_suspend(dev, cb); 64 } 65 66 return err; 67 } 68 69 static int 70 scsi_bus_resume_common(struct device *dev, int (*cb)(struct device *)) 71 { 72 int err = 0; 73 74 if (scsi_is_sdev_device(dev)) 75 err = scsi_dev_type_resume(dev, cb); 76 77 if (err == 0) { 78 pm_runtime_disable(dev); 79 pm_runtime_set_active(dev); 80 pm_runtime_enable(dev); 81 } 82 return err; 83 } 84 85 static int scsi_bus_prepare(struct device *dev) 86 { 87 if (scsi_is_sdev_device(dev)) { 88 /* sd probing uses async_schedule. Wait until it finishes. */ 89 async_synchronize_full_domain(&scsi_sd_probe_domain); 90 91 } else if (scsi_is_host_device(dev)) { 92 /* Wait until async scanning is finished */ 93 scsi_complete_async_scans(); 94 } 95 return 0; 96 } 97 98 static int scsi_bus_suspend(struct device *dev) 99 { 100 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 101 return scsi_bus_suspend_common(dev, pm ? pm->suspend : NULL); 102 } 103 104 static int scsi_bus_resume(struct device *dev) 105 { 106 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 107 return scsi_bus_resume_common(dev, pm ? pm->resume : NULL); 108 } 109 110 static int scsi_bus_freeze(struct device *dev) 111 { 112 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 113 return scsi_bus_suspend_common(dev, pm ? pm->freeze : NULL); 114 } 115 116 static int scsi_bus_thaw(struct device *dev) 117 { 118 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 119 return scsi_bus_resume_common(dev, pm ? pm->thaw : NULL); 120 } 121 122 static int scsi_bus_poweroff(struct device *dev) 123 { 124 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 125 return scsi_bus_suspend_common(dev, pm ? pm->poweroff : NULL); 126 } 127 128 static int scsi_bus_restore(struct device *dev) 129 { 130 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 131 return scsi_bus_resume_common(dev, pm ? pm->restore : NULL); 132 } 133 134 #else /* CONFIG_PM_SLEEP */ 135 136 #define scsi_bus_prepare NULL 137 #define scsi_bus_suspend NULL 138 #define scsi_bus_resume NULL 139 #define scsi_bus_freeze NULL 140 #define scsi_bus_thaw NULL 141 #define scsi_bus_poweroff NULL 142 #define scsi_bus_restore NULL 143 144 #endif /* CONFIG_PM_SLEEP */ 145 146 #ifdef CONFIG_PM_RUNTIME 147 148 static int sdev_blk_runtime_suspend(struct scsi_device *sdev, 149 int (*cb)(struct device *)) 150 { 151 int err; 152 153 err = blk_pre_runtime_suspend(sdev->request_queue); 154 if (err) 155 return err; 156 if (cb) 157 err = cb(&sdev->sdev_gendev); 158 blk_post_runtime_suspend(sdev->request_queue, err); 159 160 return err; 161 } 162 163 static int sdev_runtime_suspend(struct device *dev) 164 { 165 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 166 int (*cb)(struct device *) = pm ? pm->runtime_suspend : NULL; 167 struct scsi_device *sdev = to_scsi_device(dev); 168 int err; 169 170 if (sdev->request_queue->dev) 171 return sdev_blk_runtime_suspend(sdev, cb); 172 173 err = scsi_dev_type_suspend(dev, cb); 174 if (err == -EAGAIN) 175 pm_schedule_suspend(dev, jiffies_to_msecs( 176 round_jiffies_up_relative(HZ/10))); 177 return err; 178 } 179 180 static int scsi_runtime_suspend(struct device *dev) 181 { 182 int err = 0; 183 184 dev_dbg(dev, "scsi_runtime_suspend\n"); 185 if (scsi_is_sdev_device(dev)) 186 err = sdev_runtime_suspend(dev); 187 188 /* Insert hooks here for targets, hosts, and transport classes */ 189 190 return err; 191 } 192 193 static int sdev_blk_runtime_resume(struct scsi_device *sdev, 194 int (*cb)(struct device *)) 195 { 196 int err = 0; 197 198 blk_pre_runtime_resume(sdev->request_queue); 199 if (cb) 200 err = cb(&sdev->sdev_gendev); 201 blk_post_runtime_resume(sdev->request_queue, err); 202 203 return err; 204 } 205 206 static int sdev_runtime_resume(struct device *dev) 207 { 208 struct scsi_device *sdev = to_scsi_device(dev); 209 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 210 int (*cb)(struct device *) = pm ? pm->runtime_resume : NULL; 211 212 if (sdev->request_queue->dev) 213 return sdev_blk_runtime_resume(sdev, cb); 214 else 215 return scsi_dev_type_resume(dev, cb); 216 } 217 218 static int scsi_runtime_resume(struct device *dev) 219 { 220 int err = 0; 221 222 dev_dbg(dev, "scsi_runtime_resume\n"); 223 if (scsi_is_sdev_device(dev)) 224 err = sdev_runtime_resume(dev); 225 226 /* Insert hooks here for targets, hosts, and transport classes */ 227 228 return err; 229 } 230 231 static int scsi_runtime_idle(struct device *dev) 232 { 233 dev_dbg(dev, "scsi_runtime_idle\n"); 234 235 /* Insert hooks here for targets, hosts, and transport classes */ 236 237 if (scsi_is_sdev_device(dev)) { 238 struct scsi_device *sdev = to_scsi_device(dev); 239 240 if (sdev->request_queue->dev) { 241 pm_runtime_mark_last_busy(dev); 242 pm_runtime_autosuspend(dev); 243 return -EBUSY; 244 } 245 } 246 return 0; 247 } 248 249 int scsi_autopm_get_device(struct scsi_device *sdev) 250 { 251 int err; 252 253 err = pm_runtime_get_sync(&sdev->sdev_gendev); 254 if (err < 0 && err !=-EACCES) 255 pm_runtime_put_sync(&sdev->sdev_gendev); 256 else 257 err = 0; 258 return err; 259 } 260 EXPORT_SYMBOL_GPL(scsi_autopm_get_device); 261 262 void scsi_autopm_put_device(struct scsi_device *sdev) 263 { 264 pm_runtime_put_sync(&sdev->sdev_gendev); 265 } 266 EXPORT_SYMBOL_GPL(scsi_autopm_put_device); 267 268 void scsi_autopm_get_target(struct scsi_target *starget) 269 { 270 pm_runtime_get_sync(&starget->dev); 271 } 272 273 void scsi_autopm_put_target(struct scsi_target *starget) 274 { 275 pm_runtime_put_sync(&starget->dev); 276 } 277 278 int scsi_autopm_get_host(struct Scsi_Host *shost) 279 { 280 int err; 281 282 err = pm_runtime_get_sync(&shost->shost_gendev); 283 if (err < 0 && err !=-EACCES) 284 pm_runtime_put_sync(&shost->shost_gendev); 285 else 286 err = 0; 287 return err; 288 } 289 290 void scsi_autopm_put_host(struct Scsi_Host *shost) 291 { 292 pm_runtime_put_sync(&shost->shost_gendev); 293 } 294 295 #else 296 297 #define scsi_runtime_suspend NULL 298 #define scsi_runtime_resume NULL 299 #define scsi_runtime_idle NULL 300 301 #endif /* CONFIG_PM_RUNTIME */ 302 303 const struct dev_pm_ops scsi_bus_pm_ops = { 304 .prepare = scsi_bus_prepare, 305 .suspend = scsi_bus_suspend, 306 .resume = scsi_bus_resume, 307 .freeze = scsi_bus_freeze, 308 .thaw = scsi_bus_thaw, 309 .poweroff = scsi_bus_poweroff, 310 .restore = scsi_bus_restore, 311 .runtime_suspend = scsi_runtime_suspend, 312 .runtime_resume = scsi_runtime_resume, 313 .runtime_idle = scsi_runtime_idle, 314 }; 315