1. 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
  2. 07 9月, 2013 2 次提交
  3. 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
  4. 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
  5. 23 7月, 2013 29 次提交
  6. 15 7月, 2013 2 次提交
  7. 24 6月, 2013 1 次提交
    • R
      ACPI / dock / PCI: Synchronous handling of dock events for PCI devices · 21a31013
      Rafael J. Wysocki 提交于
      The interactions between the ACPI dock driver and the ACPI-based PCI
      hotplug (acpiphp) are currently problematic because of ordering
      issues during hot-remove operations.
      
      First of all, the current ACPI glue code expects that physical
      devices will always be deleted before deleting the companion ACPI
      device objects.  Otherwise, acpi_unbind_one() will fail with a
      warning message printed to the kernel log, for example:
      
      [  185.026073] usb usb5: Oops, 'acpi_handle' corrupt
      [  185.035150] pci 0000:1b:00.0: Oops, 'acpi_handle' corrupt
      [  185.035515] pci 0000:18:02.0: Oops, 'acpi_handle' corrupt
      [  180.013656]  port1: Oops, 'acpi_handle' corrupt
      
      This means, in particular, that struct pci_dev objects have to
      be deleted before the struct acpi_device objects they are "glued"
      with.
      
      Now, the following happens the during the undocking of an ACPI-based
      dock station:
       1) hotplug_dock_devices() invokes registered hotplug callbacks to
          destroy physical devices associated with the ACPI device objects
          depending on the dock station.  It calls dd->ops->handler() for
          each of those device objects.
       2) For PCI devices dd->ops->handler() points to
          handle_hotplug_event_func() that queues up a separate work item
          to execute _handle_hotplug_event_func() for the given device and
          returns immediately.  That work item will be executed later.
       3) hotplug_dock_devices() calls dock_remove_acpi_device() for each
          device depending on the dock station.  This runs acpi_bus_trim()
          for each of them, which causes the underlying ACPI device object
          to be destroyed, but the work items queued up by
          handle_hotplug_event_func() haven't been started yet.
       4) _handle_hotplug_event_func() queued up in step 2) are executed
          and cause the above failure to happen, because the PCI devices
          they handle do not have the companion ACPI device objects any
          more (those objects have been deleted in step 3).
      
      The possible breakage doesn't end here, though, because
      hotplug_dock_devices() may return before at least some of the
      _handle_hotplug_event_func() work items spawned by it have a
      chance to complete and then undock() will cause _DCK to be
      evaluated and that will cause the devices handled by the
      _handle_hotplug_event_func() to go away possibly while they are
      being accessed.
      
      This means that dd->ops->handler() for PCI devices should not point
      to handle_hotplug_event_func().  Instead, it should point to a
      function that will do the work of _handle_hotplug_event_func()
      synchronously.  For this reason, introduce such a function,
      hotplug_event_func(), and modity acpiphp_dock_ops to point to
      it as the handler.
      
      Unfortunately, however, this is not sufficient, because if the dock
      code were not changed further, hotplug_event_func() would now
      deadlock with hotplug_dock_devices() that called it, since it would
      run unregister_hotplug_dock_device() which in turn would attempt to
      acquire the dock station's hp_lock mutex already acquired by
      hotplug_dock_devices().
      
      To resolve that deadlock use the observation that
      unregister_hotplug_dock_device() won't need to acquire hp_lock
      if PCI bridges the devices on the dock station depend on are
      prevented from being removed prematurely while the first loop in
      hotplug_dock_devices() is in progress.
      
      To make that possible, introduce a mechanism by which the callers of
      register_hotplug_dock_device() can provide "init" and "release"
      routines that will be executed, respectively, during the addition
      and removal of the physical device object associated with the
      given ACPI device handle.  Make acpiphp use two new functions,
      acpiphp_dock_init() and acpiphp_dock_release(), that call
      get_bridge() and put_bridge(), respectively, on the acpiphp bridge
      holding the given device, for this purpose.
      
      In addition to that, remove the dock station's list of
      "hotplug devices" and make the dock code always walk the whole list
      of "dependent devices" instead in such a way that the loops in
      hotplug_dock_devices() and dock_event() (replacing the loops over
      "hotplug devices") will take references to the list entries that
      register_hotplug_dock_device() has been called for.  That prevents
      the "release" routines associated with those entries from being
      called while the given entry is being processed and for PCI
      devices this means that their bridges won't be removed (by a
      concurrent thread) while hotplug_event_func() handling them is
      being executed.
      
      This change is based on two earlier patches from Jiang Liu.
      
      References: https://bugzilla.kernel.org/show_bug.cgi?id=59501Reported-and-tested-by: NAlexander E. Patrakov <patrakov@gmail.com>
      Tracked-down-by: NJiang Liu <jiang.liu@huawei.com>
      Tested-by: NIllya Klymov <xanf@xanf.me>
      Signed-off-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
      Acked-by: NYinghai Lu <yinghai@kernel.org>
      Cc: 3.9+ <stable@vger.kernel.org>
      21a31013
  8. 23 6月, 2013 1 次提交
    • J
      PCI / ACPI: Use boot-time resource allocation rules during hotplug · d66ecb72
      Jiang Liu 提交于
      On x86 platforms, the kernel respects PCI resource assignments from
      the BIOS and only reassigns resources for unassigned BARs at boot
      time.  However, with the ACPI-based hotplug (acpiphp), it ignores the
      BIOS' PCI resource assignments completely and reassigns all resources
      by itself.  This causes differences in PCI resource allocation
      between boot time and runtime hotplug to occur, which is generally
      undesirable and sometimes actively breaks things.
      
      Namely, if there are enough resources, reassigning all PCI resources
      during runtime hotplug should work, but it may fail if the resources
      are constrained.  This may happen, for instance, when some PCI
      devices with huge MMIO BARs are involved in the runtime hotplug
      operations, because the current PCI MMIO alignment algorithm may
      waste huge chunks of MMIO address space in those cases.
      
      On the Alexander's Sony VAIO VPCZ23A4R the BIOS allocates limited
      MMIO resources for the dock station which contains a device
      (graphics adapter) with a 256MB MMIO BAR.  An attempt to reassign
      that during runtime hotplug causes the dock station MMIO window to be
      exhausted and acpiphp fails to allocate resources for the majority
      of devices on the dock station as a result.
      
      To prevent that from happening, modify acpiphp to follow the boot
      time resources allocation behavior so that the BIOS' resource
      assignments are respected during runtime hotplug too.
      
      [rjw: Changelog]
      References: https://bugzilla.kernel.org/show_bug.cgi?id=56531Reported-and-tested-by: NAlexander E. Patrakov <patrakov@gmail.com>
      Tested-by: NIllya Klymov <xanf@xanf.me>
      Signed-off-by: NJiang Liu <jiang.liu@huawei.com>
      Acked-by: NYinghai Lu <yinghai@kernel.org>
      Cc: 3.9+ <stable@vger.kernel.org>
      Signed-off-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
      d66ecb72
  9. 18 5月, 2013 1 次提交
  10. 17 4月, 2013 1 次提交
    • J
      PCI: acpiphp: Protect acpiphp data structures from concurrent updates · 3d54a316
      Jiang Liu 提交于
      Now acpiphp_enumerate_slots() and acpiphp_remove_slots() may be invoked
      concurrently by the PCI core, so add a bridge_mutex and reference count
      mechanism to protect acpiphp bridge/slot/function data structures.
      
      To avoid deadlock, handle_hotplug_event_bridge() will requeue the
      hotplug event onto the kacpi_hotplug_wq by calling alloc_acpi_hp_work().
      But the workaround has introduced a minor race window because the
      'bridge' passed to _handle_hotplug_event_bridge() may have already been
      destroyed when _handle_hotplug_event_bridge() is actually executed by
      the kacpi_hotplug_wq.  So hold a reference count on the passed 'bridge'.
      Fix the same issue for handle_hotplug_event_func() too.
      Signed-off-by: NJiang Liu <jiang.liu@huawei.com>
      Signed-off-by: NYijing Wang <wangyijing@huawei.com>
      Signed-off-by: NBjorn Helgaas <bhelgaas@google.com>
      Reviewed-by: NYinghai Lu <yinghai@kernel.org>
      Cc: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
      Cc: Toshi Kani <toshi.kani@hp.com>
      3d54a316