ide: improve handling of Power Management requests
[pandora-kernel.git] / drivers / ide / ide-io.c
index 272cc38..93b7886 100644 (file)
@@ -476,10 +476,14 @@ 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;
+
+               if (drive->dev_flags & IDE_DFLAG_BLOCKED)
+                       rq = hwif->rq;
+               else
+                       WARN_ON_ONCE(hwif->rq);
+
                if (drive->dev_flags & IDE_DFLAG_SLEEPING &&
                    time_after(drive->sleep, jiffies)) {
                        ide_unlock_port(hwif);
@@ -506,43 +510,29 @@ repeat:
                hwif->cur_dev = drive;
                drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED);
 
-               spin_unlock_irq(&hwif->lock);
-               spin_lock_irq(q->queue_lock);
-               /*
-                * we know that the queue isn't empty, but this can happen
-                * if the q->prep_rq_fn() decides to kill a request
-                */
-               if (!rq)
+               if (rq == NULL) {
+                       spin_unlock_irq(&hwif->lock);
+                       spin_lock_irq(q->queue_lock);
+                       /*
+                        * we know that the queue isn't empty, but this can
+                        * happen if ->prep_rq_fn() decides to kill a request
+                        */
                        rq = blk_fetch_request(drive->queue);
+                       spin_unlock_irq(q->queue_lock);
+                       spin_lock_irq(&hwif->lock);
 
-               spin_unlock_irq(q->queue_lock);
-               spin_lock_irq(&hwif->lock);
-
-               if (!rq) {
-                       ide_unlock_port(hwif);
-                       goto out;
+                       if (rq == NULL) {
+                               ide_unlock_port(hwif);
+                               goto out;
+                       }
                }
 
                /*
                 * 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 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...
-                * 
-                * We let requests forced at head of queue with ide-preempt
-                * though. I hope that doesn't happen too much, hopefully not
-                * unless the subdriver triggers such a thing in its own PM
-                * state machine.
+                * if we are currently power managed.
                 */
-               if ((drive->dev_flags & IDE_DFLAG_BLOCKED) &&
-                   blk_pm_request(rq) == 0 &&
-                   (rq->cmd_flags & REQ_PREEMPT) == 0) {
-                       /* there should be no pending command at this point */
-                       ide_unlock_port(hwif);
-                       goto plug_device;
-               }
+               BUG_ON((drive->dev_flags & IDE_DFLAG_BLOCKED) &&
+                      blk_pm_request(rq) == 0);
 
                hwif->rq = rq;
 
@@ -683,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);
@@ -803,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;