aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/misc/thinkpad_acpi.c402
-rw-r--r--drivers/misc/thinkpad_acpi.h51
2 files changed, 278 insertions, 175 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index e8fc8da35669..56112684967b 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -470,7 +470,7 @@ static char *next_cmd(char **cmds)
470 * thinkpad-acpi init subdriver 470 * thinkpad-acpi init subdriver
471 */ 471 */
472 472
473static int thinkpad_acpi_driver_init(void) 473static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm)
474{ 474{
475 printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION); 475 printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION);
476 printk(IBM_INFO "%s\n", IBM_URL); 476 printk(IBM_INFO "%s\n", IBM_URL);
@@ -492,6 +492,11 @@ static int thinkpad_acpi_driver_read(char *p)
492 return len; 492 return len;
493} 493}
494 494
495static struct ibm_struct thinkpad_acpi_driver_data = {
496 .name = "driver",
497 .read = thinkpad_acpi_driver_read,
498};
499
495/************************************************************************* 500/*************************************************************************
496 * Hotkey subdriver 501 * Hotkey subdriver
497 */ 502 */
@@ -501,7 +506,7 @@ static int hotkey_mask_supported;
501static int hotkey_orig_status; 506static int hotkey_orig_status;
502static int hotkey_orig_mask; 507static int hotkey_orig_mask;
503 508
504static int hotkey_init(void) 509static int __init hotkey_init(struct ibm_init_struct *iibm)
505{ 510{
506 vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); 511 vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n");
507 512
@@ -640,13 +645,24 @@ static int hotkey_write(char *buf)
640 return 0; 645 return 0;
641} 646}
642 647
648static struct ibm_struct hotkey_driver_data = {
649 .name = "hotkey",
650 .hid = IBM_HKEY_HID,
651 .read = hotkey_read,
652 .write = hotkey_write,
653 .exit = hotkey_exit,
654 .notify = hotkey_notify,
655 .handle = &hkey_handle,
656 .type = ACPI_DEVICE_NOTIFY,
657};
658
643/************************************************************************* 659/*************************************************************************
644 * Bluetooth subdriver 660 * Bluetooth subdriver
645 */ 661 */
646 662
647static int bluetooth_supported; 663static int bluetooth_supported;
648 664
649static int bluetooth_init(void) 665static int __init bluetooth_init(struct ibm_init_struct *iibm)
650{ 666{
651 vdbg_printk(TPACPI_DBG_INIT, "initializing bluetooth subdriver\n"); 667 vdbg_printk(TPACPI_DBG_INIT, "initializing bluetooth subdriver\n");
652 668
@@ -716,13 +732,19 @@ static int bluetooth_write(char *buf)
716 return 0; 732 return 0;
717} 733}
718 734
735static struct ibm_struct bluetooth_driver_data = {
736 .name = "bluetooth",
737 .read = bluetooth_read,
738 .write = bluetooth_write,
739};
740
719/************************************************************************* 741/*************************************************************************
720 * Wan subdriver 742 * Wan subdriver
721 */ 743 */
722 744
723static int wan_supported; 745static int wan_supported;
724 746
725static int wan_init(void) 747static int __init wan_init(struct ibm_init_struct *iibm)
726{ 748{
727 vdbg_printk(TPACPI_DBG_INIT, "initializing wan subdriver\n"); 749 vdbg_printk(TPACPI_DBG_INIT, "initializing wan subdriver\n");
728 750
@@ -789,6 +811,13 @@ static int wan_write(char *buf)
789 return 0; 811 return 0;
790} 812}
791 813
814static struct ibm_struct wan_driver_data = {
815 .name = "wan",
816 .read = wan_read,
817 .write = wan_write,
818 .experimental = 1,
819};
820
792/************************************************************************* 821/*************************************************************************
793 * Video subdriver 822 * Video subdriver
794 */ 823 */
@@ -805,7 +834,7 @@ IBM_HANDLE(vid, root, "\\_SB.PCI.AGP.VGA", /* 570 */
805 834
806IBM_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID"); /* G41 */ 835IBM_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID"); /* G41 */
807 836
808static int video_init(void) 837static int __init video_init(struct ibm_init_struct *iibm)
809{ 838{
810 int ivga; 839 int ivga;
811 840
@@ -1011,6 +1040,13 @@ static int video_write(char *buf)
1011 return 0; 1040 return 0;
1012} 1041}
1013 1042
1043static struct ibm_struct video_driver_data = {
1044 .name = "video",
1045 .read = video_read,
1046 .write = video_write,
1047 .exit = video_exit,
1048};
1049
1014/************************************************************************* 1050/*************************************************************************
1015 * Light (thinklight) subdriver 1051 * Light (thinklight) subdriver
1016 */ 1052 */
@@ -1021,7 +1057,7 @@ static int light_status_supported;
1021IBM_HANDLE(lght, root, "\\LGHT"); /* A21e, A2xm/p, T20-22, X20-21 */ 1057IBM_HANDLE(lght, root, "\\LGHT"); /* A21e, A2xm/p, T20-22, X20-21 */
1022IBM_HANDLE(ledb, ec, "LEDB"); /* G4x */ 1058IBM_HANDLE(ledb, ec, "LEDB"); /* G4x */
1023 1059
1024static int light_init(void) 1060static int __init light_init(struct ibm_init_struct *iibm)
1025{ 1061{
1026 vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n"); 1062 vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n");
1027 1063
@@ -1093,6 +1129,12 @@ static int light_write(char *buf)
1093 return 0; 1129 return 0;
1094} 1130}
1095 1131
1132static struct ibm_struct light_driver_data = {
1133 .name = "light",
1134 .read = light_read,
1135 .write = light_write,
1136};
1137
1096/************************************************************************* 1138/*************************************************************************
1097 * Dock subdriver 1139 * Dock subdriver
1098 */ 1140 */
@@ -1110,7 +1152,7 @@ IBM_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */
1110 1152
1111#define dock_docked() (_sta(dock_handle) & 1) 1153#define dock_docked() (_sta(dock_handle) & 1)
1112 1154
1113static int dock_init(void) 1155static int __init dock_init(struct ibm_init_struct *iibm)
1114{ 1156{
1115 vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver\n"); 1157 vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver\n");
1116 1158
@@ -1184,6 +1226,24 @@ static int dock_write(char *buf)
1184 return 0; 1226 return 0;
1185} 1227}
1186 1228
1229static struct ibm_struct dock_driver_data[2] = {
1230 {
1231 .name = "dock",
1232 .read = dock_read,
1233 .write = dock_write,
1234 .notify = dock_notify,
1235 .handle = &dock_handle,
1236 .type = ACPI_SYSTEM_NOTIFY,
1237 },
1238 {
1239 .name = "dock",
1240 .hid = IBM_PCI_HID,
1241 .notify = dock_notify,
1242 .handle = &pci_handle,
1243 .type = ACPI_SYSTEM_NOTIFY,
1244 },
1245};
1246
1187#endif /* CONFIG_THINKPAD_ACPI_DOCK */ 1247#endif /* CONFIG_THINKPAD_ACPI_DOCK */
1188 1248
1189/************************************************************************* 1249/*************************************************************************
@@ -1211,7 +1271,7 @@ IBM_HANDLE(bay2_ej, bay2, "_EJ3", /* 600e/x, 770e, A3x */
1211 "_EJ0", /* 770x */ 1271 "_EJ0", /* 770x */
1212 ); /* all others */ 1272 ); /* all others */
1213 1273
1214static int bay_init(void) 1274static int __init bay_init(struct ibm_init_struct *iibm)
1215{ 1275{
1216 vdbg_printk(TPACPI_DBG_INIT, "initializing bay subdriver\n"); 1276 vdbg_printk(TPACPI_DBG_INIT, "initializing bay subdriver\n");
1217 1277
@@ -1298,13 +1358,23 @@ static int bay_write(char *buf)
1298 1358
1299 return 0; 1359 return 0;
1300} 1360}
1361
1362static struct ibm_struct bay_driver_data = {
1363 .name = "bay",
1364 .read = bay_read,
1365 .write = bay_write,
1366 .notify = bay_notify,
1367 .handle = &bay_handle,
1368 .type = ACPI_SYSTEM_NOTIFY,
1369};
1370
1301#endif /* CONFIG_THINKPAD_ACPI_BAY */ 1371#endif /* CONFIG_THINKPAD_ACPI_BAY */
1302 1372
1303/************************************************************************* 1373/*************************************************************************
1304 * CMOS subdriver 1374 * CMOS subdriver
1305 */ 1375 */
1306 1376
1307static int cmos_init(void) 1377static int __init cmos_init(struct ibm_init_struct *iibm)
1308{ 1378{
1309 vdbg_printk(TPACPI_DBG_INIT, 1379 vdbg_printk(TPACPI_DBG_INIT,
1310 "initializing cmos commands subdriver\n"); 1380 "initializing cmos commands subdriver\n");
@@ -1362,6 +1432,11 @@ static int cmos_write(char *buf)
1362 return 0; 1432 return 0;
1363} 1433}
1364 1434
1435static struct ibm_struct cmos_driver_data = {
1436 .name = "cmos",
1437 .read = cmos_read,
1438 .write = cmos_write,
1439};
1365 1440
1366/************************************************************************* 1441/*************************************************************************
1367 * LED subdriver 1442 * LED subdriver
@@ -1374,7 +1449,7 @@ IBM_HANDLE(led, ec, "SLED", /* 570 */
1374 "LED", /* all others */ 1449 "LED", /* all others */
1375 ); /* R30, R31 */ 1450 ); /* R30, R31 */
1376 1451
1377static int led_init(void) 1452static int __init led_init(struct ibm_init_struct *iibm)
1378{ 1453{
1379 vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n"); 1454 vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n");
1380 1455
@@ -1487,13 +1562,19 @@ static int led_write(char *buf)
1487 return 0; 1562 return 0;
1488} 1563}
1489 1564
1565static struct ibm_struct led_driver_data = {
1566 .name = "led",
1567 .read = led_read,
1568 .write = led_write,
1569};
1570
1490/************************************************************************* 1571/*************************************************************************
1491 * Beep subdriver 1572 * Beep subdriver
1492 */ 1573 */
1493 1574
1494IBM_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */ 1575IBM_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */
1495 1576
1496static int beep_init(void) 1577static int __init beep_init(struct ibm_init_struct *iibm)
1497{ 1578{
1498 vdbg_printk(TPACPI_DBG_INIT, "initializing beep subdriver\n"); 1579 vdbg_printk(TPACPI_DBG_INIT, "initializing beep subdriver\n");
1499 1580
@@ -1540,13 +1621,19 @@ static int beep_write(char *buf)
1540 return 0; 1621 return 0;
1541} 1622}
1542 1623
1624static struct ibm_struct beep_driver_data = {
1625 .name = "beep",
1626 .read = beep_read,
1627 .write = beep_write,
1628};
1629
1543/************************************************************************* 1630/*************************************************************************
1544 * Thermal subdriver 1631 * Thermal subdriver
1545 */ 1632 */
1546 1633
1547static enum thermal_access_mode thermal_read_mode; 1634static enum thermal_access_mode thermal_read_mode;
1548 1635
1549static int thermal_init(void) 1636static int __init thermal_init(struct ibm_init_struct *iibm)
1550{ 1637{
1551 u8 t, ta1, ta2; 1638 u8 t, ta1, ta2;
1552 int i; 1639 int i;
@@ -1692,6 +1779,11 @@ static int thermal_read(char *p)
1692 return len; 1779 return len;
1693} 1780}
1694 1781
1782static struct ibm_struct thermal_driver_data = {
1783 .name = "thermal",
1784 .read = thermal_read,
1785};
1786
1695/************************************************************************* 1787/*************************************************************************
1696 * EC Dump subdriver 1788 * EC Dump subdriver
1697 */ 1789 */
@@ -1755,6 +1847,13 @@ static int ecdump_write(char *buf)
1755 return 0; 1847 return 0;
1756} 1848}
1757 1849
1850static struct ibm_struct ecdump_driver_data = {
1851 .name = "ecdump",
1852 .read = ecdump_read,
1853 .write = ecdump_write,
1854 .experimental = 1,
1855};
1856
1758/************************************************************************* 1857/*************************************************************************
1759 * Backlight/brightness subdriver 1858 * Backlight/brightness subdriver
1760 */ 1859 */
@@ -1766,7 +1865,7 @@ static struct backlight_ops ibm_backlight_data = {
1766 .update_status = brightness_update_status, 1865 .update_status = brightness_update_status,
1767}; 1866};
1768 1867
1769static int brightness_init(void) 1868static int __init brightness_init(struct ibm_init_struct *iibm)
1770{ 1869{
1771 int b; 1870 int b;
1772 1871
@@ -1883,6 +1982,13 @@ static int brightness_write(char *buf)
1883 return 0; 1982 return 0;
1884} 1983}
1885 1984
1985static struct ibm_struct brightness_driver_data = {
1986 .name = "brightness",
1987 .read = brightness_read,
1988 .write = brightness_write,
1989 .exit = brightness_exit,
1990};
1991
1886/************************************************************************* 1992/*************************************************************************
1887 * Volume subdriver 1993 * Volume subdriver
1888 */ 1994 */
@@ -1967,6 +2073,11 @@ static int volume_write(char *buf)
1967 return 0; 2073 return 0;
1968} 2074}
1969 2075
2076static struct ibm_struct volume_driver_data = {
2077 .name = "volume",
2078 .read = volume_read,
2079 .write = volume_write,
2080};
1970 2081
1971/************************************************************************* 2082/*************************************************************************
1972 * Fan subdriver 2083 * Fan subdriver
@@ -2092,7 +2203,7 @@ IBM_HANDLE(sfan, ec, "SFAN", /* 570 */
2092 "JFNS", /* 770x-JL */ 2203 "JFNS", /* 770x-JL */
2093 ); /* all others */ 2204 ); /* all others */
2094 2205
2095static int fan_init(void) 2206static int __init fan_init(struct ibm_init_struct *iibm)
2096{ 2207{
2097 vdbg_printk(TPACPI_DBG_INIT, "initializing fan subdriver\n"); 2208 vdbg_printk(TPACPI_DBG_INIT, "initializing fan subdriver\n");
2098 2209
@@ -2568,6 +2679,14 @@ static int fan_write(char *buf)
2568 return rc; 2679 return rc;
2569} 2680}
2570 2681
2682static struct ibm_struct fan_driver_data = {
2683 .name = "fan",
2684 .read = fan_read,
2685 .write = fan_write,
2686 .exit = fan_exit,
2687 .experimental = 1,
2688};
2689
2571/**************************************************************************** 2690/****************************************************************************
2572 **************************************************************************** 2691 ****************************************************************************
2573 * 2692 *
@@ -2580,159 +2699,45 @@ static int fan_write(char *buf)
2580static struct proc_dir_entry *proc_dir = NULL; 2699static struct proc_dir_entry *proc_dir = NULL;
2581 2700
2582/* Subdriver registry */ 2701/* Subdriver registry */
2583static struct ibm_struct ibms[] = { 2702static LIST_HEAD(tpacpi_all_drivers);
2584 { 2703
2585 .name = "driver",
2586 .init = thinkpad_acpi_driver_init,
2587 .read = thinkpad_acpi_driver_read,
2588 },
2589 {
2590 .name = "hotkey",
2591 .hid = IBM_HKEY_HID,
2592 .init = hotkey_init,
2593 .read = hotkey_read,
2594 .write = hotkey_write,
2595 .exit = hotkey_exit,
2596 .notify = hotkey_notify,
2597 .handle = &hkey_handle,
2598 .type = ACPI_DEVICE_NOTIFY,
2599 },
2600 {
2601 .name = "bluetooth",
2602 .init = bluetooth_init,
2603 .read = bluetooth_read,
2604 .write = bluetooth_write,
2605 },
2606 {
2607 .name = "wan",
2608 .init = wan_init,
2609 .read = wan_read,
2610 .write = wan_write,
2611 .experimental = 1,
2612 },
2613 {
2614 .name = "video",
2615 .init = video_init,
2616 .read = video_read,
2617 .write = video_write,
2618 .exit = video_exit,
2619 },
2620 {
2621 .name = "light",
2622 .init = light_init,
2623 .read = light_read,
2624 .write = light_write,
2625 },
2626#ifdef CONFIG_THINKPAD_ACPI_DOCK
2627 {
2628 .name = "dock",
2629 .init = dock_init,
2630 .read = dock_read,
2631 .write = dock_write,
2632 .notify = dock_notify,
2633 .handle = &dock_handle,
2634 .type = ACPI_SYSTEM_NOTIFY,
2635 },
2636 {
2637 .name = "dock",
2638 .hid = IBM_PCI_HID,
2639 .notify = dock_notify,
2640 .handle = &pci_handle,
2641 .type = ACPI_SYSTEM_NOTIFY,
2642 },
2643#endif
2644#ifdef CONFIG_THINKPAD_ACPI_BAY
2645 {
2646 .name = "bay",
2647 .init = bay_init,
2648 .read = bay_read,
2649 .write = bay_write,
2650 .notify = bay_notify,
2651 .handle = &bay_handle,
2652 .type = ACPI_SYSTEM_NOTIFY,
2653 },
2654#endif /* CONFIG_THINKPAD_ACPI_BAY */
2655 {
2656 .name = "cmos",
2657 .init = cmos_init,
2658 .read = cmos_read,
2659 .write = cmos_write,
2660 },
2661 {
2662 .name = "led",
2663 .init = led_init,
2664 .read = led_read,
2665 .write = led_write,
2666 },
2667 {
2668 .name = "beep",
2669 .init = beep_init,
2670 .read = beep_read,
2671 .write = beep_write,
2672 },
2673 {
2674 .name = "thermal",
2675 .init = thermal_init,
2676 .read = thermal_read,
2677 },
2678 {
2679 .name = "ecdump",
2680 .read = ecdump_read,
2681 .write = ecdump_write,
2682 .experimental = 1,
2683 },
2684 {
2685 .name = "brightness",
2686 .read = brightness_read,
2687 .write = brightness_write,
2688 .init = brightness_init,
2689 .exit = brightness_exit,
2690 },
2691 {
2692 .name = "volume",
2693 .read = volume_read,
2694 .write = volume_write,
2695 },
2696 {
2697 .name = "fan",
2698 .read = fan_read,
2699 .write = fan_write,
2700 .init = fan_init,
2701 .exit = fan_exit,
2702 .experimental = 1,
2703 },
2704};
2705 2704
2706/* 2705/*
2707 * Module and infrastructure proble, init and exit handling 2706 * Module and infrastructure proble, init and exit handling
2708 */ 2707 */
2709 2708
2710#ifdef CONFIG_THINKPAD_ACPI_DEBUG 2709#ifdef CONFIG_THINKPAD_ACPI_DEBUG
2711static const char * str_supported(int is_supported) 2710static const char * __init str_supported(int is_supported)
2712{ 2711{
2713 static const char * const text_unsupported = "not supported"; 2712 static char text_unsupported[] __initdata = "not supported";
2714 2713
2715 return (is_supported)? text_unsupported + 4 : text_unsupported; 2714 return (is_supported)? &text_unsupported[4] : &text_unsupported[0];
2716} 2715}
2717#endif /* CONFIG_THINKPAD_ACPI_DEBUG */ 2716#endif /* CONFIG_THINKPAD_ACPI_DEBUG */
2718 2717
2719static int __init ibm_init(struct ibm_struct *ibm) 2718static int __init ibm_init(struct ibm_init_struct *iibm)
2720{ 2719{
2721 int ret; 2720 int ret;
2721 struct ibm_struct *ibm = iibm->data;
2722 struct proc_dir_entry *entry; 2722 struct proc_dir_entry *entry;
2723 2723
2724 BUG_ON(ibm == NULL);
2725
2726 INIT_LIST_HEAD(&ibm->all_drivers);
2727
2724 if (ibm->experimental && !experimental) 2728 if (ibm->experimental && !experimental)
2725 return 0; 2729 return 0;
2726 2730
2727 dbg_printk(TPACPI_DBG_INIT, 2731 dbg_printk(TPACPI_DBG_INIT,
2728 "probing for %s\n", ibm->name); 2732 "probing for %s\n", ibm->name);
2729 2733
2730 if (ibm->init) { 2734 if (iibm->init) {
2731 ret = ibm->init(); 2735 ret = iibm->init(iibm);
2732 if (ret > 0) 2736 if (ret > 0)
2733 return 0; /* probe failed */ 2737 return 0; /* probe failed */
2734 if (ret) 2738 if (ret)
2735 return ret; 2739 return ret;
2740
2736 ibm->init_called = 1; 2741 ibm->init_called = 1;
2737 } 2742 }
2738 2743
@@ -2775,6 +2780,8 @@ static int __init ibm_init(struct ibm_struct *ibm)
2775 ibm->proc_created = 1; 2780 ibm->proc_created = 1;
2776 } 2781 }
2777 2782
2783 list_add_tail(&ibm->all_drivers, &tpacpi_all_drivers);
2784
2778 return 0; 2785 return 0;
2779 2786
2780err_out: 2787err_out:
@@ -2789,6 +2796,9 @@ err_out:
2789static void ibm_exit(struct ibm_struct *ibm) 2796static void ibm_exit(struct ibm_struct *ibm)
2790{ 2797{
2791 dbg_printk(TPACPI_DBG_EXIT, "removing %s\n", ibm->name); 2798 dbg_printk(TPACPI_DBG_EXIT, "removing %s\n", ibm->name);
2799
2800 list_del_init(&ibm->all_drivers);
2801
2792 if (ibm->notify_installed) { 2802 if (ibm->notify_installed) {
2793 dbg_printk(TPACPI_DBG_EXIT, 2803 dbg_printk(TPACPI_DBG_EXIT,
2794 "%s: acpi_remove_notify_handler\n", ibm->name); 2804 "%s: acpi_remove_notify_handler\n", ibm->name);
@@ -2817,6 +2827,8 @@ static void ibm_exit(struct ibm_struct *ibm)
2817 ibm->exit(); 2827 ibm->exit();
2818 ibm->init_called = 0; 2828 ibm->init_called = 0;
2819 } 2829 }
2830
2831 dbg_printk(TPACPI_DBG_INIT, "finished removing %s\n", ibm->name);
2820} 2832}
2821 2833
2822/* Probing */ 2834/* Probing */
@@ -2875,18 +2887,95 @@ static int __init probe_for_thinkpad(void)
2875 2887
2876/* Module init, exit, parameters */ 2888/* Module init, exit, parameters */
2877 2889
2890static struct ibm_init_struct ibms_init[] __initdata = {
2891 {
2892 .init = thinkpad_acpi_driver_init,
2893 .data = &thinkpad_acpi_driver_data,
2894 },
2895 {
2896 .init = hotkey_init,
2897 .data = &hotkey_driver_data,
2898 },
2899 {
2900 .init = bluetooth_init,
2901 .data = &bluetooth_driver_data,
2902 },
2903 {
2904 .init = wan_init,
2905 .data = &wan_driver_data,
2906 },
2907 {
2908 .init = video_init,
2909 .data = &video_driver_data,
2910 },
2911 {
2912 .init = light_init,
2913 .data = &light_driver_data,
2914 },
2915#ifdef CONFIG_THINKPAD_ACPI_DOCK
2916 {
2917 .init = dock_init,
2918 .data = &dock_driver_data[0],
2919 },
2920 {
2921 .data = &dock_driver_data[1],
2922 },
2923#endif
2924#ifdef CONFIG_THINKPAD_ACPI_BAY
2925 {
2926 .init = bay_init,
2927 .data = &bay_driver_data,
2928 },
2929#endif
2930 {
2931 .init = cmos_init,
2932 .data = &cmos_driver_data,
2933 },
2934 {
2935 .init = led_init,
2936 .data = &led_driver_data,
2937 },
2938 {
2939 .init = beep_init,
2940 .data = &beep_driver_data,
2941 },
2942 {
2943 .init = thermal_init,
2944 .data = &thermal_driver_data,
2945 },
2946 {
2947 .data = &ecdump_driver_data,
2948 },
2949 {
2950 .init = brightness_init,
2951 .data = &brightness_driver_data,
2952 },
2953 {
2954 .data = &volume_driver_data,
2955 },
2956 {
2957 .init = fan_init,
2958 .data = &fan_driver_data,
2959 },
2960};
2961
2878static int __init set_ibm_param(const char *val, struct kernel_param *kp) 2962static int __init set_ibm_param(const char *val, struct kernel_param *kp)
2879{ 2963{
2880 unsigned int i; 2964 unsigned int i;
2965 struct ibm_struct *ibm;
2881 2966
2882 for (i = 0; i < ARRAY_SIZE(ibms); i++) 2967 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
2883 if (strcmp(ibms[i].name, kp->name) == 0 && ibms[i].write) { 2968 ibm = ibms_init[i].data;
2884 if (strlen(val) > sizeof(ibms[i].param) - 2) 2969 BUG_ON(ibm == NULL);
2970
2971 if (strcmp(ibm->name, kp->name) == 0 && ibm->write) {
2972 if (strlen(val) > sizeof(ibms_init[i].param) - 2)
2885 return -ENOSPC; 2973 return -ENOSPC;
2886 strcpy(ibms[i].param, val); 2974 strcpy(ibms_init[i].param, val);
2887 strcat(ibms[i].param, ","); 2975 strcat(ibms_init[i].param, ",");
2888 return 0; 2976 return 0;
2889 } 2977 }
2978 }
2890 2979
2891 return -EINVAL; 2980 return -EINVAL;
2892} 2981}
@@ -2938,10 +3027,10 @@ static int __init thinkpad_acpi_module_init(void)
2938 } 3027 }
2939 proc_dir->owner = THIS_MODULE; 3028 proc_dir->owner = THIS_MODULE;
2940 3029
2941 for (i = 0; i < ARRAY_SIZE(ibms); i++) { 3030 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
2942 ret = ibm_init(&ibms[i]); 3031 ret = ibm_init(&ibms_init[i]);
2943 if (ret >= 0 && *ibms[i].param) 3032 if (ret >= 0 && *ibms_init[i].param)
2944 ret = ibms[i].write(ibms[i].param); 3033 ret = ibms_init[i].data->write(ibms_init[i].param);
2945 if (ret < 0) { 3034 if (ret < 0) {
2946 thinkpad_acpi_module_exit(); 3035 thinkpad_acpi_module_exit();
2947 return ret; 3036 return ret;
@@ -2953,10 +3042,15 @@ static int __init thinkpad_acpi_module_init(void)
2953 3042
2954static void thinkpad_acpi_module_exit(void) 3043static void thinkpad_acpi_module_exit(void)
2955{ 3044{
2956 int i; 3045 struct ibm_struct *ibm, *itmp;
3046
3047 list_for_each_entry_safe_reverse(ibm, itmp,
3048 &tpacpi_all_drivers,
3049 all_drivers) {
3050 ibm_exit(ibm);
3051 }
2957 3052
2958 for (i = ARRAY_SIZE(ibms) - 1; i >= 0; i--) 3053 dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n");
2959 ibm_exit(&ibms[i]);
2960 3054
2961 if (proc_dir) 3055 if (proc_dir)
2962 remove_proc_entry(IBM_DIR, acpi_root_dir); 3056 remove_proc_entry(IBM_DIR, acpi_root_dir);
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h
index beb1447a7f3f..97467b71b727 100644
--- a/drivers/misc/thinkpad_acpi.h
+++ b/drivers/misc/thinkpad_acpi.h
@@ -29,6 +29,7 @@
29#include <linux/init.h> 29#include <linux/init.h>
30#include <linux/types.h> 30#include <linux/types.h>
31#include <linux/string.h> 31#include <linux/string.h>
32#include <linux/list.h>
32 33
33#include <linux/proc_fs.h> 34#include <linux/proc_fs.h>
34#include <linux/backlight.h> 35#include <linux/backlight.h>
@@ -116,8 +117,6 @@ static void ibm_handle_init(char *name,
116 117
117/* procfs support */ 118/* procfs support */
118static struct proc_dir_entry *proc_dir; 119static struct proc_dir_entry *proc_dir;
119static int thinkpad_acpi_driver_init(void);
120static int thinkpad_acpi_driver_read(char *p);
121 120
122/* procfs helpers */ 121/* procfs helpers */
123static int dispatch_read(char *page, char **start, off_t off, int count, 122static int dispatch_read(char *page, char **start, off_t off, int count,
@@ -142,12 +141,10 @@ static void thinkpad_acpi_module_exit(void);
142 141
143struct ibm_struct { 142struct ibm_struct {
144 char *name; 143 char *name;
145 char param[32];
146 144
147 char *hid; 145 char *hid;
148 struct acpi_driver *driver; 146 struct acpi_driver *driver;
149 147
150 int (*init) (void);
151 int (*read) (char *); 148 int (*read) (char *);
152 int (*write) (char *); 149 int (*write) (char *);
153 void (*exit) (void); 150 void (*exit) (void);
@@ -157,6 +154,8 @@ struct ibm_struct {
157 int type; 154 int type;
158 struct acpi_device *device; 155 struct acpi_device *device;
159 156
157 struct list_head all_drivers;
158
160 int driver_registered; 159 int driver_registered;
161 int proc_created; 160 int proc_created;
162 int init_called; 161 int init_called;
@@ -165,16 +164,26 @@ struct ibm_struct {
165 int experimental; 164 int experimental;
166}; 165};
167 166
168static struct ibm_struct ibms[]; 167struct ibm_init_struct {
168 char param[32];
169
170 int (*init) (struct ibm_init_struct *);
171 struct ibm_struct *data;
172};
173
174static struct list_head tpacpi_all_drivers;
175
176static struct ibm_init_struct ibms_init[];
169static int set_ibm_param(const char *val, struct kernel_param *kp); 177static int set_ibm_param(const char *val, struct kernel_param *kp);
170static int ibm_init(struct ibm_struct *ibm); 178static int ibm_init(struct ibm_init_struct *iibm);
171static void ibm_exit(struct ibm_struct *ibm); 179static void ibm_exit(struct ibm_struct *ibm);
172 180
173/* ACPI devices */ 181
174static void dispatch_notify(acpi_handle handle, u32 event, void *data); 182/*
175static int setup_notify(struct ibm_struct *ibm); 183 * procfs master subdriver
176static int ibm_device_add(struct acpi_device *device); 184 */
177static int register_tpacpi_subdriver(struct ibm_struct *ibm); 185static int thinkpad_acpi_driver_init(struct ibm_init_struct *iibm);
186static int thinkpad_acpi_driver_read(char *p);
178 187
179 188
180/* 189/*
@@ -188,7 +197,7 @@ static int bay_status2_supported, bay_eject2_supported;
188static acpi_handle bay_handle, bay_ej_handle; 197static acpi_handle bay_handle, bay_ej_handle;
189static acpi_handle bay2_handle, bay2_ej_handle; 198static acpi_handle bay2_handle, bay2_ej_handle;
190 199
191static int bay_init(void); 200static int bay_init(struct ibm_init_struct *iibm);
192static void bay_notify(struct ibm_struct *ibm, u32 event); 201static void bay_notify(struct ibm_struct *ibm, u32 event);
193static int bay_read(char *p); 202static int bay_read(char *p);
194static int bay_write(char *buf); 203static int bay_write(char *buf);
@@ -211,7 +220,7 @@ static int beep_write(char *buf);
211 220
212static int bluetooth_supported; 221static int bluetooth_supported;
213 222
214static int bluetooth_init(void); 223static int bluetooth_init(struct ibm_init_struct *iibm);
215static int bluetooth_status(void); 224static int bluetooth_status(void);
216static int bluetooth_read(char *p); 225static int bluetooth_read(char *p);
217static int bluetooth_write(char *buf); 226static int bluetooth_write(char *buf);
@@ -224,7 +233,7 @@ static int bluetooth_write(char *buf);
224static struct backlight_device *ibm_backlight_device; 233static struct backlight_device *ibm_backlight_device;
225static int brightness_offset = 0x31; 234static int brightness_offset = 0x31;
226 235
227static int brightness_init(void); 236static int brightness_init(struct ibm_init_struct *iibm);
228static void brightness_exit(void); 237static void brightness_exit(void);
229static int brightness_get(struct backlight_device *bd); 238static int brightness_get(struct backlight_device *bd);
230static int brightness_set(int value); 239static int brightness_set(int value);
@@ -306,7 +315,7 @@ static int fan_watchdog_maxinterval;
306 315
307static acpi_handle fans_handle, gfan_handle, sfan_handle; 316static acpi_handle fans_handle, gfan_handle, sfan_handle;
308 317
309static int fan_init(void); 318static int fan_init(struct ibm_init_struct *iibm);
310static void fan_exit(void); 319static void fan_exit(void);
311static int fan_get_status(u8 *status); 320static int fan_get_status(u8 *status);
312static int fan_get_speed(unsigned int *speed); 321static int fan_get_speed(unsigned int *speed);
@@ -334,7 +343,7 @@ static int hotkey_mask_supported;
334static int hotkey_orig_status; 343static int hotkey_orig_status;
335static int hotkey_orig_mask; 344static int hotkey_orig_mask;
336 345
337static int hotkey_init(void); 346static int hotkey_init(struct ibm_init_struct *iibm);
338static void hotkey_exit(void); 347static void hotkey_exit(void);
339static int hotkey_get(int *status, int *mask); 348static int hotkey_get(int *status, int *mask);
340static int hotkey_set(int status, int mask); 349static int hotkey_set(int status, int mask);
@@ -363,7 +372,7 @@ enum { /* For TPACPI_LED_OLD */
363static enum led_access_mode led_supported; 372static enum led_access_mode led_supported;
364static acpi_handle led_handle; 373static acpi_handle led_handle;
365 374
366static int led_init(void); 375static int led_init(struct ibm_init_struct *iibm);
367static int led_read(char *p); 376static int led_read(char *p);
368static int led_write(char *buf); 377static int led_write(char *buf);
369 378
@@ -375,7 +384,7 @@ static int light_supported;
375static int light_status_supported; 384static int light_status_supported;
376static acpi_handle lght_handle, ledb_handle; 385static acpi_handle lght_handle, ledb_handle;
377 386
378static int light_init(void); 387static int light_init(struct ibm_init_struct *iibm);
379static int light_read(char *p); 388static int light_read(char *p);
380static int light_write(char *buf); 389static int light_write(char *buf);
381 390
@@ -397,7 +406,7 @@ struct ibm_thermal_sensors_struct {
397 s32 temp[TPACPI_MAX_THERMAL_SENSORS]; 406 s32 temp[TPACPI_MAX_THERMAL_SENSORS];
398}; 407};
399 408
400static int thermal_init(void); 409static int thermal_init(struct ibm_init_struct *iibm);
401static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s); 410static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s);
402static int thermal_read(char *p); 411static int thermal_read(char *p);
403 412
@@ -417,7 +426,7 @@ static enum video_access_mode video_supported;
417static int video_orig_autosw; 426static int video_orig_autosw;
418static acpi_handle vid_handle, vid2_handle; 427static acpi_handle vid_handle, vid2_handle;
419 428
420static int video_init(void); 429static int video_init(struct ibm_init_struct *iibm);
421static void video_exit(void); 430static void video_exit(void);
422static int video_status(void); 431static int video_status(void);
423static int video_autosw(void); 432static int video_autosw(void);
@@ -444,7 +453,7 @@ static int volume_write(char *buf);
444 453
445static int wan_supported; 454static int wan_supported;
446 455
447static int wan_init(void); 456static int wan_init(struct ibm_init_struct *iibm);
448static int wan_status(void); 457static int wan_status(void);
449static int wan_read(char *p); 458static int wan_read(char *p);
450static int wan_write(char *buf); 459static int wan_write(char *buf);