]> Pileus Git - ~andy/linux/commitdiff
Merge tag 'pci-v3.9-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 26 Feb 2013 05:18:18 +0000 (21:18 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 26 Feb 2013 05:18:18 +0000 (21:18 -0800)
Pull PCI changes from Bjorn Helgaas:
 "Host bridge hotplug
    - Major overhaul of ACPI host bridge add/start (Rafael Wysocki, Yinghai Lu)
    - Major overhaul of PCI/ACPI binding (Rafael Wysocki, Yinghai Lu)
    - Split out ACPI host bridge and ACPI PCI device hotplug (Yinghai Lu)
    - Stop caching _PRT and make independent of bus numbers (Yinghai Lu)

  PCI device hotplug
    - Clean up cpqphp dead code (Sasha Levin)
    - Disable ARI unless device and upstream bridge support it (Yijing Wang)
    - Initialize all hot-added devices (not functions 0-7) (Yijing Wang)

  Power management
    - Don't touch ASPM if disabled (Joe Lawrence)
    - Fix ASPM link state management (Myron Stowe)

  Miscellaneous
    - Fix PCI_EXP_FLAGS accessor (Alex Williamson)
    - Disable Bus Master in pci_device_shutdown (Konstantin Khlebnikov)
    - Document hotplug resource and MPS parameters (Yijing Wang)
    - Add accessor for PCIe capabilities (Myron Stowe)
    - Drop pciehp suspend/resume messages (Paul Bolle)
    - Make pci_slot built-in only (not a module) (Jiang Liu)
    - Remove unused PCI/ACPI bind ops (Jiang Liu)
    - Removed used pci_root_bus (Bjorn Helgaas)"

* tag 'pci-v3.9-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (51 commits)
  PCI/ACPI: Don't cache _PRT, and don't associate them with bus numbers
  PCI: Fix PCI Express Capability accessors for PCI_EXP_FLAGS
  ACPI / PCI: Make pci_slot built-in only, not a module
  PCI/PM: Clear state_saved during suspend
  PCI: Use atomic_inc_return() rather than atomic_add_return()
  PCI: Catch attempts to disable already-disabled devices
  PCI: Disable Bus Master unconditionally in pci_device_shutdown()
  PCI: acpiphp: Remove dead code for PCI host bridge hotplug
  PCI: acpiphp: Create companion ACPI devices before creating PCI devices
  PCI: Remove unused "rc" in virtfn_add_bus()
  PCI: pciehp: Drop suspend/resume ENTRY messages
  PCI/ASPM: Don't touch ASPM if forcibly disabled
  PCI/ASPM: Deallocate upstream link state even if device is not PCIe
  PCI: Document MPS parameters pci=pcie_bus_safe, pci=pcie_bus_perf, etc
  PCI: Document hpiosize= and hpmemsize= resource reservation parameters
  PCI: Use PCI Express Capability accessor
  PCI: Introduce accessor to retrieve PCIe Capabilities Register
  PCI: Put pci_dev in device tree as early as possible
  PCI: Skip attaching driver in device_add()
  PCI: acpiphp: Keep driver loaded even if no slots found
  ...

46 files changed:
Documentation/kernel-parameters.txt
arch/frv/mb93090-mb00/pci-frv.h
arch/frv/mb93090-mb00/pci-vdk.c
arch/ia64/pci/pci.c
arch/mn10300/unit-asb2305/pci-asb2305.h
arch/mn10300/unit-asb2305/pci.c
arch/x86/include/asm/pci.h
arch/x86/include/asm/pci_x86.h
arch/x86/pci/acpi.c
arch/x86/pci/common.c
arch/x86/pci/i386.c
arch/x86/pci/legacy.c
arch/x86/pci/numaq_32.c
drivers/acpi/Kconfig
drivers/acpi/internal.h
drivers/acpi/osl.c
drivers/acpi/pci_irq.c
drivers/acpi/pci_root.c
drivers/acpi/pci_slot.c
drivers/acpi/scan.c
drivers/pci/access.c
drivers/pci/bus.c
drivers/pci/hotplug/acpiphp.h
drivers/pci/hotplug/acpiphp_core.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/cpci_hotplug_pci.c
drivers/pci/hotplug/cpqphp_ctrl.c
drivers/pci/hotplug/pciehp_core.c
drivers/pci/hotplug/pciehp_pci.c
drivers/pci/hotplug/sgi_hotplug.c
drivers/pci/hotplug/shpchp_pci.c
drivers/pci/iov.c
drivers/pci/pci-acpi.c
drivers/pci/pci-driver.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/aspm.c
drivers/pci/pcie/portdrv_core.c
drivers/pci/probe.c
drivers/pci/remove.c
drivers/pci/search.c
drivers/pci/setup-bus.c
include/acpi/acpi_bus.h
include/acpi/acpi_drivers.h
include/acpi/acpiosxf.h
include/linux/pci.h

index 766087781ecd6a7ae52b2843cb58c22fc678a8fb..1da94654877274e431971ae51c0726d0027eb5a1 100644 (file)
@@ -2262,6 +2262,21 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                                This sorting is done to get a device
                                order compatible with older (<= 2.4) kernels.
                nobfsort        Don't sort PCI devices into breadth-first order.
+               pcie_bus_tune_off       Disable PCIe MPS (Max Payload Size)
+                               tuning and use the BIOS-configured MPS defaults.
+               pcie_bus_safe   Set every device's MPS to the largest value
+                               supported by all devices below the root complex.
+               pcie_bus_perf   Set device MPS to the largest allowable MPS
+                               based on its parent bus. Also set MRRS (Max
+                               Read Request Size) to the largest supported
+                               value (no larger than the MPS that the device
+                               or bus can support) for best performance.
+               pcie_bus_peer2peer      Set every device's MPS to 128B, which
+                               every device is guaranteed to support. This
+                               configuration allows peer-to-peer DMA between
+                               any pair of devices, possibly at the cost of
+                               reduced performance.  This also guarantees
+                               that hot-added devices will work.
                cbiosize=nn[KMG]        The fixed amount of bus space which is
                                reserved for the CardBus bridge's IO window.
                                The default value is 256 bytes.
@@ -2283,6 +2298,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                                the default.
                                off: Turn ECRC off
                                on: Turn ECRC on.
+               hpiosize=nn[KMG]        The fixed amount of bus space which is
+                               reserved for hotplug bridge's IO window.
+                               Default size is 256 bytes.
+               hpmemsize=nn[KMG]       The fixed amount of bus space which is
+                               reserved for hotplug bridge's memory window.
+                               Default size is 2 megabytes.
                realloc=        Enable/disable reallocating PCI bridge resources
                                if allocations done by BIOS are too small to
                                accommodate resources required by all child
index 089eeba4f3bc4f92b5a28c32e071289723cb8bc3..76c4e73d643d3f8c7dea7d3b59546489aa6f7d96 100644 (file)
@@ -31,7 +31,6 @@ void pcibios_resource_survey(void);
 /* pci-vdk.c */
 
 extern int __nongpreldata pcibios_last_bus;
-extern struct pci_bus *__nongpreldata pci_root_bus;
 extern struct pci_ops *__nongpreldata pci_root_ops;
 
 /* pci-irq.c */
index d186b254ce99fd87046177e8c2d15eb15529dcff..0aa35f0eb0dbfa0cc5fc34c443645ae484c68dc3 100644 (file)
@@ -26,7 +26,6 @@
 unsigned int __nongpreldata pci_probe = 1;
 
 int  __nongpreldata pcibios_last_bus = -1;
-struct pci_bus *__nongpreldata pci_root_bus;
 struct pci_ops *__nongpreldata pci_root_ops;
 
 /*
@@ -416,8 +415,7 @@ int __init pcibios_init(void)
        printk("PCI: Probing PCI hardware\n");
        pci_add_resource(&resources, &pci_ioport_resource);
        pci_add_resource(&resources, &pci_iomem_resource);
-       pci_root_bus = pci_scan_root_bus(NULL, 0, pci_root_ops, NULL,
-                                        &resources);
+       pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources);
 
        pcibios_irq_init();
        pcibios_fixup_peer_bridges();
index 55b72ad573292d58af2d6eff037a46bab8d75dba..60532ab2734684eafc036e5a5bc88194b7bae142 100644 (file)
@@ -393,6 +393,14 @@ out1:
        return NULL;
 }
 
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+       struct pci_controller *controller = bridge->bus->sysdata;
+
+       ACPI_HANDLE_SET(&bridge->dev, controller->acpi_handle);
+       return 0;
+}
+
 static int is_valid_resource(struct pci_dev *dev, int idx)
 {
        unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM;
index 1194fe486b01e6334c5ec12ec4f43261723e9538..7fa66a0e462423d8a415dca78ad24b014aca89c7 100644 (file)
@@ -36,7 +36,6 @@ extern void pcibios_resource_survey(void);
 /* pci.c */
 
 extern int pcibios_last_bus;
-extern struct pci_bus *pci_root_bus;
 extern struct pci_ops *pci_root_ops;
 
 extern struct irq_routing_table *pcibios_get_irq_routing_table(void);
index 6911e845b8cdff49dc85f50f91d2f905c3e2f1c1..1adcf024bb9a4c2221ae93bce8558d85c0b64abb 100644 (file)
@@ -24,7 +24,6 @@
 unsigned int pci_probe = 1;
 
 int pcibios_last_bus = -1;
-struct pci_bus *pci_root_bus;
 struct pci_ops *pci_root_ops;
 
 /*
@@ -377,8 +376,7 @@ static int __init pcibios_init(void)
 
        pci_add_resource_offset(&resources, &pci_ioport_resource, io_offset);
        pci_add_resource_offset(&resources, &pci_iomem_resource, mem_offset);
-       pci_root_bus = pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL,
-                                        &resources);
+       pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources);
 
        pcibios_irq_init();
        pcibios_fixup_irqs();
index c28fd02f4bf76e3fc7cc65bbfb946d5c324101f2..d9e9e6c7ed321c24ad46bd852b1f65da936872e4 100644 (file)
@@ -14,6 +14,9 @@
 struct pci_sysdata {
        int             domain;         /* PCI domain */
        int             node;           /* NUMA node */
+#ifdef CONFIG_ACPI
+       void            *acpi;          /* ACPI-specific data */
+#endif
 #ifdef CONFIG_X86_64
        void            *iommu;         /* IOMMU private data */
 #endif
index 747e5a38b59042026b370acf9fcb86b40d1bf3e4..fa1195dae42541aaa1d836782a3a65aa25640e74 100644 (file)
@@ -54,7 +54,6 @@ void pcibios_set_cache_line_size(void);
 /* pci-pc.c */
 
 extern int pcibios_last_bus;
-extern struct pci_bus *pci_root_bus;
 extern struct pci_ops pci_root_ops;
 
 void pcibios_scan_specific_bus(int busn);
index 53ea60458e01c941a4a9c7113fbb9eebae24efa2..3e724256dbee6b0bb4d2e4156522a08e3bd480e4 100644 (file)
@@ -521,6 +521,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
        sd = &info->sd;
        sd->domain = domain;
        sd->node = node;
+       sd->acpi = device->handle;
        /*
         * Maybe the desired pci bus has been already scanned. In such case
         * it is unnecessary to scan the pci bus with the given domain,busnum.
@@ -592,6 +593,14 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
        return bus;
 }
 
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+       struct pci_sysdata *sd = bridge->bus->sysdata;
+
+       ACPI_HANDLE_SET(&bridge->dev, sd->acpi);
+       return 0;
+}
+
 int __init pci_acpi_init(void)
 {
        struct pci_dev *dev = NULL;
index ccd0ab3ab8996b764b0166f91e84e15f0dbe8ba7..901177d75ff5e36663b3083ba7f7eb77ab4a86c8 100644 (file)
@@ -34,7 +34,6 @@ int noioapicreroute = 1;
 #endif
 int pcibios_last_bus = -1;
 unsigned long pirq_table_addr;
-struct pci_bus *pci_root_bus;
 const struct pci_raw_ops *__read_mostly raw_pci_ops;
 const struct pci_raw_ops *__read_mostly raw_pci_ext_ops;
 
index dd8ca6f7223be11ad7900649e699a35f147e2da1..94919e307f8e97c52d4cd69cee64cf7b0eb68584 100644 (file)
@@ -51,6 +51,7 @@ struct pcibios_fwaddrmap {
 
 static LIST_HEAD(pcibios_fwaddrmappings);
 static DEFINE_SPINLOCK(pcibios_fwaddrmap_lock);
+static bool pcibios_fw_addr_done;
 
 /* Must be called with 'pcibios_fwaddrmap_lock' lock held. */
 static struct pcibios_fwaddrmap *pcibios_fwaddrmap_lookup(struct pci_dev *dev)
@@ -72,6 +73,9 @@ pcibios_save_fw_addr(struct pci_dev *dev, int idx, resource_size_t fw_addr)
        unsigned long flags;
        struct pcibios_fwaddrmap *map;
 
+       if (pcibios_fw_addr_done)
+               return;
+
        spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
        map = pcibios_fwaddrmap_lookup(dev);
        if (!map) {
@@ -97,6 +101,9 @@ resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx)
        struct pcibios_fwaddrmap *map;
        resource_size_t fw_addr = 0;
 
+       if (pcibios_fw_addr_done)
+               return 0;
+
        spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
        map = pcibios_fwaddrmap_lookup(dev);
        if (map)
@@ -106,7 +113,7 @@ resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx)
        return fw_addr;
 }
 
-static void pcibios_fw_addr_list_del(void)
+static void __init pcibios_fw_addr_list_del(void)
 {
        unsigned long flags;
        struct pcibios_fwaddrmap *entry, *next;
@@ -118,6 +125,7 @@ static void pcibios_fw_addr_list_del(void)
                kfree(entry);
        }
        spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);
+       pcibios_fw_addr_done = true;
 }
 
 static int
@@ -193,46 +201,46 @@ EXPORT_SYMBOL(pcibios_align_resource);
  *         as well.
  */
 
-static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
+static void pcibios_allocate_bridge_resources(struct pci_dev *dev)
 {
-       struct pci_bus *bus;
-       struct pci_dev *dev;
        int idx;
        struct resource *r;
 
-       /* Depth-First Search on bus tree */
-       list_for_each_entry(bus, bus_list, node) {
-               if ((dev = bus->self)) {
-                       for (idx = PCI_BRIDGE_RESOURCES;
-                           idx < PCI_NUM_RESOURCES; idx++) {
-                               r = &dev->resource[idx];
-                               if (!r->flags)
-                                       continue;
-                               if (!r->start ||
-                                   pci_claim_resource(dev, idx) < 0) {
-                                       /*
-                                        * Something is wrong with the region.
-                                        * Invalidate the resource to prevent
-                                        * child resource allocations in this
-                                        * range.
-                                        */
-                                       r->start = r->end = 0;
-                                       r->flags = 0;
-                               }
-                       }
+       for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
+               r = &dev->resource[idx];
+               if (!r->flags)
+                       continue;
+               if (!r->start || pci_claim_resource(dev, idx) < 0) {
+                       /*
+                        * Something is wrong with the region.
+                        * Invalidate the resource to prevent
+                        * child resource allocations in this
+                        * range.
+                        */
+                       r->start = r->end = 0;
+                       r->flags = 0;
                }
-               pcibios_allocate_bus_resources(&bus->children);
        }
 }
 
+static void pcibios_allocate_bus_resources(struct pci_bus *bus)
+{
+       struct pci_bus *child;
+
+       /* Depth-First Search on bus tree */
+       if (bus->self)
+               pcibios_allocate_bridge_resources(bus->self);
+       list_for_each_entry(child, &bus->children, node)
+               pcibios_allocate_bus_resources(child);
+}
+
 struct pci_check_idx_range {
        int start;
        int end;
 };
 
-static void __init pcibios_allocate_resources(int pass)
+static void pcibios_allocate_dev_resources(struct pci_dev *dev, int pass)
 {
-       struct pci_dev *dev = NULL;
        int idx, disabled, i;
        u16 command;
        struct resource *r;
@@ -244,14 +252,13 @@ static void __init pcibios_allocate_resources(int pass)
 #endif
        };
 
-       for_each_pci_dev(dev) {
-               pci_read_config_word(dev, PCI_COMMAND, &command);
-               for (i = 0; i < ARRAY_SIZE(idx_range); i++)
+       pci_read_config_word(dev, PCI_COMMAND, &command);
+       for (i = 0; i < ARRAY_SIZE(idx_range); i++)
                for (idx = idx_range[i].start; idx <= idx_range[i].end; idx++) {
                        r = &dev->resource[idx];
-                       if (r->parent)          /* Already allocated */
+                       if (r->parent)  /* Already allocated */
                                continue;
-                       if (!r->start)          /* Address not assigned at all */
+                       if (!r->start)  /* Address not assigned at all */
                                continue;
                        if (r->flags & IORESOURCE_IO)
                                disabled = !(command & PCI_COMMAND_IO);
@@ -270,44 +277,74 @@ static void __init pcibios_allocate_resources(int pass)
                                }
                        }
                }
-               if (!pass) {
-                       r = &dev->resource[PCI_ROM_RESOURCE];
-                       if (r->flags & IORESOURCE_ROM_ENABLE) {
-                               /* Turn the ROM off, leave the resource region,
-                                * but keep it unregistered. */
-                               u32 reg;
-                               dev_dbg(&dev->dev, "disabling ROM %pR\n", r);
-                               r->flags &= ~IORESOURCE_ROM_ENABLE;
-                               pci_read_config_dword(dev,
-                                               dev->rom_base_reg, &reg);
-                               pci_write_config_dword(dev, dev->rom_base_reg,
+       if (!pass) {
+               r = &dev->resource[PCI_ROM_RESOURCE];
+               if (r->flags & IORESOURCE_ROM_ENABLE) {
+                       /* Turn the ROM off, leave the resource region,
+                        * but keep it unregistered. */
+                       u32 reg;
+                       dev_dbg(&dev->dev, "disabling ROM %pR\n", r);
+                       r->flags &= ~IORESOURCE_ROM_ENABLE;
+                       pci_read_config_dword(dev, dev->rom_base_reg, &reg);
+                       pci_write_config_dword(dev, dev->rom_base_reg,
                                                reg & ~PCI_ROM_ADDRESS_ENABLE);
-                       }
                }
        }
 }
 
-static int __init pcibios_assign_resources(void)
+static void pcibios_allocate_resources(struct pci_bus *bus, int pass)
+{
+       struct pci_dev *dev;
+       struct pci_bus *child;
+
+       list_for_each_entry(dev, &bus->devices, bus_list) {
+               pcibios_allocate_dev_resources(dev, pass);
+
+               child = dev->subordinate;
+               if (child)
+                       pcibios_allocate_resources(child, pass);
+       }
+}
+
+static void pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
 {
-       struct pci_dev *dev = NULL;
        struct resource *r;
 
-       if (!(pci_probe & PCI_ASSIGN_ROMS)) {
-               /*
-                * Try to use BIOS settings for ROMs, otherwise let
-                * pci_assign_unassigned_resources() allocate the new
-                * addresses.
-                */
-               for_each_pci_dev(dev) {
-                       r = &dev->resource[PCI_ROM_RESOURCE];
-                       if (!r->flags || !r->start)
-                               continue;
-                       if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
-                               r->end -= r->start;
-                               r->start = 0;
-                       }
-               }
+       /*
+        * Try to use BIOS settings for ROMs, otherwise let
+        * pci_assign_unassigned_resources() allocate the new
+        * addresses.
+        */
+       r = &dev->resource[PCI_ROM_RESOURCE];
+       if (!r->flags || !r->start)
+               return;
+
+       if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
+               r->end -= r->start;
+               r->start = 0;
        }
+}
+static void pcibios_allocate_rom_resources(struct pci_bus *bus)
+{
+       struct pci_dev *dev;
+       struct pci_bus *child;
+
+       list_for_each_entry(dev, &bus->devices, bus_list) {
+               pcibios_allocate_dev_rom_resource(dev);
+
+               child = dev->subordinate;
+               if (child)
+                       pcibios_allocate_rom_resources(child);
+       }
+}
+
+static int __init pcibios_assign_resources(void)
+{
+       struct pci_bus *bus;
+
+       if (!(pci_probe & PCI_ASSIGN_ROMS))
+               list_for_each_entry(bus, &pci_root_buses, node)
+                       pcibios_allocate_rom_resources(bus);
 
        pci_assign_unassigned_resources();
        pcibios_fw_addr_list_del();
@@ -315,12 +352,32 @@ static int __init pcibios_assign_resources(void)
        return 0;
 }
 
+void pcibios_resource_survey_bus(struct pci_bus *bus)
+{
+       dev_printk(KERN_DEBUG, &bus->dev, "Allocating resources\n");
+
+       pcibios_allocate_bus_resources(bus);
+
+       pcibios_allocate_resources(bus, 0);
+       pcibios_allocate_resources(bus, 1);
+
+       if (!(pci_probe & PCI_ASSIGN_ROMS))
+               pcibios_allocate_rom_resources(bus);
+}
+
 void __init pcibios_resource_survey(void)
 {
+       struct pci_bus *bus;
+
        DBG("PCI: Allocating resources\n");
-       pcibios_allocate_bus_resources(&pci_root_buses);
-       pcibios_allocate_resources(0);
-       pcibios_allocate_resources(1);
+
+       list_for_each_entry(bus, &pci_root_buses, node)
+               pcibios_allocate_bus_resources(bus);
+
+       list_for_each_entry(bus, &pci_root_buses, node)
+               pcibios_allocate_resources(bus, 0);
+       list_for_each_entry(bus, &pci_root_buses, node)
+               pcibios_allocate_resources(bus, 1);
 
        e820_reserve_resources_late();
        /*
index 4a2ab9cb36591235541a63b7e3c07513b2be641a..4db96fb1c23260394bb7c4f44775ee1c1f0c6f2d 100644 (file)
@@ -30,7 +30,7 @@ int __init pci_legacy_init(void)
        }
 
        printk("PCI: Probing PCI hardware\n");
-       pci_root_bus = pcibios_scan_root(0);
+       pcibios_scan_root(0);
        return 0;
 }
 
index b96b14c250b6d3a9129116440ea662eb19d641de..72c229f9ebcf68aca50cd7bbb5f668c009df8c5e 100644 (file)
@@ -152,7 +152,7 @@ int __init pci_numaq_init(void)
 
        raw_pci_ops = &pci_direct_conf1_mq;
 
-       pci_root_bus = pcibios_scan_root(0);
+       pcibios_scan_root(0);
        if (num_online_nodes() > 1)
                for_each_online_node(quad) {
                        if (quad == 0)
index 1a4ed64586a726bfd8ccc70ea6b7f8a9cde0651a..320006019e68bfc8fe3f26d63a80b9cf0a9a1f3d 100644 (file)
@@ -306,7 +306,7 @@ config ACPI_DEBUG_FUNC_TRACE
          is about half of the penalty and is rarely useful.
 
 config ACPI_PCI_SLOT
-       tristate "PCI slot detection driver"
+       bool "PCI slot detection driver"
        depends on SYSFS
        default n
        help
@@ -315,9 +315,6 @@ config ACPI_PCI_SLOT
          i.e., segment/bus/device/function tuples, with physical slots in
          the system.  If you are unsure, say N.
 
-         To compile this driver as a module, choose M here:
-         the module will be called pci_slot.
-
 config X86_PM_TIMER
        bool "Power Management Timer Support" if EXPERT
        depends on X86
index 79092328cf064b237c090690c29b64ec1a733063..c8b70b5b2814d273c204080734ec3dce8530cf42 100644 (file)
 
 int init_acpi_device_notify(void);
 int acpi_scan_init(void);
+#ifdef CONFIG_ACPI_PCI_SLOT
+void acpi_pci_slot_init(void);
+#else
+static inline void acpi_pci_slot_init(void) { }
+#endif
 void acpi_pci_root_init(void);
 void acpi_pci_link_init(void);
+void acpi_pci_root_hp_init(void);
 void acpi_platform_init(void);
 int acpi_sysfs_init(void);
 void acpi_csrt_init(void);
index 8080588f88cb39d97b423fc4f3033089a39ecac6..586e7e993d3d01365dfdf9ec21c157e1df4bb490 100644 (file)
@@ -84,8 +84,7 @@ static acpi_osd_handler acpi_irq_handler;
 static void *acpi_irq_context;
 static struct workqueue_struct *kacpid_wq;
 static struct workqueue_struct *kacpi_notify_wq;
-struct workqueue_struct *kacpi_hotplug_wq;
-EXPORT_SYMBOL(kacpi_hotplug_wq);
+static struct workqueue_struct *kacpi_hotplug_wq;
 
 /*
  * This list of permanent mappings is for memory that may be accessed from
@@ -1778,3 +1777,24 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
 {
        __acpi_os_prepare_sleep = func;
 }
+
+void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context,
+                       void (*func)(struct work_struct *work))
+{
+       struct acpi_hp_work *hp_work;
+       int ret;
+
+       hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL);
+       if (!hp_work)
+               return;
+
+       hp_work->handle = handle;
+       hp_work->type = type;
+       hp_work->context = context;
+
+       INIT_WORK(&hp_work->work, func);
+       ret = queue_work(kacpi_hotplug_wq, &hp_work->work);
+       if (!ret)
+               kfree(hp_work);
+}
+EXPORT_SYMBOL_GPL(alloc_acpi_hp_work);
index 68a921d032475edbaa7740d9f880ee5bf52a8db3..41c5e1b799ef938ff1eed92e4cf48a7c7677f8bd 100644 (file)
@@ -53,9 +53,6 @@ struct acpi_prt_entry {
        u32                     index;          /* GSI, or link _CRS index */
 };
 
-static LIST_HEAD(acpi_prt_list);
-static DEFINE_SPINLOCK(acpi_prt_lock);
-
 static inline char pin_name(int pin)
 {
        return 'A' + pin - 1;
@@ -65,28 +62,6 @@ static inline char pin_name(int pin)
                          PCI IRQ Routing Table (PRT) Support
    -------------------------------------------------------------------------- */
 
-static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev,
-                                                         int pin)
-{
-       struct acpi_prt_entry *entry;
-       int segment = pci_domain_nr(dev->bus);
-       int bus = dev->bus->number;
-       int device = PCI_SLOT(dev->devfn);
-
-       spin_lock(&acpi_prt_lock);
-       list_for_each_entry(entry, &acpi_prt_list, list) {
-               if ((segment == entry->id.segment)
-                   && (bus == entry->id.bus)
-                   && (device == entry->id.device)
-                   && (pin == entry->pin)) {
-                       spin_unlock(&acpi_prt_lock);
-                       return entry;
-               }
-       }
-       spin_unlock(&acpi_prt_lock);
-       return NULL;
-}
-
 /* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */
 static const struct dmi_system_id medion_md9580[] = {
        {
@@ -184,11 +159,19 @@ static void do_prt_fixups(struct acpi_prt_entry *entry,
        }
 }
 
-static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,
-                                 struct acpi_pci_routing_table *prt)
+static int acpi_pci_irq_check_entry(acpi_handle handle, struct pci_dev *dev,
+                                 int pin, struct acpi_pci_routing_table *prt,
+                                 struct acpi_prt_entry **entry_ptr)
 {
+       int segment = pci_domain_nr(dev->bus);
+       int bus = dev->bus->number;
+       int device = PCI_SLOT(dev->devfn);
        struct acpi_prt_entry *entry;
 
+       if (((prt->address >> 16) & 0xffff) != device ||
+           prt->pin + 1 != pin)
+               return -ENODEV;
+
        entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL);
        if (!entry)
                return -ENOMEM;
@@ -237,43 +220,37 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,
                              entry->id.device, pin_name(entry->pin),
                              prt->source, entry->index));
 
-       spin_lock(&acpi_prt_lock);
-       list_add_tail(&entry->list, &acpi_prt_list);
-       spin_unlock(&acpi_prt_lock);
+       *entry_ptr = entry;
 
        return 0;
 }
 
-int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
+static int acpi_pci_irq_find_prt_entry(struct pci_dev *dev,
+                         int pin, struct acpi_prt_entry **entry_ptr)
 {
        acpi_status status;
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
        struct acpi_pci_routing_table *entry;
+       acpi_handle handle = NULL;
 
-       /* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */
-       status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
-       if (ACPI_FAILURE(status))
-               return -ENODEV;
-
-       printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
-              (char *) buffer.pointer);
-
-       kfree(buffer.pointer);
+       if (dev->bus->bridge)
+               handle = ACPI_HANDLE(dev->bus->bridge);
 
-       buffer.length = ACPI_ALLOCATE_BUFFER;
-       buffer.pointer = NULL;
+       if (!handle)
+               return -ENODEV;
 
+       /* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */
        status = acpi_get_irq_routing_table(handle, &buffer);
        if (ACPI_FAILURE(status)) {
-               ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRT [%s]",
-                               acpi_format_exception(status)));
                kfree(buffer.pointer);
                return -ENODEV;
        }
 
        entry = buffer.pointer;
        while (entry && (entry->length > 0)) {
-               acpi_pci_irq_add_entry(handle, segment, bus, entry);
+               if (!acpi_pci_irq_check_entry(handle, dev, pin,
+                                                entry, entry_ptr))
+                       break;
                entry = (struct acpi_pci_routing_table *)
                    ((unsigned long)entry + entry->length);
        }
@@ -282,23 +259,6 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
        return 0;
 }
 
-void acpi_pci_irq_del_prt(int segment, int bus)
-{
-       struct acpi_prt_entry *entry, *tmp;
-
-       printk(KERN_DEBUG
-              "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n",
-              segment, bus);
-       spin_lock(&acpi_prt_lock);
-       list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) {
-               if (segment == entry->id.segment && bus == entry->id.bus) {
-                       list_del(&entry->list);
-                       kfree(entry);
-               }
-       }
-       spin_unlock(&acpi_prt_lock);
-}
-
 /* --------------------------------------------------------------------------
                           PCI Interrupt Routing Support
    -------------------------------------------------------------------------- */
@@ -359,12 +319,13 @@ static int acpi_reroute_boot_interrupt(struct pci_dev *dev,
 
 static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
 {
-       struct acpi_prt_entry *entry;
+       struct acpi_prt_entry *entry = NULL;
        struct pci_dev *bridge;
        u8 bridge_pin, orig_pin = pin;
+       int ret;
 
-       entry = acpi_pci_irq_find_prt_entry(dev, pin);
-       if (entry) {
+       ret = acpi_pci_irq_find_prt_entry(dev, pin, &entry);
+       if (!ret && entry) {
 #ifdef CONFIG_X86_IO_APIC
                acpi_reroute_boot_interrupt(dev, entry);
 #endif /* CONFIG_X86_IO_APIC */
@@ -373,7 +334,7 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
                return entry;
        }
 
-       /* 
+       /*
         * Attempt to derive an IRQ for this device from a parent bridge's
         * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge).
         */
@@ -393,8 +354,8 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
                        pin = bridge_pin;
                }
 
-               entry = acpi_pci_irq_find_prt_entry(bridge, pin);
-               if (entry) {
+               ret = acpi_pci_irq_find_prt_entry(bridge, pin, &entry);
+               if (!ret && entry) {
                        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                         "Derived GSI for %s INT %c from %s\n",
                                         pci_name(dev), pin_name(orig_pin),
@@ -470,6 +431,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
                        dev_warn(&dev->dev, "PCI INT %c: no GSI\n",
                                 pin_name(pin));
                }
+
                return 0;
        }
 
@@ -477,6 +439,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
        if (rc < 0) {
                dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
                         pin_name(pin));
+               kfree(entry);
                return rc;
        }
        dev->irq = rc;
@@ -491,6 +454,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
                (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
                (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
 
+       kfree(entry);
        return 0;
 }
 
@@ -513,6 +477,8 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
        else
                gsi = entry->index;
 
+       kfree(entry);
+
        /*
         * TBD: It might be worth clearing dev->irq by magic constant
         * (e.g. PCI_UNDEFINED_IRQ).
index b3cc69c5caf1e07bd93aa4111bfcbb0a0d4293b5..0ac546d5e53f5b0f079792c71419dd07001fe892 100644 (file)
@@ -103,24 +103,6 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
 }
 EXPORT_SYMBOL(acpi_pci_unregister_driver);
 
-acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus)
-{
-       struct acpi_pci_root *root;
-       acpi_handle handle = NULL;
-       
-       mutex_lock(&acpi_pci_root_lock);
-       list_for_each_entry(root, &acpi_pci_roots, node)
-               if ((root->segment == (u16) seg) &&
-                   (root->secondary.start == (u16) bus)) {
-                       handle = root->device->handle;
-                       break;
-               }
-       mutex_unlock(&acpi_pci_root_lock);
-       return handle;
-}
-
-EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle);
-
 /**
  * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge
  * @handle - the ACPI CA node in question.
@@ -431,7 +413,6 @@ static int acpi_pci_root_add(struct acpi_device *device,
        acpi_status status;
        int result;
        struct acpi_pci_root *root;
-       acpi_handle handle;
        struct acpi_pci_driver *driver;
        u32 flags, base_flags;
        bool is_osc_granted = false;
@@ -486,16 +467,6 @@ static int acpi_pci_root_add(struct acpi_device *device,
               acpi_device_name(device), acpi_device_bid(device),
               root->segment, &root->secondary);
 
-       /*
-        * PCI Routing Table
-        * -----------------
-        * Evaluate and parse _PRT, if exists.
-        */
-       status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
-       if (ACPI_SUCCESS(status))
-               result = acpi_pci_irq_add_prt(device->handle, root->segment,
-                                             root->secondary.start);
-
        root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
 
        /*
@@ -597,8 +568,10 @@ static int acpi_pci_root_add(struct acpi_device *device,
        if (device->wakeup.flags.run_wake)
                device_set_run_wake(root->bus->bridge, true);
 
-       if (system_state != SYSTEM_BOOTING)
+       if (system_state != SYSTEM_BOOTING) {
+               pcibios_resource_survey_bus(root->bus);
                pci_assign_unassigned_bus_resources(root->bus);
+       }
 
        mutex_lock(&acpi_pci_root_lock);
        list_for_each_entry(driver, &acpi_pci_drivers, node)
@@ -618,7 +591,6 @@ out_del_root:
        list_del(&root->node);
        mutex_unlock(&acpi_pci_root_lock);
 
-       acpi_pci_irq_del_prt(root->segment, root->secondary.start);
 end:
        kfree(root);
        return result;
@@ -626,8 +598,6 @@ end:
 
 static void acpi_pci_root_remove(struct acpi_device *device)
 {
-       acpi_status status;
-       acpi_handle handle;
        struct acpi_pci_root *root = acpi_driver_data(device);
        struct acpi_pci_driver *driver;
 
@@ -642,10 +612,6 @@ static void acpi_pci_root_remove(struct acpi_device *device)
        device_set_run_wake(root->bus->bridge, false);
        pci_acpi_remove_bus_pm_notifier(device);
 
-       status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
-       if (ACPI_SUCCESS(status))
-               acpi_pci_irq_del_prt(root->segment, root->secondary.start);
-
        pci_remove_root_bus(root->bus);
 
        mutex_lock(&acpi_pci_root_lock);
@@ -663,3 +629,133 @@ void __init acpi_pci_root_init(void)
                acpi_scan_add_handler(&pci_root_handler);
        }
 }
+/* Support root bridge hotplug */
+
+static void handle_root_bridge_insertion(acpi_handle handle)
+{
+       struct acpi_device *device;
+
+       if (!acpi_bus_get_device(handle, &device)) {
+               printk(KERN_DEBUG "acpi device exists...\n");
+               return;
+       }
+
+       if (acpi_bus_scan(handle))
+               printk(KERN_ERR "cannot add bridge to acpi list\n");
+}
+
+static void handle_root_bridge_removal(struct acpi_device *device)
+{
+       struct acpi_eject_event *ej_event;
+
+       ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
+       if (!ej_event) {
+               /* Inform firmware the hot-remove operation has error */
+               (void) acpi_evaluate_hotplug_ost(device->handle,
+                                       ACPI_NOTIFY_EJECT_REQUEST,
+                                       ACPI_OST_SC_NON_SPECIFIC_FAILURE,
+                                       NULL);
+               return;
+       }
+
+       ej_event->device = device;
+       ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
+
+       acpi_bus_hot_remove_device(ej_event);
+}
+
+static void _handle_hotplug_event_root(struct work_struct *work)
+{
+       struct acpi_pci_root *root;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER };
+       struct acpi_hp_work *hp_work;
+       acpi_handle handle;
+       u32 type;
+
+       hp_work = container_of(work, struct acpi_hp_work, work);
+       handle = hp_work->handle;
+       type = hp_work->type;
+
+       root = acpi_pci_find_root(handle);
+
+       acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+
+       switch (type) {
+       case ACPI_NOTIFY_BUS_CHECK:
+               /* bus enumerate */
+               printk(KERN_DEBUG "%s: Bus check notify on %s\n", __func__,
+                                (char *)buffer.pointer);
+               if (!root)
+                       handle_root_bridge_insertion(handle);
+
+               break;
+
+       case ACPI_NOTIFY_DEVICE_CHECK:
+               /* device check */
+               printk(KERN_DEBUG "%s: Device check notify on %s\n", __func__,
+                                (char *)buffer.pointer);
+               if (!root)
+                       handle_root_bridge_insertion(handle);
+               break;
+
+       case ACPI_NOTIFY_EJECT_REQUEST:
+               /* request device eject */
+               printk(KERN_DEBUG "%s: Device eject notify on %s\n", __func__,
+                                (char *)buffer.pointer);
+               if (root)
+                       handle_root_bridge_removal(root->device);
+               break;
+       default:
+               printk(KERN_WARNING "notify_handler: unknown event type 0x%x for %s\n",
+                                type, (char *)buffer.pointer);
+               break;
+       }
+
+       kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
+       kfree(buffer.pointer);
+}
+
+static void handle_hotplug_event_root(acpi_handle handle, u32 type,
+                                       void *context)
+{
+       alloc_acpi_hp_work(handle, type, context,
+                               _handle_hotplug_event_root);
+}
+
+static acpi_status __init
+find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+       acpi_status status;
+       char objname[64];
+       struct acpi_buffer buffer = { .length = sizeof(objname),
+                                     .pointer = objname };
+       int *count = (int *)context;
+
+       if (!acpi_is_root_bridge(handle))
+               return AE_OK;
+
+       (*count)++;
+
+       acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+
+       status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+                                       handle_hotplug_event_root, NULL);
+       if (ACPI_FAILURE(status))
+               printk(KERN_DEBUG "acpi root: %s notify handler is not installed, exit status: %u\n",
+                                 objname, (unsigned int)status);
+       else
+               printk(KERN_DEBUG "acpi root: %s notify handler is installed\n",
+                                objname);
+
+       return AE_OK;
+}
+
+void __init acpi_pci_root_hp_init(void)
+{
+       int num = 0;
+
+       acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+               ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL);
+
+       printk(KERN_DEBUG "Found %d acpi root devices\n", num);
+}
index 2c630c006c2ff30a9461b6fb2e0ccb6265c5c224..cd1434eb1de8d806e28f794ff2e1d55d69020989 100644 (file)
@@ -329,19 +329,8 @@ static struct dmi_system_id acpi_pci_slot_dmi_table[] __initdata = {
        {}
 };
 
-static int __init
-acpi_pci_slot_init(void)
+void __init acpi_pci_slot_init(void)
 {
        dmi_check_system(acpi_pci_slot_dmi_table);
        acpi_pci_register_driver(&acpi_pci_slot_driver);
-       return 0;
 }
-
-static void __exit
-acpi_pci_slot_exit(void)
-{
-       acpi_pci_unregister_driver(&acpi_pci_slot_driver);
-}
-
-module_init(acpi_pci_slot_init);
-module_exit(acpi_pci_slot_exit);
index daee7497efd30137f2dddef2497f9968555d4e26..4be408756adc1df4e15eee0d237f06bfe3e5070e 100644 (file)
@@ -1783,6 +1783,7 @@ int __init acpi_scan_init(void)
        acpi_platform_init();
        acpi_csrt_init();
        acpi_container_init();
+       acpi_pci_slot_init();
 
        mutex_lock(&acpi_scan_lock);
        /*
@@ -1804,6 +1805,8 @@ int __init acpi_scan_init(void)
 
        acpi_update_all_gpes();
 
+       acpi_pci_root_hp_init();
+
  out:
        mutex_unlock(&acpi_scan_lock);
        return result;
index 3af0478c057bdbf8253f2ad62cebaadef22f3656..1cc23661f79bbefa80e636fd4cbb765148306b80 100644 (file)
@@ -472,7 +472,7 @@ EXPORT_SYMBOL_GPL(pci_cfg_access_unlock);
 
 static inline int pcie_cap_version(const struct pci_dev *dev)
 {
-       return dev->pcie_flags_reg & PCI_EXP_FLAGS_VERS;
+       return pcie_caps_reg(dev) & PCI_EXP_FLAGS_VERS;
 }
 
 static inline bool pcie_cap_has_devctl(const struct pci_dev *dev)
@@ -497,7 +497,7 @@ static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev)
        return pcie_cap_version(dev) > 1 ||
               type == PCI_EXP_TYPE_ROOT_PORT ||
               (type == PCI_EXP_TYPE_DOWNSTREAM &&
-               dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT);
+               pcie_caps_reg(dev) & PCI_EXP_FLAGS_SLOT);
 }
 
 static inline bool pcie_cap_has_rtctl(const struct pci_dev *dev)
@@ -515,7 +515,7 @@ static bool pcie_capability_reg_implemented(struct pci_dev *dev, int pos)
                return false;
 
        switch (pos) {
-       case PCI_EXP_FLAGS_TYPE:
+       case PCI_EXP_FLAGS:
                return true;
        case PCI_EXP_DEVCAP:
        case PCI_EXP_DEVCTL:
index ad6a8b63569201050dd3a7b487c5396b6b8ed28f..8647dc6f52d0cfab432826a1261118c487d29bad 100644 (file)
@@ -158,69 +158,38 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
        return ret;
 }
 
+void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { }
+
 /**
- * pci_bus_add_device - add a single device
+ * pci_bus_add_device - start driver for a single device
  * @dev: device to add
  *
- * This adds a single pci device to the global
- * device list and adds sysfs and procfs entries
+ * This adds add sysfs entries and start device drivers
  */
 int pci_bus_add_device(struct pci_dev *dev)
 {
        int retval;
 
-       pci_fixup_device(pci_fixup_final, dev);
-
-       retval = pcibios_add_device(dev);
-       if (retval)
-               return retval;
-
-       retval = device_add(&dev->dev);
-       if (retval)
-               return retval;
-
-       dev->is_added = 1;
-       pci_proc_attach_device(dev);
+       /*
+        * Can not put in pci_device_add yet because resources
+        * are not assigned yet for some devices.
+        */
        pci_create_sysfs_dev_files(dev);
-       return 0;
-}
-
-/**
- * pci_bus_add_child - add a child bus
- * @bus: bus to add
- *
- * This adds sysfs entries for a single bus
- */
-int pci_bus_add_child(struct pci_bus *bus)
-{
-       int retval;
-
-       if (bus->bridge)
-               bus->dev.parent = bus->bridge;
 
-       retval = device_register(&bus->dev);
-       if (retval)
-               return retval;
+       dev->match_driver = true;
+       retval = device_attach(&dev->dev);
+       WARN_ON(retval < 0);
 
-       bus->is_added = 1;
-
-       /* Create legacy_io and legacy_mem files for this bus */
-       pci_create_legacy_files(bus);
+       dev->is_added = 1;
 
-       return retval;
+       return 0;
 }
 
 /**
- * pci_bus_add_devices - insert newly discovered PCI devices
+ * pci_bus_add_devices - start driver for PCI devices
  * @bus: bus to check for new devices
  *
- * Add newly discovered PCI devices (which are on the bus->devices
- * list) to the global PCI device list, add the sysfs and procfs
- * entries.  Where a bridge is found, add the discovered bus to
- * the parents list of child buses, and recurse (breadth-first
- * to be compatible with 2.4)
- *
- * Call hotplug for each new devices.
+ * Start driver for PCI devices and add some sysfs entries.
  */
 void pci_bus_add_devices(const struct pci_bus *bus)
 {
@@ -233,36 +202,20 @@ void pci_bus_add_devices(const struct pci_bus *bus)
                if (dev->is_added)
                        continue;
                retval = pci_bus_add_device(dev);
-               if (retval)
-                       dev_err(&dev->dev, "Error adding device, continuing\n");
        }
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
                BUG_ON(!dev->is_added);
 
                child = dev->subordinate;
-               /*
-                * If there is an unattached subordinate bus, attach
-                * it and then scan for unattached PCI devices.
-                */
+
                if (!child)
                        continue;
-               if (list_empty(&child->node)) {
-                       down_write(&pci_bus_sem);
-                       list_add_tail(&child->node, &dev->bus->children);
-                       up_write(&pci_bus_sem);
-               }
                pci_bus_add_devices(child);
 
-               /*
-                * register the bus with sysfs as the parent is now
-                * properly registered.
-                */
                if (child->is_added)
                        continue;
-               retval = pci_bus_add_child(child);
-               if (retval)
-                       dev_err(&dev->dev, "Error adding bus, continuing\n");
+               child->is_added = 1;
        }
 }
 
index a1afb5b39ad4d03b075a02326796b4e9a8045949..b70ac00a117e1eaa3c65939cd64555982a482f7a 100644 (file)
@@ -79,7 +79,6 @@ struct acpiphp_bridge {
        /* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */
        struct acpiphp_func *func;
 
-       int type;
        int nr_slots;
 
        u32 flags;
@@ -146,10 +145,6 @@ struct acpiphp_attention_info
 /* PCI bus bridge HID */
 #define ACPI_PCI_HOST_HID              "PNP0A03"
 
-/* PCI BRIDGE type */
-#define BRIDGE_TYPE_HOST               0
-#define BRIDGE_TYPE_P2P                        1
-
 /* ACPI _STA method value (ignore bit 4; battery present) */
 #define ACPI_STA_PRESENT               (0x00000001)
 #define ACPI_STA_ENABLED               (0x00000002)
@@ -158,13 +153,7 @@ struct acpiphp_attention_info
 #define ACPI_STA_ALL                   (0x0000000f)
 
 /* bridge flags */
-#define BRIDGE_HAS_STA         (0x00000001)
-#define BRIDGE_HAS_EJ0         (0x00000002)
-#define BRIDGE_HAS_HPP         (0x00000004)
-#define BRIDGE_HAS_PS0         (0x00000010)
-#define BRIDGE_HAS_PS1         (0x00000020)
-#define BRIDGE_HAS_PS2         (0x00000040)
-#define BRIDGE_HAS_PS3         (0x00000080)
+#define BRIDGE_HAS_EJ0         (0x00000001)
 
 /* slot flags */
 
@@ -193,7 +182,6 @@ extern void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot);
 /* acpiphp_glue.c */
 extern int acpiphp_glue_init (void);
 extern void acpiphp_glue_exit (void);
-extern int acpiphp_get_num_slots (void);
 typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);
 
 extern int acpiphp_enable_slot (struct acpiphp_slot *slot);
index 96316b74969f6e7588243e5b36839647319df077..c2fd3095701f5a8bd3f91c56f7b7a8e51913d182 100644 (file)
@@ -50,7 +50,6 @@
 bool acpiphp_debug;
 
 /* local variables */
-static int num_slots;
 static struct acpiphp_attention_info *attention_info;
 
 #define DRIVER_VERSION "0.5"
@@ -272,25 +271,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
        return 0;
 }
 
-static int __init init_acpi(void)
-{
-       int retval;
-
-       /* initialize internal data structure etc. */
-       retval = acpiphp_glue_init();
-
-       /* read initial number of slots */
-       if (!retval) {
-               num_slots = acpiphp_get_num_slots();
-               if (num_slots == 0) {
-                       acpiphp_glue_exit();
-                       retval = -ENODEV;
-               }
-       }
-
-       return retval;
-}
-
 /**
  * release_slot - free up the memory used by a slot
  * @hotplug_slot: slot to free
@@ -379,7 +359,8 @@ static int __init acpiphp_init(void)
                return 0;
 
        /* read all the ACPI info from the system */
-       return init_acpi();
+       /* initialize internal data structure etc. */
+       return acpiphp_glue_init();
 }
 
 
index a951c22921d165bb1553de35cb68ffc95ddc3abf..270fdbadc19c93e97b62db8049a1542a748b1223 100644 (file)
@@ -325,8 +325,8 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge)
                return;
        }
 
-       /* install notify handler */
-       if (bridge->type != BRIDGE_TYPE_HOST) {
+       /* install notify handler for P2P bridges */
+       if (!pci_is_root_bus(bridge->pci_bus)) {
                if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
                        status = acpi_remove_notify_handler(bridge->func->handle,
                                                ACPI_SYSTEM_NOTIFY,
@@ -369,27 +369,12 @@ static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle
 static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge)
 {
        acpi_handle dummy_handle;
+       struct acpiphp_func *func;
 
        if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
-                                       "_STA", &dummy_handle)))
-               bridge->flags |= BRIDGE_HAS_STA;
-
-       if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
-                                       "_EJ0", &dummy_handle)))
+                                       "_EJ0", &dummy_handle))) {
                bridge->flags |= BRIDGE_HAS_EJ0;
 
-       if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
-                                       "_PS0", &dummy_handle)))
-               bridge->flags |= BRIDGE_HAS_PS0;
-
-       if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
-                                       "_PS3", &dummy_handle)))
-               bridge->flags |= BRIDGE_HAS_PS3;
-
-       /* is this ejectable p2p bridge? */
-       if (bridge->flags & BRIDGE_HAS_EJ0) {
-               struct acpiphp_func *func;
-
                dbg("found ejectable p2p bridge\n");
 
                /* make link between PCI bridge and PCI function */
@@ -412,7 +397,6 @@ static void add_host_bridge(struct acpi_pci_root *root)
        if (bridge == NULL)
                return;
 
-       bridge->type = BRIDGE_TYPE_HOST;
        bridge->handle = handle;
 
        bridge->pci_bus = root->bus;
@@ -432,7 +416,6 @@ static void add_p2p_bridge(acpi_handle *handle)
                return;
        }
 
-       bridge->type = BRIDGE_TYPE_P2P;
        bridge->handle = handle;
        config_p2p_bridge_flags(bridge);
 
@@ -543,13 +526,15 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
        acpi_status status;
        acpi_handle handle = bridge->handle;
 
-       status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+       if (!pci_is_root_bus(bridge->pci_bus)) {
+               status = acpi_remove_notify_handler(handle,
+                                           ACPI_SYSTEM_NOTIFY,
                                            handle_hotplug_event_bridge);
-       if (ACPI_FAILURE(status))
-               err("failed to remove notify handler\n");
+               if (ACPI_FAILURE(status))
+                       err("failed to remove notify handler\n");
+       }
 
-       if ((bridge->type != BRIDGE_TYPE_HOST) &&
-           ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)) {
+       if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
                status = acpi_install_notify_handler(bridge->func->handle,
                                                ACPI_SYSTEM_NOTIFY,
                                                handle_hotplug_event_func,
@@ -630,9 +615,6 @@ static void remove_bridge(struct acpi_pci_root *root)
        bridge = acpiphp_handle_to_bridge(handle);
        if (bridge)
                cleanup_bridge(bridge);
-       else
-               acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-                                          handle_hotplug_event_bridge);
 }
 
 static int power_on_slot(struct acpiphp_slot *slot)
@@ -793,6 +775,29 @@ static void acpiphp_set_acpi_region(struct acpiphp_slot *slot)
        }
 }
 
+static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev)
+{
+       struct acpiphp_func *func;
+
+       if (!dev->subordinate)
+               return;
+
+       /* quirk, or pcie could set it already */
+       if (dev->is_hotplug_bridge)
+               return;
+
+       if (PCI_SLOT(dev->devfn) != slot->device)
+               return;
+
+       list_for_each_entry(func, &slot->funcs, sibling) {
+               if (PCI_FUNC(dev->devfn) == func->function) {
+                       /* check if this bridge has ejectable slots */
+                       if ((detect_ejectable_slots(func->handle) > 0))
+                               dev->is_hotplug_bridge = 1;
+                       break;
+               }
+       }
+}
 /**
  * enable_device - enable, configure a slot
  * @slot: slot to be enabled
@@ -812,6 +817,9 @@ static int __ref enable_device(struct acpiphp_slot *slot)
        if (slot->flags & SLOT_ENABLED)
                goto err_exit;
 
+       list_for_each_entry(func, &slot->funcs, sibling)
+               acpiphp_bus_add(func);
+
        num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0));
        if (num == 0) {
                /* Maybe only part of funcs are added. */
@@ -827,15 +835,14 @@ static int __ref enable_device(struct acpiphp_slot *slot)
                        if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
                            dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
                                max = pci_scan_bridge(bus, dev, max, pass);
-                               if (pass && dev->subordinate)
+                               if (pass && dev->subordinate) {
+                                       check_hotplug_bridge(slot, dev);
                                        pci_bus_size_bridges(dev->subordinate);
+                               }
                        }
                }
        }
 
-       list_for_each_entry(func, &slot->funcs, sibling)
-               acpiphp_bus_add(func);
-
        pci_bus_assign_resources(bus);
        acpiphp_sanitize_bus(bus);
        acpiphp_set_hpp_values(bus);
@@ -1093,69 +1100,10 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)
        }
 }
 
-/* Program resources in newly inserted bridge */
-static int acpiphp_configure_bridge (acpi_handle handle)
-{
-       struct pci_bus *bus;
-
-       if (acpi_is_root_bridge(handle)) {
-               struct acpi_pci_root *root = acpi_pci_find_root(handle);
-               bus = root->bus;
-       } else {
-               struct pci_dev *pdev = acpi_get_pci_dev(handle);
-               bus = pdev->subordinate;
-               pci_dev_put(pdev);
-       }
-
-       pci_bus_size_bridges(bus);
-       pci_bus_assign_resources(bus);
-       acpiphp_sanitize_bus(bus);
-       acpiphp_set_hpp_values(bus);
-       pci_enable_bridges(bus);
-       return 0;
-}
-
-static void handle_bridge_insertion(acpi_handle handle, u32 type)
-{
-       struct acpi_device *device;
-
-       if ((type != ACPI_NOTIFY_BUS_CHECK) &&
-                       (type != ACPI_NOTIFY_DEVICE_CHECK)) {
-               err("unexpected notification type %d\n", type);
-               return;
-       }
-
-       if (acpi_bus_scan(handle)) {
-               err("cannot add bridge to acpi list\n");
-               return;
-       }
-       if (acpi_bus_get_device(handle, &device)) {
-               err("ACPI device object missing\n");
-               return;
-       }
-       if (!acpiphp_configure_bridge(handle))
-               add_bridge(handle);
-       else
-               err("cannot configure and start bridge\n");
-
-}
-
 /*
  * ACPI event handlers
  */
 
-static acpi_status
-count_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-       int *count = (int *)context;
-       struct acpiphp_bridge *bridge;
-
-       bridge = acpiphp_handle_to_bridge(handle);
-       if (bridge)
-               (*count)++;
-       return AE_OK ;
-}
-
 static acpi_status
 check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
@@ -1174,83 +1122,33 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
        return AE_OK ;
 }
 
-struct acpiphp_hp_work {
-       struct work_struct work;
-       acpi_handle handle;
-       u32 type;
-       void *context;
-};
-
-static void alloc_acpiphp_hp_work(acpi_handle handle, u32 type,
-                                 void *context,
-                                 void (*func)(struct work_struct *work))
-{
-       struct acpiphp_hp_work *hp_work;
-       int ret;
-
-       hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL);
-       if (!hp_work)
-               return;
-
-       hp_work->handle = handle;
-       hp_work->type = type;
-       hp_work->context = context;
-
-       INIT_WORK(&hp_work->work, func);
-       ret = queue_work(kacpi_hotplug_wq, &hp_work->work);
-       if (!ret)
-               kfree(hp_work);
-}
-
 static void _handle_hotplug_event_bridge(struct work_struct *work)
 {
        struct acpiphp_bridge *bridge;
        char objname[64];
        struct acpi_buffer buffer = { .length = sizeof(objname),
                                      .pointer = objname };
-       struct acpi_device *device;
-       int num_sub_bridges = 0;
-       struct acpiphp_hp_work *hp_work;
+       struct acpi_hp_work *hp_work;
        acpi_handle handle;
        u32 type;
 
-       hp_work = container_of(work, struct acpiphp_hp_work, work);
+       hp_work = container_of(work, struct acpi_hp_work, work);
        handle = hp_work->handle;
        type = hp_work->type;
+       bridge = (struct acpiphp_bridge *)hp_work->context;
 
        acpi_scan_lock_acquire();
 
-       if (acpi_bus_get_device(handle, &device)) {
-               /* This bridge must have just been physically inserted */
-               handle_bridge_insertion(handle, type);
-               goto out;
-       }
-
-       bridge = acpiphp_handle_to_bridge(handle);
-       if (type == ACPI_NOTIFY_BUS_CHECK) {
-               acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX,
-                       count_sub_bridges, NULL, &num_sub_bridges, NULL);
-       }
-
-       if (!bridge && !num_sub_bridges) {
-               err("cannot get bridge info\n");
-               goto out;
-       }
-
        acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 
        switch (type) {
        case ACPI_NOTIFY_BUS_CHECK:
                /* bus re-enumerate */
                dbg("%s: Bus check notify on %s\n", __func__, objname);
-               if (bridge) {
-                       dbg("%s: re-enumerating slots under %s\n",
-                               __func__, objname);
-                       acpiphp_check_bridge(bridge);
-               }
-               if (num_sub_bridges)
-                       acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
-                               ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL);
+               dbg("%s: re-enumerating slots under %s\n", __func__, objname);
+               acpiphp_check_bridge(bridge);
+               acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
+                       ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL);
                break;
 
        case ACPI_NOTIFY_DEVICE_CHECK:
@@ -1267,8 +1165,7 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
        case ACPI_NOTIFY_EJECT_REQUEST:
                /* request device eject */
                dbg("%s: Device eject notify on %s\n", __func__, objname);
-               if ((bridge->type != BRIDGE_TYPE_HOST) &&
-                   (bridge->flags & BRIDGE_HAS_EJ0)) {
+               if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
                        struct acpiphp_slot *slot;
                        slot = bridge->func->slot;
                        if (!acpiphp_disable_slot(slot))
@@ -1296,7 +1193,6 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
                break;
        }
 
-out:
        acpi_scan_lock_release();
        kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
 }
@@ -1320,8 +1216,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type,
         * For now just re-add this work to the kacpi_hotplug_wq so we
         * don't deadlock on hotplug actions.
         */
-       alloc_acpiphp_hp_work(handle, type, context,
-                             _handle_hotplug_event_bridge);
+       alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge);
 }
 
 static void _handle_hotplug_event_func(struct work_struct *work)
@@ -1330,22 +1225,19 @@ static void _handle_hotplug_event_func(struct work_struct *work)
        char objname[64];
        struct acpi_buffer buffer = { .length = sizeof(objname),
                                      .pointer = objname };
-       struct acpiphp_hp_work *hp_work;
+       struct acpi_hp_work *hp_work;
        acpi_handle handle;
        u32 type;
-       void *context;
 
-       hp_work = container_of(work, struct acpiphp_hp_work, work);
+       hp_work = container_of(work, struct acpi_hp_work, work);
        handle = hp_work->handle;
        type = hp_work->type;
-       context = hp_work->context;
-
-       acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
-
-       func = (struct acpiphp_func *)context;
+       func = (struct acpiphp_func *)hp_work->context;
 
        acpi_scan_lock_acquire();
 
+       acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+
        switch (type) {
        case ACPI_NOTIFY_BUS_CHECK:
                /* bus re-enumerate */
@@ -1399,23 +1291,7 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type,
         * For now just re-add this work to the kacpi_hotplug_wq so we
         * don't deadlock on hotplug actions.
         */
-       alloc_acpiphp_hp_work(handle, type, context,
-                             _handle_hotplug_event_func);
-}
-
-static acpi_status
-find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-       int *count = (int *)context;
-
-       if (!acpi_is_root_bridge(handle))
-               return AE_OK;
-
-       (*count)++;
-       acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-                                   handle_hotplug_event_bridge, NULL);
-
-       return AE_OK ;
+       alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_func);
 }
 
 static struct acpi_pci_driver acpi_pci_hp_driver = {
@@ -1428,15 +1304,7 @@ static struct acpi_pci_driver acpi_pci_hp_driver = {
  */
 int __init acpiphp_glue_init(void)
 {
-       int num = 0;
-
-       acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-                       ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL);
-
-       if (num <= 0)
-               return -1;
-       else
-               acpi_pci_register_driver(&acpi_pci_hp_driver);
+       acpi_pci_register_driver(&acpi_pci_hp_driver);
 
        return 0;
 }
@@ -1452,28 +1320,6 @@ void  acpiphp_glue_exit(void)
        acpi_pci_unregister_driver(&acpi_pci_hp_driver);
 }
 
-
-/**
- * acpiphp_get_num_slots - count number of slots in a system
- */
-int __init acpiphp_get_num_slots(void)
-{
-       struct acpiphp_bridge *bridge;
-       int num_slots = 0;
-
-       list_for_each_entry(bridge, &bridge_list, list) {
-               dbg("Bus %04x:%02x has %d slot%s\n",
-                               pci_domain_nr(bridge->pci_bus),
-                               bridge->pci_bus->number, bridge->nr_slots,
-                               bridge->nr_slots == 1 ? "" : "s");
-               num_slots += bridge->nr_slots;
-       }
-
-       dbg("Total %d slots\n", num_slots);
-       return num_slots;
-}
-
-
 /**
  * acpiphp_enable_slot - power on slot
  * @slot: ACPI PHP slot
index dcc75c78544324d9c761a71c0b4d392243a9446c..d8add34177f2cfa2725972bb3d57308d61b603df 100644 (file)
@@ -252,8 +252,8 @@ int cpci_led_off(struct slot* slot)
 
 int __ref cpci_configure_slot(struct slot *slot)
 {
+       struct pci_dev *dev;
        struct pci_bus *parent;
-       int fn;
 
        dbg("%s - enter", __func__);
 
@@ -282,18 +282,13 @@ int __ref cpci_configure_slot(struct slot *slot)
        }
        parent = slot->dev->bus;
 
-       for (fn = 0; fn < 8; fn++) {
-               struct pci_dev *dev;
-
-               dev = pci_get_slot(parent,
-                                  PCI_DEVFN(PCI_SLOT(slot->devfn), fn));
-               if (!dev)
+       list_for_each_entry(dev, &parent->devices, bus_list)
+               if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn))
                        continue;
                if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
                    (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
                        pci_hp_add_bridge(dev);
-               pci_dev_put(dev);
-       }
+
 
        pci_assign_unassigned_bridge_resources(parent->self);
 
@@ -305,8 +300,7 @@ int __ref cpci_configure_slot(struct slot *slot)
 
 int cpci_unconfigure_slot(struct slot* slot)
 {
-       int i;
-       struct pci_dev *dev;
+       struct pci_dev *dev, *temp;
 
        dbg("%s - enter", __func__);
        if (!slot->dev) {
@@ -314,13 +308,12 @@ int cpci_unconfigure_slot(struct slot* slot)
                return -ENODEV;
        }
 
-       for (i = 0; i < 8; i++) {
-               dev = pci_get_slot(slot->bus,
-                                   PCI_DEVFN(PCI_SLOT(slot->devfn), i));
-               if (dev) {
-                       pci_stop_and_remove_bus_device(dev);
-                       pci_dev_put(dev);
-               }
+       list_for_each_entry_safe(dev, temp, &slot->bus->devices, bus_list) {
+               if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn))
+                       continue;
+               pci_dev_get(dev);
+               pci_stop_and_remove_bus_device(dev);
+               pci_dev_put(dev);
        }
        pci_dev_put(slot->dev);
        slot->dev = NULL;
index 36112fe212d34139cca7cd54c32fc969feaeaaee..d282019cda5fad4c3e4583eab78fe72017648cde 100644 (file)
@@ -1900,8 +1900,7 @@ static void interrupt_event_handler(struct controller *ctrl)
                                        dbg("power fault\n");
                                } else {
                                        /* refresh notification */
-                                       if (p_slot)
-                                               update_slot_info(ctrl, p_slot);
+                                       update_slot_info(ctrl, p_slot);
                                }
 
                                ctrl->event_queue[loop].event_type = 0;
@@ -2520,44 +2519,28 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
 
                /* If we have IO resources copy them and fill in the bridge's
                 * IO range registers */
-               if (io_node) {
-                       memcpy(hold_IO_node, io_node, sizeof(struct pci_resource));
-                       io_node->next = NULL;
+               memcpy(hold_IO_node, io_node, sizeof(struct pci_resource));
+               io_node->next = NULL;
 
-                       /* set IO base and Limit registers */
-                       temp_byte = io_node->base >> 8;
-                       rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_BASE, temp_byte);
+               /* set IO base and Limit registers */
+               temp_byte = io_node->base >> 8;
+               rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_BASE, temp_byte);
 
-                       temp_byte = (io_node->base + io_node->length - 1) >> 8;
-                       rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
-               } else {
-                       kfree(hold_IO_node);
-                       hold_IO_node = NULL;
-               }
-
-               /* If we have memory resources copy them and fill in the
-                * bridge's memory range registers.  Otherwise, fill in the
-                * range registers with values that disable them. */
-               if (mem_node) {
-                       memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource));
-                       mem_node->next = NULL;
-
-                       /* set Mem base and Limit registers */
-                       temp_word = mem_node->base >> 16;
-                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+               temp_byte = (io_node->base + io_node->length - 1) >> 8;
+               rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
 
-                       temp_word = (mem_node->base + mem_node->length - 1) >> 16;
-                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
-               } else {
-                       temp_word = 0xFFFF;
-                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+               /* Copy the memory resources and fill in the bridge's memory
+                * range registers.
+                */
+               memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource));
+               mem_node->next = NULL;
 
-                       temp_word = 0x0000;
-                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+               /* set Mem base and Limit registers */
+               temp_word = mem_node->base >> 16;
+               rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
 
-                       kfree(hold_mem_node);
-                       hold_mem_node = NULL;
-               }
+               temp_word = (mem_node->base + mem_node->length - 1) >> 16;
+               rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
 
                memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource));
                p_mem_node->next = NULL;
@@ -2627,7 +2610,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
                /* Return unused bus resources
                 * First use the temporary node to store information for
                 * the board */
-               if (hold_bus_node && bus_node && temp_resources.bus_head) {
+               if (bus_node && temp_resources.bus_head) {
                        hold_bus_node->length = bus_node->base - hold_bus_node->base;
 
                        hold_bus_node->next = func->bus_head;
@@ -2751,7 +2734,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
                }
                /* If we have prefetchable memory space available and there
                 * is some left at the end, return the unused portion */
-               if (hold_p_mem_node && temp_resources.p_mem_head) {
+               if (temp_resources.p_mem_head) {
                        p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head),
                                                                  &hold_p_mem_node, 0x100000);
 
index 939bd1d4b5b138b8f8bbe319007973579a6c39df..7d72c5e2eba90cc98cb233142ba6baadd778d9ae 100644 (file)
@@ -293,7 +293,6 @@ static void pciehp_remove(struct pcie_device *dev)
 #ifdef CONFIG_PM
 static int pciehp_suspend (struct pcie_device *dev)
 {
-       dev_info(&dev->device, "%s ENTRY\n", __func__);
        return 0;
 }
 
@@ -303,7 +302,6 @@ static int pciehp_resume (struct pcie_device *dev)
        struct slot *slot;
        u8 status;
 
-       dev_info(&dev->device, "%s ENTRY\n", __func__);
        ctrl = get_service_data(dev);
 
        /* reinitialize the chipset's event detection logic */
index 09cecaf450c5bebb3a56410f9bf3871d120019bb..aac7a40e4a4ac9205441d9c6918a080531117571 100644 (file)
@@ -39,7 +39,7 @@ int pciehp_configure_device(struct slot *p_slot)
        struct pci_dev *dev;
        struct pci_dev *bridge = p_slot->ctrl->pcie->port;
        struct pci_bus *parent = bridge->subordinate;
-       int num, fn;
+       int num;
        struct controller *ctrl = p_slot->ctrl;
 
        dev = pci_get_slot(parent, PCI_DEVFN(0, 0));
@@ -57,28 +57,18 @@ int pciehp_configure_device(struct slot *p_slot)
                return -ENODEV;
        }
 
-       for (fn = 0; fn < 8; fn++) {
-               dev = pci_get_slot(parent, PCI_DEVFN(0, fn));
-               if (!dev)
-                       continue;
+       list_for_each_entry(dev, &parent->devices, bus_list)
                if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
                                (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
                        pci_hp_add_bridge(dev);
-               pci_dev_put(dev);
-       }
 
        pci_assign_unassigned_bridge_resources(bridge);
 
-       for (fn = 0; fn < 8; fn++) {
-               dev = pci_get_slot(parent, PCI_DEVFN(0, fn));
-               if (!dev)
+       list_for_each_entry(dev, &parent->devices, bus_list) {
+               if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
                        continue;
-               if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
-                       pci_dev_put(dev);
-                       continue;
-               }
+
                pci_configure_slot(dev);
-               pci_dev_put(dev);
        }
 
        pci_bus_add_devices(parent);
@@ -89,9 +79,9 @@ int pciehp_configure_device(struct slot *p_slot)
 int pciehp_unconfigure_device(struct slot *p_slot)
 {
        int ret, rc = 0;
-       int j;
        u8 bctl = 0;
        u8 presence = 0;
+       struct pci_dev *dev, *temp;
        struct pci_bus *parent = p_slot->ctrl->pcie->port->subordinate;
        u16 command;
        struct controller *ctrl = p_slot->ctrl;
@@ -102,33 +92,31 @@ int pciehp_unconfigure_device(struct slot *p_slot)
        if (ret)
                presence = 0;
 
-       for (j = 0; j < 8; j++) {
-               struct pci_dev *temp = pci_get_slot(parent, PCI_DEVFN(0, j));
-               if (!temp)
-                       continue;
-               if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
-                       pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
+       list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) {
+               pci_dev_get(dev);
+               if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
+                       pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bctl);
                        if (bctl & PCI_BRIDGE_CTL_VGA) {
                                ctrl_err(ctrl,
                                         "Cannot remove display device %s\n",
-                                        pci_name(temp));
-                               pci_dev_put(temp);
+                                        pci_name(dev));
+                               pci_dev_put(dev);
                                rc = -EINVAL;
                                break;
                        }
                }
-               pci_stop_and_remove_bus_device(temp);
+               pci_stop_and_remove_bus_device(dev);
                /*
                 * Ensure that no new Requests will be generated from
                 * the device.
                 */
                if (presence) {
-                       pci_read_config_word(temp, PCI_COMMAND, &command);
+                       pci_read_config_word(dev, PCI_COMMAND, &command);
                        command &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
                        command |= PCI_COMMAND_INTX_DISABLE;
-                       pci_write_config_word(temp, PCI_COMMAND, command);
+                       pci_write_config_word(dev, PCI_COMMAND, command);
                }
-               pci_dev_put(temp);
+               pci_dev_put(dev);
        }
 
        return rc;
index 574421bc2fa63bd4e407cafbe2ecd8ca1d22d780..b2781dfe60e9e3cbc79095de46b96f8421958275 100644 (file)
@@ -334,7 +334,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
        struct slot *slot = bss_hotplug_slot->private;
        struct pci_bus *new_bus = NULL;
        struct pci_dev *dev;
-       int func, num_funcs;
+       int num_funcs;
        int new_ppb = 0;
        int rc;
        char *ssdt = NULL;
@@ -381,29 +381,26 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
         * to the Linux PCI interface and tell the drivers
         * about them.
         */
-       for (func = 0; func < num_funcs;  func++) {
-               dev = pci_get_slot(slot->pci_bus,
-                                  PCI_DEVFN(slot->device_num + 1,
-                                            PCI_FUNC(func)));
-               if (dev) {
-                       /* Need to do slot fixup on PPB before fixup of children
-                        * (PPB's pcidev_info needs to be in pcidev_info list
-                        * before child's SN_PCIDEV_INFO() call to setup
-                        * pdi_host_pcidev_info).
-                        */
-                       pcibios_fixup_device_resources(dev);
-                       if (SN_ACPI_BASE_SUPPORT())
-                               sn_acpi_slot_fixup(dev);
-                       else
-                               sn_io_slot_fixup(dev);
-                       if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-                               pci_hp_add_bridge(dev);
-                               if (dev->subordinate) {
-                                       new_bus = dev->subordinate;
-                                       new_ppb = 1;
-                               }
+       list_for_each_entry(dev, &slot->pci_bus->devices, bus_list) {
+               if (PCI_SLOT(dev->devfn) != slot->device_num + 1)
+                       continue;
+
+               /* Need to do slot fixup on PPB before fixup of children
+                * (PPB's pcidev_info needs to be in pcidev_info list
+                * before child's SN_PCIDEV_INFO() call to setup
+                * pdi_host_pcidev_info).
+                */
+               pcibios_fixup_device_resources(dev);
+               if (SN_ACPI_BASE_SUPPORT())
+                       sn_acpi_slot_fixup(dev);
+               else
+                       sn_io_slot_fixup(dev);
+               if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+                       pci_hp_add_bridge(dev);
+                       if (dev->subordinate) {
+                               new_bus = dev->subordinate;
+                               new_ppb = 1;
                        }
-                       pci_dev_put(dev);
                }
        }
 
@@ -483,8 +480,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
 static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
 {
        struct slot *slot = bss_hotplug_slot->private;
-       struct pci_dev *dev;
-       int func;
+       struct pci_dev *dev, *temp;
        int rc;
        acpi_owner_id ssdt_id = 0;
 
@@ -545,15 +541,14 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
        }
 
        /* Free the SN resources assigned to the Linux device.*/
-       for (func = 0; func < 8;  func++) {
-               dev = pci_get_slot(slot->pci_bus,
-                                  PCI_DEVFN(slot->device_num + 1,
-                                            PCI_FUNC(func)));
-               if (dev) {
-                       sn_bus_free_data(dev);
-                       pci_stop_and_remove_bus_device(dev);
-                       pci_dev_put(dev);
-               }
+       list_for_each_entry_safe(dev, temp, &slot->pci_bus->devices, bus_list) {
+               if (PCI_SLOT(dev->devfn) != slot->device_num + 1)
+                       continue;
+
+               pci_dev_get(dev);
+               sn_bus_free_data(dev);
+               pci_stop_and_remove_bus_device(dev);
+               pci_dev_put(dev);
        }
 
        /* Remove the SSDT for the slot from the ACPI namespace */
index c627ed9957d1c32fc1768b6a7e51e5cf18a9cb6f..b0e83132542e4ddb52482f899e0d0b1c29a776b2 100644 (file)
@@ -40,7 +40,7 @@ int __ref shpchp_configure_device(struct slot *p_slot)
        struct controller *ctrl = p_slot->ctrl;
        struct pci_dev *bridge = ctrl->pci_dev;
        struct pci_bus *parent = bridge->subordinate;
-       int num, fn;
+       int num;
 
        dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
        if (dev) {
@@ -57,24 +57,20 @@ int __ref shpchp_configure_device(struct slot *p_slot)
                return -ENODEV;
        }
 
-       for (fn = 0; fn < 8; fn++) {
-               dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn));
-               if (!dev)
+       list_for_each_entry(dev, &parent->devices, bus_list) {
+               if (PCI_SLOT(dev->devfn) != p_slot->device)
                        continue;
                if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
                    (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
                        pci_hp_add_bridge(dev);
-               pci_dev_put(dev);
        }
 
        pci_assign_unassigned_bridge_resources(bridge);
 
-       for (fn = 0; fn < 8; fn++) {
-               dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn));
-               if (!dev)
+       list_for_each_entry(dev, &parent->devices, bus_list) {
+               if (PCI_SLOT(dev->devfn) != p_slot->device)
                        continue;
                pci_configure_slot(dev);
-               pci_dev_put(dev);
        }
 
        pci_bus_add_devices(parent);
@@ -85,32 +81,32 @@ int __ref shpchp_configure_device(struct slot *p_slot)
 int shpchp_unconfigure_device(struct slot *p_slot)
 {
        int rc = 0;
-       int j;
        u8 bctl = 0;
        struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
+       struct pci_dev *dev, *temp;
        struct controller *ctrl = p_slot->ctrl;
 
        ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n",
                 __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device);
 
-       for (j = 0; j < 8 ; j++) {
-               struct pci_dev *temp = pci_get_slot(parent,
-                               (p_slot->device << 3) | j);
-               if (!temp)
+       list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) {
+               if (PCI_SLOT(dev->devfn) != p_slot->device)
                        continue;
-               if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-                       pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
+
+               pci_dev_get(dev);
+               if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+                       pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bctl);
                        if (bctl & PCI_BRIDGE_CTL_VGA) {
                                ctrl_err(ctrl,
                                         "Cannot remove display device %s\n",
-                                        pci_name(temp));
-                               pci_dev_put(temp);
+                                        pci_name(dev));
+                               pci_dev_put(dev);
                                rc = -EINVAL;
                                break;
                        }
                }
-               pci_stop_and_remove_bus_device(temp);
-               pci_dev_put(temp);
+               pci_stop_and_remove_bus_device(dev);
+               pci_dev_put(dev);
        }
        return rc;
 }
index c18e5bf444faa693d41c6a9103ef7ab8982b07da..ee599f274f057ed54b2af74cd9c72afee3cb1fbe 100644 (file)
@@ -33,7 +33,6 @@ static inline u8 virtfn_devfn(struct pci_dev *dev, int id)
 
 static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr)
 {
-       int rc;
        struct pci_bus *child;
 
        if (bus->number == busnr)
@@ -48,12 +47,7 @@ static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr)
                return NULL;
 
        pci_bus_insert_busn_res(child, busnr, busnr);
-       child->dev.parent = bus->bridge;
-       rc = pci_bus_add_child(child);
-       if (rc) {
-               pci_remove_bus(child);
-               return NULL;
-       }
+       bus->is_added = 1;
 
        return child;
 }
@@ -123,8 +117,6 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
        virtfn->is_virtfn = 1;
 
        rc = pci_bus_add_device(virtfn);
-       if (rc)
-               goto failed1;
        sprintf(buf, "virtfn%u", id);
        rc = sysfs_create_link(&dev->dev.kobj, &virtfn->dev.kobj, buf);
        if (rc)
index e407c61559ca0f09c452b9f130a07ac93ad3dba6..39c937f9b426ef392e3820ee2c7f69e128da403e 100644 (file)
@@ -302,48 +302,11 @@ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
        return 0;
 }
 
-static int acpi_pci_find_root_bridge(struct device *dev, acpi_handle *handle)
-{
-       int num;
-       unsigned int seg, bus;
-
-       /*
-        * The string should be the same as root bridge's name
-        * Please look at 'pci_scan_bus_parented'
-        */
-       num = sscanf(dev_name(dev), "pci%04x:%02x", &seg, &bus);
-       if (num != 2)
-               return -ENODEV;
-       *handle = acpi_get_pci_rootbridge_handle(seg, bus);
-       if (!*handle)
-               return -ENODEV;
-       return 0;
-}
-
 static void pci_acpi_setup(struct device *dev)
 {
        struct pci_dev *pci_dev = to_pci_dev(dev);
        acpi_handle handle = ACPI_HANDLE(dev);
        struct acpi_device *adev;
-       acpi_status status;
-       acpi_handle dummy;
-
-       /*
-        * Evaluate and parse _PRT, if exists.  This code allows parsing of
-        * _PRT objects within the scope of non-bridge devices.  Note that
-        * _PRTs within the scope of a PCI bridge assume the bridge's
-        * subordinate bus number.
-        *
-        * TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
-        */
-       status = acpi_get_handle(handle, METHOD_NAME__PRT, &dummy);
-       if (ACPI_SUCCESS(status)) {
-               unsigned char bus;
-
-               bus = pci_dev->subordinate ?
-                       pci_dev->subordinate->number : pci_dev->bus->number;
-               acpi_pci_irq_add_prt(handle, pci_domain_nr(pci_dev->bus), bus);
-       }
 
        if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
                return;
@@ -358,7 +321,6 @@ static void pci_acpi_setup(struct device *dev)
 
 static void pci_acpi_cleanup(struct device *dev)
 {
-       struct pci_dev *pci_dev = to_pci_dev(dev);
        acpi_handle handle = ACPI_HANDLE(dev);
        struct acpi_device *adev;
 
@@ -367,16 +329,11 @@ static void pci_acpi_cleanup(struct device *dev)
                device_set_run_wake(dev, false);
                pci_acpi_remove_pm_notifier(adev);
        }
-
-       if (pci_dev->subordinate)
-               acpi_pci_irq_del_prt(pci_domain_nr(pci_dev->bus),
-                                    pci_dev->subordinate->number);
 }
 
 static struct acpi_bus_type acpi_pci_bus = {
        .bus = &pci_bus_type,
        .find_device = acpi_pci_find_device,
-       .find_bridge = acpi_pci_find_root_bridge,
        .setup = pci_acpi_setup,
        .cleanup = pci_acpi_cleanup,
 };
index f79cbcd3944bf5e61e76a96022331a665e63f93e..1fa1e482a99976d36d8e91b2affee58af3bda693 100644 (file)
@@ -392,7 +392,7 @@ static void pci_device_shutdown(struct device *dev)
         * Turn off Bus Master bit on the device to tell it to not
         * continue to do DMA
         */
-       pci_disable_device(pci_dev);
+       pci_clear_master(pci_dev);
 }
 
 #ifdef CONFIG_PM
@@ -628,6 +628,7 @@ static int pci_pm_suspend(struct device *dev)
                goto Fixup;
        }
 
+       pci_dev->state_saved = false;
        if (pm->suspend) {
                pci_power_t prev = pci_dev->current_state;
                int error;
@@ -774,6 +775,7 @@ static int pci_pm_freeze(struct device *dev)
                return 0;
        }
 
+       pci_dev->state_saved = false;
        if (pm->freeze) {
                int error;
 
@@ -862,6 +864,7 @@ static int pci_pm_poweroff(struct device *dev)
                goto Fixup;
        }
 
+       pci_dev->state_saved = false;
        if (pm->poweroff) {
                int error;
 
@@ -987,6 +990,7 @@ static int pci_pm_runtime_suspend(struct device *dev)
        if (!pm || !pm->runtime_suspend)
                return -ENOSYS;
 
+       pci_dev->state_saved = false;
        pci_dev->no_d3cold = false;
        error = pm->runtime_suspend(dev);
        suspend_report_result(pm->runtime_suspend, error);
@@ -1186,9 +1190,13 @@ pci_dev_driver(const struct pci_dev *dev)
 static int pci_bus_match(struct device *dev, struct device_driver *drv)
 {
        struct pci_dev *pci_dev = to_pci_dev(dev);
-       struct pci_driver *pci_drv = to_pci_driver(drv);
+       struct pci_driver *pci_drv;
        const struct pci_device_id *found_id;
 
+       if (!pci_dev->match_driver)
+               return 0;
+
+       pci_drv = to_pci_driver(drv);
        found_id = pci_match_device(pci_drv, pci_dev);
        if (found_id)
                return 1;
index 0c4f641b7be169841e0ec68bc7e7642fc6efaaf4..924e4665bd57a940661452a477667f66f4b3a4d3 100644 (file)
@@ -1151,8 +1151,7 @@ int pci_reenable_device(struct pci_dev *dev)
        return 0;
 }
 
-static int __pci_enable_device_flags(struct pci_dev *dev,
-                                    resource_size_t flags)
+static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags)
 {
        int err;
        int i, bars = 0;
@@ -1169,7 +1168,7 @@ static int __pci_enable_device_flags(struct pci_dev *dev,
                dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
        }
 
-       if (atomic_add_return(1, &dev->enable_cnt) > 1)
+       if (atomic_inc_return(&dev->enable_cnt) > 1)
                return 0;               /* already enabled */
 
        /* only skip sriov related */
@@ -1196,7 +1195,7 @@ static int __pci_enable_device_flags(struct pci_dev *dev,
  */
 int pci_enable_device_io(struct pci_dev *dev)
 {
-       return __pci_enable_device_flags(dev, IORESOURCE_IO);
+       return pci_enable_device_flags(dev, IORESOURCE_IO);
 }
 
 /**
@@ -1209,7 +1208,7 @@ int pci_enable_device_io(struct pci_dev *dev)
  */
 int pci_enable_device_mem(struct pci_dev *dev)
 {
-       return __pci_enable_device_flags(dev, IORESOURCE_MEM);
+       return pci_enable_device_flags(dev, IORESOURCE_MEM);
 }
 
 /**
@@ -1225,7 +1224,7 @@ int pci_enable_device_mem(struct pci_dev *dev)
  */
 int pci_enable_device(struct pci_dev *dev)
 {
-       return __pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO);
+       return pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO);
 }
 
 /*
@@ -1396,7 +1395,10 @@ pci_disable_device(struct pci_dev *dev)
        if (dr)
                dr->enabled = 0;
 
-       if (atomic_sub_return(1, &dev->enable_cnt) != 0)
+       dev_WARN_ONCE(&dev->dev, atomic_read(&dev->enable_cnt) <= 0,
+                     "disabling already-disabled device");
+
+       if (atomic_dec_return(&dev->enable_cnt) != 0)
                return;
 
        do_pci_disable_device(dev);
@@ -2043,10 +2045,13 @@ void pci_free_cap_save_buffers(struct pci_dev *dev)
 }
 
 /**
- * pci_enable_ari - enable ARI forwarding if hardware support it
+ * pci_configure_ari - enable or disable ARI forwarding
  * @dev: the PCI device
+ *
+ * If @dev and its upstream bridge both support ARI, enable ARI in the
+ * bridge.  Otherwise, disable ARI in the bridge.
  */
-void pci_enable_ari(struct pci_dev *dev)
+void pci_configure_ari(struct pci_dev *dev)
 {
        u32 cap;
        struct pci_dev *bridge;
@@ -2054,9 +2059,6 @@ void pci_enable_ari(struct pci_dev *dev)
        if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn)
                return;
 
-       if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI))
-               return;
-
        bridge = dev->bus->self;
        if (!bridge)
                return;
@@ -2065,8 +2067,15 @@ void pci_enable_ari(struct pci_dev *dev)
        if (!(cap & PCI_EXP_DEVCAP2_ARI))
                return;
 
-       pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_ARI);
-       bridge->ari_enabled = 1;
+       if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI)) {
+               pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2,
+                                        PCI_EXP_DEVCTL2_ARI);
+               bridge->ari_enabled = 1;
+       } else {
+               pcie_capability_clear_word(bridge, PCI_EXP_DEVCTL2,
+                                          PCI_EXP_DEVCTL2_ARI);
+               bridge->ari_enabled = 0;
+       }
 }
 
 /**
@@ -3742,18 +3751,6 @@ resource_size_t pci_specified_resource_alignment(struct pci_dev *dev)
        return align;
 }
 
-/**
- * pci_is_reassigndev - check if specified PCI is target device to reassign
- * @dev: the PCI device to check
- *
- * RETURNS: non-zero for PCI device is a target device to reassign,
- *          or zero is not.
- */
-int pci_is_reassigndev(struct pci_dev *dev)
-{
-       return (pci_specified_resource_alignment(dev) != 0);
-}
-
 /*
  * This function disables memory decoding and releases memory resources
  * of the device specified by kernel's boot parameter 'pci=resource_alignment='.
@@ -3768,7 +3765,9 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
        resource_size_t align, size;
        u16 command;
 
-       if (!pci_is_reassigndev(dev))
+       /* check if specified PCI is target device to reassign */
+       align = pci_specified_resource_alignment(dev);
+       if (!align)
                return;
 
        if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL &&
@@ -3784,7 +3783,6 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
        command &= ~PCI_COMMAND_MEMORY;
        pci_write_config_word(dev, PCI_COMMAND, command);
 
-       align = pci_specified_resource_alignment(dev);
        for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) {
                r = &dev->resource[i];
                if (!(r->flags & IORESOURCE_MEM))
index adfd172c5b9b53ea1797af3d10d7a958f844d777..7346ee68f47d198ce67df5a1445cef9203556b0b 100644 (file)
@@ -203,8 +203,8 @@ extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                                struct resource *res, unsigned int reg);
 extern int pci_resource_bar(struct pci_dev *dev, int resno,
                            enum pci_bar_type *type);
-extern int pci_bus_add_child(struct pci_bus *bus);
-extern void pci_enable_ari(struct pci_dev *dev);
+extern void pci_configure_ari(struct pci_dev *dev);
+
 /**
  * pci_ari_enabled - query ARI forwarding status
  * @bus: the PCI bus
index 8474b6a4fc9bb714e7ab85cf539353fd151b8125..d320df6375a2c807f8a45a8badc247bf16a956bf 100644 (file)
@@ -556,6 +556,9 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
        struct pcie_link_state *link;
        int blacklist = !!pcie_aspm_sanity_check(pdev);
 
+       if (!aspm_support_enabled)
+               return;
+
        if (!pci_is_pcie(pdev) || pdev->link_state)
                return;
        if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT &&
@@ -634,10 +637,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
        struct pci_dev *parent = pdev->bus->self;
        struct pcie_link_state *link, *root, *parent_link;
 
-       if (!pci_is_pcie(pdev) || !parent || !parent->link_state)
-               return;
-       if ((pci_pcie_type(parent) != PCI_EXP_TYPE_ROOT_PORT) &&
-           (pci_pcie_type(parent) != PCI_EXP_TYPE_DOWNSTREAM))
+       if (!parent || !parent->link_state)
                return;
 
        down_read(&pci_bus_sem);
index b42133afca985659f6e9dde41a99ce2a05808a7b..31063ac3099234941e0924e66e2fb4c277deee6d 100644 (file)
@@ -272,7 +272,7 @@ static int get_port_device_capability(struct pci_dev *dev)
 
        /* Hot-Plug Capable */
        if ((cap_mask & PCIE_PORT_SERVICE_HP) &&
-           dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT) {
+           pcie_caps_reg(dev) & PCI_EXP_FLAGS_SLOT) {
                pcie_capability_read_dword(dev, PCI_EXP_SLTCAP, &reg32);
                if (reg32 & PCI_EXP_SLTCAP_HPC) {
                        services |= PCIE_PORT_SERVICE_HP;
index 2dcd22d9c816f98c681f572a2f48fbba7da5680b..b494066ef32f5f08e3f5d4f4b3d88acf9257d710 100644 (file)
@@ -623,6 +623,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
 {
        struct pci_bus *child;
        int i;
+       int ret;
 
        /*
         * Allocate a new bus, and inherit stuff from the parent..
@@ -637,8 +638,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
        child->bus_flags = parent->bus_flags;
 
        /* initialize some portions of the bus device, but don't register it
-        * now as the parent is not properly set up yet.  This device will get
-        * registered later in pci_bus_add_devices()
+        * now as the parent is not properly set up yet.
         */
        child->dev.class = &pcibus_class;
        dev_set_name(&child->dev, "%04x:%02x", pci_domain_nr(child), busnr);
@@ -651,11 +651,14 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
        child->primary = parent->busn_res.start;
        child->busn_res.end = 0xff;
 
-       if (!bridge)
-               return child;
+       if (!bridge) {
+               child->dev.parent = parent->bridge;
+               goto add_dev;
+       }
 
        child->self = bridge;
        child->bridge = get_device(&bridge->dev);
+       child->dev.parent = child->bridge;
        pci_set_bus_of_node(child);
        pci_set_bus_speed(child);
 
@@ -666,6 +669,13 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
        }
        bridge->subordinate = child;
 
+add_dev:
+       ret = device_register(&child->dev);
+       WARN_ON(ret < 0);
+
+       /* Create legacy_io and legacy_mem files for this bus */
+       pci_create_legacy_files(child);
+
        return child;
 }
 
@@ -1285,7 +1295,7 @@ static void pci_init_capabilities(struct pci_dev *dev)
        pci_vpd_pci22_init(dev);
 
        /* Alternative Routing-ID Forwarding */
-       pci_enable_ari(dev);
+       pci_configure_ari(dev);
 
        /* Single Root I/O Virtualization */
        pci_iov_init(dev);
@@ -1296,10 +1306,12 @@ static void pci_init_capabilities(struct pci_dev *dev)
 
 void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
 {
+       int ret;
+
        device_initialize(&dev->dev);
        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;
@@ -1326,6 +1338,17 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
        down_write(&pci_bus_sem);
        list_add_tail(&dev->bus_list, &bus->devices);
        up_write(&pci_bus_sem);
+
+       pci_fixup_device(pci_fixup_final, dev);
+       ret = pcibios_add_device(dev);
+       WARN_ON(ret < 0);
+
+       /* Notifier could use PCI capabilities */
+       dev->match_driver = false;
+       ret = device_add(&dev->dev);
+       WARN_ON(ret < 0);
+
+       pci_proc_attach_device(dev);
 }
 
 struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn)
@@ -1348,31 +1371,31 @@ struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn)
 }
 EXPORT_SYMBOL(pci_scan_single_device);
 
-static unsigned next_ari_fn(struct pci_dev *dev, unsigned fn)
+static unsigned next_fn(struct pci_bus *bus, struct pci_dev *dev, unsigned fn)
 {
-       u16 cap;
-       unsigned pos, next_fn;
+       int pos;
+       u16 cap = 0;
+       unsigned next_fn;
 
-       if (!dev)
-               return 0;
+       if (pci_ari_enabled(bus)) {
+               if (!dev)
+                       return 0;
+               pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
+               if (!pos)
+                       return 0;
 
-       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
-       if (!pos)
-               return 0;
-       pci_read_config_word(dev, pos + 4, &cap);
-       next_fn = cap >> 8;
-       if (next_fn <= fn)
-               return 0;
-       return next_fn;
-}
+               pci_read_config_word(dev, pos + PCI_ARI_CAP, &cap);
+               next_fn = PCI_ARI_CAP_NFN(cap);
+               if (next_fn <= fn)
+                       return 0;       /* protect against malformed list */
 
-static unsigned next_trad_fn(struct pci_dev *dev, unsigned fn)
-{
-       return (fn + 1) % 8;
-}
+               return next_fn;
+       }
+
+       /* dev may be NULL for non-contiguous multifunction devices */
+       if (!dev || dev->multifunction)
+               return (fn + 1) % 8;
 
-static unsigned no_next_fn(struct pci_dev *dev, unsigned fn)
-{
        return 0;
 }
 
@@ -1405,7 +1428,6 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
 {
        unsigned fn, nr = 0;
        struct pci_dev *dev;
-       unsigned (*next_fn)(struct pci_dev *, unsigned) = no_next_fn;
 
        if (only_one_child(bus) && (devfn > 0))
                return 0; /* Already scanned the entire slot */
@@ -1416,12 +1438,7 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
        if (!dev->is_added)
                nr++;
 
-       if (pci_ari_enabled(bus))
-               next_fn = next_ari_fn;
-       else if (dev->multifunction)
-               next_fn = next_trad_fn;
-
-       for (fn = next_fn(dev, 0); fn > 0; fn = next_fn(dev, fn)) {
+       for (fn = next_fn(bus, dev, 0); fn > 0; fn = next_fn(bus, dev, fn)) {
                dev = pci_scan_single_device(bus, devfn + fn);
                if (dev) {
                        if (!dev->is_added)
@@ -1632,6 +1649,18 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus)
        return max;
 }
 
+/**
+ * pcibios_root_bridge_prepare - Platform-specific host bridge setup.
+ * @bridge: Host bridge to set up.
+ *
+ * Default empty implementation.  Replace with an architecture-specific setup
+ * routine, if necessary.
+ */
+int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+       return 0;
+}
+
 struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
                struct pci_ops *ops, void *sysdata, struct list_head *resources)
 {
@@ -1644,13 +1673,13 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
        char bus_addr[64];
        char *fmt;
 
-
        b = pci_alloc_bus();
        if (!b)
                return NULL;
 
        b->sysdata = sysdata;
        b->ops = ops;
+       b->number = b->busn_res.start = bus;
        b2 = pci_find_bus(pci_domain_nr(b), bus);
        if (b2) {
                /* If we already got to this bus through a different bridge, ignore it */
@@ -1665,6 +1694,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
        bridge->dev.parent = parent;
        bridge->dev.release = pci_release_bus_bridge_dev;
        dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
+       error = pcibios_root_bridge_prepare(bridge);
+       if (error)
+               goto bridge_dev_reg_err;
+
        error = device_register(&bridge->dev);
        if (error)
                goto bridge_dev_reg_err;
@@ -1685,8 +1718,6 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
        /* Create legacy_io and legacy_mem files for this bus */
        pci_create_legacy_files(b);
 
-       b->number = b->busn_res.start = bus;
-
        if (parent)
                dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
        else
index 84954a726a94d058ecf2e95100dcb01800cc434b..cc875e6ed159f1edb890946a96e78917bb6fe2c5 100644 (file)
@@ -24,7 +24,7 @@ static void pci_stop_dev(struct pci_dev *dev)
        if (dev->is_added) {
                pci_proc_detach_device(dev);
                pci_remove_sysfs_dev_files(dev);
-               device_unregister(&dev->dev);
+               device_del(&dev->dev);
                dev->is_added = 0;
        }
 
@@ -39,7 +39,7 @@ static void pci_destroy_dev(struct pci_dev *dev)
        up_write(&pci_bus_sem);
 
        pci_free_resources(dev);
-       pci_dev_put(dev);
+       put_device(&dev->dev);
 }
 
 void pci_remove_bus(struct pci_bus *bus)
index bf969ba58e59d10aa770909005bee01ac76dd060..d0627fa9f36827fdd864e462d519fd2279ef7d56 100644 (file)
@@ -319,13 +319,13 @@ int pci_dev_present(const struct pci_device_id *ids)
        WARN_ON(in_interrupt());
        while (ids->vendor || ids->subvendor || ids->class_mask) {
                found = pci_get_dev_by_id(ids, NULL);
-               if (found)
-                       goto exit;
+               if (found) {
+                       pci_dev_put(found);
+                       return 1;
+               }
                ids++;
        }
-exit:
-       if (found)
-               return 1;
+
        return 0;
 }
 EXPORT_SYMBOL(pci_dev_present);
index 6d3591d57ea00734148e48e8fb2774bc34bb81b6..7e8739e25b9ecddd9b52d19c7bfc486f8c3e7ac7 100644 (file)
@@ -283,7 +283,7 @@ static void assign_requested_resources_sorted(struct list_head *head,
                idx = res - &dev_res->dev->resource[0];
                if (resource_size(res) &&
                    pci_assign_resource(dev_res->dev, idx)) {
-                       if (fail_head && !pci_is_root_bus(dev_res->dev->bus)) {
+                       if (fail_head) {
                                /*
                                 * if the failed res is for ROM BAR, and it will
                                 * be enabled later, don't add it to the list
index 227ba7dc293d0f334e4d56de92189022200badd2..e65278f560c40593e5a3f6fd8b520d5fce3f4468 100644 (file)
@@ -323,6 +323,15 @@ struct acpi_eject_event {
        u32             event;
 };
 
+struct acpi_hp_work {
+       struct work_struct work;
+       acpi_handle handle;
+       u32 type;
+       void *context;
+};
+void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context,
+                       void (*func)(struct work_struct *work));
+
 extern struct kobject *acpi_kobj;
 extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int);
 void acpi_bus_private_data_handler(acpi_handle, void *);
@@ -454,7 +463,6 @@ struct acpi_pci_root {
 /* helper */
 acpi_handle acpi_get_child(acpi_handle, u64);
 int acpi_is_root_bridge(acpi_handle);
-acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int);
 struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle);
 #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)ACPI_HANDLE(dev))
 
index 8b1d7a6a9695c44582890dc2a89acdd0e709e7b4..627749af0ba7f77889222819504cd8f54e1f7c55 100644 (file)
@@ -90,11 +90,6 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
                               int *polarity, char **name);
 int acpi_pci_link_free_irq(acpi_handle handle);
 
-/* ACPI PCI Interrupt Routing (pci_irq.c) */
-
-int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus);
-void acpi_pci_irq_del_prt(int segment, int bus);
-
 /* ACPI PCI Device Binding (pci_bind.c) */
 
 struct pci_bus;
index 7d2a9eaab9ebaf254b7d108c99af9c3d0a2d45e0..5b3d2bd4813ae30895160d1a383ea149615d292e 100644 (file)
@@ -194,8 +194,6 @@ void acpi_os_fixed_event_count(u32 fixed_event_number);
 /*
  * Threads and Scheduling
  */
-extern struct workqueue_struct *kacpi_hotplug_wq;
-
 acpi_thread_id acpi_os_get_thread_id(void);
 
 acpi_status
index 6fa4dd2a3b9e08f94b2f6b446d88b8b2ed8e3ad4..2461033a798728203f456eff4d6a0099816a7072 100644 (file)
@@ -286,6 +286,7 @@ struct pci_dev {
        unsigned int    irq;
        struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */
 
+       bool match_driver;              /* Skip attaching driver */
        /* These fields are used by common fixups */
        unsigned int    transparent:1;  /* Transparent PCI bridge */
        unsigned int    multifunction:1;/* Part of multi-function device */
@@ -378,6 +379,8 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
                     void (*release_fn)(struct pci_host_bridge *),
                     void *release_data);
 
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
+
 /*
  * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
  * to P2P or CardBus bridge windows) go in a table.  Additional ones (for
@@ -674,6 +677,7 @@ extern struct list_head pci_root_buses;     /* list of all known PCI buses */
 /* Some device drivers need know if pci is initiated */
 extern int no_pci_devices(void);
 
+void pcibios_resource_survey_bus(struct pci_bus *bus);
 void pcibios_fixup_bus(struct pci_bus *);
 int __must_check pcibios_enable_device(struct pci_dev *, int mask);
 /* Architecture specific versions may override this (weak) */
@@ -1699,13 +1703,22 @@ static inline bool pci_is_pcie(struct pci_dev *dev)
        return !!pci_pcie_cap(dev);
 }
 
+/**
+ * pcie_caps_reg - get the PCIe Capabilities Register
+ * @dev: PCI device
+ */
+static inline u16 pcie_caps_reg(const struct pci_dev *dev)
+{
+       return dev->pcie_flags_reg;
+}
+
 /**
  * pci_pcie_type - get the PCIe device/port type
  * @dev: PCI device
  */
 static inline int pci_pcie_type(const struct pci_dev *dev)
 {
-       return (dev->pcie_flags_reg & PCI_EXP_FLAGS_TYPE) >> 4;
+       return (pcie_caps_reg(dev) & PCI_EXP_FLAGS_TYPE) >> 4;
 }
 
 void pci_request_acs(void);