Commit 0ce166b7 authored by Linus Torvalds's avatar Linus Torvalds

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"
parents 57d7f282 3be4ee51
...@@ -36,8 +36,6 @@ detailed description): ...@@ -36,8 +36,6 @@ detailed description):
- Bluetooth enable and disable - Bluetooth enable and disable
- video output switching, expansion control - video output switching, expansion control
- ThinkLight on and off - ThinkLight on and off
- limited docking and undocking
- UltraBay eject
- CMOS/UCMS control - CMOS/UCMS control
- LED control - LED control
- ACPI sounds - ACPI sounds
...@@ -729,131 +727,6 @@ cannot be read or if it is unknown, thinkpad-acpi will report it as "off". ...@@ -729,131 +727,6 @@ cannot be read or if it is unknown, thinkpad-acpi will report it as "off".
It is impossible to know if the status returned through sysfs is valid. It is impossible to know if the status returned through sysfs is valid.
Docking / undocking -- /proc/acpi/ibm/dock
------------------------------------------
Docking and undocking (e.g. with the X4 UltraBase) requires some
actions to be taken by the operating system to safely make or break
the electrical connections with the dock.
The docking feature of this driver generates the following ACPI events:
ibm/dock GDCK 00000003 00000001 -- eject request
ibm/dock GDCK 00000003 00000002 -- undocked
ibm/dock GDCK 00000000 00000003 -- docked
NOTE: These events will only be generated if the laptop was docked
when originally booted. This is due to the current lack of support for
hot plugging of devices in the Linux ACPI framework. If the laptop was
booted while not in the dock, the following message is shown in the
logs:
Mar 17 01:42:34 aero kernel: thinkpad_acpi: dock device not present
In this case, no dock-related events are generated but the dock and
undock commands described below still work. They can be executed
manually or triggered by Fn key combinations (see the example acpid
configuration files included in the driver tarball package available
on the web site).
When the eject request button on the dock is pressed, the first event
above is generated. The handler for this event should issue the
following command:
echo undock > /proc/acpi/ibm/dock
After the LED on the dock goes off, it is safe to eject the laptop.
Note: if you pressed this key by mistake, go ahead and eject the
laptop, then dock it back in. Otherwise, the dock may not function as
expected.
When the laptop is docked, the third event above is generated. The
handler for this event should issue the following command to fully
enable the dock:
echo dock > /proc/acpi/ibm/dock
The contents of the /proc/acpi/ibm/dock file shows the current status
of the dock, as provided by the ACPI framework.
The docking support in this driver does not take care of enabling or
disabling any other devices you may have attached to the dock. For
example, a CD drive plugged into the UltraBase needs to be disabled or
enabled separately. See the provided example acpid configuration files
for how this can be accomplished.
There is no support yet for PCI devices that may be attached to a
docking station, e.g. in the ThinkPad Dock II. The driver currently
does not recognize, enable or disable such devices. This means that
the only docking stations currently supported are the X-series
UltraBase docks and "dumb" port replicators like the Mini Dock (the
latter don't need any ACPI support, actually).
UltraBay eject -- /proc/acpi/ibm/bay
------------------------------------
Inserting or ejecting an UltraBay device requires some actions to be
taken by the operating system to safely make or break the electrical
connections with the device.
This feature generates the following ACPI events:
ibm/bay MSTR 00000003 00000000 -- eject request
ibm/bay MSTR 00000001 00000000 -- eject lever inserted
NOTE: These events will only be generated if the UltraBay was present
when the laptop was originally booted (on the X series, the UltraBay
is in the dock, so it may not be present if the laptop was undocked).
This is due to the current lack of support for hot plugging of devices
in the Linux ACPI framework. If the laptop was booted without the
UltraBay, the following message is shown in the logs:
Mar 17 01:42:34 aero kernel: thinkpad_acpi: bay device not present
In this case, no bay-related events are generated but the eject
command described below still works. It can be executed manually or
triggered by a hot key combination.
Sliding the eject lever generates the first event shown above. The
handler for this event should take whatever actions are necessary to
shut down the device in the UltraBay (e.g. call idectl), then issue
the following command:
echo eject > /proc/acpi/ibm/bay
After the LED on the UltraBay goes off, it is safe to pull out the
device.
When the eject lever is inserted, the second event above is
generated. The handler for this event should take whatever actions are
necessary to enable the UltraBay device (e.g. call idectl).
The contents of the /proc/acpi/ibm/bay file shows the current status
of the UltraBay, as provided by the ACPI framework.
EXPERIMENTAL warm eject support on the 600e/x, A22p and A3x (To use
this feature, you need to supply the experimental=1 parameter when
loading the module):
These models do not have a button near the UltraBay device to request
a hot eject but rather require the laptop to be put to sleep
(suspend-to-ram) before the bay device is ejected or inserted).
The sequence of steps to eject the device is as follows:
echo eject > /proc/acpi/ibm/bay
put the ThinkPad to sleep
remove the drive
resume from sleep
cat /proc/acpi/ibm/bay should show that the drive was removed
On the A3x, both the UltraBay 2000 and UltraBay Plus devices are
supported. Use "eject2" instead of "eject" for the second bay.
Note: the UltraBay eject support on the 600e/x, A22p and A3x is
EXPERIMENTAL and may not work as expected. USE WITH CAUTION!
CMOS/UCMS control CMOS/UCMS control
----------------- -----------------
......
...@@ -38,6 +38,9 @@ ...@@ -38,6 +38,9 @@
#define _COMPONENT ACPI_MEMORY_DEVICE_COMPONENT #define _COMPONENT ACPI_MEMORY_DEVICE_COMPONENT
#undef PREFIX
#define PREFIX "ACPI:memory_hp:"
ACPI_MODULE_NAME("acpi_memhotplug"); ACPI_MODULE_NAME("acpi_memhotplug");
MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>"); MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
MODULE_DESCRIPTION("Hotplug Mem Driver"); MODULE_DESCRIPTION("Hotplug Mem Driver");
...@@ -153,6 +156,7 @@ acpi_memory_get_device(acpi_handle handle, ...@@ -153,6 +156,7 @@ acpi_memory_get_device(acpi_handle handle,
acpi_handle phandle; acpi_handle phandle;
struct acpi_device *device = NULL; struct acpi_device *device = NULL;
struct acpi_device *pdevice = NULL; struct acpi_device *pdevice = NULL;
int result;
if (!acpi_bus_get_device(handle, &device) && device) if (!acpi_bus_get_device(handle, &device) && device)
...@@ -165,9 +169,9 @@ acpi_memory_get_device(acpi_handle handle, ...@@ -165,9 +169,9 @@ acpi_memory_get_device(acpi_handle handle,
} }
/* Get the parent device */ /* Get the parent device */
status = acpi_bus_get_device(phandle, &pdevice); result = acpi_bus_get_device(phandle, &pdevice);
if (ACPI_FAILURE(status)) { if (result) {
ACPI_EXCEPTION((AE_INFO, status, "Cannot get acpi bus device")); printk(KERN_WARNING PREFIX "Cannot get acpi bus device");
return -EINVAL; return -EINVAL;
} }
...@@ -175,9 +179,9 @@ acpi_memory_get_device(acpi_handle handle, ...@@ -175,9 +179,9 @@ acpi_memory_get_device(acpi_handle handle,
* Now add the notified device. This creates the acpi_device * Now add the notified device. This creates the acpi_device
* and invokes .add function * and invokes .add function
*/ */
status = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE); result = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE);
if (ACPI_FAILURE(status)) { if (result) {
ACPI_EXCEPTION((AE_INFO, status, "Cannot add acpi bus")); printk(KERN_WARNING PREFIX "Cannot add acpi bus");
return -EINVAL; return -EINVAL;
} }
...@@ -238,7 +242,12 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) ...@@ -238,7 +242,12 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
num_enabled++; num_enabled++;
continue; continue;
} }
/*
* If the memory block size is zero, please ignore it.
* Don't try to do the following memory hotplug flowchart.
*/
if (!info->length)
continue;
if (node < 0) if (node < 0)
node = memory_add_physaddr_to_nid(info->start_addr); node = memory_add_physaddr_to_nid(info->start_addr);
...@@ -253,8 +262,15 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) ...@@ -253,8 +262,15 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
mem_device->state = MEMORY_INVALID_STATE; mem_device->state = MEMORY_INVALID_STATE;
return -EINVAL; return -EINVAL;
} }
/*
return result; * Sometimes the memory device will contain several memory blocks.
* When one memory block is hot-added to the system memory, it will
* be regarded as a success.
* Otherwise if the last memory block can't be hot-added to the system
* memory, it will be failure and the memory device can't be bound with
* driver.
*/
return 0;
} }
static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device) static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
......
...@@ -97,6 +97,7 @@ ...@@ -97,6 +97,7 @@
#define AOPOBJ_OBJECT_INITIALIZED 0x08 #define AOPOBJ_OBJECT_INITIALIZED 0x08
#define AOPOBJ_SETUP_COMPLETE 0x10 #define AOPOBJ_SETUP_COMPLETE 0x10
#define AOPOBJ_SINGLE_DATUM 0x20 #define AOPOBJ_SINGLE_DATUM 0x20
#define AOPOBJ_INVALID 0x40 /* Used if host OS won't allow an op_region address */
/****************************************************************************** /******************************************************************************
* *
......
...@@ -397,6 +397,30 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) ...@@ -397,6 +397,30 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
extra_desc->extra.aml_length, extra_desc->extra.aml_length,
extra_desc->extra.aml_start); extra_desc->extra.aml_start);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Validate the region address/length via the host OS */
status = acpi_os_validate_address(obj_desc->region.space_id,
obj_desc->region.address,
(acpi_size) obj_desc->region.length,
acpi_ut_get_node_name(node));
if (ACPI_FAILURE(status)) {
/*
* Invalid address/length. We will emit an error message and mark
* the region as invalid, so that it will cause an additional error if
* it is ever used. Then return AE_OK.
*/
ACPI_EXCEPTION((AE_INFO, status,
"During address validation of OpRegion [%4.4s]",
node->name.ascii));
obj_desc->common.flags |= AOPOBJ_INVALID;
status = AE_OK;
}
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
......
...@@ -113,6 +113,12 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, ...@@ -113,6 +113,12 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
} }
} }
/* Exit if Address/Length have been disallowed by the host OS */
if (rgn_desc->common.flags & AOPOBJ_INVALID) {
return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS);
}
/* /*
* Exit now for SMBus address space, it has a non-linear address space * Exit now for SMBus address space, it has a non-linear address space
* and the request cannot be directly validated * and the request cannot be directly validated
......
...@@ -189,11 +189,36 @@ acpi_status __init acpi_os_initialize(void) ...@@ -189,11 +189,36 @@ acpi_status __init acpi_os_initialize(void)
return AE_OK; return AE_OK;
} }
static void bind_to_cpu0(struct work_struct *work)
{
set_cpus_allowed(current, cpumask_of_cpu(0));
kfree(work);
}
static void bind_workqueue(struct workqueue_struct *wq)
{
struct work_struct *work;
work = kzalloc(sizeof(struct work_struct), GFP_KERNEL);
INIT_WORK(work, bind_to_cpu0);
queue_work(wq, work);
}
acpi_status acpi_os_initialize1(void) acpi_status acpi_os_initialize1(void)
{ {
/*
* On some machines, a software-initiated SMI causes corruption unless
* the SMI runs on CPU 0. An SMI can be initiated by any AML, but
* typically it's done in GPE-related methods that are run via
* workqueues, so we can avoid the known corruption cases by binding
* the workqueues to CPU 0.
*/
kacpid_wq = create_singlethread_workqueue("kacpid"); kacpid_wq = create_singlethread_workqueue("kacpid");
bind_workqueue(kacpid_wq);
kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify");
bind_workqueue(kacpi_notify_wq);
kacpi_hotplug_wq = create_singlethread_workqueue("kacpi_hotplug"); kacpi_hotplug_wq = create_singlethread_workqueue("kacpi_hotplug");
bind_workqueue(kacpi_hotplug_wq);
BUG_ON(!kacpid_wq); BUG_ON(!kacpid_wq);
BUG_ON(!kacpi_notify_wq); BUG_ON(!kacpi_notify_wq);
BUG_ON(!kacpi_hotplug_wq); BUG_ON(!kacpi_hotplug_wq);
......
...@@ -121,7 +121,7 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr, ...@@ -121,7 +121,7 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr,
table_attr->attr.size = 0; table_attr->attr.size = 0;
table_attr->attr.read = acpi_table_show; table_attr->attr.read = acpi_table_show;
table_attr->attr.attr.name = table_attr->name; table_attr->attr.attr.name = table_attr->name;
table_attr->attr.attr.mode = 0444; table_attr->attr.attr.mode = 0400;
return; return;
} }
......
...@@ -277,31 +277,6 @@ config THINKPAD_ACPI_UNSAFE_LEDS ...@@ -277,31 +277,6 @@ config THINKPAD_ACPI_UNSAFE_LEDS
Say N here, unless you are building a kernel for your own Say N here, unless you are building a kernel for your own
use, and need to control the important firmware LEDs. use, and need to control the important firmware LEDs.
config THINKPAD_ACPI_DOCK
bool "Legacy Docking Station Support"
depends on THINKPAD_ACPI
depends on ACPI_DOCK=n
default n
---help---
Allows the thinkpad_acpi driver to handle docking station events.
This support was made obsolete by the generic ACPI docking station
support (CONFIG_ACPI_DOCK). It will allow locking and removing the
laptop from the docking station, but will not properly connect PCI
devices.
If you are not sure, say N here.
config THINKPAD_ACPI_BAY
bool "Legacy Removable Bay Support"
depends on THINKPAD_ACPI
default y
---help---
Allows the thinkpad_acpi driver to handle removable bays. It will
electrically disable the device in the bay, and also generate
notifications when the bay lever is ejected or inserted.
If you are not sure, say Y here.
config THINKPAD_ACPI_VIDEO config THINKPAD_ACPI_VIDEO
bool "Video output control support" bool "Video output control support"
depends on THINKPAD_ACPI depends on THINKPAD_ACPI
......
...@@ -143,6 +143,7 @@ struct eeepc_hotk { ...@@ -143,6 +143,7 @@ struct eeepc_hotk {
struct rfkill *bluetooth_rfkill; struct rfkill *bluetooth_rfkill;
struct rfkill *wwan3g_rfkill; struct rfkill *wwan3g_rfkill;
struct hotplug_slot *hotplug_slot; struct hotplug_slot *hotplug_slot;
struct work_struct hotplug_work;
}; };
/* The actual device the driver binds to */ /* The actual device the driver binds to */
...@@ -660,7 +661,7 @@ static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot, ...@@ -660,7 +661,7 @@ static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
return 0; return 0;
} }
static void eeepc_rfkill_hotplug(void) static void eeepc_hotplug_work(struct work_struct *work)
{ {
struct pci_dev *dev; struct pci_dev *dev;
struct pci_bus *bus = pci_find_bus(0, 1); 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,7 +702,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
if (event != ACPI_NOTIFY_BUS_CHECK) if (event != ACPI_NOTIFY_BUS_CHECK)
return; return;
eeepc_rfkill_hotplug(); schedule_work(&ehotk->hotplug_work);
} }
static void eeepc_hotk_notify(struct acpi_device *device, u32 event) static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
...@@ -892,7 +893,7 @@ static int eeepc_hotk_resume(struct acpi_device *device) ...@@ -892,7 +893,7 @@ static int eeepc_hotk_resume(struct acpi_device *device)
rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1); rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1);
eeepc_rfkill_hotplug(); schedule_work(&ehotk->hotplug_work);
} }
if (ehotk->bluetooth_rfkill) if (ehotk->bluetooth_rfkill)
...@@ -1093,6 +1094,8 @@ static int eeepc_rfkill_init(struct device *dev) ...@@ -1093,6 +1094,8 @@ static int eeepc_rfkill_init(struct device *dev)
{ {
int result = 0; int result = 0;
INIT_WORK(&ehotk->hotplug_work, eeepc_hotplug_work);
eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
......
...@@ -520,11 +520,13 @@ static int hp_wmi_resume_handler(struct platform_device *device) ...@@ -520,11 +520,13 @@ static int hp_wmi_resume_handler(struct platform_device *device)
* the input layer will only actually pass it on if the state * the input layer will only actually pass it on if the state
* changed. * changed.
*/ */
if (hp_wmi_input_dev) {
input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state()); input_report_switch(hp_wmi_input_dev, SW_DOCK,
input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, hp_wmi_dock_state());
hp_wmi_tablet_state()); input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
input_sync(hp_wmi_input_dev); hp_wmi_tablet_state());
input_sync(hp_wmi_input_dev);
}
return 0; return 0;
} }
......
This diff is collapsed.
...@@ -242,6 +242,10 @@ acpi_os_derive_pci_id(acpi_handle rhandle, ...@@ -242,6 +242,10 @@ acpi_os_derive_pci_id(acpi_handle rhandle,
acpi_status acpi_os_validate_interface(char *interface); acpi_status acpi_os_validate_interface(char *interface);
acpi_status acpi_osi_invalidate(char* interface); acpi_status acpi_osi_invalidate(char* interface);
acpi_status
acpi_os_validate_address(u8 space_id, acpi_physical_address address,
acpi_size length, char *name);
u64 acpi_os_get_timer(void); u64 acpi_os_get_timer(void);
acpi_status acpi_os_signal(u32 function, void *info); acpi_status acpi_os_signal(u32 function, void *info);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment