Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 13b53b44 authored by FUJITA Tomonori's avatar FUJITA Tomonori Committed by James Bottomley
Browse files

[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: default avatarFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Acked-by: default avatarKai Makisara <Kai.Makisara@kolumbus.fi>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent d0e1ae31
Loading
Loading
Loading
Loading
+54 −0
Original line number Diff line number Diff line
@@ -475,6 +475,60 @@ static void st_release_request(struct st_request *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.
   Otherwise write_behind_check() is used to check that the command
   has finished. */
+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ struct st_request {
	int result;
	struct scsi_tape *stp;
	struct completion *waiting;
	struct bio *bio;
};

/* The tape buffer descriptor. */