]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/pci/probe.c
PCI: introduce pci_slot
[linux-2.6-omap-h63xx.git] / drivers / pci / probe.c
index 4a55bf380957fd5142f0dd0a8dfa9c39af6d73e8..4562827b7e22c360652e5d6f9bff397cce4a800d 100644 (file)
@@ -414,6 +414,7 @@ static struct pci_bus * pci_alloc_bus(void)
                INIT_LIST_HEAD(&b->node);
                INIT_LIST_HEAD(&b->children);
                INIT_LIST_HEAD(&b->devices);
+               INIT_LIST_HEAD(&b->slots);
        }
        return b;
 }
@@ -842,13 +843,68 @@ static void set_pcie_port_type(struct pci_dev *pdev)
  * reading the dword at 0x100 which must either be 0 or a valid extended
  * capability header.
  */
-int pci_cfg_space_size_ext(struct pci_dev *dev, unsigned check_exp_pcix)
+int pci_cfg_space_size_ext(struct pci_dev *dev)
 {
-       int pos;
        u32 status;
 
-       if (!check_exp_pcix)
-               goto skip;
+       if (pci_read_config_dword(dev, 256, &status) != PCIBIOS_SUCCESSFUL)
+               goto fail;
+       if (status == 0xffffffff)
+               goto fail;
+
+       return PCI_CFG_SPACE_EXP_SIZE;
+
+ fail:
+       return PCI_CFG_SPACE_SIZE;
+}
+
+/**
+ * pci_disable_pme - Disable the PME function of PCI device
+ * @dev: PCI device affected
+ * -EINVAL is returned if PCI device doesn't support PME.
+ * Zero is returned if the PME is supported and can be disabled.
+ */
+static int pci_disable_pme(struct pci_dev *dev)
+{
+       int pm;
+       u16 value;
+
+       /* find PCI PM capability in list */
+       pm = pci_find_capability(dev, PCI_CAP_ID_PM);
+
+       /* If device doesn't support PM Capabilities, it means that PME is
+        * not supported.
+        */
+       if (!pm)
+               return -EINVAL;
+       /* Check device's ability to generate PME# */
+       pci_read_config_word(dev, pm + PCI_PM_PMC, &value);
+
+       value &= PCI_PM_CAP_PME_MASK;
+       /* Check if it can generate PME# */
+       if (!value) {
+               /*
+                * If it is zero, it means that PME is still unsupported
+                * although there exists the PM capability.
+                */
+               return -EINVAL;
+       }
+
+       pci_read_config_word(dev, pm + PCI_PM_CTRL, &value);
+
+       /* Clear PME_Status by writing 1 to it */
+       value |= PCI_PM_CTRL_PME_STATUS ;
+       /* Disable PME enable bit */
+       value &= ~PCI_PM_CTRL_PME_ENABLE;
+       pci_write_config_word(dev, pm + PCI_PM_CTRL, value);
+
+       return 0;
+}
+
+int pci_cfg_space_size(struct pci_dev *dev)
+{
+       int pos;
+       u32 status;
 
        pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
        if (!pos) {
@@ -861,23 +917,12 @@ int pci_cfg_space_size_ext(struct pci_dev *dev, unsigned check_exp_pcix)
                        goto fail;
        }
 
- skip:
-       if (pci_read_config_dword(dev, 256, &status) != PCIBIOS_SUCCESSFUL)
-               goto fail;
-       if (status == 0xffffffff)
-               goto fail;
-
-       return PCI_CFG_SPACE_EXP_SIZE;
+       return pci_cfg_space_size_ext(dev);
 
  fail:
        return PCI_CFG_SPACE_SIZE;
 }
 
-int pci_cfg_space_size(struct pci_dev *dev)
-{
-       return pci_cfg_space_size_ext(dev, 1);
-}
-
 static void pci_release_bus_bridge_dev(struct device *dev)
 {
        kfree(dev);
@@ -963,6 +1008,7 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
        }
 
        pci_vpd_pci22_init(dev);
+       pci_disable_pme(dev);
 
        return dev;
 }