aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorChandra Seetharaman <sekharan@us.ibm.com>2009-10-21 12:22:58 -0400
committerJames Bottomley <James.Bottomley@suse.de>2009-12-04 13:00:47 -0500
commit4e2ef86cd5ce057b60acea33bb71c06676e71888 (patch)
treeac043801ebd475a482aafe8d17412f31c42137bc /drivers/scsi
parent970f3f47e7c97c0bfe9f91356943b55ac389cb1d (diff)
[SCSI] scsi_dh: Make hp hardware handler's activate() async
Make the activate function asynchronous by using blk_execute_rq_nowait() Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/device_handler/scsi_dh_hp_sw.c87
1 files changed, 54 insertions, 33 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
index 0aacafc96f21..857fdd6032b2 100644
--- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c
+++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
@@ -39,8 +39,14 @@ struct hp_sw_dh_data {
39 unsigned char sense[SCSI_SENSE_BUFFERSIZE]; 39 unsigned char sense[SCSI_SENSE_BUFFERSIZE];
40 int path_state; 40 int path_state;
41 int retries; 41 int retries;
42 int retry_cnt;
43 struct scsi_device *sdev;
44 activate_complete callback_fn;
45 void *callback_data;
42}; 46};
43 47
48static int hp_sw_start_stop(struct hp_sw_dh_data *);
49
44static inline struct hp_sw_dh_data *get_hp_sw_data(struct scsi_device *sdev) 50static inline struct hp_sw_dh_data *get_hp_sw_data(struct scsi_device *sdev)
45{ 51{
46 struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data; 52 struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
@@ -191,19 +197,53 @@ static int start_done(struct scsi_device *sdev, unsigned char *sense)
191 return rc; 197 return rc;
192} 198}
193 199
200static void start_stop_endio(struct request *req, int error)
201{
202 struct hp_sw_dh_data *h = req->end_io_data;
203 unsigned err = SCSI_DH_OK;
204
205 if (error || host_byte(req->errors) != DID_OK ||
206 msg_byte(req->errors) != COMMAND_COMPLETE) {
207 sdev_printk(KERN_WARNING, h->sdev,
208 "%s: sending start_stop_unit failed with %x\n",
209 HP_SW_NAME, req->errors);
210 err = SCSI_DH_IO;
211 goto done;
212 }
213
214 if (req->sense_len > 0) {
215 err = start_done(h->sdev, h->sense);
216 if (err == SCSI_DH_RETRY) {
217 err = SCSI_DH_IO;
218 if (--h->retry_cnt) {
219 blk_put_request(req);
220 err = hp_sw_start_stop(h);
221 if (err == SCSI_DH_OK)
222 return;
223 }
224 }
225 }
226done:
227 blk_put_request(req);
228 if (h->callback_fn) {
229 h->callback_fn(h->callback_data, err);
230 h->callback_fn = h->callback_data = NULL;
231 }
232 return;
233
234}
235
194/* 236/*
195 * hp_sw_start_stop - Send START STOP UNIT command 237 * hp_sw_start_stop - Send START STOP UNIT command
196 * @sdev: sdev command should be sent to 238 * @sdev: sdev command should be sent to
197 * 239 *
198 * Sending START STOP UNIT activates the SP. 240 * Sending START STOP UNIT activates the SP.
199 */ 241 */
200static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h) 242static int hp_sw_start_stop(struct hp_sw_dh_data *h)
201{ 243{
202 struct request *req; 244 struct request *req;
203 int ret, retry;
204 245
205retry: 246 req = blk_get_request(h->sdev->request_queue, WRITE, GFP_ATOMIC);
206 req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO);
207 if (!req) 247 if (!req)
208 return SCSI_DH_RES_TEMP_UNAVAIL; 248 return SCSI_DH_RES_TEMP_UNAVAIL;
209 249
@@ -217,32 +257,10 @@ retry:
217 req->sense = h->sense; 257 req->sense = h->sense;
218 memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE); 258 memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
219 req->sense_len = 0; 259 req->sense_len = 0;
220 retry = h->retries; 260 req->end_io_data = h;
221
222 ret = blk_execute_rq(req->q, NULL, req, 1);
223 if (ret == -EIO) {
224 if (req->sense_len > 0) {
225 ret = start_done(sdev, h->sense);
226 } else {
227 sdev_printk(KERN_WARNING, sdev,
228 "%s: sending start_stop_unit failed with %x\n",
229 HP_SW_NAME, req->errors);
230 ret = SCSI_DH_IO;
231 }
232 } else
233 ret = SCSI_DH_OK;
234
235 if (ret == SCSI_DH_RETRY) {
236 if (--retry) {
237 blk_put_request(req);
238 goto retry;
239 }
240 ret = SCSI_DH_IO;
241 }
242
243 blk_put_request(req);
244 261
245 return ret; 262 blk_execute_rq_nowait(req->q, NULL, req, 1, start_stop_endio);
263 return SCSI_DH_OK;
246} 264}
247 265
248static int hp_sw_prep_fn(struct scsi_device *sdev, struct request *req) 266static int hp_sw_prep_fn(struct scsi_device *sdev, struct request *req)
@@ -277,11 +295,13 @@ static int hp_sw_activate(struct scsi_device *sdev,
277 ret = hp_sw_tur(sdev, h); 295 ret = hp_sw_tur(sdev, h);
278 296
279 if (ret == SCSI_DH_OK && h->path_state == HP_SW_PATH_PASSIVE) { 297 if (ret == SCSI_DH_OK && h->path_state == HP_SW_PATH_PASSIVE) {
280 ret = hp_sw_start_stop(sdev, h); 298 h->retry_cnt = h->retries;
299 h->callback_fn = fn;
300 h->callback_data = data;
301 ret = hp_sw_start_stop(h);
281 if (ret == SCSI_DH_OK) 302 if (ret == SCSI_DH_OK)
282 sdev_printk(KERN_INFO, sdev, 303 return 0;
283 "%s: activated path\n", 304 h->callback_fn = h->callback_data = NULL;
284 HP_SW_NAME);
285 } 305 }
286 306
287 if (fn) 307 if (fn)
@@ -329,6 +349,7 @@ static int hp_sw_bus_attach(struct scsi_device *sdev)
329 h = (struct hp_sw_dh_data *) scsi_dh_data->buf; 349 h = (struct hp_sw_dh_data *) scsi_dh_data->buf;
330 h->path_state = HP_SW_PATH_UNINITIALIZED; 350 h->path_state = HP_SW_PATH_UNINITIALIZED;
331 h->retries = HP_SW_RETRIES; 351 h->retries = HP_SW_RETRIES;
352 h->sdev = sdev;
332 353
333 ret = hp_sw_tur(sdev, h); 354 ret = hp_sw_tur(sdev, h);
334 if (ret != SCSI_DH_OK || h->path_state == HP_SW_PATH_UNINITIALIZED) 355 if (ret != SCSI_DH_OK || h->path_state == HP_SW_PATH_UNINITIALIZED)