1. 06 2月, 2014 4 次提交
  2. 04 2月, 2014 5 次提交
    • R
      ACPI / hotplug / PCI: Fix bridge removal race vs dock events · af9d8adc
      Rafael J. Wysocki 提交于
      If a PCI bridge with an ACPIPHP context attached is removed via
      sysfs, the code path executed as a result is the following:
      
      pci_stop_and_remove_bus_device_locked
       pci_remove_bus
        pcibios_remove_bus
         acpi_pci_remove_bus
          acpiphp_remove_slots
           cleanup_bridge
            unregister_hotplug_dock_device (drops dock references to the bridge)
           put_bridge
            free_bridge
             acpiphp_put_context (for each child, under context lock)
              kfree (context)
      
      Now, if a dock event affecting one of the bridge's child devices
      occurs (roughly at the same time), it will lead to the following code
      path:
      
      acpi_dock_deferred_cb
       dock_notify
        handle_eject_request
         hot_remove_dock_devices
          dock_hotplug_event
           hotplug_event (dereferences context)
      
      That may lead to a kernel crash in hotplug_event() if it is executed
      after the last kfree() in the bridge removal code path.
      
      To prevent that from happening, add a wrapper around hotplug_event()
      called dock_event() and point the .handler pointer in acpiphp_dock_ops
      to it.  Make that wrapper retrieve the device's ACPIPHP context using
      acpiphp_get_context() (instead of taking it from the data argument)
      under acpiphp_context_lock and check if the parent bridge's
      is_going_away flag is set.  If that flag is set, it will return
      immediately and if it is not set it will grab a reference to the
      device's parent bridge before executing hotplug_event().
      
      Then, in the above scenario, the reference to the parent bridge
      held by dock_event() will prevent free_bridge() from being executed
      for it until hotplug_event() returns.
      Signed-off-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
      af9d8adc
    • R
      ACPI / hotplug / PCI: Fix bridge removal race in handle_hotplug_event() · 1b360f44
      Rafael J. Wysocki 提交于
      If a PCI bridge with an ACPIPHP context attached is removed via
      sysfs, the code path executed as a result is the following:
      
      pci_stop_and_remove_bus_device_locked
       pci_remove_bus
        pcibios_remove_bus
         acpi_pci_remove_bus
          acpiphp_remove_slots
           cleanup_bridge
           put_bridge
            free_bridge
             acpiphp_put_context (for each child, under context lock)
              kfree (child context)
      
      Now, if a hotplug notify is dispatched for one of the bridge's
      children and the timing is such that handle_hotplug_event() for
      that notify is executed while free_bridge() above is running,
      the get_bridge(context->func.parent) in handle_hotplug_event()
      will not really help, because it is too late to prevent the bridge
      from going away and the child's context may be freed before
      hotplug_event_work() scheduled from handle_hotplug_event()
      dereferences the pointer to it passed via the data argument.
      That will cause a kernel crash to happpen in hotplug_event_work().
      
      To prevent that from happening, make handle_hotplug_event()
      check the is_going_away flag of the function's parent bridge
      (under acpiphp_context_lock) and bail out if it's set.  Also,
      make cleanup_bridge() set the bridge's is_going_away flag under
      acpiphp_context_lock so that it cannot be changed between the
      check and the subsequent get_bridge(context->func.parent) in
      handle_hotplug_event().
      
      Then, in the above scenario, handle_hotplug_event() will notice
      that context->func.parent->is_going_away is already set and it
      will exit immediately preventing the crash from happening.
      Signed-off-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
      1b360f44
    • R
      ACPI / hotplug / PCI: Scan root bus under the PCI rescan-remove lock · d42f5da2
      Rafael J. Wysocki 提交于
      Since acpiphp_check_bridge() called by acpiphp_check_host_bridge()
      does things that require PCI rescan-remove locking around it,
      make acpiphp_check_host_bridge() use that locking.
      Signed-off-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
      Tested-by: NMika Westerberg <mika.westerberg@linux.intel.com>
      d42f5da2
    • R
      ACPI / hotplug / PCI: Move PCI rescan-remove locking to hotplug_event() · f41b3261
      Rafael J. Wysocki 提交于
      Commit 9217a984 (ACPI / hotplug / PCI: Use global PCI rescan-remove
      locking) modified ACPIPHP to protect its PCI device removal and addition
      code paths from races against sysfs-driven rescan and remove operations
      with the help of PCI rescan-remove locking.  However, it overlooked the
      fact that hotplug_event_work() is not the only caller of hotplug_event()
      which may also be called by dock_hotplug_event() and that code path
      is missing the PCI rescan-remove locking.  This means that, although
      the PCI rescan-remove lock is held as appropriate during the handling
      of events originating from handle_hotplug_event(), the ACPIPHP's
      operations resulting from dock events may still suffer the race
      conditions that commit 9217a984 was supposed to eliminate.
      
      To address that problem, move the PCI rescan-remove locking from
      hotplug_event_work() to hotplug_event() so that it is used regardless
      of the way that function is invoked.
      
      Revamps: 9217a984 (ACPI / hotplug / PCI: Use global PCI rescan-remove locking)
      Signed-off-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
      Tested-by: NMika Westerberg <mika.westerberg@linux.intel.com>
      f41b3261
    • R
      ACPI / hotplug / PCI: Remove entries from bus->devices in reverse order · 2d7c1b77
      Rafael J. Wysocki 提交于
      According to the changelog of commit 29ed1f29 (PCI: pciehp: Fix null
      pointer deref when hot-removing SR-IOV device) it is unsafe to walk the
      bus->devices list of a PCI bus and remove devices from it in direct order,
      because that may lead to NULL pointer dereferences related to virtual
      functions.
      
      For this reason, change all of the bus->devices list walks in
      acpiphp_glue.c during which devices may be removed to be carried out in
      reverse order.
      Signed-off-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
      Tested-by: NMika Westerberg <mika.westerberg@linux.intel.com>
      2d7c1b77
  3. 15 1月, 2014 1 次提交
  4. 31 12月, 2013 1 次提交
    • R
      ACPIPHP / radeon / nouveau: Fix VGA switcheroo problem related to hotplug · f244d8b6
      Rafael J. Wysocki 提交于
      The changes in the ACPI-based PCI hotplug (ACPIPHP) subsystem made
      during the 3.12 development cycle uncovered a problem with VGA
      switcheroo that on some systems, when the device-specific method
      (ATPX in the radeon case, _DSM in the nouveau case) is used to turn
      off the discrete graphics, the BIOS generates ACPI hotplug events for
      that device and those events cause ACPIPHP to attempt to remove the
      device from the system (they are events for a device that was present
      previously and is not present any more, so that's what should be done
      according to the spec).  Then, the system stops functioning correctly.
      
      Since the hotplug events in question were simply silently ignored
      previously, the least intrusive way to address that problem is to
      make ACPIPHP ignore them again.  For this purpose, introduce a new
      ACPI device flag, no_hotplug, and modify ACPIPHP to ignore hotplug
      events for PCI devices whose ACPI companions have that flag set.
      Next, make the radeon and nouveau switcheroo detection code set the
      no_hotplug flag for the discrete graphics' ACPI companion.
      
      Fixes: bbd34fcd (ACPI / hotplug / PCI: Register all devices under the given bridge)
      References: https://bugzilla.kernel.org/show_bug.cgi?id=61891
      References: https://bugzilla.kernel.org/show_bug.cgi?id=64891Reported-and-tested-by: NMike Lothian <mike@fireburn.co.uk>
      Reported-and-tested-by: <madcatx@atlas.cz>
      Reported-and-tested-by: NJoaquín Aramendía <samsagax@gmail.com>
      Cc: Alex Deucher <alexdeucher@gmail.com>
      Cc: Dave Airlie <airlied@linux.ie>
      Cc: Takashi Iwai <tiwai@suse.de>
      Signed-off-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
      Cc: 3.12+ <stable@vger.kernel.org> # 3.12+
      f244d8b6
  5. 28 11月, 2013 1 次提交
  6. 23 11月, 2013 1 次提交
    • R
      ACPI / scan: Add acpi_device objects for all device nodes in the namespace · 202317a5
      Rafael J. Wysocki 提交于
      Modify the ACPI namespace scanning code to register a struct
      acpi_device object for every namespace node representing a device,
      processor and so on, even if the device represented by that namespace
      node is reported to be not present and not functional by _STA.
      
      There are multiple reasons to do that.  First of all, it avoids
      quite a lot of overhead when struct acpi_device objects are
      deleted every time acpi_bus_trim() is run and then added again
      by a subsequent acpi_bus_scan() for the same scope, although the
      namespace objects they correspond to stay in memory all the time
      (which always is the case on a vast majority of systems).
      
      Second, it will allow user space to see that there are namespace
      nodes representing devices that are not present at the moment and may
      be added to the system.  It will also allow user space to evaluate
      _SUN for those nodes to check what physical slots the "missing"
      devices may be put into and it will make sense to add a sysfs
      attribute for _STA evaluation after this change (that will be
      useful for thermal management on some systems).
      
      Next, it will help to consolidate the ACPI hotplug handling among
      subsystems by making it possible to store hotplug-related information
      in struct acpi_device objects in a standard common way.
      
      Finally, it will help to avoid a race condition related to the
      deletion of ACPI namespace nodes.  Namely, namespace nodes may be
      deleted as a result of a table unload triggered by _EJ0 or _DCK.
      If a hotplug notification for one of those nodes is triggered
      right before the deletion and it executes a hotplug callback
      via acpi_hotplug_execute(), the ACPI handle passed to that
      callback may be stale when the callback actually runs.  One way
      to work around that is to always pass struct acpi_device pointers
      to hotplug callbacks after doing a get_device() on the objects in
      question which eliminates the use-after-free possibility (the ACPI
      handles in those objects are invalidated by acpi_scan_drop_device(),
      so they will trigger ACPICA errors on attempts to use them).
      Signed-off-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
      Tested-by: NMika Westerberg <mika.westerberg@linux.intel.com>
      202317a5
  7. 15 11月, 2013 1 次提交
  8. 08 11月, 2013 1 次提交
    • R
      ACPI / hotplug: Consolidate deferred execution of ACPI hotplug routines · 7b98118a
      Rafael J. Wysocki 提交于
      There are two different interfaces for queuing up work items on the
      ACPI hotplug workqueue, alloc_acpi_hp_work() used by PCI and PCI host
      bridge hotplug code and acpi_os_hotplug_execute() used by the common
      ACPI hotplug code and docking stations.  They both are somewhat
      cumbersome to use and work slightly differently.
      
      The users of alloc_acpi_hp_work() have to submit a work function that
      will extract the necessary data items from a struct acpi_hp_work
      object allocated by alloc_acpi_hp_work() and then will free that
      object, while it would be more straightforward to simply use a work
      function with one more argument and let the interface take care of
      the execution details.
      
      The users of acpi_os_hotplug_execute() also have to deal with the
      fact that it takes only one argument in addition to the work function
      pointer, although acpi_os_execute_deferred() actually takes care of
      the allocation and freeing of memory, so it would have been able to
      pass more arguments to the work function if it hadn't been
      constrained by the connection with acpi_os_execute().
      
      Moreover, while alloc_acpi_hp_work() makes GFP_KERNEL memory
      allocations, which is correct, because hotplug work items are
      always queued up from process context, acpi_os_hotplug_execute()
      uses GFP_ATOMIC, as that is needed by acpi_os_execute().  Also,
      acpi_os_execute_deferred() queued up by it waits for the ACPI event
      workqueues to flush before executing the work function, whereas
      alloc_acpi_hp_work() can't do anything similar.  That leads to
      somewhat arbitrary differences in behavior between various ACPI
      hotplug code paths and has to be straightened up.
      
      For this reason, replace both alloc_acpi_hp_work() and
      acpi_os_hotplug_execute() with a single interface,
      acpi_hotplug_execute(), combining their behavior and being more
      friendly to its users than any of the two.
      Signed-off-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
      Tested-by: NMika Westerberg <mika.westerberg@linux.intel.com>
      7b98118a
  9. 30 10月, 2013 1 次提交
  10. 12 10月, 2013 2 次提交
  11. 26 9月, 2013 1 次提交
    • L
      PCI: acpiphp: Convert to dynamic debug · bd950799
      Lan Tianyu 提交于
      This patch is to use pr_debug/info/warn/err to replace acpiphp debug
      functions and remove module's debug param.
      
      User interface change: before this patch, boot with the "acpiphp.debug"
      kernel parameter to turn on debug.  After this patch, set
      CONFIG_DYNAMIC_DEBUG=y and boot with "acpiphp.dyndebug=+p" instead.
      See Documentation/dynamic-debug-howto.txt.
      
      [bhelgaas: changelog]
      Signed-off-by: NLan Tianyu <tianyu.lan@intel.com>
      Signed-off-by: NBjorn Helgaas <bhelgaas@google.com>
      bd950799
  12. 10 9月, 2013 1 次提交
    • R
      ACPI / hotplug / PCI: Avoid parent bus rescans on spurious device checks · a47d8c8e
      Rafael J. Wysocki 提交于
      In the current ACPIPHP notify handler we always go directly for a
      rescan of the parent bus if we get a device check notification for
      a device that is not a bridge.  However, this obviously is
      overzealous if nothing really changes, because this way we may rescan
      the whole PCI hierarchy pretty much in vain.
      
      That happens on Alex Williamson's machine whose ACPI tables contain
      device objects that are supposed to coresspond to PCIe root ports,
      but those ports aren't physically present (or at least they aren't
      visible in the PCI config space to us).  The BIOS generates multiple
      device check notifies for those objects during boot and for each of
      them we go straight for the parent bus rescan, but the parent bus is
      the root bus in this particular case.  In consequence, we rescan the
      whole PCI bus from the top several times in a row, which is
      completely unnecessary, increases boot time by 50% (after previous
      fixes) and generates excess dmesg output from the PCI subsystem.
      
      Fix the problem by checking if we can find anything new in the
      slot corresponding to the device we've got a device check notify
      for and doing nothig if that's not the case.
      
      The spec (ACPI 5.0, Section 5.6.6) appears to mandate this behavior,
      as it says:
      
        Device Check. Used to notify OSPM that the device either appeared
        or disappeared. If the device has appeared, OSPM will re-enumerate
        from the parent. If the device has disappeared, OSPM will
        invalidate the state of the device. OSPM may optimize out
        re-enumeration.
      
      Therefore, according to the spec, we are free to do nothing if
      nothing changes.
      
      References: https://bugzilla.kernel.org/show_bug.cgi?id=60865Reported-and-tested-by: NAlex Williamson <alex.williamson@redhat.com>
      Signed-off-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
      a47d8c8e
  13. 07 9月, 2013 2 次提交
  14. 06 9月, 2013 1 次提交
    • R
      ACPI / hotplug / PCI: Don't trim devices before scanning the namespace · 89ec2f2e
      Rafael J. Wysocki 提交于
      In acpiphp_bus_add() we first remove device objects corresponding to
      the given handle and the ACPI namespace branch below it, which are
      then re-created by acpi_bus_scan().  This used to be done to clean
      up after surprise removals, but now we do the cleanup through
      trim_stale_devices() which checks if the devices in question are
      actually gone before removing them, so the device hierarchy trimming
      in acpiphp_bus_add() is not necessary any more and, moreover, it may
      lead to problems if it removes device objects corresponding to
      devices that are actually present.
      
      For this reason, remove the leftover acpiphp_bus_trim() from
      acpiphp_bus_add().
      Reported-by: NAlex Williamson <alex.williamson@redhat.com>
      Signed-off-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
      89ec2f2e
  15. 18 8月, 2013 1 次提交
    • R
      ACPI / hotplug / PCI: Fix NULL pointer dereference in cleanup_bridge() · 1aaac071
      Rafael J. Wysocki 提交于
      After commit bbd34fcd (ACPI / hotplug / PCI: Register all devices
      under the given bridge) register_slot() is called for all PCI
      devices under a given bridge that have corresponding objects in
      the ACPI namespace, but it calls acpiphp_register_hotplug_slot()
      only for devices satisfying specific criteria.  Still,
      cleanup_bridge() calls acpiphp_unregister_hotplug_slot() for all
      objects created by register_slot(), although it should only call it
      for the ones that acpiphp_register_hotplug_slot() has been called
      for (successfully).  This causes a NULL pointer to be dereferenced
      by the acpiphp_unregister_hotplug_slot() executed by cleanup_bridge()
      if the object it is called for has not been passed to
      acpiphp_register_hotplug_slot().
      
      To fix this problem, check if the 'slot' field of the object passed
      to acpiphp_unregister_hotplug_slot() in cleanup_bridge() is not NULL,
      which only is the case if acpiphp_register_hotplug_slot() has been
      executed for that object.  In addition to that, make register_slot()
      reset the 'slot' field to NULL if acpiphp_register_hotplug_slot() has
      failed for the given object to prevent stale pointers from being
      used by acpiphp_unregister_hotplug_slot().
      Reported-and-tested-by: NYinghai Lu <yinghai@kernel.org>
      Signed-off-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
      1aaac071
  16. 26 7月, 2013 1 次提交
  17. 23 7月, 2013 15 次提交