Merge branch 'x86-mrst-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / drivers / pci / pci.c
index f4a2738..77b493b 100644 (file)
@@ -303,6 +303,49 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
 }
 EXPORT_SYMBOL_GPL(pci_find_ext_capability);
 
+/**
+ * pci_bus_find_ext_capability - find an extended capability
+ * @bus:   the PCI bus to query
+ * @devfn: PCI device to query
+ * @cap:   capability code
+ *
+ * Like pci_find_ext_capability() but works for pci devices that do not have a
+ * pci_dev structure set up yet.
+ *
+ * Returns the address of the requested capability structure within the
+ * device's PCI configuration space or 0 in case the device does not
+ * support it.
+ */
+int pci_bus_find_ext_capability(struct pci_bus *bus, unsigned int devfn,
+                               int cap)
+{
+       u32 header;
+       int ttl;
+       int pos = PCI_CFG_SPACE_SIZE;
+
+       /* minimum 8 bytes per capability */
+       ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
+
+       if (!pci_bus_read_config_dword(bus, devfn, pos, &header))
+               return 0;
+       if (header == 0xffffffff || header == 0)
+               return 0;
+
+       while (ttl-- > 0) {
+               if (PCI_EXT_CAP_ID(header) == cap)
+                       return pos;
+
+               pos = PCI_EXT_CAP_NEXT(header);
+               if (pos < PCI_CFG_SPACE_SIZE)
+                       break;
+
+               if (!pci_bus_read_config_dword(bus, devfn, pos, &header))
+                       break;
+       }
+
+       return 0;
+}
+
 static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap)
 {
        int rc, ttl = PCI_FIND_CAP_TTL;
@@ -1540,6 +1583,7 @@ void pci_pm_init(struct pci_dev *dev)
        int pm;
        u16 pmc;
 
+       device_enable_async_suspend(&dev->dev);
        dev->wakeup_prepared = false;
        dev->pm_cap = 0;
 
@@ -2753,6 +2797,23 @@ int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type)
        return 0;
 }
 
+/* Some architectures require additional programming to enable VGA */
+static arch_set_vga_state_t arch_set_vga_state;
+
+void __init pci_register_set_vga_state(arch_set_vga_state_t func)
+{
+       arch_set_vga_state = func;      /* NULL disables */
+}
+
+static int pci_set_vga_state_arch(struct pci_dev *dev, bool decode,
+                     unsigned int command_bits, bool change_bridge)
+{
+       if (arch_set_vga_state)
+               return arch_set_vga_state(dev, decode, command_bits,
+                                               change_bridge);
+       return 0;
+}
+
 /**
  * pci_set_vga_state - set VGA decode state on device and parents if requested
  * @dev: the PCI device
@@ -2766,9 +2827,15 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode,
        struct pci_bus *bus;
        struct pci_dev *bridge;
        u16 cmd;
+       int rc;
 
        WARN_ON(command_bits & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY));
 
+       /* ARCH specific VGA enables */
+       rc = pci_set_vga_state_arch(dev, decode, command_bits, change_bridge);
+       if (rc)
+               return rc;
+
        pci_read_config_word(dev, PCI_COMMAND, &cmd);
        if (decode == true)
                cmd |= command_bits;
@@ -2983,6 +3050,7 @@ EXPORT_SYMBOL(pcim_pin_device);
 EXPORT_SYMBOL(pci_disable_device);
 EXPORT_SYMBOL(pci_find_capability);
 EXPORT_SYMBOL(pci_bus_find_capability);
+EXPORT_SYMBOL(pci_register_set_vga_state);
 EXPORT_SYMBOL(pci_release_regions);
 EXPORT_SYMBOL(pci_request_regions);
 EXPORT_SYMBOL(pci_request_regions_exclusive);
@@ -3014,4 +3082,3 @@ EXPORT_SYMBOL(pci_target_state);
 EXPORT_SYMBOL(pci_prepare_to_sleep);
 EXPORT_SYMBOL(pci_back_from_sleep);
 EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state);
-