]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/ide-scsi.c
NFS: Fix a resolution problem with nfs_inode->cache_change_attribute
[linux-2.6-omap-h63xx.git] / drivers / scsi / ide-scsi.c
index f843c1383a4b599480fdd53c9887a1263132e294..461331d3dc45f041fd23bb8c02cc0f87b6737fe8 100644 (file)
@@ -84,7 +84,6 @@ typedef struct ide_scsi_obj {
        struct Scsi_Host        *host;
 
        struct ide_atapi_pc *pc;                /* Current packet command */
-       unsigned long flags;                    /* Status/Action flags */
        unsigned long transform;                /* SCSI cmd translation layer */
        unsigned long log;                      /* log flags */
 } idescsi_scsi_t;
@@ -102,16 +101,23 @@ static struct ide_scsi_obj *ide_scsi_get(struct gendisk *disk)
 
        mutex_lock(&idescsi_ref_mutex);
        scsi = ide_scsi_g(disk);
-       if (scsi)
-               scsi_host_get(scsi->host);
+       if (scsi) {
+               if (ide_device_get(scsi->drive))
+                       scsi = NULL;
+               else
+                       scsi_host_get(scsi->host);
+       }
        mutex_unlock(&idescsi_ref_mutex);
        return scsi;
 }
 
 static void ide_scsi_put(struct ide_scsi_obj *scsi)
 {
+       ide_drive_t *drive = scsi->drive;
+
        mutex_lock(&idescsi_ref_mutex);
        scsi_host_put(scsi->host);
+       ide_device_put(drive);
        mutex_unlock(&idescsi_ref_mutex);
 }
 
@@ -125,16 +131,6 @@ static inline idescsi_scsi_t *drive_to_idescsi(ide_drive_t *ide_drive)
        return scsihost_to_idescsi(ide_drive->driver_data);
 }
 
-/*
- *     Per ATAPI device status bits.
- */
-#define IDESCSI_DRQ_INTERRUPT          0       /* DRQ interrupt device */
-
-/*
- *     ide-scsi requests.
- */
-#define IDESCSI_PC_RQ                  90
-
 /*
  *     PIO data transfer routine using the scatter gather table.
  */
@@ -142,7 +138,8 @@ static void ide_scsi_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
                                unsigned int bcount, int write)
 {
        ide_hwif_t *hwif = drive->hwif;
-       xfer_func_t *xf = write ? hwif->output_data : hwif->input_data;
+       const struct ide_tp_ops *tp_ops = hwif->tp_ops;
+       xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data;
        char *buf;
        int count;
 
@@ -211,15 +208,15 @@ static int idescsi_check_condition(ide_drive_t *drive,
 
        /* stuff a sense request in front of our current request */
        pc = kzalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC);
-       rq = kmalloc(sizeof(struct request), GFP_ATOMIC);
+       rq = blk_get_request(drive->queue, READ, GFP_ATOMIC);
        buf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_ATOMIC);
        if (!pc || !rq || !buf) {
                kfree(buf);
-               kfree(rq);
+               if (rq)
+                       blk_put_request(rq);
                kfree(pc);
                return -ENOMEM;
        }
-       blk_rq_init(NULL, rq);
        rq->special = (char *) pc;
        pc->rq = rq;
        pc->buf = buf;
@@ -228,7 +225,6 @@ static int idescsi_check_condition(ide_drive_t *drive,
        rq->cmd_type = REQ_TYPE_SENSE;
        rq->cmd_flags |= REQ_PREEMPT;
        pc->timeout = jiffies + WAIT_READY;
-       pc->callback = ide_scsi_callback;
        /* NOTE! Save the failed packet command in "rq->buffer" */
        rq->buffer = (void *) failed_cmd->special;
        pc->scsi_cmd = ((struct ide_atapi_pc *) failed_cmd->special)->scsi_cmd;
@@ -237,6 +233,8 @@ static int idescsi_check_condition(ide_drive_t *drive,
                ide_scsi_hex_dump(pc->c, 6);
        }
        rq->rq_disk = scsi->disk;
+       rq->ref_count++;
+       memcpy(rq->cmd, pc->c, 12);
        ide_do_drive_cmd(drive, rq);
        return 0;
 }
@@ -246,10 +244,9 @@ idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
 {
        ide_hwif_t *hwif = drive->hwif;
 
-       if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+       if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
                /* force an abort */
-               hwif->OUTBSYNC(hwif, WIN_IDLEIMMEDIATE,
-                              hwif->io_ports.command_addr);
+               hwif->tp_ops->exec_command(hwif, WIN_IDLEIMMEDIATE);
 
        rq->errors++;
 
@@ -283,7 +280,7 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
                        SCSI_SENSE_BUFFERSIZE);
                kfree(pc->buf);
                kfree(pc);
-               kfree(rq);
+               blk_put_request(rq);
                pc = opc;
                rq = pc->rq;
                pc->scsi_cmd->result = (CHECK_CONDITION << 1) |
@@ -314,7 +311,7 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
        pc->done(pc->scsi_cmd);
        spin_unlock_irqrestore(host->host_lock, flags);
        kfree(pc);
-       kfree(rq);
+       blk_put_request(rq);
        scsi->pc = NULL;
        return 0;
 }
@@ -421,10 +418,6 @@ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *r
 
        if (blk_sense_request(rq) || blk_special_request(rq)) {
                struct ide_atapi_pc *pc = (struct ide_atapi_pc *)rq->special;
-               idescsi_scsi_t *scsi = drive_to_idescsi(drive);
-
-               if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags))
-                       pc->flags |= PC_FLAG_DRQ_INTERRUPT;
 
                if (drive->using_dma && !idescsi_map_sg(drive, pc))
                        pc->flags |= PC_FLAG_DMA_OK;
@@ -460,11 +453,14 @@ static inline void idescsi_add_settings(ide_drive_t *drive) { ; }
 static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
 {
        if (drive->id && (drive->id->config & 0x0060) == 0x20)
-               set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags);
+               set_bit(IDE_AFLAG_DRQ_INTERRUPT, &drive->atapi_flags);
        clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
 #if IDESCSI_DEBUG_LOG
        set_bit(IDESCSI_LOG_CMD, &scsi->log);
 #endif /* IDESCSI_DEBUG_LOG */
+
+       drive->pc_callback = ide_scsi_callback;
+
        idescsi_add_settings(drive);
 }
 
@@ -589,6 +585,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
        ide_drive_t *drive = scsi->drive;
        struct request *rq = NULL;
        struct ide_atapi_pc *pc = NULL;
+       int write = cmd->sc_data_direction == DMA_TO_DEVICE;
 
        if (!drive) {
                scmd_printk (KERN_ERR, cmd, "drive not present\n");
@@ -596,7 +593,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
        }
        scsi = drive_to_idescsi(drive);
        pc = kmalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC);
-       rq = kmalloc(sizeof(struct request), GFP_ATOMIC);
+       rq = blk_get_request(drive->queue, write, GFP_ATOMIC);
        if (rq == NULL || pc == NULL) {
                printk (KERN_ERR "ide-scsi: %s: out of memory\n", drive->name);
                goto abort;
@@ -616,7 +613,6 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
        pc->scsi_cmd = cmd;
        pc->done = done;
        pc->timeout = jiffies + cmd->timeout_per_command;
-       pc->callback = ide_scsi_callback;
 
        if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
                printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number);
@@ -627,16 +623,18 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
                }
        }
 
-       blk_rq_init(NULL, rq);
        rq->special = (char *) pc;
        rq->cmd_type = REQ_TYPE_SPECIAL;
        spin_unlock_irq(host->host_lock);
+       rq->ref_count++;
+       memcpy(rq->cmd, pc->c, 12);
        blk_execute_rq_nowait(drive->queue, scsi->disk, rq, 0, NULL);
        spin_lock_irq(host->host_lock);
        return 0;
 abort:
        kfree (pc);
-       kfree (rq);
+       if (rq)
+               blk_put_request(rq);
        cmd->result = DID_ERROR << 16;
        done(cmd);
        return 0;
@@ -684,7 +682,9 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd)
 
                if (blk_sense_request(scsi->pc->rq))
                        kfree(scsi->pc->buf);
-               kfree(scsi->pc->rq);
+               /* we need to call blk_put_request twice. */
+               blk_put_request(scsi->pc->rq);
+               blk_put_request(scsi->pc->rq);
                kfree(scsi->pc);
                scsi->pc = NULL;
 
@@ -736,7 +736,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
                kfree(scsi->pc->buf);
        kfree(scsi->pc);
        scsi->pc = NULL;
-       kfree(req);
+       blk_put_request(req);
 
        /* now nuke the drive queue */
        while ((req = elv_next_request(drive->queue))) {