From 478a8a0543021172220feeb0b39bb1b3e43c988f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 16 Jun 2010 14:52:17 -0400 Subject: [PATCH] [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 Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8802e48..cc8a1d1 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) sdev = sdkp->device; + retval = scsi_autopm_get_device(sdev); + if (retval) + goto error_autopm; + /* * If the device is in error recovery, wait until it is done. * 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) return 0; error_out: + scsi_autopm_put_device(sdev); +error_autopm: scsi_disk_put(sdkp); return retval; } @@ -834,6 +840,8 @@ static int sd_release(struct gendisk *disk, fmode_t mode) * XXX and what if there are packets in flight and this close() * XXX is followed by a "rmmod sd_mod"? */ + + scsi_autopm_put_device(sdev); scsi_disk_put(sdkp); return 0; } @@ -2232,7 +2240,6 @@ static void sd_probe_async(void *data, async_cookie_t cookie) if (sdp->removable) gd->flags |= GENHD_FL_REMOVABLE; - dev_set_drvdata(dev, sdkp); add_disk(gd); sd_dif_config_host(sdkp); @@ -2240,6 +2247,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie) sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", sdp->removable ? "removable " : ""); + scsi_autopm_put_device(sdp); put_device(&sdkp->dev); } @@ -2317,14 +2325,15 @@ static int sd_probe(struct device *dev) } device_initialize(&sdkp->dev); - sdkp->dev.parent = &sdp->sdev_gendev; + sdkp->dev.parent = dev; sdkp->dev.class = &sd_disk_class; - dev_set_name(&sdkp->dev, dev_name(&sdp->sdev_gendev)); + dev_set_name(&sdkp->dev, dev_name(dev)); if (device_add(&sdkp->dev)) goto out_free_index; - get_device(&sdp->sdev_gendev); + get_device(dev); + dev_set_drvdata(dev, sdkp); get_device(&sdkp->dev); /* prevent release before async_schedule */ async_schedule(sd_probe_async, sdkp); @@ -2358,8 +2367,10 @@ static int sd_remove(struct device *dev) { struct scsi_disk *sdkp; - async_synchronize_full(); sdkp = dev_get_drvdata(dev); + scsi_autopm_get_device(sdkp->device); + + async_synchronize_full(); blk_queue_prep_rq(sdkp->device->request_queue, scsi_prep_fn); device_del(&sdkp->dev); del_gendisk(sdkp->disk); -- 2.7.4