]> 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 b224823a8ae7f9f29e46ef9f83c77a37ba6accd0..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)
@@ -780,7 +779,14 @@ static void ide_tape_handle_dsc(ide_drive_t *drive)
        idetape_postpone_request(drive);
 }
 
-typedef void idetape_io_buf(ide_drive_t *, struct ide_atapi_pc *, unsigned int);
+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
@@ -791,132 +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) {
-                       ide_tape_handle_dsc(drive);
-                       return ide_stopped;
-               }
-               /* 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);
 }
 
 /*
@@ -1041,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) {
@@ -1066,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_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_OK;
+       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;
@@ -1142,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);
@@ -1176,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) {
@@ -2305,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__);
 
@@ -2366,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;
 }
 
@@ -2709,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
@@ -2816,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);