pata_artop: add Power Management support
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Thu, 13 Oct 2011 10:59:35 +0000 (12:59 +0200)
committerJeff Garzik <jgarzik@redhat.com>
Fri, 14 Oct 2011 17:32:54 +0000 (13:32 -0400)
Fixes IDE -> libata regression.

There shouldn't be any problems with it as corresponding IDE's host
driver (aec62xx) has been supporting PCI Power Management since
Oct 10 2008 (commit feb22b7f "ide: add proper PCI PM support (v2)")
and IDE PM since Jun 14 2003 (patch v2.5.73 "ide: Power Management").

Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
drivers/ata/pata_artop.c

index ef2bec0..4b8b22e 100644 (file)
@@ -2,7 +2,7 @@
  *    pata_artop.c - ARTOP ATA controller driver
  *
  *     (C) 2006 Red Hat
- *     (C) 2007 Bartlomiej Zolnierkiewicz
+ *     (C) 2007,2011 Bartlomiej Zolnierkiewicz
  *
  *    Based in part on drivers/ide/pci/aec62xx.c
  *     Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org>
@@ -28,7 +28,7 @@
 #include <linux/ata.h>
 
 #define DRV_NAME       "pata_artop"
-#define DRV_VERSION    "0.4.5"
+#define DRV_VERSION    "0.4.6"
 
 /*
  *     The ARTOP has 33 Mhz and "over clocked" timing tables. Until we
@@ -313,6 +313,33 @@ static struct ata_port_operations artop6260_ops = {
        .prereset               = artop62x0_pre_reset,
 };
 
+static void atp8xx_fixup(struct pci_dev *pdev)
+{
+       if (pdev->device == 0x0005)
+               /* BIOS may have left us in UDMA, clear it before libata probe */
+               pci_write_config_byte(pdev, 0x54, 0);
+       else if (pdev->device == 0x0008 || pdev->device == 0x0009) {
+               u8 reg;
+
+               /* Mac systems come up with some registers not set as we
+                  will need them */
+
+               /* Clear reset & test bits */
+               pci_read_config_byte(pdev, 0x49, &reg);
+               pci_write_config_byte(pdev, 0x49, reg & ~0x30);
+
+               /* PCI latency must be > 0x80 for burst mode, tweak it
+                * if required.
+                */
+               pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &reg);
+               if (reg <= 0x80)
+                       pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x90);
+
+               /* Enable IRQ output and burst mode */
+               pci_read_config_byte(pdev, 0x4a, &reg);
+               pci_write_config_byte(pdev, 0x4a, (reg & ~0x01) | 0x80);
+       }
+}
 
 /**
  *     artop_init_one - Register ARTOP ATA PCI device with kernel services
@@ -367,42 +394,22 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
        if (rc)
                return rc;
 
-       if (id->driver_data == 0) {     /* 6210 variant */
+       if (id->driver_data == 0)       /* 6210 variant */
                ppi[0] = &info_6210;
-               /* BIOS may have left us in UDMA, clear it before libata probe */
-               pci_write_config_byte(pdev, 0x54, 0);
-       }
        else if (id->driver_data == 1)  /* 6260 */
                ppi[0] = &info_626x;
        else if (id->driver_data == 2)  { /* 6280 or 6280 + fast */
                unsigned long io = pci_resource_start(pdev, 4);
-               u8 reg;
 
                ppi[0] = &info_628x;
                if (inb(io) & 0x10)
                        ppi[0] = &info_628x_fast;
-               /* Mac systems come up with some registers not set as we
-                  will need them */
-
-               /* Clear reset & test bits */
-               pci_read_config_byte(pdev, 0x49, &reg);
-               pci_write_config_byte(pdev, 0x49, reg & ~ 0x30);
-
-               /* PCI latency must be > 0x80 for burst mode, tweak it
-                * if required.
-                */
-               pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &reg);
-               if (reg <= 0x80)
-                       pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x90);
-
-               /* Enable IRQ output and burst mode */
-               pci_read_config_byte(pdev, 0x4a, &reg);
-               pci_write_config_byte(pdev, 0x4a, (reg & ~0x01) | 0x80);
-
        }
 
        BUG_ON(ppi[0] == NULL);
 
+       atp8xx_fixup(pdev);
+
        return ata_pci_bmdma_init_one(pdev, ppi, &artop_sht, NULL, 0);
 }
 
@@ -416,11 +423,32 @@ static const struct pci_device_id artop_pci_tbl[] = {
        { }     /* terminate list */
 };
 
+#ifdef CONFIG_PM
+static int atp8xx_reinit_one(struct pci_dev *pdev)
+{
+       struct ata_host *host = dev_get_drvdata(&pdev->dev);
+       int rc;
+
+       rc = ata_pci_device_do_resume(pdev);
+       if (rc)
+               return rc;
+
+       atp8xx_fixup(pdev);
+
+       ata_host_resume(host);
+       return 0;
+}
+#endif
+
 static struct pci_driver artop_pci_driver = {
        .name                   = DRV_NAME,
        .id_table               = artop_pci_tbl,
        .probe                  = artop_init_one,
        .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
+       .suspend                = ata_pci_device_suspend,
+       .resume                 = atp8xx_reinit_one,
+#endif
 };
 
 static int __init artop_init(void)
@@ -436,9 +464,8 @@ static void __exit artop_exit(void)
 module_init(artop_init);
 module_exit(artop_exit);
 
-MODULE_AUTHOR("Alan Cox");
+MODULE_AUTHOR("Alan Cox, Bartlomiej Zolnierkiewicz");
 MODULE_DESCRIPTION("SCSI low-level driver for ARTOP PATA");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, artop_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
-