include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / drivers / ata / libata-sff.c
index 0eae9b4..6411e0c 100644 (file)
@@ -33,6 +33,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/gfp.h>
 #include <linux/pci.h>
 #include <linux/libata.h>
 #include <linux/highmem.h>
@@ -52,6 +53,7 @@ const struct ata_port_operations ata_sff_port_ops = {
        .softreset              = ata_sff_softreset,
        .hardreset              = sata_sff_hardreset,
        .postreset              = ata_sff_postreset,
+       .drain_fifo             = ata_sff_drain_fifo,
        .error_handler          = ata_sff_error_handler,
        .post_internal_cmd      = ata_sff_post_internal_cmd,
 
@@ -64,6 +66,8 @@ const struct ata_port_operations ata_sff_port_ops = {
        .sff_irq_on             = ata_sff_irq_on,
        .sff_irq_clear          = ata_sff_irq_clear,
 
+       .lost_interrupt         = ata_sff_lost_interrupt,
+
        .port_start             = ata_sff_port_start,
 };
 EXPORT_SYMBOL_GPL(ata_sff_port_ops);
@@ -84,6 +88,7 @@ const struct ata_port_operations ata_bmdma32_port_ops = {
        .inherits               = &ata_bmdma_port_ops,
 
        .sff_data_xfer          = ata_sff_data_xfer32,
+       .port_start             = ata_sff_port_start32,
 };
 EXPORT_SYMBOL_GPL(ata_bmdma32_port_ops);
 
@@ -723,17 +728,23 @@ unsigned int ata_sff_data_xfer(struct ata_device *dev, unsigned char *buf,
        else
                iowrite16_rep(data_addr, buf, words);
 
-       /* Transfer trailing byte, if any. */
+       /* Transfer trailing byte, if any. */
        if (unlikely(buflen & 0x01)) {
-               __le16 align_buf[1] = { 0 };
-               unsigned char *trailing_buf = buf + buflen - 1;
+               unsigned char pad[2];
+
+               /* Point buf to the tail of buffer */
+               buf += buflen - 1;
 
+               /*
+                * Use io*16_rep() accessors here as well to avoid pointlessly
+                * swapping bytes to and from on the big endian machines...
+                */
                if (rw == READ) {
-                       align_buf[0] = cpu_to_le16(ioread16(data_addr));
-                       memcpy(trailing_buf, align_buf, 1);
+                       ioread16_rep(data_addr, pad, 1);
+                       *buf = pad[0];
                } else {
-                       memcpy(align_buf, trailing_buf, 1);
-                       iowrite16(le16_to_cpu(align_buf[0]), data_addr);
+                       pad[0] = *buf;
+                       iowrite16_rep(data_addr, pad, 1);
                }
                words++;
        }
@@ -767,24 +778,41 @@ unsigned int ata_sff_data_xfer32(struct ata_device *dev, unsigned char *buf,
        unsigned int words = buflen >> 2;
        int slop = buflen & 3;
 
+       if (!(ap->pflags & ATA_PFLAG_PIO32))
+               return ata_sff_data_xfer(dev, buf, buflen, rw);
+
        /* Transfer multiple of 4 bytes */
        if (rw == READ)
                ioread32_rep(data_addr, buf, words);
        else
                iowrite32_rep(data_addr, buf, words);
 
+       /* Transfer trailing bytes, if any */
        if (unlikely(slop)) {
-               __le32 pad;
+               unsigned char pad[4];
+
+               /* Point buf to the tail of buffer */
+               buf += buflen - slop;
+
+               /*
+                * Use io*_rep() accessors here as well to avoid pointlessly
+                * swapping bytes to and from on the big endian machines...
+                */
                if (rw == READ) {
-                       pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
-                       memcpy(buf + buflen - slop, &pad, slop);
+                       if (slop < 3)
+                               ioread16_rep(data_addr, pad, 1);
+                       else
+                               ioread32_rep(data_addr, pad, 1);
+                       memcpy(buf, pad, slop);
                } else {
-                       memcpy(&pad, buf + buflen - slop, slop);
-                       iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
+                       memcpy(pad, buf, slop);
+                       if (slop < 3)
+                               iowrite16_rep(data_addr, pad, 1);
+                       else
+                               iowrite32_rep(data_addr, pad, 1);
                }
-               words++;
        }
-       return words << 2;
+       return (buflen + 1) & ~1;
 }
 EXPORT_SYMBOL_GPL(ata_sff_data_xfer32);
 
@@ -866,6 +894,9 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
                                       do_write);
        }
 
+       if (!do_write)
+               flush_dcache_page(page);
+
        qc->curbytes += qc->sect_size;
        qc->cursg_ofs += qc->sect_size;
 
@@ -1013,9 +1044,12 @@ next_sg:
                qc->cursg_ofs = 0;
        }
 
-       /* consumed can be larger than count only for the last transfer */
-       WARN_ON_ONCE(qc->cursg && count != consumed);
-
+       /*
+        * There used to be a  WARN_ON_ONCE(qc->cursg && count != consumed);
+        * Unfortunately __atapi_pio_bytes doesn't know enough to do the WARN
+        * check correctly as it doesn't know if it is the last request being
+        * made. Somebody should implement a proper sanity check.
+        */
        if (bytes)
                goto next_sg;
        return 0;
@@ -1319,7 +1353,7 @@ fsm_start:
                                         * condition.  Mark hint.
                                         */
                                        ata_ehi_push_desc(ehi, "ST-ATA: "
-                                               "DRQ=1 with device error, "
+                                               "DRQ=0 without device error, "
                                                "dev_stat 0x%X", status);
                                        qc->err_mask |= AC_ERR_HSM |
                                                        AC_ERR_NODEV_HINT;
@@ -1355,6 +1389,16 @@ fsm_start:
                                        qc->err_mask |= AC_ERR_HSM;
                                }
 
+                               /* There are oddball controllers with
+                                * status register stuck at 0x7f and
+                                * lbal/m/h at zero which makes it
+                                * pass all other presence detection
+                                * mechanisms we have.  Set NODEV_HINT
+                                * for it.  Kernel bz#7241.
+                                */
+                               if (status == 0x7f)
+                                       qc->err_mask |= AC_ERR_NODEV_HINT;
+
                                /* ata_pio_sectors() might change the
                                 * state to HSM_ST_LAST. so, the state
                                 * is changed after ata_pio_sectors().
@@ -1619,11 +1663,12 @@ EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf);
  *     RETURNS:
  *     One if interrupt was handled, zero if not (shared irq).
  */
-inline unsigned int ata_sff_host_intr(struct ata_port *ap,
+unsigned int ata_sff_host_intr(struct ata_port *ap,
                                      struct ata_queued_cmd *qc)
 {
        struct ata_eh_info *ehi = &ap->link.eh_info;
        u8 status, host_stat = 0;
+       bool bmdma_stopped = false;
 
        VPRINTK("ata%u: protocol %d task_state %d\n",
                ap->print_id, qc->tf.protocol, ap->hsm_task_state);
@@ -1656,6 +1701,7 @@ inline unsigned int ata_sff_host_intr(struct ata_port *ap,
 
                        /* before we do anything else, clear DMA-Start bit */
                        ap->ops->bmdma_stop(qc);
+                       bmdma_stopped = true;
 
                        if (unlikely(host_stat & ATA_DMA_ERR)) {
                                /* error when transfering data to/from memory */
@@ -1673,8 +1719,14 @@ inline unsigned int ata_sff_host_intr(struct ata_port *ap,
 
        /* check main status, clearing INTRQ if needed */
        status = ata_sff_irq_status(ap);
-       if (status & ATA_BUSY)
-               goto idle_irq;
+       if (status & ATA_BUSY) {
+               if (bmdma_stopped) {
+                       /* BMDMA engine is already stopped, we're screwed */
+                       qc->err_mask |= AC_ERR_HSM;
+                       ap->hsm_task_state = HSM_ST_ERR;
+               } else
+                       goto idle_irq;
+       }
 
        /* ack bmdma irq events */
        ap->ops->sff_irq_clear(ap);
@@ -1719,25 +1771,72 @@ EXPORT_SYMBOL_GPL(ata_sff_host_intr);
 irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
 {
        struct ata_host *host = dev_instance;
+       bool retried = false;
        unsigned int i;
-       unsigned int handled = 0;
+       unsigned int handled, idle, polling;
        unsigned long flags;
 
        /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
        spin_lock_irqsave(&host->lock, flags);
 
+retry:
+       handled = idle = polling = 0;
        for (i = 0; i < host->n_ports; i++) {
-               struct ata_port *ap;
+               struct ata_port *ap = host->ports[i];
+               struct ata_queued_cmd *qc;
 
-               ap = host->ports[i];
-               if (ap &&
-                   !(ap->flags & ATA_FLAG_DISABLED)) {
-                       struct ata_queued_cmd *qc;
+               if (unlikely(ap->flags & ATA_FLAG_DISABLED))
+                       continue;
 
-                       qc = ata_qc_from_tag(ap, ap->link.active_tag);
-                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
-                           (qc->flags & ATA_QCFLAG_ACTIVE))
+               qc = ata_qc_from_tag(ap, ap->link.active_tag);
+               if (qc) {
+                       if (!(qc->tf.flags & ATA_TFLAG_POLLING))
                                handled |= ata_sff_host_intr(ap, qc);
+                       else
+                               polling |= 1 << i;
+               } else
+                       idle |= 1 << i;
+       }
+
+       /*
+        * If no port was expecting IRQ but the controller is actually
+        * asserting IRQ line, nobody cared will ensue.  Check IRQ
+        * pending status if available and clear spurious IRQ.
+        */
+       if (!handled && !retried) {
+               bool retry = false;
+
+               for (i = 0; i < host->n_ports; i++) {
+                       struct ata_port *ap = host->ports[i];
+
+                       if (polling & (1 << i))
+                               continue;
+
+                       if (!ap->ops->sff_irq_check ||
+                           !ap->ops->sff_irq_check(ap))
+                               continue;
+
+                       if (printk_ratelimit())
+                               ata_port_printk(ap, KERN_INFO,
+                                               "clearing spurious IRQ\n");
+
+                       if (idle & (1 << i)) {
+                               ap->ops->sff_check_status(ap);
+                               ap->ops->sff_irq_clear(ap);
+                       } else {
+                               /* clear INTRQ and check if BUSY cleared */
+                               if (!(ap->ops->sff_check_status(ap) & ATA_BUSY))
+                                       retry |= true;
+                               /*
+                                * With command in flight, we can't do
+                                * sff_irq_clear() w/o racing with completion.
+                                */
+                       }
+               }
+
+               if (retry) {
+                       retried = true;
+                       goto retry;
                }
        }
 
@@ -1748,6 +1847,48 @@ irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
 EXPORT_SYMBOL_GPL(ata_sff_interrupt);
 
 /**
+ *     ata_sff_lost_interrupt  -       Check for an apparent lost interrupt
+ *     @ap: port that appears to have timed out
+ *
+ *     Called from the libata error handlers when the core code suspects
+ *     an interrupt has been lost. If it has complete anything we can and
+ *     then return. Interface must support altstatus for this faster
+ *     recovery to occur.
+ *
+ *     Locking:
+ *     Caller holds host lock
+ */
+
+void ata_sff_lost_interrupt(struct ata_port *ap)
+{
+       u8 status;
+       struct ata_queued_cmd *qc;
+
+       /* Only one outstanding command per SFF channel */
+       qc = ata_qc_from_tag(ap, ap->link.active_tag);
+       /* Check we have a live one.. */
+       if (qc == NULL ||  !(qc->flags & ATA_QCFLAG_ACTIVE))
+               return;
+       /* We cannot lose an interrupt on a polled command */
+       if (qc->tf.flags & ATA_TFLAG_POLLING)
+               return;
+       /* See if the controller thinks it is still busy - if so the command
+          isn't a lost IRQ but is still in progress */
+       status = ata_sff_altstatus(ap);
+       if (status & ATA_BUSY)
+               return;
+
+       /* There was a command running, we are no longer busy and we have
+          no interrupt. */
+       ata_port_printk(ap, KERN_WARNING, "lost interrupt (Status 0x%x)\n",
+                                                               status);
+       /* Run the host interrupt logic as if the interrupt had not been
+          lost */
+       ata_sff_host_intr(ap, qc);
+}
+EXPORT_SYMBOL_GPL(ata_sff_lost_interrupt);
+
+/**
  *     ata_sff_freeze - Freeze SFF controller port
  *     @ap: port to freeze
  *
@@ -2039,6 +2180,7 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
        iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
        udelay(20);     /* FIXME: flush */
        iowrite8(ap->ctl, ioaddr->ctl_addr);
+       ap->last_ctl = ap->ctl;
 
        /* wait the port to become ready */
        return ata_sff_wait_after_reset(&ap->link, devmask, deadline);
@@ -2163,12 +2305,47 @@ void ata_sff_postreset(struct ata_link *link, unsigned int *classes)
        }
 
        /* set up device control */
-       if (ap->ioaddr.ctl_addr)
+       if (ap->ioaddr.ctl_addr) {
                iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
+               ap->last_ctl = ap->ctl;
+       }
 }
 EXPORT_SYMBOL_GPL(ata_sff_postreset);
 
 /**
+ *     ata_sff_drain_fifo - Stock FIFO drain logic for SFF controllers
+ *     @qc: command
+ *
+ *     Drain the FIFO and device of any stuck data following a command
+ *     failing to complete. In some cases this is necessary before a
+ *     reset will recover the device.
+ *
+ */
+
+void ata_sff_drain_fifo(struct ata_queued_cmd *qc)
+{
+       int count;
+       struct ata_port *ap;
+
+       /* We only need to flush incoming data when a command was running */
+       if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE)
+               return;
+
+       ap = qc->ap;
+       /* Drain up to 64K of data before we give up this recovery method */
+       for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ)
+                                               && count < 65536; count += 2)
+               ioread16(ap->ioaddr.data_addr);
+
+       /* Can become DEBUG later */
+       if (count)
+               ata_port_printk(ap, KERN_DEBUG,
+                       "drained %d bytes to clear DRQ.\n", count);
+
+}
+EXPORT_SYMBOL_GPL(ata_sff_drain_fifo);
+
+/**
  *     ata_sff_error_handler - Stock error handler for BMDMA controller
  *     @ap: port to handle error for
  *
@@ -2209,7 +2386,8 @@ void ata_sff_error_handler(struct ata_port *ap)
                 * really a timeout event, adjust error mask and
                 * cancel frozen state.
                 */
-               if (qc->err_mask == AC_ERR_TIMEOUT && (host_stat & ATA_DMA_ERR)) {
+               if (qc->err_mask == AC_ERR_TIMEOUT
+                                               && (host_stat & ATA_DMA_ERR)) {
                        qc->err_mask = AC_ERR_HOST_BUS;
                        thaw = 1;
                }
@@ -2220,6 +2398,13 @@ void ata_sff_error_handler(struct ata_port *ap)
        ata_sff_sync(ap);               /* FIXME: We don't need this */
        ap->ops->sff_check_status(ap);
        ap->ops->sff_irq_clear(ap);
+       /* We *MUST* do FIFO draining before we issue a reset as several
+        * devices helpfully clear their internal state and will lock solid
+        * if we touch the data port post reset. Pass qc in case anyone wants
+        *  to do different PIO/DMA recovery or has per command fixups
+        */
+       if (ap->ops->drain_fifo)
+               ap->ops->drain_fifo(qc);
 
        spin_unlock_irqrestore(ap->lock, flags);
 
@@ -2258,7 +2443,7 @@ void ata_sff_post_internal_cmd(struct ata_queued_cmd *qc)
        ap->hsm_task_state = HSM_ST_IDLE;
 
        if (ap->ioaddr.bmdma_addr)
-               ata_bmdma_stop(qc);
+               ap->ops->bmdma_stop(qc);
 
        spin_unlock_irqrestore(ap->lock, flags);
 }
@@ -2286,6 +2471,29 @@ int ata_sff_port_start(struct ata_port *ap)
 EXPORT_SYMBOL_GPL(ata_sff_port_start);
 
 /**
+ *     ata_sff_port_start32 - Set port up for dma.
+ *     @ap: Port to initialize
+ *
+ *     Called just after data structures for each port are
+ *     initialized.  Allocates space for PRD table if the device
+ *     is DMA capable SFF.
+ *
+ *     May be used as the port_start() entry in ata_port_operations for
+ *     devices that are capable of 32bit PIO.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+int ata_sff_port_start32(struct ata_port *ap)
+{
+       ap->pflags |= ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE;
+       if (ap->ioaddr.bmdma_addr)
+               return ata_port_start(ap);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ata_sff_port_start32);
+
+/**
  *     ata_sff_std_ports - initialize ioaddr with standard port offsets.
  *     @ioaddr: IO address structure to be initialized
  *
@@ -2507,6 +2715,7 @@ void ata_bus_reset(struct ata_port *ap)
        if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) {
                /* set up device control for ATA_FLAG_SATA_RESET */
                iowrite8(ap->ctl, ioaddr->ctl_addr);
+               ap->last_ctl = ap->ctl;
        }
 
        DPRINTK("EXIT\n");
@@ -2858,6 +3067,7 @@ EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host);
  *     @ppi: array of port_info, must be enough for two ports
  *     @sht: scsi_host_template to use when registering the host
  *     @host_priv: host private_data
+ *     @hflag: host flags
  *
  *     This is a helper function which can be called from a driver's
  *     xxx_init_one() probe function if the hardware uses traditional
@@ -2878,8 +3088,8 @@ EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host);
  *     Zero on success, negative on errno-based value on error.
  */
 int ata_pci_sff_init_one(struct pci_dev *pdev,
-                        const struct ata_port_info * const *ppi,
-                        struct scsi_host_template *sht, void *host_priv)
+                const struct ata_port_info * const *ppi,
+                struct scsi_host_template *sht, void *host_priv, int hflag)
 {
        struct device *dev = &pdev->dev;
        const struct ata_port_info *pi = NULL;
@@ -2914,6 +3124,7 @@ int ata_pci_sff_init_one(struct pci_dev *pdev,
        if (rc)
                goto out;
        host->private_data = host_priv;
+       host->flags |= hflag;
 
        pci_set_master(pdev);
        rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht);
@@ -2928,4 +3139,3 @@ out:
 EXPORT_SYMBOL_GPL(ata_pci_sff_init_one);
 
 #endif /* CONFIG_PCI */
-