diff options
author | Tejun Heo <htejun@gmail.com> | 2007-03-20 11:13:59 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-03-20 13:06:20 -0400 |
commit | c3c94c5a2fb43a654e777f509d5032b0db8ed09f (patch) | |
tree | cbc9b0adfa0a83fc5859344d6f9911d3010a29ac /drivers/scsi/scsi_sysfs.c | |
parent | 3721050afc6cb6ddf6de0f782e2054ebcc225e9b (diff) |
[SCSI] sd: implement START/STOP management
Implement SBC START/STOP management. sdev->mange_start_stop is added.
When it's set to one, sd STOPs the device on suspend and shutdown and
STARTs it on resume. sdev->manage_start_stop defaults is in sdev
instead of scsi_disk cdev to allow ->slave_config() override the
default configuration but is exported under scsi_disk sysfs node as
sdev->allow_restart is.
When manage_start_stop is zero (the default value), this patch doesn't
introduce any behavior change.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Rejections fixed and
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/scsi_sysfs.c')
-rw-r--r-- | drivers/scsi/scsi_sysfs.c | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index c275dcac3f18..96db51c40ef3 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
@@ -278,6 +278,7 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv) | |||
278 | 278 | ||
279 | static int scsi_bus_suspend(struct device * dev, pm_message_t state) | 279 | static int scsi_bus_suspend(struct device * dev, pm_message_t state) |
280 | { | 280 | { |
281 | struct device_driver *drv = dev->driver; | ||
281 | struct scsi_device *sdev = to_scsi_device(dev); | 282 | struct scsi_device *sdev = to_scsi_device(dev); |
282 | struct scsi_host_template *sht = sdev->host->hostt; | 283 | struct scsi_host_template *sht = sdev->host->hostt; |
283 | int err; | 284 | int err; |
@@ -286,23 +287,45 @@ static int scsi_bus_suspend(struct device * dev, pm_message_t state) | |||
286 | if (err) | 287 | if (err) |
287 | return err; | 288 | return err; |
288 | 289 | ||
289 | if (sht->suspend) | 290 | /* call HLD suspend first */ |
291 | if (drv && drv->suspend) { | ||
292 | err = drv->suspend(dev, state); | ||
293 | if (err) | ||
294 | return err; | ||
295 | } | ||
296 | |||
297 | /* then, call host suspend */ | ||
298 | if (sht->suspend) { | ||
290 | err = sht->suspend(sdev, state); | 299 | err = sht->suspend(sdev, state); |
300 | if (err) { | ||
301 | if (drv && drv->resume) | ||
302 | drv->resume(dev); | ||
303 | return err; | ||
304 | } | ||
305 | } | ||
291 | 306 | ||
292 | return err; | 307 | return 0; |
293 | } | 308 | } |
294 | 309 | ||
295 | static int scsi_bus_resume(struct device * dev) | 310 | static int scsi_bus_resume(struct device * dev) |
296 | { | 311 | { |
312 | struct device_driver *drv = dev->driver; | ||
297 | struct scsi_device *sdev = to_scsi_device(dev); | 313 | struct scsi_device *sdev = to_scsi_device(dev); |
298 | struct scsi_host_template *sht = sdev->host->hostt; | 314 | struct scsi_host_template *sht = sdev->host->hostt; |
299 | int err = 0; | 315 | int err = 0, err2 = 0; |
300 | 316 | ||
317 | /* call host resume first */ | ||
301 | if (sht->resume) | 318 | if (sht->resume) |
302 | err = sht->resume(sdev); | 319 | err = sht->resume(sdev); |
303 | 320 | ||
321 | /* then, call HLD resume */ | ||
322 | if (drv && drv->resume) | ||
323 | err2 = drv->resume(dev); | ||
324 | |||
304 | scsi_device_resume(sdev); | 325 | scsi_device_resume(sdev); |
305 | return err; | 326 | |
327 | /* favor LLD failure */ | ||
328 | return err ? err : err2;; | ||
306 | } | 329 | } |
307 | 330 | ||
308 | struct bus_type scsi_bus_type = { | 331 | struct bus_type scsi_bus_type = { |