Merge tag 'pci-v3.9-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Linus Torvalds [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
  ...

26 files changed:
1  2 
Documentation/kernel-parameters.txt
arch/frv/mb93090-mb00/pci-vdk.c
arch/ia64/pci/pci.c
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/legacy.c
arch/x86/pci/numaq_32.c
drivers/acpi/Kconfig
drivers/acpi/internal.h
drivers/acpi/osl.c
drivers/acpi/pci_root.c
drivers/acpi/pci_slot.c
drivers/acpi/scan.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/pciehp_core.c
drivers/pci/hotplug/sgi_hotplug.c
drivers/pci/iov.c
drivers/pci/pci-acpi.c
drivers/pci/pcie/aspm.c
drivers/pci/remove.c
include/acpi/acpi_bus.h
include/acpi/acpiosxf.h
include/linux/pci.h

Simple merge
Simple merge
@@@ -393,7 -396,15 +393,15 @@@ 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 __devinit is_valid_resource(struct pci_dev *dev, int idx)
 +static int is_valid_resource(struct pci_dev *dev, int idx)
  {
        unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM;
        struct resource *devr = &dev->resource[idx], *busr;
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
  
  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);
 +#ifdef CONFIG_ACPI_CONTAINER
 +void acpi_container_init(void);
 +#else
 +static inline void acpi_container_init(void) {}
 +#endif
  
  #ifdef CONFIG_DEBUG_FS
  extern struct dentry *acpi_debugfs_dir;
Simple merge
@@@ -624,10 -599,8 +596,8 @@@ end
        return result;
  }
  
 -static int acpi_pci_root_remove(struct acpi_device *device, int type)
 +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;
  
@@@ -658,8 -628,142 +624,138 @@@ void __init acpi_pci_root_init(void
  {
        acpi_hest_init();
  
 -      if (acpi_pci_disabled)
 -              return 0;
 -
 -      pci_acpi_crs_quirks();
 -      if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0)
 -              return -ENODEV;
 -
 -      return 0;
 +      if (!acpi_pci_disabled) {
 +              pci_acpi_crs_quirks();
 +              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);
+ }
Simple merge
@@@ -1778,13 -1685,10 +1778,14 @@@ int __init acpi_scan_init(void
                printk(KERN_ERR PREFIX "Could not register bus type\n");
        }
  
 -      acpi_power_init();
        acpi_pci_root_init();
 +      acpi_pci_link_init();
 +      acpi_platform_init();
 +      acpi_csrt_init();
 +      acpi_container_init();
+       acpi_pci_slot_init();
  
 +      mutex_lock(&acpi_scan_lock);
        /*
         * Enumerate devices in the ACPI namespace.
         */
  
        acpi_update_all_gpes();
  
+       acpi_pci_root_hp_init();
 -      return 0;
 + out:
 +      mutex_unlock(&acpi_scan_lock);
 +      return result;
  }
@@@ -1214,29 -1136,11 +1132,13 @@@ static void _handle_hotplug_event_bridg
        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) {
                break;
        }
  
- out:
 +      acpi_scan_lock_release();
        kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
  }
  
@@@ -1330,22 -1226,17 +1225,19 @@@ static void _handle_hotplug_event_func(
        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 */
Simple merge
Simple merge
Simple merge
@@@ -325,26 -307,8 +307,7 @@@ static void pci_acpi_setup(struct devic
        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);
-       }
  
 -      acpi_power_resource_register_device(dev, handle);
        if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
                return;
  
@@@ -367,10 -330,7 +329,6 @@@ static void pci_acpi_cleanup(struct 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);
 -      acpi_power_resource_unregister_device(dev, handle);
  }
  
  static struct acpi_bus_type acpi_pci_bus = {
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge