[libata] Remove ->irq_ack() hook, and ata_dummy_irq_on()
[safe/jmp/linux-2.6] / drivers / ata / sata_nv.c
index 783281e..88ecca6 100644 (file)
@@ -49,7 +49,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME                       "sata_nv"
-#define DRV_VERSION                    "3.3"
+#define DRV_VERSION                    "3.5"
 
 #define NV_ADMA_DMA_BOUNDARY           0xffffffffUL
 
@@ -229,14 +229,15 @@ struct nv_host_priv {
 #define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT)))))
 
 static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static void nv_remove_one (struct pci_dev *pdev);
+#ifdef CONFIG_PM
 static int nv_pci_device_resume(struct pci_dev *pdev);
+#endif
 static void nv_ck804_host_stop(struct ata_host *host);
 static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance);
 static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance);
 static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance);
-static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg);
-static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+static int nv_scr_read (struct ata_port *ap, unsigned int sc_reg, u32 *val);
+static int nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 
 static void nv_nf2_freeze(struct ata_port *ap);
 static void nv_nf2_thaw(struct ata_port *ap);
@@ -251,11 +252,16 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance);
 static void nv_adma_irq_clear(struct ata_port *ap);
 static int nv_adma_port_start(struct ata_port *ap);
 static void nv_adma_port_stop(struct ata_port *ap);
+#ifdef CONFIG_PM
 static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg);
 static int nv_adma_port_resume(struct ata_port *ap);
+#endif
+static void nv_adma_freeze(struct ata_port *ap);
+static void nv_adma_thaw(struct ata_port *ap);
 static void nv_adma_error_handler(struct ata_port *ap);
 static void nv_adma_host_stop(struct ata_host *host);
 static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc);
+static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
 
 enum nv_host_type
 {
@@ -281,12 +287,6 @@ static const struct pci_device_id nv_pci_tbl[] = {
        { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), GENERIC },
        { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), GENERIC },
        { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), GENERIC },
-       { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
-               PCI_ANY_ID, PCI_ANY_ID,
-               PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
-       { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
-               PCI_ANY_ID, PCI_ANY_ID,
-               PCI_CLASS_STORAGE_RAID<<8, 0xffff00, GENERIC },
 
        { } /* terminate list */
 };
@@ -295,9 +295,11 @@ static struct pci_driver nv_pci_driver = {
        .name                   = DRV_NAME,
        .id_table               = nv_pci_tbl,
        .probe                  = nv_init_one,
+#ifdef CONFIG_PM
        .suspend                = ata_pci_device_suspend,
        .resume                 = nv_pci_device_resume,
-       .remove                 = nv_remove_one,
+#endif
+       .remove                 = ata_pci_remove_one,
 };
 
 static struct scsi_host_template nv_sht = {
@@ -316,8 +318,6 @@ static struct scsi_host_template nv_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
-       .suspend                = ata_scsi_device_suspend,
-       .resume                 = ata_scsi_device_resume,
 };
 
 static struct scsi_host_template nv_adma_sht = {
@@ -325,6 +325,7 @@ static struct scsi_host_template nv_adma_sht = {
        .name                   = DRV_NAME,
        .ioctl                  = ata_scsi_ioctl,
        .queuecommand           = ata_scsi_queuecmd,
+       .change_queue_depth     = ata_scsi_change_queue_depth,
        .can_queue              = NV_ADMA_MAX_CPBS,
        .this_id                = ATA_SHT_THIS_ID,
        .sg_tablesize           = NV_ADMA_SGTBL_TOTAL_LEN,
@@ -336,8 +337,6 @@ static struct scsi_host_template nv_adma_sht = {
        .slave_configure        = nv_adma_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
-       .suspend                = ata_scsi_device_suspend,
-       .resume                 = ata_scsi_device_resume,
 };
 
 static const struct ata_port_operations nv_generic_ops = {
@@ -358,10 +357,8 @@ static const struct ata_port_operations nv_generic_ops = {
        .error_handler          = nv_error_handler,
        .post_internal_cmd      = ata_bmdma_post_internal_cmd,
        .data_xfer              = ata_data_xfer,
-       .irq_handler            = nv_generic_interrupt,
        .irq_clear              = ata_bmdma_irq_clear,
        .irq_on                 = ata_irq_on,
-       .irq_ack                = ata_irq_ack,
        .scr_read               = nv_scr_read,
        .scr_write              = nv_scr_write,
        .port_start             = ata_port_start,
@@ -385,10 +382,8 @@ static const struct ata_port_operations nv_nf2_ops = {
        .error_handler          = nv_error_handler,
        .post_internal_cmd      = ata_bmdma_post_internal_cmd,
        .data_xfer              = ata_data_xfer,
-       .irq_handler            = nv_nf2_interrupt,
        .irq_clear              = ata_bmdma_irq_clear,
        .irq_on                 = ata_irq_on,
-       .irq_ack                = ata_irq_ack,
        .scr_read               = nv_scr_read,
        .scr_write              = nv_scr_write,
        .port_start             = ata_port_start,
@@ -412,10 +407,8 @@ static const struct ata_port_operations nv_ck804_ops = {
        .error_handler          = nv_error_handler,
        .post_internal_cmd      = ata_bmdma_post_internal_cmd,
        .data_xfer              = ata_data_xfer,
-       .irq_handler            = nv_ck804_interrupt,
        .irq_clear              = ata_bmdma_irq_clear,
        .irq_on                 = ata_irq_on,
-       .irq_ack                = ata_irq_ack,
        .scr_read               = nv_scr_read,
        .scr_write              = nv_scr_write,
        .port_start             = ata_port_start,
@@ -425,7 +418,7 @@ static const struct ata_port_operations nv_ck804_ops = {
 static const struct ata_port_operations nv_adma_ops = {
        .port_disable           = ata_port_disable,
        .tf_load                = ata_tf_load,
-       .tf_read                = ata_tf_read,
+       .tf_read                = nv_adma_tf_read,
        .check_atapi_dma        = nv_adma_check_atapi_dma,
        .exec_command           = ata_exec_command,
        .check_status           = ata_check_status,
@@ -436,65 +429,69 @@ static const struct ata_port_operations nv_adma_ops = {
        .bmdma_status           = ata_bmdma_status,
        .qc_prep                = nv_adma_qc_prep,
        .qc_issue               = nv_adma_qc_issue,
-       .freeze                 = nv_ck804_freeze,
-       .thaw                   = nv_ck804_thaw,
+       .freeze                 = nv_adma_freeze,
+       .thaw                   = nv_adma_thaw,
        .error_handler          = nv_adma_error_handler,
        .post_internal_cmd      = nv_adma_post_internal_cmd,
        .data_xfer              = ata_data_xfer,
-       .irq_handler            = nv_adma_interrupt,
        .irq_clear              = nv_adma_irq_clear,
        .irq_on                 = ata_irq_on,
-       .irq_ack                = ata_irq_ack,
        .scr_read               = nv_scr_read,
        .scr_write              = nv_scr_write,
        .port_start             = nv_adma_port_start,
        .port_stop              = nv_adma_port_stop,
+#ifdef CONFIG_PM
        .port_suspend           = nv_adma_port_suspend,
        .port_resume            = nv_adma_port_resume,
+#endif
        .host_stop              = nv_adma_host_stop,
 };
 
-static struct ata_port_info nv_port_info[] = {
+static const struct ata_port_info nv_port_info[] = {
        /* generic */
        {
                .sht            = &nv_sht,
-               .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_HRST_TO_RESUME,
+               .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+               .link_flags     = ATA_LFLAG_HRST_TO_RESUME,
                .pio_mask       = NV_PIO_MASK,
                .mwdma_mask     = NV_MWDMA_MASK,
                .udma_mask      = NV_UDMA_MASK,
                .port_ops       = &nv_generic_ops,
+               .irq_handler    = nv_generic_interrupt,
        },
        /* nforce2/3 */
        {
                .sht            = &nv_sht,
-               .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_HRST_TO_RESUME,
+               .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+               .link_flags     = ATA_LFLAG_HRST_TO_RESUME,
                .pio_mask       = NV_PIO_MASK,
                .mwdma_mask     = NV_MWDMA_MASK,
                .udma_mask      = NV_UDMA_MASK,
                .port_ops       = &nv_nf2_ops,
+               .irq_handler    = nv_nf2_interrupt,
        },
        /* ck804 */
        {
                .sht            = &nv_sht,
-               .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_HRST_TO_RESUME,
+               .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+               .link_flags     = ATA_LFLAG_HRST_TO_RESUME,
                .pio_mask       = NV_PIO_MASK,
                .mwdma_mask     = NV_MWDMA_MASK,
                .udma_mask      = NV_UDMA_MASK,
                .port_ops       = &nv_ck804_ops,
+               .irq_handler    = nv_ck804_interrupt,
        },
        /* ADMA */
        {
                .sht            = &nv_adma_sht,
                .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_HRST_TO_RESUME |
                                  ATA_FLAG_MMIO | ATA_FLAG_NCQ,
+               .link_flags     = ATA_LFLAG_HRST_TO_RESUME,
                .pio_mask       = NV_PIO_MASK,
                .mwdma_mask     = NV_MWDMA_MASK,
                .udma_mask      = NV_UDMA_MASK,
                .port_ops       = &nv_adma_ops,
+               .irq_handler    = nv_adma_interrupt,
        },
 };
 
@@ -593,7 +590,7 @@ static int nv_adma_slave_config(struct scsi_device *sdev)
                /* Not a proper libata device, ignore */
                return rc;
 
-       if (ap->device[sdev->id].class == ATA_DEV_ATAPI) {
+       if (ap->link.device[sdev->id].class == ATA_DEV_ATAPI) {
                /*
                 * NVIDIA reports that ADMA mode does not support ATAPI commands.
                 * Therefore ATAPI commands are sent through the legacy interface.
@@ -655,6 +652,18 @@ static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc)
        return !(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE);
 }
 
+static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+       /* Since commands where a result TF is requested are not
+          executed in ADMA mode, the only time this function will be called
+          in ADMA mode will be if a command fails. In this case we
+          don't care about going into register mode with ADMA commands
+          pending, as the commands will all shortly be aborted anyway. */
+       nv_adma_register_mode(ap);
+
+       ata_tf_read(ap, tf);
+}
+
 static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb)
 {
        unsigned int idx = 0;
@@ -669,18 +678,18 @@ static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb)
                        cpb[idx++] = cpu_to_le16((ATA_REG_ERR    << 8) | tf->feature);
                } else
                        cpb[idx++] = cpu_to_le16((ATA_REG_ERR    << 8) | tf->feature | WNB);
-                       
+
                cpb[idx++] = cpu_to_le16((ATA_REG_NSECT  << 8) | tf->nsect);
                cpb[idx++] = cpu_to_le16((ATA_REG_LBAL   << 8) | tf->lbal);
                cpb[idx++] = cpu_to_le16((ATA_REG_LBAM   << 8) | tf->lbam);
                cpb[idx++] = cpu_to_le16((ATA_REG_LBAH   << 8) | tf->lbah);
        }
-       
+
        if(tf->flags & ATA_TFLAG_DEVICE)
                cpb[idx++] = cpu_to_le16((ATA_REG_DEVICE << 8) | tf->device);
 
        cpb[idx++] = cpu_to_le16((ATA_REG_CMD    << 8) | tf->command | CMDEND);
-       
+
        while(idx < 12)
                cpb[idx++] = cpu_to_le16(IGN);
 
@@ -698,23 +707,24 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
                     flags & (NV_CPB_RESP_ATA_ERR |
                              NV_CPB_RESP_CMD_ERR |
                              NV_CPB_RESP_CPB_ERR)))) {
-               struct ata_eh_info *ehi = &ap->eh_info;
+               struct ata_eh_info *ehi = &ap->link.eh_info;
                int freeze = 0;
 
                ata_ehi_clear_desc(ehi);
-               ata_ehi_push_desc(ehi, "CPB resp_flags 0x%x", flags );
+               __ata_ehi_push_desc(ehi, "CPB resp_flags 0x%x: ", flags );
                if (flags & NV_CPB_RESP_ATA_ERR) {
-                       ata_ehi_push_desc(ehi, "ATA error");
+                       ata_ehi_push_desc(ehi, "ATA error");
                        ehi->err_mask |= AC_ERR_DEV;
                } else if (flags & NV_CPB_RESP_CMD_ERR) {
-                       ata_ehi_push_desc(ehi, "CMD error");
+                       ata_ehi_push_desc(ehi, "CMD error");
                        ehi->err_mask |= AC_ERR_DEV;
                } else if (flags & NV_CPB_RESP_CPB_ERR) {
-                       ata_ehi_push_desc(ehi, "CPB error");
+                       ata_ehi_push_desc(ehi, "CPB error");
                        ehi->err_mask |= AC_ERR_SYSTEM;
                        freeze = 1;
                } else {
                        /* notifier error, but no error in CPB flags? */
+                       ata_ehi_push_desc(ehi, "unknown");
                        ehi->err_mask |= AC_ERR_OTHER;
                        freeze = 1;
                }
@@ -726,22 +736,14 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
                return 1;
        }
 
-       if (flags & NV_CPB_RESP_DONE) {
+       if (likely(flags & NV_CPB_RESP_DONE)) {
                struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num);
                VPRINTK("CPB flags done, flags=0x%x\n", flags);
                if (likely(qc)) {
-                       /* Grab the ATA port status for non-NCQ commands.
-                          For NCQ commands the current status may have nothing to do with
-                          the command just completed. */
-                       if (qc->tf.protocol != ATA_PROT_NCQ) {
-                               u8 ata_status = readb(pp->ctl_block + (ATA_REG_STATUS * 4));
-                               qc->err_mask |= ac_err_mask(ata_status);
-                       }
-                       DPRINTK("Completing qc from tag %d with err_mask %u\n",cpb_num,
-                               qc->err_mask);
+                       DPRINTK("Completing qc from tag %d\n",cpb_num);
                        ata_qc_complete(qc);
                } else {
-                       struct ata_eh_info *ehi = &ap->eh_info;
+                       struct ata_eh_info *ehi = &ap->link.eh_info;
                        /* Notifier bits set without a command may indicate the drive
                           is misbehaving. Raise host state machine violation on this
                           condition. */
@@ -758,7 +760,7 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
 
 static int nv_host_intr(struct ata_port *ap, u8 irq_stat)
 {
-       struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+       struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->link.active_tag);
 
        /* freeze if hotplugged */
        if (unlikely(irq_stat & (NV_INT_ADDED | NV_INT_REMOVED))) {
@@ -799,17 +801,24 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
                        u32 gen_ctl;
                        u32 notifier, notifier_error;
 
-                       /* if in ATA register mode, use standard ata interrupt handler */
+                       /* if ADMA is disabled, use standard ata interrupt handler */
+                       if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) {
+                               u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804)
+                                       >> (NV_INT_PORT_SHIFT * i);
+                               handled += nv_host_intr(ap, irq_stat);
+                               continue;
+                       }
+
+                       /* if in ATA register mode, check for standard interrupts */
                        if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) {
                                u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804)
                                        >> (NV_INT_PORT_SHIFT * i);
-                               if(ata_tag_valid(ap->active_tag))
+                               if(ata_tag_valid(ap->link.active_tag))
                                        /** NV_INT_DEV indication seems unreliable at times
                                            at least in ADMA mode. Force it on always when a
                                            command is active, to prevent losing interrupts. */
                                        irq_stat |= NV_INT_DEV;
                                handled += nv_host_intr(ap, irq_stat);
-                               continue;
                        }
 
                        notifier = readl(mmio + NV_ADMA_NOTIFIER);
@@ -839,31 +848,38 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
                                               NV_ADMA_STAT_HOTUNPLUG |
                                               NV_ADMA_STAT_TIMEOUT |
                                               NV_ADMA_STAT_SERROR))) {
-                               struct ata_eh_info *ehi = &ap->eh_info;
+                               struct ata_eh_info *ehi = &ap->link.eh_info;
 
                                ata_ehi_clear_desc(ehi);
-                               ata_ehi_push_desc(ehi, "ADMA status 0x%08x", status );
+                               __ata_ehi_push_desc(ehi, "ADMA status 0x%08x: ", status );
                                if (status & NV_ADMA_STAT_TIMEOUT) {
                                        ehi->err_mask |= AC_ERR_SYSTEM;
-                                       ata_ehi_push_desc(ehi, "timeout");
+                                       ata_ehi_push_desc(ehi, "timeout");
                                } else if (status & NV_ADMA_STAT_HOTPLUG) {
                                        ata_ehi_hotplugged(ehi);
-                                       ata_ehi_push_desc(ehi, "hotplug");
+                                       ata_ehi_push_desc(ehi, "hotplug");
                                } else if (status & NV_ADMA_STAT_HOTUNPLUG) {
                                        ata_ehi_hotplugged(ehi);
-                                       ata_ehi_push_desc(ehi, "hot unplug");
+                                       ata_ehi_push_desc(ehi, "hot unplug");
                                } else if (status & NV_ADMA_STAT_SERROR) {
                                        /* let libata analyze SError and figure out the cause */
-                                       ata_ehi_push_desc(ehi, ": SError");
-                               }
+                                       ata_ehi_push_desc(ehi, "SError");
+                               } else
+                                       ata_ehi_push_desc(ehi, "unknown");
                                ata_port_freeze(ap);
                                continue;
                        }
 
                        if (status & (NV_ADMA_STAT_DONE |
                                      NV_ADMA_STAT_CPBERR)) {
-                               u32 check_commands = notifier | notifier_error;
+                               u32 check_commands;
                                int pos, error = 0;
+
+                               if(ata_tag_valid(ap->link.active_tag))
+                                       check_commands = 1 << ap->link.active_tag;
+                               else
+                                       check_commands = ap->link.sactive;
+
                                /** Check CPBs for completed commands */
                                while ((pos = ffs(check_commands)) && !error) {
                                        pos--;
@@ -889,22 +905,77 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
        return IRQ_RETVAL(handled);
 }
 
+static void nv_adma_freeze(struct ata_port *ap)
+{
+       struct nv_adma_port_priv *pp = ap->private_data;
+       void __iomem *mmio = pp->ctl_block;
+       u16 tmp;
+
+       nv_ck804_freeze(ap);
+
+       if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
+               return;
+
+       /* clear any outstanding CK804 notifications */
+       writeb( NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT),
+               ap->host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804);
+
+       /* Disable interrupt */
+       tmp = readw(mmio + NV_ADMA_CTL);
+       writew( tmp & ~(NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN),
+               mmio + NV_ADMA_CTL);
+       readw( mmio + NV_ADMA_CTL );    /* flush posted write */
+}
+
+static void nv_adma_thaw(struct ata_port *ap)
+{
+       struct nv_adma_port_priv *pp = ap->private_data;
+       void __iomem *mmio = pp->ctl_block;
+       u16 tmp;
+
+       nv_ck804_thaw(ap);
+
+       if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
+               return;
+
+       /* Enable interrupt */
+       tmp = readw(mmio + NV_ADMA_CTL);
+       writew( tmp | (NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN),
+               mmio + NV_ADMA_CTL);
+       readw( mmio + NV_ADMA_CTL );    /* flush posted write */
+}
+
 static void nv_adma_irq_clear(struct ata_port *ap)
 {
        struct nv_adma_port_priv *pp = ap->private_data;
        void __iomem *mmio = pp->ctl_block;
-       u16 status = readw(mmio + NV_ADMA_STAT);
-       u32 notifier = readl(mmio + NV_ADMA_NOTIFIER);
-       u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR);
-       void __iomem *dma_stat_addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
+       u32 notifier_clears[2];
+
+       if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) {
+               ata_bmdma_irq_clear(ap);
+               return;
+       }
+
+       /* clear any outstanding CK804 notifications */
+       writeb( NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT),
+               ap->host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804);
 
        /* clear ADMA status */
-       writew(status, mmio + NV_ADMA_STAT);
-       writel(notifier | notifier_error,
-              pp->notifier_clear_block);
+       writew(0xffff, mmio + NV_ADMA_STAT);
 
-       /** clear legacy status */
-       iowrite8(ioread8(dma_stat_addr), dma_stat_addr);
+       /* clear notifiers - note both ports need to be written with
+          something even though we are only clearing on one */
+       if (ap->port_no == 0) {
+               notifier_clears[0] = 0xFFFFFFFF;
+               notifier_clears[1] = 0;
+       } else {
+               notifier_clears[0] = 0;
+               notifier_clears[1] = 0xFFFFFFFF;
+       }
+       pp = ap->host->ports[0]->private_data;
+       writel(notifier_clears[0], pp->notifier_clear_block);
+       pp = ap->host->ports[1]->private_data;
+       writel(notifier_clears[1], pp->notifier_clear_block);
 }
 
 static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc)
@@ -1003,6 +1074,7 @@ static void nv_adma_port_stop(struct ata_port *ap)
        writew(0, mmio + NV_ADMA_CTL);
 }
 
+#ifdef CONFIG_PM
 static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg)
 {
        struct nv_adma_port_priv *pp = ap->private_data;
@@ -1053,15 +1125,16 @@ static int nv_adma_port_resume(struct ata_port *ap)
 
        return 0;
 }
+#endif
 
-static void nv_adma_setup_port(struct ata_probe_ent *probe_ent, unsigned int port)
+static void nv_adma_setup_port(struct ata_port *ap)
 {
-       void __iomem *mmio = probe_ent->iomap[NV_MMIO_BAR];
-       struct ata_ioports *ioport = &probe_ent->port[port];
+       void __iomem *mmio = ap->host->iomap[NV_MMIO_BAR];
+       struct ata_ioports *ioport = &ap->ioaddr;
 
        VPRINTK("ENTER\n");
 
-       mmio += NV_ADMA_PORT + port * NV_ADMA_PORT_SIZE;
+       mmio += NV_ADMA_PORT + ap->port_no * NV_ADMA_PORT_SIZE;
 
        ioport->cmd_addr        = mmio;
        ioport->data_addr       = mmio + (ATA_REG_DATA * 4);
@@ -1078,9 +1151,9 @@ static void nv_adma_setup_port(struct ata_probe_ent *probe_ent, unsigned int por
        ioport->ctl_addr        = mmio + 0x20;
 }
 
-static int nv_adma_host_init(struct ata_probe_ent *probe_ent)
+static int nv_adma_host_init(struct ata_host *host)
 {
-       struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
+       struct pci_dev *pdev = to_pci_dev(host->dev);
        unsigned int i;
        u32 tmp32;
 
@@ -1095,8 +1168,8 @@ static int nv_adma_host_init(struct ata_probe_ent *probe_ent)
 
        pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32);
 
-       for (i = 0; i < probe_ent->n_ports; i++)
-               nv_adma_setup_port(probe_ent, i);
+       for (i = 0; i < host->n_ports; i++)
+               nv_adma_setup_port(host->ports[i]);
 
        return 0;
 }
@@ -1147,9 +1220,11 @@ static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc)
        struct nv_adma_port_priv *pp = qc->ap->private_data;
 
        /* ADMA engine can only be used for non-ATAPI DMA commands,
-          or interrupt-driven no-data commands. */
+          or interrupt-driven no-data commands, where a result taskfile
+          is not required. */
        if((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) ||
-          (qc->tf.flags & ATA_TFLAG_POLLING))
+          (qc->tf.flags & ATA_TFLAG_POLLING) ||
+          (qc->flags & ATA_QCFLAG_RESULT_TF))
                return 1;
 
        if((qc->flags & ATA_QCFLAG_DMAMAP) ||
@@ -1254,7 +1329,7 @@ static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance)
                    !(ap->flags & ATA_FLAG_DISABLED)) {
                        struct ata_queued_cmd *qc;
 
-                       qc = ata_qc_from_tag(ap, ap->active_tag);
+                       qc = ata_qc_from_tag(ap, ap->link.active_tag);
                        if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
                                handled += ata_host_intr(ap, qc);
                        else
@@ -1314,20 +1389,22 @@ static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance)
        return ret;
 }
 
-static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg)
+static int nv_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
 {
        if (sc_reg > SCR_CONTROL)
-               return 0xffffffffU;
+               return -EINVAL;
 
-       return ioread32(ap->ioaddr.scr_addr + (sc_reg * 4));
+       *val = ioread32(ap->ioaddr.scr_addr + (sc_reg * 4));
+       return 0;
 }
 
-static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
+static int nv_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
 {
        if (sc_reg > SCR_CONTROL)
-               return;
+               return -EINVAL;
 
        iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4));
+       return 0;
 }
 
 static void nv_nf2_freeze(struct ata_port *ap)
@@ -1378,7 +1455,8 @@ static void nv_ck804_thaw(struct ata_port *ap)
        writeb(mask, mmio_base + NV_INT_ENABLE_CK804);
 }
 
-static int nv_hardreset(struct ata_port *ap, unsigned int *class)
+static int nv_hardreset(struct ata_link *link, unsigned int *class,
+                       unsigned long deadline)
 {
        unsigned int dummy;
 
@@ -1386,7 +1464,7 @@ static int nv_hardreset(struct ata_port *ap, unsigned int *class)
         * some controllers.  Don't classify on hardreset.  For more
         * info, see http://bugme.osdl.org/show_bug.cgi?id=3352
         */
-       return sata_std_hardreset(ap, &dummy);
+       return sata_std_hardreset(link, &dummy, deadline);
 }
 
 static void nv_error_handler(struct ata_port *ap)
@@ -1402,8 +1480,8 @@ static void nv_adma_error_handler(struct ata_port *ap)
                void __iomem *mmio = pp->ctl_block;
                int i;
                u16 tmp;
-               
-               if(ata_tag_valid(ap->active_tag) || ap->sactive) {
+
+               if(ata_tag_valid(ap->link.active_tag) || ap->link.sactive) {
                        u32 notifier = readl(mmio + NV_ADMA_NOTIFIER);
                        u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR);
                        u32 gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL);
@@ -1419,8 +1497,8 @@ static void nv_adma_error_handler(struct ata_port *ap)
 
                        for( i=0;i<NV_ADMA_MAX_CPBS;i++) {
                                struct nv_adma_cpb *cpb = &pp->cpb[i];
-                               if( (ata_tag_valid(ap->active_tag) && i == ap->active_tag) ||
-                                   ap->sactive & (1 << i) )
+                               if( (ata_tag_valid(ap->link.active_tag) && i == ap->link.active_tag) ||
+                                   ap->link.sactive & (1 << i) )
                                        ata_port_printk(ap, KERN_ERR,
                                                "CPB %d: ctl_flags 0x%x, resp_flags 0x%x\n",
                                                i, cpb->ctl_flags, cpb->resp_flags);
@@ -1453,14 +1531,13 @@ static void nv_adma_error_handler(struct ata_port *ap)
 static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        static int printed_version = 0;
-       struct ata_port_info *ppi[2];
-       struct ata_probe_ent *probe_ent;
+       const struct ata_port_info *ppi[] = { NULL, NULL };
+       struct ata_host *host;
        struct nv_host_priv *hpriv;
        int rc;
        u32 bar;
        void __iomem *base;
        unsigned long type = ent->driver_data;
-       int mask_set = 0;
 
         // Make sure this is a SATA controller by counting the number of bars
         // (NVIDIA SATA controllers will always have six bars).  Otherwise,
@@ -1476,50 +1553,38 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc)
                return rc;
 
-       rc = pci_request_regions(pdev, DRV_NAME);
-       if (rc) {
-               pcim_pin_device(pdev);
-               return rc;
-       }
-
-       if(type >= CK804 && adma_enabled) {
+       /* determine type and allocate host */
+       if (type >= CK804 && adma_enabled) {
                dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n");
                type = ADMA;
-               if(!pci_set_dma_mask(pdev, DMA_64BIT_MASK) &&
-                  !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
-                       mask_set = 1;
-       }
-
-       if(!mask_set) {
-               rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
-               if (rc)
-                       return rc;
-               rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
-               if (rc)
-                       return rc;
        }
 
-       rc = -ENOMEM;
+       ppi[0] = &nv_port_info[type];
+       rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
+       if (rc)
+               return rc;
 
        hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
        if (!hpriv)
                return -ENOMEM;
+       hpriv->type = type;
+       host->private_data = hpriv;
 
-       ppi[0] = ppi[1] = &nv_port_info[type];
-       probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
-       if (!probe_ent)
-               return -ENOMEM;
-
-       if (!pcim_iomap(pdev, NV_MMIO_BAR, 0))
-               return -EIO;
-       probe_ent->iomap = pcim_iomap_table(pdev);
+       /* set 64bit dma masks, may fail */
+       if (type == ADMA) {
+               if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0)
+                       pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+       }
 
-       probe_ent->private_data = hpriv;
-       hpriv->type = type;
+       /* request and iomap NV_MMIO_BAR */
+       rc = pcim_iomap_regions(pdev, 1 << NV_MMIO_BAR, DRV_NAME);
+       if (rc)
+               return rc;
 
-       base = probe_ent->iomap[NV_MMIO_BAR];
-       probe_ent->port[0].scr_addr = base + NV_PORT0_SCR_REG_OFFSET;
-       probe_ent->port[1].scr_addr = base + NV_PORT1_SCR_REG_OFFSET;
+       /* configure SCR access */
+       base = host->iomap[NV_MMIO_BAR];
+       host->ports[0]->ioaddr.scr_addr = base + NV_PORT0_SCR_REG_OFFSET;
+       host->ports[1]->ioaddr.scr_addr = base + NV_PORT1_SCR_REG_OFFSET;
 
        /* enable SATA space for CK804 */
        if (type >= CK804) {
@@ -1530,31 +1595,19 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
        }
 
-       pci_set_master(pdev);
-
+       /* init ADMA */
        if (type == ADMA) {
-               rc = nv_adma_host_init(probe_ent);
+               rc = nv_adma_host_init(host);
                if (rc)
                        return rc;
        }
 
-       rc = ata_device_add(probe_ent);
-       if (rc != NV_PORTS)
-               return -ENODEV;
-
-       devm_kfree(&pdev->dev, probe_ent);
-       return 0;
-}
-
-static void nv_remove_one (struct pci_dev *pdev)
-{
-       struct ata_host *host = dev_get_drvdata(&pdev->dev);
-       struct nv_host_priv *hpriv = host->private_data;
-
-       ata_pci_remove_one(pdev);
-       kfree(hpriv);
+       pci_set_master(pdev);
+       return ata_host_activate(host, pdev->irq, ppi[0]->irq_handler,
+                                IRQF_SHARED, ppi[0]->sht);
 }
 
+#ifdef CONFIG_PM
 static int nv_pci_device_resume(struct pci_dev *pdev)
 {
        struct ata_host *host = dev_get_drvdata(&pdev->dev);
@@ -1602,6 +1655,7 @@ static int nv_pci_device_resume(struct pci_dev *pdev)
 
        return 0;
 }
+#endif
 
 static void nv_ck804_host_stop(struct ata_host *host)
 {