libata: fix reporting of drained bytes when clearing DRQ
[safe/jmp/linux-2.6] / drivers / ata / sata_nv.c
index 2e0279f..0c82d33 100644 (file)
@@ -57,9 +57,9 @@ enum {
        NV_MMIO_BAR                     = 5,
 
        NV_PORTS                        = 2,
-       NV_PIO_MASK                     = 0x1f,
-       NV_MWDMA_MASK                   = 0x07,
-       NV_UDMA_MASK                    = 0x7f,
+       NV_PIO_MASK                     = ATA_PIO4,
+       NV_MWDMA_MASK                   = ATA_MWDMA2,
+       NV_UDMA_MASK                    = ATA_UDMA6,
        NV_PORT0_SCR_REG_OFFSET         = 0x00,
        NV_PORT1_SCR_REG_OFFSET         = 0x40,
 
@@ -247,6 +247,7 @@ struct nv_adma_port_priv {
        void __iomem            *ctl_block;
        void __iomem            *gen_block;
        void __iomem            *notifier_clear_block;
+       u64                     adma_dma_mask;
        u8                      flags;
        int                     last_issue_ncq;
 };
@@ -291,7 +292,7 @@ struct nv_swncq_port_priv {
 };
 
 
-#define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT)))))
+#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);
 #ifdef CONFIG_PM
@@ -301,14 +302,15 @@ 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 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 int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
+static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
 
+static int nv_hardreset(struct ata_link *link, unsigned int *class,
+                       unsigned long deadline);
 static void nv_nf2_freeze(struct ata_port *ap);
 static void nv_nf2_thaw(struct ata_port *ap);
 static void nv_ck804_freeze(struct ata_port *ap);
 static void nv_ck804_thaw(struct ata_port *ap);
-static void nv_error_handler(struct ata_port *ap);
 static int nv_adma_slave_config(struct scsi_device *sdev);
 static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc);
 static void nv_adma_qc_prep(struct ata_queued_cmd *qc);
@@ -350,6 +352,7 @@ enum nv_host_type
        NFORCE3 = NFORCE2,      /* NF2 == NF3 as far as sata_nv is concerned */
        CK804,
        ADMA,
+       MCP5x,
        SWNCQ,
 };
 
@@ -361,13 +364,13 @@ static const struct pci_device_id nv_pci_tbl[] = {
        { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2), CK804 },
        { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA), CK804 },
        { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2), CK804 },
-       { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA), SWNCQ },
-       { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), SWNCQ },
-       { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), SWNCQ },
-       { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), SWNCQ },
-       { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), SWNCQ },
-       { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), SWNCQ },
-       { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), SWNCQ },
+       { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA), MCP5x },
+       { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), MCP5x },
+       { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), MCP5x },
+       { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), MCP5x },
+       { 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 },
 
        { } /* terminate list */
 };
@@ -384,157 +387,119 @@ static struct pci_driver nv_pci_driver = {
 };
 
 static struct scsi_host_template nv_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = ATA_DEF_QUEUE,
-       .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = LIBATA_MAX_PRD,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = ATA_SHT_USE_CLUSTERING,
-       .proc_name              = DRV_NAME,
-       .dma_boundary           = ATA_DMA_BOUNDARY,
-       .slave_configure        = ata_scsi_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
+       ATA_BMDMA_SHT(DRV_NAME),
 };
 
 static struct scsi_host_template nv_adma_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .change_queue_depth     = ata_scsi_change_queue_depth,
+       ATA_NCQ_SHT(DRV_NAME),
        .can_queue              = NV_ADMA_MAX_CPBS,
-       .this_id                = ATA_SHT_THIS_ID,
        .sg_tablesize           = NV_ADMA_SGTBL_TOTAL_LEN,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = ATA_SHT_USE_CLUSTERING,
-       .proc_name              = DRV_NAME,
        .dma_boundary           = NV_ADMA_DMA_BOUNDARY,
        .slave_configure        = nv_adma_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
 };
 
 static struct scsi_host_template nv_swncq_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .change_queue_depth     = ata_scsi_change_queue_depth,
+       ATA_NCQ_SHT(DRV_NAME),
        .can_queue              = ATA_MAX_QUEUE,
-       .this_id                = ATA_SHT_THIS_ID,
        .sg_tablesize           = LIBATA_MAX_PRD,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = ATA_SHT_USE_CLUSTERING,
-       .proc_name              = DRV_NAME,
        .dma_boundary           = ATA_DMA_BOUNDARY,
        .slave_configure        = nv_swncq_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
 };
 
-static const struct ata_port_operations nv_generic_ops = {
-       .tf_load                = ata_tf_load,
-       .tf_read                = ata_tf_read,
-       .exec_command           = ata_exec_command,
-       .check_status           = ata_check_status,
-       .dev_select             = ata_std_dev_select,
-       .bmdma_setup            = ata_bmdma_setup,
-       .bmdma_start            = ata_bmdma_start,
-       .bmdma_stop             = ata_bmdma_stop,
-       .bmdma_status           = ata_bmdma_status,
-       .qc_prep                = ata_qc_prep,
-       .qc_issue               = ata_qc_issue_prot,
-       .freeze                 = ata_bmdma_freeze,
-       .thaw                   = ata_bmdma_thaw,
-       .error_handler          = nv_error_handler,
-       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
-       .data_xfer              = ata_data_xfer,
-       .irq_clear              = ata_bmdma_irq_clear,
-       .irq_on                 = ata_irq_on,
+/*
+ * NV SATA controllers have various different problems with hardreset
+ * protocol depending on the specific controller and device.
+ *
+ * GENERIC:
+ *
+ *  bko11195 reports that link doesn't come online after hardreset on
+ *  generic nv's and there have been several other similar reports on
+ *  linux-ide.
+ *
+ *  bko12351#c23 reports that warmplug on MCP61 doesn't work with
+ *  softreset.
+ *
+ * NF2/3:
+ *
+ *  bko3352 reports nf2/3 controllers can't determine device signature
+ *  reliably after hardreset.  The following thread reports detection
+ *  failure on cold boot with the standard debouncing timing.
+ *
+ *  http://thread.gmane.org/gmane.linux.ide/34098
+ *
+ *  bko12176 reports that hardreset fails to bring up the link during
+ *  boot on nf2.
+ *
+ * CK804:
+ *
+ *  For initial probing after boot and hot plugging, hardreset mostly
+ *  works fine on CK804 but curiously, reprobing on the initial port
+ *  by rescanning or rmmod/insmod fails to acquire the initial D2H Reg
+ *  FIS in somewhat undeterministic way.
+ *
+ * SWNCQ:
+ *
+ *  bko12351 reports that when SWNCQ is enabled, for hotplug to work,
+ *  hardreset should be used and hardreset can't report proper
+ *  signature, which suggests that mcp5x is closer to nf2 as long as
+ *  reset quirkiness is concerned.
+ *
+ *  bko12703 reports that boot probing fails for intel SSD with
+ *  hardreset.  Link fails to come online.  Softreset works fine.
+ *
+ * The failures are varied but the following patterns seem true for
+ * all flavors.
+ *
+ * - Softreset during boot always works.
+ *
+ * - Hardreset during boot sometimes fails to bring up the link on
+ *   certain comibnations and device signature acquisition is
+ *   unreliable.
+ *
+ * - Hardreset is often necessary after hotplug.
+ *
+ * So, preferring softreset for boot probing and error handling (as
+ * hardreset might bring down the link) but using hardreset for
+ * post-boot probing should work around the above issues in most
+ * cases.  Define nv_hardreset() which only kicks in for post-boot
+ * probing and use it for all variants.
+ */
+static struct ata_port_operations nv_generic_ops = {
+       .inherits               = &ata_bmdma_port_ops,
+       .lost_interrupt         = ATA_OP_NULL,
        .scr_read               = nv_scr_read,
        .scr_write              = nv_scr_write,
-       .port_start             = ata_port_start,
+       .hardreset              = nv_hardreset,
 };
 
-static const struct ata_port_operations nv_nf2_ops = {
-       .tf_load                = ata_tf_load,
-       .tf_read                = ata_tf_read,
-       .exec_command           = ata_exec_command,
-       .check_status           = ata_check_status,
-       .dev_select             = ata_std_dev_select,
-       .bmdma_setup            = ata_bmdma_setup,
-       .bmdma_start            = ata_bmdma_start,
-       .bmdma_stop             = ata_bmdma_stop,
-       .bmdma_status           = ata_bmdma_status,
-       .qc_prep                = ata_qc_prep,
-       .qc_issue               = ata_qc_issue_prot,
+static struct ata_port_operations nv_nf2_ops = {
+       .inherits               = &nv_generic_ops,
        .freeze                 = nv_nf2_freeze,
        .thaw                   = nv_nf2_thaw,
-       .error_handler          = nv_error_handler,
-       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
-       .data_xfer              = ata_data_xfer,
-       .irq_clear              = ata_bmdma_irq_clear,
-       .irq_on                 = ata_irq_on,
-       .scr_read               = nv_scr_read,
-       .scr_write              = nv_scr_write,
-       .port_start             = ata_port_start,
 };
 
-static const struct ata_port_operations nv_ck804_ops = {
-       .tf_load                = ata_tf_load,
-       .tf_read                = ata_tf_read,
-       .exec_command           = ata_exec_command,
-       .check_status           = ata_check_status,
-       .dev_select             = ata_std_dev_select,
-       .bmdma_setup            = ata_bmdma_setup,
-       .bmdma_start            = ata_bmdma_start,
-       .bmdma_stop             = ata_bmdma_stop,
-       .bmdma_status           = ata_bmdma_status,
-       .qc_prep                = ata_qc_prep,
-       .qc_issue               = ata_qc_issue_prot,
+static struct ata_port_operations nv_ck804_ops = {
+       .inherits               = &nv_generic_ops,
        .freeze                 = nv_ck804_freeze,
        .thaw                   = nv_ck804_thaw,
-       .error_handler          = nv_error_handler,
-       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
-       .data_xfer              = ata_data_xfer,
-       .irq_clear              = ata_bmdma_irq_clear,
-       .irq_on                 = ata_irq_on,
-       .scr_read               = nv_scr_read,
-       .scr_write              = nv_scr_write,
-       .port_start             = ata_port_start,
        .host_stop              = nv_ck804_host_stop,
 };
 
-static const struct ata_port_operations nv_adma_ops = {
-       .tf_load                = ata_tf_load,
-       .tf_read                = nv_adma_tf_read,
+static struct ata_port_operations nv_adma_ops = {
+       .inherits               = &nv_ck804_ops,
+
        .check_atapi_dma        = nv_adma_check_atapi_dma,
-       .exec_command           = ata_exec_command,
-       .check_status           = ata_check_status,
-       .dev_select             = ata_std_dev_select,
-       .bmdma_setup            = ata_bmdma_setup,
-       .bmdma_start            = ata_bmdma_start,
-       .bmdma_stop             = ata_bmdma_stop,
-       .bmdma_status           = ata_bmdma_status,
+       .sff_tf_read            = nv_adma_tf_read,
        .qc_defer               = ata_std_qc_defer,
        .qc_prep                = nv_adma_qc_prep,
        .qc_issue               = nv_adma_qc_issue,
+       .sff_irq_clear          = nv_adma_irq_clear,
+
        .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_clear              = nv_adma_irq_clear,
-       .irq_on                 = ata_irq_on,
-       .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
@@ -544,28 +509,17 @@ static const struct ata_port_operations nv_adma_ops = {
        .host_stop              = nv_adma_host_stop,
 };
 
-static const struct ata_port_operations nv_swncq_ops = {
-       .tf_load                = ata_tf_load,
-       .tf_read                = ata_tf_read,
-       .exec_command           = ata_exec_command,
-       .check_status           = ata_check_status,
-       .dev_select             = ata_std_dev_select,
-       .bmdma_setup            = ata_bmdma_setup,
-       .bmdma_start            = ata_bmdma_start,
-       .bmdma_stop             = ata_bmdma_stop,
-       .bmdma_status           = ata_bmdma_status,
+static struct ata_port_operations nv_swncq_ops = {
+       .inherits               = &nv_generic_ops,
+
        .qc_defer               = ata_std_qc_defer,
        .qc_prep                = nv_swncq_qc_prep,
        .qc_issue               = nv_swncq_qc_issue,
+
        .freeze                 = nv_mcp55_freeze,
        .thaw                   = nv_mcp55_thaw,
        .error_handler          = nv_swncq_error_handler,
-       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
-       .data_xfer              = ata_data_xfer,
-       .irq_clear              = ata_bmdma_irq_clear,
-       .irq_on                 = ata_irq_on,
-       .scr_read               = nv_scr_read,
-       .scr_write              = nv_scr_write,
+
 #ifdef CONFIG_PM
        .port_suspend           = nv_swncq_port_suspend,
        .port_resume            = nv_swncq_port_resume,
@@ -573,63 +527,70 @@ static const struct ata_port_operations nv_swncq_ops = {
        .port_start             = nv_swncq_port_start,
 };
 
+struct nv_pi_priv {
+       irq_handler_t                   irq_handler;
+       struct scsi_host_template       *sht;
+};
+
+#define NV_PI_PRIV(_irq_handler, _sht) \
+       &(struct nv_pi_priv){ .irq_handler = _irq_handler, .sht = _sht }
+
 static const struct ata_port_info nv_port_info[] = {
        /* generic */
        {
-               .sht            = &nv_sht,
                .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,
+               .private_data   = NV_PI_PRIV(nv_generic_interrupt, &nv_sht),
        },
        /* nforce2/3 */
        {
-               .sht            = &nv_sht,
                .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,
+               .private_data   = NV_PI_PRIV(nv_nf2_interrupt, &nv_sht),
        },
        /* ck804 */
        {
-               .sht            = &nv_sht,
                .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,
+               .private_data   = NV_PI_PRIV(nv_ck804_interrupt, &nv_sht),
        },
        /* ADMA */
        {
-               .sht            = &nv_adma_sht,
                .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                  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,
+               .private_data   = NV_PI_PRIV(nv_adma_interrupt, &nv_adma_sht),
+       },
+       /* MCP5x */
+       {
+               .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+               .pio_mask       = NV_PIO_MASK,
+               .mwdma_mask     = NV_MWDMA_MASK,
+               .udma_mask      = NV_UDMA_MASK,
+               .port_ops       = &nv_generic_ops,
+               .private_data   = NV_PI_PRIV(nv_generic_interrupt, &nv_sht),
        },
        /* SWNCQ */
        {
-               .sht            = &nv_swncq_sht,
                .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                  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_swncq_ops,
-               .irq_handler    = nv_swncq_interrupt,
+               .private_data   = NV_PI_PRIV(nv_swncq_interrupt, &nv_swncq_sht),
        },
 };
 
@@ -639,8 +600,9 @@ MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
 
-static int adma_enabled = 1;
-static int swncq_enabled;
+static int adma_enabled;
+static int swncq_enabled = 1;
+static int msi_enabled;
 
 static void nv_adma_register_mode(struct ata_port *ap)
 {
@@ -715,9 +677,10 @@ static int nv_adma_slave_config(struct scsi_device *sdev)
 {
        struct ata_port *ap = ata_shost_to_port(sdev->host);
        struct nv_adma_port_priv *pp = ap->private_data;
+       struct nv_adma_port_priv *port0, *port1;
+       struct scsi_device *sdev0, *sdev1;
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-       u64 bounce_limit;
-       unsigned long segment_boundary;
+       unsigned long segment_boundary, flags;
        unsigned short sg_tablesize;
        int rc;
        int adma_enable;
@@ -729,6 +692,8 @@ static int nv_adma_slave_config(struct scsi_device *sdev)
                /* Not a proper libata device, ignore */
                return rc;
 
+       spin_lock_irqsave(ap->lock, flags);
+
        if (ap->link.device[sdev->id].class == ATA_DEV_ATAPI) {
                /*
                 * NVIDIA reports that ADMA mode does not support ATAPI commands.
@@ -737,7 +702,6 @@ static int nv_adma_slave_config(struct scsi_device *sdev)
                 * Restrict DMA parameters as required by the legacy interface
                 * when an ATAPI device is connected.
                 */
-               bounce_limit = ATA_DMA_MASK;
                segment_boundary = ATA_DMA_BOUNDARY;
                /* Subtract 1 since an extra entry may be needed for padding, see
                   libata-scsi.c */
@@ -748,7 +712,6 @@ static int nv_adma_slave_config(struct scsi_device *sdev)
                adma_enable = 0;
                nv_adma_register_mode(ap);
        } else {
-               bounce_limit = *ap->dev->dma_mask;
                segment_boundary = NV_ADMA_DMA_BOUNDARY;
                sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN;
                adma_enable = 1;
@@ -774,12 +737,49 @@ static int nv_adma_slave_config(struct scsi_device *sdev)
        if (current_reg != new_reg)
                pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, new_reg);
 
-       blk_queue_bounce_limit(sdev->request_queue, bounce_limit);
+       port0 = ap->host->ports[0]->private_data;
+       port1 = ap->host->ports[1]->private_data;
+       sdev0 = ap->host->ports[0]->link.device[0].sdev;
+       sdev1 = ap->host->ports[1]->link.device[0].sdev;
+       if ((port0->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) ||
+           (port1->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) {
+               /** We have to set the DMA mask to 32-bit if either port is in
+                   ATAPI mode, since they are on the same PCI device which is
+                   used for DMA mapping. If we set the mask we also need to set
+                   the bounce limit on both ports to ensure that the block
+                   layer doesn't feed addresses that cause DMA mapping to
+                   choke. If either SCSI device is not allocated yet, it's OK
+                   since that port will discover its correct setting when it
+                   does get allocated.
+                   Note: Setting 32-bit mask should not fail. */
+               if (sdev0)
+                       blk_queue_bounce_limit(sdev0->request_queue,
+                                              ATA_DMA_MASK);
+               if (sdev1)
+                       blk_queue_bounce_limit(sdev1->request_queue,
+                                              ATA_DMA_MASK);
+
+               pci_set_dma_mask(pdev, ATA_DMA_MASK);
+       } else {
+               /** This shouldn't fail as it was set to this value before */
+               pci_set_dma_mask(pdev, pp->adma_dma_mask);
+               if (sdev0)
+                       blk_queue_bounce_limit(sdev0->request_queue,
+                                              pp->adma_dma_mask);
+               if (sdev1)
+                       blk_queue_bounce_limit(sdev1->request_queue,
+                                              pp->adma_dma_mask);
+       }
+
        blk_queue_segment_boundary(sdev->request_queue, segment_boundary);
        blk_queue_max_hw_segments(sdev->request_queue, sg_tablesize);
        ata_port_printk(ap, KERN_INFO,
-               "bounce limit 0x%llX, segment boundary 0x%lX, hw segs %hu\n",
-               (unsigned long long)bounce_limit, segment_boundary, sg_tablesize);
+               "DMA mask 0x%llX, segment boundary 0x%lX, hw segs %hu\n",
+               (unsigned long long)*ap->host->dev->dma_mask,
+               segment_boundary, sg_tablesize);
+
+       spin_unlock_irqrestore(ap->lock, flags);
+
        return rc;
 }
 
@@ -791,14 +791,16 @@ static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc)
 
 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. */
+       /* Other than when internal or pass-through commands are executed,
+          the only time this function will be called in ADMA mode will be
+          if a command fails. In the failure case we don't care about going
+          into register mode with ADMA commands pending, as the commands will
+          all shortly be aborted anyway. We assume that NCQ commands are not
+          issued via passthrough, which is the only way that switching into
+          ADMA mode could abort outstanding commands. */
        nv_adma_register_mode(ap);
 
-       ata_tf_read(ap, tf);
+       ata_sff_tf_read(ap, tf);
 }
 
 static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb)
@@ -884,10 +886,11 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
                        /* Notifier bits set without a command may indicate the drive
                           is misbehaving. Raise host state machine violation on this
                           condition. */
-                       ata_port_printk(ap, KERN_ERR, "notifier for tag %d with no command?\n",
-                               cpb_num);
+                       ata_port_printk(ap, KERN_ERR,
+                                       "notifier for tag %d with no cmd?\n",
+                                       cpb_num);
                        ehi->err_mask |= AC_ERR_HSM;
-                       ehi->action |= ATA_EH_SOFTRESET;
+                       ehi->action |= ATA_EH_RESET;
                        ata_port_freeze(ap);
                        return 1;
                }
@@ -911,12 +914,12 @@ static int nv_host_intr(struct ata_port *ap, u8 irq_stat)
 
        /* DEV interrupt w/ no active qc? */
        if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
-               ata_check_status(ap);
+               ata_sff_check_status(ap);
                return 1;
        }
 
        /* handle interrupt */
-       return ata_host_intr(ap, qc);
+       return ata_sff_host_intr(ap, qc);
 }
 
 static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
@@ -1008,27 +1011,33 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
                        }
 
                        if (status & (NV_ADMA_STAT_DONE |
-                                     NV_ADMA_STAT_CPBERR)) {
-                               u32 check_commands;
+                                     NV_ADMA_STAT_CPBERR |
+                                     NV_ADMA_STAT_CMD_COMPLETE)) {
+                               u32 check_commands = notifier_clears[i];
                                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;
+                               if (status & NV_ADMA_STAT_CPBERR) {
+                                       /* Check all active commands */
+                                       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--;
                                        error = nv_adma_check_cpb(ap, pos,
-                                               notifier_error & (1 << pos) );
-                                       check_commands &= ~(1 << pos );
+                                               notifier_error & (1 << pos));
+                                       check_commands &= ~(1 << pos);
                                }
                        }
                }
        }
 
-       if(notifier_clears[0] || notifier_clears[1]) {
+       if (notifier_clears[0] || notifier_clears[1]) {
                /* Note: Both notifier clear registers must be written
                   if either is set, even if one is zero, according to NVIDIA. */
                struct nv_adma_port_priv *pp = host->ports[0]->private_data;
@@ -1061,7 +1070,7 @@ static void nv_adma_freeze(struct ata_port *ap)
        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 */
+       readw(mmio + NV_ADMA_CTL);      /* flush posted write */
 }
 
 static void nv_adma_thaw(struct ata_port *ap)
@@ -1079,7 +1088,7 @@ static void nv_adma_thaw(struct ata_port *ap)
        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 */
+       readw(mmio + NV_ADMA_CTL);      /* flush posted write */
 }
 
 static void nv_adma_irq_clear(struct ata_port *ap)
@@ -1089,7 +1098,7 @@ static void nv_adma_irq_clear(struct ata_port *ap)
        u32 notifier_clears[2];
 
        if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) {
-               ata_bmdma_irq_clear(ap);
+               ata_sff_irq_clear(ap);
                return;
        }
 
@@ -1119,8 +1128,8 @@ static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc)
 {
        struct nv_adma_port_priv *pp = qc->ap->private_data;
 
-       if(pp->flags & NV_ADMA_PORT_REGISTER_MODE)
-               ata_bmdma_post_internal_cmd(qc);
+       if (pp->flags & NV_ADMA_PORT_REGISTER_MODE)
+               ata_sff_post_internal_cmd(qc);
 }
 
 static int nv_adma_port_start(struct ata_port *ap)
@@ -1131,10 +1140,20 @@ static int nv_adma_port_start(struct ata_port *ap)
        void *mem;
        dma_addr_t mem_dma;
        void __iomem *mmio;
+       struct pci_dev *pdev = to_pci_dev(dev);
        u16 tmp;
 
        VPRINTK("ENTER\n");
 
+       /* Ensure DMA mask is set to 32-bit before allocating legacy PRD and
+          pad buffers */
+       rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+       if (rc)
+               return rc;
+       rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+       if (rc)
+               return rc;
+
        rc = ata_port_start(ap);
        if (rc)
                return rc;
@@ -1150,6 +1169,15 @@ static int nv_adma_port_start(struct ata_port *ap)
        pp->notifier_clear_block = pp->gen_block +
               NV_ADMA_NOTIFIER_CLEAR + (4 * ap->port_no);
 
+       /* Now that the legacy PRD and padding buffer are allocated we can
+          safely raise the DMA mask to allocate the CPB/APRD table.
+          These are allowed to fail since we store the value that ends up
+          being used to set as the bounce limit in slave_config later if
+          needed. */
+       pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+       pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+       pp->adma_dma_mask = *dev->dma_mask;
+
        mem = dmam_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ,
                                  &mem_dma, GFP_KERNEL);
        if (!mem)
@@ -1165,7 +1193,7 @@ static int nv_adma_port_start(struct ata_port *ap)
        pp->cpb_dma = mem_dma;
 
        writel(mem_dma & 0xFFFFFFFF,    mmio + NV_ADMA_CPB_BASE_LOW);
-       writel((mem_dma >> 16 ) >> 16,  mmio + NV_ADMA_CPB_BASE_HIGH);
+       writel((mem_dma >> 16) >> 16,   mmio + NV_ADMA_CPB_BASE_HIGH);
 
        mem     += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ;
        mem_dma += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ;
@@ -1189,15 +1217,15 @@ static int nv_adma_port_start(struct ata_port *ap)
 
        /* clear GO for register mode, enable interrupt */
        tmp = readw(mmio + NV_ADMA_CTL);
-       writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN |
-                NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL);
+       writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN |
+               NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL);
 
        tmp = readw(mmio + NV_ADMA_CTL);
        writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
-       readw( mmio + NV_ADMA_CTL );    /* flush posted write */
+       readw(mmio + NV_ADMA_CTL);      /* flush posted write */
        udelay(1);
        writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
-       readw( mmio + NV_ADMA_CTL );    /* flush posted write */
+       readw(mmio + NV_ADMA_CTL);      /* flush posted write */
 
        return 0;
 }
@@ -1237,7 +1265,7 @@ static int nv_adma_port_resume(struct ata_port *ap)
 
        /* set CPB block location */
        writel(pp->cpb_dma & 0xFFFFFFFF,        mmio + NV_ADMA_CPB_BASE_LOW);
-       writel((pp->cpb_dma >> 16 ) >> 16,      mmio + NV_ADMA_CPB_BASE_HIGH);
+       writel((pp->cpb_dma >> 16) >> 16,       mmio + NV_ADMA_CPB_BASE_HIGH);
 
        /* clear any outstanding interrupt conditions */
        writew(0xffff, mmio + NV_ADMA_STAT);
@@ -1250,15 +1278,15 @@ static int nv_adma_port_resume(struct ata_port *ap)
 
        /* clear GO for register mode, enable interrupt */
        tmp = readw(mmio + NV_ADMA_CTL);
-       writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN |
-                NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL);
+       writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN |
+               NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL);
 
        tmp = readw(mmio + NV_ADMA_CTL);
        writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
-       readw( mmio + NV_ADMA_CTL );    /* flush posted write */
+       readw(mmio + NV_ADMA_CTL);      /* flush posted write */
        udelay(1);
        writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
-       readw( mmio + NV_ADMA_CTL );    /* flush posted write */
+       readw(mmio + NV_ADMA_CTL);      /* flush posted write */
 
        return 0;
 }
@@ -1333,20 +1361,18 @@ static void nv_adma_fill_aprd(struct ata_queued_cmd *qc,
 static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb)
 {
        struct nv_adma_port_priv *pp = qc->ap->private_data;
-       unsigned int idx;
        struct nv_adma_prd *aprd;
        struct scatterlist *sg;
+       unsigned int si;
 
        VPRINTK("ENTER\n");
 
-       idx = 0;
-
-       ata_for_each_sg(sg, qc) {
-               aprd = (idx < 5) ? &cpb->aprd[idx] : &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (idx-5)];
-               nv_adma_fill_aprd(qc, sg, idx, aprd);
-               idx++;
+       for_each_sg(qc->sg, sg, qc->n_elem, si) {
+               aprd = (si < 5) ? &cpb->aprd[si] :
+                              &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (si-5)];
+               nv_adma_fill_aprd(qc, sg, si, aprd);
        }
-       if (idx > 5)
+       if (si > 5)
                cpb->next_aprd = cpu_to_le64(((u64)(pp->aprd_dma + NV_ADMA_SGTBL_SZ * qc->tag)));
        else
                cpb->next_aprd = cpu_to_le64(0);
@@ -1357,14 +1383,12 @@ 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, where a result taskfile
-          is not required. */
-       if((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) ||
-          (qc->tf.flags & ATA_TFLAG_POLLING) ||
-          (qc->flags & ATA_QCFLAG_RESULT_TF))
+          or interrupt-driven no-data commands. */
+       if ((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) ||
+          (qc->tf.flags & ATA_TFLAG_POLLING))
                return 1;
 
-       if((qc->flags & ATA_QCFLAG_DMAMAP) ||
+       if ((qc->flags & ATA_QCFLAG_DMAMAP) ||
           (qc->tf.protocol == ATA_PROT_NODATA))
                return 0;
 
@@ -1379,8 +1403,10 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc)
                       NV_CPB_CTL_IEN;
 
        if (nv_adma_use_reg_mode(qc)) {
+               BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) &&
+                       (qc->flags & ATA_QCFLAG_DMAMAP));
                nv_adma_register_mode(qc->ap);
-               ata_qc_prep(qc);
+               ata_sff_qc_prep(qc);
                return;
        }
 
@@ -1401,14 +1427,14 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc)
 
        nv_adma_tf_to_cpb(&qc->tf, cpb->tf);
 
-       if(qc->flags & ATA_QCFLAG_DMAMAP) {
+       if (qc->flags & ATA_QCFLAG_DMAMAP) {
                nv_adma_fill_sg(qc, cpb);
                ctl_flags |= NV_CPB_CTL_APRD_VALID;
        } else
                memset(&cpb->aprd[0], 0, sizeof(struct nv_adma_prd) * 5);
 
-       /* Be paranoid and don't let the device see NV_CPB_CTL_CPB_VALID until we are
-          finished filling in all of the contents */
+       /* Be paranoid and don't let the device see NV_CPB_CTL_CPB_VALID
+          until we are finished filling in all of the contents */
        wmb();
        cpb->ctl_flags = ctl_flags;
        wmb();
@@ -1423,11 +1449,23 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
 
        VPRINTK("ENTER\n");
 
+       /* We can't handle result taskfile with NCQ commands, since
+          retrieving the taskfile switches us out of ADMA mode and would abort
+          existing commands. */
+       if (unlikely(qc->tf.protocol == ATA_PROT_NCQ &&
+                    (qc->flags & ATA_QCFLAG_RESULT_TF))) {
+               ata_dev_printk(qc->dev, KERN_ERR,
+                       "NCQ w/ RESULT_TF not allowed\n");
+               return AC_ERR_SYSTEM;
+       }
+
        if (nv_adma_use_reg_mode(qc)) {
                /* use ATA register mode */
                VPRINTK("using ATA register mode: 0x%lx\n", qc->flags);
+               BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) &&
+                       (qc->flags & ATA_QCFLAG_DMAMAP));
                nv_adma_register_mode(qc->ap);
-               return ata_qc_issue_prot(qc);
+               return ata_sff_qc_issue(qc);
        } else
                nv_adma_mode(qc->ap);
 
@@ -1435,16 +1473,16 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
           and (number of cpbs to append -1) in top 8 bits */
        wmb();
 
-       if(curr_ncq != pp->last_issue_ncq) {
-               /* Seems to need some delay before switching between NCQ and non-NCQ
-                  commands, else we get command timeouts and such. */
+       if (curr_ncq != pp->last_issue_ncq) {
+               /* Seems to need some delay before switching between NCQ and
+                  non-NCQ commands, else we get command timeouts and such. */
                udelay(20);
                pp->last_issue_ncq = curr_ncq;
        }
 
        writew(qc->tag, mmio + NV_ADMA_APPEND);
 
-       DPRINTK("Issued tag %u\n",qc->tag);
+       DPRINTK("Issued tag %u\n", qc->tag);
 
        return 0;
 }
@@ -1468,11 +1506,11 @@ static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance)
 
                        qc = ata_qc_from_tag(ap, ap->link.active_tag);
                        if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
-                               handled += ata_host_intr(ap, qc);
+                               handled += ata_sff_host_intr(ap, qc);
                        else
                                // No request pending?  Clear interrupt status
                                // anyway, in case there's one pending.
-                               ap->ops->check_status(ap);
+                               ap->ops->sff_check_status(ap);
                }
 
        }
@@ -1526,24 +1564,56 @@ static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance)
        return ret;
 }
 
-static int nv_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
 {
        if (sc_reg > SCR_CONTROL)
                return -EINVAL;
 
-       *val = ioread32(ap->ioaddr.scr_addr + (sc_reg * 4));
+       *val = ioread32(link->ap->ioaddr.scr_addr + (sc_reg * 4));
        return 0;
 }
 
-static int nv_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
 {
        if (sc_reg > SCR_CONTROL)
                return -EINVAL;
 
-       iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4));
+       iowrite32(val, link->ap->ioaddr.scr_addr + (sc_reg * 4));
        return 0;
 }
 
+static int nv_hardreset(struct ata_link *link, unsigned int *class,
+                       unsigned long deadline)
+{
+       struct ata_eh_context *ehc = &link->eh_context;
+
+       /* Do hardreset iff it's post-boot probing, please read the
+        * comment above port ops for details.
+        */
+       if (!(link->ap->pflags & ATA_PFLAG_LOADING) &&
+           !ata_dev_enabled(link->device))
+               sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
+                                   NULL, NULL);
+       else {
+               const unsigned long *timing = sata_ehc_deb_timing(ehc);
+               int rc;
+
+               if (!(ehc->i.flags & ATA_EHI_QUIET))
+                       ata_link_printk(link, KERN_INFO, "nv: skipping "
+                                       "hardreset on occupied port\n");
+
+               /* make sure the link is online */
+               rc = sata_link_resume(link, timing, deadline);
+               /* whine about phy resume failure but proceed */
+               if (rc && rc != -EOPNOTSUPP)
+                       ata_link_printk(link, KERN_WARNING, "failed to resume "
+                                       "link (errno=%d)\n", rc);
+       }
+
+       /* device signature acquisition is unreliable */
+       return -EAGAIN;
+}
+
 static void nv_nf2_freeze(struct ata_port *ap)
 {
        void __iomem *scr_addr = ap->host->ports[0]->ioaddr.scr_addr;
@@ -1603,7 +1673,7 @@ static void nv_mcp55_freeze(struct ata_port *ap)
        mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
        mask &= ~(NV_INT_ALL_MCP55 << shift);
        writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
-       ata_bmdma_freeze(ap);
+       ata_sff_freeze(ap);
 }
 
 static void nv_mcp55_thaw(struct ata_port *ap)
@@ -1617,36 +1687,18 @@ static void nv_mcp55_thaw(struct ata_port *ap)
        mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
        mask |= (NV_INT_MASK_MCP55 << shift);
        writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
-       ata_bmdma_thaw(ap);
-}
-
-static int nv_hardreset(struct ata_link *link, unsigned int *class,
-                       unsigned long deadline)
-{
-       unsigned int dummy;
-
-       /* SATA hardreset fails to retrieve proper device signature on
-        * some controllers.  Don't classify on hardreset.  For more
-        * info, see http://bugme.osdl.org/show_bug.cgi?id=3352
-        */
-       return sata_std_hardreset(link, &dummy, deadline);
-}
-
-static void nv_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
-                          nv_hardreset, ata_std_postreset);
+       ata_sff_thaw(ap);
 }
 
 static void nv_adma_error_handler(struct ata_port *ap)
 {
        struct nv_adma_port_priv *pp = ap->private_data;
-       if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) {
+       if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) {
                void __iomem *mmio = pp->ctl_block;
                int i;
                u16 tmp;
 
-               if(ata_tag_valid(ap->link.active_tag) || ap->link.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);
@@ -1654,16 +1706,17 @@ static void nv_adma_error_handler(struct ata_port *ap)
                        u8 cpb_count = readb(mmio + NV_ADMA_CPB_COUNT);
                        u8 next_cpb_idx = readb(mmio + NV_ADMA_NEXT_CPB_IDX);
 
-                       ata_port_printk(ap, KERN_ERR, "EH in ADMA mode, notifier 0x%X "
+                       ata_port_printk(ap, KERN_ERR,
+                               "EH in ADMA mode, notifier 0x%X "
                                "notifier_error 0x%X gen_ctl 0x%X status 0x%X "
                                "next cpb count 0x%X next cpb idx 0x%x\n",
                                notifier, notifier_error, gen_ctl, status,
                                cpb_count, next_cpb_idx);
 
-                       for( i=0;i<NV_ADMA_MAX_CPBS;i++) {
+                       for (i = 0; i < NV_ADMA_MAX_CPBS; i++) {
                                struct nv_adma_cpb *cpb = &pp->cpb[i];
-                               if(ata_tag_valid(ap->link.active_tag) && i == ap->link.active_tag) ||
-                                   ap->link.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);
@@ -1673,8 +1726,9 @@ static void nv_adma_error_handler(struct ata_port *ap)
                /* Push us back into port register mode for error handling. */
                nv_adma_register_mode(ap);
 
-               /* Mark all of the CPBs as invalid to prevent them from being executed */
-               for( i=0;i<NV_ADMA_MAX_CPBS;i++)
+               /* Mark all of the CPBs as invalid to prevent them from
+                  being executed */
+               for (i = 0; i < NV_ADMA_MAX_CPBS; i++)
                        pp->cpb[i].ctl_flags &= ~NV_CPB_CTL_CPB_VALID;
 
                /* clear CPB fetch count */
@@ -1683,14 +1737,13 @@ static void nv_adma_error_handler(struct ata_port *ap)
                /* Reset channel */
                tmp = readw(mmio + NV_ADMA_CTL);
                writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
-               readw( mmio + NV_ADMA_CTL );    /* flush posted write */
+               readw(mmio + NV_ADMA_CTL);      /* flush posted write */
                udelay(1);
                writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
-               readw( mmio + NV_ADMA_CTL );    /* flush posted write */
+               readw(mmio + NV_ADMA_CTL);      /* flush posted write */
        }
 
-       ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
-                          nv_hardreset, ata_std_postreset);
+       ata_sff_error_handler(ap);
 }
 
 static void nv_swncq_qc_to_dq(struct ata_port *ap, struct ata_queued_cmd *qc)
@@ -1776,7 +1829,7 @@ static void nv_swncq_ncq_stop(struct ata_port *ap)
                pp->dhfis_bits, pp->dmafis_bits, pp->sdbfis_bits);
 
        ata_port_printk(ap, KERN_ERR, "ATA_REG 0x%X ERR_REG 0x%X\n",
-                       ap->ops->check_status(ap),
+                       ap->ops->sff_check_status(ap),
                        ioread8(ap->ioaddr.error_addr));
 
        sactive = readl(pp->sactive_block);
@@ -1802,7 +1855,7 @@ static void nv_swncq_ncq_stop(struct ata_port *ap)
        }
 
        nv_swncq_pp_reinit(ap);
-       ap->ops->irq_clear(ap);
+       ap->ops->sff_irq_clear(ap);
        __ata_bmdma_stop(ap);
        nv_swncq_irq_clear(ap, 0xffff);
 }
@@ -1813,11 +1866,10 @@ static void nv_swncq_error_handler(struct ata_port *ap)
 
        if (ap->link.sactive) {
                nv_swncq_ncq_stop(ap);
-               ehc->i.action |= ATA_EH_HARDRESET;
+               ehc->i.action |= ATA_EH_RESET;
        }
 
-       ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
-                          nv_hardreset, ata_std_postreset);
+       ata_sff_error_handler(ap);
 }
 
 #ifdef CONFIG_PM
@@ -1923,7 +1975,7 @@ static int nv_swncq_slave_config(struct scsi_device *sdev)
        ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
 
        if (strncmp(model_num, "Maxtor", 6) == 0) {
-               ata_scsi_change_queue_depth(sdev, 1);
+               ata_scsi_change_queue_depth(sdev, 1, SCSI_QDEPTH_DEFAULT);
                ata_dev_printk(dev, KERN_NOTICE,
                        "Disabling SWNCQ mode (depth %x)\n", sdev->queue_depth);
        }
@@ -1963,7 +2015,7 @@ static int nv_swncq_port_start(struct ata_port *ap)
 static void nv_swncq_qc_prep(struct ata_queued_cmd *qc)
 {
        if (qc->tf.protocol != ATA_PROT_NCQ) {
-               ata_qc_prep(qc);
+               ata_sff_qc_prep(qc);
                return;
        }
 
@@ -1977,17 +2029,14 @@ static void nv_swncq_fill_sg(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
        struct scatterlist *sg;
-       unsigned int idx;
        struct nv_swncq_port_priv *pp = ap->private_data;
        struct ata_prd *prd;
-
-       WARN_ON(qc->__sg == NULL);
-       WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
+       unsigned int si, idx;
 
        prd = pp->prd + ATA_MAX_PRD * qc->tag;
 
        idx = 0;
-       ata_for_each_sg(sg, qc) {
+       for_each_sg(qc->sg, sg, qc->n_elem, si) {
                u32 addr, offset;
                u32 sg_len, len;
 
@@ -2009,8 +2058,7 @@ static void nv_swncq_fill_sg(struct ata_queued_cmd *qc)
                }
        }
 
-       if (idx)
-               prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+       prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
 }
 
 static unsigned int nv_swncq_issue_atacmd(struct ata_port *ap,
@@ -2029,8 +2077,8 @@ static unsigned int nv_swncq_issue_atacmd(struct ata_port *ap,
        pp->dmafis_bits &= ~(1 << qc->tag);
        pp->qc_active |= (0x1 << qc->tag);
 
-       ap->ops->tf_load(ap, &qc->tf);   /* load tf registers */
-       ap->ops->exec_command(ap, &qc->tf);
+       ap->ops->sff_tf_load(ap, &qc->tf);       /* load tf registers */
+       ap->ops->sff_exec_command(ap, &qc->tf);
 
        DPRINTK("Issued tag %u\n", qc->tag);
 
@@ -2043,7 +2091,7 @@ static unsigned int nv_swncq_qc_issue(struct ata_queued_cmd *qc)
        struct nv_swncq_port_priv *pp = ap->private_data;
 
        if (qc->tf.protocol != ATA_PROT_NCQ)
-               return ata_qc_issue_prot(qc);
+               return ata_sff_qc_issue(qc);
 
        DPRINTK("Enter\n");
 
@@ -2098,11 +2146,11 @@ static int nv_swncq_sdbfis(struct ata_port *ap)
                ata_ehi_clear_desc(ehi);
                ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
                ehi->err_mask |= AC_ERR_HOST_BUS;
-               ehi->action |= ATA_EH_SOFTRESET;
+               ehi->action |= ATA_EH_RESET;
                return -EINVAL;
        }
 
-       ap->ops->irq_clear(ap);
+       ap->ops->sff_irq_clear(ap);
        __ata_bmdma_stop(ap);
 
        sactive = readl(pp->sactive_block);
@@ -2113,7 +2161,7 @@ static int nv_swncq_sdbfis(struct ata_port *ap)
                ata_ehi_push_desc(ehi, "illegal SWNCQ:qc_active transition"
                                  "(%08x->%08x)", pp->qc_active, sactive);
                ehi->err_mask |= AC_ERR_HSM;
-               ehi->action |= ATA_EH_HARDRESET;
+               ehi->action |= ATA_EH_RESET;
                return -EINVAL;
        }
        for (i = 0; i < ATA_MAX_QUEUE; i++) {
@@ -2224,7 +2272,7 @@ static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis)
        u8 ata_stat;
        int rc = 0;
 
-       ata_stat = ap->ops->check_status(ap);
+       ata_stat = ap->ops->sff_check_status(ap);
        nv_swncq_irq_clear(ap, fis);
        if (!fis)
                return;
@@ -2240,16 +2288,16 @@ static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis)
        if (!pp->qc_active)
                return;
 
-       if (ap->ops->scr_read(ap, SCR_ERROR, &serror))
+       if (ap->ops->scr_read(&ap->link, SCR_ERROR, &serror))
                return;
-       ap->ops->scr_write(ap, SCR_ERROR, serror);
+       ap->ops->scr_write(&ap->link, SCR_ERROR, serror);
 
        if (ata_stat & ATA_ERR) {
                ata_ehi_clear_desc(ehi);
                ata_ehi_push_desc(ehi, "Ata error. fis:0x%X", fis);
                ehi->err_mask |= AC_ERR_DEV;
                ehi->serror |= serror;
-               ehi->action |= ATA_EH_SOFTRESET;
+               ehi->action |= ATA_EH_RESET;
                ata_port_freeze(ap);
                return;
        }
@@ -2281,13 +2329,13 @@ static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis)
                if (pp->ncq_flags & (ncq_saw_sdb | ncq_saw_backout)) {
                        ata_ehi_push_desc(ehi, "illegal fis transaction");
                        ehi->err_mask |= AC_ERR_HSM;
-                       ehi->action |= ATA_EH_HARDRESET;
+                       ehi->action |= ATA_EH_RESET;
                        goto irq_error;
                }
 
                if (!(fis & NV_SWNCQ_IRQ_DMASETUP) &&
                    !(pp->ncq_flags & ncq_saw_dmas)) {
-                       ata_stat = ap->ops->check_status(ap);
+                       ata_stat = ap->ops->sff_check_status(ap);
                        if (ata_stat & ATA_BUSY)
                                goto irq_exit;
 
@@ -2350,10 +2398,11 @@ static irqreturn_t nv_swncq_interrupt(int irq, void *dev_instance)
        return IRQ_RETVAL(handled);
 }
 
-static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-       static int printed_version = 0;
+       static int printed_version;
        const struct ata_port_info *ppi[] = { NULL, NULL };
+       struct nv_pi_priv *ipriv;
        struct ata_host *host;
        struct nv_host_priv *hpriv;
        int rc;
@@ -2364,7 +2413,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
         // Make sure this is a SATA controller by counting the number of bars
         // (NVIDIA SATA controllers will always have six bars).  Otherwise,
         // it's an IDE controller and we ignore it.
-       for (bar=0; bar<6; bar++)
+       for (bar = 0; bar < 6; bar++)
                if (pci_resource_start(pdev, bar) == 0)
                        return -ENODEV;
 
@@ -2379,10 +2428,14 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        if (type == CK804 && adma_enabled) {
                dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n");
                type = ADMA;
+       } else if (type == MCP5x && swncq_enabled) {
+               dev_printk(KERN_NOTICE, &pdev->dev, "Using SWNCQ mode\n");
+               type = SWNCQ;
        }
 
        ppi[0] = &nv_port_info[type];
-       rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
+       ipriv = ppi[0]->private_data;
+       rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
        if (rc)
                return rc;
 
@@ -2392,12 +2445,6 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        hpriv->type = type;
        host->private_data = hpriv;
 
-       /* 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);
-       }
-
        /* request and iomap NV_MMIO_BAR */
        rc = pcim_iomap_regions(pdev, 1 << NV_MMIO_BAR, DRV_NAME);
        if (rc)
@@ -2422,14 +2469,17 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                rc = nv_adma_host_init(host);
                if (rc)
                        return rc;
-       } else if (type == SWNCQ && swncq_enabled) {
-               dev_printk(KERN_NOTICE, &pdev->dev, "Using SWNCQ mode\n");
+       } else if (type == SWNCQ)
                nv_swncq_host_init(host);
+
+       if (msi_enabled) {
+               dev_printk(KERN_NOTICE, &pdev->dev, "Using MSI\n");
+               pci_enable_msi(pdev);
        }
 
        pci_set_master(pdev);
-       return ata_host_activate(host, pdev->irq, ppi[0]->irq_handler,
-                                IRQF_SHARED, ppi[0]->sht);
+       return ata_host_activate(host, pdev->irq, ipriv->irq_handler,
+                                IRQF_SHARED, ipriv->sht);
 }
 
 #ifdef CONFIG_PM
@@ -2440,37 +2490,37 @@ static int nv_pci_device_resume(struct pci_dev *pdev)
        int rc;
 
        rc = ata_pci_device_do_resume(pdev);
-       if(rc)
+       if (rc)
                return rc;
 
        if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
-               if(hpriv->type >= CK804) {
+               if (hpriv->type >= CK804) {
                        u8 regval;
 
                        pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);
                        regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
                        pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
                }
-               if(hpriv->type == ADMA) {
+               if (hpriv->type == ADMA) {
                        u32 tmp32;
                        struct nv_adma_port_priv *pp;
                        /* enable/disable ADMA on the ports appropriately */
                        pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32);
 
                        pp = host->ports[0]->private_data;
-                       if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
+                       if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
                                tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN |
-                                          NV_MCP_SATA_CFG_20_PORT0_PWB_EN);
+                                          NV_MCP_SATA_CFG_20_PORT0_PWB_EN);
                        else
                                tmp32 |=  (NV_MCP_SATA_CFG_20_PORT0_EN |
-                                          NV_MCP_SATA_CFG_20_PORT0_PWB_EN);
+                                          NV_MCP_SATA_CFG_20_PORT0_PWB_EN);
                        pp = host->ports[1]->private_data;
-                       if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
+                       if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
                                tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT1_EN |
-                                          NV_MCP_SATA_CFG_20_PORT1_PWB_EN);
+                                          NV_MCP_SATA_CFG_20_PORT1_PWB_EN);
                        else
                                tmp32 |=  (NV_MCP_SATA_CFG_20_PORT1_EN |
-                                          NV_MCP_SATA_CFG_20_PORT1_PWB_EN);
+                                          NV_MCP_SATA_CFG_20_PORT1_PWB_EN);
 
                        pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32);
                }
@@ -2523,7 +2573,9 @@ static void __exit nv_exit(void)
 module_init(nv_init);
 module_exit(nv_exit);
 module_param_named(adma, adma_enabled, bool, 0444);
-MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: true)");
+MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: false)");
 module_param_named(swncq, swncq_enabled, bool, 0444);
-MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: false)");
+MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: true)");
+module_param_named(msi, msi_enabled, bool, 0444);
+MODULE_PARM_DESC(msi, "Enable use of MSI (Default: false)");