diff options
Diffstat (limited to 'drivers/scsi/scsi_sysfs.c')
-rw-r--r-- | drivers/scsi/scsi_sysfs.c | 54 |
1 files changed, 50 insertions, 4 deletions
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 939de0de18bc..67a38a1409ba 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
@@ -276,8 +276,22 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv) | |||
276 | return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0; | 276 | return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0; |
277 | } | 277 | } |
278 | 278 | ||
279 | static int scsi_bus_uevent(struct device *dev, char **envp, int num_envp, | ||
280 | char *buffer, int buffer_size) | ||
281 | { | ||
282 | struct scsi_device *sdev = to_scsi_device(dev); | ||
283 | int i = 0; | ||
284 | int length = 0; | ||
285 | |||
286 | add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, | ||
287 | "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type); | ||
288 | envp[i] = NULL; | ||
289 | return 0; | ||
290 | } | ||
291 | |||
279 | static int scsi_bus_suspend(struct device * dev, pm_message_t state) | 292 | static int scsi_bus_suspend(struct device * dev, pm_message_t state) |
280 | { | 293 | { |
294 | struct device_driver *drv = dev->driver; | ||
281 | struct scsi_device *sdev = to_scsi_device(dev); | 295 | struct scsi_device *sdev = to_scsi_device(dev); |
282 | struct scsi_host_template *sht = sdev->host->hostt; | 296 | struct scsi_host_template *sht = sdev->host->hostt; |
283 | int err; | 297 | int err; |
@@ -286,28 +300,51 @@ static int scsi_bus_suspend(struct device * dev, pm_message_t state) | |||
286 | if (err) | 300 | if (err) |
287 | return err; | 301 | return err; |
288 | 302 | ||
289 | if (sht->suspend) | 303 | /* call HLD suspend first */ |
304 | if (drv && drv->suspend) { | ||
305 | err = drv->suspend(dev, state); | ||
306 | if (err) | ||
307 | return err; | ||
308 | } | ||
309 | |||
310 | /* then, call host suspend */ | ||
311 | if (sht->suspend) { | ||
290 | err = sht->suspend(sdev, state); | 312 | err = sht->suspend(sdev, state); |
313 | if (err) { | ||
314 | if (drv && drv->resume) | ||
315 | drv->resume(dev); | ||
316 | return err; | ||
317 | } | ||
318 | } | ||
291 | 319 | ||
292 | return err; | 320 | return 0; |
293 | } | 321 | } |
294 | 322 | ||
295 | static int scsi_bus_resume(struct device * dev) | 323 | static int scsi_bus_resume(struct device * dev) |
296 | { | 324 | { |
325 | struct device_driver *drv = dev->driver; | ||
297 | struct scsi_device *sdev = to_scsi_device(dev); | 326 | struct scsi_device *sdev = to_scsi_device(dev); |
298 | struct scsi_host_template *sht = sdev->host->hostt; | 327 | struct scsi_host_template *sht = sdev->host->hostt; |
299 | int err = 0; | 328 | int err = 0, err2 = 0; |
300 | 329 | ||
330 | /* call host resume first */ | ||
301 | if (sht->resume) | 331 | if (sht->resume) |
302 | err = sht->resume(sdev); | 332 | err = sht->resume(sdev); |
303 | 333 | ||
334 | /* then, call HLD resume */ | ||
335 | if (drv && drv->resume) | ||
336 | err2 = drv->resume(dev); | ||
337 | |||
304 | scsi_device_resume(sdev); | 338 | scsi_device_resume(sdev); |
305 | return err; | 339 | |
340 | /* favor LLD failure */ | ||
341 | return err ? err : err2;; | ||
306 | } | 342 | } |
307 | 343 | ||
308 | struct bus_type scsi_bus_type = { | 344 | struct bus_type scsi_bus_type = { |
309 | .name = "scsi", | 345 | .name = "scsi", |
310 | .match = scsi_bus_match, | 346 | .match = scsi_bus_match, |
347 | .uevent = scsi_bus_uevent, | ||
311 | .suspend = scsi_bus_suspend, | 348 | .suspend = scsi_bus_suspend, |
312 | .resume = scsi_bus_resume, | 349 | .resume = scsi_bus_resume, |
313 | }; | 350 | }; |
@@ -547,6 +584,14 @@ show_sdev_iostat(iorequest_cnt); | |||
547 | show_sdev_iostat(iodone_cnt); | 584 | show_sdev_iostat(iodone_cnt); |
548 | show_sdev_iostat(ioerr_cnt); | 585 | show_sdev_iostat(ioerr_cnt); |
549 | 586 | ||
587 | static ssize_t | ||
588 | sdev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf) | ||
589 | { | ||
590 | struct scsi_device *sdev; | ||
591 | sdev = to_scsi_device(dev); | ||
592 | return snprintf (buf, 20, SCSI_DEVICE_MODALIAS_FMT "\n", sdev->type); | ||
593 | } | ||
594 | static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL); | ||
550 | 595 | ||
551 | /* Default template for device attributes. May NOT be modified */ | 596 | /* Default template for device attributes. May NOT be modified */ |
552 | static struct device_attribute *scsi_sysfs_sdev_attrs[] = { | 597 | static struct device_attribute *scsi_sysfs_sdev_attrs[] = { |
@@ -566,6 +611,7 @@ static struct device_attribute *scsi_sysfs_sdev_attrs[] = { | |||
566 | &dev_attr_iorequest_cnt, | 611 | &dev_attr_iorequest_cnt, |
567 | &dev_attr_iodone_cnt, | 612 | &dev_attr_iodone_cnt, |
568 | &dev_attr_ioerr_cnt, | 613 | &dev_attr_ioerr_cnt, |
614 | &dev_attr_modalias, | ||
569 | NULL | 615 | NULL |
570 | }; | 616 | }; |
571 | 617 | ||