aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ide/ide-tape.c110
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
990static int idetape_init_read(ide_drive_t *drive) 990static 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) {