]> err.no Git - linux-2.6/blobdiff - drivers/scsi/aic7xxx/aic79xx_osm_pci.c
Merge branch 'r6040' of git://git.kernel.org/pub/scm/linux/kernel/git/romieu/netdev...
[linux-2.6] / drivers / scsi / aic7xxx / aic79xx_osm_pci.c
index 1a3ab6aa856bb158e79574a4856e8374bbeb5127..4150c8a8fdc2546cdd21224dd0f1dea987ee2416 100644 (file)
 #include "aic79xx_inline.h"
 #include "aic79xx_pci.h"
 
-static int     ahd_linux_pci_dev_probe(struct pci_dev *pdev,
-                                       const struct pci_device_id *ent);
-static int     ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd,
-                                                u_long *base, u_long *base2);
-static int     ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd,
-                                                u_long *bus_addr,
-                                                uint8_t __iomem **maddr);
-static void    ahd_linux_pci_dev_remove(struct pci_dev *pdev);
-
 /* Define the macro locally since it's different for different class of chips.
  */
 #define ID(x)            \
@@ -83,12 +74,51 @@ static struct pci_device_id ahd_linux_pci_id_table[] = {
 
 MODULE_DEVICE_TABLE(pci, ahd_linux_pci_id_table);
 
-static struct pci_driver aic79xx_pci_driver = {
-       .name           = "aic79xx",
-       .probe          = ahd_linux_pci_dev_probe,
-       .remove         = ahd_linux_pci_dev_remove,
-       .id_table       = ahd_linux_pci_id_table
-};
+#ifdef CONFIG_PM
+static int
+ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg)
+{
+       struct ahd_softc *ahd = pci_get_drvdata(pdev);
+       int rc;
+
+       if ((rc = ahd_suspend(ahd)))
+               return rc;
+
+       ahd_pci_suspend(ahd);
+
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
+
+       if (mesg.event == PM_EVENT_SUSPEND)
+               pci_set_power_state(pdev, PCI_D3hot);
+
+       return rc;
+}
+
+static int
+ahd_linux_pci_dev_resume(struct pci_dev *pdev)
+{
+       struct ahd_softc *ahd = pci_get_drvdata(pdev);
+       int rc;
+
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+
+       if ((rc = pci_enable_device(pdev))) {
+               dev_printk(KERN_ERR, &pdev->dev,
+                          "failed to enable device after resume (%d)\n", rc);
+               return rc;
+       }
+
+       pci_set_master(pdev);
+
+       ahd_pci_resume(ahd);
+
+       ahd_resume(ahd);
+
+       return rc;
+}
+#endif
 
 static void
 ahd_linux_pci_dev_remove(struct pci_dev *pdev)
@@ -132,6 +162,7 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct           ahd_pci_identity *entry;
        char            *name;
        int              error;
+       struct device   *dev = &pdev->dev;
 
        pci = pdev;
        entry = ahd_find_pci_device(pci);
@@ -161,20 +192,18 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        pci_set_master(pdev);
 
        if (sizeof(dma_addr_t) > 4) {
-               uint64_t   memsize;
-               const uint64_t mask_39bit = 0x7FFFFFFFFFULL;
+               const u64 required_mask = dma_get_required_mask(dev);
 
-               memsize = ahd_linux_get_memsize();
-
-               if (memsize >= 0x8000000000ULL
-                && pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) {
+               if (required_mask > DMA_39BIT_MASK &&
+                   dma_set_mask(dev, DMA_64BIT_MASK) == 0)
                        ahd->flags |= AHD_64BIT_ADDRESSING;
-               } else if (memsize > 0x80000000
-                       && pci_set_dma_mask(pdev, mask_39bit) == 0) {
+               else if (required_mask > DMA_32BIT_MASK &&
+                        dma_set_mask(dev, DMA_39BIT_MASK) == 0)
                        ahd->flags |= AHD_39BIT_ADDRESSING;
-               }
+               else
+                       dma_set_mask(dev, DMA_32BIT_MASK);
        } else {
-               pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+               dma_set_mask(dev, DMA_32BIT_MASK);
        }
        ahd->dev_softc = pci;
        error = ahd_pci_config(ahd, entry);
@@ -196,6 +225,17 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        return (0);
 }
 
+static struct pci_driver aic79xx_pci_driver = {
+       .name           = "aic79xx",
+       .probe          = ahd_linux_pci_dev_probe,
+#ifdef CONFIG_PM
+       .suspend        = ahd_linux_pci_dev_suspend,
+       .resume         = ahd_linux_pci_dev_resume,
+#endif
+       .remove         = ahd_linux_pci_dev_remove,
+       .id_table       = ahd_linux_pci_id_table
+};
+
 int
 ahd_linux_pci_init(void)
 {