kernel-ark/drivers/acpi
Rafael J. Wysocki 60f75b8e97 ACPI: Try harder to resolve _ADR collisions for bridges
In theory, under a given ACPI namespace node there should be only
one child device object with _ADR whose value matches a given bus
address exactly.  In practice, however, there are systems in which
multiple child device objects under a given parent have _ADR matching
exactly the same address.  In those cases we use _STA to determine
which of the multiple matching devices is enabled, since some systems
are known to indicate which ACPI device object to associate with the
given physical (usually PCI) device this way.

Unfortunately, as it turns out, there are systems in which many
device objects under the same parent have _ADR matching exactly the
same bus address and none of them has _STA, in which case they all
should be regarded as enabled according to the spec.  Still, if
those device objects are supposed to represent bridges (e.g. this
is the case for device objects corresponding to PCIe ports), we can
try harder and skip the ones that have no child device objects in the
ACPI namespace.  With luck, we can avoid using device objects that we
are not expected to use this way.

Although this only works for bridges whose children also have ACPI
namespace representation, it is sufficient to address graphics
adapter detection issues on some systems, so rework the code finding
a matching device ACPI handle for a given bus address to implement
this idea.

Introduce a new function, acpi_find_child(), taking three arguments:
the ACPI handle of the device's parent, a bus address suitable for
the device's bus type and a bool indicating if the device is a
bridge and make it work as outlined above.  Reimplement the function
currently used for this purpose, acpi_get_child(), as a call to
acpi_find_child() with the last argument set to 'false' and make
the PCI subsystem use acpi_find_child() with the bridge information
passed as the last argument to it.  [Lan Tianyu notices that it is
not sufficient to use pci_is_bridge() for that, because the device's
subordinate pointer hasn't been set yet at this point, so use
hdr_type instead.]

This change fixes a regression introduced inadvertently by commit
33f767d (ACPI: Rework acpi_get_child() to be more efficient) which
overlooked the fact that for acpi_walk_namespace() "post-order" means
"after all children have been visited" rather than "on the way back",
so for device objects without children and for namespace walks of
depth 1, as in the acpi_get_child() case, the "post-order" callbacks
ordering is actually the same as the ordering of "pre-order" ones.
Since that commit changed the namespace walk in acpi_get_child() to
terminate after finding the first matching object instead of going
through all of them and returning the last one, it effectively
changed the result returned by that function in some rare cases and
that led to problems (the switch from a "pre-order" to a "post-order"
callback was supposed to prevent that from happening, but it was
ineffective).

As it turns out, the systems where the change made by commit
33f767d actually matters are those where there are multiple ACPI
device objects representing the same PCIe port (which effectively
is a bridge).  Moreover, only one of them, and the one we are
expected to use, has child device objects in the ACPI namespace,
so the regression can be addressed as described above.

References: https://bugzilla.kernel.org/show_bug.cgi?id=60561
Reported-by: Peter Wu <lekensteyn@gmail.com>
Tested-by: Vladimir Lalov <mail@vlalov.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Cc: 3.9+ <stable@vger.kernel.org> # 3.9+
2013-08-07 22:55:00 +02:00
..
acpica ACPICA: expose OSI version 2013-07-18 01:29:14 +02:00
apei Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc 2013-07-04 10:29:23 -07:00
ac.c ACPI / AC: Add sleep quirk for Thinkpad e530 2013-05-12 14:03:15 +02:00
acpi_cmos_rtc.c ACPI: Add CMOS RTC Operation Region handler support 2013-06-27 21:35:37 +02:00
acpi_i2c.c ACPI / I2C: Use parent's ACPI_HANDLE() in acpi_i2c_register_devices() 2013-04-02 15:30:41 +02:00
acpi_ipmi.c
acpi_lpss.c Merge branch 'acpi-lpss' 2013-06-28 12:59:02 +02:00
acpi_memhotplug.c ACPI / memhotplug: Fix a stale pointer in error path 2013-07-15 01:26:18 +02:00
acpi_pad.c ACPI / acpi_pad: Used PTR_RET 2013-03-25 00:13:15 +01:00
acpi_platform.c ACPI / scan: Add special handler for Intel Lynxpoint LPSS devices 2013-03-21 22:44:38 +01:00
acpi_processor.c ACPI / processor: move try_offline_node() after acpi_unmap_lsapic() 2013-08-07 22:18:53 +02:00
battery.c ACPI / battery: Fix parsing _BIX return value 2013-07-30 14:00:42 +02:00
bgrt.c efi: Fix the ACPI BGRT driver for images located in EFI boot services memory 2012-09-29 12:21:03 -07:00
blacklist.c acpi: delete module.h include from files explicitly not needing it 2011-10-31 19:30:33 -04:00
bus.c ACPI: Remove useless initializers 2013-06-19 23:34:58 +02:00
button.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2013-05-01 17:51:54 -07:00
cm_sbs.c
container.c Merge branch 'acpi-assorted' 2013-04-28 01:54:08 +02:00
custom_method.c The sweeping change is to make add_taint() explicitly indicate whether to disable 2013-02-25 15:41:43 -08:00
debugfs.c acpi: add export.h to files using THIS_MODULE/EXPORT_SYMBOL 2011-10-31 19:30:34 -04:00
device_pm.c ACPI / PM: Fix corner case in acpi_bus_update_power() 2013-07-04 13:22:11 +02:00
dock.c ACPI / dock: Actually define acpi_dock_init() as void 2013-07-04 13:25:04 +02:00
ec_sys.c ACPI / EC: access user space with get_user()/put_user() 2013-06-19 23:29:20 +02:00
ec.c ACPI / EC: Add HP Folio 13 to ec_dmi_table in order to skip DSDT scan 2013-06-27 21:37:18 +02:00
event.c acpi: add export.h to files using THIS_MODULE/EXPORT_SYMBOL 2011-10-31 19:30:34 -04:00
fan.c ACPI / fan: Initialize acpi_state variable 2013-07-04 13:33:25 +02:00
glue.c ACPI: Try harder to resolve _ADR collisions for bridges 2013-08-07 22:55:00 +02:00
hed.c ACPI: Remove useless type argument of driver .remove() operation 2013-01-26 00:37:24 +01:00
internal.h Revert "ACPI / video / i915: No ACPI backlight if firmware expects Windows 8" 2013-07-26 14:59:20 +02:00
Kconfig Merge branch 'acpi-assorted' 2013-04-28 01:54:08 +02:00
Makefile Merge branch 'acpi-assorted' 2013-06-28 13:00:38 +02:00
numa.c x86, ACPI, mm: Revert movablemem_map support 2013-03-02 09:34:39 -08:00
nvs.c ACPI / PM: print physical addresses consistently with other parts of kernel 2012-03-30 02:46:57 -04:00
osl.c Merge branch 'acpi-assorted' 2013-06-29 15:03:44 +02:00
pci_irq.c PCI/ACPI: Don't cache _PRT, and don't associate them with bus numbers 2013-02-16 11:58:34 -07:00
pci_link.c ACPI: Set length even for TYPE_END_TAG acpi resource 2013-03-24 01:00:38 +01:00
pci_root.c PCI changes for the v3.11 merge window: 2013-07-03 16:31:35 -07:00
pci_slot.c PCI/ACPI: Handle PCI slot devices when creating/destroying PCI buses 2013-04-12 15:38:25 -06:00
power.c ACPI / power: add missing newline to debug messages 2013-07-05 13:30:20 +02:00
proc.c ACPI / PM: Walk physical_node_list under physical_node_lock 2013-08-06 02:26:22 +02:00
processor_core.c acpi: delete __cpuinit usage from all acpi files 2013-07-14 19:36:58 -04:00
processor_driver.c acpi: delete __cpuinit usage from all acpi files 2013-07-14 19:36:58 -04:00
processor_idle.c acpi: delete __cpuinit usage from all acpi files 2013-07-14 19:36:58 -04:00
processor_perflib.c ACPI / processor: Drop unused variable from processor_perflib.c 2013-06-25 23:05:24 +02:00
processor_thermal.c ACPI / processor_thermal: avoid null pointer deference error 2013-03-25 23:01:01 +01:00
processor_throttling.c ACPI: suppress compiler warnings in processor_throttling.c 2013-03-25 00:05:48 +01:00
reboot.c Revert "ACPI: ignore FADT reset-reg-sup flag" 2012-04-20 11:19:35 -07:00
resource.c ACPI / resources: call acpi_get_override_irq() only for legacy IRQ resources 2013-06-19 23:55:59 +02:00
sbs.c proc: Supply a function to remove a proc entry by PDE 2013-05-01 17:29:46 -04:00
sbshc.c ACPI: Remove useless type argument of driver .remove() operation 2013-01-26 00:37:24 +01:00
sbshc.h
scan.c ACPI / scan: Always call acpi_bus_scan() for bus check notifications 2013-07-15 01:26:18 +02:00
sleep.c x86 / ACPI / sleep: Provide registration for acpi_suspend_lowlevel. 2013-06-19 23:36:30 +02:00
sleep.h ACPI: Drop power resources driver 2013-01-17 14:11:06 +01:00
sysfs.c Merge branch 'akpm' (updates from Andrew Morton) 2013-07-03 17:12:13 -07:00
tables.c ACPICA: Cleanup table handler naming conflicts. 2013-01-11 13:10:16 +01:00
thermal.c ACPI / thermal: do not always return THERMAL_TREND_RAISING for active trip points 2013-04-26 13:34:40 +02:00
utils.c ACPI: Add acpi_handle_<level>() interfaces 2012-11-21 23:20:22 +01:00
video_detect.c Revert "ACPI / video / i915: No ACPI backlight if firmware expects Windows 8" 2013-07-26 14:59:20 +02:00
video.c ACPI / video: improve quirk check in acpi_video_bqc_quirk() 2013-08-04 23:45:39 +02:00
wakeup.c