]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ide/ide-tape.c
drivers/ide/ide-tape.c: remove double kfree
[linux-2.6-omap-h63xx.git] / drivers / ide / ide-tape.c
index ce9b6d327528a8cd5e57aa8ab1eb5b53318c35cd..663671f69f88e1028b9a9c7ddfd4cd406c4db371 100644 (file)
@@ -398,7 +398,7 @@ static void idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
                count = min(
                        (unsigned int)(bh->b_size - atomic_read(&bh->b_count)),
                        bcount);
-               drive->hwif->input_data(drive, NULL, bh->b_data +
+               drive->hwif->tp_ops->input_data(drive, NULL, bh->b_data +
                                        atomic_read(&bh->b_count), count);
                bcount -= count;
                atomic_add(count, &bh->b_count);
@@ -424,7 +424,7 @@ static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
                        return;
                }
                count = min((unsigned int)pc->b_count, (unsigned int)bcount);
-               drive->hwif->output_data(drive, NULL, pc->b_data, count);
+               drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count);
                bcount -= count;
                pc->b_data += count;
                pc->b_count -= count;
@@ -439,7 +439,7 @@ static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
        }
 }
 
-static void idetape_update_buffers(struct ide_atapi_pc *pc)
+static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc)
 {
        struct idetape_bh *bh = pc->bh;
        int count;
@@ -524,7 +524,7 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
                pc->xferred = pc->req_xfer -
                        tape->blk_size *
                        get_unaligned_be32(&sense[3]);
-               idetape_update_buffers(pc);
+               idetape_update_buffers(drive, pc);
        }
 
        /*
@@ -585,7 +585,6 @@ static void ide_tape_kfree_buffer(idetape_tape_t *tape)
                bh = bh->b_reqnext;
                kfree(prev_bh);
        }
-       kfree(tape->merge_bh);
 }
 
 static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
@@ -627,6 +626,9 @@ static void ide_tape_callback(ide_drive_t *drive)
 
        debug_log(DBG_PROCS, "Enter %s\n", __func__);
 
+       if (tape->failed_pc == pc)
+               tape->failed_pc = NULL;
+
        if (pc->c[0] == REQUEST_SENSE) {
                if (uptodate)
                        idetape_analyze_error(drive, pc->buf);
@@ -765,7 +767,26 @@ static void idetape_postpone_request(ide_drive_t *drive)
        ide_stall_queue(drive, tape->dsc_poll_freq);
 }
 
-typedef void idetape_io_buf(ide_drive_t *, struct ide_atapi_pc *, unsigned int);
+static void ide_tape_handle_dsc(ide_drive_t *drive)
+{
+       idetape_tape_t *tape = drive->driver_data;
+
+       /* Media access command */
+       tape->dsc_polling_start = jiffies;
+       tape->dsc_poll_freq = IDETAPE_DSC_MA_FAST;
+       tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT;
+       /* Allow ide.c to handle other requests */
+       idetape_postpone_request(drive);
+}
+
+static void ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
+                               unsigned int bcount, int write)
+{
+       if (write)
+               idetape_output_buffers(drive, pc, bcount);
+       else
+               idetape_input_buffers(drive, pc, bcount);
+}
 
 /*
  * This is the usual interrupt handler which will be called during a packet
@@ -776,139 +797,11 @@ typedef void idetape_io_buf(ide_drive_t *, struct ide_atapi_pc *, unsigned int);
  */
 static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = drive->hwif;
        idetape_tape_t *tape = drive->driver_data;
-       struct ide_atapi_pc *pc = tape->pc;
-       xfer_func_t *xferfunc;
-       idetape_io_buf *iobuf;
-       unsigned int temp;
-       u16 bcount;
-       u8 stat, ireason;
-
-       debug_log(DBG_PROCS, "Enter %s - interrupt handler\n", __func__);
-
-       /* Clear the interrupt */
-       stat = ide_read_status(drive);
-
-       if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
-               if (hwif->dma_ops->dma_end(drive) || (stat & ERR_STAT)) {
-                       pc->flags |= PC_FLAG_DMA_ERROR;
-               } else {
-                       pc->xferred = pc->req_xfer;
-                       idetape_update_buffers(pc);
-               }
-               debug_log(DBG_PROCS, "DMA finished\n");
-
-       }
-
-       /* No more interrupts */
-       if ((stat & DRQ_STAT) == 0) {
-               debug_log(DBG_SENSE, "Packet command completed, %d bytes"
-                               " transferred\n", pc->xferred);
-
-               pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
-               local_irq_enable_in_hardirq();
-
-               if ((stat & ERR_STAT) && pc->c[0] == REQUEST_SENSE)
-                       stat &= ~ERR_STAT;
-               if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) {
-                       /* Error detected */
-                       debug_log(DBG_ERR, "%s: I/O error\n", tape->name);
-
-                       if (pc->c[0] == REQUEST_SENSE) {
-                               printk(KERN_ERR "%s: I/O error in request sense"
-                                               " command\n", drive->name);
-                               return ide_do_reset(drive);
-                       }
-                       debug_log(DBG_ERR, "[cmd %x]: check condition\n",
-                                       pc->c[0]);
-
-                       /* Retry operation */
-                       idetape_retry_pc(drive);
-                       return ide_stopped;
-               }
-               pc->error = 0;
-               if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) &&
-                   (stat & SEEK_STAT) == 0) {
-                       /* Media access command */
-                       tape->dsc_polling_start = jiffies;
-                       tape->dsc_poll_freq = IDETAPE_DSC_MA_FAST;
-                       tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT;
-                       /* Allow ide.c to handle other requests */
-                       idetape_postpone_request(drive);
-                       return ide_stopped;
-               }
-               if (tape->failed_pc == pc)
-                       tape->failed_pc = NULL;
-               /* Command finished - Call the callback function */
-               pc->callback(drive);
-               return ide_stopped;
-       }
 
-       if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
-               pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
-               printk(KERN_ERR "%s: The device wants to issue more interrupts "
-                               "in DMA mode\n", drive->name);
-               ide_dma_off(drive);
-               return ide_do_reset(drive);
-       }
-       /* Get the number of bytes to transfer on this interrupt. */
-       bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) |
-                 hwif->INB(hwif->io_ports.lbam_addr);
-
-       ireason = hwif->INB(hwif->io_ports.nsect_addr);
-
-       if (ireason & CD) {
-               printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__);
-               return ide_do_reset(drive);
-       }
-       if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) {
-               /* Hopefully, we will never get here */
-               printk(KERN_ERR "%s: We wanted to %s, but the device wants us "
-                               "to %s!\n", drive->name,
-                               (ireason & IO) ? "Write" : "Read",
-                               (ireason & IO) ? "Read" : "Write");
-               return ide_do_reset(drive);
-       }
-       if (!(pc->flags & PC_FLAG_WRITING)) {
-               /* Reading - Check that we have enough space */
-               temp = pc->xferred + bcount;
-               if (temp > pc->req_xfer) {
-                       if (temp > pc->buf_size) {
-                               printk(KERN_ERR "%s: The device wants to send "
-                                               "us more data than expected - "
-                                               "discarding data\n",
-                                               drive->name);
-                               ide_pad_transfer(drive, 0, bcount);
-                               ide_set_handler(drive, &idetape_pc_intr,
-                                               IDETAPE_WAIT_CMD, NULL);
-                               return ide_started;
-                       }
-                       debug_log(DBG_SENSE, "The device wants to send us more "
-                               "data than expected - allowing transfer\n");
-               }
-               iobuf = &idetape_input_buffers;
-               xferfunc = hwif->input_data;
-       } else {
-               iobuf = &idetape_output_buffers;
-               xferfunc = hwif->output_data;
-       }
-
-       if (pc->bh)
-               iobuf(drive, pc, bcount);
-       else
-               xferfunc(drive, NULL, pc->cur_pos, bcount);
-
-       /* Update the current position */
-       pc->xferred += bcount;
-       pc->cur_pos += bcount;
-
-       debug_log(DBG_SENSE, "[cmd %x] transferred %d bytes on that intr.\n",
-                       pc->c[0], bcount);
-
-       /* And set the interrupt handler again */
-       ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
-       return ide_started;
+       return ide_pc_intr(drive, tape->pc, idetape_pc_intr, IDETAPE_WAIT_CMD,
+                          NULL, idetape_update_buffers, idetape_retry_pc,
+                          ide_tape_handle_dsc, ide_tape_io_buffers);
 }
 
 /*
@@ -949,57 +842,16 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
  */
 static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = drive->hwif;
        idetape_tape_t *tape = drive->driver_data;
-       struct ide_atapi_pc *pc = tape->pc;
-       int retries = 100;
-       ide_startstop_t startstop;
-       u8 ireason;
-
-       if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
-               printk(KERN_ERR "%s: Strange, packet command initiated yet "
-                               "DRQ isn't asserted\n", drive->name);
-               return startstop;
-       }
-       ireason = hwif->INB(hwif->io_ports.nsect_addr);
-       while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) {
-               printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
-                               "a packet command, retrying\n", drive->name);
-               udelay(100);
-               ireason = hwif->INB(hwif->io_ports.nsect_addr);
-               if (retries == 0) {
-                       printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
-                                       "a packet command, ignoring\n",
-                                       drive->name);
-                       ireason |= CD;
-                       ireason &= ~IO;
-               }
-       }
-       if ((ireason & CD) == 0 || (ireason & IO)) {
-               printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing "
-                               "a packet command\n", drive->name);
-               return ide_do_reset(drive);
-       }
-       /* Set the interrupt routine */
-       ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
-
-       /* Begin DMA, if necessary */
-       if (pc->flags & PC_FLAG_DMA_IN_PROGRESS)
-               hwif->dma_ops->dma_start(drive);
 
-       /* Send the actual packet */
-       hwif->output_data(drive, NULL, pc->c, 12);
-
-       return ide_started;
+       return ide_transfer_pc(drive, tape->pc, idetape_pc_intr,
+                              IDETAPE_WAIT_CMD, NULL);
 }
 
 static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
                struct ide_atapi_pc *pc)
 {
-       ide_hwif_t *hwif = drive->hwif;
        idetape_tape_t *tape = drive->driver_data;
-       int dma_ok = 0;
-       u16 bcount;
 
        if (tape->pc->c[0] == REQUEST_SENSE &&
            pc->c[0] == REQUEST_SENSE) {
@@ -1040,32 +892,9 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
        debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
 
        pc->retries++;
-       /* We haven't transferred any data yet */
-       pc->xferred = 0;
-       pc->cur_pos = pc->buf;
-       /* Request to transfer the entire buffer at once */
-       bcount = pc->req_xfer;
 
-       if (pc->flags & PC_FLAG_DMA_ERROR) {
-               pc->flags &= ~PC_FLAG_DMA_ERROR;
-               ide_dma_off(drive);
-       }
-       if ((pc->flags & PC_FLAG_DMA_RECOMMENDED) && drive->using_dma)
-               dma_ok = !hwif->dma_ops->dma_setup(drive);
-
-       ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_DEVICE, bcount, dma_ok);
-
-       if (dma_ok)
-               /* Will begin DMA later */
-               pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
-       if (test_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags)) {
-               ide_execute_command(drive, WIN_PACKETCMD, &idetape_transfer_pc,
-                                   IDETAPE_WAIT_CMD, NULL);
-               return ide_started;
-       } else {
-               ide_execute_pkt_cmd(drive);
-               return idetape_transfer_pc(drive);
-       }
+       return ide_issue_pc(drive, pc, idetape_transfer_pc,
+                           IDETAPE_WAIT_CMD, NULL);
 }
 
 /* A mode sense command is used to "sense" tape parameters. */
@@ -1097,11 +926,12 @@ static void idetape_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
 
 static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
 {
+       ide_hwif_t *hwif = drive->hwif;
        idetape_tape_t *tape = drive->driver_data;
        struct ide_atapi_pc *pc = tape->pc;
        u8 stat;
 
-       stat = ide_read_status(drive);
+       stat = hwif->tp_ops->read_status(hwif);
 
        if (stat & SEEK_STAT) {
                if (stat & ERR_STAT) {
@@ -1114,8 +944,6 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
                        return ide_stopped;
                }
                pc->error = 0;
-               if (tape->failed_pc == pc)
-                       tape->failed_pc = NULL;
        } else {
                pc->error = IDETAPE_ERROR_GENERAL;
                tape->failed_pc = NULL;
@@ -1124,45 +952,35 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
        return ide_stopped;
 }
 
-static void idetape_create_read_cmd(idetape_tape_t *tape,
-               struct ide_atapi_pc *pc,
-               unsigned int length, struct idetape_bh *bh)
+static void ide_tape_create_rw_cmd(idetape_tape_t *tape,
+               struct ide_atapi_pc *pc, unsigned int length,
+               struct idetape_bh *bh, u8 opcode)
 {
        idetape_init_pc(pc);
-       pc->c[0] = READ_6;
        put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
        pc->c[1] = 1;
        pc->bh = bh;
-       atomic_set(&bh->b_count, 0);
        pc->buf = NULL;
        pc->buf_size = length * tape->blk_size;
        pc->req_xfer = pc->buf_size;
        if (pc->req_xfer == tape->buffer_size)
-               pc->flags |= PC_FLAG_DMA_RECOMMENDED;
-}
+               pc->flags |= PC_FLAG_DMA_OK;
 
-static void idetape_create_write_cmd(idetape_tape_t *tape,
-               struct ide_atapi_pc *pc,
-               unsigned int length, struct idetape_bh *bh)
-{
-       idetape_init_pc(pc);
-       pc->c[0] = WRITE_6;
-       put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
-       pc->c[1] = 1;
-       pc->flags |= PC_FLAG_WRITING;
-       pc->bh = bh;
-       pc->b_data = bh->b_data;
-       pc->b_count = atomic_read(&bh->b_count);
-       pc->buf = NULL;
-       pc->buf_size = length * tape->blk_size;
-       pc->req_xfer = pc->buf_size;
-       if (pc->req_xfer == tape->buffer_size)
-               pc->flags |= PC_FLAG_DMA_RECOMMENDED;
+       if (opcode == READ_6) {
+               pc->c[0] = READ_6;
+               atomic_set(&bh->b_count, 0);
+       } else if (opcode == WRITE_6) {
+               pc->c[0] = WRITE_6;
+               pc->flags |= PC_FLAG_WRITING;
+               pc->b_data = bh->b_data;
+               pc->b_count = atomic_read(&bh->b_count);
+       }
 }
 
 static ide_startstop_t idetape_do_request(ide_drive_t *drive,
                                          struct request *rq, sector_t block)
 {
+       ide_hwif_t *hwif = drive->hwif;
        idetape_tape_t *tape = drive->driver_data;
        struct ide_atapi_pc *pc = NULL;
        struct request *postponed_rq = tape->postponed_rq;
@@ -1181,8 +999,10 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
        }
 
        /* Retry a failed packet command */
-       if (tape->failed_pc && tape->pc->c[0] == REQUEST_SENSE)
-               return idetape_issue_pc(drive, tape->failed_pc);
+       if (tape->failed_pc && tape->pc->c[0] == REQUEST_SENSE) {
+               pc = tape->failed_pc;
+               goto out;
+       }
 
        if (postponed_rq != NULL)
                if (rq != postponed_rq) {
@@ -1198,7 +1018,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
         * If the tape is still busy, postpone our request and service
         * the other device meanwhile.
         */
-       stat = ide_read_status(drive);
+       stat = hwif->tp_ops->read_status(hwif);
 
        if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2))
                set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
@@ -1232,14 +1052,16 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
        }
        if (rq->cmd[0] & REQ_IDETAPE_READ) {
                pc = idetape_next_pc_storage(drive);
-               idetape_create_read_cmd(tape, pc, rq->current_nr_sectors,
-                                       (struct idetape_bh *)rq->special);
+               ide_tape_create_rw_cmd(tape, pc, rq->current_nr_sectors,
+                                       (struct idetape_bh *)rq->special,
+                                       READ_6);
                goto out;
        }
        if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
                pc = idetape_next_pc_storage(drive);
-               idetape_create_write_cmd(tape, pc, rq->current_nr_sectors,
-                                        (struct idetape_bh *)rq->special);
+               ide_tape_create_rw_cmd(tape, pc, rq->current_nr_sectors,
+                                        (struct idetape_bh *)rq->special,
+                                        WRITE_6);
                goto out;
        }
        if (rq->cmd[0] & REQ_IDETAPE_PC1) {
@@ -1254,6 +1076,9 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
        }
        BUG();
 out:
+       if (test_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags))
+               pc->flags |= PC_FLAG_DRQ_INTERRUPT;
+
        return idetape_issue_pc(drive, pc);
 }
 
@@ -2358,9 +2183,12 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
        if (i >= MAX_HWIFS * MAX_DRIVES)
                return -ENXIO;
 
+       lock_kernel();
        tape = ide_tape_chrdev_get(i);
-       if (!tape)
+       if (!tape) {
+               unlock_kernel();
                return -ENXIO;
+       }
 
        debug_log(DBG_CHRDEV, "Enter %s\n", __func__);
 
@@ -2419,10 +2247,12 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
                        }
                }
        }
+       unlock_kernel();
        return 0;
 
 out_put_tape:
        ide_tape_put(tape);
+       unlock_kernel();
        return retval;
 }
 
@@ -2762,7 +2592,6 @@ static ide_driver_t idetape_driver = {
        .do_request             = idetape_do_request,
        .end_request            = idetape_end_request,
        .error                  = __ide_error,
-       .abort                  = __ide_abort,
 #ifdef CONFIG_IDE_PROC_FS
        .proc                   = idetape_proc,
 #endif
@@ -2836,11 +2665,6 @@ static int ide_tape_probe(ide_drive_t *drive)
                                " the driver\n", drive->name);
                goto failed;
        }
-       if (drive->scsi) {
-               printk(KERN_INFO "ide-tape: passing drive %s to ide-scsi"
-                                " emulation.\n", drive->name);
-               goto failed;
-       }
        tape = kzalloc(sizeof(idetape_tape_t), GFP_KERNEL);
        if (tape == NULL) {
                printk(KERN_ERR "ide-tape: %s: Can't allocate a tape struct\n",
@@ -2874,10 +2698,12 @@ static int ide_tape_probe(ide_drive_t *drive)
 
        idetape_setup(drive, tape, minor);
 
-       device_create(idetape_sysfs_class, &drive->gendev,
-                     MKDEV(IDETAPE_MAJOR, minor), "%s", tape->name);
-       device_create(idetape_sysfs_class, &drive->gendev,
-                       MKDEV(IDETAPE_MAJOR, minor + 128), "n%s", tape->name);
+       device_create_drvdata(idetape_sysfs_class, &drive->gendev,
+                             MKDEV(IDETAPE_MAJOR, minor), NULL,
+                             "%s", tape->name);
+       device_create_drvdata(idetape_sysfs_class, &drive->gendev,
+                             MKDEV(IDETAPE_MAJOR, minor + 128), NULL,
+                             "n%s", tape->name);
 
        g->fops = &idetape_block_ops;
        ide_register_region(g);