Add patches accepted for 2.6.26-rc6
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / releases / upstream / 2.6.26-rc6 / 0002-thinkpad-acpi-fix-initialization-error-paths.patch
blob491cd59bf4795cd731b4ecb943da1e600f0eaa74
1 From 9c0a76e16ee6648f4bd19563e9fe12a4f4fabba1 Mon Sep 17 00:00:00 2001
2 From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
3 Date: Tue, 3 Jun 2008 23:36:10 -0300
4 Subject: thinkpad-acpi: fix initialization error paths
6 Rework some subdriver init and exit handlers, in order to fix some
7 initialization error paths that were missing, or broken.
9 Hitting those bugs should be extremely rare in the real world, but should
10 that happen, thinkpad-acpi would fail to dealocate some resources and a
11 reboot might well be needed to be able to load the driver again.
13 Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
14 Signed-off-by: Len Brown <len.brown@intel.com>
15 ---
16 drivers/misc/thinkpad_acpi.c | 435 ++++++++++++++++++++++--------------------
17 1 files changed, 229 insertions(+), 206 deletions(-)
19 diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
20 index f81e048..58973da 100644
21 --- a/drivers/misc/thinkpad_acpi.c
22 +++ b/drivers/misc/thinkpad_acpi.c
23 @@ -1921,6 +1921,29 @@ static struct attribute *hotkey_mask_attributes[] __initdata = {
24 &dev_attr_hotkey_wakeup_hotunplug_complete.attr,
27 +static void hotkey_exit(void)
29 +#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
30 + hotkey_poll_stop_sync();
31 +#endif
33 + if (hotkey_dev_attributes)
34 + delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj);
36 + kfree(hotkey_keycode_map);
38 + if (tp_features.hotkey) {
39 + dbg_printk(TPACPI_DBG_EXIT,
40 + "restoring original hot key mask\n");
41 + /* no short-circuit boolean operator below! */
42 + if ((hotkey_mask_set(hotkey_orig_mask) |
43 + hotkey_status_set(hotkey_orig_status)) != 0)
44 + printk(TPACPI_ERR
45 + "failed to restore hot key mask "
46 + "to BIOS defaults\n");
47 + }
50 static int __init hotkey_init(struct ibm_init_struct *iibm)
52 /* Requirements for changing the default keymaps:
53 @@ -2060,226 +2083,220 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
54 vdbg_printk(TPACPI_DBG_INIT, "hotkeys are %s\n",
55 str_supported(tp_features.hotkey));
57 - if (tp_features.hotkey) {
58 - hotkey_dev_attributes = create_attr_set(13, NULL);
59 - if (!hotkey_dev_attributes)
60 - return -ENOMEM;
61 - res = add_many_to_attr_set(hotkey_dev_attributes,
62 - hotkey_attributes,
63 - ARRAY_SIZE(hotkey_attributes));
64 - if (res)
65 - return res;
66 + if (!tp_features.hotkey)
67 + return 1;
69 - /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
70 - A30, R30, R31, T20-22, X20-21, X22-24. Detected by checking
71 - for HKEY interface version 0x100 */
72 - if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) {
73 - if ((hkeyv >> 8) != 1) {
74 - printk(TPACPI_ERR "unknown version of the "
75 - "HKEY interface: 0x%x\n", hkeyv);
76 - printk(TPACPI_ERR "please report this to %s\n",
77 - TPACPI_MAIL);
78 - } else {
79 - /*
80 - * MHKV 0x100 in A31, R40, R40e,
81 - * T4x, X31, and later
82 - */
83 - tp_features.hotkey_mask = 1;
84 - }
85 + hotkey_dev_attributes = create_attr_set(13, NULL);
86 + if (!hotkey_dev_attributes)
87 + return -ENOMEM;
88 + res = add_many_to_attr_set(hotkey_dev_attributes,
89 + hotkey_attributes,
90 + ARRAY_SIZE(hotkey_attributes));
91 + if (res)
92 + goto err_exit;
94 + /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
95 + A30, R30, R31, T20-22, X20-21, X22-24. Detected by checking
96 + for HKEY interface version 0x100 */
97 + if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) {
98 + if ((hkeyv >> 8) != 1) {
99 + printk(TPACPI_ERR "unknown version of the "
100 + "HKEY interface: 0x%x\n", hkeyv);
101 + printk(TPACPI_ERR "please report this to %s\n",
102 + TPACPI_MAIL);
103 + } else {
104 + /*
105 + * MHKV 0x100 in A31, R40, R40e,
106 + * T4x, X31, and later
107 + */
108 + tp_features.hotkey_mask = 1;
112 - vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n",
113 - str_supported(tp_features.hotkey_mask));
114 + vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n",
115 + str_supported(tp_features.hotkey_mask));
117 - if (tp_features.hotkey_mask) {
118 - if (!acpi_evalf(hkey_handle, &hotkey_all_mask,
119 - "MHKA", "qd")) {
120 - printk(TPACPI_ERR
121 - "missing MHKA handler, "
122 - "please report this to %s\n",
123 - TPACPI_MAIL);
124 - /* FN+F12, FN+F4, FN+F3 */
125 - hotkey_all_mask = 0x080cU;
127 + if (tp_features.hotkey_mask) {
128 + if (!acpi_evalf(hkey_handle, &hotkey_all_mask,
129 + "MHKA", "qd")) {
130 + printk(TPACPI_ERR
131 + "missing MHKA handler, "
132 + "please report this to %s\n",
133 + TPACPI_MAIL);
134 + /* FN+F12, FN+F4, FN+F3 */
135 + hotkey_all_mask = 0x080cU;
139 - /* hotkey_source_mask *must* be zero for
140 - * the first hotkey_mask_get */
141 - res = hotkey_status_get(&hotkey_orig_status);
142 - if (!res && tp_features.hotkey_mask) {
143 - res = hotkey_mask_get();
144 - hotkey_orig_mask = hotkey_mask;
145 - if (!res) {
146 - res = add_many_to_attr_set(
147 - hotkey_dev_attributes,
148 - hotkey_mask_attributes,
149 - ARRAY_SIZE(hotkey_mask_attributes));
152 + /* hotkey_source_mask *must* be zero for
153 + * the first hotkey_mask_get */
154 + res = hotkey_status_get(&hotkey_orig_status);
155 + if (res)
156 + goto err_exit;
158 + if (tp_features.hotkey_mask) {
159 + res = hotkey_mask_get();
160 + if (res)
161 + goto err_exit;
163 + hotkey_orig_mask = hotkey_mask;
164 + res = add_many_to_attr_set(
165 + hotkey_dev_attributes,
166 + hotkey_mask_attributes,
167 + ARRAY_SIZE(hotkey_mask_attributes));
168 + if (res)
169 + goto err_exit;
172 #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
173 - if (tp_features.hotkey_mask) {
174 - hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK
175 - & ~hotkey_all_mask;
176 - } else {
177 - hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK;
179 + if (tp_features.hotkey_mask) {
180 + hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK
181 + & ~hotkey_all_mask;
182 + } else {
183 + hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK;
186 - vdbg_printk(TPACPI_DBG_INIT,
187 - "hotkey source mask 0x%08x, polling freq %d\n",
188 - hotkey_source_mask, hotkey_poll_freq);
189 + vdbg_printk(TPACPI_DBG_INIT,
190 + "hotkey source mask 0x%08x, polling freq %d\n",
191 + hotkey_source_mask, hotkey_poll_freq);
192 #endif
194 - /* Not all thinkpads have a hardware radio switch */
195 - if (!res && acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
196 - tp_features.hotkey_wlsw = 1;
197 - printk(TPACPI_INFO
198 - "radio switch found; radios are %s\n",
199 - enabled(status, 0));
200 - res = add_to_attr_set(hotkey_dev_attributes,
201 - &dev_attr_hotkey_radio_sw.attr);
203 + /* Not all thinkpads have a hardware radio switch */
204 + if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
205 + tp_features.hotkey_wlsw = 1;
206 + printk(TPACPI_INFO
207 + "radio switch found; radios are %s\n",
208 + enabled(status, 0));
209 + res = add_to_attr_set(hotkey_dev_attributes,
210 + &dev_attr_hotkey_radio_sw.attr);
213 - /* For X41t, X60t, X61t Tablets... */
214 - if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) {
215 - tp_features.hotkey_tablet = 1;
216 - printk(TPACPI_INFO
217 - "possible tablet mode switch found; "
218 - "ThinkPad in %s mode\n",
219 - (status & TP_HOTKEY_TABLET_MASK)?
220 - "tablet" : "laptop");
221 - res = add_to_attr_set(hotkey_dev_attributes,
222 - &dev_attr_hotkey_tablet_mode.attr);
224 + /* For X41t, X60t, X61t Tablets... */
225 + if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) {
226 + tp_features.hotkey_tablet = 1;
227 + printk(TPACPI_INFO
228 + "possible tablet mode switch found; "
229 + "ThinkPad in %s mode\n",
230 + (status & TP_HOTKEY_TABLET_MASK)?
231 + "tablet" : "laptop");
232 + res = add_to_attr_set(hotkey_dev_attributes,
233 + &dev_attr_hotkey_tablet_mode.attr);
236 - if (!res)
237 - res = register_attr_set_with_sysfs(
238 - hotkey_dev_attributes,
239 - &tpacpi_pdev->dev.kobj);
240 - if (res)
241 - return res;
242 + if (!res)
243 + res = register_attr_set_with_sysfs(
244 + hotkey_dev_attributes,
245 + &tpacpi_pdev->dev.kobj);
246 + if (res)
247 + goto err_exit;
249 - /* Set up key map */
250 + /* Set up key map */
252 - hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE,
253 - GFP_KERNEL);
254 - if (!hotkey_keycode_map) {
255 - printk(TPACPI_ERR
256 - "failed to allocate memory for key map\n");
257 - return -ENOMEM;
259 + hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE,
260 + GFP_KERNEL);
261 + if (!hotkey_keycode_map) {
262 + printk(TPACPI_ERR
263 + "failed to allocate memory for key map\n");
264 + res = -ENOMEM;
265 + goto err_exit;
268 - if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) {
269 - dbg_printk(TPACPI_DBG_INIT,
270 - "using Lenovo default hot key map\n");
271 - memcpy(hotkey_keycode_map, &lenovo_keycode_map,
272 - TPACPI_HOTKEY_MAP_SIZE);
273 + if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) {
274 + dbg_printk(TPACPI_DBG_INIT,
275 + "using Lenovo default hot key map\n");
276 + memcpy(hotkey_keycode_map, &lenovo_keycode_map,
277 + TPACPI_HOTKEY_MAP_SIZE);
278 + } else {
279 + dbg_printk(TPACPI_DBG_INIT,
280 + "using IBM default hot key map\n");
281 + memcpy(hotkey_keycode_map, &ibm_keycode_map,
282 + TPACPI_HOTKEY_MAP_SIZE);
285 + set_bit(EV_KEY, tpacpi_inputdev->evbit);
286 + set_bit(EV_MSC, tpacpi_inputdev->evbit);
287 + set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
288 + tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
289 + tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN;
290 + tpacpi_inputdev->keycode = hotkey_keycode_map;
291 + for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) {
292 + if (hotkey_keycode_map[i] != KEY_RESERVED) {
293 + set_bit(hotkey_keycode_map[i],
294 + tpacpi_inputdev->keybit);
295 } else {
296 - dbg_printk(TPACPI_DBG_INIT,
297 - "using IBM default hot key map\n");
298 - memcpy(hotkey_keycode_map, &ibm_keycode_map,
299 - TPACPI_HOTKEY_MAP_SIZE);
302 - set_bit(EV_KEY, tpacpi_inputdev->evbit);
303 - set_bit(EV_MSC, tpacpi_inputdev->evbit);
304 - set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
305 - tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
306 - tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN;
307 - tpacpi_inputdev->keycode = hotkey_keycode_map;
308 - for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) {
309 - if (hotkey_keycode_map[i] != KEY_RESERVED) {
310 - set_bit(hotkey_keycode_map[i],
311 - tpacpi_inputdev->keybit);
312 - } else {
313 - if (i < sizeof(hotkey_reserved_mask)*8)
314 - hotkey_reserved_mask |= 1 << i;
318 - if (tp_features.hotkey_wlsw) {
319 - set_bit(EV_SW, tpacpi_inputdev->evbit);
320 - set_bit(SW_RFKILL_ALL, tpacpi_inputdev->swbit);
322 - if (tp_features.hotkey_tablet) {
323 - set_bit(EV_SW, tpacpi_inputdev->evbit);
324 - set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit);
325 + if (i < sizeof(hotkey_reserved_mask)*8)
326 + hotkey_reserved_mask |= 1 << i;
330 - /* Do not issue duplicate brightness change events to
331 - * userspace */
332 - if (!tp_features.bright_acpimode)
333 - /* update bright_acpimode... */
334 - tpacpi_check_std_acpi_brightness_support();
336 - if (tp_features.bright_acpimode) {
337 - printk(TPACPI_INFO
338 - "This ThinkPad has standard ACPI backlight "
339 - "brightness control, supported by the ACPI "
340 - "video driver\n");
341 - printk(TPACPI_NOTICE
342 - "Disabling thinkpad-acpi brightness events "
343 - "by default...\n");
345 - /* The hotkey_reserved_mask change below is not
346 - * necessary while the keys are at KEY_RESERVED in the
347 - * default map, but better safe than sorry, leave it
348 - * here as a marker of what we have to do, especially
349 - * when we finally become able to set this at runtime
350 - * on response to X.org requests */
351 - hotkey_reserved_mask |=
352 - (1 << TP_ACPI_HOTKEYSCAN_FNHOME)
353 - | (1 << TP_ACPI_HOTKEYSCAN_FNEND);
355 + if (tp_features.hotkey_wlsw) {
356 + set_bit(EV_SW, tpacpi_inputdev->evbit);
357 + set_bit(SW_RFKILL_ALL, tpacpi_inputdev->swbit);
359 + if (tp_features.hotkey_tablet) {
360 + set_bit(EV_SW, tpacpi_inputdev->evbit);
361 + set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit);
364 - dbg_printk(TPACPI_DBG_INIT,
365 - "enabling hot key handling\n");
366 - res = hotkey_status_set(1);
367 - if (res)
368 - return res;
369 - res = hotkey_mask_set(((hotkey_all_mask | hotkey_source_mask)
370 - & ~hotkey_reserved_mask)
371 - | hotkey_orig_mask);
372 - if (res < 0 && res != -ENXIO)
373 - return res;
374 + /* Do not issue duplicate brightness change events to
375 + * userspace */
376 + if (!tp_features.bright_acpimode)
377 + /* update bright_acpimode... */
378 + tpacpi_check_std_acpi_brightness_support();
380 - dbg_printk(TPACPI_DBG_INIT,
381 - "legacy hot key reporting over procfs %s\n",
382 - (hotkey_report_mode < 2) ?
383 - "enabled" : "disabled");
384 + if (tp_features.bright_acpimode) {
385 + printk(TPACPI_INFO
386 + "This ThinkPad has standard ACPI backlight "
387 + "brightness control, supported by the ACPI "
388 + "video driver\n");
389 + printk(TPACPI_NOTICE
390 + "Disabling thinkpad-acpi brightness events "
391 + "by default...\n");
393 + /* The hotkey_reserved_mask change below is not
394 + * necessary while the keys are at KEY_RESERVED in the
395 + * default map, but better safe than sorry, leave it
396 + * here as a marker of what we have to do, especially
397 + * when we finally become able to set this at runtime
398 + * on response to X.org requests */
399 + hotkey_reserved_mask |=
400 + (1 << TP_ACPI_HOTKEYSCAN_FNHOME)
401 + | (1 << TP_ACPI_HOTKEYSCAN_FNEND);
404 + dbg_printk(TPACPI_DBG_INIT, "enabling hot key handling\n");
405 + res = hotkey_status_set(1);
406 + if (res) {
407 + hotkey_exit();
408 + return res;
410 + res = hotkey_mask_set(((hotkey_all_mask | hotkey_source_mask)
411 + & ~hotkey_reserved_mask)
412 + | hotkey_orig_mask);
413 + if (res < 0 && res != -ENXIO) {
414 + hotkey_exit();
415 + return res;
418 - tpacpi_inputdev->open = &hotkey_inputdev_open;
419 - tpacpi_inputdev->close = &hotkey_inputdev_close;
420 + dbg_printk(TPACPI_DBG_INIT,
421 + "legacy hot key reporting over procfs %s\n",
422 + (hotkey_report_mode < 2) ?
423 + "enabled" : "disabled");
425 - hotkey_poll_setup_safe(1);
426 - tpacpi_input_send_radiosw();
427 - tpacpi_input_send_tabletsw();
429 + tpacpi_inputdev->open = &hotkey_inputdev_open;
430 + tpacpi_inputdev->close = &hotkey_inputdev_close;
432 - return (tp_features.hotkey)? 0 : 1;
434 + hotkey_poll_setup_safe(1);
435 + tpacpi_input_send_radiosw();
436 + tpacpi_input_send_tabletsw();
438 -static void hotkey_exit(void)
440 -#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
441 - hotkey_poll_stop_sync();
442 -#endif
443 + return 0;
445 - if (tp_features.hotkey) {
446 - dbg_printk(TPACPI_DBG_EXIT,
447 - "restoring original hot key mask\n");
448 - /* no short-circuit boolean operator below! */
449 - if ((hotkey_mask_set(hotkey_orig_mask) |
450 - hotkey_status_set(hotkey_orig_status)) != 0)
451 - printk(TPACPI_ERR
452 - "failed to restore hot key mask "
453 - "to BIOS defaults\n");
455 +err_exit:
456 + delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj);
457 + hotkey_dev_attributes = NULL;
459 - if (hotkey_dev_attributes) {
460 - delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj);
461 - hotkey_dev_attributes = NULL;
463 + return (res < 0)? res : 1;
466 static void hotkey_notify(struct ibm_struct *ibm, u32 event)
467 @@ -3319,7 +3336,7 @@ static struct tpacpi_led_classdev tpacpi_led_thinklight = {
469 static int __init light_init(struct ibm_init_struct *iibm)
471 - int rc = 0;
472 + int rc;
474 vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n");
476 @@ -3337,20 +3354,23 @@ static int __init light_init(struct ibm_init_struct *iibm)
477 tp_features.light_status =
478 acpi_evalf(ec_handle, NULL, "KBLT", "qv");
480 - vdbg_printk(TPACPI_DBG_INIT, "light is %s\n",
481 - str_supported(tp_features.light));
482 + vdbg_printk(TPACPI_DBG_INIT, "light is %s, light status is %s\n",
483 + str_supported(tp_features.light),
484 + str_supported(tp_features.light_status));
486 - if (tp_features.light) {
487 - rc = led_classdev_register(&tpacpi_pdev->dev,
488 - &tpacpi_led_thinklight.led_classdev);
490 + if (!tp_features.light)
491 + return 1;
493 + rc = led_classdev_register(&tpacpi_pdev->dev,
494 + &tpacpi_led_thinklight.led_classdev);
496 if (rc < 0) {
497 tp_features.light = 0;
498 tp_features.light_status = 0;
499 - } else {
500 - rc = (tp_features.light)? 0 : 1;
501 + } else {
502 + rc = 0;
505 return rc;
508 @@ -3978,7 +3998,6 @@ static void led_exit(void)
511 kfree(tpacpi_leds);
512 - tpacpi_leds = NULL;
515 static int __init led_init(struct ibm_init_struct *iibm)
516 @@ -4802,7 +4821,6 @@ static void brightness_exit(void)
517 vdbg_printk(TPACPI_DBG_EXIT,
518 "calling backlight_device_unregister()\n");
519 backlight_device_unregister(ibm_backlight_device);
520 - ibm_backlight_device = NULL;
524 @@ -5764,11 +5782,16 @@ static int __init fan_init(struct ibm_init_struct *iibm)
525 fan_control_access_mode != TPACPI_FAN_WR_NONE) {
526 rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
527 &fan_attr_group);
528 - if (!(rc < 0))
529 - rc = driver_create_file(&tpacpi_hwmon_pdriver.driver,
530 - &driver_attr_fan_watchdog);
531 if (rc < 0)
532 return rc;
534 + rc = driver_create_file(&tpacpi_hwmon_pdriver.driver,
535 + &driver_attr_fan_watchdog);
536 + if (rc < 0) {
537 + sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj,
538 + &fan_attr_group);
539 + return rc;
541 return 0;
542 } else
543 return 1;
545 1.5.5.3