]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/sata_mv.c
Merge branch 'irq-pio'
[linux-2.6-omap-h63xx.git] / drivers / scsi / sata_mv.c
index 275ed9bd898cae8a0d1d25d5d47b7a077715179f..e6d141dd0385b20d3f3fb54913d98e37e0987790 100644 (file)
@@ -87,7 +87,7 @@ enum {
        MV_FLAG_IRQ_COALESCE    = (1 << 29),  /* IRQ coalescing capability */
        MV_COMMON_FLAGS         = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                   ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
-                                  ATA_FLAG_NO_ATAPI),
+                                  ATA_FLAG_PIO_POLLING),
        MV_6XXX_FLAGS           = MV_FLAG_IRQ_COALESCE,
 
        CRQB_FLAG_READ          = (1 << 0),
@@ -378,7 +378,6 @@ static struct scsi_host_template mv_sht = {
        .name                   = DRV_NAME,
        .ioctl                  = ata_scsi_ioctl,
        .queuecommand           = ata_scsi_queuecmd,
-       .eh_strategy_handler    = ata_scsi_error,
        .can_queue              = MV_USE_Q_DEPTH,
        .this_id                = ATA_SHT_THIS_ID,
        .sg_tablesize           = MV_MAX_SG_CT / 2,
@@ -681,7 +680,7 @@ static void mv_stop_dma(struct ata_port *ap)
        }
 
        if (EDMA_EN & reg) {
-               printk(KERN_ERR "ata%u: Unable to stop eDMA\n", ap->id);
+               ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
                /* FIXME: Consider doing a reset here to recover */
        }
 }
@@ -748,7 +747,7 @@ static void mv_dump_all_regs(void __iomem *mmio_base, int port,
        mv_dump_mem(mmio_base+0xf00, 0x4);
        mv_dump_mem(mmio_base+0x1d00, 0x6c);
        for (hc = start_hc; hc < start_hc + num_hcs; hc++) {
-               hc_base = mv_hc_base(mmio_base, port >> MV_PORT_HC_SHIFT);
+               hc_base = mv_hc_base(mmio_base, hc);
                DPRINTK("HC regs (HC %i):\n", hc);
                mv_dump_mem(hc_base, 0x1c);
        }
@@ -1010,7 +1009,7 @@ static void mv_fill_sg(struct ata_queued_cmd *qc)
 
                        pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff);
                        pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16);
-                       pp->sg_tbl[i].flags_size = cpu_to_le32(len);
+                       pp->sg_tbl[i].flags_size = cpu_to_le32(len & 0xffff);
 
                        sg_len -= len;
                        addr += len;
@@ -1310,8 +1309,8 @@ static void mv_err_intr(struct ata_port *ap)
        edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
 
        if (EDMA_ERR_SERR & edma_err_cause) {
-               serr = scr_read(ap, SCR_ERROR);
-               scr_write_flush(ap, SCR_ERROR, serr);
+               sata_scr_read(ap, SCR_ERROR, &serr);
+               sata_scr_write_flush(ap, SCR_ERROR, serr);
        }
        if (EDMA_ERR_SELF_DIS & edma_err_cause) {
                struct mv_port_priv *pp = ap->private_data;
@@ -1350,7 +1349,6 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
 {
        void __iomem *mmio = host_set->mmio_base;
        void __iomem *hc_mmio = mv_hc_base(mmio, hc);
-       struct ata_port *ap;
        struct ata_queued_cmd *qc;
        u32 hc_irq_cause;
        int shift, port, port0, hard_port, handled;
@@ -1373,25 +1371,32 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
 
        for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
                u8 ata_status = 0;
-               ap = host_set->ports[port];
+               struct ata_port *ap = host_set->ports[port];
+               struct mv_port_priv *pp = ap->private_data;
+
                hard_port = port & MV_PORT_MASK;        /* range 0-3 */
                handled = 0;    /* ensure ata_status is set if handled++ */
 
-               if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
-                       /* new CRPB on the queue; just one at a time until NCQ
-                        */
-                       ata_status = mv_get_crpb_status(ap);
-                       handled++;
-               } else if ((DEV_IRQ << hard_port) & hc_irq_cause) {
-                       /* received ATA IRQ; read the status reg to clear INTRQ
-                        */
-                       ata_status = readb((void __iomem *)
+               /* Note that DEV_IRQ might happen spuriously during EDMA,
+                * and should be ignored in such cases.  We could mask it,
+                * but it's pretty rare and may not be worth the overhead.
+                */ 
+               if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
+                       /* EDMA: check for response queue interrupt */
+                       if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
+                               ata_status = mv_get_crpb_status(ap);
+                               handled = 1;
+                       }
+               } else {
+                       /* PIO: check for device (drive) interrupt */
+                       if ((DEV_IRQ << hard_port) & hc_irq_cause) {
+                               ata_status = readb((void __iomem *)
                                           ap->ioaddr.status_addr);
-                       handled++;
+                               handled = 1;
+                       }
                }
 
-               if (ap &&
-                   (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)))
+               if (ap && (ap->flags & ATA_FLAG_DISABLED))
                        continue;
 
                err_mask = ac_err_mask(ata_status);
@@ -1403,16 +1408,16 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
                if ((PORT0_ERR << shift) & relevant) {
                        mv_err_intr(ap);
                        err_mask |= AC_ERR_OTHER;
-                       handled++;
+                       handled = 1;
                }
 
-               if (handled && ap) {
+               if (handled) {
                        qc = ata_qc_from_tag(ap, ap->active_tag);
-                       if (NULL != qc) {
+                       if (qc && (qc->flags & ATA_QCFLAG_ACTIVE)) {
                                VPRINTK("port %u IRQ found for qc, "
                                        "ata_status 0x%x\n", port,ata_status);
                                /* mark qc status appropriately */
-                               if (!(qc->tf.ctl & ATA_NIEN)) {
+                               if (!(qc->tf.flags & ATA_TFLAG_POLLING)) {
                                        qc->err_mask |= err_mask;
                                        ata_qc_complete(qc);
                                }
@@ -1929,15 +1934,16 @@ static void __mv_phy_reset(struct ata_port *ap, int can_sleep)
 
        /* Issue COMRESET via SControl */
 comreset_retry:
-       scr_write_flush(ap, SCR_CONTROL, 0x301);
+       sata_scr_write_flush(ap, SCR_CONTROL, 0x301);
        __msleep(1, can_sleep);
 
-       scr_write_flush(ap, SCR_CONTROL, 0x300);
+       sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
        __msleep(20, can_sleep);
 
        timeout = jiffies + msecs_to_jiffies(200);
        do {
-               sstatus = scr_read(ap, SCR_STATUS) & 0x3;
+               sata_scr_read(ap, SCR_STATUS, &sstatus);
+               sstatus &= 0x3;
                if ((sstatus == 3) || (sstatus == 0))
                        break;
 
@@ -1954,11 +1960,12 @@ comreset_retry:
                "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
                mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
 
-       if (sata_dev_present(ap)) {
+       if (ata_port_online(ap)) {
                ata_port_probe(ap);
        } else {
-               printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n",
-                      ap->id, scr_read(ap, SCR_STATUS));
+               sata_scr_read(ap, SCR_STATUS, &sstatus);
+               ata_port_printk(ap, KERN_INFO,
+                               "no device found (phy stat %08x)\n", sstatus);
                ata_port_disable(ap);
                return;
        }
@@ -1985,7 +1992,7 @@ comreset_retry:
        tf.nsect = readb((void __iomem *) ap->ioaddr.nsect_addr);
 
        dev->class = ata_dev_classify(&tf);
-       if (!ata_dev_present(dev)) {
+       if (!ata_dev_enabled(dev)) {
                VPRINTK("Port disabled post-sig: No device present.\n");
                ata_port_disable(ap);
        }
@@ -2016,7 +2023,7 @@ static void mv_eng_timeout(struct ata_port *ap)
 {
        struct ata_queued_cmd *qc;
 
-       printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id);
+       ata_port_printk(ap, KERN_ERR, "Entering mv_eng_timeout\n");
        DPRINTK("All regs @ start of eng_timeout\n");
        mv_dump_all_regs(ap->host_set->mmio_base, ap->port_no,
                         to_pci_dev(ap->host_set->dev));