PCI: add PCI Express ASPM support
[pandora-kernel.git] / drivers / pci / pci.c
index 342857c..f331feb 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/log2.h>
+#include <linux/pci-aspm.h>
 #include <asm/dma.h>   /* isa_dma_bridge_buggy */
 #include "pci.h"
 
@@ -314,24 +315,6 @@ int pci_find_ht_capability(struct pci_dev *dev, int ht_cap)
 }
 EXPORT_SYMBOL_GPL(pci_find_ht_capability);
 
-void pcie_wait_pending_transaction(struct pci_dev *dev)
-{
-       int pos;
-       u16 reg16;
-
-       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
-       if (!pos)
-               return;
-       while (1) {
-               pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &reg16);
-               if (!(reg16 & PCI_EXP_DEVSTA_TRPND))
-                       break;
-               cpu_relax();
-       }
-
-}
-EXPORT_SYMBOL_GPL(pcie_wait_pending_transaction);
-
 /**
  * pci_find_parent_resource - return resource region of parent bus of given region
  * @dev: PCI device structure contains resources to be searched
@@ -519,6 +502,9 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
        if (need_restore)
                pci_restore_bars(dev);
 
+       if (dev->bus->self)
+               pcie_aspm_pm_state_change(dev->bus->self);
+
        return 0;
 }
 
@@ -554,6 +540,7 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
        case PM_EVENT_PRETHAW:
                /* REVISIT both freeze and pre-thaw "should" use D0 */
        case PM_EVENT_SUSPEND:
+       case PM_EVENT_HIBERNATE:
                return PCI_D3hot;
        default:
                printk("Unrecognized suspend event %d\n", state.event);
@@ -569,6 +556,7 @@ static int pci_save_pcie_state(struct pci_dev *dev)
        int pos, i = 0;
        struct pci_cap_saved_state *save_state;
        u16 *cap;
+       int found = 0;
 
        pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
        if (pos <= 0)
@@ -577,6 +565,8 @@ static int pci_save_pcie_state(struct pci_dev *dev)
        save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
        if (!save_state)
                save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL);
+       else
+               found = 1;
        if (!save_state) {
                dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
                return -ENOMEM;
@@ -588,7 +578,8 @@ static int pci_save_pcie_state(struct pci_dev *dev)
        pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
        pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
        save_state->cap_nr = PCI_CAP_ID_EXP;
-       pci_add_saved_cap(dev, save_state);
+       if (!found)
+               pci_add_saved_cap(dev, save_state);
        return 0;
 }
 
@@ -616,6 +607,7 @@ static int pci_save_pcix_state(struct pci_dev *dev)
        int pos, i = 0;
        struct pci_cap_saved_state *save_state;
        u16 *cap;
+       int found = 0;
 
        pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
        if (pos <= 0)
@@ -624,6 +616,8 @@ static int pci_save_pcix_state(struct pci_dev *dev)
        save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX);
        if (!save_state)
                save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL);
+       else
+               found = 1;
        if (!save_state) {
                dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
                return -ENOMEM;
@@ -632,7 +626,8 @@ static int pci_save_pcix_state(struct pci_dev *dev)
 
        pci_read_config_word(dev, pos + PCI_X_CMD, &cap[i++]);
        save_state->cap_nr = PCI_CAP_ID_PCIX;
-       pci_add_saved_cap(dev, save_state);
+       if (!found)
+               pci_add_saved_cap(dev, save_state);
        return 0;
 }
 
@@ -733,29 +728,51 @@ int pci_reenable_device(struct pci_dev *dev)
        return 0;
 }
 
-/**
- * pci_enable_device_bars - Initialize some of a device for use
- * @dev: PCI device to be initialized
- * @bars: bitmask of BAR's that must be configured
- *
- *  Initialize device before it's used by a driver. Ask low-level code
- *  to enable selected I/O and memory resources. Wake up the device if it
- *  was suspended. Beware, this function can fail.
- */
-int
-pci_enable_device_bars(struct pci_dev *dev, int bars)
+static int __pci_enable_device_flags(struct pci_dev *dev,
+                                    resource_size_t flags)
 {
        int err;
+       int i, bars = 0;
 
        if (atomic_add_return(1, &dev->enable_cnt) > 1)
                return 0;               /* already enabled */
 
+       for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+               if (dev->resource[i].flags & flags)
+                       bars |= (1 << i);
+
        err = do_pci_enable_device(dev, bars);
        if (err < 0)
                atomic_dec(&dev->enable_cnt);
        return err;
 }
 
+/**
+ * pci_enable_device_io - Initialize a device for use with IO space
+ * @dev: PCI device to be initialized
+ *
+ *  Initialize device before it's used by a driver. Ask low-level code
+ *  to enable I/O resources. Wake up the device if it was suspended.
+ *  Beware, this function can fail.
+ */
+int pci_enable_device_io(struct pci_dev *dev)
+{
+       return __pci_enable_device_flags(dev, IORESOURCE_IO);
+}
+
+/**
+ * pci_enable_device_mem - Initialize a device for use with Memory space
+ * @dev: PCI device to be initialized
+ *
+ *  Initialize device before it's used by a driver. Ask low-level code
+ *  to enable Memory resources. Wake up the device if it was suspended.
+ *  Beware, this function can fail.
+ */
+int pci_enable_device_mem(struct pci_dev *dev)
+{
+       return __pci_enable_device_flags(dev, IORESOURCE_MEM);
+}
+
 /**
  * pci_enable_device - Initialize device before it's used by a driver.
  * @dev: PCI device to be initialized
@@ -769,7 +786,7 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
  */
 int pci_enable_device(struct pci_dev *dev)
 {
-       return pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1);
+       return __pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO);
 }
 
 /*
@@ -843,7 +860,8 @@ int pcim_enable_device(struct pci_dev *pdev)
        dr = get_pci_dr(pdev);
        if (unlikely(!dr))
                return -ENOMEM;
-       WARN_ON(!!dr->enabled);
+       if (dr->enabled)
+               return 0;
 
        rc = pci_enable_device(pdev);
        if (!rc) {
@@ -904,9 +922,6 @@ pci_disable_device(struct pci_dev *dev)
        if (atomic_sub_return(1, &dev->enable_cnt) != 0)
                return;
 
-       /* Wait for all transactions are finished before disabling the device */
-       pcie_wait_pending_transaction(dev);
-
        pci_read_config_word(dev, PCI_COMMAND, &pci_command);
        if (pci_command & PCI_COMMAND_MASTER) {
                pci_command &= ~PCI_COMMAND_MASTER;
@@ -1420,6 +1435,22 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
 }
 #endif
 
+#ifndef HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE
+int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size)
+{
+       return dma_set_max_seg_size(&dev->dev, size);
+}
+EXPORT_SYMBOL(pci_set_dma_max_seg_size);
+#endif
+
+#ifndef HAVE_ARCH_PCI_SET_DMA_SEGMENT_BOUNDARY
+int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask)
+{
+       return dma_set_seg_boundary(&dev->dev, mask);
+}
+EXPORT_SYMBOL(pci_set_dma_seg_boundary);
+#endif
+
 /**
  * pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count
  * @dev: PCI device to query
@@ -1642,7 +1673,8 @@ early_param("pci", pci_setup);
 device_initcall(pci_init);
 
 EXPORT_SYMBOL(pci_reenable_device);
-EXPORT_SYMBOL(pci_enable_device_bars);
+EXPORT_SYMBOL(pci_enable_device_io);
+EXPORT_SYMBOL(pci_enable_device_mem);
 EXPORT_SYMBOL(pci_enable_device);
 EXPORT_SYMBOL(pcim_enable_device);
 EXPORT_SYMBOL(pcim_pin_device);