diff options
author | Chandra Seetharaman <sekharan@us.ibm.com> | 2009-10-21 12:22:58 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-12-04 13:00:47 -0500 |
commit | 4e2ef86cd5ce057b60acea33bb71c06676e71888 (patch) | |
tree | ac043801ebd475a482aafe8d17412f31c42137bc /drivers/scsi | |
parent | 970f3f47e7c97c0bfe9f91356943b55ac389cb1d (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.c | 87 |
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 | ||
48 | static int hp_sw_start_stop(struct hp_sw_dh_data *); | ||
49 | |||
44 | static inline struct hp_sw_dh_data *get_hp_sw_data(struct scsi_device *sdev) | 50 | static 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 | ||
200 | static 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 | } | ||
226 | done: | ||
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 | */ |
200 | static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h) | 242 | static 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 | ||
205 | retry: | 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 | ||
248 | static int hp_sw_prep_fn(struct scsi_device *sdev, struct request *req) | 266 | static 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) |