aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/osst.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/osst.c')
-rw-r--r--drivers/scsi/osst.c96
1 files changed, 83 insertions, 13 deletions
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 0ea78d9a37db..acb835837eec 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -280,8 +280,8 @@ static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
280 static int notyetprinted = 1; 280 static int notyetprinted = 1;
281 281
282 printk(KERN_WARNING 282 printk(KERN_WARNING
283 "%s:W: Warning %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n", 283 "%s:W: Warning %x (driver bt 0x%x, host bt 0x%x).\n",
284 name, result, suggestion(result), driver_byte(result) & DRIVER_MASK, 284 name, result, driver_byte(result),
285 host_byte(result)); 285 host_byte(result));
286 if (notyetprinted) { 286 if (notyetprinted) {
287 notyetprinted = 0; 287 notyetprinted = 0;
@@ -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) {
@@ -5286,11 +5361,6 @@ static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
5286 struct page *page = alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order); 5361 struct page *page = alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
5287 STbuffer->sg[segs].offset = 0; 5362 STbuffer->sg[segs].offset = 0;
5288 if (page == NULL) { 5363 if (page == NULL) {
5289 if (OS_FRAME_SIZE - got <= (max_segs - segs) * b_size / 2 && order) {
5290 b_size /= 2; /* Large enough for the rest of the buffers */
5291 order--;
5292 continue;
5293 }
5294 printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n", 5364 printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n",
5295 OS_FRAME_SIZE); 5365 OS_FRAME_SIZE);
5296#if DEBUG 5366#if DEBUG