libata: convert the remaining SATA drivers to new init model
[powerpc.git] / drivers / ata / ahci.c
index 6d93240..7c61bc7 100644 (file)
@@ -80,6 +80,7 @@ enum {
        board_ahci_pi           = 1,
        board_ahci_vt8251       = 2,
        board_ahci_ign_iferr    = 3,
+       board_ahci_sb600        = 4,
 
        /* global controller registers */
        HOST_CAP                = 0x00, /* host capabilities */
@@ -168,6 +169,7 @@ enum {
        AHCI_FLAG_NO_NCQ                = (1 << 24),
        AHCI_FLAG_IGN_IRQ_IF_ERR        = (1 << 25), /* ignore IRQ_IF_ERR */
        AHCI_FLAG_HONOR_PI              = (1 << 26), /* honor PORTS_IMPL */
+       AHCI_FLAG_IGN_SERR_INTERNAL     = (1 << 27), /* ignore SERR_INTERNAL */
 };
 
 struct ahci_cmd_hdr {
@@ -186,8 +188,10 @@ struct ahci_sg {
 };
 
 struct ahci_host_priv {
-       u32                     cap;    /* cache of HOST_CAP register */
-       u32                     port_map; /* cache of HOST_PORTS_IMPL reg */
+       u32                     cap;            /* cap to use */
+       u32                     port_map;       /* port map to use */
+       u32                     saved_cap;      /* saved initial cap */
+       u32                     saved_port_map; /* saved initial port_map */
 };
 
 struct ahci_port_priv {
@@ -200,13 +204,13 @@ struct ahci_port_priv {
        /* for NCQ spurious interrupt analysis */
        unsigned int            ncq_saw_d2h:1;
        unsigned int            ncq_saw_dmas:1;
+       unsigned int            ncq_saw_sdb:1;
 };
 
 static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
 static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
-static irqreturn_t ahci_interrupt (int irq, void *dev_instance);
 static void ahci_irq_clear(struct ata_port *ap);
 static int ahci_port_start(struct ata_port *ap);
 static void ahci_port_stop(struct ata_port *ap);
@@ -218,10 +222,12 @@ static void ahci_thaw(struct ata_port *ap);
 static void ahci_error_handler(struct ata_port *ap);
 static void ahci_vt8251_error_handler(struct ata_port *ap);
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
+#ifdef CONFIG_PM
 static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
 static int ahci_port_resume(struct ata_port *ap);
 static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
 static int ahci_pci_device_resume(struct pci_dev *pdev);
+#endif
 
 static struct scsi_host_template ahci_sht = {
        .module                 = THIS_MODULE,
@@ -240,8 +246,10 @@ static struct scsi_host_template ahci_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .suspend                = ata_scsi_device_suspend,
        .resume                 = ata_scsi_device_resume,
+#endif
 };
 
 static const struct ata_port_operations ahci_ops = {
@@ -256,7 +264,6 @@ static const struct ata_port_operations ahci_ops = {
        .qc_prep                = ahci_qc_prep,
        .qc_issue               = ahci_qc_issue,
 
-       .irq_handler            = ahci_interrupt,
        .irq_clear              = ahci_irq_clear,
        .irq_on                 = ata_dummy_irq_on,
        .irq_ack                = ata_dummy_irq_ack,
@@ -270,8 +277,10 @@ static const struct ata_port_operations ahci_ops = {
        .error_handler          = ahci_error_handler,
        .post_internal_cmd      = ahci_post_internal_cmd,
 
+#ifdef CONFIG_PM
        .port_suspend           = ahci_port_suspend,
        .port_resume            = ahci_port_resume,
+#endif
 
        .port_start             = ahci_port_start,
        .port_stop              = ahci_port_stop,
@@ -289,7 +298,6 @@ static const struct ata_port_operations ahci_vt8251_ops = {
        .qc_prep                = ahci_qc_prep,
        .qc_issue               = ahci_qc_issue,
 
-       .irq_handler            = ahci_interrupt,
        .irq_clear              = ahci_irq_clear,
        .irq_on                 = ata_dummy_irq_on,
        .irq_ack                = ata_dummy_irq_ack,
@@ -303,8 +311,10 @@ static const struct ata_port_operations ahci_vt8251_ops = {
        .error_handler          = ahci_vt8251_error_handler,
        .post_internal_cmd      = ahci_post_internal_cmd,
 
+#ifdef CONFIG_PM
        .port_suspend           = ahci_port_suspend,
        .port_resume            = ahci_port_resume,
+#endif
 
        .port_start             = ahci_port_start,
        .port_stop              = ahci_port_stop,
@@ -313,7 +323,6 @@ static const struct ata_port_operations ahci_vt8251_ops = {
 static const struct ata_port_info ahci_port_info[] = {
        /* board_ahci */
        {
-               .sht            = &ahci_sht,
                .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
                                  ATA_FLAG_SKIP_D2H_BSY,
@@ -323,7 +332,6 @@ static const struct ata_port_info ahci_port_info[] = {
        },
        /* board_ahci_pi */
        {
-               .sht            = &ahci_sht,
                .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
                                  ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_HONOR_PI,
@@ -333,7 +341,6 @@ static const struct ata_port_info ahci_port_info[] = {
        },
        /* board_ahci_vt8251 */
        {
-               .sht            = &ahci_sht,
                .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
                                  ATA_FLAG_SKIP_D2H_BSY |
@@ -344,7 +351,6 @@ static const struct ata_port_info ahci_port_info[] = {
        },
        /* board_ahci_ign_iferr */
        {
-               .sht            = &ahci_sht,
                .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
                                  ATA_FLAG_SKIP_D2H_BSY |
@@ -353,6 +359,18 @@ static const struct ata_port_info ahci_port_info[] = {
                .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
                .port_ops       = &ahci_ops,
        },
+       /* board_ahci_sb600 */
+       {
+               .sht            = &ahci_sht,
+               .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+                                 ATA_FLAG_SKIP_D2H_BSY |
+                                 AHCI_FLAG_IGN_SERR_INTERNAL,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
+               .port_ops       = &ahci_ops,
+       },
+
 };
 
 static const struct pci_device_id ahci_pci_tbl[] = {
@@ -380,23 +398,21 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x2929), board_ahci_pi }, /* ICH9M */
        { PCI_VDEVICE(INTEL, 0x292a), board_ahci_pi }, /* ICH9M */
        { PCI_VDEVICE(INTEL, 0x292b), board_ahci_pi }, /* ICH9M */
+       { PCI_VDEVICE(INTEL, 0x292c), board_ahci_pi }, /* ICH9M */
        { PCI_VDEVICE(INTEL, 0x292f), board_ahci_pi }, /* ICH9M */
        { PCI_VDEVICE(INTEL, 0x294d), board_ahci_pi }, /* ICH9 */
        { PCI_VDEVICE(INTEL, 0x294e), board_ahci_pi }, /* ICH9M */
 
-       /* JMicron */
-       { PCI_VDEVICE(JMICRON, 0x2360), board_ahci_ign_iferr }, /* JMB360 */
-       { PCI_VDEVICE(JMICRON, 0x2361), board_ahci_ign_iferr }, /* JMB361 */
-       { PCI_VDEVICE(JMICRON, 0x2363), board_ahci_ign_iferr }, /* JMB363 */
-       { PCI_VDEVICE(JMICRON, 0x2365), board_ahci_ign_iferr }, /* JMB365 */
-       { PCI_VDEVICE(JMICRON, 0x2366), board_ahci_ign_iferr }, /* JMB366 */
+       /* JMicron 360/1/3/5/6, match class to avoid IDE function */
+       { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+         PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
 
        /* ATI */
-       { PCI_VDEVICE(ATI, 0x4380), board_ahci }, /* ATI SB600 non-raid */
-       { PCI_VDEVICE(ATI, 0x4381), board_ahci }, /* ATI SB600 raid */
+       { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
 
        /* VIA */
        { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
+       { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
 
        /* NVIDIA */
        { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci },            /* MCP65 */
@@ -438,8 +454,10 @@ static struct pci_driver ahci_pci_driver = {
        .id_table               = ahci_pci_tbl,
        .probe                  = ahci_init_one,
        .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend                = ahci_pci_device_suspend,
        .resume                 = ahci_pci_device_resume,
+#endif
 };
 
 
@@ -448,10 +466,100 @@ static inline int ahci_nr_ports(u32 cap)
        return (cap & 0x1f) + 1;
 }
 
-static inline void __iomem *ahci_port_base(void __iomem *base,
-                                          unsigned int port)
+static inline void __iomem *ahci_port_base(struct ata_port *ap)
+{
+       void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
+
+       return mmio + 0x100 + (ap->port_no * 0x80);
+}
+
+/**
+ *     ahci_save_initial_config - Save and fixup initial config values
+ *     @pdev: target PCI device
+ *     @pi: associated ATA port info
+ *     @hpriv: host private area to store config values
+ *
+ *     Some registers containing configuration info might be setup by
+ *     BIOS and might be cleared on reset.  This function saves the
+ *     initial values of those registers into @hpriv such that they
+ *     can be restored after controller reset.
+ *
+ *     If inconsistent, config values are fixed up by this function.
+ *
+ *     LOCKING:
+ *     None.
+ */
+static void ahci_save_initial_config(struct pci_dev *pdev,
+                                    const struct ata_port_info *pi,
+                                    struct ahci_host_priv *hpriv)
+{
+       void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
+       u32 cap, port_map;
+       int i;
+
+       /* Values prefixed with saved_ are written back to host after
+        * reset.  Values without are used for driver operation.
+        */
+       hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
+       hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL);
+
+       /* fixup zero port_map */
+       if (!port_map) {
+               port_map = (1 << ahci_nr_ports(hpriv->cap)) - 1;
+               dev_printk(KERN_WARNING, &pdev->dev,
+                          "PORTS_IMPL is zero, forcing 0x%x\n", port_map);
+
+               /* write the fixed up value to the PI register */
+               hpriv->saved_port_map = port_map;
+       }
+
+       /* cross check port_map and cap.n_ports */
+       if (pi->flags & AHCI_FLAG_HONOR_PI) {
+               u32 tmp_port_map = port_map;
+               int n_ports = ahci_nr_ports(cap);
+
+               for (i = 0; i < AHCI_MAX_PORTS && n_ports; i++) {
+                       if (tmp_port_map & (1 << i)) {
+                               n_ports--;
+                               tmp_port_map &= ~(1 << i);
+                       }
+               }
+
+               /* Whine if inconsistent.  No need to update cap.
+                * port_map is used to determine number of ports.
+                */
+               if (n_ports || tmp_port_map)
+                       dev_printk(KERN_WARNING, &pdev->dev,
+                                  "nr_ports (%u) and implemented port map "
+                                  "(0x%x) don't match\n",
+                                  ahci_nr_ports(cap), port_map);
+       } else {
+               /* fabricate port_map from cap.nr_ports */
+               port_map = (1 << ahci_nr_ports(cap)) - 1;
+       }
+
+       /* record values to use during operation */
+       hpriv->cap = cap;
+       hpriv->port_map = port_map;
+}
+
+/**
+ *     ahci_restore_initial_config - Restore initial config
+ *     @host: target ATA host
+ *
+ *     Restore initial config stored by ahci_save_initial_config().
+ *
+ *     LOCKING:
+ *     None.
+ */
+static void ahci_restore_initial_config(struct ata_host *host)
 {
-       return base + 0x100 + (port * 0x80);
+       struct ahci_host_priv *hpriv = host->private_data;
+       void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
+
+       writel(hpriv->saved_cap, mmio + HOST_CAP);
+       writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);
+       (void) readl(mmio + HOST_PORTS_IMPL);   /* flush */
 }
 
 static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in)
@@ -488,8 +596,9 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in,
        writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
-static void ahci_start_engine(void __iomem *port_mmio)
+static void ahci_start_engine(struct ata_port *ap)
 {
+       void __iomem *port_mmio = ahci_port_base(ap);
        u32 tmp;
 
        /* start DMA */
@@ -499,8 +608,9 @@ static void ahci_start_engine(void __iomem *port_mmio)
        readl(port_mmio + PORT_CMD); /* flush */
 }
 
-static int ahci_stop_engine(void __iomem *port_mmio)
+static int ahci_stop_engine(struct ata_port *ap)
 {
+       void __iomem *port_mmio = ahci_port_base(ap);
        u32 tmp;
 
        tmp = readl(port_mmio + PORT_CMD);
@@ -522,19 +632,23 @@ static int ahci_stop_engine(void __iomem *port_mmio)
        return 0;
 }
 
-static void ahci_start_fis_rx(void __iomem *port_mmio, u32 cap,
-                             dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
+static void ahci_start_fis_rx(struct ata_port *ap)
 {
+       void __iomem *port_mmio = ahci_port_base(ap);
+       struct ahci_host_priv *hpriv = ap->host->private_data;
+       struct ahci_port_priv *pp = ap->private_data;
        u32 tmp;
 
        /* set FIS registers */
-       if (cap & HOST_CAP_64)
-               writel((cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI);
-       writel(cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
+       if (hpriv->cap & HOST_CAP_64)
+               writel((pp->cmd_slot_dma >> 16) >> 16,
+                      port_mmio + PORT_LST_ADDR_HI);
+       writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
 
-       if (cap & HOST_CAP_64)
-               writel((rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI);
-       writel(rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
+       if (hpriv->cap & HOST_CAP_64)
+               writel((pp->rx_fis_dma >> 16) >> 16,
+                      port_mmio + PORT_FIS_ADDR_HI);
+       writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
 
        /* enable FIS reception */
        tmp = readl(port_mmio + PORT_CMD);
@@ -545,8 +659,9 @@ static void ahci_start_fis_rx(void __iomem *port_mmio, u32 cap,
        readl(port_mmio + PORT_CMD);
 }
 
-static int ahci_stop_fis_rx(void __iomem *port_mmio)
+static int ahci_stop_fis_rx(struct ata_port *ap)
 {
+       void __iomem *port_mmio = ahci_port_base(ap);
        u32 tmp;
 
        /* disable FIS reception */
@@ -563,14 +678,16 @@ static int ahci_stop_fis_rx(void __iomem *port_mmio)
        return 0;
 }
 
-static void ahci_power_up(void __iomem *port_mmio, u32 cap)
+static void ahci_power_up(struct ata_port *ap)
 {
+       struct ahci_host_priv *hpriv = ap->host->private_data;
+       void __iomem *port_mmio = ahci_port_base(ap);
        u32 cmd;
 
        cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
 
        /* spin up device */
-       if (cap & HOST_CAP_SSS) {
+       if (hpriv->cap & HOST_CAP_SSS) {
                cmd |= PORT_CMD_SPIN_UP;
                writel(cmd, port_mmio + PORT_CMD);
        }
@@ -579,11 +696,14 @@ static void ahci_power_up(void __iomem *port_mmio, u32 cap)
        writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
 }
 
-static void ahci_power_down(void __iomem *port_mmio, u32 cap)
+#ifdef CONFIG_PM
+static void ahci_power_down(struct ata_port *ap)
 {
+       struct ahci_host_priv *hpriv = ap->host->private_data;
+       void __iomem *port_mmio = ahci_port_base(ap);
        u32 cmd, scontrol;
 
-       if (!(cap & HOST_CAP_SSS))
+       if (!(hpriv->cap & HOST_CAP_SSS))
                return;
 
        /* put device into listen mode, first set PxSCTL.DET to 0 */
@@ -596,30 +716,30 @@ static void ahci_power_down(void __iomem *port_mmio, u32 cap)
        cmd &= ~PORT_CMD_SPIN_UP;
        writel(cmd, port_mmio + PORT_CMD);
 }
+#endif
 
-static void ahci_init_port(void __iomem *port_mmio, u32 cap,
-                          dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
+static void ahci_init_port(struct ata_port *ap)
 {
        /* enable FIS reception */
-       ahci_start_fis_rx(port_mmio, cap, cmd_slot_dma, rx_fis_dma);
+       ahci_start_fis_rx(ap);
 
        /* enable DMA */
-       ahci_start_engine(port_mmio);
+       ahci_start_engine(ap);
 }
 
-static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg)
+static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
 {
        int rc;
 
        /* disable DMA */
-       rc = ahci_stop_engine(port_mmio);
+       rc = ahci_stop_engine(ap);
        if (rc) {
                *emsg = "failed to stop engine";
                return rc;
        }
 
        /* disable FIS reception */
-       rc = ahci_stop_fis_rx(port_mmio);
+       rc = ahci_stop_fis_rx(ap);
        if (rc) {
                *emsg = "failed stop FIS RX";
                return rc;
@@ -628,12 +748,11 @@ static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg)
        return 0;
 }
 
-static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
+static int ahci_reset_controller(struct ata_host *host)
 {
-       u32 cap_save, impl_save, tmp;
-
-       cap_save = readl(mmio + HOST_CAP);
-       impl_save = readl(mmio + HOST_PORTS_IMPL);
+       struct pci_dev *pdev = to_pci_dev(host->dev);
+       void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
+       u32 tmp;
 
        /* global controller reset */
        tmp = readl(mmio + HOST_CTL);
@@ -649,7 +768,7 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
 
        tmp = readl(mmio + HOST_CTL);
        if (tmp & HOST_RESET) {
-               dev_printk(KERN_ERR, &pdev->dev,
+               dev_printk(KERN_ERR, host->dev,
                           "controller reset failed (0x%x)\n", tmp);
                return -EIO;
        }
@@ -658,18 +777,8 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
        writel(HOST_AHCI_EN, mmio + HOST_CTL);
        (void) readl(mmio + HOST_CTL);  /* flush */
 
-       /* These write-once registers are normally cleared on reset.
-        * Restore BIOS values... which we HOPE were present before
-        * reset.
-        */
-       if (!impl_save) {
-               impl_save = (1 << ahci_nr_ports(cap_save)) - 1;
-               dev_printk(KERN_WARNING, &pdev->dev,
-                          "PORTS_IMPL is zero, forcing 0x%x\n", impl_save);
-       }
-       writel(cap_save, mmio + HOST_CAP);
-       writel(impl_save, mmio + HOST_PORTS_IMPL);
-       (void) readl(mmio + HOST_PORTS_IMPL);   /* flush */
+       /* some registers might be cleared on reset.  restore initial values */
+       ahci_restore_initial_config(host);
 
        if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
                u16 tmp16;
@@ -683,23 +792,23 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
        return 0;
 }
 
-static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev,
-                                int n_ports, unsigned int port_flags,
-                                struct ahci_host_priv *hpriv)
+static void ahci_init_controller(struct ata_host *host)
 {
+       struct pci_dev *pdev = to_pci_dev(host->dev);
+       void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
        int i, rc;
        u32 tmp;
 
-       for (i = 0; i < n_ports; i++) {
-               void __iomem *port_mmio = ahci_port_base(mmio, i);
+       for (i = 0; i < host->n_ports; i++) {
+               struct ata_port *ap = host->ports[i];
+               void __iomem *port_mmio = ahci_port_base(ap);
                const char *emsg = NULL;
 
-               if ((port_flags & AHCI_FLAG_HONOR_PI) &&
-                   !(hpriv->port_map & (1 << i)))
+               if (ata_port_is_dummy(ap))
                        continue;
 
                /* make sure port is not active */
-               rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
+               rc = ahci_deinit_port(ap, &emsg);
                if (rc)
                        dev_printk(KERN_WARNING, &pdev->dev,
                                   "%s (%d)\n", emsg, rc);
@@ -727,7 +836,7 @@ static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev,
 
 static unsigned int ahci_dev_classify(struct ata_port *ap)
 {
-       void __iomem *port_mmio = ap->ioaddr.cmd_addr;
+       void __iomem *port_mmio = ahci_port_base(ap);
        struct ata_taskfile tf;
        u32 tmp;
 
@@ -777,8 +886,7 @@ static int ahci_clo(struct ata_port *ap)
 static int ahci_softreset(struct ata_port *ap, unsigned int *class)
 {
        struct ahci_port_priv *pp = ap->private_data;
-       void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+       void __iomem *port_mmio = ahci_port_base(ap);
        const u32 cmd_fis_len = 5; /* five dwords */
        const char *reason = NULL;
        struct ata_taskfile tf;
@@ -795,7 +903,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
        }
 
        /* prepare for SRST (AHCI-1.1 10.4.1) */
-       rc = ahci_stop_engine(port_mmio);
+       rc = ahci_stop_engine(ap);
        if (rc) {
                reason = "failed to stop engine";
                goto fail_restart;
@@ -815,7 +923,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
        }
 
        /* restart engine */
-       ahci_start_engine(port_mmio);
+       ahci_start_engine(ap);
 
        ata_tf_init(ap->device, &tf);
        fis = pp->cmd_tbl;
@@ -874,7 +982,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
        return 0;
 
  fail_restart:
-       ahci_start_engine(port_mmio);
+       ahci_start_engine(ap);
  fail:
        ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
        return rc;
@@ -885,13 +993,11 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
        struct ahci_port_priv *pp = ap->private_data;
        u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
        struct ata_taskfile tf;
-       void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
        int rc;
 
        DPRINTK("ENTER\n");
 
-       ahci_stop_engine(port_mmio);
+       ahci_stop_engine(ap);
 
        /* clear D2H reception area to properly wait for D2H FIS */
        ata_tf_init(ap->device, &tf);
@@ -900,7 +1006,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
 
        rc = sata_std_hardreset(ap, class);
 
-       ahci_start_engine(port_mmio);
+       ahci_start_engine(ap);
 
        if (rc == 0 && ata_port_online(ap))
                *class = ahci_dev_classify(ap);
@@ -913,20 +1019,18 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
 
 static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class)
 {
-       void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
        int rc;
 
        DPRINTK("ENTER\n");
 
-       ahci_stop_engine(port_mmio);
+       ahci_stop_engine(ap);
 
        rc = sata_port_hardreset(ap, sata_ehc_deb_timing(&ap->eh_context));
 
        /* vt8251 needs SError cleared for the port to operate */
        ahci_scr_write(ap, SCR_ERROR, ahci_scr_read(ap, SCR_ERROR));
 
-       ahci_start_engine(port_mmio);
+       ahci_start_engine(ap);
 
        DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
 
@@ -938,7 +1042,7 @@ static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class)
 
 static void ahci_postreset(struct ata_port *ap, unsigned int *class)
 {
-       void __iomem *port_mmio = ap->ioaddr.cmd_addr;
+       void __iomem *port_mmio = ahci_port_base(ap);
        u32 new_tmp, tmp;
 
        ata_std_postreset(ap, class);
@@ -1056,8 +1160,11 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
        if (ap->flags & AHCI_FLAG_IGN_IRQ_IF_ERR)
                irq_stat &= ~PORT_IRQ_IF_ERR;
 
-       if (irq_stat & PORT_IRQ_TF_ERR)
+       if (irq_stat & PORT_IRQ_TF_ERR) {
                err_mask |= AC_ERR_DEV;
+               if (ap->flags & AHCI_FLAG_IGN_SERR_INTERNAL)
+                       serror &= ~SERR_INTERNAL;
+       }
 
        if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
                err_mask |= AC_ERR_HOST_BUS;
@@ -1103,8 +1210,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
 
 static void ahci_host_intr(struct ata_port *ap)
 {
-       void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+       void __iomem *port_mmio = ap->ioaddr.cmd_addr;
        struct ata_eh_info *ehi = &ap->eh_info;
        struct ahci_port_priv *pp = ap->private_data;
        u32 status, qc_active;
@@ -1160,23 +1266,31 @@ static void ahci_host_intr(struct ata_port *ap)
        }
 
        if (status & PORT_IRQ_SDB_FIS) {
-               /* SDB FIS containing spurious completions might be
-                * dangerous, whine and fail commands with HSM
-                * violation.  EH will turn off NCQ after several such
-                * failures.
-                */
                const __le32 *f = pp->rx_fis + RX_FIS_SDB;
 
-               ata_ehi_push_desc(ehi, "spurious completion during NCQ "
-                                 "issue=0x%x SAct=0x%x FIS=%08x:%08x",
-                                 readl(port_mmio + PORT_CMD_ISSUE),
-                                 readl(port_mmio + PORT_SCR_ACT),
-                                 le32_to_cpu(f[0]), le32_to_cpu(f[1]));
-
-               ehi->err_mask |= AC_ERR_HSM;
-               ehi->action |= ATA_EH_SOFTRESET;
-               ata_port_freeze(ap);
-
+               if (le32_to_cpu(f[1])) {
+                       /* SDB FIS containing spurious completions
+                        * might be dangerous, whine and fail commands
+                        * with HSM violation.  EH will turn off NCQ
+                        * after several such failures.
+                        */
+                       ata_ehi_push_desc(ehi,
+                               "spurious completions during NCQ "
+                               "issue=0x%x SAct=0x%x FIS=%08x:%08x",
+                               readl(port_mmio + PORT_CMD_ISSUE),
+                               readl(port_mmio + PORT_SCR_ACT),
+                               le32_to_cpu(f[0]), le32_to_cpu(f[1]));
+                       ehi->err_mask |= AC_ERR_HSM;
+                       ehi->action |= ATA_EH_SOFTRESET;
+                       ata_port_freeze(ap);
+               } else {
+                       if (!pp->ncq_saw_sdb)
+                               ata_port_printk(ap, KERN_INFO,
+                                       "spurious SDB FIS %08x:%08x during NCQ, "
+                                       "this message won't be printed again\n",
+                                       le32_to_cpu(f[0]), le32_to_cpu(f[1]));
+                       pp->ncq_saw_sdb = 1;
+               }
                known_irq = 1;
        }
 
@@ -1247,7 +1361,7 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
 static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
-       void __iomem *port_mmio = ap->ioaddr.cmd_addr;
+       void __iomem *port_mmio = ahci_port_base(ap);
 
        if (qc->tf.protocol == ATA_PROT_NCQ)
                writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
@@ -1259,8 +1373,7 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
 
 static void ahci_freeze(struct ata_port *ap)
 {
-       void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+       void __iomem *port_mmio = ahci_port_base(ap);
 
        /* turn IRQ off */
        writel(0, port_mmio + PORT_IRQ_MASK);
@@ -1269,7 +1382,7 @@ static void ahci_freeze(struct ata_port *ap)
 static void ahci_thaw(struct ata_port *ap)
 {
        void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+       void __iomem *port_mmio = ahci_port_base(ap);
        u32 tmp;
 
        /* clear IRQ */
@@ -1283,13 +1396,10 @@ static void ahci_thaw(struct ata_port *ap)
 
 static void ahci_error_handler(struct ata_port *ap)
 {
-       void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-
        if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
                /* restart engine */
-               ahci_stop_engine(port_mmio);
-               ahci_start_engine(port_mmio);
+               ahci_stop_engine(ap);
+               ahci_start_engine(ap);
        }
 
        /* perform recovery */
@@ -1299,13 +1409,10 @@ static void ahci_error_handler(struct ata_port *ap)
 
 static void ahci_vt8251_error_handler(struct ata_port *ap)
 {
-       void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-
        if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
                /* restart engine */
-               ahci_stop_engine(port_mmio);
-               ahci_start_engine(port_mmio);
+               ahci_stop_engine(ap);
+               ahci_start_engine(ap);
        }
 
        /* perform recovery */
@@ -1316,35 +1423,26 @@ static void ahci_vt8251_error_handler(struct ata_port *ap)
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
-       void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-
-       if (qc->flags & ATA_QCFLAG_FAILED)
-               qc->err_mask |= AC_ERR_OTHER;
 
-       if (qc->err_mask) {
+       if (qc->flags & ATA_QCFLAG_FAILED) {
                /* make DMA engine forget about the failed command */
-               ahci_stop_engine(port_mmio);
-               ahci_start_engine(port_mmio);
+               ahci_stop_engine(ap);
+               ahci_start_engine(ap);
        }
 }
 
+#ifdef CONFIG_PM
 static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
 {
-       struct ahci_host_priv *hpriv = ap->host->private_data;
-       struct ahci_port_priv *pp = ap->private_data;
-       void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
        const char *emsg = NULL;
        int rc;
 
-       rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
+       rc = ahci_deinit_port(ap, &emsg);
        if (rc == 0)
-               ahci_power_down(port_mmio, hpriv->cap);
+               ahci_power_down(ap);
        else {
                ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
-               ahci_init_port(port_mmio, hpriv->cap,
-                              pp->cmd_slot_dma, pp->rx_fis_dma);
+               ahci_init_port(ap);
        }
 
        return rc;
@@ -1352,13 +1450,8 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
 
 static int ahci_port_resume(struct ata_port *ap)
 {
-       struct ahci_port_priv *pp = ap->private_data;
-       struct ahci_host_priv *hpriv = ap->host->private_data;
-       void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-
-       ahci_power_up(port_mmio, hpriv->cap);
-       ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
+       ahci_power_up(ap);
+       ahci_init_port(ap);
 
        return 0;
 }
@@ -1386,8 +1479,6 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
 static int ahci_pci_device_resume(struct pci_dev *pdev)
 {
        struct ata_host *host = dev_get_drvdata(&pdev->dev);
-       struct ahci_host_priv *hpriv = host->private_data;
-       void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
        int rc;
 
        rc = ata_pci_device_do_resume(pdev);
@@ -1395,26 +1486,23 @@ static int ahci_pci_device_resume(struct pci_dev *pdev)
                return rc;
 
        if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
-               rc = ahci_reset_controller(mmio, pdev);
+               rc = ahci_reset_controller(host);
                if (rc)
                        return rc;
 
-               ahci_init_controller(mmio, pdev, host->n_ports,
-                                    host->ports[0]->flags, hpriv);
+               ahci_init_controller(host);
        }
 
        ata_host_resume(host);
 
        return 0;
 }
+#endif
 
 static int ahci_port_start(struct ata_port *ap)
 {
        struct device *dev = ap->host->dev;
-       struct ahci_host_priv *hpriv = ap->host->private_data;
        struct ahci_port_priv *pp;
-       void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
        void *mem;
        dma_addr_t mem_dma;
        int rc;
@@ -1462,85 +1550,29 @@ static int ahci_port_start(struct ata_port *ap)
        ap->private_data = pp;
 
        /* power up port */
-       ahci_power_up(port_mmio, hpriv->cap);
+       ahci_power_up(ap);
 
        /* initialize port */
-       ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
+       ahci_init_port(ap);
 
        return 0;
 }
 
 static void ahci_port_stop(struct ata_port *ap)
 {
-       struct ahci_host_priv *hpriv = ap->host->private_data;
-       void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
        const char *emsg = NULL;
        int rc;
 
        /* de-initialize port */
-       rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
+       rc = ahci_deinit_port(ap, &emsg);
        if (rc)
                ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc);
 }
 
-static void ahci_setup_port(struct ata_ioports *port, void __iomem *base,
-                           unsigned int port_idx)
+static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
 {
-       VPRINTK("ENTER, base==0x%lx, port_idx %u\n", base, port_idx);
-       base = ahci_port_base(base, port_idx);
-       VPRINTK("base now==0x%lx\n", base);
-
-       port->cmd_addr          = base;
-       port->scr_addr          = base + PORT_SCR;
-
-       VPRINTK("EXIT\n");
-}
-
-static int ahci_host_init(struct ata_probe_ent *probe_ent)
-{
-       struct ahci_host_priv *hpriv = probe_ent->private_data;
-       struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
-       void __iomem *mmio = probe_ent->iomap[AHCI_PCI_BAR];
-       unsigned int i, cap_n_ports, using_dac;
        int rc;
 
-       rc = ahci_reset_controller(mmio, pdev);
-       if (rc)
-               return rc;
-
-       hpriv->cap = readl(mmio + HOST_CAP);
-       hpriv->port_map = readl(mmio + HOST_PORTS_IMPL);
-       cap_n_ports = ahci_nr_ports(hpriv->cap);
-
-       VPRINTK("cap 0x%x  port_map 0x%x  n_ports %d\n",
-               hpriv->cap, hpriv->port_map, cap_n_ports);
-
-       if (probe_ent->port_flags & AHCI_FLAG_HONOR_PI) {
-               unsigned int n_ports = cap_n_ports;
-               u32 port_map = hpriv->port_map;
-               int max_port = 0;
-
-               for (i = 0; i < AHCI_MAX_PORTS && n_ports; i++) {
-                       if (port_map & (1 << i)) {
-                               n_ports--;
-                               port_map &= ~(1 << i);
-                               max_port = i;
-                       } else
-                               probe_ent->dummy_port_mask |= 1 << i;
-               }
-
-               if (n_ports || port_map)
-                       dev_printk(KERN_WARNING, &pdev->dev,
-                                  "nr_ports (%u) and implemented port map "
-                                  "(0x%x) don't match\n",
-                                  cap_n_ports, hpriv->port_map);
-
-               probe_ent->n_ports = max_port + 1;
-       } else
-               probe_ent->n_ports = cap_n_ports;
-
-       using_dac = hpriv->cap & HOST_CAP_64;
        if (using_dac &&
            !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
                rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
@@ -1566,23 +1598,14 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
                        return rc;
                }
        }
-
-       for (i = 0; i < probe_ent->n_ports; i++)
-               ahci_setup_port(&probe_ent->port[i], mmio, i);
-
-       ahci_init_controller(mmio, pdev, probe_ent->n_ports,
-                            probe_ent->port_flags, hpriv);
-
-       pci_set_master(pdev);
-
        return 0;
 }
 
-static void ahci_print_info(struct ata_probe_ent *probe_ent)
+static void ahci_print_info(struct ata_host *host)
 {
-       struct ahci_host_priv *hpriv = probe_ent->private_data;
-       struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
-       void __iomem *mmio = probe_ent->iomap[AHCI_PCI_BAR];
+       struct ahci_host_priv *hpriv = host->private_data;
+       struct pci_dev *pdev = to_pci_dev(host->dev);
+       void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
        u32 vers, cap, impl, speed;
        const char *speed_s;
        u16 cc;
@@ -1652,11 +1675,12 @@ static void ahci_print_info(struct ata_probe_ent *probe_ent)
 static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        static int printed_version;
-       unsigned int board_idx = (unsigned int) ent->driver_data;
+       struct ata_port_info pi = ahci_port_info[ent->driver_data];
+       const struct ata_port_info *ppi[] = { &pi, NULL };
        struct device *dev = &pdev->dev;
-       struct ata_probe_ent *probe_ent;
        struct ahci_host_priv *hpriv;
-       int rc;
+       struct ata_host *host;
+       int i, rc;
 
        VPRINTK("ENTER\n");
 
@@ -1665,13 +1689,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (!printed_version++)
                dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-       if (pdev->vendor == PCI_VENDOR_ID_JMICRON) {
-               /* Function 1 is the PATA controller except on the 368, where
-                  we are not AHCI anyway */
-               if (PCI_FUNC(pdev->devfn))
-                       return -ENODEV;
-       }
-
+       /* acquire resources */
        rc = pcim_enable_device(pdev);
        if (rc)
                return rc;
@@ -1685,44 +1703,49 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (pci_enable_msi(pdev))
                pci_intx(pdev, 1);
 
-       probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
-       if (probe_ent == NULL)
-               return -ENOMEM;
-
-       probe_ent->dev = pci_dev_to_dev(pdev);
-       INIT_LIST_HEAD(&probe_ent->node);
-
        hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
        if (!hpriv)
                return -ENOMEM;
 
-       probe_ent->sht          = ahci_port_info[board_idx].sht;
-       probe_ent->port_flags   = ahci_port_info[board_idx].flags;
-       probe_ent->pio_mask     = ahci_port_info[board_idx].pio_mask;
-       probe_ent->udma_mask    = ahci_port_info[board_idx].udma_mask;
-       probe_ent->port_ops     = ahci_port_info[board_idx].port_ops;
+       /* save initial config */
+       ahci_save_initial_config(pdev, &pi, hpriv);
 
-               probe_ent->irq = pdev->irq;
-               probe_ent->irq_flags = IRQF_SHARED;
-       probe_ent->iomap = pcim_iomap_table(pdev);
-       probe_ent->private_data = hpriv;
+       /* prepare host */
+       if (!(pi.flags & AHCI_FLAG_NO_NCQ) && (hpriv->cap & HOST_CAP_NCQ))
+               pi.flags |= ATA_FLAG_NCQ;
+
+       host = ata_host_alloc_pinfo(&pdev->dev, ppi, fls(hpriv->port_map));
+       if (!host)
+               return -ENOMEM;
+       host->iomap = pcim_iomap_table(pdev);
+       host->private_data = hpriv;
+
+       for (i = 0; i < host->n_ports; i++) {
+               if (hpriv->port_map & (1 << i)) {
+                       struct ata_port *ap = host->ports[i];
+                       void __iomem *port_mmio = ahci_port_base(ap);
+
+                       ap->ioaddr.cmd_addr = port_mmio;
+                       ap->ioaddr.scr_addr = port_mmio + PORT_SCR;
+               } else
+                       host->ports[i]->ops = &ata_dummy_port_ops;
+       }
 
        /* initialize adapter */
-       rc = ahci_host_init(probe_ent);
+       rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
        if (rc)
                return rc;
 
-       if (!(probe_ent->port_flags & AHCI_FLAG_NO_NCQ) &&
-           (hpriv->cap & HOST_CAP_NCQ))
-               probe_ent->port_flags |= ATA_FLAG_NCQ;
-
-       ahci_print_info(probe_ent);
+       rc = ahci_reset_controller(host);
+       if (rc)
+               return rc;
 
-       if (!ata_device_add(probe_ent))
-               return -ENODEV;
+       ahci_init_controller(host);
+       ahci_print_info(host);
 
-       devm_kfree(dev, probe_ent);
-       return 0;
+       pci_set_master(pdev);
+       return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED,
+                                &ahci_sht);
 }
 
 static int __init ahci_init(void)