[SCSI] st: add st_scsi_execute helper function
st_scsi_execute is a helper function to perform SCSI commands involving data transfer between user and kernel space (st_read and st_write). It's the future plan to combine this with st_scsi_kern_execute helper function. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Acked-by: Kai Makisara <Kai.Makisara@kolumbus.fi> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
committed by
James Bottomley
parent
d0e1ae31be
commit
13b53b4434
@@ -475,6 +475,60 @@ static void st_release_request(struct st_request *streq)
|
|||||||
kfree(streq);
|
kfree(streq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void st_scsi_execute_end(struct request *req, int uptodate)
|
||||||
|
{
|
||||||
|
struct st_request *SRpnt = req->end_io_data;
|
||||||
|
struct scsi_tape *STp = SRpnt->stp;
|
||||||
|
|
||||||
|
STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors;
|
||||||
|
STp->buffer->cmdstat.residual = req->data_len;
|
||||||
|
|
||||||
|
if (SRpnt->waiting)
|
||||||
|
complete(SRpnt->waiting);
|
||||||
|
|
||||||
|
blk_rq_unmap_user(SRpnt->bio);
|
||||||
|
__blk_put_request(req->q, req);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd,
|
||||||
|
int data_direction, void *buffer, unsigned bufflen,
|
||||||
|
int timeout, int retries)
|
||||||
|
{
|
||||||
|
struct request *req;
|
||||||
|
struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
|
||||||
|
int err = 0;
|
||||||
|
int write = (data_direction == DMA_TO_DEVICE);
|
||||||
|
|
||||||
|
req = blk_get_request(SRpnt->stp->device->request_queue, write,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!req)
|
||||||
|
return DRIVER_ERROR << 24;
|
||||||
|
|
||||||
|
req->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||||
|
req->cmd_flags |= REQ_QUIET;
|
||||||
|
|
||||||
|
mdata->null_mapped = 1;
|
||||||
|
|
||||||
|
err = blk_rq_map_user(req->q, req, mdata, NULL, bufflen, GFP_KERNEL);
|
||||||
|
if (err) {
|
||||||
|
blk_put_request(req);
|
||||||
|
return DRIVER_ERROR << 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRpnt->bio = req->bio;
|
||||||
|
req->cmd_len = COMMAND_SIZE(cmd[0]);
|
||||||
|
memset(req->cmd, 0, BLK_MAX_CDB);
|
||||||
|
memcpy(req->cmd, cmd, req->cmd_len);
|
||||||
|
req->sense = SRpnt->sense;
|
||||||
|
req->sense_len = 0;
|
||||||
|
req->timeout = timeout;
|
||||||
|
req->retries = retries;
|
||||||
|
req->end_io_data = SRpnt;
|
||||||
|
|
||||||
|
blk_execute_rq_nowait(req->q, NULL, req, 1, st_scsi_execute_end);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Do the scsi command. Waits until command performed if do_wait is true.
|
/* Do the scsi command. Waits until command performed if do_wait is true.
|
||||||
Otherwise write_behind_check() is used to check that the command
|
Otherwise write_behind_check() is used to check that the command
|
||||||
has finished. */
|
has finished. */
|
||||||
|
@@ -29,6 +29,7 @@ struct st_request {
|
|||||||
int result;
|
int result;
|
||||||
struct scsi_tape *stp;
|
struct scsi_tape *stp;
|
||||||
struct completion *waiting;
|
struct completion *waiting;
|
||||||
|
struct bio *bio;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The tape buffer descriptor. */
|
/* The tape buffer descriptor. */
|
||||||
|
Reference in New Issue
Block a user