aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <JBottomley@Parallels.com>2013-05-10 10:54:01 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-05-10 10:54:01 -0400
commit297b8a07347555f0d2fafa4a1ddfc332d2d4afa9 (patch)
tree7c54ce22c1cd10118b5094441b8d7da2f4c58d6a
parent832e77bc1106592c621fc42f2f6a4500e414a0a1 (diff)
parent6df339a51e3bf18b868384bdeb31e49a4fbaa3d8 (diff)
Merge branch 'postmerge' into for-linus
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/scsi_lib.c9
-rw-r--r--drivers/scsi/scsi_pm.c84
-rw-r--r--drivers/scsi/sd.c22
-rw-r--r--include/scsi/scsi_device.h16
4 files changed, 93 insertions, 38 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index c31187d79343..86d522004a20 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -276,11 +276,10 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
276} 276}
277EXPORT_SYMBOL(scsi_execute); 277EXPORT_SYMBOL(scsi_execute);
278 278
279 279int scsi_execute_req_flags(struct scsi_device *sdev, const unsigned char *cmd,
280int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
281 int data_direction, void *buffer, unsigned bufflen, 280 int data_direction, void *buffer, unsigned bufflen,
282 struct scsi_sense_hdr *sshdr, int timeout, int retries, 281 struct scsi_sense_hdr *sshdr, int timeout, int retries,
283 int *resid) 282 int *resid, int flags)
284{ 283{
285 char *sense = NULL; 284 char *sense = NULL;
286 int result; 285 int result;
@@ -291,14 +290,14 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
291 return DRIVER_ERROR << 24; 290 return DRIVER_ERROR << 24;
292 } 291 }
293 result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen, 292 result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen,
294 sense, timeout, retries, 0, resid); 293 sense, timeout, retries, flags, resid);
295 if (sshdr) 294 if (sshdr)
296 scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr); 295 scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr);
297 296
298 kfree(sense); 297 kfree(sense);
299 return result; 298 return result;
300} 299}
301EXPORT_SYMBOL(scsi_execute_req); 300EXPORT_SYMBOL(scsi_execute_req_flags);
302 301
303/* 302/*
304 * Function: scsi_init_cmd_errh() 303 * Function: scsi_init_cmd_errh()
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index 8f6b12cbd224..42539ee2cb11 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -144,33 +144,83 @@ static int scsi_bus_restore(struct device *dev)
144 144
145#ifdef CONFIG_PM_RUNTIME 145#ifdef CONFIG_PM_RUNTIME
146 146
147static int sdev_blk_runtime_suspend(struct scsi_device *sdev,
148 int (*cb)(struct device *))
149{
150 int err;
151
152 err = blk_pre_runtime_suspend(sdev->request_queue);
153 if (err)
154 return err;
155 if (cb)
156 err = cb(&sdev->sdev_gendev);
157 blk_post_runtime_suspend(sdev->request_queue, err);
158
159 return err;
160}
161
162static int sdev_runtime_suspend(struct device *dev)
163{
164 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
165 int (*cb)(struct device *) = pm ? pm->runtime_suspend : NULL;
166 struct scsi_device *sdev = to_scsi_device(dev);
167 int err;
168
169 if (sdev->request_queue->dev)
170 return sdev_blk_runtime_suspend(sdev, cb);
171
172 err = scsi_dev_type_suspend(dev, cb);
173 if (err == -EAGAIN)
174 pm_schedule_suspend(dev, jiffies_to_msecs(
175 round_jiffies_up_relative(HZ/10)));
176 return err;
177}
178
147static int scsi_runtime_suspend(struct device *dev) 179static int scsi_runtime_suspend(struct device *dev)
148{ 180{
149 int err = 0; 181 int err = 0;
150 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
151 182
152 dev_dbg(dev, "scsi_runtime_suspend\n"); 183 dev_dbg(dev, "scsi_runtime_suspend\n");
153 if (scsi_is_sdev_device(dev)) { 184 if (scsi_is_sdev_device(dev))
154 err = scsi_dev_type_suspend(dev, 185 err = sdev_runtime_suspend(dev);
155 pm ? pm->runtime_suspend : NULL);
156 if (err == -EAGAIN)
157 pm_schedule_suspend(dev, jiffies_to_msecs(
158 round_jiffies_up_relative(HZ/10)));
159 }
160 186
161 /* Insert hooks here for targets, hosts, and transport classes */ 187 /* Insert hooks here for targets, hosts, and transport classes */
162 188
163 return err; 189 return err;
164} 190}
165 191
166static int scsi_runtime_resume(struct device *dev) 192static int sdev_blk_runtime_resume(struct scsi_device *sdev,
193 int (*cb)(struct device *))
167{ 194{
168 int err = 0; 195 int err = 0;
196
197 blk_pre_runtime_resume(sdev->request_queue);
198 if (cb)
199 err = cb(&sdev->sdev_gendev);
200 blk_post_runtime_resume(sdev->request_queue, err);
201
202 return err;
203}
204
205static int sdev_runtime_resume(struct device *dev)
206{
207 struct scsi_device *sdev = to_scsi_device(dev);
169 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 208 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
209 int (*cb)(struct device *) = pm ? pm->runtime_resume : NULL;
210
211 if (sdev->request_queue->dev)
212 return sdev_blk_runtime_resume(sdev, cb);
213 else
214 return scsi_dev_type_resume(dev, cb);
215}
216
217static int scsi_runtime_resume(struct device *dev)
218{
219 int err = 0;
170 220
171 dev_dbg(dev, "scsi_runtime_resume\n"); 221 dev_dbg(dev, "scsi_runtime_resume\n");
172 if (scsi_is_sdev_device(dev)) 222 if (scsi_is_sdev_device(dev))
173 err = scsi_dev_type_resume(dev, pm ? pm->runtime_resume : NULL); 223 err = sdev_runtime_resume(dev);
174 224
175 /* Insert hooks here for targets, hosts, and transport classes */ 225 /* Insert hooks here for targets, hosts, and transport classes */
176 226
@@ -185,10 +235,18 @@ static int scsi_runtime_idle(struct device *dev)
185 235
186 /* Insert hooks here for targets, hosts, and transport classes */ 236 /* Insert hooks here for targets, hosts, and transport classes */
187 237
188 if (scsi_is_sdev_device(dev)) 238 if (scsi_is_sdev_device(dev)) {
189 err = pm_schedule_suspend(dev, 100); 239 struct scsi_device *sdev = to_scsi_device(dev);
190 else 240
241 if (sdev->request_queue->dev) {
242 pm_runtime_mark_last_busy(dev);
243 err = pm_runtime_autosuspend(dev);
244 } else {
245 err = pm_runtime_suspend(dev);
246 }
247 } else {
191 err = pm_runtime_suspend(dev); 248 err = pm_runtime_suspend(dev);
249 }
192 return err; 250 return err;
193} 251}
194 252
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 196240dcf26e..c1c555242d0d 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1136,10 +1136,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
1136 1136
1137 sdev = sdkp->device; 1137 sdev = sdkp->device;
1138 1138
1139 retval = scsi_autopm_get_device(sdev);
1140 if (retval)
1141 goto error_autopm;
1142
1143 /* 1139 /*
1144 * If the device is in error recovery, wait until it is done. 1140 * If the device is in error recovery, wait until it is done.
1145 * If the device is offline, then disallow any access to it. 1141 * If the device is offline, then disallow any access to it.
@@ -1184,8 +1180,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
1184 return 0; 1180 return 0;
1185 1181
1186error_out: 1182error_out:
1187 scsi_autopm_put_device(sdev);
1188error_autopm:
1189 scsi_disk_put(sdkp); 1183 scsi_disk_put(sdkp);
1190 return retval;