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:
Коммит
145628130b
|
@ -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:
|
||||||
|
|
Загрузка…
Ссылка в новой задаче