aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sd.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2010-06-16 14:52:17 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-07-28 10:07:50 -0400
commit478a8a0543021172220feeb0b39bb1b3e43c988f (patch)
treec80eb31436487294a43d23ad3869576a620fe1d3 /drivers/scsi/sd.c
parentbc4f24014de58f045f169742701a6598884d93db (diff)
[SCSI] sd: add support for runtime PM
This patch (as1399) adds runtime-PM support to the sd driver. The support is unsophisticated: If a SCSI disk device is mounted, or if its device file is held open, then the device will not be runtime-suspended; otherwise it will (provided userspace gives permission by writing "auto" to the sysfs power/control attribute). In order to make this work, a dev_set_drvdata() call had to be moved from sd_probe_async() to sd_probe(). Also, a few lines of code were changed to use a local variable instead of recalculating the address of an embedded struct device. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r--drivers/scsi/sd.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 8802e48bc063..cc8a1d1d915a 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -759,6 +759,10 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
759 759
760 sdev = sdkp->device; 760 sdev = sdkp->device;
761 761
762 retval = scsi_autopm_get_device(sdev);
763 if (retval)
764 goto error_autopm;
765
762 /* 766 /*
763 * If the device is in error recovery, wait until it is done. 767 * If the device is in error recovery, wait until it is done.
764 * If the device is offline, then disallow any access to it. 768 * If the device is offline, then disallow any access to it.
@@ -803,6 +807,8 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
803 return 0; 807 return 0;
804 808
805error_out: 809error_out:
810 scsi_autopm_put_device(sdev);
811error_autopm:
806 scsi_disk_put(sdkp); 812 scsi_disk_put(sdkp);
807 return retval; 813 return retval;
808} 814}
@@ -834,6 +840,8 @@ static int sd_release(struct gendisk *disk, fmode_t mode)
834 * XXX and what if there are packets in flight and this close() 840 * XXX and what if there are packets in flight and this close()
835 * XXX is followed by a "rmmod sd_mod"? 841 * XXX is followed by a "rmmod sd_mod"?
836 */ 842 */
843
844 scsi_autopm_put_device(sdev);
837 scsi_disk_put(sdkp); 845 scsi_disk_put(sdkp);
838 return 0; 846 return 0;
839} 847}
@@ -2232,7 +2240,6 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
2232 if (sdp->removable) 2240 if (sdp->removable)
2233 gd->flags |= GENHD_FL_REMOVABLE; 2241 gd->flags |= GENHD_FL_REMOVABLE;
2234 2242
2235 dev_set_drvdata(dev, sdkp);
2236 add_disk(gd); 2243 add_disk(gd);
2237 sd_dif_config_host(sdkp); 2244 sd_dif_config_host(sdkp);
2238 2245
@@ -2240,6 +2247,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
2240 2247
2241 sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", 2248 sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
2242 sdp->removable ? "removable " : ""); 2249 sdp->removable ? "removable " : "");
2250 scsi_autopm_put_device(sdp);
2243 put_device(&sdkp->dev); 2251 put_device(&sdkp->dev);
2244} 2252}
2245 2253
@@ -2317,14 +2325,15 @@ static int sd_probe(struct device *dev)
2317 } 2325 }
2318 2326
2319 device_initialize(&sdkp->dev); 2327 device_initialize(&sdkp->dev);
2320 sdkp->dev.parent = &sdp->sdev_gendev; 2328 sdkp->dev.parent = dev;
2321 sdkp->dev.class = &sd_disk_class; 2329 sdkp->dev.class = &sd_disk_class;
2322 dev_set_name(&sdkp->dev, dev_name(&sdp->sdev_gendev)); 2330 dev_set_name(&sdkp->dev, dev_name(dev));
2323 2331
2324 if (device_add(&sdkp->dev)) 2332 if (device_add(&sdkp->dev))
2325 goto out_free_index; 2333 goto out_free_index;
2326 2334
2327 get_device(&sdp->sdev_gendev); 2335 get_device(dev);
2336 dev_set_drvdata(dev, sdkp);
2328 2337
2329 get_device(&sdkp->dev); /* prevent release before async_schedule */ 2338 get_device(&sdkp->dev); /* prevent release before async_schedule */
2330 async_schedule(sd_probe_async, sdkp); 2339 async_schedule(sd_probe_async, sdkp);
@@ -2358,8 +2367,10 @@ static int sd_remove(struct device *dev)
2358{ 2367{
2359 struct scsi_disk *sdkp; 2368 struct scsi_disk *sdkp;
2360 2369
2361 async_synchronize_full();
2362 sdkp = dev_get_drvdata(dev); 2370 sdkp = dev_get_drvdata(dev);
2371 scsi_autopm_get_device(sdkp->device);
2372
2373 async_synchronize_full();
2363 blk_queue_prep_rq(sdkp->device->request_queue, scsi_prep_fn); 2374 blk_queue_prep_rq(sdkp->device->request_queue, scsi_prep_fn);
2364 device_del(&sdkp->dev); 2375 device_del(&sdkp->dev);
2365 del_gendisk(sdkp->disk); 2376 del_gendisk(sdkp->disk);