]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Thomas Renninger <trenn@suse.de> |
2 | Subject: ACPI: video: Ignore devices that aren't present in hardware | |
3 | Patch-Mainline: queued for .28 in Len's/ak's ACPI tree | |
4 | ||
5 | commit ad9ed8385ed6ec5be8da7094db911c824258ceec | |
6 | ||
7 | This is a reimplemention of commit | |
8 | 0119509c4fbc9adcef1472817fda295334612976 | |
9 | from Matthew Garrett <mjg59@srcf.ucam.org> | |
10 | ||
11 | This patch got removed because of a regression: ThinkPads with a | |
12 | Intel graphics card and an Integrated Graphics Device BIOS implementation | |
13 | stopped working. | |
14 | In fact, they only worked because the ACPI device of the discrete, the | |
15 | wrong one, got used (via int10). So ACPI functions were poking on the wrong | |
16 | hardware used which is a sever bug. | |
17 | The next patch provides support for above ThinkPads to be able to | |
18 | switch brightness via the legacy thinkpad_acpi driver and automatically | |
19 | detect when to use it. | |
20 | ||
21 | Original commit message from Matthew Garrett: | |
22 | Vendors often ship machines with a choice of integrated or discrete | |
23 | graphics, and use the same DSDT for both. As a result, the ACPI video | |
24 | module will locate devices that may not exist on this specific platform. | |
25 | Attempt to determine whether the device exists or not, and abort the | |
26 | device creation if it doesn't. | |
27 | ||
28 | http://bugzilla.kernel.org/show_bug.cgi?id=9614 | |
29 | ||
30 | Signed-off-by: Thomas Renninger <trenn@suse.de> | |
31 | Signed-off-by: Andi Kleen <ak@linux.intel.com> | |
32 | ||
33 | --- | |
34 | drivers/acpi/glue.c | 40 ++++++++++++++++++++++++++++++++++++++++ | |
35 | drivers/acpi/video.c | 7 ++++++- | |
36 | include/acpi/acpi_bus.h | 2 ++ | |
37 | 3 files changed, 48 insertions(+), 1 deletion(-) | |
38 | ||
39 | --- a/drivers/acpi/glue.c | |
40 | +++ b/drivers/acpi/glue.c | |
41 | @@ -140,6 +140,46 @@ struct device *acpi_get_physical_device( | |
42 | ||
43 | EXPORT_SYMBOL(acpi_get_physical_device); | |
44 | ||
45 | +/* ToDo: When a PCI bridge is found, return the PCI device behind the bridge | |
46 | + * This should work in general, but did not on a Lenovo T61 for the | |
47 | + * graphics card. But this must be fixed when the PCI device is | |
48 | + * bound and the kernel device struct is attached to the acpi device | |
49 | + * Note: A success call will increase reference count by one | |
50 | + * Do call put_device(dev) on the returned device then | |
51 | + */ | |
52 | +struct device *acpi_get_physical_pci_device(acpi_handle handle) | |
53 | +{ | |
54 | + struct device *dev; | |
55 | + long long device_id; | |
56 | + acpi_status status; | |
57 | + | |
58 | + status = | |
59 | + acpi_evaluate_integer(handle, "_ADR", NULL, &device_id); | |
60 | + | |
61 | + if (ACPI_FAILURE(status)) | |
62 | + return NULL; | |
63 | + | |
64 | + /* We need to attempt to determine whether the _ADR refers to a | |
65 | + PCI device or not. There's no terribly good way to do this, | |
66 | + so the best we can hope for is to assume that there'll never | |
67 | + be a device in the host bridge */ | |
68 | + if (device_id >= 0x10000) { | |
69 | + /* It looks like a PCI device. Does it exist? */ | |
70 | + dev = acpi_get_physical_device(handle); | |
71 | + } else { | |
72 | + /* It doesn't look like a PCI device. Does its parent | |
73 | + exist? */ | |
74 | + acpi_handle phandle; | |
75 | + if (acpi_get_parent(handle, &phandle)) | |
76 | + return NULL; | |
77 | + dev = acpi_get_physical_device(phandle); | |
78 | + } | |
79 | + if (!dev) | |
80 | + return NULL; | |
81 | + return dev; | |
82 | +} | |
83 | +EXPORT_SYMBOL(acpi_get_physical_pci_device); | |
84 | + | |
85 | static int acpi_bind_one(struct device *dev, acpi_handle handle) | |
86 | { | |
87 | struct acpi_device *acpi_dev; | |
88 | --- a/drivers/acpi/video.c | |
89 | +++ b/drivers/acpi/video.c | |
90 | @@ -862,11 +862,16 @@ static void acpi_video_bus_find_cap(stru | |
91 | static int acpi_video_bus_check(struct acpi_video_bus *video) | |
92 | { | |
93 | acpi_status status = -ENOENT; | |
94 | - | |
95 | + struct device *dev; | |
96 | ||
97 | if (!video) | |
98 | return -EINVAL; | |
99 | ||
100 | + dev = acpi_get_physical_pci_device(video->device->handle); | |
101 | + if (!dev) | |
102 | + return -ENODEV; | |
103 | + put_device(dev); | |
104 | + | |
105 | /* Since there is no HID, CID and so on for VGA driver, we have | |
106 | * to check well known required nodes. | |
107 | */ | |
108 | --- a/include/acpi/acpi_bus.h | |
109 | +++ b/include/acpi/acpi_bus.h | |
110 | @@ -373,6 +373,8 @@ struct acpi_bus_type { | |
111 | int register_acpi_bus_type(struct acpi_bus_type *); | |
112 | int unregister_acpi_bus_type(struct acpi_bus_type *); | |
113 | struct device *acpi_get_physical_device(acpi_handle); | |
114 | +struct device *acpi_get_physical_pci_device(acpi_handle); | |
115 | + | |
116 | /* helper */ | |
117 | acpi_handle acpi_get_child(acpi_handle, acpi_integer); | |
118 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); |