]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
[PATCH] libata-dev: Convert ata_pio_task() to use the new ata_hsm_move()
authorAlbert Lee <albertcc@tw.ibm.com>
Sat, 25 Mar 2006 09:50:15 +0000 (17:50 +0800)
committerJeff Garzik <jeff@garzik.org>
Wed, 29 Mar 2006 22:21:54 +0000 (17:21 -0500)
Convert ata_pio_task() to use the new ata_hsm_move().

Changes:
- refactor ata_pio_task() to poll device status register and
- call the new ata_hsm_move() when device indicates it is not BSY.

Signed-off-by: Albert Lee <albertcc@tw.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
drivers/scsi/libata-core.c

index 33b39d3ce2d328276662e2a882a55f29a8632d19..eeeeda0481a2aec0fd5b0842c44e164e9bc14b68 100644 (file)
@@ -3986,44 +3986,40 @@ fsm_start:
 static void ata_pio_task(void *_data)
 {
        struct ata_port *ap = _data;
-       unsigned long timeout;
-       int has_next;
+       struct ata_queued_cmd *qc;
+       u8 status;
+       int poll_next;
 
 fsm_start:
-       timeout = 0;
-       has_next = 1;
+       WARN_ON(ap->hsm_task_state == HSM_ST_IDLE);
 
-       switch (ap->hsm_task_state) {
-       case HSM_ST_FIRST:
-               has_next = ata_pio_first_block(ap);
-               break;
-
-       case HSM_ST:
-               ata_pio_block(ap);
-               break;
-
-       case HSM_ST_LAST:
-               has_next = ata_pio_complete(ap);
-               break;
-
-       case HSM_ST_POLL:
-       case HSM_ST_LAST_POLL:
-               timeout = ata_pio_poll(ap);
-               break;
-
-       case HSM_ST_TMOUT:
-       case HSM_ST_ERR:
-               ata_pio_error(ap);
-               return;
+       qc = ata_qc_from_tag(ap, ap->active_tag);
+       WARN_ON(qc == NULL);
 
-       default:
-               BUG();
-               return;
+       /*
+        * This is purely heuristic.  This is a fast path.
+        * Sometimes when we enter, BSY will be cleared in
+        * a chk-status or two.  If not, the drive is probably seeking
+        * or something.  Snooze for a couple msecs, then
+        * chk-status again.  If still busy, queue delayed work.
+        */
+       status = ata_busy_wait(ap, ATA_BUSY, 5);
+       if (status & ATA_BUSY) {
+               msleep(2);
+               status = ata_busy_wait(ap, ATA_BUSY, 10);
+               if (status & ATA_BUSY) {
+                       ata_port_queue_task(ap, ata_pio_task, ap, ATA_SHORT_PAUSE);
+                       return;
+               }
        }
 
-       if (timeout)
-               ata_port_queue_task(ap, ata_pio_task, ap, timeout);
-       else if (has_next)
+       /* move the HSM */
+       poll_next = ata_hsm_move(ap, qc, status, 1);
+
+       /* another command or interrupt handler
+        * may be running at this point.
+        */
+       if (poll_next)
                goto fsm_start;
 }