diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ide/ide-tape.c | 110 |
1 files changed, 46 insertions, 64 deletions
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index d2e9c09b5215..4da7fa9bca1e 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
@@ -987,42 +987,50 @@ static void ide_tape_flush_merge_buffer(ide_drive_t *drive) | |||
987 | tape->chrdev_dir = IDETAPE_DIR_NONE; | 987 | tape->chrdev_dir = IDETAPE_DIR_NONE; |
988 | } | 988 | } |
989 | 989 | ||
990 | static int idetape_init_read(ide_drive_t *drive) | 990 | static int idetape_init_rw(ide_drive_t *drive, int dir) |
991 | { | 991 | { |
992 | idetape_tape_t *tape = drive->driver_data; | 992 | idetape_tape_t *tape = drive->driver_data; |
993 | int bytes_read; | 993 | int rc; |
994 | 994 | ||
995 | /* Initialize read operation */ | 995 | BUG_ON(dir != IDETAPE_DIR_READ && dir != IDETAPE_DIR_WRITE); |
996 | if (tape->chrdev_dir != IDETAPE_DIR_READ) { | ||
997 | if (tape->chrdev_dir == IDETAPE_DIR_WRITE) { | ||
998 | ide_tape_flush_merge_buffer(drive); | ||
999 | idetape_flush_tape_buffers(drive); | ||
1000 | } | ||
1001 | if (tape->buf || tape->valid) { | ||
1002 | printk(KERN_ERR "ide-tape: valid should be 0 now\n"); | ||
1003 | tape->valid = 0; | ||
1004 | } | ||
1005 | tape->buf = kmalloc(tape->buffer_size, GFP_KERNEL); | ||
1006 | if (!tape->buf) | ||
1007 | return -ENOMEM; | ||
1008 | tape->chrdev_dir = IDETAPE_DIR_READ; | ||
1009 | tape->cur = tape->buf; | ||
1010 | 996 | ||
1011 | /* | 997 | if (tape->chrdev_dir == dir) |
1012 | * Issue a read 0 command to ensure that DSC handshake is | 998 | return 0; |
1013 | * switched from completion mode to buffer available mode. | 999 | |
1014 | * No point in issuing this if DSC overlap isn't supported, some | 1000 | if (tape->chrdev_dir == IDETAPE_DIR_READ) |
1015 | * drives (Seagate STT3401A) will return an error. | 1001 | ide_tape_discard_merge_buffer(drive, 1); |
1016 | */ | 1002 | else if (tape->chrdev_dir == IDETAPE_DIR_WRITE) { |
1017 | if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) { | 1003 | ide_tape_flush_merge_buffer(drive); |
1018 | bytes_read = idetape_queue_rw_tail(drive, | 1004 | idetape_flush_tape_buffers(drive); |
1019 | REQ_IDETAPE_READ, 0); | 1005 | } |
1020 | if (bytes_read < 0) { | 1006 | |
1021 | kfree(tape->buf); | 1007 | if (tape->buf || tape->valid) { |
1022 | tape->buf = NULL; | 1008 | printk(KERN_ERR "ide-tape: valid should be 0 now\n"); |
1023 | tape->chrdev_dir = IDETAPE_DIR_NONE; | 1009 | tape->valid = 0; |
1024 | return bytes_read; | 1010 | } |
1025 | } | 1011 | |
1012 | tape->buf = kmalloc(tape->buffer_size, GFP_KERNEL); | ||
1013 | if (!tape->buf) | ||
1014 | return -ENOMEM; | ||
1015 | tape->chrdev_dir = dir; | ||
1016 | tape->cur = tape->buf; | ||
1017 | |||
1018 | /* | ||
1019 | * Issue a 0 rw command to ensure that DSC handshake is | ||
1020 | * switched from completion mode to buffer available mode. No | ||
1021 | * point in issuing this if DSC overlap isn't supported, some | ||
1022 | * drives (Seagate STT3401A) will return an error. | ||
1023 | */ | ||
1024 | if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) { | ||
1025 | int cmd = dir == IDETAPE_DIR_READ ? REQ_IDETAPE_READ | ||
1026 | : REQ_IDETAPE_WRITE; | ||
1027 | |||
1028 | rc = idetape_queue_rw_tail(drive, cmd, 0); | ||
1029 | if (rc < 0) { | ||
1030 | kfree(tape->buf); | ||
1031 | tape->buf = NULL; | ||
1032 | tape->chrdev_dir = IDETAPE_DIR_NONE; | ||
1033 | return rc; | ||
1026 | } | 1034 | } |
1027 | } | 1035 | } |
1028 | 1036 | ||
@@ -1038,7 +1046,7 @@ static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks) | |||
1038 | if (test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) | 1046 | if (test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) |
1039 | return 0; | 1047 | return 0; |
1040 | 1048 | ||
1041 | idetape_init_read(drive); | 1049 | idetape_init_rw(drive, IDETAPE_DIR_READ); |
1042 | 1050 | ||
1043 | return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks); | 1051 | return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks); |
1044 | } | 1052 | } |
@@ -1195,7 +1203,7 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf, | |||
1195 | (count % tape->blk_size) == 0) | 1203 | (count % tape->blk_size) == 0) |
1196 | tape->user_bs_factor = count / tape->blk_size; | 1204 | tape->user_bs_factor = count / tape->blk_size; |
1197 | } | 1205 | } |
1198 | rc = idetape_init_read(drive); | 1206 | rc = idetape_init_rw(drive, IDETAPE_DIR_READ); |
1199 | if (rc < 0) | 1207 | if (rc < 0) |
1200 | return rc; | 1208 | return rc; |
1201 | if (count == 0) | 1209 | if (count == 0) |
@@ -1249,6 +1257,7 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, | |||
1249 | ssize_t actually_written = 0; | 1257 | ssize_t actually_written = 0; |
1250 | ssize_t ret = 0; | 1258 | ssize_t ret = 0; |
1251 | u16 ctl = *(u16 *)&tape->caps[12]; | 1259 | u16 ctl = *(u16 *)&tape->caps[12]; |
1260 | int rc; | ||
1252 | 1261 | ||
1253 | /* The drive is write protected. */ | 1262 | /* The drive is write protected. */ |
1254 | if (tape->write_prot) | 1263 | if (tape->write_prot) |
@@ -1257,36 +1266,9 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, | |||
1257 | debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count); | 1266 | debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count); |
1258 | 1267 | ||
1259 | /* Initialize write operation */ | 1268 | /* Initialize write operation */ |
1260 | if (tape->chrdev_dir != IDETAPE_DIR_WRITE) { | 1269 | rc = idetape_init_rw(drive, IDETAPE_DIR_WRITE); |
1261 | if (tape->chrdev_dir == IDETAPE_DIR_READ) | 1270 | if (rc < 0) |
1262 | ide_tape_discard_merge_buffer(drive, 1); | 1271 | return rc; |
1263 | if (tape->buf || tape->valid) { | ||
1264 | printk(KERN_ERR "ide-tape: valid should be 0 now\n"); | ||
1265 | tape->valid = 0; | ||
1266 | } | ||
1267 | tape->buf = kmalloc(tape->buffer_size, GFP_KERNEL); | ||
1268 | if (!tape->buf) | ||
1269 | return -ENOMEM; | ||
1270 | tape->chrdev_dir = IDETAPE_DIR_WRITE; | ||
1271 | tape->cur = tape->buf; | ||
1272 | |||
1273 | /* | ||
1274 | * Issue a write 0 command to ensure that DSC handshake is | ||
1275 | * switched from completion mode to buffer available mode. No | ||
1276 | * point in issuing this if DSC overlap isn't supported, some | ||
1277 | * drives (Seagate STT3401A) will return an error. | ||
1278 | */ | ||
1279 | if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) { | ||
1280 | ssize_t retval = idetape_queue_rw_tail(drive, | ||
1281 | REQ_IDETAPE_WRITE, 0); | ||
1282 | if (retval < 0) { | ||
1283 | kfree(tape->buf); | ||
1284 | tape->buf = NULL; | ||
1285 | tape->chrdev_dir = IDETAPE_DIR_NONE; | ||
1286 | return retval; | ||
1287 | } | ||
1288 | } | ||
1289 | } | ||
1290 | if (count == 0) | 1272 | if (count == 0) |
1291 | return (0); | 1273 | return (0); |
1292 | if (tape->valid < tape->buffer_size) { | 1274 | if (tape->valid < tape->buffer_size) { |