intelfb: add preliminary i2c support
[safe/jmp/linux-2.6] / drivers / scsi / sata_mv.c
index 3e91632..4a71578 100644 (file)
@@ -37,7 +37,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME       "sata_mv"
-#define DRV_VERSION    "0.6"
+#define DRV_VERSION    "0.7"
 
 enum {
        /* BAR's are enumerated in terms of pci_resource_start() terms */
@@ -50,6 +50,12 @@ enum {
 
        MV_PCI_REG_BASE         = 0,
        MV_IRQ_COAL_REG_BASE    = 0x18000,      /* 6xxx part only */
+       MV_IRQ_COAL_CAUSE               = (MV_IRQ_COAL_REG_BASE + 0x08),
+       MV_IRQ_COAL_CAUSE_LO            = (MV_IRQ_COAL_REG_BASE + 0x88),
+       MV_IRQ_COAL_CAUSE_HI            = (MV_IRQ_COAL_REG_BASE + 0x8c),
+       MV_IRQ_COAL_THRESHOLD           = (MV_IRQ_COAL_REG_BASE + 0xcc),
+       MV_IRQ_COAL_TIME_THRESHOLD      = (MV_IRQ_COAL_REG_BASE + 0xd0),
+
        MV_SATAHC0_REG_BASE     = 0x20000,
        MV_FLASH_CTL            = 0x1046c,
        MV_GPIO_PORT_CTL        = 0x104f0,
@@ -87,7 +93,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_NO_ATAPI | ATA_FLAG_PIO_POLLING),
        MV_6XXX_FLAGS           = MV_FLAG_IRQ_COALESCE,
 
        CRQB_FLAG_READ          = (1 << 0),
@@ -266,33 +272,33 @@ enum chip_type {
 
 /* Command ReQuest Block: 32B */
 struct mv_crqb {
-       u32                     sg_addr;
-       u32                     sg_addr_hi;
-       u16                     ctrl_flags;
-       u16                     ata_cmd[11];
+       __le32                  sg_addr;
+       __le32                  sg_addr_hi;
+       __le16                  ctrl_flags;
+       __le16                  ata_cmd[11];
 };
 
 struct mv_crqb_iie {
-       u32                     addr;
-       u32                     addr_hi;
-       u32                     flags;
-       u32                     len;
-       u32                     ata_cmd[4];
+       __le32                  addr;
+       __le32                  addr_hi;
+       __le32                  flags;
+       __le32                  len;
+       __le32                  ata_cmd[4];
 };
 
 /* Command ResPonse Block: 8B */
 struct mv_crpb {
-       u16                     id;
-       u16                     flags;
-       u32                     tmstmp;
+       __le16                  id;
+       __le16                  flags;
+       __le32                  tmstmp;
 };
 
 /* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */
 struct mv_sg {
-       u32                     addr;
-       u32                     flags_size;
-       u32                     addr_hi;
-       u32                     reserved;
+       __le32                  addr;
+       __le32                  flags_size;
+       __le32                  addr_hi;
+       __le32                  reserved;
 };
 
 struct mv_port_priv {
@@ -302,9 +308,6 @@ struct mv_port_priv {
        dma_addr_t              crpb_dma;
        struct mv_sg            *sg_tbl;
        dma_addr_t              sg_tbl_dma;
-
-       unsigned                req_producer;           /* cp of req_in_ptr */
-       unsigned                rsp_consumer;           /* cp of rsp_out_ptr */
        u32                     pp_flags;
 };
 
@@ -378,17 +381,16 @@ 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,
-       .max_sectors            = ATA_MAX_SECTORS,
        .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
        .emulated               = ATA_SHT_EMULATED,
        .use_clustering         = ATA_SHT_USE_CLUSTERING,
        .proc_name              = DRV_NAME,
        .dma_boundary           = MV_DMA_BOUNDARY,
        .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
 };
 
@@ -405,6 +407,7 @@ static const struct ata_port_operations mv5_ops = {
 
        .qc_prep                = mv_qc_prep,
        .qc_issue               = mv_qc_issue,
+       .data_xfer              = ata_mmio_data_xfer,
 
        .eng_timeout            = mv_eng_timeout,
 
@@ -432,6 +435,7 @@ static const struct ata_port_operations mv6_ops = {
 
        .qc_prep                = mv_qc_prep,
        .qc_issue               = mv_qc_issue,
+       .data_xfer              = ata_mmio_data_xfer,
 
        .eng_timeout            = mv_eng_timeout,
 
@@ -631,8 +635,8 @@ static void mv_irq_clear(struct ata_port *ap)
  *      @base: port base address
  *      @pp: port private data
  *
- *      Verify the local cache of the eDMA state is accurate with an
- *      assert.
+ *      Verify the local cache of the eDMA state is accurate with a
+ *      WARN_ON.
  *
  *      LOCKING:
  *      Inherited from caller.
@@ -643,15 +647,15 @@ static void mv_start_dma(void __iomem *base, struct mv_port_priv *pp)
                writelfl(EDMA_EN, base + EDMA_CMD_OFS);
                pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
        }
-       assert(EDMA_EN & readl(base + EDMA_CMD_OFS));
+       WARN_ON(!(EDMA_EN & readl(base + EDMA_CMD_OFS)));
 }
 
 /**
  *      mv_stop_dma - Disable eDMA engine
  *      @ap: ATA channel to manipulate
  *
- *      Verify the local cache of the eDMA state is accurate with an
- *      assert.
+ *      Verify the local cache of the eDMA state is accurate with a
+ *      WARN_ON.
  *
  *      LOCKING:
  *      Inherited from caller.
@@ -669,7 +673,7 @@ static void mv_stop_dma(struct ata_port *ap)
                writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
                pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
        } else {
-               assert(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)));
+               WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
        }
 
        /* now properly wait for the eDMA to stop */
@@ -682,7 +686,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 */
        }
 }
@@ -749,7 +753,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);
        }
@@ -939,8 +943,6 @@ static int mv_port_start(struct ata_port *ap)
        writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK,
                 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
 
-       pp->req_producer = pp->rsp_consumer = 0;
-
        /* Don't turn on EDMA here...do it before DMA commands only.  Else
         * we'll be unable to send non-data, PIO, etc due to restricted access
         * to shadow regs.
@@ -1011,7 +1013,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;
@@ -1024,16 +1026,16 @@ static void mv_fill_sg(struct ata_queued_cmd *qc)
        }
 }
 
-static inline unsigned mv_inc_q_index(unsigned *index)
+static inline unsigned mv_inc_q_index(unsigned index)
 {
-       *index = (*index + 1) & MV_MAX_Q_DEPTH_MASK;
-       return *index;
+       return (index + 1) & MV_MAX_Q_DEPTH_MASK;
 }
 
-static inline void mv_crqb_pack_cmd(u16 *cmdw, u8 data, u8 addr, unsigned last)
+static inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
 {
-       *cmdw = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
+       u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
                (last ? CRQB_CMD_LAST : 0);
+       *cmdw = cpu_to_le16(tmp);
 }
 
 /**
@@ -1052,32 +1054,32 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
        struct mv_port_priv *pp = ap->private_data;
-       u16 *cw;
+       __le16 *cw;
        struct ata_taskfile *tf;
        u16 flags = 0;
+       unsigned in_index;
 
        if (ATA_PROT_DMA != qc->tf.protocol)
                return;
 
-       /* the req producer index should be the same as we remember it */
-       assert(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >>
-                EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
-              pp->req_producer);
-
        /* Fill in command request block
         */
        if (!(qc->tf.flags & ATA_TFLAG_WRITE))
                flags |= CRQB_FLAG_READ;
-       assert(MV_MAX_Q_DEPTH > qc->tag);
+       WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
        flags |= qc->tag << CRQB_TAG_SHIFT;
 
-       pp->crqb[pp->req_producer].sg_addr =
+       /* get current queue index from hardware */
+       in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
+                       >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+
+       pp->crqb[in_index].sg_addr =
                cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
-       pp->crqb[pp->req_producer].sg_addr_hi =
+       pp->crqb[in_index].sg_addr_hi =
                cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
-       pp->crqb[pp->req_producer].ctrl_flags = cpu_to_le16(flags);
+       pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
 
-       cw = &pp->crqb[pp->req_producer].ata_cmd[0];
+       cw = &pp->crqb[in_index].ata_cmd[0];
        tf = &qc->tf;
 
        /* Sadly, the CRQB cannot accomodate all registers--there are
@@ -1091,6 +1093,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
        case ATA_CMD_READ_EXT:
        case ATA_CMD_WRITE:
        case ATA_CMD_WRITE_EXT:
+       case ATA_CMD_WRITE_FUA_EXT:
                mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
                break;
 #ifdef LIBATA_NCQ              /* FIXME: remove this line when NCQ added */
@@ -1145,25 +1148,25 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
        struct mv_port_priv *pp = ap->private_data;
        struct mv_crqb_iie *crqb;
        struct ata_taskfile *tf;
+       unsigned in_index;
        u32 flags = 0;
 
        if (ATA_PROT_DMA != qc->tf.protocol)
                return;
 
-       /* the req producer index should be the same as we remember it */
-       assert(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >>
-                EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
-              pp->req_producer);
-
        /* Fill in Gen IIE command request block
         */
        if (!(qc->tf.flags & ATA_TFLAG_WRITE))
                flags |= CRQB_FLAG_READ;
 
-       assert(MV_MAX_Q_DEPTH > qc->tag);
+       WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
        flags |= qc->tag << CRQB_TAG_SHIFT;
 
-       crqb = (struct mv_crqb_iie *) &pp->crqb[pp->req_producer];
+       /* get current queue index from hardware */
+       in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
+                       >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+
+       crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
        crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
        crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
        crqb->flags = cpu_to_le32(flags);
@@ -1211,6 +1214,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
 {
        void __iomem *port_mmio = mv_ap_base(qc->ap);
        struct mv_port_priv *pp = qc->ap->private_data;
+       unsigned in_index;
        u32 in_ptr;
 
        if (ATA_PROT_DMA != qc->tf.protocol) {
@@ -1222,23 +1226,20 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
                return ata_qc_issue_prot(qc);
        }
 
-       in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+       in_ptr   = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+       in_index = (in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
 
-       /* the req producer index should be the same as we remember it */
-       assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
-              pp->req_producer);
        /* until we do queuing, the queue should be empty at this point */
-       assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
-              ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) >>
-                EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
+       WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
+               >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
 
-       mv_inc_q_index(&pp->req_producer);      /* now incr producer index */
+       in_index = mv_inc_q_index(in_index);    /* now incr producer index */
 
        mv_start_dma(port_mmio, pp);
 
        /* and write the request in pointer to kick the EDMA to life */
        in_ptr &= EDMA_REQ_Q_BASE_LO_MASK;
-       in_ptr |= pp->req_producer << EDMA_REQ_Q_PTR_SHIFT;
+       in_ptr |= in_index << EDMA_REQ_Q_PTR_SHIFT;
        writelfl(in_ptr, port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
 
        return 0;
@@ -1250,7 +1251,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
  *
  *      This routine is for use when the port is in DMA mode, when it
  *      will be using the CRPB (command response block) method of
- *      returning command completion information.  We assert indices
+ *      returning command completion information.  We check indices
  *      are good, grab status, and bump the response consumer index to
  *      prove that we're up to date.
  *
@@ -1261,34 +1262,36 @@ static u8 mv_get_crpb_status(struct ata_port *ap)
 {
        void __iomem *port_mmio = mv_ap_base(ap);
        struct mv_port_priv *pp = ap->private_data;
+       unsigned out_index;
        u32 out_ptr;
+       u8 ata_status;
 
-       out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+       out_ptr   = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+       out_index = (out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
 
-       /* the response consumer index should be the same as we remember it */
-       assert(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
-              pp->rsp_consumer);
+       ata_status = le16_to_cpu(pp->crpb[out_index].flags)
+                                       >> CRPB_FLAG_STATUS_SHIFT;
 
        /* increment our consumer index... */
-       pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer);
+       out_index = mv_inc_q_index(out_index);
 
        /* and, until we do NCQ, there should only be 1 CRPB waiting */
-       assert(((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) >>
-                EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
-              pp->rsp_consumer);
+       WARN_ON(out_index != ((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
+               >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
 
        /* write out our inc'd consumer index so EDMA knows we're caught up */
        out_ptr &= EDMA_RSP_Q_BASE_LO_MASK;
-       out_ptr |= pp->rsp_consumer << EDMA_RSP_Q_PTR_SHIFT;
+       out_ptr |= out_index << EDMA_RSP_Q_PTR_SHIFT;
        writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
 
        /* Return ATA status register for completed CRPB */
-       return (pp->crpb[pp->rsp_consumer].flags >> CRPB_FLAG_STATUS_SHIFT);
+       return ata_status;
 }
 
 /**
  *      mv_err_intr - Handle error interrupts on the port
  *      @ap: ATA channel to manipulate
+ *      @reset_allowed: bool: 0 == don't trigger from reset here
  *
  *      In most cases, just clear the interrupt and move on.  However,
  *      some cases require an eDMA reset, which is done right before
@@ -1299,7 +1302,7 @@ static u8 mv_get_crpb_status(struct ata_port *ap)
  *      LOCKING:
  *      Inherited from caller.
  */
-static void mv_err_intr(struct ata_port *ap)
+static void mv_err_intr(struct ata_port *ap, int reset_allowed)
 {
        void __iomem *port_mmio = mv_ap_base(ap);
        u32 edma_err_cause, serr = 0;
@@ -1307,8 +1310,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;
@@ -1321,9 +1324,8 @@ static void mv_err_intr(struct ata_port *ap)
        writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
 
        /* check for fatal here and recover if needed */
-       if (EDMA_ERR_FATAL & edma_err_cause) {
+       if (reset_allowed && (EDMA_ERR_FATAL & edma_err_cause))
                mv_stop_and_reset(ap);
-       }
 }
 
 /**
@@ -1347,12 +1349,10 @@ 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;
        unsigned int err_mask;
-       u8 ata_status = 0;
 
        if (hc == 0) {
                port0 = 0;
@@ -1370,25 +1370,38 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
                hc,relevant,hc_irq_cause);
 
        for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
-               ap = host_set->ports[port];
-               hard_port = port & MV_PORT_MASK;        /* range 0-3 */
+               u8 ata_status = 0;
+               struct ata_port *ap = host_set->ports[port];
+               struct mv_port_priv *pp = ap->private_data;
+
+               hard_port = mv_hardport_from_port(port); /* 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.
+                * The cause of this is still under investigation.
+                */
+               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;
+                               /* ignore spurious intr if drive still BUSY */
+                               if (ata_status & ATA_BUSY) {
+                                       ata_status = 0;
+                                       handled = 0;
+                               }
+                       }
                }
 
-               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);
@@ -1398,18 +1411,18 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
                        shift++;        /* skip bit 8 in the HC Main IRQ reg */
                }
                if ((PORT0_ERR << shift) & relevant) {
-                       mv_err_intr(ap);
+                       mv_err_intr(ap, 1);
                        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);
                                }
@@ -1440,6 +1453,7 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance,
        struct ata_host_set *host_set = dev_instance;
        unsigned int hc, handled = 0, n_hcs;
        void __iomem *mmio = host_set->mmio_base;
+       struct mv_host_priv *hpriv;
        u32 irq_stat;
 
        irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
@@ -1461,6 +1475,17 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance,
                        handled++;
                }
        }
+
+       hpriv = host_set->private_data;
+       if (IS_60XX(hpriv)) {
+               /* deal with the interrupt coalescing bits */
+               if (irq_stat & (TRAN_LO_DONE | TRAN_HI_DONE | PORTS_0_7_COAL_DONE)) {
+                       writelfl(0, mmio + MV_IRQ_COAL_CAUSE_LO);
+                       writelfl(0, mmio + MV_IRQ_COAL_CAUSE_HI);
+                       writelfl(0, mmio + MV_IRQ_COAL_CAUSE);
+               }
+       }
+
        if (PCI_ERR & irq_stat) {
                printk(KERN_ERR DRV_NAME ": PCI ERROR; PCI IRQ cause=0x%08x\n",
                       readl(mmio + PCI_IRQ_CAUSE_OFS));
@@ -1859,7 +1884,8 @@ static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
 
        if (IS_60XX(hpriv)) {
                u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
-               ifctl |= (1 << 12) | (1 << 7);
+               ifctl |= (1 << 7);              /* enable gen2i speed */
+               ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
                writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
        }
 
@@ -1926,15 +1952,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;
 
@@ -1951,11 +1978,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;
        }
@@ -1982,7 +2010,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);
        }
@@ -2012,8 +2040,9 @@ static void mv_phy_reset(struct ata_port *ap)
 static void mv_eng_timeout(struct ata_port *ap)
 {
        struct ata_queued_cmd *qc;
+       unsigned long flags;
 
-       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));
@@ -2023,13 +2052,13 @@ static void mv_eng_timeout(struct ata_port *ap)
               ap->host_set->mmio_base, ap, qc, qc->scsicmd,
               &qc->scsicmd->cmnd);
 
-       mv_err_intr(ap);
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       mv_err_intr(ap, 0);
        mv_stop_and_reset(ap);
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
 
-       if (!qc) {
-               printk(KERN_ERR "ata%u: BUG: timeout without command\n",
-                      ap->id);
-       } else {
+       WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
+       if (qc->flags & ATA_QCFLAG_ACTIVE) {
                qc->err_mask |= AC_ERR_TIMEOUT;
                ata_eh_qc_complete(qc);
        }
@@ -2226,7 +2255,8 @@ static int mv_init_host(struct pci_dev *pdev, struct ata_probe_ent *probe_ent,
                        void __iomem *port_mmio = mv_port_base(mmio, port);
 
                        u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
-                       ifctl |= (1 << 12);
+                       ifctl |= (1 << 7);              /* enable gen2i speed */
+                       ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
                        writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
                }
 
@@ -2327,6 +2357,7 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc) {
                return rc;
        }
+       pci_set_master(pdev);
 
        rc = pci_request_regions(pdev, DRV_NAME);
        if (rc) {