IDE: pass IRQ flags to the IDE core
[safe/jmp/linux-2.6] / drivers / ide / ide-io.c
index 9654bd3..172ac92 100644 (file)
@@ -112,16 +112,6 @@ void ide_complete_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat, u8 err)
        }
 }
 
-/* obsolete, blk_rq_bytes() should be used instead */
-unsigned int ide_rq_bytes(struct request *rq)
-{
-       if (blk_pc_request(rq))
-               return rq->data_len;
-       else
-               return rq->hard_cur_sectors << 9;
-}
-EXPORT_SYMBOL_GPL(ide_rq_bytes);
-
 int ide_complete_rq(ide_drive_t *drive, int error, unsigned int nr_bytes)
 {
        ide_hwif_t *hwif = drive->hwif;
@@ -133,7 +123,7 @@ int ide_complete_rq(ide_drive_t *drive, int error, unsigned int nr_bytes)
         * and complete the whole request right now
         */
        if (blk_noretry_request(rq) && error <= 0)
-               nr_bytes = rq->hard_nr_sectors << 9;
+               nr_bytes = blk_rq_sectors(rq) << 9;
 
        rc = ide_end_rq(drive, rq, error, nr_bytes);
        if (rc == 0)
@@ -152,14 +142,14 @@ void ide_kill_rq(ide_drive_t *drive, struct request *rq)
 
        if ((media == ide_floppy || media == ide_tape) && drv_req) {
                rq->errors = 0;
-               ide_complete_rq(drive, 0, blk_rq_bytes(rq));
        } else {
                if (media == ide_tape)
                        rq->errors = IDE_DRV_ERROR_GENERAL;
                else if (blk_fs_request(rq) == 0 && rq->errors == 0)
                        rq->errors = -EIO;
-               ide_complete_rq(drive, -EIO, ide_rq_bytes(rq));
        }
+
+       ide_complete_rq(drive, -EIO, blk_rq_bytes(rq));
 }
 
 static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
@@ -267,7 +257,7 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
 
        if (cmd) {
                if (cmd->protocol == ATA_PROT_PIO) {
-                       ide_init_sg_cmd(cmd, rq->nr_sectors << 9);
+                       ide_init_sg_cmd(cmd, blk_rq_sectors(rq) << 9);
                        ide_map_sg(drive, cmd);
                }
 
@@ -376,7 +366,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
 
                drv = *(struct ide_driver **)rq->rq_disk->private_data;
 
-               return drv->do_request(drive, rq, rq->sector);
+               return drv->do_request(drive, rq, blk_rq_pos(rq));
        }
        return do_special(drive);
 kill_rq:
@@ -476,10 +466,10 @@ void do_ide_request(struct request_queue *q)
 
        if (!ide_lock_port(hwif)) {
                ide_hwif_t *prev_port;
+
+               WARN_ON_ONCE(hwif->rq);
 repeat:
                prev_port = hwif->host->cur_port;
-               hwif->rq = NULL;
-
                if (drive->dev_flags & IDE_DFLAG_SLEEPING &&
                    time_after(drive->sleep, jiffies)) {
                        ide_unlock_port(hwif);
@@ -488,11 +478,15 @@ repeat:
 
                if ((hwif->host->host_flags & IDE_HFLAG_SERIALIZE) &&
                    hwif != prev_port) {
+                       ide_drive_t *cur_dev =
+                               prev_port ? prev_port->cur_dev : NULL;
+
                        /*
                         * set nIEN for previous port, drives in the
-                        * quirk_list may not like intr setups/cleanups
+                        * quirk list may not like intr setups/cleanups
                         */
-                       if (prev_port && prev_port->cur_dev->quirk_list == 0)
+                       if (cur_dev &&
+                           (cur_dev->dev_flags & IDE_DFLAG_NIEN_QUIRK) == 0)
                                prev_port->tp_ops->write_devctl(prev_port,
                                                                ATA_NIEN |
                                                                ATA_DEVCTL_OBS);
@@ -508,7 +502,9 @@ repeat:
                 * we know that the queue isn't empty, but this can happen
                 * if the q->prep_rq_fn() decides to kill a request
                 */
-               rq = elv_next_request(drive->queue);
+               if (!rq)
+                       rq = blk_fetch_request(drive->queue);
+
                spin_unlock_irq(q->queue_lock);
                spin_lock_irq(&hwif->lock);
 
@@ -520,7 +516,7 @@ repeat:
                /*
                 * Sanity: don't accept a request that isn't a PM request
                 * if we are currently power managed. This is very important as
-                * blk_stop_queue() doesn't prevent the elv_next_request()
+                * blk_stop_queue() doesn't prevent the blk_fetch_request()
                 * above to return us whatever is in the queue. Since we call
                 * ide_do_request() ourselves, we end up taking requests while
                 * the queue is blocked...
@@ -544,8 +540,11 @@ repeat:
                startstop = start_request(drive, rq);
                spin_lock_irq(&hwif->lock);
 
-               if (startstop == ide_stopped)
+               if (startstop == ide_stopped) {
+                       rq = hwif->rq;
+                       hwif->rq = NULL;
                        goto repeat;
+               }
        } else
                goto plug_device;
 out:
@@ -561,18 +560,24 @@ plug_device:
 plug_device_2:
        spin_lock_irq(q->queue_lock);
 
+       if (rq)
+               blk_requeue_request(q, rq);
        if (!elv_queue_empty(q))
                blk_plug_device(q);
 }
 
-static void ide_plug_device(ide_drive_t *drive)
+void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq)
 {
        struct request_queue *q = drive->queue;
        unsigned long flags;
 
        spin_lock_irqsave(q->queue_lock, flags);
+
+       if (rq)
+               blk_requeue_request(q, rq);
        if (!elv_queue_empty(q))
                blk_plug_device(q);
+
        spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
@@ -621,6 +626,7 @@ void ide_timer_expiry (unsigned long data)
        unsigned long   flags;
        int             wait = -1;
        int             plug_device = 0;
+       struct request  *uninitialized_var(rq_in_flight);
 
        spin_lock_irqsave(&hwif->lock, flags);
 
@@ -667,8 +673,9 @@ void ide_timer_expiry (unsigned long data)
                } else if (drive_is_ready(drive)) {
                        if (drive->waiting_for_dma)
                                hwif->dma_ops->dma_lost_irq(drive);
-                       if (hwif->ack_intr)
-                               hwif->ack_intr(hwif);
+                       if (hwif->port_ops && hwif->port_ops->clear_irq)
+                               hwif->port_ops->clear_irq(drive);
+
                        printk(KERN_WARNING "%s: lost interrupt\n",
                                drive->name);
                        startstop = handler(drive);
@@ -682,6 +689,8 @@ void ide_timer_expiry (unsigned long data)
                spin_lock_irq(&hwif->lock);
                enable_irq(hwif->irq);
                if (startstop == ide_stopped && hwif->polling == 0) {
+                       rq_in_flight = hwif->rq;
+                       hwif->rq = NULL;
                        ide_unlock_port(hwif);
                        plug_device = 1;
                }
@@ -690,7 +699,7 @@ void ide_timer_expiry (unsigned long data)
 
        if (plug_device) {
                ide_unlock_host(hwif->host);
-               ide_plug_device(drive);
+               ide_requeue_and_plug(drive, rq_in_flight);
        }
 }
 
@@ -776,6 +785,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
        ide_startstop_t startstop;
        irqreturn_t irq_ret = IRQ_NONE;
        int plug_device = 0;
+       struct request *uninitialized_var(rq_in_flight);
 
        if (host->host_flags & IDE_HFLAG_SERIALIZE) {
                if (hwif != host->cur_port)
@@ -784,7 +794,8 @@ irqreturn_t ide_intr (int irq, void *dev_id)
 
        spin_lock_irqsave(&hwif->lock, flags);
 
-       if (hwif->ack_intr && hwif->ack_intr(hwif) == 0)
+       if (hwif->port_ops && hwif->port_ops->test_irq &&
+           hwif->port_ops->test_irq(hwif) == 0)
                goto out;
 
        handler = hwif->handler;
@@ -855,6 +866,8 @@ irqreturn_t ide_intr (int irq, void *dev_id)
         */
        if (startstop == ide_stopped && hwif->polling == 0) {
                BUG_ON(hwif->handler);
+               rq_in_flight = hwif->rq;
+               hwif->rq = NULL;
                ide_unlock_port(hwif);
                plug_device = 1;
        }
@@ -864,7 +877,7 @@ out:
 out_early:
        if (plug_device) {
                ide_unlock_host(hwif->host);
-               ide_plug_device(drive);
+               ide_requeue_and_plug(drive, rq_in_flight);
        }
 
        return irq_ret;