ahci: RAID mode SATA patch for Intel ICH9M
[powerpc.git] / drivers / ata / ahci.c
index 6a3543e..dc7b562 100644 (file)
@@ -46,7 +46,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "ahci"
-#define DRV_VERSION    "2.0"
+#define DRV_VERSION    "2.1"
 
 
 enum {
@@ -198,9 +198,9 @@ struct ahci_port_priv {
        void                    *rx_fis;
        dma_addr_t              rx_fis_dma;
        /* for NCQ spurious interrupt analysis */
-       int                     ncq_saw_spurious_sdb_cnt;
        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);
@@ -219,10 +219,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,
@@ -241,8 +243,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 = {
@@ -271,8 +275,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,
@@ -304,8 +310,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,
@@ -381,16 +389,14 @@ 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 */
@@ -439,8 +445,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
 };
 
 
@@ -580,6 +588,7 @@ static void ahci_power_up(void __iomem *port_mmio, u32 cap)
        writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
 }
 
+#ifdef CONFIG_PM
 static void ahci_power_down(void __iomem *port_mmio, u32 cap)
 {
        u32 cmd, scontrol;
@@ -597,6 +606,7 @@ 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)
@@ -1160,23 +1170,32 @@ static void ahci_host_intr(struct ata_port *ap)
                known_irq = 1;
        }
 
-       if (status & PORT_IRQ_SDB_FIS &&
-                  pp->ncq_saw_spurious_sdb_cnt < 10) {
-               /* SDB FIS containing spurious completions might be
-                * dangerous, we need to know more about them.  Print
-                * more of it.
-                */
+       if (status & PORT_IRQ_SDB_FIS) {
                const __le32 *f = pp->rx_fis + RX_FIS_SDB;
 
-               ata_port_printk(ap, KERN_INFO, "Spurious SDB FIS during NCQ "
-                               "issue=0x%x SAct=0x%x FIS=%08x:%08x%s\n",
+               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]),
-                               pp->ncq_saw_spurious_sdb_cnt < 10 ?
-                               "" : ", shutting up");
-
-               pp->ncq_saw_spurious_sdb_cnt++;
+                               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;
        }
 
@@ -1329,6 +1348,7 @@ 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)
 {
        struct ahci_host_priv *hpriv = ap->host->private_data;
@@ -1407,6 +1427,7 @@ static int ahci_pci_device_resume(struct pci_dev *pdev)
 
        return 0;
 }
+#endif
 
 static int ahci_port_start(struct ata_port *ap)
 {
@@ -1665,13 +1686,6 @@ 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;
-       }
-
        rc = pcim_enable_device(pdev);
        if (rc)
                return rc;