diff options
author | Henrique de Moraes Holschuh <hmh@hmh.eng.br> | 2007-04-21 10:08:31 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-04-21 23:30:33 -0400 |
commit | 5fba344cfdbaa79e6320da26c3db34dfb219a845 (patch) | |
tree | 7dd7629444f4ca95b469b56341b40268fad98aab /drivers/misc | |
parent | 132ce09123755ec5e3d3a8ae22f4f753c3baac97 (diff) |
ACPI: thinkpad-acpi: clean up probing and move init to subdrivers
Move most of the probing code to its own function, and most of the
subdriver-specific init code into subdriver init functions.
This allows us to not define pci_handle unless the dock subdriver is
enabled, as well.
This patch causes a minor userland interface change: if a subdriver doesn't
detect a capability, /proc entries for it are not created anymore (as
opposed to a /proc entry that just returned "unsupported").
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/thinkpad_acpi.c | 231 | ||||
-rw-r--r-- | drivers/misc/thinkpad_acpi.h | 4 |
2 files changed, 151 insertions, 84 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 7fa906fd45c0..eeab39418c71 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
@@ -277,9 +277,9 @@ static int _sta(acpi_handle handle) | |||
277 | * ACPI device model | 277 | * ACPI device model |
278 | */ | 278 | */ |
279 | 279 | ||
280 | static void __init ibm_handle_init(char *name, | 280 | static void ibm_handle_init(char *name, |
281 | acpi_handle * handle, acpi_handle parent, | 281 | acpi_handle *handle, acpi_handle parent, |
282 | char **paths, int num_paths, char **path) | 282 | char **paths, int num_paths, char **path) |
283 | { | 283 | { |
284 | int i; | 284 | int i; |
285 | acpi_status status; | 285 | acpi_status status; |
@@ -351,8 +351,8 @@ static int __init register_tpacpi_subdriver(struct ibm_struct *ibm) | |||
351 | 351 | ||
352 | ibm->driver = kzalloc(sizeof(struct acpi_driver), GFP_KERNEL); | 352 | ibm->driver = kzalloc(sizeof(struct acpi_driver), GFP_KERNEL); |
353 | if (!ibm->driver) { | 353 | if (!ibm->driver) { |
354 | printk(IBM_ERR "kmalloc(ibm->driver) failed\n"); | 354 | printk(IBM_ERR "kzalloc(ibm->driver) failed\n"); |
355 | return -1; | 355 | return -ENOMEM; |
356 | } | 356 | } |
357 | 357 | ||
358 | sprintf(ibm->driver->name, "%s_%s", IBM_NAME, ibm->name); | 358 | sprintf(ibm->driver->name, "%s_%s", IBM_NAME, ibm->name); |
@@ -364,7 +364,9 @@ static int __init register_tpacpi_subdriver(struct ibm_struct *ibm) | |||
364 | printk(IBM_ERR "acpi_bus_register_driver(%s) failed: %d\n", | 364 | printk(IBM_ERR "acpi_bus_register_driver(%s) failed: %d\n", |
365 | ibm->hid, ret); | 365 | ibm->hid, ret); |
366 | kfree(ibm->driver); | 366 | kfree(ibm->driver); |
367 | } | 367 | ibm->driver = NULL; |
368 | } else if (!ret) | ||
369 | ibm->driver_registered = 1; | ||
368 | 370 | ||
369 | return ret; | 371 | return ret; |
370 | } | 372 | } |
@@ -495,6 +497,8 @@ static int hotkey_orig_mask; | |||
495 | 497 | ||
496 | static int hotkey_init(void) | 498 | static int hotkey_init(void) |
497 | { | 499 | { |
500 | IBM_HANDLE_INIT(hkey); | ||
501 | |||
498 | /* hotkey not supported on 570 */ | 502 | /* hotkey not supported on 570 */ |
499 | hotkey_supported = hkey_handle != NULL; | 503 | hotkey_supported = hkey_handle != NULL; |
500 | 504 | ||
@@ -508,13 +512,14 @@ static int hotkey_init(void) | |||
508 | return -ENODEV; | 512 | return -ENODEV; |
509 | } | 513 | } |
510 | 514 | ||
511 | return 0; | 515 | return (hotkey_supported)? 0 : 1; |
512 | } | 516 | } |
513 | 517 | ||
514 | static void hotkey_exit(void) | 518 | static void hotkey_exit(void) |
515 | { | 519 | { |
516 | if (hotkey_supported) | 520 | if (hotkey_supported) { |
517 | hotkey_set(hotkey_orig_status, hotkey_orig_mask); | 521 | hotkey_set(hotkey_orig_status, hotkey_orig_mask); |
522 | } | ||
518 | } | 523 | } |
519 | 524 | ||
520 | static void hotkey_notify(struct ibm_struct *ibm, u32 event) | 525 | static void hotkey_notify(struct ibm_struct *ibm, u32 event) |
@@ -628,12 +633,14 @@ static int bluetooth_supported; | |||
628 | 633 | ||
629 | static int bluetooth_init(void) | 634 | static int bluetooth_init(void) |
630 | { | 635 | { |
636 | IBM_HANDLE_INIT(hkey); | ||
637 | |||
631 | /* bluetooth not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, | 638 | /* bluetooth not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, |
632 | G4x, R30, R31, R40e, R50e, T20-22, X20-21 */ | 639 | G4x, R30, R31, R40e, R50e, T20-22, X20-21 */ |
633 | bluetooth_supported = hkey_handle && | 640 | bluetooth_supported = hkey_handle && |
634 | acpi_evalf(hkey_handle, NULL, "GBDC", "qv"); | 641 | acpi_evalf(hkey_handle, NULL, "GBDC", "qv"); |
635 | 642 | ||
636 | return 0; | 643 | return (bluetooth_supported)? 0 : 1; |
637 | } | 644 | } |
638 | 645 | ||
639 | static int bluetooth_status(void) | 646 | static int bluetooth_status(void) |
@@ -697,10 +704,12 @@ static int wan_supported; | |||
697 | 704 | ||
698 | static int wan_init(void) | 705 | static int wan_init(void) |
699 | { | 706 | { |
707 | IBM_HANDLE_INIT(hkey); | ||
708 | |||
700 | wan_supported = hkey_handle && | 709 | wan_supported = hkey_handle && |
701 | acpi_evalf(hkey_handle, NULL, "GWAN", "qv"); | 710 | acpi_evalf(hkey_handle, NULL, "GWAN", "qv"); |
702 | 711 | ||
703 | return 0; | 712 | return (wan_supported)? 0 : 1; |
704 | } | 713 | } |
705 | 714 | ||
706 | static int wan_status(void) | 715 | static int wan_status(void) |
@@ -775,6 +784,9 @@ static int video_init(void) | |||
775 | { | 784 | { |
776 | int ivga; | 785 | int ivga; |
777 | 786 | ||
787 | IBM_HANDLE_INIT(vid); | ||
788 | IBM_HANDLE_INIT(vid2); | ||
789 | |||
778 | if (vid2_handle && acpi_evalf(NULL, &ivga, "\\IVGA", "d") && ivga) | 790 | if (vid2_handle && acpi_evalf(NULL, &ivga, "\\IVGA", "d") && ivga) |
779 | /* G41, assume IVGA doesn't change */ | 791 | /* G41, assume IVGA doesn't change */ |
780 | vid_handle = vid2_handle; | 792 | vid_handle = vid2_handle; |
@@ -792,7 +804,7 @@ static int video_init(void) | |||
792 | /* all others */ | 804 | /* all others */ |
793 | video_supported = TPACPI_VIDEO_NEW; | 805 | video_supported = TPACPI_VIDEO_NEW; |
794 | 806 | ||
795 | return 0; | 807 | return (video_supported != TPACPI_VIDEO_NONE)? 0 : 1; |
796 | } | 808 | } |
797 | 809 | ||
798 | static void video_exit(void) | 810 | static void video_exit(void) |
@@ -979,6 +991,10 @@ IBM_HANDLE(ledb, ec, "LEDB"); /* G4x */ | |||
979 | 991 | ||
980 | static int light_init(void) | 992 | static int light_init(void) |
981 | { | 993 | { |
994 | IBM_HANDLE_INIT(ledb); | ||
995 | IBM_HANDLE_INIT(lght); | ||
996 | IBM_HANDLE_INIT(cmos); | ||
997 | |||
982 | /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */ | 998 | /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */ |
983 | light_supported = (cmos_handle || lght_handle) && !ledb_handle; | 999 | light_supported = (cmos_handle || lght_handle) && !ledb_handle; |
984 | 1000 | ||
@@ -988,7 +1004,7 @@ static int light_init(void) | |||
988 | light_status_supported = acpi_evalf(ec_handle, NULL, | 1004 | light_status_supported = acpi_evalf(ec_handle, NULL, |
989 | "KBLT", "qv"); | 1005 | "KBLT", "qv"); |
990 | 1006 | ||
991 | return 0; | 1007 | return (light_supported)? 0 : 1; |
992 | } | 1008 | } |
993 | 1009 | ||
994 | static int light_read(char *p) | 1010 | static int light_read(char *p) |
@@ -1044,9 +1060,6 @@ static int light_write(char *buf) | |||
1044 | * Dock subdriver | 1060 | * Dock subdriver |
1045 | */ | 1061 | */ |
1046 | 1062 | ||
1047 | /* don't list other alternatives as we install a notify handler on the 570 */ | ||
1048 | IBM_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */ | ||
1049 | |||
1050 | #ifdef CONFIG_THINKPAD_ACPI_DOCK | 1063 | #ifdef CONFIG_THINKPAD_ACPI_DOCK |
1051 | 1064 | ||
1052 | IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */ | 1065 | IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */ |
@@ -1055,8 +1068,19 @@ IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */ | |||
1055 | "\\_SB.PCI.ISA.SLCE", /* 570 */ | 1068 | "\\_SB.PCI.ISA.SLCE", /* 570 */ |
1056 | ); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */ | 1069 | ); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */ |
1057 | 1070 | ||
1071 | /* don't list other alternatives as we install a notify handler on the 570 */ | ||
1072 | IBM_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */ | ||
1073 | |||
1058 | #define dock_docked() (_sta(dock_handle) & 1) | 1074 | #define dock_docked() (_sta(dock_handle) & 1) |
1059 | 1075 | ||
1076 | static int dock_init(void) | ||
1077 | { | ||
1078 | IBM_HANDLE_INIT(dock); | ||
1079 | IBM_HANDLE_INIT(pci); | ||
1080 | |||
1081 | return (dock_handle)? 0 : 1; | ||
1082 | } | ||
1083 | |||
1060 | static void dock_notify(struct ibm_struct *ibm, u32 event) | 1084 | static void dock_notify(struct ibm_struct *ibm, u32 event) |
1061 | { | 1085 | { |
1062 | int docked = dock_docked(); | 1086 | int docked = dock_docked(); |
@@ -1147,6 +1171,13 @@ IBM_HANDLE(bay2_ej, bay2, "_EJ3", /* 600e/x, 770e, A3x */ | |||
1147 | 1171 | ||
1148 | static int bay_init(void) | 1172 | static int bay_init(void) |
1149 | { | 1173 | { |
1174 | IBM_HANDLE_INIT(bay); | ||
1175 | if (bay_handle) | ||
1176 | IBM_HANDLE_INIT(bay_ej); | ||
1177 | IBM_HANDLE_INIT(bay2); | ||
1178 | if (bay2_handle) | ||
1179 | IBM_HANDLE_INIT(bay2_ej); | ||
1180 | |||
1150 | bay_status_supported = bay_handle && | 1181 | bay_status_supported = bay_handle && |
1151 | acpi_evalf(bay_handle, NULL, "_STA", "qv"); | 1182 | acpi_evalf(bay_handle, NULL, "_STA", "qv"); |
1152 | bay_status2_supported = bay2_handle && | 1183 | bay_status2_supported = bay2_handle && |
@@ -1157,7 +1188,8 @@ static int bay_init(void) | |||
1157 | bay_eject2_supported = bay2_handle && bay2_ej_handle && | 1188 | bay_eject2_supported = bay2_handle && bay2_ej_handle && |
1158 | (strlencmp(bay2_ej_path, "_EJ0") == 0 || experimental); | 1189 | (strlencmp(bay2_ej_path, "_EJ0") == 0 || experimental); |
1159 | 1190 | ||
1160 | return 0; | 1191 | return (bay_status_supported || bay_eject_supported || |
1192 | bay_status2_supported || bay_eject2_supported)? 0 : 1; | ||
1161 | } | 1193 | } |
1162 | 1194 | ||
1163 | static void bay_notify(struct ibm_struct *ibm, u32 event) | 1195 | static void bay_notify(struct ibm_struct *ibm, u32 event) |
@@ -1221,6 +1253,13 @@ static int bay_write(char *buf) | |||
1221 | * CMOS subdriver | 1253 | * CMOS subdriver |
1222 | */ | 1254 | */ |
1223 | 1255 | ||
1256 | static int cmos_init(void) | ||
1257 | { | ||
1258 | IBM_HANDLE_INIT(cmos); | ||
1259 | |||
1260 | return (cmos_handle)? 0 : 1; | ||
1261 | } | ||
1262 | |||
1224 | static int cmos_eval(int cmos_cmd) | 1263 | static int cmos_eval(int cmos_cmd) |
1225 | { | 1264 | { |
1226 | if (cmos_handle) | 1265 | if (cmos_handle) |
@@ -1281,6 +1320,8 @@ IBM_HANDLE(led, ec, "SLED", /* 570 */ | |||
1281 | 1320 | ||
1282 | static int led_init(void) | 1321 | static int led_init(void) |
1283 | { | 1322 | { |
1323 | IBM_HANDLE_INIT(led); | ||
1324 | |||
1284 | if (!led_handle) | 1325 | if (!led_handle) |
1285 | /* led not supported on R30, R31 */ | 1326 | /* led not supported on R30, R31 */ |
1286 | led_supported = TPACPI_LED_NONE; | 1327 | led_supported = TPACPI_LED_NONE; |
@@ -1294,7 +1335,7 @@ static int led_init(void) | |||
1294 | /* all others */ | 1335 | /* all others */ |
1295 | led_supported = TPACPI_LED_NEW; | 1336 | led_supported = TPACPI_LED_NEW; |
1296 | 1337 | ||
1297 | return 0; | 1338 | return (led_supported != TPACPI_LED_NONE)? 0 : 1; |
1298 | } | 1339 | } |
1299 | 1340 | ||
1300 | #define led_status(s) ((s) == 0 ? "off" : ((s) == 1 ? "on" : "blinking")) | 1341 | #define led_status(s) ((s) == 0 ? "off" : ((s) == 1 ? "on" : "blinking")) |
@@ -1391,6 +1432,13 @@ static int led_write(char *buf) | |||
1391 | 1432 | ||
1392 | IBM_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */ | 1433 | IBM_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */ |
1393 | 1434 | ||
1435 | static int beep_init(void) | ||
1436 | { | ||
1437 | IBM_HANDLE_INIT(beep); | ||
1438 | |||
1439 | return (beep_handle)? 0 : 1; | ||
1440 | } | ||
1441 | |||
1394 | static int beep_read(char *p) | 1442 | static int beep_read(char *p) |
1395 | { | 1443 | { |
1396 | int len = 0; | 1444 | int len = 0; |
@@ -1436,7 +1484,9 @@ static int thermal_init(void) | |||
1436 | { | 1484 | { |
1437 | u8 t, ta1, ta2; | 1485 | u8 t, ta1, ta2; |
1438 | int i; | 1486 | int i; |
1439 | int acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv"); | 1487 | int acpi_tmp7; |
1488 | |||
1489 | acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv"); | ||
1440 | 1490 | ||
1441 | if (ibm_thinkpad_ec_found && experimental) { | 1491 | if (ibm_thinkpad_ec_found && experimental) { |
1442 | /* | 1492 | /* |
@@ -1492,7 +1542,7 @@ static int thermal_init(void) | |||
1492 | thermal_read_mode = TPACPI_THERMAL_NONE; | 1542 | thermal_read_mode = TPACPI_THERMAL_NONE; |
1493 | } | 1543 | } |
1494 | 1544 | ||
1495 | return 0; | 1545 | return (thermal_read_mode != TPACPI_THERMAL_NONE)? 0 : 1; |
1496 | } | 1546 | } |
1497 | 1547 | ||
1498 | static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s) | 1548 | static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s) |
@@ -1973,6 +2023,10 @@ static int fan_init(void) | |||
1973 | fan_control_status_known = 1; | 2023 | fan_control_status_known = 1; |
1974 | fan_watchdog_maxinterval = 0; | 2024 | fan_watchdog_maxinterval = 0; |
1975 | 2025 | ||
2026 | IBM_HANDLE_INIT(fans); | ||
2027 | IBM_HANDLE_INIT(gfan); | ||
2028 | IBM_HANDLE_INIT(sfan); | ||
2029 | |||
1976 | if (gfan_handle) { | 2030 | if (gfan_handle) { |
1977 | /* 570, 600e/x, 770e, 770x */ | 2031 | /* 570, 600e/x, 770e, 770x */ |
1978 | fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN; | 2032 | fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN; |
@@ -2010,7 +2064,7 @@ static int fan_init(void) | |||
2010 | printk(IBM_ERR | 2064 | printk(IBM_ERR |
2011 | "ThinkPad ACPI EC access misbehaving, " | 2065 | "ThinkPad ACPI EC access misbehaving, " |
2012 | "fan status and control unavailable\n"); | 2066 | "fan status and control unavailable\n"); |
2013 | return 0; | 2067 | return 1; |
2014 | } | 2068 | } |
2015 | } | 2069 | } |
2016 | 2070 | ||
@@ -2041,7 +2095,9 @@ static int fan_init(void) | |||
2041 | } | 2095 | } |
2042 | } | 2096 | } |
2043 | 2097 | ||
2044 | return 0; | 2098 | return (fan_status_access_mode != TPACPI_FAN_NONE || |
2099 | fan_control_access_mode != TPACPI_FAN_WR_NONE)? | ||
2100 | 0 : 1; | ||
2045 | } | 2101 | } |
2046 | 2102 | ||
2047 | static int fan_get_status(u8 *status) | 2103 | static int fan_get_status(u8 *status) |
@@ -2485,6 +2541,7 @@ static struct ibm_struct ibms[] = { | |||
2485 | #ifdef CONFIG_THINKPAD_ACPI_DOCK | 2541 | #ifdef CONFIG_THINKPAD_ACPI_DOCK |
2486 | { | 2542 | { |
2487 | .name = "dock", | 2543 | .name = "dock", |
2544 | .init = dock_init, | ||
2488 | .read = dock_read, | 2545 | .read = dock_read, |
2489 | .write = dock_write, | 2546 | .write = dock_write, |
2490 | .notify = dock_notify, | 2547 | .notify = dock_notify, |
@@ -2512,6 +2569,7 @@ static struct ibm_struct ibms[] = { | |||
2512 | #endif /* CONFIG_THINKPAD_ACPI_BAY */ | 2569 | #endif /* CONFIG_THINKPAD_ACPI_BAY */ |
2513 | { | 2570 | { |
2514 | .name = "cmos", | 2571 | .name = "cmos", |
2572 | .init = cmos_init, | ||
2515 | .read = cmos_read, | 2573 | .read = cmos_read, |
2516 | .write = cmos_write, | 2574 | .write = cmos_write, |
2517 | }, | 2575 | }, |
@@ -2523,6 +2581,7 @@ static struct ibm_struct ibms[] = { | |||
2523 | }, | 2581 | }, |
2524 | { | 2582 | { |
2525 | .name = "beep", | 2583 | .name = "beep", |
2584 | .init = beep_init, | ||
2526 | .read = beep_read, | 2585 | .read = beep_read, |
2527 | .write = beep_write, | 2586 | .write = beep_write, |
2528 | }, | 2587 | }, |
@@ -2571,20 +2630,33 @@ static int __init ibm_init(struct ibm_struct *ibm) | |||
2571 | if (ibm->experimental && !experimental) | 2630 | if (ibm->experimental && !experimental) |
2572 | return 0; | 2631 | return 0; |
2573 | 2632 | ||
2574 | if (ibm->hid) { | ||
2575 | ret = register_tpacpi_subdriver(ibm); | ||
2576 | if (ret < 0) | ||
2577 | return ret; | ||
2578 | ibm->driver_registered = 1; | ||
2579 | } | ||
2580 | |||
2581 | if (ibm->init) { | 2633 | if (ibm->init) { |
2582 | ret = ibm->init(); | 2634 | ret = ibm->init(); |
2583 | if (ret != 0) | 2635 | if (ret > 0) |
2636 | return 0; /* probe failed */ | ||
2637 | if (ret) | ||
2584 | return ret; | 2638 | return ret; |
2585 | ibm->init_called = 1; | 2639 | ibm->init_called = 1; |
2586 | } | 2640 | } |
2587 | 2641 | ||
2642 | if (ibm->hid) { | ||
2643 | ret = register_tpacpi_subdriver(ibm); | ||
2644 | if (ret) | ||
2645 | goto err_out; | ||
2646 | } | ||
2647 | |||
2648 | if (ibm->notify) { | ||
2649 | ret = setup_notify(ibm); | ||
2650 | if (ret == -ENODEV) { | ||
2651 | printk(IBM_NOTICE "disabling subdriver %s\n", | ||
2652 | ibm->name); | ||
2653 | ret = 0; | ||
2654 | goto err_out; | ||
2655 | } | ||
2656 | if (ret < 0) | ||
2657 | goto err_out; | ||
2658 | } | ||
2659 | |||
2588 | if (ibm->read) { | 2660 | if (ibm->read) { |
2589 | entry = create_proc_entry(ibm->name, | 2661 | entry = create_proc_entry(ibm->name, |
2590 | S_IFREG | S_IRUGO | S_IWUSR, | 2662 | S_IFREG | S_IRUGO | S_IWUSR, |
@@ -2592,7 +2664,8 @@ static int __init ibm_init(struct ibm_struct *ibm) | |||
2592 | if (!entry) { | 2664 | if (!entry) { |
2593 | printk(IBM_ERR "unable to create proc entry %s\n", | 2665 | printk(IBM_ERR "unable to create proc entry %s\n", |
2594 | ibm->name); | 2666 | ibm->name); |
2595 | return -ENODEV; | 2667 | ret = -ENODEV; |
2668 | goto err_out; | ||
2596 | } | 2669 | } |
2597 | entry->owner = THIS_MODULE; | 2670 | entry->owner = THIS_MODULE; |
2598 | entry->data = ibm; | 2671 | entry->data = ibm; |
@@ -2602,36 +2675,36 @@ static int __init ibm_init(struct ibm_struct *ibm) | |||
2602 | ibm->proc_created = 1; | 2675 | ibm->proc_created = 1; |
2603 | } | 2676 | } |
2604 | 2677 | ||
2605 | if (ibm->notify) { | ||
2606 | ret = setup_notify(ibm); | ||
2607 | if (ret == -ENODEV) { | ||
2608 | printk(IBM_NOTICE "disabling subdriver %s\n", | ||
2609 | ibm->name); | ||
2610 | ibm_exit(ibm); | ||
2611 | return 0; | ||
2612 | } | ||
2613 | if (ret < 0) | ||
2614 | return ret; | ||
2615 | } | ||
2616 | |||
2617 | return 0; | 2678 | return 0; |
2679 | |||
2680 | err_out: | ||
2681 | ibm_exit(ibm); | ||
2682 | return (ret < 0)? ret : 0; | ||
2618 | } | 2683 | } |
2619 | 2684 | ||
2620 | static void ibm_exit(struct ibm_struct *ibm) | 2685 | static void ibm_exit(struct ibm_struct *ibm) |
2621 | { | 2686 | { |
2622 | if (ibm->notify_installed) | 2687 | if (ibm->notify_installed) { |
2623 | acpi_remove_notify_handler(*ibm->handle, ibm->type, | 2688 | acpi_remove_notify_handler(*ibm->handle, ibm->type, |
2624 | dispatch_notify); | 2689 | dispatch_notify); |
2690 | ibm->notify_installed = 0; | ||
2691 | } | ||
2625 | 2692 | ||
2626 | if (ibm->proc_created) | 2693 | if (ibm->proc_created) { |
2627 | remove_proc_entry(ibm->name, proc_dir); | 2694 | remove_proc_entry(ibm->name, proc_dir); |
2628 | 2695 | ibm->proc_created = 0; | |
2629 | if (ibm->init_called && ibm->exit) | 2696 | } |
2630 | ibm->exit(); | ||
2631 | 2697 | ||
2632 | if (ibm->driver_registered) { | 2698 | if (ibm->driver_registered) { |
2633 | acpi_bus_unregister_driver(ibm->driver); | 2699 | acpi_bus_unregister_driver(ibm->driver); |
2634 | kfree(ibm->driver); | 2700 | kfree(ibm->driver); |
2701 | ibm->driver = NULL; | ||
2702 | ibm->driver_registered = 0; | ||
2703 | } | ||
2704 | |||
2705 | if (ibm->init_called && ibm->exit) { | ||
2706 | ibm->exit(); | ||
2707 | ibm->init_called = 0; | ||
2635 | } | 2708 | } |
2636 | } | 2709 | } |
2637 | 2710 | ||
@@ -2663,6 +2736,32 @@ static char* __init check_dmi_for_ec(void) | |||
2663 | return NULL; | 2736 | return NULL; |
2664 | } | 2737 | } |
2665 | 2738 | ||
2739 | static int __init probe_for_thinkpad(void) | ||
2740 | { | ||
2741 | int is_thinkpad; | ||
2742 | |||
2743 | if (acpi_disabled) | ||
2744 | return -ENODEV; | ||
2745 | |||
2746 | /* | ||
2747 | * Non-ancient models have better DMI tagging, but very old models | ||
2748 | * don't. | ||
2749 | */ | ||
2750 | is_thinkpad = dmi_name_in_vendors("ThinkPad"); | ||
2751 | |||
2752 | /* ec is required because many other handles are relative to it */ | ||
2753 | IBM_HANDLE_INIT(ec); | ||
2754 | if (!ec_handle) { | ||
2755 | if (is_thinkpad) | ||
2756 | printk(IBM_ERR | ||
2757 | "Not yet supported ThinkPad detected!\n"); | ||
2758 | return -ENODEV; | ||
2759 | } | ||
2760 | |||
2761 | return 0; | ||
2762 | } | ||
2763 | |||
2764 | |||
2666 | /* Module init, exit, parameters */ | 2765 | /* Module init, exit, parameters */ |
2667 | 2766 | ||
2668 | static int __init set_ibm_param(const char *val, struct kernel_param *kp) | 2767 | static int __init set_ibm_param(const char *val, struct kernel_param *kp) |
@@ -2712,45 +2811,13 @@ static int __init thinkpad_acpi_module_init(void) | |||
2712 | { | 2811 | { |
2713 | int ret, i; | 2812 | int ret, i; |
2714 | 2813 | ||
2715 | if (acpi_disabled) | 2814 | ret = probe_for_thinkpad(); |
2716 | return -ENODEV; | 2815 | if (ret) |
2816 | return ret; | ||
2717 | 2817 | ||
2718 | /* ec is required because many other handles are relative to it */ | ||
2719 | IBM_HANDLE_INIT(ec); | ||
2720 | if (!ec_handle) { | ||
2721 | printk(IBM_ERR "ec object not found\n"); | ||
2722 | return -ENODEV; | ||
2723 | } | ||
2724 | |||
2725 | /* Models with newer firmware report the EC in DMI */ | ||
2726 | ibm_thinkpad_ec_found = check_dmi_for_ec(); | 2818 | ibm_thinkpad_ec_found = check_dmi_for_ec(); |
2727 | |||
2728 | /* these handles are not required */ | ||
2729 | IBM_HANDLE_INIT(vid); | ||
2730 | IBM_HANDLE_INIT(vid2); | ||
2731 | IBM_HANDLE_INIT(ledb); | ||
2732 | IBM_HANDLE_INIT(led); | ||
2733 | IBM_HANDLE_INIT(hkey); | ||
2734 | IBM_HANDLE_INIT(lght); | ||
2735 | IBM_HANDLE_INIT(cmos); | ||
2736 | #ifdef CONFIG_THINKPAD_ACPI_DOCK | ||
2737 | IBM_HANDLE_INIT(dock); | ||
2738 | #endif | ||
2739 | IBM_HANDLE_INIT(pci); | ||
2740 | #ifdef CONFIG_THINKPAD_ACPI_BAY | ||
2741 | IBM_HANDLE_INIT(bay); | ||
2742 | if (bay_handle) | ||
2743 | IBM_HANDLE_INIT(bay_ej); | ||
2744 | IBM_HANDLE_INIT(bay2); | ||
2745 | if (bay2_handle) | ||
2746 | IBM_HANDLE_INIT(bay2_ej); | ||
2747 | #endif /* CONFIG_THINKPAD_ACPI_BAY */ | ||
2748 | IBM_HANDLE_INIT(beep); | ||
2749 | IBM_HANDLE_INIT(ecrd); | 2819 | IBM_HANDLE_INIT(ecrd); |
2750 | IBM_HANDLE_INIT(ecwr); | 2820 | IBM_HANDLE_INIT(ecwr); |
2751 | IBM_HANDLE_INIT(fans); | ||
2752 | IBM_HANDLE_INIT(gfan); | ||
2753 | IBM_HANDLE_INIT(sfan); | ||
2754 | 2821 | ||
2755 | proc_dir = proc_mkdir(IBM_DIR, acpi_root_dir); | 2822 | proc_dir = proc_mkdir(IBM_DIR, acpi_root_dir); |
2756 | if (!proc_dir) { | 2823 | if (!proc_dir) { |
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h index b2348d7a07c4..06d4c3839afd 100644 --- a/drivers/misc/thinkpad_acpi.h +++ b/drivers/misc/thinkpad_acpi.h | |||
@@ -104,7 +104,7 @@ static acpi_handle ecrd_handle, ecwr_handle; /* 570 EC access */ | |||
104 | static acpi_handle cmos_handle, hkey_handle; /* basic thinkpad handles */ | 104 | static acpi_handle cmos_handle, hkey_handle; /* basic thinkpad handles */ |
105 | 105 | ||
106 | static void ibm_handle_init(char *name, | 106 | static void ibm_handle_init(char *name, |
107 | acpi_handle * handle, acpi_handle parent, | 107 | acpi_handle *handle, acpi_handle parent, |
108 | char **paths, int num_paths, char **path); | 108 | char **paths, int num_paths, char **path); |
109 | #define IBM_HANDLE_INIT(object) \ | 109 | #define IBM_HANDLE_INIT(object) \ |
110 | ibm_handle_init(#object, &object##_handle, *object##_parent, \ | 110 | ibm_handle_init(#object, &object##_handle, *object##_parent, \ |
@@ -242,8 +242,8 @@ static int cmos_write(char *buf); | |||
242 | * Dock subdriver | 242 | * Dock subdriver |
243 | */ | 243 | */ |
244 | 244 | ||
245 | static acpi_handle pci_handle; | ||
246 | #ifdef CONFIG_THINKPAD_ACPI_DOCK | 245 | #ifdef CONFIG_THINKPAD_ACPI_DOCK |
246 | static acpi_handle pci_handle; | ||
247 | static acpi_handle dock_handle; | 247 | static acpi_handle dock_handle; |
248 | 248 | ||
249 | static void dock_notify(struct ibm_struct *ibm, u32 event); | 249 | static void dock_notify(struct ibm_struct *ibm, u32 event); |