]> 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 504f19b2af458d7e4da5ada45e71c72a99416222..4562827b7e22c360652e5d6f9bff397cce4a800d 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/cpumask.h>
+#include <linux/pci-aspm.h>
 #include "pci.h"
 
 #define CARDBUS_LATENCY_TIMER  176     /* secondary latency timer */
@@ -91,6 +92,7 @@ void pci_remove_legacy_files(struct pci_bus *bus) { return; }
  * PCI Bus Class Devices
  */
 static ssize_t pci_bus_show_cpuaffinity(struct device *dev,
+                                       int type,
                                        struct device_attribute *attr,
                                        char *buf)
 {
@@ -98,12 +100,30 @@ static ssize_t pci_bus_show_cpuaffinity(struct device *dev,
        cpumask_t cpumask;
 
        cpumask = pcibus_to_cpumask(to_pci_bus(dev));
-       ret = cpumask_scnprintf(buf, PAGE_SIZE, cpumask);
-       if (ret < PAGE_SIZE)
-               buf[ret++] = '\n';
+       ret = type?
+               cpulist_scnprintf(buf, PAGE_SIZE-2, cpumask):
+               cpumask_scnprintf(buf, PAGE_SIZE-2, cpumask);
+       buf[ret++] = '\n';
+       buf[ret] = '\0';
        return ret;
 }
-DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL);
+
+static ssize_t inline pci_bus_show_cpumaskaffinity(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       return pci_bus_show_cpuaffinity(dev, 0, attr, buf);
+}
+
+static ssize_t inline pci_bus_show_cpulistaffinity(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       return pci_bus_show_cpuaffinity(dev, 1, attr, buf);
+}
+
+DEVICE_ATTR(cpuaffinity,     S_IRUGO, pci_bus_show_cpumaskaffinity, NULL);
+DEVICE_ATTR(cpulistaffinity, S_IRUGO, pci_bus_show_cpulistaffinity, NULL);
 
 /*
  * PCI Bus Class
@@ -234,7 +254,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
                        res->flags |= l & ~PCI_BASE_ADDRESS_IO_MASK;
                }
                res->end = res->start + (unsigned long) sz;
-               res->flags |= pci_calc_resource_flags(l);
+               res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN;
                if (is_64bit_memory(l)) {
                        u32 szhi, lhi;
 
@@ -287,7 +307,8 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
                        if (sz) {
                                res->flags = (l & IORESOURCE_ROM_ENABLE) |
                                  IORESOURCE_MEM | IORESOURCE_PREFETCH |
-                                 IORESOURCE_READONLY | IORESOURCE_CACHEABLE;
+                                 IORESOURCE_READONLY | IORESOURCE_CACHEABLE |
+                                 IORESOURCE_SIZEALIGN;
                                res->start = l & PCI_ROM_ADDRESS_MASK;
                                res->end = res->start + (unsigned long) sz;
                        }
@@ -393,12 +414,13 @@ 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;
 }
 
-static struct pci_bus * __devinit
-pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
+static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
+                                          struct pci_dev *bridge, int busnr)
 {
        struct pci_bus *child;
        int i;
@@ -631,7 +653,9 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
                pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
        }
 
-       sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number);
+       sprintf(child->name,
+               (is_cardbus ? "PCI CardBus %04x:%02x" : "PCI Bus %04x:%02x"),
+               pci_domain_nr(bus), child->number);
 
        /* Has only triggered on CardBus, fixup is in yenta_socket */
        while (bus->parent) {
@@ -791,6 +815,7 @@ static void pci_release_dev(struct device *dev)
        struct pci_dev *pci_dev;
 
        pci_dev = to_pci_dev(dev);
+       pci_vpd_release(pci_dev);
        kfree(pci_dev);
 }
 
@@ -818,6 +843,64 @@ 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)
+{
+       u32 status;
+
+       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;
@@ -834,12 +917,7 @@ int pci_cfg_space_size(struct pci_dev *dev)
                        goto fail;
        }
 
-       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;
@@ -870,8 +948,7 @@ EXPORT_SYMBOL(alloc_pci_dev);
  * Read the config data for a PCI device, sanity-check it
  * and fill in the dev structure...
  */
-static struct pci_dev * __devinit
-pci_scan_device(struct pci_bus *bus, int devfn)
+static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
 {
        struct pci_dev *dev;
        u32 l;
@@ -930,6 +1007,9 @@ pci_scan_device(struct pci_bus *bus, int devfn)
                return NULL;
        }
 
+       pci_vpd_pci22_init(dev);
+       pci_disable_pme(dev);
+
        return dev;
 }
 
@@ -939,7 +1019,6 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
        dev->dev.release = pci_release_dev;
        pci_dev_get(dev);
 
-       set_dev_node(&dev->dev, pcibus_to_node(bus));
        dev->dev.dma_mask = &dev->dma_mask;
        dev->dev.dma_parms = &dev->dma_parms;
        dev->dev.coherent_dma_mask = 0xffffffffull;
@@ -1012,6 +1091,10 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
                                break;
                }
        }
+
+       if (bus->self)
+               pcie_aspm_init_link_state(bus->self);
+
        return nr;
 }
 
@@ -1051,6 +1134,10 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
        return max;
 }
 
+void __attribute__((weak)) set_pci_bus_resources_arch_default(struct pci_bus *b)
+{
+}
+
 struct pci_bus * pci_create_bus(struct device *parent,
                int bus, struct pci_ops *ops, void *sysdata)
 {
@@ -1090,6 +1177,9 @@ struct pci_bus * pci_create_bus(struct device *parent,
                goto dev_reg_err;
        b->bridge = get_device(dev);
 
+       if (!parent)
+               set_dev_node(b->bridge, pcibus_to_node(b));
+
        b->dev.class = &pcibus_class;
        b->dev.parent = b->bridge;
        sprintf(b->dev.bus_id, "%04x:%02x", pci_domain_nr(b), bus);
@@ -1107,6 +1197,8 @@ struct pci_bus * pci_create_bus(struct device *parent,
        b->resource[0] = &ioport_resource;
        b->resource[1] = &iomem_resource;
 
+       set_pci_bus_resources_arch_default(b);
+
        return b;
 
 dev_create_file_err: