Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86:
  hp-wmi: fix use after free
  dell-laptop - using buffer without mutex_lock
  Revert: "dell-laptop: Toggle the unsupported hardware killswitch"
  platform-drivers-x86: set backlight type to BACKLIGHT_PLATFORM
  thinkpad-acpi: handle HKEY 0x4010, 0x4011 events
  drivers/platform/x86: Fix memory leak
  thinkpad-acpi: handle some new HKEY 0x60xx events
  acer-wmi: fix bitwise bug when set device state
  acer-wmi: Only update rfkill status for associated hotkey events
This commit is contained in:
Linus Torvalds 2011-07-11 12:47:09 -07:00
Родитель 83e9569714 0401846c33
Коммит 145628130b
8 изменённых файлов: 108 добавлений и 63 удалений

Просмотреть файл

@ -534,6 +534,8 @@ Events that are never propagated by the driver:
0x2404 System is waking up from hibernation to undock 0x2404 System is waking up from hibernation to undock
0x2405 System is waking up from hibernation to eject bay 0x2405 System is waking up from hibernation to eject bay
0x5010 Brightness level changed/control event 0x5010 Brightness level changed/control event
0x6000 KEYBOARD: Numlock key pressed
0x6005 KEYBOARD: Fn key pressed (TO BE VERIFIED)
Events that are propagated by the driver to userspace: Events that are propagated by the driver to userspace:
@ -545,6 +547,8 @@ Events that are propagated by the driver to userspace:
0x3006 Bay hotplug request (hint to power up SATA link when 0x3006 Bay hotplug request (hint to power up SATA link when
the optical drive tray is ejected) the optical drive tray is ejected)
0x4003 Undocked (see 0x2x04), can sleep again 0x4003 Undocked (see 0x2x04), can sleep again
0x4010 Docked into hotplug port replicator (non-ACPI dock)
0x4011 Undocked from hotplug port replicator (non-ACPI dock)
0x500B Tablet pen inserted into its storage bay 0x500B Tablet pen inserted into its storage bay
0x500C Tablet pen removed from its storage bay 0x500C Tablet pen removed from its storage bay
0x6011 ALARM: battery is too hot 0x6011 ALARM: battery is too hot
@ -552,6 +556,7 @@ Events that are propagated by the driver to userspace:
0x6021 ALARM: a sensor is too hot 0x6021 ALARM: a sensor is too hot
0x6022 ALARM: a sensor is extremely hot 0x6022 ALARM: a sensor is extremely hot
0x6030 System thermal table changed 0x6030 System thermal table changed
0x6040 Nvidia Optimus/AC adapter related (TO BE VERIFIED)
Battery nearly empty alarms are a last resort attempt to get the Battery nearly empty alarms are a last resort attempt to get the
operating system to hibernate or shutdown cleanly (0x2313), or shutdown operating system to hibernate or shutdown cleanly (0x2313), or shutdown

Просмотреть файл

@ -1156,9 +1156,9 @@ static acpi_status wmid3_set_device_status(u32 value, u16 device)
struct wmid3_gds_input_param params = { struct wmid3_gds_input_param params = {
.function_num = 0x1, .function_num = 0x1,
.hotkey_number = 0x01, .hotkey_number = 0x01,
.devices = ACER_WMID3_GDS_WIRELESS & .devices = ACER_WMID3_GDS_WIRELESS |
ACER_WMID3_GDS_THREEG & ACER_WMID3_GDS_THREEG |
ACER_WMID3_GDS_WIMAX & ACER_WMID3_GDS_WIMAX |
ACER_WMID3_GDS_BLUETOOTH, ACER_WMID3_GDS_BLUETOOTH,
}; };
struct acpi_buffer input = { struct acpi_buffer input = {
@ -1445,6 +1445,8 @@ static void acer_wmi_notify(u32 value, void *context)
union acpi_object *obj; union acpi_object *obj;
struct event_return_value return_value; struct event_return_value return_value;
acpi_status status; acpi_status status;
u16 device_state;
const struct key_entry *key;
status = wmi_get_event_data(value, &response); status = wmi_get_event_data(value, &response);
if (status != AE_OK) { if (status != AE_OK) {
@ -1472,23 +1474,32 @@ static void acer_wmi_notify(u32 value, void *context)
switch (return_value.function) { switch (return_value.function) {
case WMID_HOTKEY_EVENT: case WMID_HOTKEY_EVENT:
if (return_value.device_state) { device_state = return_value.device_state;
u16 device_state = return_value.device_state; pr_debug("device state: 0x%x\n", device_state);
pr_debug("device state: 0x%x\n", device_state);
if (has_cap(ACER_CAP_WIRELESS)) key = sparse_keymap_entry_from_scancode(acer_wmi_input_dev,
rfkill_set_sw_state(wireless_rfkill, return_value.key_num);
!(device_state & ACER_WMID3_GDS_WIRELESS)); if (!key) {
if (has_cap(ACER_CAP_BLUETOOTH))
rfkill_set_sw_state(bluetooth_rfkill,
!(device_state & ACER_WMID3_GDS_BLUETOOTH));
if (has_cap(ACER_CAP_THREEG))
rfkill_set_sw_state(threeg_rfkill,
!(device_state & ACER_WMID3_GDS_THREEG));
}
if (!sparse_keymap_report_event(acer_wmi_input_dev,
return_value.key_num, 1, true))
pr_warn("Unknown key number - 0x%x\n", pr_warn("Unknown key number - 0x%x\n",
return_value.key_num); return_value.key_num);
} else {
switch (key->keycode) {
case KEY_WLAN:
case KEY_BLUETOOTH:
if (has_cap(ACER_CAP_WIRELESS))
rfkill_set_sw_state(wireless_rfkill,
!(device_state & ACER_WMID3_GDS_WIRELESS));
if (has_cap(ACER_CAP_THREEG))
rfkill_set_sw_state(threeg_rfkill,
!(device_state & ACER_WMID3_GDS_THREEG));
if (has_cap(ACER_CAP_BLUETOOTH))
rfkill_set_sw_state(bluetooth_rfkill,
!(device_state & ACER_WMID3_GDS_BLUETOOTH));
break;
}
sparse_keymap_report_entry(acer_wmi_input_dev, key,
1, true);
}
break; break;
default: default:
pr_warn("Unknown function number - %d - %d\n", pr_warn("Unknown function number - %d - %d\n",

Просмотреть файл

@ -1025,6 +1025,7 @@ static int asus_wmi_backlight_init(struct asus_wmi *asus)
return power; return power;
memset(&props, 0, sizeof(struct backlight_properties)); memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_PLATFORM;
props.max_brightness = max; props.max_brightness = max;
bd = backlight_device_register(asus->driver->name, bd = backlight_device_register(asus->driver->name,
&asus->platform_device->dev, asus, &asus->platform_device->dev, asus,

Просмотреть файл

@ -1030,8 +1030,10 @@ static int __devinit compal_probe(struct platform_device *pdev)
initialize_fan_control_data(data); initialize_fan_control_data(data);
err = sysfs_create_group(&pdev->dev.kobj, &compal_attribute_group); err = sysfs_create_group(&pdev->dev.kobj, &compal_attribute_group);
if (err) if (err) {
kfree(data);
return err; return err;
}
data->hwmon_dev = hwmon_device_register(&pdev->dev); data->hwmon_dev = hwmon_device_register(&pdev->dev);
if (IS_ERR(data->hwmon_dev)) { if (IS_ERR(data->hwmon_dev)) {

Просмотреть файл

@ -292,12 +292,9 @@ static int dell_rfkill_set(void *data, bool blocked)
dell_send_request(buffer, 17, 11); dell_send_request(buffer, 17, 11);
/* If the hardware switch controls this radio, and the hardware /* If the hardware switch controls this radio, and the hardware
switch is disabled, don't allow changing the software state. switch is disabled, don't allow changing the software state */
If the hardware switch is reported as not supported, always
fire the SMI to toggle the killswitch. */
if ((hwswitch_state & BIT(hwswitch_bit)) && if ((hwswitch_state & BIT(hwswitch_bit)) &&
!(buffer->output[1] & BIT(16)) && !(buffer->output[1] & BIT(16))) {
(buffer->output[1] & BIT(0))) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
@ -403,23 +400,6 @@ static const struct file_operations dell_debugfs_fops = {
static void dell_update_rfkill(struct work_struct *ignored) static void dell_update_rfkill(struct work_struct *ignored)
{ {
int status;
get_buffer();
dell_send_request(buffer, 17, 11);
status = buffer->output[1];
release_buffer();
/* if hardware rfkill is not supported, set it explicitly */
if (!(status & BIT(0))) {
if (wifi_rfkill)
dell_rfkill_set((void *)1, !((status & BIT(17)) >> 17));
if (bluetooth_rfkill)
dell_rfkill_set((void *)2, !((status & BIT(18)) >> 18));
if (wwan_rfkill)
dell_rfkill_set((void *)3, !((status & BIT(19)) >> 19));
}
if (wifi_rfkill) if (wifi_rfkill)
dell_rfkill_query(wifi_rfkill, (void *)1); dell_rfkill_query(wifi_rfkill, (void *)1);
if (bluetooth_rfkill) if (bluetooth_rfkill)
@ -560,11 +540,11 @@ static int dell_get_intensity(struct backlight_device *bd)
else else
dell_send_request(buffer, 0, 1); dell_send_request(buffer, 0, 1);
ret = buffer->output[1];
out: out:
release_buffer(); release_buffer();
if (ret) return ret;
return ret;
return buffer->output[1];
} }
static const struct backlight_ops dell_ops = { static const struct backlight_ops dell_ops = {

Просмотреть файл

@ -207,6 +207,7 @@ static int hp_wmi_perform_query(int query, int write, void *buffer,
}; };
struct acpi_buffer input = { sizeof(struct bios_args), &args }; struct acpi_buffer input = { sizeof(struct bios_args), &args };
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
u32 rc;
if (WARN_ON(insize > sizeof(args.data))) if (WARN_ON(insize > sizeof(args.data)))
return -EINVAL; return -EINVAL;
@ -224,13 +225,13 @@ static int hp_wmi_perform_query(int query, int write, void *buffer,
} }
bios_return = (struct bios_return *)obj->buffer.pointer; bios_return = (struct bios_return *)obj->buffer.pointer;
rc = bios_return->return_code;
if (bios_return->return_code) { if (rc) {
if (bios_return->return_code != HPWMI_RET_UNKNOWN_CMDTYPE) if (rc != HPWMI_RET_UNKNOWN_CMDTYPE)
pr_warn("query 0x%x returned error 0x%x\n", pr_warn("query 0x%x returned error 0x%x\n", query, rc);
query, bios_return->return_code);
kfree(obj); kfree(obj);
return bios_return->return_code; return rc;
} }
if (!outsize) { if (!outsize) {

Просмотреть файл

@ -250,6 +250,7 @@ static int oaktrail_backlight_init(void)
struct backlight_properties props; struct backlight_properties props;
memset(&props, 0, sizeof(struct backlight_properties)); memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_PLATFORM;
props.max_brightness = OT_EC_BL_BRIGHTNESS_MAX; props.max_brightness = OT_EC_BL_BRIGHTNESS_MAX;
bd = backlight_device_register(DRIVER_NAME, bd = backlight_device_register(DRIVER_NAME,
&oaktrail_device->dev, NULL, &oaktrail_device->dev, NULL,

Просмотреть файл

@ -184,6 +184,10 @@ enum tpacpi_hkey_event_t {
/* Misc bay events */ /* Misc bay events */
TP_HKEY_EV_OPTDRV_EJ = 0x3006, /* opt. drive tray ejected */ TP_HKEY_EV_OPTDRV_EJ = 0x3006, /* opt. drive tray ejected */
TP_HKEY_EV_HOTPLUG_DOCK = 0x4010, /* docked into hotplug dock
or port replicator */
TP_HKEY_EV_HOTPLUG_UNDOCK = 0x4011, /* undocked from hotplug
dock or port replicator */
/* User-interface events */ /* User-interface events */
TP_HKEY_EV_LID_CLOSE = 0x5001, /* laptop lid closed */ TP_HKEY_EV_LID_CLOSE = 0x5001, /* laptop lid closed */
@ -194,6 +198,10 @@ enum tpacpi_hkey_event_t {
TP_HKEY_EV_PEN_REMOVED = 0x500c, /* tablet pen removed */ TP_HKEY_EV_PEN_REMOVED = 0x500c, /* tablet pen removed */
TP_HKEY_EV_BRGHT_CHANGED = 0x5010, /* backlight control event */ TP_HKEY_EV_BRGHT_CHANGED = 0x5010, /* backlight control event */
/* Key-related user-interface events */
TP_HKEY_EV_KEY_NUMLOCK = 0x6000, /* NumLock key pressed */
TP_HKEY_EV_KEY_FN = 0x6005, /* Fn key pressed? E420 */
/* Thermal events */ /* Thermal events */
TP_HKEY_EV_ALARM_BAT_HOT = 0x6011, /* battery too hot */ TP_HKEY_EV_ALARM_BAT_HOT = 0x6011, /* battery too hot */
TP_HKEY_EV_ALARM_BAT_XHOT = 0x6012, /* battery critically hot */ TP_HKEY_EV_ALARM_BAT_XHOT = 0x6012, /* battery critically hot */
@ -201,6 +209,10 @@ enum tpacpi_hkey_event_t {
TP_HKEY_EV_ALARM_SENSOR_XHOT = 0x6022, /* sensor critically hot */ TP_HKEY_EV_ALARM_SENSOR_XHOT = 0x6022, /* sensor critically hot */
TP_HKEY_EV_THM_TABLE_CHANGED = 0x6030, /* thermal table changed */ TP_HKEY_EV_THM_TABLE_CHANGED = 0x6030, /* thermal table changed */
TP_HKEY_EV_UNK_6040 = 0x6040, /* Related to AC change?
some sort of APM hint,
W520 */
/* Misc */ /* Misc */
TP_HKEY_EV_RFKILL_CHANGED = 0x7000, /* rfkill switch changed */ TP_HKEY_EV_RFKILL_CHANGED = 0x7000, /* rfkill switch changed */
}; };
@ -3513,6 +3525,34 @@ static bool hotkey_notify_wakeup(const u32 hkey,
return true; return true;
} }
static bool hotkey_notify_dockevent(const u32 hkey,
bool *send_acpi_ev,
bool *ignore_acpi_ev)
{
/* 0x4000-0x4FFF: dock-related events */
*send_acpi_ev = true;
*ignore_acpi_ev = false;
switch (hkey) {
case TP_HKEY_EV_UNDOCK_ACK:
/* ACPI undock operation completed after wakeup */
hotkey_autosleep_ack = 1;
pr_info("undocked\n");
hotkey_wakeup_hotunplug_complete_notify_change();
return true;
case TP_HKEY_EV_HOTPLUG_DOCK: /* docked to port replicator */
pr_info("docked into hotplug port replicator\n");
return true;
case TP_HKEY_EV_HOTPLUG_UNDOCK: /* undocked from port replicator */
pr_info("undocked from hotplug port replicator\n");
return true;
default:
return false;
}
}
static bool hotkey_notify_usrevent(const u32 hkey, static bool hotkey_notify_usrevent(const u32 hkey,
bool *send_acpi_ev, bool *send_acpi_ev,
bool *ignore_acpi_ev) bool *ignore_acpi_ev)
@ -3547,13 +3587,13 @@ static bool hotkey_notify_usrevent(const u32 hkey,
static void thermal_dump_all_sensors(void); static void thermal_dump_all_sensors(void);
static bool hotkey_notify_thermal(const u32 hkey, static bool hotkey_notify_6xxx(const u32 hkey,
bool *send_acpi_ev, bool *send_acpi_ev,
bool *ignore_acpi_ev) bool *ignore_acpi_ev)
{ {
bool known = true; bool known = true;
/* 0x6000-0x6FFF: thermal alarms */ /* 0x6000-0x6FFF: thermal alarms/notices and keyboard events */
*send_acpi_ev = true; *send_acpi_ev = true;
*ignore_acpi_ev = false; *ignore_acpi_ev = false;
@ -3582,8 +3622,17 @@ static bool hotkey_notify_thermal(const u32 hkey,
"a sensor reports something is extremely hot!\n"); "a sensor reports something is extremely hot!\n");
/* recommended action: immediate sleep/hibernate */ /* recommended action: immediate sleep/hibernate */
break; break;
case TP_HKEY_EV_KEY_NUMLOCK:
case TP_HKEY_EV_KEY_FN:
/* key press events, we just ignore them as long as the EC
* is still reporting them in the normal keyboard stream */
*send_acpi_ev = false;
*ignore_acpi_ev = true;
return true;
default: default:
pr_alert("THERMAL ALERT: unknown thermal alarm received\n"); pr_warn("unknown possible thermal alarm or keyboard event received\n");
known = false; known = false;
} }
@ -3652,15 +3701,9 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
} }
break; break;
case 4: case 4:
/* 0x4000-0x4FFF: dock-related wakeups */ /* 0x4000-0x4FFF: dock-related events */
if (hkey == TP_HKEY_EV_UNDOCK_ACK) { known_ev = hotkey_notify_dockevent(hkey, &send_acpi_ev,
hotkey_autosleep_ack = 1; &ignore_acpi_ev);
pr_info("undocked\n");
hotkey_wakeup_hotunplug_complete_notify_change();
known_ev = true;
} else {
known_ev = false;
}
break; break;
case 5: case 5:
/* 0x5000-0x5FFF: human interface helpers */ /* 0x5000-0x5FFF: human interface helpers */
@ -3668,8 +3711,9 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
&ignore_acpi_ev); &ignore_acpi_ev);
break; break;
case 6: case 6:
/* 0x6000-0x6FFF: thermal alarms */ /* 0x6000-0x6FFF: thermal alarms/notices and
known_ev = hotkey_notify_thermal(hkey, &send_acpi_ev, * keyboard events */
known_ev = hotkey_notify_6xxx(hkey, &send_acpi_ev,
&ignore_acpi_ev); &ignore_acpi_ev);
break; break;
case 7: case 7: