diff options
Diffstat (limited to 'drivers/scsi/st.c')
-rw-r--r-- | drivers/scsi/st.c | 492 |
1 files changed, 222 insertions, 270 deletions
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 7f3f317ee6ca..c6f19ee8f2cb 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c | |||
@@ -17,7 +17,7 @@ | |||
17 | Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support | 17 | Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support |
18 | */ | 18 | */ |
19 | 19 | ||
20 | static const char *verstr = "20080504"; | 20 | static const char *verstr = "20081215"; |
21 | 21 | ||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | 23 | ||
@@ -182,18 +182,16 @@ static struct scsi_tape **scsi_tapes = NULL; | |||
182 | 182 | ||
183 | static int modes_defined; | 183 | static int modes_defined; |
184 | 184 | ||
185 | static struct st_buffer *new_tape_buffer(int, int, int); | ||
186 | static int enlarge_buffer(struct st_buffer *, int, int); | 185 | static int enlarge_buffer(struct st_buffer *, int, int); |
187 | static void clear_buffer(struct st_buffer *); | 186 | static void clear_buffer(struct st_buffer *); |
188 | static void normalize_buffer(struct st_buffer *); | 187 | static void normalize_buffer(struct st_buffer *); |
189 | static int append_to_buffer(const char __user *, struct st_buffer *, int); | 188 | static int append_to_buffer(const char __user *, struct st_buffer *, int); |
190 | static int from_buffer(struct st_buffer *, char __user *, int); | 189 | static int from_buffer(struct st_buffer *, char __user *, int); |
191 | static void move_buffer_data(struct st_buffer *, int); | 190 | static void move_buffer_data(struct st_buffer *, int); |
192 | static void buf_to_sg(struct st_buffer *, unsigned int); | ||
193 | 191 | ||
194 | static int sgl_map_user_pages(struct scatterlist *, const unsigned int, | 192 | static int sgl_map_user_pages(struct st_buffer *, const unsigned int, |
195 | unsigned long, size_t, int); | 193 | unsigned long, size_t, int); |
196 | static int sgl_unmap_user_pages(struct scatterlist *, const unsigned int, int); | 194 | static int sgl_unmap_user_pages(struct st_buffer *, const unsigned int, int); |
197 | 195 | ||
198 | static int st_probe(struct device *); | 196 | static int st_probe(struct device *); |
199 | static int st_remove(struct device *); | 197 | static int st_remove(struct device *); |
@@ -435,22 +433,6 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt) | |||
435 | return (-EIO); | 433 | return (-EIO); |
436 | } | 434 | } |
437 | 435 | ||
438 | |||
439 | /* Wakeup from interrupt */ | ||
440 | static void st_sleep_done(void *data, char *sense, int result, int resid) | ||
441 | { | ||
442 | struct st_request *SRpnt = data; | ||
443 | struct scsi_tape *STp = SRpnt->stp; | ||
444 | |||
445 | memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE); | ||
446 | (STp->buffer)->cmdstat.midlevel_result = SRpnt->result = result; | ||
447 | (STp->buffer)->cmdstat.residual = resid; | ||
448 | DEB( STp->write_pending = 0; ) | ||
449 | |||
450 | if (SRpnt->waiting) | ||
451 | complete(SRpnt->waiting); | ||
452 | } | ||
453 | |||
454 | static struct st_request *st_allocate_request(struct scsi_tape *stp) | 436 | static struct st_request *st_allocate_request(struct scsi_tape *stp) |
455 | { | 437 | { |
456 | struct st_request *streq; | 438 | struct st_request *streq; |
@@ -475,6 +457,63 @@ static void st_release_request(struct st_request *streq) | |||
475 | kfree(streq); | 457 | kfree(streq); |
476 | } | 458 | } |
477 | 459 | ||
460 | static void st_scsi_execute_end(struct request *req, int uptodate) | ||
461 | { | ||
462 | struct st_request *SRpnt = req->end_io_data; | ||
463 | struct scsi_tape *STp = SRpnt->stp; | ||
464 | |||
465 | STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors; | ||
466 | STp->buffer->cmdstat.residual = req->data_len; | ||
467 | |||
468 | if (SRpnt->waiting) | ||
469 | complete(SRpnt->waiting); | ||
470 | |||
471 | blk_rq_unmap_user(SRpnt->bio); | ||
472 | __blk_put_request(req->q, req); | ||
473 | } | ||
474 | |||
475 | static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd, | ||
476 | int data_direction, void *buffer, unsigned bufflen, | ||
477 | int timeout, int retries) | ||
478 | { | ||
479 | struct request *req; | ||
480 | struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data; | ||
481 | int err = 0; | ||
482 | int write = (data_direction == DMA_TO_DEVICE); | ||
483 | |||
484 | req = blk_get_request(SRpnt->stp->device->request_queue, write, | ||
485 | GFP_KERNEL); | ||
486 | if (!req) | ||
487 | return DRIVER_ERROR << 24; | ||
488 | |||
489 | req->cmd_type = REQ_TYPE_BLOCK_PC; | ||
490 | req->cmd_flags |= REQ_QUIET; | ||
491 | |||
492 | mdata->null_mapped = 1; | ||
493 | |||
494 | if (bufflen) { | ||
495 | err = blk_rq_map_user(req->q, req, mdata, NULL, bufflen, | ||
496 | GFP_KERNEL); | ||
497 | if (err) { | ||
498 | blk_put_request(req); | ||
499 | return DRIVER_ERROR << 24; | ||
500 | } | ||
501 | } | ||
502 | |||
503 | SRpnt->bio = req->bio; | ||
504 | req->cmd_len = COMMAND_SIZE(cmd[0]); | ||
505 | memset(req->cmd, 0, BLK_MAX_CDB); | ||
506 | memcpy(req->cmd, cmd, req->cmd_len); | ||
507 | req->sense = SRpnt->sense; | ||
508 | req->sense_len = 0; | ||
509 | req->timeout = timeout; | ||
510 | req->retries = retries; | ||
511 | req->end_io_data = SRpnt; | ||
512 | |||
513 | blk_execute_rq_nowait(req->q, NULL, req, 1, st_scsi_execute_end); | ||
514 | return 0; | ||
515 | } | ||
516 | |||
478 | /* Do the scsi command. Waits until command performed if do_wait is true. | 517 | /* Do the scsi command. Waits until command performed if do_wait is true. |
479 | Otherwise write_behind_check() is used to check that the command | 518 | Otherwise write_behind_check() is used to check that the command |
480 | has finished. */ | 519 | has finished. */ |
@@ -483,6 +522,8 @@ st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd | |||
483 | int bytes, int direction, int timeout, int retries, int do_wait) | 522 | int bytes, int direction, int timeout, int retries, int do_wait) |
484 | { | 523 | { |
485 | struct completion *waiting; | 524 | struct completion *waiting; |
525 | struct rq_map_data *mdata = &STp->buffer->map_data; | ||
526 | int ret; | ||
486 | 527 | ||
487 | /* if async, make sure there's no command outstanding */ | 528 | /* if async, make sure there's no command outstanding */ |
488 | if (!do_wait && ((STp->buffer)->last_SRpnt)) { | 529 | if (!do_wait && ((STp->buffer)->last_SRpnt)) { |
@@ -510,21 +551,27 @@ st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd | |||
510 | init_completion(waiting); | 551 | init_completion(waiting); |
511 | SRpnt->waiting = waiting; | 552 | SRpnt->waiting = waiting; |
512 | 553 | ||
513 | if (!STp->buffer->do_dio) | 554 | if (STp->buffer->do_dio) { |
514 | buf_to_sg(STp->buffer, bytes); | 555 | mdata->nr_entries = STp->buffer->sg_segs; |
556 | mdata->pages = STp->buffer->mapped_pages; | ||
557 | } else { | ||
558 | mdata->nr_entries = | ||
559 | DIV_ROUND_UP(bytes, PAGE_SIZE << mdata->page_order); | ||
560 | STp->buffer->map_data.pages = STp->buffer->reserved_pages; | ||
561 | STp->buffer->map_data.offset = 0; | ||
562 | } | ||
515 | 563 | ||
516 | memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd)); | 564 | memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd)); |
517 | STp->buffer->cmdstat.have_sense = 0; | 565 | STp->buffer->cmdstat.have_sense = 0; |
518 | STp->buffer->syscall_result = 0; | 566 | STp->buffer->syscall_result = 0; |
519 | 567 | ||
520 | if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction, | 568 | ret = st_scsi_execute(SRpnt, cmd, direction, NULL, bytes, timeout, |
521 | &((STp->buffer)->sg[0]), bytes, (STp->buffer)->sg_segs, | 569 | retries); |
522 | timeout, retries, SRpnt, st_sleep_done, GFP_KERNEL)) { | 570 | if (ret) { |
523 | /* could not allocate the buffer or request was too large */ | 571 | /* could not allocate the buffer or request was too large */ |
524 | (STp->buffer)->syscall_result = (-EBUSY); | 572 | (STp->buffer)->syscall_result = (-EBUSY); |
525 | (STp->buffer)->last_SRpnt = NULL; | 573 | (STp->buffer)->last_SRpnt = NULL; |
526 | } | 574 | } else if (do_wait) { |
527 | else if (do_wait) { | ||
528 | wait_for_completion(waiting); | 575 | wait_for_completion(waiting); |
529 | SRpnt->waiting = NULL; | 576 | SRpnt->waiting = NULL; |
530 | (STp->buffer)->syscall_result = st_chk_result(STp, SRpnt); | 577 | (STp->buffer)->syscall_result = st_chk_result(STp, SRpnt); |
@@ -533,28 +580,6 @@ st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd | |||
533 | return SRpnt; | 580 | return SRpnt; |
534 | } | 581 | } |
535 | 582 | ||
536 | static int st_scsi_kern_execute(struct st_request *streq, | ||
537 | const unsigned char *cmd, int data_direction, | ||
538 | void *buffer, unsigned bufflen, int timeout, | ||
539 | int retries) | ||
540 | { | ||
541 | struct scsi_tape *stp = streq->stp; | ||
542 | int ret, resid; | ||
543 | |||
544 | stp->buffer->cmdstat.have_sense = 0; | ||
545 | memcpy(streq->cmd, cmd, sizeof(streq->cmd)); | ||
546 | |||
547 | ret = scsi_execute(stp->device, cmd, data_direction, buffer, bufflen, | ||
548 | streq->sense, timeout, retries, 0, &resid); | ||
549 | if (driver_byte(ret) & DRIVER_ERROR) | ||
550 | return -EBUSY; | ||
551 | |||
552 | stp->buffer->cmdstat.midlevel_result = streq->result = ret; | ||
553 | stp->buffer->cmdstat.residual = resid; | ||
554 | stp->buffer->syscall_result = st_chk_result(stp, streq); | ||
555 | |||
556 | return 0; | ||
557 | } | ||
558 | 583 | ||
559 | /* Handle the write-behind checking (waits for completion). Returns -ENOSPC if | 584 | /* Handle the write-behind checking (waits for completion). Returns -ENOSPC if |
560 | write has been correct but EOM early warning reached, -EIO if write ended in | 585 | write has been correct but EOM early warning reached, -EIO if write ended in |
@@ -627,7 +652,6 @@ static int cross_eof(struct scsi_tape * STp, int forward) | |||
627 | { | 652 | { |
628 | struct st_request *SRpnt; | 653 | struct st_request *SRpnt; |
629 | unsigned char cmd[MAX_COMMAND_SIZE]; | 654 | unsigned char cmd[MAX_COMMAND_SIZE]; |
630 | int ret; | ||
631 | 655 | ||
632 | cmd[0] = SPACE; | 656 | cmd[0] = SPACE; |
633 | cmd[1] = 0x01; /* Space FileMarks */ | 657 | cmd[1] = 0x01; /* Space FileMarks */ |
@@ -641,26 +665,20 @@ static int cross_eof(struct scsi_tape * STp, int forward) | |||
641 | DEBC(printk(ST_DEB_MSG "%s: Stepping over filemark %s.\n", | 665 | DEBC(printk(ST_DEB_MSG "%s: Stepping over filemark %s.\n", |
642 | tape_name(STp), forward ? "forward" : "backward")); | 666 | tape_name(STp), forward ? "forward" : "backward")); |
643 | 667 | ||
644 | SRpnt = st_allocate_request(STp); | 668 | SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE, |
669 | STp->device->request_queue->rq_timeout, | ||
670 | MAX_RETRIES, 1); | ||
645 | if (!SRpnt) | 671 | if (!SRpnt) |
646 | return STp->buffer->syscall_result; | 672 | return (STp->buffer)->syscall_result; |
647 | |||
648 | ret = st_scsi_kern_execute(SRpnt, cmd, DMA_NONE, NULL, 0, | ||
649 | STp->device->request_queue->rq_timeout, | ||
650 | MAX_RETRIES); | ||
651 | if (ret) | ||
652 | goto out; | ||
653 | 673 | ||
654 | ret = STp->buffer->syscall_result; | 674 | st_release_request(SRpnt); |
675 | SRpnt = NULL; | ||
655 | 676 | ||
656 | if ((STp->buffer)->cmdstat.midlevel_result != 0) | 677 | if ((STp->buffer)->cmdstat.midlevel_result != 0) |
657 | printk(KERN_ERR "%s: Stepping over filemark %s failed.\n", | 678 | printk(KERN_ERR "%s: Stepping over filemark %s failed.\n", |
658 | tape_name(STp), forward ? "forward" : "backward"); | 679 | tape_name(STp), forward ? "forward" : "backward"); |
659 | 680 | ||
660 | out: | 681 | return (STp->buffer)->syscall_result; |
661 | st_release_request(SRpnt); | ||
662 | |||
663 | return ret; | ||
664 | } | 682 | } |
665 | 683 | ||
666 | 684 | ||
@@ -881,24 +899,21 @@ static int test_ready(struct scsi_tape *STp, int do_wait) | |||
881 | int attentions, waits, max_wait, scode; | 899 | int attentions, waits, max_wait, scode; |
882 | int retval = CHKRES_READY, new_session = 0; | 900 | int retval = CHKRES_READY, new_session = 0; |
883 | unsigned char cmd[MAX_COMMAND_SIZE]; | 901 | unsigned char cmd[MAX_COMMAND_SIZE]; |
884 | struct st_request *SRpnt; | 902 | struct st_request *SRpnt = NULL; |
885 | struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat; | 903 | struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat; |
886 | 904 | ||
887 | SRpnt = st_allocate_request(STp); | ||
888 | if (!SRpnt) | ||
889 | return STp->buffer->syscall_result; | ||
890 | |||
891 | max_wait = do_wait ? ST_BLOCK_SECONDS : 0; | 905 | max_wait = do_wait ? ST_BLOCK_SECONDS : 0; |
892 | 906 | ||
893 | for (attentions=waits=0; ; ) { | 907 | for (attentions=waits=0; ; ) { |
894 | memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE); | 908 | memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE); |
895 | cmd[0] = TEST_UNIT_READY; | 909 | cmd[0] = TEST_UNIT_READY; |
910 | SRpnt = st_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, | ||
911 | STp->long_timeout, MAX_READY_RETRIES, 1); | ||
896 | 912 | ||
897 | retval = st_scsi_kern_execute(SRpnt, cmd, DMA_NONE, NULL, 0, | 913 | if (!SRpnt) { |
898 | STp->long_timeout, | 914 | retval = (STp->buffer)->syscall_result; |
899 | MAX_READY_RETRIES); | ||
900 | if (retval) | ||
901 | break; | 915 | break; |
916 | } | ||
902 | 917 | ||
903 | if (cmdstatp->have_sense) { | 918 | if (cmdstatp->have_sense) { |
904 | 919 | ||
@@ -942,8 +957,8 @@ static int test_ready(struct scsi_tape *STp, int do_wait) | |||
942 | break; | 957 | break; |
943 | } | 958 | } |
944 | 959 | ||
945 | st_release_request(SRpnt); | 960 | if (SRpnt != NULL) |
946 | 961 | st_release_request(SRpnt); | |
947 | return retval; | 962 | return retval; |
948 | } | 963 | } |
949 | 964 | ||
@@ -1020,24 +1035,17 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) | |||
1020 | } | 1035 | } |
1021 | } | 1036 | } |
1022 | 1037 | ||
1023 | SRpnt = st_allocate_request(STp); | ||
1024 | if (!SRpnt) { | ||
1025 | retval = STp->buffer->syscall_result; | ||
1026 | goto err_out; | ||
1027 | } | ||
1028 | |||
1029 | if (STp->omit_blklims) | 1038 | if (STp->omit_blklims) |
1030 | STp->min_block = STp->max_block = (-1); | 1039 | STp->min_block = STp->max_block = (-1); |
1031 | else { | 1040 | else { |
1032 | memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE); | 1041 | memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE); |
1033 | cmd[0] = READ_BLOCK_LIMITS; | 1042 | cmd[0] = READ_BLOCK_LIMITS; |
1034 | 1043 | ||
1035 | retval = st_scsi_kern_execute(SRpnt, cmd, DMA_FROM_DEVICE, | 1044 | SRpnt = st_do_scsi(SRpnt, STp, cmd, 6, DMA_FROM_DEVICE, |
1036 | STp->buffer->b_data, 6, | 1045 | STp->device->request_queue->rq_timeout, |
1037 | STp->device->request_queue->rq_timeout, | 1046 | MAX_READY_RETRIES, 1); |
1038 | MAX_READY_RETRIES); | 1047 | if (!SRpnt) { |
1039 | if (retval) { | 1048 | retval = (STp->buffer)->syscall_result; |
1040 | st_release_request(SRpnt); | ||
1041 | goto err_out; | 1049 | goto err_out; |
1042 | } | 1050 | } |
1043 | 1051 | ||
@@ -1061,12 +1069,11 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) | |||
1061 | cmd[0] = MODE_SENSE; | 1069 | cmd[0] = MODE_SENSE; |
1062 | cmd[4] = 12; | 1070 | cmd[4] = 12; |
1063 | 1071 | ||
1064 | retval = st_scsi_kern_execute(SRpnt, cmd, DMA_FROM_DEVICE, | 1072 | SRpnt = st_do_scsi(SRpnt, STp, cmd, 12, DMA_FROM_DEVICE, |
1065 | STp->buffer->b_data, 12, | 1073 | STp->device->request_queue->rq_timeout, |
1066 | STp->device->request_queue->rq_timeout, | 1074 | MAX_READY_RETRIES, 1); |
1067 | MAX_READY_RETRIES); | 1075 | if (!SRpnt) { |
1068 | if (retval) { | 1076 | retval = (STp->buffer)->syscall_result; |
1069 | st_release_request(SRpnt); | ||
1070 | goto err_out; | 1077 | goto err_out; |
1071 | } | 1078 | } |
1072 | 1079 | ||
@@ -1296,17 +1303,11 @@ static int st_flush(struct file *filp, fl_owner_t id) | |||
1296 | cmd[0] = WRITE_FILEMARKS; | 1303 | cmd[0] = WRITE_FILEMARKS; |
1297 | cmd[4] = 1 + STp->two_fm; | 1304 | cmd[4] = 1 + STp->two_fm; |
1298 | 1305 | ||
1299 | SRpnt = st_allocate_request(STp); | 1306 | SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE, |
1307 | STp->device->request_queue->rq_timeout, | ||
1308 | MAX_WRITE_RETRIES, 1); | ||
1300 | if (!SRpnt) { | 1309 | if (!SRpnt) { |
1301 | result = STp->buffer->syscall_result; | 1310 | result = (STp->buffer)->syscall_result; |
1302 | goto out; | ||
1303 | } | ||
1304 | |||
1305 | result = st_scsi_kern_execute(SRpnt, cmd, DMA_NONE, NULL, 0, | ||
1306 | STp->device->request_queue->rq_timeout, | ||
1307 | MAX_WRITE_RETRIES); | ||
1308 | if (result) { | ||
1309 | st_release_request(SRpnt); | ||
1310 | goto out; | 1311 | goto out; |
1311 | } | 1312 | } |
1312 | 1313 | ||
@@ -1471,8 +1472,8 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf, | |||
1471 | 1472 | ||
1472 | if (i && ((unsigned long)buf & queue_dma_alignment( | 1473 | if (i && ((unsigned long)buf & queue_dma_alignment( |
1473 | STp->device->request_queue)) == 0) { | 1474 | STp->device->request_queue)) == 0) { |
1474 | i = sgl_map_user_pages(&(STbp->sg[0]), STbp->use_sg, | 1475 | i = sgl_map_user_pages(STbp, STbp->use_sg, (unsigned long)buf, |
1475 | (unsigned long)buf, count, (is_read ? READ : WRITE)); | 1476 | count, (is_read ? READ : WRITE)); |
1476 | if (i > 0) { | 1477 | if (i > 0) { |
1477 | STbp->do_dio = i; | 1478 | STbp->do_dio = i; |
1478 | STbp->buffer_bytes = 0; /* can be used as transfer counter */ | 1479 | STbp->buffer_bytes = 0; /* can be used as transfer counter */ |
@@ -1480,7 +1481,6 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf, | |||
1480 | else | 1481 | else |
1481 | STbp->do_dio = 0; /* fall back to buffering with any error */ | 1482 | STbp->do_dio = 0; /* fall back to buffering with any error */ |
1482 | STbp->sg_segs = STbp->do_dio; | 1483 | STbp->sg_segs = STbp->do_dio; |
1483 | STbp->frp_sg_current = 0; | ||
1484 | DEB( | 1484 | DEB( |
1485 | if (STbp->do_dio) { | 1485 | if (STbp->do_dio) { |
1486 | STp->nbr_dio++; | 1486 | STp->nbr_dio++; |
@@ -1526,7 +1526,7 @@ static void release_buffering(struct scsi_tape *STp, int is_read) | |||
1526 | 1526 | ||
1527 | STbp = STp->buffer; | 1527 | STbp = STp->buffer; |
1528 | if (STbp->do_dio) { | 1528 | if (STbp->do_dio) { |
1529 | sgl_unmap_user_pages(&(STbp->sg[0]), STbp->do_dio, is_read); | 1529 | sgl_unmap_user_pages(STbp, STbp->do_dio, is_read); |
1530 | STbp->do_dio = 0; | 1530 | STbp->do_dio = 0; |
1531 | STbp->sg_segs = 0; | 1531 | STbp->sg_segs = 0; |
1532 | } | 1532 | } |
@@ -2372,7 +2372,6 @@ static int read_mode_page(struct scsi_tape *STp, int page, int omit_block_descs) | |||
2372 | { | 2372 | { |
2373 | unsigned char cmd[MAX_COMMAND_SIZE]; | 2373 | unsigned char cmd[MAX_COMMAND_SIZE]; |
2374 | struct st_request *SRpnt; | 2374 | struct st_request *SRpnt; |
2375 | int ret; | ||
2376 | 2375 | ||
2377 | memset(cmd, 0, MAX_COMMAND_SIZE); | 2376 | memset(cmd, 0, MAX_COMMAND_SIZE); |
2378 | cmd[0] = MODE_SENSE; | 2377 | cmd[0] = MODE_SENSE; |
@@ -2381,17 +2380,14 @@ static int read_mode_page(struct scsi_tape *STp, int page, int omit_block_descs) | |||
2381 | cmd[2] = page; | 2380 | cmd[2] = page; |
2382 | cmd[4] = 255; | 2381 | cmd[4] = 255; |
2383 | 2382 | ||
2384 | SRpnt = st_allocate_request(STp); | 2383 | SRpnt = st_do_scsi(NULL, STp, cmd, cmd[4], DMA_FROM_DEVICE, |
2385 | if (!SRpnt) | 2384 | STp->device->request_queue->rq_timeout, 0, 1); |
2386 | return STp->buffer->syscall_result; | 2385 | if (SRpnt == NULL) |
2386 | return (STp->buffer)->syscall_result; | ||
2387 | 2387 | ||
2388 | ret = st_scsi_kern_execute(SRpnt, cmd, DMA_FROM_DEVICE, | ||
2389 | STp->buffer->b_data, cmd[4], | ||
2390 | STp->device->request_queue->rq_timeout, | ||
2391 | MAX_RETRIES); | ||
2392 | st_release_request(SRpnt); | 2388 | st_release_request(SRpnt); |
2393 | 2389 | ||
2394 | return ret ? : STp->buffer->syscall_result; | 2390 | return STp->buffer->syscall_result; |
2395 | } | 2391 | } |
2396 | 2392 | ||
2397 | 2393 | ||
@@ -2399,9 +2395,10 @@ static int read_mode_page(struct scsi_tape *STp, int page, int omit_block_descs) | |||
2399 | in the buffer is correctly formatted. The long timeout is used if slow is non-zero. */ | 2395 | in the buffer is correctly formatted. The long timeout is used if slow is non-zero. */ |
2400 | static int write_mode_page(struct scsi_tape *STp, int page, int slow) | 2396 | static int write_mode_page(struct scsi_tape *STp, int page, int slow) |
2401 | { | 2397 | { |
2402 | int pgo, timeout, ret = 0; | 2398 | int pgo; |
2403 | unsigned char cmd[MAX_COMMAND_SIZE]; | 2399 | unsigned char cmd[MAX_COMMAND_SIZE]; |
2404 | struct st_request *SRpnt; | 2400 | struct st_request *SRpnt; |
2401 | int timeout; | ||
2405 | 2402 | ||
2406 | memset(cmd, 0, MAX_COMMAND_SIZE); | 2403 | memset(cmd, 0, MAX_COMMAND_SIZE); |
2407 | cmd[0] = MODE_SELECT; | 2404 | cmd[0] = MODE_SELECT; |
@@ -2415,21 +2412,16 @@ static int write_mode_page(struct scsi_tape *STp, int page, int slow) | |||
2415 | (STp->buffer)->b_data[MH_OFF_DEV_SPECIFIC] &= ~MH_BIT_WP; | 2412 | (STp->buffer)->b_data[MH_OFF_DEV_SPECIFIC] &= ~MH_BIT_WP; |
2416 | (STp->buffer)->b_data[pgo + MP_OFF_PAGE_NBR] &= MP_MSK_PAGE_NBR; | 2413 | (STp->buffer)->b_data[pgo + MP_OFF_PAGE_NBR] &= MP_MSK_PAGE_NBR; |
2417 | 2414 | ||
2418 | SRpnt = st_allocate_request(STp); | 2415 | timeout = slow ? |
2419 | if (!SRpnt) | 2416 | STp->long_timeout : STp->device->request_queue->rq_timeout; |
2420 | return ret; | 2417 | SRpnt = st_do_scsi(NULL, STp, cmd, cmd[4], DMA_TO_DEVICE, |
2421 | 2418 | timeout, 0, 1); | |
2422 | timeout = slow ? STp->long_timeout : | 2419 | if (SRpnt == NULL) |
2423 | STp->device->request_queue->rq_timeout; | 2420 | return (STp->buffer)->syscall_result; |
2424 | |||
2425 | ret = st_scsi_kern_execute(SRpnt, cmd, DMA_TO_DEVICE, | ||
2426 | STp->buffer->b_data, cmd[4], timeout, 0); | ||
2427 | if (!ret) | ||
2428 | ret = STp->buffer->syscall_result; | ||
2429 | 2421 | ||
2430 | st_release_request(SRpnt); | 2422 | st_release_request(SRpnt); |
2431 | 2423 | ||
2432 | return ret; | 2424 | return STp->buffer->syscall_result; |
2433 | } | 2425 | } |
2434 | 2426 | ||
2435 | 2427 | ||
@@ -2547,16 +2539,13 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_cod | |||
2547 | printk(ST_DEB_MSG "%s: Loading tape.\n", name); | 2539 | printk(ST_DEB_MSG "%s: Loading tape.\n", name); |
2548 | ); | 2540 | ); |
2549 | 2541 | ||
2550 | SRpnt = st_allocate_request(STp); | 2542 | SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE, |
2543 | timeout, MAX_RETRIES, 1); | ||
2551 | if (!SRpnt) | 2544 | if (!SRpnt) |
2552 | return STp->buffer->syscall_result; | 2545 | return (STp->buffer)->syscall_result; |
2553 | |||
2554 | retval = st_scsi_kern_execute(SRpnt, cmd, DMA_NONE, NULL, 0, timeout, | ||
2555 | MAX_RETRIES); | ||
2556 | if (retval) | ||
2557 | goto out; | ||
2558 | 2546 | ||
2559 | retval = (STp->buffer)->syscall_result; | 2547 | retval = (STp->buffer)->syscall_result; |
2548 | st_release_request(SRpnt); | ||
2560 | 2549 | ||
2561 | if (!retval) { /* SCSI command successful */ | 2550 | if (!retval) { /* SCSI command successful */ |
2562 | 2551 | ||
@@ -2575,8 +2564,6 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_cod | |||
2575 | STps = &(STp->ps[STp->partition]); | 2564 | STps = &(STp->ps[STp->partition]); |
2576 | STps->drv_file = STps->drv_block = (-1); | 2565 | STps->drv_file = STps->drv_block = (-1); |
2577 | } | 2566 | } |
2578 | out: | ||
2579 | st_release_request(SRpnt); | ||
2580 | 2567 | ||
2581 | return retval; | 2568 | return retval; |
2582 | } | 2569 | } |
@@ -2852,15 +2839,12 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon | |||
2852 | return (-ENOSYS); | 2839 | return (-ENOSYS); |
2853 | } | 2840 | } |
2854 | 2841 | ||
2855 | SRpnt = st_allocate_request(STp); | 2842 | SRpnt = st_do_scsi(NULL, STp, cmd, datalen, direction, |
2843 | timeout, MAX_RETRIES, 1); | ||
2856 | if (!SRpnt) | 2844 | if (!SRpnt) |
2857 | return (STp->buffer)->syscall_result; | 2845 | return (STp->buffer)->syscall_result; |
2858 | 2846 | ||
2859 | ioctl_result = st_scsi_kern_execute(SRpnt, cmd, direction, | 2847 | ioctl_result = (STp->buffer)->syscall_result; |
2860 | STp->buffer->b_data, datalen, | ||
2861 | timeout, MAX_RETRIES); | ||
2862 | if (!ioctl_result) | ||
2863 | ioctl_result = (STp->buffer)->syscall_result; | ||
2864 | 2848 | ||
2865 | if (!ioctl_result) { /* SCSI command successful */ | 2849 | if (!ioctl_result) { /* SCSI command successful */ |
2866 | st_release_request(SRpnt); | 2850 | st_release_request(SRpnt); |
@@ -3022,17 +3006,11 @@ static int get_location(struct scsi_tape *STp, unsigned int *block, int *partiti | |||
3022 | if (!logical && !STp->scsi2_logical) | 3006 | if (!logical && !STp->scsi2_logical) |
3023 | scmd[1] = 1; | 3007 | scmd[1] = 1; |
3024 | } | 3008 | } |
3025 | 3009 | SRpnt = st_do_scsi(NULL, STp, scmd, 20, DMA_FROM_DEVICE, | |
3026 | SRpnt = st_allocate_request(STp); | 3010 | STp->device->request_queue->rq_timeout, |
3011 | MAX_READY_RETRIES, 1); | ||
3027 | if (!SRpnt) | 3012 | if (!SRpnt) |
3028 | return STp->buffer->syscall_result; | 3013 | return (STp->buffer)->syscall_result; |
3029 | |||
3030 | result = st_scsi_kern_execute(SRpnt, scmd, DMA_FROM_DEVICE, | ||
3031 | STp->buffer->b_data, 20, | ||
3032 | STp->device->request_queue->rq_timeout, | ||
3033 | MAX_READY_RETRIES); | ||
3034 | if (result) | ||
3035 | goto out; | ||
3036 | 3014 | ||
3037 | if ((STp->buffer)->syscall_result != 0 || | 3015 | if ((STp->buffer)->syscall_result != 0 || |
3038 | (STp->device->scsi_level >= SCSI_2 && | 3016 | (STp->device->scsi_level >= SCSI_2 && |
@@ -3060,7 +3038,6 @@ static int get_location(struct scsi_tape *STp, unsigned int *block, int *partiti | |||
3060 | DEBC(printk(ST_DEB_MSG "%s: Got tape pos. blk %d part %d.\n", name, | 3038 | DEBC(printk(ST_DEB_MSG "%s: Got tape pos. blk %d part %d.\n", name, |
3061 | *block, *partition)); | 3039 | *block, *partition)); |
3062 | } | 3040 | } |
3063 | out: | ||
3064 | st_release_request(SRpnt); | 3041 | st_release_request(SRpnt); |
3065 | SRpnt = NULL; | 3042 | SRpnt = NULL; |
3066 | 3043 | ||
@@ -3135,14 +3112,10 @@ static int set_location(struct scsi_tape *STp, unsigned int block, int partition | |||
3135 | timeout = STp->device->request_queue->rq_timeout; | 3112 | timeout = STp->device->request_queue->rq_timeout; |
3136 | } | 3113 | } |
3137 | 3114 | ||
3138 | SRpnt = st_allocate_request(STp); | 3115 | SRpnt = st_do_scsi(NULL, STp, scmd, 0, DMA_NONE, |
3116 | timeout, MAX_READY_RETRIES, 1); | ||
3139 | if (!SRpnt) | 3117 | if (!SRpnt) |
3140 | return STp->buffer->syscall_result; | 3118 | return (STp->buffer)->syscall_result; |
3141 | |||
3142 | result = st_scsi_kern_execute(SRpnt, scmd, DMA_NONE, NULL, 0, | ||
3143 | timeout, MAX_READY_RETRIES); | ||
3144 | if (result) | ||
3145 | goto out; | ||
3146 | 3119 | ||
3147 | STps->drv_block = STps->drv_file = (-1); | 3120 | STps->drv_block = STps->drv_file = (-1); |
3148 | STps->eof = ST_NOEOF; | 3121 | STps->eof = ST_NOEOF; |
@@ -3167,7 +3140,7 @@ static int set_location(struct scsi_tape *STp, unsigned int block, int partition | |||
3167 | STps->drv_block = STps->drv_file = 0; | 3140 | STps->drv_block = STps->drv_file = 0; |
3168 | result = 0; | 3141 | result = 0; |
3169 | } | 3142 | } |
3170 | out: | 3143 | |
3171 | st_release_request(SRpnt); | 3144 | st_release_request(SRpnt); |
3172 | SRpnt = NULL; | 3145 | SRpnt = NULL; |
3173 | 3146 | ||
@@ -3696,38 +3669,34 @@ static long st_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a | |||
3696 | 3669 | ||
3697 | /* Try to allocate a new tape buffer. Calling function must not hold | 3670 | /* Try to allocate a new tape buffer. Calling function must not hold |
3698 | dev_arr_lock. */ | 3671 | dev_arr_lock. */ |
3699 | static struct st_buffer * | 3672 | static struct st_buffer *new_tape_buffer(int need_dma, int max_sg) |
3700 | new_tape_buffer(int from_initialization, int need_dma, int max_sg) | ||
3701 | { | 3673 | { |
3702 | int i, got = 0; | ||
3703 | gfp_t priority; | ||
3704 | struct st_buffer *tb; | 3674 | struct st_buffer *tb; |
3705 | 3675 | ||
3706 | if (from_initialization) | 3676 | tb = kzalloc(sizeof(struct st_buffer), GFP_ATOMIC); |
3707 | priority = GFP_ATOMIC; | ||
3708 | else | ||
3709 | priority = GFP_KERNEL; | ||
3710 | |||
3711 | i = sizeof(struct st_buffer) + (max_sg - 1) * sizeof(struct scatterlist) + | ||
3712 | max_sg * sizeof(struct st_buf_fragment); | ||
3713 | tb = kzalloc(i, priority); | ||
3714 | if (!tb) { | 3677 | if (!tb) { |
3715 | printk(KERN_NOTICE "st: Can't allocate new tape buffer.\n"); | 3678 | printk(KERN_NOTICE "st: Can't allocate new tape buffer.\n"); |
3716 | return NULL; | 3679 | return NULL; |
3717 | } | 3680 | } |
3718 | tb->frp_segs = tb->orig_frp_segs = 0; | 3681 | tb->frp_segs = 0; |
3719 | tb->use_sg = max_sg; | 3682 | tb->use_sg = max_sg; |
3720 | tb->frp = (struct st_buf_fragment *)(&(tb->sg[0]) + max_sg); | ||
3721 | |||
3722 | tb->dma = need_dma; | 3683 | tb->dma = need_dma; |
3723 | tb->buffer_size = got; | 3684 | tb->buffer_size = 0; |
3724 | sg_init_table(tb->sg, max_sg); | 3685 | |
3686 | tb->reserved_pages = kzalloc(max_sg * sizeof(struct page *), | ||
3687 | GFP_ATOMIC); | ||
3688 | if (!tb->reserved_pages) { | ||
3689 | kfree(tb); | ||
3690 | return NULL; | ||
3691 | } | ||
3725 | 3692 | ||
3726 | return tb; | 3693 | return tb; |
3727 | } | 3694 | } |
3728 | 3695 | ||
3729 | 3696 | ||
3730 | /* Try to allocate enough space in the tape buffer */ | 3697 | /* Try to allocate enough space in the tape buffer */ |
3698 | #define ST_MAX_ORDER 6 | ||
3699 | |||
3731 | static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dma) | 3700 | static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dma) |
3732 | { | 3701 | { |
3733 | int segs, nbr, max_segs, b_size, order, got; | 3702 | int segs, nbr, max_segs, b_size, order, got; |
@@ -3747,33 +3716,45 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm | |||
3747 | priority = GFP_KERNEL | __GFP_NOWARN; | 3716 | priority = GFP_KERNEL | __GFP_NOWARN; |
3748 | if (need_dma) | 3717 | if (need_dma) |
3749 | priority |= GFP_DMA; | 3718 | priority |= GFP_DMA; |
3750 | for (b_size = PAGE_SIZE, order=0; order <= 6 && | 3719 | |
3751 | b_size < new_size - STbuffer->buffer_size; | 3720 | if (STbuffer->cleared) |
3752 | order++, b_size *= 2) | 3721 | priority |= __GFP_ZERO; |
3753 | ; /* empty */ | 3722 | |
3723 | if (STbuffer->frp_segs) { | ||
3724 | order = STbuffer->map_data.page_order; | ||
3725 | b_size = PAGE_SIZE << order; | ||
3726 | } else { | ||
3727 | for (b_size = PAGE_SIZE, order = 0; | ||
3728 | order < ST_MAX_ORDER && b_size < new_size; | ||
3729 | order++, b_size *= 2) | ||
3730 | ; /* empty */ | ||
3731 | } | ||
3732 | if (max_segs * (PAGE_SIZE << order) < new_size) { | ||
3733 | if (order == ST_MAX_ORDER) | ||
3734 | return 0; | ||
3735 | normalize_buffer(STbuffer); | ||
3736 | return enlarge_buffer(STbuffer, new_size, need_dma); | ||
3737 | } | ||
3754 | 3738 | ||
3755 | for (segs = STbuffer->frp_segs, got = STbuffer->buffer_size; | 3739 | for (segs = STbuffer->frp_segs, got = STbuffer->buffer_size; |
3756 | segs < max_segs && got < new_size;) { | 3740 | segs < max_segs && got < new_size;) { |
3757 | STbuffer->frp[segs].page = alloc_pages(priority, order); | 3741 | struct page *page; |
3758 | if (STbuffer->frp[segs].page == NULL) { | 3742 | |
3759 | if (new_size - got <= (max_segs - segs) * b_size / 2) { | 3743 | page = alloc_pages(priority, order); |
3760 | b_size /= 2; /* Large enough for the rest of the buffers */ | 3744 | if (!page) { |
3761 | order--; | ||
3762 | continue; | ||
3763 | } | ||
3764 | DEB(STbuffer->buffer_size = got); | 3745 | DEB(STbuffer->buffer_size = got); |
3765 | normalize_buffer(STbuffer); | 3746 | normalize_buffer(STbuffer); |
3766 | return 0; | 3747 | return 0; |
3767 | } | 3748 | } |
3768 | STbuffer->frp[segs].length = b_size; | 3749 | |
3769 | STbuffer->frp_segs += 1; | 3750 | STbuffer->frp_segs += 1; |
3770 | got += b_size; | 3751 | got += b_size; |
3771 | STbuffer->buffer_size = got; | 3752 | STbuffer->buffer_size = got; |
3772 | if (STbuffer->cleared) | 3753 | STbuffer->reserved_pages[segs] = page; |
3773 | memset(page_address(STbuffer->frp[segs].page), 0, b_size); | ||
3774 | segs++; | 3754 | segs++; |
3775 | } | 3755 | } |
3776 | STbuffer->b_data = page_address(STbuffer->frp[0].page); | 3756 | STbuffer->b_data = page_address(STbuffer->reserved_pages[0]); |
3757 | STbuffer->map_data.page_order = order; | ||
3777 | 3758 | ||
3778 | return 1; | 3759 | return 1; |
3779 | } | 3760 | } |
@@ -3785,7 +3766,8 @@ static void clear_buffer(struct st_buffer * st_bp) | |||
3785 | int i; | 3766 | int i; |
3786 | 3767 | ||
3787 | for (i=0; i < st_bp->frp_segs; i++) | 3768 | for (i=0; i < st_bp->frp_segs; i++) |
3788 | memset(page_address(st_bp->frp[i].page), 0, st_bp->frp[i].length); | 3769 | memset(page_address(st_bp->reserved_pages[i]), 0, |
3770 | PAGE_SIZE << st_bp->map_data.page_order); | ||
3789 | st_bp->cleared = 1; | 3771 | st_bp->cleared = 1; |
3790 | } | 3772 | } |
3791 | 3773 | ||
@@ -3793,16 +3775,16 @@ static void clear_buffer(struct st_buffer * st_bp) | |||
3793 | /* Release the extra buffer */ | 3775 | /* Release the extra buffer */ |
3794 | static void normalize_buffer(struct st_buffer * STbuffer) | 3776 | static void normalize_buffer(struct st_buffer * STbuffer) |
3795 | { | 3777 | { |
3796 | int i, order; | 3778 | int i, order = STbuffer->map_data.page_order; |
3797 | 3779 | ||
3798 | for (i = STbuffer->orig_frp_segs; i < STbuffer->frp_segs; i++) { | 3780 | for (i = 0; i < STbuffer->frp_segs; i++) { |
3799 | order = get_order(STbuffer->frp[i].length); | 3781 | __free_pages(STbuffer->reserved_pages[i], order); |
3800 | __free_pages(STbuffer->frp[i].page, order); | 3782 | STbuffer->buffer_size -= (PAGE_SIZE << order); |
3801 | STbuffer->buffer_size -= STbuffer->frp[i].length; | ||
3802 | } | 3783 | } |
3803 | STbuffer->frp_segs = STbuffer->orig_frp_segs; | 3784 | STbuffer->frp_segs = 0; |
3804 | STbuffer->frp_sg_current = 0; | ||
3805 | STbuffer->sg_segs = 0; | 3785 | STbuffer->sg_segs = 0; |
3786 | STbuffer->map_data.page_order = 0; | ||
3787 | STbuffer->map_data.offset = 0; | ||
3806 | } | 3788 | } |
3807 | 3789 | ||
3808 | 3790 | ||
@@ -3811,18 +3793,19 @@ static void normalize_buffer(struct st_buffer * STbuffer) | |||
3811 | static int append_to_buffer(const char __user *ubp, struct st_buffer * st_bp, int do_count) | 3793 | static int append_to_buffer(const char __user *ubp, struct st_buffer * st_bp, int do_count) |
3812 | { | 3794 | { |
3813 | int i, cnt, res, offset; | 3795 | int i, cnt, res, offset; |
3796 | int length = PAGE_SIZE << st_bp->map_data.page_order; | ||
3814 | 3797 | ||
3815 | for (i = 0, offset = st_bp->buffer_bytes; | 3798 | for (i = 0, offset = st_bp->buffer_bytes; |
3816 | i < st_bp->frp_segs && offset >= st_bp->frp[i].length; i++) | 3799 | i < st_bp->frp_segs && offset >= length; i++) |
3817 | offset -= st_bp->frp[i].length; | 3800 | offset -= length; |
3818 | if (i == st_bp->frp_segs) { /* Should never happen */ | 3801 | if (i == st_bp->frp_segs) { /* Should never happen */ |
3819 | printk(KERN_WARNING "st: append_to_buffer offset overflow.\n"); | 3802 | printk(KERN_WARNING "st: append_to_buffer offset overflow.\n"); |
3820 | return (-EIO); | 3803 | return (-EIO); |
3821 | } | 3804 | } |
3822 | for (; i < st_bp->frp_segs && do_count > 0; i++) { | 3805 | for (; i < st_bp->frp_segs && do_count > 0; i++) { |
3823 | cnt = st_bp->frp[i].length - offset < do_count ? | 3806 | struct page *page = st_bp->reserved_pages[i]; |
3824 | st_bp->frp[i].length - offset : do_count; | 3807 | cnt = length - offset < do_count ? length - offset : do_count; |
3825 | res = copy_from_user(page_address(st_bp->frp[i].page) + offset, ubp, cnt); | 3808 | res = copy_from_user(page_address(page) + offset, ubp, cnt); |
3826 | if (res) | 3809 | if (res) |
3827 | return (-EFAULT); | 3810 | return (-EFAULT); |
3828 | do_count -= cnt; | 3811 | do_count -= cnt; |
@@ -3842,18 +3825,19 @@ static int append_to_buffer(const char __user *ubp, struct st_buffer * st_bp, in | |||
3842 | static int from_buffer(struct st_buffer * st_bp, char __user *ubp, int do_count) | 3825 | static int from_buffer(struct st_buffer * st_bp, char __user *ubp, int do_count) |
3843 | { | 3826 | { |
3844 | int i, cnt, res, offset; | 3827 | int i, cnt, res, offset; |
3828 | int length = PAGE_SIZE << st_bp->map_data.page_order; | ||
3845 | 3829 | ||
3846 | for (i = 0, offset = st_bp->read_pointer; | 3830 | for (i = 0, offset = st_bp->read_pointer; |
3847 | i < st_bp->frp_segs && offset >= st_bp->frp[i].length; i++) | 3831 | i < st_bp->frp_segs && offset >= length; i++) |
3848 | offset -= st_bp->frp[i].length; | 3832 | offset -= length; |
3849 | if (i == st_bp->frp_segs) { /* Should never happen */ | 3833 | if (i == st_bp->frp_segs) { /* Should never happen */ |
3850 | printk(KERN_WARNING "st: from_buffer offset overflow.\n"); | 3834 | printk(KERN_WARNING "st: from_buffer offset overflow.\n"); |
3851 | return (-EIO); | 3835 | return (-EIO); |
3852 | } | 3836 | } |
3853 | for (; i < st_bp->frp_segs && do_count > 0; i++) { | 3837 | for (; i < st_bp->frp_segs && do_count > 0; i++) { |
3854 | cnt = st_bp->frp[i].length - offset < do_count ? | 3838 | struct page *page = st_bp->reserved_pages[i]; |
3855 | st_bp->frp[i].length - offset : do_count; | 3839 | cnt = length - offset < do_count ? length - offset : do_count; |
3856 | res = copy_to_user(ubp, page_address(st_bp->frp[i].page) + offset, cnt); | 3840 | res = copy_to_user(ubp, page_address(page) + offset, cnt); |
3857 | if (res) | 3841 | if (res) |
3858 | return (-EFAULT); | 3842 | return (-EFAULT); |
3859 | do_count -= cnt; | 3843 | do_count -= cnt; |
@@ -3874,6 +3858,7 @@ static void move_buffer_data(struct st_buffer * st_bp, int offset) | |||
3874 | { | 3858 | { |
3875 | int src_seg, dst_seg, src_offset = 0, dst_offset; | 3859 | int src_seg, dst_seg, src_offset = 0, dst_offset; |
3876 | int count, total; | 3860 | int count, total; |
3861 | int length = PAGE_SIZE << st_bp->map_data.page_order; | ||
3877 | 3862 | ||
3878 | if (offset == 0) | 3863 | if (offset == 0) |
3879 | return; | 3864 | return; |
@@ -3881,24 +3866,26 @@ static void move_buffer_data(struct st_buffer * st_bp, int offset) | |||
3881 | total=st_bp->buffer_bytes - offset; | 3866 | total=st_bp->buffer_bytes - offset; |
3882 | for (src_seg=0; src_seg < st_bp->frp_segs; src_seg++) { | 3867 | for (src_seg=0; src_seg < st_bp->frp_segs; src_seg++) { |
3883 | src_offset = offset; | 3868 | src_offset = offset; |
3884 | if (src_offset < st_bp->frp[src_seg].length) | 3869 | if (src_offset < length) |
3885 | break; | 3870 | break; |
3886 | offset -= st_bp->frp[src_seg].length; | 3871 | offset -= length; |
3887 | } | 3872 | } |
3888 | 3873 | ||
3889 | st_bp->buffer_bytes = st_bp->read_pointer = total; | 3874 | st_bp->buffer_bytes = st_bp->read_pointer = total; |
3890 | for (dst_seg=dst_offset=0; total > 0; ) { | 3875 | for (dst_seg=dst_offset=0; total > 0; ) { |
3891 | count = min(st_bp->frp[dst_seg].length - dst_offset, | 3876 | struct page *dpage = st_bp->reserved_pages[dst_seg]; |
3892 | st_bp->frp[src_seg].length - src_offset); | 3877 | struct page *spage = st_bp->reserved_pages[src_seg]; |
3893 | memmove(page_address(st_bp->frp[dst_seg].page) + dst_offset, | 3878 | |
3894 | page_address(st_bp->frp[src_seg].page) + src_offset, count); | 3879 | count = min(length - dst_offset, length - src_offset); |
3880 | memmove(page_address(dpage) + dst_offset, | ||
3881 | page_address(spage) + src_offset, count); | ||
3895 | src_offset += count; | 3882 | src_offset += count; |
3896 | if (src_offset >= st_bp->frp[src_seg].length) { | 3883 | if (src_offset >= length) { |
3897 | src_seg++; | 3884 | src_seg++; |
3898 | src_offset = 0; | 3885 | src_offset = 0; |
3899 | } | 3886 | } |
3900 | dst_offset += count; | 3887 | dst_offset += count; |
3901 | if (dst_offset >= st_bp->frp[dst_seg].length) { | 3888 | if (dst_offset >= length) { |
3902 | dst_seg++; | 3889 | dst_seg++; |
3903 | dst_offset = 0; | 3890 | dst_offset = 0; |
3904 | } | 3891 | } |
@@ -3906,32 +3893,6 @@ static void move_buffer_data(struct st_buffer * st_bp, int offset) | |||
3906 | } | 3893 | } |
3907 | } | 3894 | } |
3908 | 3895 | ||
3909 | |||
3910 | /* Fill the s/g list up to the length required for this transfer */ | ||
3911 | static void buf_to_sg(struct st_buffer *STbp, unsigned int length) | ||
3912 | { | ||
3913 | int i; | ||
3914 | unsigned int count; | ||
3915 | struct scatterlist *sg; | ||
3916 | struct st_buf_fragment *frp; | ||
3917 | |||
3918 | if (length == STbp->frp_sg_current) | ||
3919 | return; /* work already done */ | ||
3920 | |||
3921 | sg = &(STbp->sg[0]); | ||
3922 | frp = STbp->frp; | ||
3923 | for (i=count=0; count < length; i++) { | ||
3924 | if (length - count > frp[i].length) | ||
3925 | sg_set_page(&sg[i], frp[i].page, frp[i].length, 0); | ||
3926 | else | ||
3927 | sg_set_page(&sg[i], frp[i].page, length - count, 0); | ||
3928 | count += sg[i].length; | ||
3929 | } | ||
3930 | STbp->sg_segs = i; | ||
3931 | STbp->frp_sg_current = length; | ||
3932 | } | ||
3933 | |||
3934 | |||
3935 | /* Validate the options from command line or module parameters */ | 3896 | /* Validate the options from command line or module parameters */ |
3936 | static void validate_options(void) | 3897 | static void validate_options(void) |
3937 | { | 3898 | { |
@@ -4026,7 +3987,7 @@ static int st_probe(struct device *dev) | |||
4026 | SDp->request_queue->max_phys_segments); | 3987 | SDp->request_queue->max_phys_segments); |
4027 | if (st_max_sg_segs < i) | 3988 | if (st_max_sg_segs < i) |
4028 | i = st_max_sg_segs; | 3989 | i = st_max_sg_segs; |
4029 | buffer = new_tape_buffer(1, (SDp->host)->unchecked_isa_dma, i); | 3990 | buffer = new_tape_buffer((SDp->host)->unchecked_isa_dma, i); |
4030 | if (buffer == NULL) { | 3991 | if (buffer == NULL) { |
4031 | printk(KERN_ERR | 3992 | printk(KERN_ERR |
4032 | "st: Can't allocate new tape buffer. Device not attached.\n"); | 3993 | "st: Can't allocate new tape buffer. Device not attached.\n"); |
@@ -4280,8 +4241,8 @@ static void scsi_tape_release(struct kref *kref) | |||
4280 | tpnt->device = NULL; | 4241 | tpnt->device = NULL; |
4281 | 4242 | ||
4282 | if (tpnt->buffer) { | 4243 | if (tpnt->buffer) { |
4283 | tpnt->buffer->orig_frp_segs = 0; | ||
4284 | normalize_buffer(tpnt->buffer); | 4244 | normalize_buffer(tpnt->buffer); |
4245 | kfree(tpnt->buffer->reserved_pages); | ||
4285 | kfree(tpnt->buffer); | 4246 | kfree(tpnt->buffer); |
4286 | } | 4247 | } |
4287 | 4248 | ||
@@ -4567,14 +4528,16 @@ out: | |||
4567 | } | 4528 | } |
4568 | 4529 | ||
4569 | /* The following functions may be useful for a larger audience. */ | 4530 | /* The following functions may be useful for a larger audience. */ |
4570 | static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, | 4531 | static int sgl_map_user_pages(struct st_buffer *STbp, |
4571 | unsigned long uaddr, size_t count, int rw) | 4532 | const unsigned int max_pages, unsigned long uaddr, |
4533 | size_t count, int rw) | ||
4572 | { | 4534 | { |
4573 | unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT; | 4535 | unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT; |
4574 | unsigned long start = uaddr >> PAGE_SHIFT; | 4536 | unsigned long start = uaddr >> PAGE_SHIFT; |
4575 | const int nr_pages = end - start; | 4537 | const int nr_pages = end - start; |
4576 | int res, i, j; | 4538 | int res, i, j; |
4577 | struct page **pages; | 4539 | struct page **pages; |
4540 | struct rq_map_data *mdata = &STbp->map_data; | ||
4578 | 4541 | ||
4579 | /* User attempted Overflow! */ | 4542 | /* User attempted Overflow! */ |
4580 | if ((uaddr + count) < uaddr) | 4543 | if ((uaddr + count) < uaddr) |
@@ -4616,24 +4579,11 @@ static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pa | |||
4616 | flush_dcache_page(pages[i]); | 4579 | flush_dcache_page(pages[i]); |
4617 | } | 4580 | } |
4618 | 4581 | ||
4619 | /* Populate the scatter/gather list */ | 4582 | mdata->offset = uaddr & ~PAGE_MASK; |
4620 | sg_set_page(&sgl[0], pages[0], 0, uaddr & ~PAGE_MASK); | 4583 | mdata->page_order = 0; |
4621 | if (nr_pages > 1) { | 4584 | STbp->mapped_pages = pages; |
4622 | sgl[0].length = PAGE_SIZE - sgl[0].offset; | ||
4623 | count -= sgl[0].length; | ||
4624 | for (i=1; i < nr_pages ; i++) { | ||
4625 | sg_set_page(&sgl[i], pages[i], | ||
4626 | count < PAGE_SIZE ? count : PAGE_SIZE, 0);; | ||
4627 | count -= PAGE_SIZE; | ||
4628 | } | ||
4629 | } | ||
4630 | else { | ||
4631 | sgl[0].length = count; | ||
4632 | } | ||
4633 | 4585 | ||
4634 | kfree(pages); | ||
4635 | return nr_pages; | 4586 | return nr_pages; |
4636 | |||
4637 | out_unmap: | 4587 | out_unmap: |
4638 | if (res > 0) { | 4588 | if (res > 0) { |
4639 | for (j=0; j < res; j++) | 4589 | for (j=0; j < res; j++) |
@@ -4646,13 +4596,13 @@ static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pa | |||
4646 | 4596 | ||
4647 | 4597 | ||
4648 | /* And unmap them... */ | 4598 | /* And unmap them... */ |
4649 | static int sgl_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_pages, | 4599 | static int sgl_unmap_user_pages(struct st_buffer *STbp, |
4650 | int dirtied) | 4600 | const unsigned int nr_pages, int dirtied) |
4651 | { | 4601 | { |
4652 | int i; | 4602 | int i; |
4653 | 4603 | ||
4654 | for (i=0; i < nr_pages; i++) { | 4604 | for (i=0; i < nr_pages; i++) { |
4655 | struct page *page = sg_page(&sgl[i]); | 4605 | struct page *page = STbp->mapped_pages[i]; |
4656 | 4606 | ||
4657 | if (dirtied) | 4607 | if (dirtied) |
4658 | SetPageDirty(page); | 4608 | SetPageDirty(page); |
@@ -4661,6 +4611,8 @@ static int sgl_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_p | |||
4661 | */ | 4611 | */ |
4662 | page_cache_release(page); | 4612 | page_cache_release(page); |
4663 | } | 4613 | } |
4614 | kfree(STbp->mapped_pages); | ||
4615 | STbp->mapped_pages = NULL; | ||
4664 | 4616 | ||
4665 | return 0; | 4617 | return 0; |
4666 | } | 4618 | } |