diff options
-rw-r--r-- | drivers/misc/thinkpad_acpi.c | 402 | ||||
-rw-r--r-- | drivers/misc/thinkpad_acpi.h | 51 |
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 | ||
473 | static int thinkpad_acpi_driver_init(void) | 473 | static 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 | ||
495 | static 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; | |||
501 | static int hotkey_orig_status; | 506 | static int hotkey_orig_status; |
502 | static int hotkey_orig_mask; | 507 | static int hotkey_orig_mask; |
503 | 508 | ||
504 | static int hotkey_init(void) | 509 | static 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 | ||
648 | static 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 | ||
647 | static int bluetooth_supported; | 663 | static int bluetooth_supported; |
648 | 664 | ||
649 | static int bluetooth_init(void) | 665 | static 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 | ||
735 | static 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 | ||
723 | static int wan_supported; | 745 | static int wan_supported; |
724 | 746 | ||
725 | static int wan_init(void) | 747 | static 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 | ||
814 | static 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 | ||
806 | IBM_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID"); /* G41 */ | 835 | IBM_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID"); /* G41 */ |
807 | 836 | ||
808 | static int video_init(void) | 837 | static 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 | ||
1043 | static 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; | |||
1021 | IBM_HANDLE(lght, root, "\\LGHT"); /* A21e, A2xm/p, T20-22, X20-21 */ | 1057 | IBM_HANDLE(lght, root, "\\LGHT"); /* A21e, A2xm/p, T20-22, X20-21 */ |
1022 | IBM_HANDLE(ledb, ec, "LEDB"); /* G4x */ | 1058 | IBM_HANDLE(ledb, ec, "LEDB"); /* G4x */ |
1023 | 1059 | ||
1024 | static int light_init(void) | 1060 | static 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 | ||
1132 | static 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 | ||
1113 | static int dock_init(void) | 1155 | static 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 | ||
1229 | static 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 | ||
1214 | static int bay_init(void) | 1274 | static 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 | |||
1362 | static 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 | ||
1307 | static int cmos_init(void) | 1377 | static 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 | ||
1435 | static 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 | ||
1377 | static int led_init(void) | 1452 | static 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 | ||
1565 | static 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 | ||
1494 | IBM_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */ | 1575 | IBM_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */ |
1495 | 1576 | ||
1496 | static int beep_init(void) | 1577 | static 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 | ||
1624 | static 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 | ||
1547 | static enum thermal_access_mode thermal_read_mode; | 1634 | static enum thermal_access_mode thermal_read_mode; |
1548 | 1635 | ||
1549 | static int thermal_init(void) | 1636 | static 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 | ||
1782 | static 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 | ||
1850 | static 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 | ||
1769 | static int brightness_init(void) | 1868 | static 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 | ||
1985 | static 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 | ||
2076 | static 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 | ||
2095 | static int fan_init(void) | 2206 | static 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 | ||
2682 | static 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) | |||
2580 | static struct proc_dir_entry *proc_dir = NULL; | 2699 | static struct proc_dir_entry *proc_dir = NULL; |
2581 | 2700 | ||
2582 | /* Subdriver registry */ | 2701 | /* Subdriver registry */ |
2583 | static struct ibm_struct ibms[] = { | 2702 | static 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 |
2711 | static const char * str_supported(int is_supported) | 2710 | static 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 | ||
2719 | static int __init ibm_init(struct ibm_struct *ibm) | 2718 | static 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 | ||
2780 | err_out: | 2787 | err_out: |
@@ -2789,6 +2796,9 @@ err_out: | |||
2789 | static void ibm_exit(struct ibm_struct *ibm) | 2796 | static 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 | ||
2890 | static 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 | |||
2878 | static int __init set_ibm_param(const char *val, struct kernel_param *kp) | 2962 | static 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 | ||
2954 | static void thinkpad_acpi_module_exit(void) | 3043 | static 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 */ |
118 | static struct proc_dir_entry *proc_dir; | 119 | static struct proc_dir_entry *proc_dir; |
119 | static int thinkpad_acpi_driver_init(void); | ||
120 | static int thinkpad_acpi_driver_read(char *p); | ||
121 | 120 | ||
122 | /* procfs helpers */ | 121 | /* procfs helpers */ |
123 | static int dispatch_read(char *page, char **start, off_t off, int count, | 122 | static 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 | ||
143 | struct ibm_struct { | 142 | struct 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 | ||
168 | static struct ibm_struct ibms[]; | 167 | struct ibm_init_struct { |
168 | char param[32]; | ||
169 | |||
170 | int (*init) (struct ibm_init_struct *); | ||
171 | struct ibm_struct *data; | ||
172 | }; | ||
173 | |||
174 | static struct list_head tpacpi_all_drivers; | ||
175 | |||
176 | static struct ibm_init_struct ibms_init[]; | ||
169 | static int set_ibm_param(const char *val, struct kernel_param *kp); | 177 | static int set_ibm_param(const char *val, struct kernel_param *kp); |
170 | static int ibm_init(struct ibm_struct *ibm); | 178 | static int ibm_init(struct ibm_init_struct *iibm); |
171 | static void ibm_exit(struct ibm_struct *ibm); | 179 | static void ibm_exit(struct ibm_struct *ibm); |
172 | 180 | ||
173 | /* ACPI devices */ | 181 | |
174 | static void dispatch_notify(acpi_handle handle, u32 event, void *data); | 182 | /* |
175 | static int setup_notify(struct ibm_struct *ibm); | 183 | * procfs master subdriver |
176 | static int ibm_device_add(struct acpi_device *device); | 184 | */ |
177 | static int register_tpacpi_subdriver(struct ibm_struct *ibm); | 185 | static int thinkpad_acpi_driver_init(struct ibm_init_struct *iibm); |
186 | static 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; | |||
188 | static acpi_handle bay_handle, bay_ej_handle; | 197 | static acpi_handle bay_handle, bay_ej_handle; |
189 | static acpi_handle bay2_handle, bay2_ej_handle; | 198 | static acpi_handle bay2_handle, bay2_ej_handle; |
190 | 199 | ||
191 | static int bay_init(void); | 200 | static int bay_init(struct ibm_init_struct *iibm); |
192 | static void bay_notify(struct ibm_struct *ibm, u32 event); | 201 | static void bay_notify(struct ibm_struct *ibm, u32 event); |
193 | static int bay_read(char *p); | 202 | static int bay_read(char *p); |
194 | static int bay_write(char *buf); | 203 | static int bay_write(char *buf); |
@@ -211,7 +220,7 @@ static int beep_write(char *buf); | |||
211 | 220 | ||
212 | static int bluetooth_supported; | 221 | static int bluetooth_supported; |
213 | 222 | ||
214 | static int bluetooth_init(void); | 223 | static int bluetooth_init(struct ibm_init_struct *iibm); |
215 | static int bluetooth_status(void); | 224 | static int bluetooth_status(void); |
216 | static int bluetooth_read(char *p); | 225 | static int bluetooth_read(char *p); |
217 | static int bluetooth_write(char *buf); | 226 | static int bluetooth_write(char *buf); |
@@ -224,7 +233,7 @@ static int bluetooth_write(char *buf); | |||
224 | static struct backlight_device *ibm_backlight_device; | 233 | static struct backlight_device *ibm_backlight_device; |
225 | static int brightness_offset = 0x31; | 234 | static int brightness_offset = 0x31; |
226 | 235 | ||
227 | static int brightness_init(void); | 236 | static int brightness_init(struct ibm_init_struct *iibm); |
228 | static void brightness_exit(void); | 237 | static void brightness_exit(void); |
229 | static int brightness_get(struct backlight_device *bd); | 238 | static int brightness_get(struct backlight_device *bd); |
230 | static int brightness_set(int value); | 239 | static int brightness_set(int value); |
@@ -306,7 +315,7 @@ static int fan_watchdog_maxinterval; | |||
306 | 315 | ||
307 | static acpi_handle fans_handle, gfan_handle, sfan_handle; | 316 | static acpi_handle fans_handle, gfan_handle, sfan_handle; |
308 | 317 | ||
309 | static int fan_init(void); | 318 | static int fan_init(struct ibm_init_struct *iibm); |
310 | static void fan_exit(void); | 319 | static void fan_exit(void); |
311 | static int fan_get_status(u8 *status); | 320 | static int fan_get_status(u8 *status); |
312 | static int fan_get_speed(unsigned int *speed); | 321 | static int fan_get_speed(unsigned int *speed); |
@@ -334,7 +343,7 @@ static int hotkey_mask_supported; | |||
334 | static int hotkey_orig_status; | 343 | static int hotkey_orig_status; |
335 | static int hotkey_orig_mask; | 344 | static int hotkey_orig_mask; |
336 | 345 | ||
337 | static int hotkey_init(void); | 346 | static int hotkey_init(struct ibm_init_struct *iibm); |
338 | static void hotkey_exit(void); | 347 | static void hotkey_exit(void); |
339 | static int hotkey_get(int *status, int *mask); | 348 | static int hotkey_get(int *status, int *mask); |
340 | static int hotkey_set(int status, int mask); | 349 | static int hotkey_set(int status, int mask); |
@@ -363,7 +372,7 @@ enum { /* For TPACPI_LED_OLD */ | |||
363 | static enum led_access_mode led_supported; | 372 | static enum led_access_mode led_supported; |
364 | static acpi_handle led_handle; | 373 | static acpi_handle led_handle; |
365 | 374 | ||
366 | static int led_init(void); | 375 | static int led_init(struct ibm_init_struct *iibm); |
367 | static int led_read(char *p); | 376 | static int led_read(char *p); |
368 | static int led_write(char *buf); | 377 | static int led_write(char *buf); |
369 | 378 | ||
@@ -375,7 +384,7 @@ static int light_supported; | |||
375 | static int light_status_supported; | 384 | static int light_status_supported; |
376 | static acpi_handle lght_handle, ledb_handle; | 385 | static acpi_handle lght_handle, ledb_handle; |
377 | 386 | ||
378 | static int light_init(void); | 387 | static int light_init(struct ibm_init_struct *iibm); |
379 | static int light_read(char *p); | 388 | static int light_read(char *p); |
380 | static int light_write(char *buf); | 389 | static 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 | ||
400 | static int thermal_init(void); | 409 | static int thermal_init(struct ibm_init_struct *iibm); |
401 | static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s); | 410 | static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s); |
402 | static int thermal_read(char *p); | 411 | static int thermal_read(char *p); |
403 | 412 | ||
@@ -417,7 +426,7 @@ static enum video_access_mode video_supported; | |||
417 | static int video_orig_autosw; | 426 | static int video_orig_autosw; |
418 | static acpi_handle vid_handle, vid2_handle; | 427 | static acpi_handle vid_handle, vid2_handle; |
419 | 428 | ||
420 | static int video_init(void); | 429 | static int video_init(struct ibm_init_struct *iibm); |
421 | static void video_exit(void); | 430 | static void video_exit(void); |
422 | static int video_status(void); | 431 | static int video_status(void); |
423 | static int video_autosw(void); | 432 | static int video_autosw(void); |
@@ -444,7 +453,7 @@ static int volume_write(char *buf); | |||
444 | 453 | ||
445 | static int wan_supported; | 454 | static int wan_supported; |
446 | 455 | ||
447 | static int wan_init(void); | 456 | static int wan_init(struct ibm_init_struct *iibm); |
448 | static int wan_status(void); | 457 | static int wan_status(void); |
449 | static int wan_read(char *p); | 458 | static int wan_read(char *p); |
450 | static int wan_write(char *buf); | 459 | static int wan_write(char *buf); |