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 | |
| 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>
| -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) |
