aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/osst.c
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2008-12-13 10:55:18 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-03-12 13:58:10 -0400
commit26243043f207b3faa00594a33e10b2103205f27b (patch)
tree0be6196be00ee0f3ded7ec0244136a27fdc04304 /drivers/scsi/osst.c
parent78a42ce8fb2604c459e9ebb2a4f2d546b8250111 (diff)
[SCSI] osst: replace scsi_execute_async with the block layer API
This replaces scsi_execute_async with the block layer API. st does the same thing so it might make sense to have something like libst (there are other things that os and osst can share). Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Cc: Willem Riede <osst@riede.org> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/osst.c')
-rw-r--r--drivers/scsi/osst.c87
1 files changed, 81 insertions, 6 deletions
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 13f908cb0674..acb835837eec 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -317,18 +317,25 @@ static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
317 317
318 318
319/* Wakeup from interrupt */ 319/* Wakeup from interrupt */
320static void osst_sleep_done(void *data, char *sense, int result, int resid) 320static void osst_end_async(struct request *req, int update)
321{ 321{
322 struct osst_request *SRpnt = data; 322 struct osst_request *SRpnt = req->end_io_data;
323 struct osst_tape *STp = SRpnt->stp; 323 struct osst_tape *STp = SRpnt->stp;
324 struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
324 325
325 memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE); 326 STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors;
326 STp->buffer->cmdstat.midlevel_result = SRpnt->result = result;
327#if DEBUG 327#if DEBUG
328 STp->write_pending = 0; 328 STp->write_pending = 0;
329#endif 329#endif
330 if (SRpnt->waiting) 330 if (SRpnt->waiting)
331 complete(SRpnt->waiting); 331 complete(SRpnt->waiting);
332
333 if (SRpnt->bio) {
334 kfree(mdata->pages);
335 blk_rq_unmap_user(SRpnt->bio);
336 }
337
338 __blk_put_request(req->q, req);
332} 339}
333 340
334/* osst_request memory management */ 341/* osst_request memory management */
@@ -342,6 +349,74 @@ static void osst_release_request(struct osst_request *streq)
342 kfree(streq); 349 kfree(streq);
343} 350}
344 351
352static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd,
353 int cmd_len, int data_direction, void *buffer, unsigned bufflen,
354 int use_sg, int timeout, int retries)
355{
356 struct request *req;
357 struct page **pages = NULL;
358 struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
359
360 int err = 0;
361 int write = (data_direction == DMA_TO_DEVICE);
362
363 req = blk_get_request(SRpnt->stp->device->request_queue, write, GFP_KERNEL);
364 if (!req)
365 return DRIVER_ERROR << 24;
366
367 req->cmd_type = REQ_TYPE_BLOCK_PC;
368 req->cmd_flags |= REQ_QUIET;
369
370 SRpnt->bio = NULL;
371
372 if (use_sg) {
373 struct scatterlist *sg, *sgl = (struct scatterlist *)buffer;
374 int i;
375
376 pages = kzalloc(use_sg * sizeof(struct page *), GFP_KERNEL);
377 if (!pages)
378 goto free_req;
379
380 for_each_sg(sgl, sg, use_sg, i)
381 pages[i] = sg_page(sg);
382
383 mdata->null_mapped = 1;
384
385 mdata->page_order = get_order(sgl[0].length);
386 mdata->nr_entries =
387 DIV_ROUND_UP(bufflen, PAGE_SIZE << mdata->page_order);
388 mdata->offset = 0;
389
390 err = blk_rq_map_user(req->q, req, mdata, NULL, bufflen, GFP_KERNEL);
391 if (err) {
392 kfree(pages);
393 goto free_req;
394 }
395 SRpnt->bio = req->bio;
396 mdata->pages = pages;
397
398 } else if (bufflen) {
399 err = blk_rq_map_kern(req->q, req, buffer, bufflen, GFP_KERNEL);
400 if (err)
401 goto free_req;
402 }
403
404 req->cmd_len = cmd_len;
405 memset(req->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
406 memcpy(req->cmd, cmd, req->cmd_len);
407 req->sense = SRpnt->sense;
408 req->sense_len = 0;
409 req->timeout = timeout;
410 req->retries = retries;
411 req->end_io_data = SRpnt;
412
413 blk_execute_rq_nowait(req->q, NULL, req, 1, osst_end_async);
414 return 0;
415free_req:
416 blk_put_request(req);
417 return DRIVER_ERROR << 24;
418}
419
345/* Do the scsi command. Waits until command performed if do_wait is true. 420/* Do the scsi command. Waits until command performed if do_wait is true.
346 Otherwise osst_write_behind_check() is used to check that the command 421 Otherwise osst_write_behind_check() is used to check that the command
347 has finished. */ 422 has finished. */
@@ -403,8 +478,8 @@ static struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct oss
403 STp->buffer->cmdstat.have_sense = 0; 478 STp->buffer->cmdstat.have_sense = 0;
404 STp->buffer->syscall_result = 0; 479 STp->buffer->syscall_result = 0;
405 480
406 if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes, 481 if (osst_execute(SRpnt, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes,
407 use_sg, timeout, retries, SRpnt, osst_sleep_done, GFP_KERNEL)) 482 use_sg, timeout, retries))
408 /* could not allocate the buffer or request was too large */ 483 /* could not allocate the buffer or request was too large */
409 (STp->buffer)->syscall_result = (-EBUSY); 484 (STp->buffer)->syscall_result = (-EBUSY);
410 else if (do_wait) { 485 else if (do_wait) {