提交 9c0a76e1 编写于 作者: H Henrique de Moraes Holschuh 提交者: Len Brown

thinkpad-acpi: fix initialization error paths

Rework some subdriver init and exit handlers, in order to fix some
initialization error paths that were missing, or broken.

Hitting those bugs should be extremely rare in the real world, but should
that happen, thinkpad-acpi would fail to dealocate some resources and a
reboot might well be needed to be able to load the driver again.
Signed-off-by: NHenrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: NLen Brown <len.brown@intel.com>
上级 197a2cd9
......@@ -1921,6 +1921,29 @@ static struct attribute *hotkey_mask_attributes[] __initdata = {
&dev_attr_hotkey_wakeup_hotunplug_complete.attr,
};
static void hotkey_exit(void)
{
#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
hotkey_poll_stop_sync();
#endif
if (hotkey_dev_attributes)
delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj);
kfree(hotkey_keycode_map);
if (tp_features.hotkey) {
dbg_printk(TPACPI_DBG_EXIT,
"restoring original hot key mask\n");
/* no short-circuit boolean operator below! */
if ((hotkey_mask_set(hotkey_orig_mask) |
hotkey_status_set(hotkey_orig_status)) != 0)
printk(TPACPI_ERR
"failed to restore hot key mask "
"to BIOS defaults\n");
}
}
static int __init hotkey_init(struct ibm_init_struct *iibm)
{
/* Requirements for changing the default keymaps:
......@@ -2060,7 +2083,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
vdbg_printk(TPACPI_DBG_INIT, "hotkeys are %s\n",
str_supported(tp_features.hotkey));
if (tp_features.hotkey) {
if (!tp_features.hotkey)
return 1;
hotkey_dev_attributes = create_attr_set(13, NULL);
if (!hotkey_dev_attributes)
return -ENOMEM;
......@@ -2068,7 +2093,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
hotkey_attributes,
ARRAY_SIZE(hotkey_attributes));
if (res)
return res;
goto err_exit;
/* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
A30, R30, R31, T20-22, X20-21, X22-24. Detected by checking
......@@ -2106,15 +2131,21 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
/* hotkey_source_mask *must* be zero for
* the first hotkey_mask_get */
res = hotkey_status_get(&hotkey_orig_status);
if (!res && tp_features.hotkey_mask) {
if (res)
goto err_exit;
if (tp_features.hotkey_mask) {
res = hotkey_mask_get();
if (res)
goto err_exit;
hotkey_orig_mask = hotkey_mask;
if (!res) {
res = add_many_to_attr_set(
hotkey_dev_attributes,
hotkey_mask_attributes,
ARRAY_SIZE(hotkey_mask_attributes));
}
if (res)
goto err_exit;
}
#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
......@@ -2131,7 +2162,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
#endif
/* Not all thinkpads have a hardware radio switch */
if (!res && acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
tp_features.hotkey_wlsw = 1;
printk(TPACPI_INFO
"radio switch found; radios are %s\n",
......@@ -2157,7 +2188,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
hotkey_dev_attributes,
&tpacpi_pdev->dev.kobj);
if (res)
return res;
goto err_exit;
/* Set up key map */
......@@ -2166,7 +2197,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
if (!hotkey_keycode_map) {
printk(TPACPI_ERR
"failed to allocate memory for key map\n");
return -ENOMEM;
res = -ENOMEM;
goto err_exit;
}
if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) {
......@@ -2232,16 +2264,19 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
| (1 << TP_ACPI_HOTKEYSCAN_FNEND);
}
dbg_printk(TPACPI_DBG_INIT,
"enabling hot key handling\n");
dbg_printk(TPACPI_DBG_INIT, "enabling hot key handling\n");
res = hotkey_status_set(1);
if (res)
if (res) {
hotkey_exit();
return res;
}
res = hotkey_mask_set(((hotkey_all_mask | hotkey_source_mask)
& ~hotkey_reserved_mask)
| hotkey_orig_mask);
if (res < 0 && res != -ENXIO)
if (res < 0 && res != -ENXIO) {
hotkey_exit();
return res;
}
dbg_printk(TPACPI_DBG_INIT,
"legacy hot key reporting over procfs %s\n",
......@@ -2254,32 +2289,14 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
hotkey_poll_setup_safe(1);
tpacpi_input_send_radiosw();
tpacpi_input_send_tabletsw();
}
return (tp_features.hotkey)? 0 : 1;
}
static void hotkey_exit(void)
{
#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
hotkey_poll_stop_sync();
#endif
if (tp_features.hotkey) {
dbg_printk(TPACPI_DBG_EXIT,
"restoring original hot key mask\n");
/* no short-circuit boolean operator below! */
if ((hotkey_mask_set(hotkey_orig_mask) |
hotkey_status_set(hotkey_orig_status)) != 0)
printk(TPACPI_ERR
"failed to restore hot key mask "
"to BIOS defaults\n");
}
return 0;
if (hotkey_dev_attributes) {
err_exit:
delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj);
hotkey_dev_attributes = NULL;
}
return (res < 0)? res : 1;
}
static void hotkey_notify(struct ibm_struct *ibm, u32 event)
......@@ -3319,7 +3336,7 @@ static struct tpacpi_led_classdev tpacpi_led_thinklight = {
static int __init light_init(struct ibm_init_struct *iibm)
{
int rc = 0;
int rc;
vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n");
......@@ -3337,20 +3354,23 @@ static int __init light_init(struct ibm_init_struct *iibm)
tp_features.light_status =
acpi_evalf(ec_handle, NULL, "KBLT", "qv");
vdbg_printk(TPACPI_DBG_INIT, "light is %s\n",
str_supported(tp_features.light));
vdbg_printk(TPACPI_DBG_INIT, "light is %s, light status is %s\n",
str_supported(tp_features.light),
str_supported(tp_features.light_status));
if (!tp_features.light)
return 1;
if (tp_features.light) {
rc = led_classdev_register(&tpacpi_pdev->dev,
&tpacpi_led_thinklight.led_classdev);
}
if (rc < 0) {
tp_features.light = 0;
tp_features.light_status = 0;
} else {
rc = (tp_features.light)? 0 : 1;
rc = 0;
}
return rc;
}
......@@ -3978,7 +3998,6 @@ static void led_exit(void)
}
kfree(tpacpi_leds);
tpacpi_leds = NULL;
}
static int __init led_init(struct ibm_init_struct *iibm)
......@@ -4802,7 +4821,6 @@ static void brightness_exit(void)
vdbg_printk(TPACPI_DBG_EXIT,
"calling backlight_device_unregister()\n");
backlight_device_unregister(ibm_backlight_device);
ibm_backlight_device = NULL;
}
}
......@@ -5764,11 +5782,16 @@ static int __init fan_init(struct ibm_init_struct *iibm)
fan_control_access_mode != TPACPI_FAN_WR_NONE) {
rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
&fan_attr_group);
if (!(rc < 0))
if (rc < 0)
return rc;
rc = driver_create_file(&tpacpi_hwmon_pdriver.driver,
&driver_attr_fan_watchdog);
if (rc < 0)
if (rc < 0) {
sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj,
&fan_attr_group);
return rc;
}
return 0;
} else
return 1;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册