Commit 4e2ef86c authored by Chandra Seetharaman's avatar Chandra Seetharaman Committed by James Bottomley

[SCSI] scsi_dh: Make hp hardware handler's activate() async

Make the activate function asynchronous by using blk_execute_rq_nowait()
Signed-off-by: default avatarChandra Seetharaman <sekharan@us.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 970f3f47
...@@ -39,8 +39,14 @@ struct hp_sw_dh_data { ...@@ -39,8 +39,14 @@ struct hp_sw_dh_data {
unsigned char sense[SCSI_SENSE_BUFFERSIZE]; unsigned char sense[SCSI_SENSE_BUFFERSIZE];
int path_state; int path_state;
int retries; int retries;
int retry_cnt;
struct scsi_device *sdev;
activate_complete callback_fn;
void *callback_data;
}; };
static int hp_sw_start_stop(struct hp_sw_dh_data *);
static inline struct hp_sw_dh_data *get_hp_sw_data(struct scsi_device *sdev) static inline struct hp_sw_dh_data *get_hp_sw_data(struct scsi_device *sdev)
{ {
struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data; 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,19 +197,53 @@ static int start_done(struct scsi_device *sdev, unsigned char *sense)
return rc; return rc;
} }
static void start_stop_endio(struct request *req, int error)
{
struct hp_sw_dh_data *h = req->end_io_data;
unsigned err = SCSI_DH_OK;
if (error || host_byte(req->errors) != DID_OK ||
msg_byte(req->errors) != COMMAND_COMPLETE) {
sdev_printk(KERN_WARNING, h->sdev,
"%s: sending start_stop_unit failed with %x\n",
HP_SW_NAME, req->errors);
err = SCSI_DH_IO;
goto done;
}
if (req->sense_len > 0) {
err = start_done(h->sdev, h->sense);
if (err == SCSI_DH_RETRY) {
err = SCSI_DH_IO;
if (--h->retry_cnt) {
blk_put_request(req);
err = hp_sw_start_stop(h);
if (err == SCSI_DH_OK)
return;
}
}
}
done:
blk_put_request(req);
if (h->callback_fn) {
h->callback_fn(h->callback_data, err);
h->callback_fn = h->callback_data = NULL;
}
return;
}
/* /*
* hp_sw_start_stop - Send START STOP UNIT command * hp_sw_start_stop - Send START STOP UNIT command
* @sdev: sdev command should be sent to * @sdev: sdev command should be sent to
* *
* Sending START STOP UNIT activates the SP. * Sending START STOP UNIT activates the SP.
*/ */
static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h) static int hp_sw_start_stop(struct hp_sw_dh_data *h)
{ {
struct request *req; struct request *req;
int ret, retry;
retry: req = blk_get_request(h->sdev->request_queue, WRITE, GFP_ATOMIC);
req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO);
if (!req) if (!req)
return SCSI_DH_RES_TEMP_UNAVAIL; return SCSI_DH_RES_TEMP_UNAVAIL;
...@@ -217,32 +257,10 @@ static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h) ...@@ -217,32 +257,10 @@ static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h)
req->sense = h->sense; req->sense = h->sense;
memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE); memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
req->sense_len = 0; req->sense_len = 0;
retry = h->retries; req->end_io_data = h;
ret = blk_execute_rq(req->q, NULL, req, 1);
if (ret == -EIO) {
if (req->sense_len > 0) {
ret = start_done(sdev, h->sense);
} else {
sdev_printk(KERN_WARNING, sdev,
"%s: sending start_stop_unit failed with %x\n",
HP_SW_NAME, req->errors);
ret = SCSI_DH_IO;
}
} else
ret = SCSI_DH_OK;
if (ret == SCSI_DH_RETRY) {
if (--retry) {
blk_put_request(req);
goto retry;
}
ret = SCSI_DH_IO;
}
blk_put_request(req);
return ret; blk_execute_rq_nowait(req->q, NULL, req, 1, start_stop_endio);
return SCSI_DH_OK;
} }
static int hp_sw_prep_fn(struct scsi_device *sdev, struct request *req) 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,11 +295,13 @@ static int hp_sw_activate(struct scsi_device *sdev,
ret = hp_sw_tur(sdev, h); ret = hp_sw_tur(sdev, h);
if (ret == SCSI_DH_OK && h->path_state == HP_SW_PATH_PASSIVE) { if (ret == SCSI_DH_OK && h->path_state == HP_SW_PATH_PASSIVE) {
ret = hp_sw_start_stop(sdev, h); h->retry_cnt = h->retries;
h->callback_fn = fn;
h->callback_data = data;
ret = hp_sw_start_stop(h);
if (ret == SCSI_DH_OK) if (ret == SCSI_DH_OK)
sdev_printk(KERN_INFO, sdev, return 0;
"%s: activated path\n", h->callback_fn = h->callback_data = NULL;
HP_SW_NAME);
} }
if (fn) if (fn)
...@@ -329,6 +349,7 @@ static int hp_sw_bus_attach(struct scsi_device *sdev) ...@@ -329,6 +349,7 @@ static int hp_sw_bus_attach(struct scsi_device *sdev)
h = (struct hp_sw_dh_data *) scsi_dh_data->buf; h = (struct hp_sw_dh_data *) scsi_dh_data->buf;
h->path_state = HP_SW_PATH_UNINITIALIZED; h->path_state = HP_SW_PATH_UNINITIALIZED;
h->retries = HP_SW_RETRIES; h->retries = HP_SW_RETRIES;
h->sdev = sdev;
ret = hp_sw_tur(sdev, h); ret = hp_sw_tur(sdev, h);
if (ret != SCSI_DH_OK || h->path_state == HP_SW_PATH_UNINITIALIZED) if (ret != SCSI_DH_OK || h->path_state == HP_SW_PATH_UNINITIALIZED)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment