aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-08-02 17:15:27 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-08-02 17:15:27 -0400
commit0ce166b7b46122bf91a4766e20c85a6485448765 (patch)
tree6ec6e5fd60c48936428af0a19dc1f8dc77016570
parent57d7f282271a83fe4ca4bd15eee79be577210210 (diff)
parent3be4ee5199ba20475749d768bf29c8399c755a69 (diff)
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: eeepc-laptop: fix hot-unplug on resume ACPI: Ingore the memory block with zero block size in course of memory hotplug ACPI: Don't treat generic error as ACPI error code in acpi memory hotplug driver ACPI: bind workqueues to CPU 0 to avoid SMI corruption ACPI: root-only read protection on /sys/firmware/acpi/tables/* thinkpad-acpi: fix incorrect use of TPACPI_BRGHT_MODE_ECNVRAM thinkpad-acpi: restrict procfs count value to sane upper limit thinkpad-acpi: remove dock and bay subdrivers thinkpad-acpi: disable broken bay and dock subdrivers hp-wmi: check that an input device exists in resume handler Revert "ACPICA: Remove obsolete acpi_os_validate_address interface"
-rw-r--r--Documentation/laptops/thinkpad-acpi.txt127
-rw-r--r--drivers/acpi/acpi_memhotplug.c34
-rw-r--r--drivers/acpi/acpica/acobject.h1
-rw-r--r--drivers/acpi/acpica/dsopcode.c24
-rw-r--r--drivers/acpi/acpica/exfldio.c6
-rw-r--r--drivers/acpi/osl.c25
-rw-r--r--drivers/acpi/system.c2
-rw-r--r--drivers/platform/x86/Kconfig25
-rw-r--r--drivers/platform/x86/eeepc-laptop.c9
-rw-r--r--drivers/platform/x86/hp-wmi.c12
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c390
-rw-r--r--include/acpi/acpiosxf.h4
12 files changed, 148 insertions, 511 deletions
diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
index f2296ecedb89..e2ddcdeb61b6 100644
--- a/Documentation/laptops/thinkpad-acpi.txt
+++ b/Documentation/laptops/thinkpad-acpi.txt
@@ -36,8 +36,6 @@ detailed description):
36 - Bluetooth enable and disable 36 - Bluetooth enable and disable
37 - video output switching, expansion control 37 - video output switching, expansion control
38 - ThinkLight on and off 38 - ThinkLight on and off
39 - limited docking and undocking
40 - UltraBay eject
41 - CMOS/UCMS control 39 - CMOS/UCMS control
42 - LED control 40 - LED control
43 - ACPI sounds 41 - ACPI sounds
@@ -729,131 +727,6 @@ cannot be read or if it is unknown, thinkpad-acpi will report it as "off".
729It is impossible to know if the status returned through sysfs is valid. 727It is impossible to know if the status returned through sysfs is valid.
730 728
731 729
732Docking / undocking -- /proc/acpi/ibm/dock
733------------------------------------------
734
735Docking and undocking (e.g. with the X4 UltraBase) requires some
736actions to be taken by the operating system to safely make or break
737the electrical connections with the dock.
738
739The docking feature of this driver generates the following ACPI events:
740
741 ibm/dock GDCK 00000003 00000001 -- eject request
742 ibm/dock GDCK 00000003 00000002 -- undocked
743 ibm/dock GDCK 00000000 00000003 -- docked
744
745NOTE: These events will only be generated if the laptop was docked
746when originally booted. This is due to the current lack of support for
747hot plugging of devices in the Linux ACPI framework. If the laptop was
748booted while not in the dock, the following message is shown in the
749logs:
750
751 Mar 17 01:42:34 aero kernel: thinkpad_acpi: dock device not present
752
753In this case, no dock-related events are generated but the dock and
754undock commands described below still work. They can be executed
755manually or triggered by Fn key combinations (see the example acpid
756configuration files included in the driver tarball package available
757on the web site).
758
759When the eject request button on the dock is pressed, the first event
760above is generated. The handler for this event should issue the
761following command:
762
763 echo undock > /proc/acpi/ibm/dock
764
765After the LED on the dock goes off, it is safe to eject the laptop.
766Note: if you pressed this key by mistake, go ahead and eject the
767laptop, then dock it back in. Otherwise, the dock may not function as
768expected.
769
770When the laptop is docked, the third event above is generated. The
771handler for this event should issue the following command to fully
772enable the dock:
773
774 echo dock > /proc/acpi/ibm/dock
775
776The contents of the /proc/acpi/ibm/dock file shows the current status
777of the dock, as provided by the ACPI framework.
778
779The docking support in this driver does not take care of enabling or
780disabling any other devices you may have attached to the dock. For
781example, a CD drive plugged into the UltraBase needs to be disabled or
782enabled separately. See the provided example acpid configuration files
783for how this can be accomplished.
784
785There is no support yet for PCI devices that may be attached to a
786docking station, e.g. in the ThinkPad Dock II. The driver currently
787does not recognize, enable or disable such devices. This means that
788the only docking stations currently supported are the X-series
789UltraBase docks and "dumb" port replicators like the Mini Dock (the
790latter don't need any ACPI support, actually).
791
792
793UltraBay eject -- /proc/acpi/ibm/bay
794------------------------------------
795
796Inserting or ejecting an UltraBay device requires some actions to be
797taken by the operating system to safely make or break the electrical
798connections with the device.
799
800This feature generates the following ACPI events:
801
802 ibm/bay MSTR 00000003 00000000 -- eject request
803 ibm/bay MSTR 00000001 00000000 -- eject lever inserted
804
805NOTE: These events will only be generated if the UltraBay was present
806when the laptop was originally booted (on the X series, the UltraBay
807is in the dock, so it may not be present if the laptop was undocked).
808This is due to the current lack of support for hot plugging of devices
809in the Linux ACPI framework. If the laptop was booted without the
810UltraBay, the following message is shown in the logs:
811
812 Mar 17 01:42:34 aero kernel: thinkpad_acpi: bay device not present
813
814In this case, no bay-related events are generated but the eject
815command described below still works. It can be executed manually or
816triggered by a hot key combination.
817
818Sliding the eject lever generates the first event shown above. The
819handler for this event should take whatever actions are necessary to
820shut down the device in the UltraBay (e.g. call idectl), then issue
821the following command:
822
823 echo eject > /proc/acpi/ibm/bay
824
825After the LED on the UltraBay goes off, it is safe to pull out the
826device.
827
828When the eject lever is inserted, the second event above is
829generated. The handler for this event should take whatever actions are
830necessary to enable the UltraBay device (e.g. call idectl).
831
832The contents of the /proc/acpi/ibm/bay file shows the current status
833of the UltraBay, as provided by the ACPI framework.
834
835EXPERIMENTAL warm eject support on the 600e/x, A22p and A3x (To use
836this feature, you need to supply the experimental=1 parameter when
837loading the module):
838
839These models do not have a button near the UltraBay device to request
840a hot eject but rather require the laptop to be put to sleep
841(suspend-to-ram) before the bay device is ejected or inserted).
842The sequence of steps to eject the device is as follows:
843
844 echo eject > /proc/acpi/ibm/bay
845 put the ThinkPad to sleep
846 remove the drive
847 resume from sleep
848 cat /proc/acpi/ibm/bay should show that the drive was removed
849
850On the A3x, both the UltraBay 2000 and UltraBay Plus devices are
851supported. Use "eject2" instead of "eject" for the second bay.
852
853Note: the UltraBay eject support on the 600e/x, A22p and A3x is
854EXPERIMENTAL and may not work as expected. USE WITH CAUTION!
855
856
857CMOS/UCMS control 730CMOS/UCMS control
858----------------- 731-----------------
859 732
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 7a0f4aa4fa1e..9a62224cc278 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -38,6 +38,9 @@
38 38
39#define _COMPONENT ACPI_MEMORY_DEVICE_COMPONENT 39#define _COMPONENT ACPI_MEMORY_DEVICE_COMPONENT
40 40
41#undef PREFIX
42#define PREFIX "ACPI:memory_hp:"
43
41ACPI_MODULE_NAME("acpi_memhotplug"); 44ACPI_MODULE_NAME("acpi_memhotplug");
42MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>"); 45MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
43MODULE_DESCRIPTION("Hotplug Mem Driver"); 46MODULE_DESCRIPTION("Hotplug Mem Driver");
@@ -153,6 +156,7 @@ acpi_memory_get_device(acpi_handle handle,
153 acpi_handle phandle; 156 acpi_handle phandle;
154 struct acpi_device *device = NULL; 157 struct acpi_device *device = NULL;
155 struct acpi_device *pdevice = NULL; 158 struct acpi_device *pdevice = NULL;
159 int result;
156 160
157 161
158 if (!acpi_bus_get_device(handle, &device) && device) 162 if (!acpi_bus_get_device(handle, &device) && device)
@@ -165,9 +169,9 @@ acpi_memory_get_device(acpi_handle handle,
165 } 169 }
166 170
167 /* Get the parent device */ 171 /* Get the parent device */
168 status = acpi_bus_get_device(phandle, &pdevice); 172 result = acpi_bus_get_device(phandle, &pdevice);
169 if (ACPI_FAILURE(status)) { 173 if (result) {
170 ACPI_EXCEPTION((AE_INFO, status, "Cannot get acpi bus device")); 174 printk(KERN_WARNING PREFIX "Cannot get acpi bus device");
171 return -EINVAL; 175 return -EINVAL;
172 } 176 }
173 177
@@ -175,9 +179,9 @@ acpi_memory_get_device(acpi_handle handle,
175 * Now add the notified device. This creates the acpi_device 179 * Now add the notified device. This creates the acpi_device
176 * and invokes .add function 180 * and invokes .add function
177 */ 181 */
178 status = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE); 182 result = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE);
179 if (ACPI_FAILURE(status)) { 183 if (result) {
180 ACPI_EXCEPTION((AE_INFO, status, "Cannot add acpi bus")); 184 printk(KERN_WARNING PREFIX "Cannot add acpi bus");
181 return -EINVAL; 185 return -EINVAL;
182 } 186 }
183 187
@@ -238,7 +242,12 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
238 num_enabled++; 242 num_enabled++;
239 continue; 243 continue;
240 } 244 }
241 245 /*
246 * If the memory block size is zero, please ignore it.
247 * Don't try to do the following memory hotplug flowchart.
248 */
249 if (!info->length)
250 continue;
242 if (node < 0) 251 if (node < 0)
243 node = memory_add_physaddr_to_nid(info->start_addr); 252 node = memory_add_physaddr_to_nid(info->start_addr);
244 253
@@ -253,8 +262,15 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
253 mem_device->state = MEMORY_INVALID_STATE; 262 mem_device->state = MEMORY_INVALID_STATE;
254 return -EINVAL; 263 return -EINVAL;
255 } 264 }
256 265 /*
257 return result; 266 * Sometimes the memory device will contain several memory blocks.
267 * When one memory block is hot-added to the system memory, it will
268 * be regarded as a success.
269 * Otherwise if the last memory block can't be hot-added to the system
270 * memory, it will be failure and the memory device can't be bound with
271 * driver.
272 */
273 return 0;
258} 274}
259 275
260static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device) 276static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h
index 544dcf834922..eb6f038b03d9 100644
--- a/drivers/acpi/acpica/acobject.h
+++ b/drivers/acpi/acpica/acobject.h
@@ -97,6 +97,7 @@
97#define AOPOBJ_OBJECT_INITIALIZED 0x08 97#define AOPOBJ_OBJECT_INITIALIZED 0x08
98#define AOPOBJ_SETUP_COMPLETE 0x10 98#define AOPOBJ_SETUP_COMPLETE 0x10
99#define AOPOBJ_SINGLE_DATUM 0x20 99#define AOPOBJ_SINGLE_DATUM 0x20
100#define AOPOBJ_INVALID 0x40 /* Used if host OS won't allow an op_region address */
100 101
101/****************************************************************************** 102/******************************************************************************
102 * 103 *
diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c
index 584d766e6f12..b79978f7bc71 100644
--- a/drivers/acpi/acpica/dsopcode.c
+++ b/drivers/acpi/acpica/dsopcode.c
@@ -397,6 +397,30 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
397 status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), 397 status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
398 extra_desc->extra.aml_length, 398 extra_desc->extra.aml_length,
399 extra_desc->extra.aml_start); 399 extra_desc->extra.aml_start);
400 if (ACPI_FAILURE(status)) {
401 return_ACPI_STATUS(status);
402 }
403
404 /* Validate the region address/length via the host OS */
405
406 status = acpi_os_validate_address(obj_desc->region.space_id,
407 obj_desc->region.address,
408 (acpi_size) obj_desc->region.length,
409 acpi_ut_get_node_name(node));
410
411 if (ACPI_FAILURE(status)) {
412 /*
413 * Invalid address/length. We will emit an error message and mark
414 * the region as invalid, so that it will cause an additional error if
415 * it is ever used. Then return AE_OK.
416 */
417 ACPI_EXCEPTION((AE_INFO, status,
418 "During address validation of OpRegion [%4.4s]",
419 node->name.ascii));
420 obj_desc->common.flags |= AOPOBJ_INVALID;
421 status = AE_OK;
422 }
423
400 return_ACPI_STATUS(status); 424 return_ACPI_STATUS(status);
401} 425}
402 426
diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c
index d4075b821021..6687be167f5f 100644
--- a/drivers/acpi/acpica/exfldio.c
+++ b/drivers/acpi/acpica/exfldio.c
@@ -113,6 +113,12 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
113 } 113 }
114 } 114 }
115 115
116 /* Exit if Address/Length have been disallowed by the host OS */
117
118 if (rgn_desc->common.flags & AOPOBJ_INVALID) {
119 return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS);
120 }
121
116 /* 122 /*
117 * Exit now for SMBus address space, it has a non-linear address space 123 * Exit now for SMBus address space, it has a non-linear address space
118 * and the request cannot be directly validated 124 * and the request cannot be directly validated
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 71670719d61a..5691f165a952 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -189,11 +189,36 @@ acpi_status __init acpi_os_initialize(void)
189 return AE_OK; 189 return AE_OK;
190} 190}
191 191
192static void bind_to_cpu0(struct work_struct *work)
193{
194 set_cpus_allowed(current, cpumask_of_cpu(0));
195 kfree(work);
196}
197
198static void bind_workqueue(struct workqueue_struct *wq)
199{
200 struct work_struct *work;
201
202 work = kzalloc(sizeof(struct work_struct), GFP_KERNEL);
203 INIT_WORK(work, bind_to_cpu0);
204 queue_work(wq, work);
205}
206
192acpi_status acpi_os_initialize1(void) 207acpi_status acpi_os_initialize1(void)
193{ 208{
209 /*
210 * On some machines, a software-initiated SMI causes corruption unless
211 * the SMI runs on CPU 0. An SMI can be initiated by any AML, but
212 * typically it's done in GPE-related methods that are run via
213 * workqueues, so we can avoid the known corruption cases by binding
214 * the workqueues to CPU 0.
215 */
194 kacpid_wq = create_singlethread_workqueue("kacpid"); 216 kacpid_wq = create_singlethread_workqueue("kacpid");
217 bind_workqueue(kacpid_wq);
195 kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); 218 kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify");
219 bind_workqueue(kacpi_notify_wq);
196 kacpi_hotplug_wq = create_singlethread_workqueue("kacpi_hotplug"); 220 kacpi_hotplug_wq = create_singlethread_workqueue("kacpi_hotplug");
221 bind_workqueue(kacpi_hotplug_wq);
197 BUG_ON(!kacpid_wq); 222 BUG_ON(!kacpid_wq);
198 BUG_ON(!kacpi_notify_wq); 223 BUG_ON(!kacpi_notify_wq);
199 BUG_ON(!kacpi_hotplug_wq); 224 BUG_ON(!kacpi_hotplug_wq);
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index 0944daec064f..9c61ab2177cf 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -121,7 +121,7 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr,
121 table_attr->attr.size = 0; 121 table_attr->attr.size = 0;
122 table_attr->attr.read = acpi_table_show; 122 table_attr->attr.read = acpi_table_show;
123 table_attr->attr.attr.name = table_attr->name; 123 table_attr->attr.attr.name = table_attr->name;
124 table_attr->attr.attr.mode = 0444; 124 table_attr->attr.attr.mode = 0400;
125 125
126 return; 126 return;
127} 127}
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 46dad12f952f..77c6097ced80 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -277,31 +277,6 @@ config THINKPAD_ACPI_UNSAFE_LEDS
277 Say N here, unless you are building a kernel for your own 277 Say N here, unless you are building a kernel for your own
278 use, and need to control the important firmware LEDs. 278 use, and need to control the important firmware LEDs.
279 279
280config THINKPAD_ACPI_DOCK
281 bool "Legacy Docking Station Support"
282 depends on THINKPAD_ACPI
283 depends on ACPI_DOCK=n
284 default n
285 ---help---
286 Allows the thinkpad_acpi driver to handle docking station events.
287 This support was made obsolete by the generic ACPI docking station
288 support (CONFIG_ACPI_DOCK). It will allow locking and removing the
289 laptop from the docking station, but will not properly connect PCI
290 devices.
291
292 If you are not sure, say N here.
293
294config THINKPAD_ACPI_BAY
295 bool "Legacy Removable Bay Support"
296 depends on THINKPAD_ACPI
297 default y
298 ---help---
299 Allows the thinkpad_acpi driver to handle removable bays. It will
300 electrically disable the device in the bay, and also generate
301 notifications when the bay lever is ejected or inserted.
302
303 If you are not sure, say Y here.
304
305config THINKPAD_ACPI_VIDEO 280config THINKPAD_ACPI_VIDEO
306 bool "Video output control support" 281 bool "Video output control support"
307 depends on THINKPAD_ACPI 282 depends on THINKPAD_ACPI
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index ec560f16d720..222ffb892f22 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -143,6 +143,7 @@ struct eeepc_hotk {
143 struct rfkill *bluetooth_rfkill; 143 struct rfkill *bluetooth_rfkill;
144 struct rfkill *wwan3g_rfkill; 144 struct rfkill *wwan3g_rfkill;
145 struct hotplug_slot *hotplug_slot; 145 struct hotplug_slot *hotplug_slot;
146 struct work_struct hotplug_work;
146}; 147};
147 148
148/* The actual device the driver binds to */ 149/* The actual device the driver binds to */
@@ -660,7 +661,7 @@ static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
660 return 0; 661 return 0;
661} 662}
662 663
663static void eeepc_rfkill_hotplug(void) 664static void eeepc_hotplug_work(struct work_struct *work)
664{ 665{
665 struct pci_dev *dev; 666 struct pci_dev *dev;
666 struct pci_bus *bus = pci_find_bus(0, 1); 667 struct pci_bus *bus = pci_find_bus(0, 1);
@@ -701,7 +702,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
701 if (event != ACPI_NOTIFY_BUS_CHECK) 702 if (event != ACPI_NOTIFY_BUS_CHECK)
702 return; 703 return;
703 704
704 eeepc_rfkill_hotplug(); 705 schedule_work(&ehotk->hotplug_work);
705} 706}
706 707
707static void eeepc_hotk_notify(struct acpi_device *device, u32 event) 708static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
@@ -892,7 +893,7 @@ static int eeepc_hotk_resume(struct acpi_device *device)
892 893
893 rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1); 894 rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1);
894 895
895 eeepc_rfkill_hotplug(); 896 schedule_work(&ehotk->hotplug_work);
896 } 897 }
897 898
898 if (ehotk->bluetooth_rfkill) 899 if (ehotk->bluetooth_rfkill)
@@ -1093,6 +1094,8 @@ static int eeepc_rfkill_init(struct device *dev)
1093{ 1094{
1094 int result = 0; 1095 int result = 0;
1095 1096
1097 INIT_WORK(&ehotk->hotplug_work, eeepc_hotplug_work);
1098
1096 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); 1099 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
1097 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); 1100 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
1098 1101
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index ca508564a181..a2ad53e15874 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -520,11 +520,13 @@ static int hp_wmi_resume_handler(struct platform_device *device)
520 * the input layer will only actually pass it on if the state 520 * the input layer will only actually pass it on if the state
521 * changed. 521 * changed.
522 */ 522 */
523 523 if (hp_wmi_input_dev) {
524 input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state()); 524 input_report_switch(hp_wmi_input_dev, SW_DOCK,
525 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, 525 hp_wmi_dock_state());
526 hp_wmi_tablet_state()); 526 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
527 input_sync(hp_wmi_input_dev); 527 hp_wmi_tablet_state());
528 input_sync(hp_wmi_input_dev);
529 }
528 530
529 return 0; 531 return 0;
530} 532}
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index a463fd72c495..e85600852502 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -239,12 +239,6 @@ struct ibm_init_struct {
239}; 239};
240 240
241static struct { 241static struct {
242#ifdef CONFIG_THINKPAD_ACPI_BAY
243 u32 bay_status:1;
244 u32 bay_eject:1;
245 u32 bay_status2:1;
246 u32 bay_eject2:1;
247#endif
248 u32 bluetooth:1; 242 u32 bluetooth:1;
249 u32 hotkey:1; 243 u32 hotkey:1;
250 u32 hotkey_mask:1; 244 u32 hotkey_mask:1;
@@ -589,18 +583,6 @@ static int acpi_ec_write(int i, u8 v)
589 return 1; 583 return 1;
590} 584}
591 585
592#if defined(CONFIG_THINKPAD_ACPI_DOCK) || defined(CONFIG_THINKPAD_ACPI_BAY)
593static int _sta(acpi_handle handle)
594{
595 int status;
596
597 if (!handle || !acpi_evalf(handle, &status, "_STA", "d"))
598 status = 0;
599
600 return status;
601}
602#endif
603
604static int issue_thinkpad_cmos_command(int cmos_cmd) 586static int issue_thinkpad_cmos_command(int cmos_cmd)
605{ 587{
606 if (!cmos_handle) 588 if (!cmos_handle)
@@ -784,6 +766,8 @@ static int dispatch_procfs_write(struct file *file,
784 766
785 if (!ibm || !ibm->write) 767 if (!ibm || !ibm->write)
786 return -EINVAL; 768 return -EINVAL;
769 if (count > PAGE_SIZE - 2)
770 return -EINVAL;
787 771
788 kernbuf = kmalloc(count + 2, GFP_KERNEL); 772 kernbuf = kmalloc(count + 2, GFP_KERNEL);
789 if (!kernbuf) 773 if (!kernbuf)
@@ -4442,293 +4426,6 @@ static struct ibm_struct light_driver_data = {
4442}; 4426};
4443 4427
4444/************************************************************************* 4428/*************************************************************************
4445 * Dock subdriver
4446 */
4447
4448#ifdef CONFIG_THINKPAD_ACPI_DOCK
4449
4450static void dock_notify(struct ibm_struct *ibm, u32 event);
4451static int dock_read(char *p);
4452static int dock_write(char *buf);
4453
4454TPACPI_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */
4455 "\\_SB.PCI0.DOCK", /* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */
4456 "\\_SB.PCI0.PCI1.DOCK", /* all others */
4457 "\\_SB.PCI.ISA.SLCE", /* 570 */
4458 ); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */
4459
4460/* don't list other alternatives as we install a notify handler on the 570 */
4461TPACPI_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */
4462
4463static const struct acpi_device_id ibm_pci_device_ids[] = {
4464 {PCI_ROOT_HID_STRING, 0},
4465 {"", 0},
4466};
4467
4468static struct tp_acpi_drv_struct ibm_dock_acpidriver[2] = {
4469 {
4470 .notify = dock_notify,
4471 .handle = &dock_handle,
4472 .type = ACPI_SYSTEM_NOTIFY,
4473 },
4474 {
4475 /* THIS ONE MUST NEVER BE USED FOR DRIVER AUTOLOADING.
4476 * We just use it to get notifications of dock hotplug
4477 * in very old thinkpads */
4478 .hid = ibm_pci_device_ids,
4479 .notify = dock_notify,
4480 .handle = &pci_handle,
4481 .type = ACPI_SYSTEM_NOTIFY,
4482 },
4483};
4484
4485static struct ibm_struct dock_driver_data[2] = {
4486 {
4487 .name = "dock",
4488 .read = dock_read,
4489 .write = dock_write,
4490 .acpi = &ibm_dock_acpidriver[0],
4491 },
4492 {
4493 .name = "dock",
4494 .acpi = &ibm_dock_acpidriver[1],
4495 },
4496};
4497
4498#define dock_docked() (_sta(dock_handle) & 1)
4499
4500static int __init dock_init(struct ibm_init_struct *iibm)
4501{
4502 vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver\n");
4503
4504 TPACPI_ACPIHANDLE_INIT(dock);
4505
4506 vdbg_printk(TPACPI_DBG_INIT, "dock is %s\n",
4507 str_supported(dock_handle != NULL));
4508
4509 return (dock_handle)? 0 : 1;
4510}
4511
4512static int __init dock_init2(struct ibm_init_struct *iibm)
4513{
4514 int dock2_needed;
4515
4516 vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver part 2\n");
4517
4518 if (dock_driver_data[0].flags.acpi_driver_registered &&
4519 dock_driver_data[0].flags.acpi_notify_installed) {
4520 TPACPI_ACPIHANDLE_INIT(pci);
4521 dock2_needed = (pci_handle != NULL);
4522 vdbg_printk(TPACPI_DBG_INIT,
4523 "dock PCI handler for the TP 570 is %s\n",
4524 str_supported(dock2_needed));
4525 } else {
4526 vdbg_printk(TPACPI_DBG_INIT,
4527 "dock subdriver part 2 not required\n");
4528 dock2_needed = 0;
4529 }
4530
4531 return (dock2_needed)? 0 : 1;
4532}
4533
4534static void dock_notify(struct ibm_struct *ibm, u32 event)
4535{
4536 int docked = dock_docked();
4537 int pci = ibm->acpi->hid && ibm->acpi->device &&
4538 acpi_match_device_ids(ibm->acpi->device, ibm_pci_device_ids);
4539 int data;
4540
4541 if (event == 1 && !pci) /* 570 */
4542 data = 1; /* button */
4543 else if (event == 1 && pci) /* 570 */
4544 data = 3; /* dock */
4545 else if (event == 3 && docked)
4546 data = 1; /* button */
4547 else if (event == 3 && !docked)
4548 data = 2; /* undock */
4549 else if (event == 0 && docked)
4550 data = 3; /* dock */
4551 else {
4552 printk(TPACPI_ERR "unknown dock event %d, status %d\n",
4553 event, _sta(dock_handle));
4554 data = 0; /* unknown */
4555 }
4556 acpi_bus_generate_proc_event(ibm->acpi->device, event, data);
4557 acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
4558 dev_name(&ibm->acpi->device->dev),
4559 event, data);
4560}
4561
4562static int dock_read(char *p)
4563{
4564 int len = 0;
4565 int docked = dock_docked();
4566
4567 if (!dock_handle)
4568 len += sprintf(p + len, "status:\t\tnot supported\n");
4569 else if (!docked)
4570 len += sprintf(p + len, "status:\t\tundocked\n");
4571 else {
4572 len += sprintf(p + len, "status:\t\tdocked\n");
4573 len += sprintf(p + len, "commands:\tdock, undock\n");
4574 }
4575
4576 return len;
4577}
4578
4579static int dock_write(char *buf)
4580{
4581 char *cmd;
4582
4583 if (!dock_docked())
4584 return -ENODEV;
4585
4586 while ((cmd = next_cmd(&buf))) {
4587 if (strlencmp(cmd, "undock") == 0) {
4588 if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 0) ||
4589 !acpi_evalf(dock_handle, NULL, "_EJ0", "vd", 1))
4590 return -EIO;
4591 } else if (strlencmp(cmd, "dock") == 0) {
4592 if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 1))
4593 return -EIO;
4594 } else
4595 return -EINVAL;
4596 }
4597
4598 return 0;
4599}
4600
4601#endif /* CONFIG_THINKPAD_ACPI_DOCK */
4602
4603/*************************************************************************
4604 * Bay subdriver
4605 */
4606
4607#ifdef CONFIG_THINKPAD_ACPI_BAY
4608
4609TPACPI_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */
4610 "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */
4611 "\\_SB.PCI0.SATA.SCND.MSTR", /* T60, X60, Z60 */
4612 "\\_SB.PCI0.IDE0.SCND.MSTR", /* all others */
4613 ); /* A21e, R30, R31 */
4614TPACPI_HANDLE(bay_ej, bay, "_EJ3", /* 600e/x, A2xm/p, A3x */
4615 "_EJ0", /* all others */
4616 ); /* 570,A21e,G4x,R30,R31,R32,R40e,R50e */
4617TPACPI_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV", /* A3x, R32 */
4618 "\\_SB.PCI0.IDE0.IDEP.IDPS", /* 600e/x, 770e, 770x */
4619 ); /* all others */
4620TPACPI_HANDLE(bay2_ej, bay2, "_EJ3", /* 600e/x, 770e, A3x */
4621 "_EJ0", /* 770x */
4622 ); /* all others */
4623
4624static int __init bay_init(struct ibm_init_struct *iibm)
4625{
4626 vdbg_printk(TPACPI_DBG_INIT, "initializing bay subdriver\n");
4627
4628 TPACPI_ACPIHANDLE_INIT(bay);
4629 if (bay_handle)
4630 TPACPI_ACPIHANDLE_INIT(bay_ej);
4631 TPACPI_ACPIHANDLE_INIT(bay2);
4632 if (bay2_handle)
4633 TPACPI_ACPIHANDLE_INIT(bay2_ej);
4634
4635 tp_features.bay_status = bay_handle &&
4636 acpi_evalf(bay_handle, NULL, "_STA", "qv");
4637 tp_features.bay_status2 = bay2_handle &&
4638 acpi_evalf(bay2_handle, NULL, "_STA", "qv");
4639
4640 tp_features.bay_eject = bay_handle && bay_ej_handle &&
4641 (strlencmp(bay_ej_path, "_EJ0") == 0 || experimental);
4642 tp_features.bay_eject2 = bay2_handle && bay2_ej_handle &&
4643 (strlencmp(bay2_ej_path, "_EJ0") == 0 || experimental);
4644
4645 vdbg_printk(TPACPI_DBG_INIT,
4646 "bay 1: status %s, eject %s; bay 2: status %s, eject %s\n",
4647 str_supported(tp_features.bay_status),
4648 str_supported(tp_features.bay_eject),
4649 str_supported(tp_features.bay_status2),
4650 str_supported(tp_features.bay_eject2));
4651
4652 return (tp_features.bay_status || tp_features.bay_eject ||
4653 tp_features.bay_status2 || tp_features.bay_eject2)? 0 : 1;
4654}
4655
4656static void bay_notify(struct ibm_struct *ibm, u32 event)
4657{
4658 acpi_bus_generate_proc_event(ibm->acpi->device, event, 0);
4659 acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
4660 dev_name(&ibm->acpi->device->dev),
4661 event, 0);
4662}
4663
4664#define bay_occupied(b) (_sta(b##_handle) & 1)
4665
4666static int bay_read(char *p)
4667{
4668 int len = 0;
4669 int occupied = bay_occupied(bay);
4670 int occupied2 = bay_occupied(bay2);
4671 int eject, eject2;
4672
4673 len += sprintf(p + len, "status:\t\t%s\n",
4674 tp_features.bay_status ?
4675 (occupied ? "occupied" : "unoccupied") :
4676 "not supported");
4677 if (tp_features.bay_status2)
4678 len += sprintf(p + len, "status2:\t%s\n", occupied2 ?
4679 "occupied" : "unoccupied");
4680
4681 eject = tp_features.bay_eject && occupied;
4682 eject2 = tp_features.bay_eject2 && occupied2;
4683
4684 if (eject && eject2)
4685 len += sprintf(p + len, "commands:\teject, eject2\n");
4686 else if (eject)
4687 len += sprintf(p + len, "commands:\teject\n");
4688 else if (eject2)
4689 len += sprintf(p + len, "commands:\teject2\n");
4690
4691 return len;
4692}
4693
4694static int bay_write(char *buf)
4695{
4696 char *cmd;
4697
4698 if (!tp_features.bay_eject && !tp_features.bay_eject2)
4699 return -ENODEV;
4700
4701 while ((cmd = next_cmd(&buf))) {
4702 if (tp_features.bay_eject && strlencmp(cmd, "eject") == 0) {
4703 if (!acpi_evalf(bay_ej_handle, NULL, NULL, "vd", 1))
4704 return -EIO;
4705 } else if (tp_features.bay_eject2 &&
4706 strlencmp(cmd, "eject2") == 0) {
4707 if (!acpi_evalf(bay2_ej_handle, NULL, NULL, "vd", 1))
4708 return -EIO;
4709 } else
4710 return -EINVAL;
4711 }
4712
4713 return 0;
4714}
4715
4716static struct tp_acpi_drv_struct ibm_bay_acpidriver = {
4717 .notify = bay_notify,
4718 .handle = &bay_handle,
4719 .type = ACPI_SYSTEM_NOTIFY,
4720};
4721
4722static struct ibm_struct bay_driver_data = {
4723 .name = "bay",
4724 .read = bay_read,
4725 .write = bay_write,
4726 .acpi = &ibm_bay_acpidriver,
4727};
4728
4729#endif /* CONFIG_THINKPAD_ACPI_BAY */
4730
4731/*************************************************************************
4732 * CMOS subdriver 4429 * CMOS subdriver
4733 */ 4430 */
4734 4431
@@ -5945,14 +5642,48 @@ static struct backlight_ops ibm_backlight_data = {
5945 5642
5946/* --------------------------------------------------------------------- */ 5643/* --------------------------------------------------------------------- */
5947 5644
5645/*
5646 * These are only useful for models that have only one possibility
5647 * of GPU. If the BIOS model handles both ATI and Intel, don't use
5648 * these quirks.
5649 */
5650#define TPACPI_BRGHT_Q_NOEC 0x0001 /* Must NOT use EC HBRV */
5651#define TPACPI_BRGHT_Q_EC 0x0002 /* Should or must use EC HBRV */
5652#define TPACPI_BRGHT_Q_ASK 0x8000 /* Ask for user report */
5653
5654static const struct tpacpi_quirk brightness_quirk_table[] __initconst = {
5655 /* Models with ATI GPUs known to require ECNVRAM mode */
5656 TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC), /* T43/p ATI */
5657
5658 /* Models with ATI GPUs (waiting confirmation) */
5659 TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
5660 TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
5661 TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
5662 TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
5663
5664 /* Models with Intel Extreme Graphics 2 (waiting confirmation) */
5665 TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
5666 TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
5667 TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
5668
5669 /* Models with Intel GMA900 */
5670 TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */
5671 TPACPI_Q_IBM('7', '4', TPACPI_BRGHT_Q_NOEC), /* X41 */
5672 TPACPI_Q_IBM('7', '5', TPACPI_BRGHT_Q_NOEC), /* X41 Tablet */
5673};
5674
5948static int __init brightness_init(struct ibm_init_struct *iibm) 5675static int __init brightness_init(struct ibm_init_struct *iibm)
5949{ 5676{
5950 int b; 5677 int b;
5678 unsigned long quirks;
5951 5679
5952 vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n"); 5680 vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n");
5953 5681
5954 mutex_init(&brightness_mutex); 5682 mutex_init(&brightness_mutex);
5955 5683
5684 quirks = tpacpi_check_quirks(brightness_quirk_table,
5685 ARRAY_SIZE(brightness_quirk_table));
5686
5956 /* 5687 /*
5957 * We always attempt to detect acpi support, so as to switch 5688 * We always attempt to detect acpi support, so as to switch
5958 * Lenovo Vista BIOS to ACPI brightness mode even if we are not 5689 * Lenovo Vista BIOS to ACPI brightness mode even if we are not
@@ -6009,23 +5740,13 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6009 /* TPACPI_BRGHT_MODE_AUTO not implemented yet, just use default */ 5740 /* TPACPI_BRGHT_MODE_AUTO not implemented yet, just use default */
6010 if (brightness_mode == TPACPI_BRGHT_MODE_AUTO || 5741 if (brightness_mode == TPACPI_BRGHT_MODE_AUTO ||
6011 brightness_mode == TPACPI_BRGHT_MODE_MAX) { 5742 brightness_mode == TPACPI_BRGHT_MODE_MAX) {
6012 if (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) { 5743 if (quirks & TPACPI_BRGHT_Q_EC)
6013 /* 5744 brightness_mode = TPACPI_BRGHT_MODE_ECNVRAM;
6014 * IBM models that define HBRV probably have 5745 else
6015 * EC-based backlight level control
6016 */
6017 if (acpi_evalf(ec_handle, NULL, "HBRV", "qd"))
6018 /* T40-T43, R50-R52, R50e, R51e, X31-X41 */
6019 brightness_mode = TPACPI_BRGHT_MODE_ECNVRAM;
6020 else
6021 /* all other IBM ThinkPads */
6022 brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP;
6023 } else
6024 /* All Lenovo ThinkPads */
6025 brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP; 5746 brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP;
6026 5747
6027 dbg_printk(TPACPI_DBG_BRGHT, 5748 dbg_printk(TPACPI_DBG_BRGHT,
6028 "selected brightness_mode=%d\n", 5749 "driver auto-selected brightness_mode=%d\n",
6029 brightness_mode); 5750 brightness_mode);
6030 } 5751 }
6031 5752
@@ -6052,6 +5773,15 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6052 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT, 5773 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT,
6053 "brightness is supported\n"); 5774 "brightness is supported\n");
6054 5775
5776 if (quirks & TPACPI_BRGHT_Q_ASK) {
5777 printk(TPACPI_NOTICE
5778 "brightness: will use unverified default: "
5779 "brightness_mode=%d\n", brightness_mode);
5780 printk(TPACPI_NOTICE
5781 "brightness: please report to %s whether it works well "
5782 "or not on your ThinkPad\n", TPACPI_MAIL);
5783 }
5784
6055 ibm_backlight_device->props.max_brightness = 5785 ibm_backlight_device->props.max_brightness =
6056 (tp_features.bright_16levels)? 15 : 7; 5786 (tp_features.bright_16levels)? 15 : 7;
6057 ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK; 5787 ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
@@ -7854,22 +7584,6 @@ static struct ibm_init_struct ibms_init[] __initdata = {
7854 .init = light_init, 7584 .init = light_init,
7855 .data = &light_driver_data, 7585 .data = &light_driver_data,
7856 }, 7586 },
7857#ifdef CONFIG_THINKPAD_ACPI_DOCK
7858 {
7859 .init = dock_init,
7860 .data = &dock_driver_data[0],
7861 },
7862 {
7863 .init = dock_init2,
7864 .data = &dock_driver_data[1],
7865 },
7866#endif
7867#ifdef CONFIG_THINKPAD_ACPI_BAY
7868 {
7869 .init = bay_init,
7870 .data = &bay_driver_data,
7871 },
7872#endif
7873 { 7587 {
7874 .init = cmos_init, 7588 .init = cmos_init,
7875 .data = &cmos_driver_data, 7589 .data = &cmos_driver_data,
@@ -7968,12 +7682,6 @@ TPACPI_PARAM(hotkey);
7968TPACPI_PARAM(bluetooth); 7682TPACPI_PARAM(bluetooth);
7969TPACPI_PARAM(video); 7683TPACPI_PARAM(video);
7970TPACPI_PARAM(light); 7684TPACPI_PARAM(light);
7971#ifdef CONFIG_THINKPAD_ACPI_DOCK
7972TPACPI_PARAM(dock);
7973#endif
7974#ifdef CONFIG_THINKPAD_ACPI_BAY
7975TPACPI_PARAM(bay);
7976#endif /* CONFIG_THINKPAD_ACPI_BAY */
7977TPACPI_PARAM(cmos); 7685TPACPI_PARAM(cmos);
7978TPACPI_PARAM(led); 7686TPACPI_PARAM(led);
7979TPACPI_PARAM(beep); 7687TPACPI_PARAM(beep);
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 3e798593b17b..ab0b85cf21f3 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -242,6 +242,10 @@ acpi_os_derive_pci_id(acpi_handle rhandle,
242acpi_status acpi_os_validate_interface(char *interface); 242acpi_status acpi_os_validate_interface(char *interface);
243acpi_status acpi_osi_invalidate(char* interface); 243acpi_status acpi_osi_invalidate(char* interface);
244 244
245acpi_status
246acpi_os_validate_address(u8 space_id, acpi_physical_address address,
247 acpi_size length, char *name);
248
245u64 acpi_os_get_timer(void); 249u64 acpi_os_get_timer(void);
246 250
247acpi_status acpi_os_signal(u32 function, void *info); 251acpi_status acpi_os_signal(u32 function, void *info);