diff options
45 files changed, 1926 insertions, 1057 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 92e1ab8178a8..040fee607282 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -229,14 +229,6 @@ and is between 256 and 4096 characters. It is defined in the file | |||
229 | to assume that this machine's pmtimer latches its value | 229 | to assume that this machine's pmtimer latches its value |
230 | and always returns good values. | 230 | and always returns good values. |
231 | 231 | ||
232 | acpi.power_nocheck= [HW,ACPI] | ||
233 | Format: 1/0 enable/disable the check of power state. | ||
234 | On some bogus BIOS the _PSC object/_STA object of | ||
235 | power resource can't return the correct device power | ||
236 | state. In such case it is unneccessary to check its | ||
237 | power state again in power transition. | ||
238 | 1 : disable the power state check | ||
239 | |||
240 | acpi_sci= [HW,ACPI] ACPI System Control Interrupt trigger mode | 232 | acpi_sci= [HW,ACPI] ACPI System Control Interrupt trigger mode |
241 | Format: { level | edge | high | low } | 233 | Format: { level | edge | high | low } |
242 | 234 | ||
diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index 78e354b42f67..f2296ecedb89 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt | |||
@@ -920,7 +920,7 @@ The available commands are: | |||
920 | echo '<LED number> off' >/proc/acpi/ibm/led | 920 | echo '<LED number> off' >/proc/acpi/ibm/led |
921 | echo '<LED number> blink' >/proc/acpi/ibm/led | 921 | echo '<LED number> blink' >/proc/acpi/ibm/led |
922 | 922 | ||
923 | The <LED number> range is 0 to 7. The set of LEDs that can be | 923 | The <LED number> range is 0 to 15. The set of LEDs that can be |
924 | controlled varies from model to model. Here is the common ThinkPad | 924 | controlled varies from model to model. Here is the common ThinkPad |
925 | mapping: | 925 | mapping: |
926 | 926 | ||
@@ -932,6 +932,11 @@ mapping: | |||
932 | 5 - UltraBase battery slot | 932 | 5 - UltraBase battery slot |
933 | 6 - (unknown) | 933 | 6 - (unknown) |
934 | 7 - standby | 934 | 7 - standby |
935 | 8 - dock status 1 | ||
936 | 9 - dock status 2 | ||
937 | 10, 11 - (unknown) | ||
938 | 12 - thinkvantage | ||
939 | 13, 14, 15 - (unknown) | ||
935 | 940 | ||
936 | All of the above can be turned on and off and can be made to blink. | 941 | All of the above can be turned on and off and can be made to blink. |
937 | 942 | ||
@@ -940,10 +945,12 @@ sysfs notes: | |||
940 | The ThinkPad LED sysfs interface is described in detail by the LED class | 945 | The ThinkPad LED sysfs interface is described in detail by the LED class |
941 | documentation, in Documentation/leds-class.txt. | 946 | documentation, in Documentation/leds-class.txt. |
942 | 947 | ||
943 | The leds are named (in LED ID order, from 0 to 7): | 948 | The LEDs are named (in LED ID order, from 0 to 12): |
944 | "tpacpi::power", "tpacpi:orange:batt", "tpacpi:green:batt", | 949 | "tpacpi::power", "tpacpi:orange:batt", "tpacpi:green:batt", |
945 | "tpacpi::dock_active", "tpacpi::bay_active", "tpacpi::dock_batt", | 950 | "tpacpi::dock_active", "tpacpi::bay_active", "tpacpi::dock_batt", |
946 | "tpacpi::unknown_led", "tpacpi::standby". | 951 | "tpacpi::unknown_led", "tpacpi::standby", "tpacpi::dock_status1", |
952 | "tpacpi::dock_status2", "tpacpi::unknown_led2", "tpacpi::unknown_led3", | ||
953 | "tpacpi::thinkvantage". | ||
947 | 954 | ||
948 | Due to limitations in the sysfs LED class, if the status of the LED | 955 | Due to limitations in the sysfs LED class, if the status of the LED |
949 | indicators cannot be read due to an error, thinkpad-acpi will report it as | 956 | indicators cannot be read due to an error, thinkpad-acpi will report it as |
@@ -958,6 +965,12 @@ ThinkPad indicator LED should blink in hardware accelerated mode, use the | |||
958 | "timer" trigger, and leave the delay_on and delay_off parameters set to | 965 | "timer" trigger, and leave the delay_on and delay_off parameters set to |
959 | zero (to request hardware acceleration autodetection). | 966 | zero (to request hardware acceleration autodetection). |
960 | 967 | ||
968 | LEDs that are known not to exist in a given ThinkPad model are not | ||
969 | made available through the sysfs interface. If you have a dock and you | ||
970 | notice there are LEDs listed for your ThinkPad that do not exist (and | ||
971 | are not in the dock), or if you notice that there are missing LEDs, | ||
972 | a report to ibm-acpi-devel@lists.sourceforge.net is appreciated. | ||
973 | |||
961 | 974 | ||
962 | ACPI sounds -- /proc/acpi/ibm/beep | 975 | ACPI sounds -- /proc/acpi/ibm/beep |
963 | ---------------------------------- | 976 | ---------------------------------- |
@@ -1156,17 +1169,19 @@ may not be distinct. Later Lenovo models that implement the ACPI | |||
1156 | display backlight brightness control methods have 16 levels, ranging | 1169 | display backlight brightness control methods have 16 levels, ranging |
1157 | from 0 to 15. | 1170 | from 0 to 15. |
1158 | 1171 | ||
1159 | There are two interfaces to the firmware for direct brightness control, | 1172 | For IBM ThinkPads, there are two interfaces to the firmware for direct |
1160 | EC and UCMS (or CMOS). To select which one should be used, use the | 1173 | brightness control, EC and UCMS (or CMOS). To select which one should be |
1161 | brightness_mode module parameter: brightness_mode=1 selects EC mode, | 1174 | used, use the brightness_mode module parameter: brightness_mode=1 selects |
1162 | brightness_mode=2 selects UCMS mode, brightness_mode=3 selects EC | 1175 | EC mode, brightness_mode=2 selects UCMS mode, brightness_mode=3 selects EC |
1163 | mode with NVRAM backing (so that brightness changes are remembered | 1176 | mode with NVRAM backing (so that brightness changes are remembered across |
1164 | across shutdown/reboot). | 1177 | shutdown/reboot). |
1165 | 1178 | ||
1166 | The driver tries to select which interface to use from a table of | 1179 | The driver tries to select which interface to use from a table of |
1167 | defaults for each ThinkPad model. If it makes a wrong choice, please | 1180 | defaults for each ThinkPad model. If it makes a wrong choice, please |
1168 | report this as a bug, so that we can fix it. | 1181 | report this as a bug, so that we can fix it. |
1169 | 1182 | ||
1183 | Lenovo ThinkPads only support brightness_mode=2 (UCMS). | ||
1184 | |||
1170 | When display backlight brightness controls are available through the | 1185 | When display backlight brightness controls are available through the |
1171 | standard ACPI interface, it is best to use it instead of this direct | 1186 | standard ACPI interface, it is best to use it instead of this direct |
1172 | ThinkPad-specific interface. The driver will disable its native | 1187 | ThinkPad-specific interface. The driver will disable its native |
@@ -1254,7 +1269,7 @@ Fan control and monitoring: fan speed, fan enable/disable | |||
1254 | 1269 | ||
1255 | procfs: /proc/acpi/ibm/fan | 1270 | procfs: /proc/acpi/ibm/fan |
1256 | sysfs device attributes: (hwmon "thinkpad") fan1_input, pwm1, | 1271 | sysfs device attributes: (hwmon "thinkpad") fan1_input, pwm1, |
1257 | pwm1_enable | 1272 | pwm1_enable, fan2_input |
1258 | sysfs hwmon driver attributes: fan_watchdog | 1273 | sysfs hwmon driver attributes: fan_watchdog |
1259 | 1274 | ||
1260 | NOTE NOTE NOTE: fan control operations are disabled by default for | 1275 | NOTE NOTE NOTE: fan control operations are disabled by default for |
@@ -1267,6 +1282,9 @@ from the hardware registers of the embedded controller. This is known | |||
1267 | to work on later R, T, X and Z series ThinkPads but may show a bogus | 1282 | to work on later R, T, X and Z series ThinkPads but may show a bogus |
1268 | value on other models. | 1283 | value on other models. |
1269 | 1284 | ||
1285 | Some Lenovo ThinkPads support a secondary fan. This fan cannot be | ||
1286 | controlled separately, it shares the main fan control. | ||
1287 | |||
1270 | Fan levels: | 1288 | Fan levels: |
1271 | 1289 | ||
1272 | Most ThinkPad fans work in "levels" at the firmware interface. Level 0 | 1290 | Most ThinkPad fans work in "levels" at the firmware interface. Level 0 |
@@ -1397,6 +1415,11 @@ hwmon device attribute fan1_input: | |||
1397 | which can take up to two minutes. May return rubbish on older | 1415 | which can take up to two minutes. May return rubbish on older |
1398 | ThinkPads. | 1416 | ThinkPads. |
1399 | 1417 | ||
1418 | hwmon device attribute fan2_input: | ||
1419 | Fan tachometer reading, in RPM, for the secondary fan. | ||
1420 | Available only on some ThinkPads. If the secondary fan is | ||
1421 | not installed, will always read 0. | ||
1422 | |||
1400 | hwmon driver attribute fan_watchdog: | 1423 | hwmon driver attribute fan_watchdog: |
1401 | Fan safety watchdog timer interval, in seconds. Minimum is | 1424 | Fan safety watchdog timer interval, in seconds. Minimum is |
1402 | 1 second, maximum is 120 seconds. 0 disables the watchdog. | 1425 | 1 second, maximum is 120 seconds. 0 disables the watchdog. |
@@ -1555,3 +1578,7 @@ Sysfs interface changelog: | |||
1555 | 0x020300: hotkey enable/disable support removed, attributes | 1578 | 0x020300: hotkey enable/disable support removed, attributes |
1556 | hotkey_bios_enabled and hotkey_enable deprecated and | 1579 | hotkey_bios_enabled and hotkey_enable deprecated and |
1557 | marked for removal. | 1580 | marked for removal. |
1581 | |||
1582 | 0x020400: Marker for 16 LEDs support. Also, LEDs that are known | ||
1583 | to not exist in a given model are not registered with | ||
1584 | the LED sysfs class anymore. | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 303129ab4b75..05a4f306f1a0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -230,6 +230,13 @@ L: linux-acenic@sunsite.dk | |||
230 | S: Maintained | 230 | S: Maintained |
231 | F: drivers/net/acenic* | 231 | F: drivers/net/acenic* |
232 | 232 | ||
233 | ACER ASPIRE ONE TEMPERATURE AND FAN DRIVER | ||
234 | P: Peter Feuerer | ||
235 | M: peter@piie.net | ||
236 | W: http://piie.net/?section=acerhdf | ||
237 | S: Maintained | ||
238 | F: drivers/platform/x86/acerhdf.c | ||
239 | |||
233 | ACER WMI LAPTOP EXTRAS | 240 | ACER WMI LAPTOP EXTRAS |
234 | P: Carlos Corbacho | 241 | P: Carlos Corbacho |
235 | M: carlos@strangeworlds.co.uk | 242 | M: carlos@strangeworlds.co.uk |
@@ -913,8 +920,7 @@ M: corentincj@iksaif.net | |||
913 | P: Karol Kozimor | 920 | P: Karol Kozimor |
914 | M: sziwan@users.sourceforge.net | 921 | M: sziwan@users.sourceforge.net |
915 | L: acpi4asus-user@lists.sourceforge.net | 922 | L: acpi4asus-user@lists.sourceforge.net |
916 | W: http://sourceforge.net/projects/acpi4asus | 923 | W: http://acpi4asus.sf.net |
917 | W: http://xf.iksaif.net/acpi4asus | ||
918 | S: Maintained | 924 | S: Maintained |
919 | F: arch/x86/kernel/acpi/boot.c | 925 | F: arch/x86/kernel/acpi/boot.c |
920 | F: drivers/platform/x86/asus_acpi.c | 926 | F: drivers/platform/x86/asus_acpi.c |
@@ -930,8 +936,7 @@ ASUS LAPTOP EXTRAS DRIVER | |||
930 | P: Corentin Chary | 936 | P: Corentin Chary |
931 | M: corentincj@iksaif.net | 937 | M: corentincj@iksaif.net |
932 | L: acpi4asus-user@lists.sourceforge.net | 938 | L: acpi4asus-user@lists.sourceforge.net |
933 | W: http://sourceforge.net/projects/acpi4asus | 939 | W: http://acpi4asus.sf.net |
934 | W: http://xf.iksaif.net/acpi4asus | ||
935 | S: Maintained | 940 | S: Maintained |
936 | F: drivers/platform/x86/asus-laptop.c | 941 | F: drivers/platform/x86/asus-laptop.c |
937 | 942 | ||
@@ -2110,7 +2115,7 @@ EEEPC LAPTOP EXTRAS DRIVER | |||
2110 | P: Corentin Chary | 2115 | P: Corentin Chary |
2111 | M: corentincj@iksaif.net | 2116 | M: corentincj@iksaif.net |
2112 | L: acpi4asus-user@lists.sourceforge.net | 2117 | L: acpi4asus-user@lists.sourceforge.net |
2113 | W: http://sourceforge.net/projects/acpi4asus | 2118 | W: http://acpi4asus.sf.net |
2114 | S: Maintained | 2119 | S: Maintained |
2115 | F: drivers/platform/x86/eeepc-laptop.c | 2120 | F: drivers/platform/x86/eeepc-laptop.c |
2116 | 2121 | ||
diff --git a/arch/ia64/kernel/acpi-processor.c b/arch/ia64/kernel/acpi-processor.c index cbe6cee5a550..dbda7bde6112 100644 --- a/arch/ia64/kernel/acpi-processor.c +++ b/arch/ia64/kernel/acpi-processor.c | |||
@@ -71,3 +71,15 @@ void arch_acpi_processor_init_pdc(struct acpi_processor *pr) | |||
71 | } | 71 | } |
72 | 72 | ||
73 | EXPORT_SYMBOL(arch_acpi_processor_init_pdc); | 73 | EXPORT_SYMBOL(arch_acpi_processor_init_pdc); |
74 | |||
75 | void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr) | ||
76 | { | ||
77 | if (pr->pdc) { | ||
78 | kfree(pr->pdc->pointer->buffer.pointer); | ||
79 | kfree(pr->pdc->pointer); | ||
80 | kfree(pr->pdc); | ||
81 | pr->pdc = NULL; | ||
82 | } | ||
83 | } | ||
84 | |||
85 | EXPORT_SYMBOL(arch_acpi_processor_cleanup_pdc); | ||
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 4518dc500903..20d1465a2ab0 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h | |||
@@ -144,6 +144,7 @@ static inline unsigned int acpi_processor_cstate_check(unsigned int max_cstate) | |||
144 | 144 | ||
145 | #else /* !CONFIG_ACPI */ | 145 | #else /* !CONFIG_ACPI */ |
146 | 146 | ||
147 | #define acpi_disabled 1 | ||
147 | #define acpi_lapic 0 | 148 | #define acpi_lapic 0 |
148 | #define acpi_ioapic 0 | 149 | #define acpi_ioapic 0 |
149 | static inline void acpi_noirq_set(void) { } | 150 | static inline void acpi_noirq_set(void) { } |
diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h index cb739cc0a080..d419f5c02669 100644 --- a/arch/x86/include/asm/pci_x86.h +++ b/arch/x86/include/asm/pci_x86.h | |||
@@ -121,6 +121,9 @@ extern int __init pcibios_init(void); | |||
121 | extern int __init pci_mmcfg_arch_init(void); | 121 | extern int __init pci_mmcfg_arch_init(void); |
122 | extern void __init pci_mmcfg_arch_free(void); | 122 | extern void __init pci_mmcfg_arch_free(void); |
123 | 123 | ||
124 | extern struct acpi_mcfg_allocation *pci_mmcfg_config; | ||
125 | extern int pci_mmcfg_config_num; | ||
126 | |||
124 | /* | 127 | /* |
125 | * AMD Fam10h CPUs are buggy, and cannot access MMIO config space | 128 | * AMD Fam10h CPUs are buggy, and cannot access MMIO config space |
126 | * on their northbrige except through the * %eax register. As such, you MUST | 129 | * on their northbrige except through the * %eax register. As such, you MUST |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 631086159c53..6b8ca3a0285d 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -44,11 +44,7 @@ | |||
44 | 44 | ||
45 | static int __initdata acpi_force = 0; | 45 | static int __initdata acpi_force = 0; |
46 | u32 acpi_rsdt_forced; | 46 | u32 acpi_rsdt_forced; |
47 | #ifdef CONFIG_ACPI | 47 | int acpi_disabled; |
48 | int acpi_disabled = 0; | ||
49 | #else | ||
50 | int acpi_disabled = 1; | ||
51 | #endif | ||
52 | EXPORT_SYMBOL(acpi_disabled); | 48 | EXPORT_SYMBOL(acpi_disabled); |
53 | 49 | ||
54 | #ifdef CONFIG_X86_64 | 50 | #ifdef CONFIG_X86_64 |
@@ -122,72 +118,6 @@ void __init __acpi_unmap_table(char *map, unsigned long size) | |||
122 | early_iounmap(map, size); | 118 | early_iounmap(map, size); |
123 | } | 119 | } |
124 | 120 | ||
125 | #ifdef CONFIG_PCI_MMCONFIG | ||
126 | |||
127 | static int acpi_mcfg_64bit_base_addr __initdata = FALSE; | ||
128 | |||
129 | /* The physical address of the MMCONFIG aperture. Set from ACPI tables. */ | ||
130 | struct acpi_mcfg_allocation *pci_mmcfg_config; | ||
131 | int pci_mmcfg_config_num; | ||
132 | |||
133 | static int __init acpi_mcfg_oem_check(struct acpi_table_mcfg *mcfg) | ||
134 | { | ||
135 | if (!strcmp(mcfg->header.oem_id, "SGI")) | ||
136 | acpi_mcfg_64bit_base_addr = TRUE; | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | int __init acpi_parse_mcfg(struct acpi_table_header *header) | ||
142 | { | ||
143 | struct acpi_table_mcfg *mcfg; | ||
144 | unsigned long i; | ||
145 | int config_size; | ||
146 | |||
147 | if (!header) | ||
148 | return -EINVAL; | ||
149 | |||
150 | mcfg = (struct acpi_table_mcfg *)header; | ||
151 | |||
152 | /* how many config structures do we have */ | ||
153 | pci_mmcfg_config_num = 0; | ||
154 | i = header->length - sizeof(struct acpi_table_mcfg); | ||
155 | while (i >= sizeof(struct acpi_mcfg_allocation)) { | ||
156 | ++pci_mmcfg_config_num; | ||
157 | i -= sizeof(struct acpi_mcfg_allocation); | ||
158 | }; | ||
159 | if (pci_mmcfg_config_num == 0) { | ||
160 | printk(KERN_ERR PREFIX "MMCONFIG has no entries\n"); | ||
161 | return -ENODEV; | ||
162 | } | ||
163 | |||
164 | config_size = pci_mmcfg_config_num * sizeof(*pci_mmcfg_config); | ||
165 | pci_mmcfg_config = kmalloc(config_size, GFP_KERNEL); | ||
166 | if (!pci_mmcfg_config) { | ||
167 | printk(KERN_WARNING PREFIX | ||
168 | "No memory for MCFG config tables\n"); | ||
169 | return -ENOMEM; | ||
170 | } | ||
171 | |||
172 | memcpy(pci_mmcfg_config, &mcfg[1], config_size); | ||
173 | |||
174 | acpi_mcfg_oem_check(mcfg); | ||
175 | |||
176 | for (i = 0; i < pci_mmcfg_config_num; ++i) { | ||
177 | if ((pci_mmcfg_config[i].address > 0xFFFFFFFF) && | ||
178 | !acpi_mcfg_64bit_base_addr) { | ||
179 | printk(KERN_ERR PREFIX | ||
180 | "MMCONFIG not in low 4GB of memory\n"); | ||
181 | kfree(pci_mmcfg_config); | ||
182 | pci_mmcfg_config_num = 0; | ||
183 | return -ENODEV; | ||
184 | } | ||
185 | } | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | #endif /* CONFIG_PCI_MMCONFIG */ | ||
190 | |||
191 | #ifdef CONFIG_X86_LOCAL_APIC | 121 | #ifdef CONFIG_X86_LOCAL_APIC |
192 | static int __init acpi_parse_madt(struct acpi_table_header *table) | 122 | static int __init acpi_parse_madt(struct acpi_table_header *table) |
193 | { | 123 | { |
@@ -1519,14 +1449,6 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = { | |||
1519 | }, | 1449 | }, |
1520 | { | 1450 | { |
1521 | .callback = force_acpi_ht, | 1451 | .callback = force_acpi_ht, |
1522 | .ident = "ASUS P4B266", | ||
1523 | .matches = { | ||
1524 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | ||
1525 | DMI_MATCH(DMI_BOARD_NAME, "P4B266"), | ||
1526 | }, | ||
1527 | }, | ||
1528 | { | ||
1529 | .callback = force_acpi_ht, | ||
1530 | .ident = "ASUS P2B-DS", | 1452 | .ident = "ASUS P2B-DS", |
1531 | .matches = { | 1453 | .matches = { |
1532 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | 1454 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), |
diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c index bbbe4bbb6f34..8c44c232efcb 100644 --- a/arch/x86/kernel/acpi/cstate.c +++ b/arch/x86/kernel/acpi/cstate.c | |||
@@ -34,12 +34,22 @@ void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, | |||
34 | flags->bm_check = 1; | 34 | flags->bm_check = 1; |
35 | else if (c->x86_vendor == X86_VENDOR_INTEL) { | 35 | else if (c->x86_vendor == X86_VENDOR_INTEL) { |
36 | /* | 36 | /* |
37 | * Today all CPUs that support C3 share cache. | 37 | * Today all MP CPUs that support C3 share cache. |
38 | * TBD: This needs to look at cache shared map, once | 38 | * And caches should not be flushed by software while |
39 | * multi-core detection patch makes to the base. | 39 | * entering C3 type state. |
40 | */ | 40 | */ |
41 | flags->bm_check = 1; | 41 | flags->bm_check = 1; |
42 | } | 42 | } |
43 | |||
44 | /* | ||
45 | * On all recent Intel platforms, ARB_DISABLE is a nop. | ||
46 | * So, set bm_control to zero to indicate that ARB_DISABLE | ||
47 | * is not required while entering C3 type state on | ||
48 | * P4, Core and beyond CPUs | ||
49 | */ | ||
50 | if (c->x86_vendor == X86_VENDOR_INTEL && | ||
51 | (c->x86 > 0x6 || (c->x86 == 6 && c->x86_model >= 14))) | ||
52 | flags->bm_control = 0; | ||
43 | } | 53 | } |
44 | EXPORT_SYMBOL(acpi_processor_power_init_bm_check); | 54 | EXPORT_SYMBOL(acpi_processor_power_init_bm_check); |
45 | 55 | ||
diff --git a/arch/x86/kernel/acpi/processor.c b/arch/x86/kernel/acpi/processor.c index 7c074eec39fb..d296f4a195c9 100644 --- a/arch/x86/kernel/acpi/processor.c +++ b/arch/x86/kernel/acpi/processor.c | |||
@@ -72,6 +72,7 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c) | |||
72 | return; | 72 | return; |
73 | } | 73 | } |
74 | 74 | ||
75 | |||
75 | /* Initialize _PDC data based on the CPU vendor */ | 76 | /* Initialize _PDC data based on the CPU vendor */ |
76 | void arch_acpi_processor_init_pdc(struct acpi_processor *pr) | 77 | void arch_acpi_processor_init_pdc(struct acpi_processor *pr) |
77 | { | 78 | { |
@@ -85,3 +86,15 @@ void arch_acpi_processor_init_pdc(struct acpi_processor *pr) | |||
85 | } | 86 | } |
86 | 87 | ||
87 | EXPORT_SYMBOL(arch_acpi_processor_init_pdc); | 88 | EXPORT_SYMBOL(arch_acpi_processor_init_pdc); |
89 | |||
90 | void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr) | ||
91 | { | ||
92 | if (pr->pdc) { | ||
93 | kfree(pr->pdc->pointer->buffer.pointer); | ||
94 | kfree(pr->pdc->pointer); | ||
95 | kfree(pr->pdc); | ||
96 | pr->pdc = NULL; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | EXPORT_SYMBOL(arch_acpi_processor_cleanup_pdc); | ||
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 8766b0e216c5..712443ec6d43 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c | |||
@@ -523,6 +523,69 @@ reject: | |||
523 | 523 | ||
524 | static int __initdata known_bridge; | 524 | static int __initdata known_bridge; |
525 | 525 | ||
526 | static int acpi_mcfg_64bit_base_addr __initdata = FALSE; | ||
527 | |||
528 | /* The physical address of the MMCONFIG aperture. Set from ACPI tables. */ | ||
529 | struct acpi_mcfg_allocation *pci_mmcfg_config; | ||
530 | int pci_mmcfg_config_num; | ||
531 | |||
532 | static int __init acpi_mcfg_oem_check(struct acpi_table_mcfg *mcfg) | ||
533 | { | ||
534 | if (!strcmp(mcfg->header.oem_id, "SGI")) | ||
535 | acpi_mcfg_64bit_base_addr = TRUE; | ||
536 | |||
537 | return 0; | ||
538 | } | ||
539 | |||
540 | static int __init pci_parse_mcfg(struct acpi_table_header *header) | ||
541 | { | ||
542 | struct acpi_table_mcfg *mcfg; | ||
543 | unsigned long i; | ||
544 | int config_size; | ||
545 | |||
546 | if (!header) | ||
547 | return -EINVAL; | ||
548 | |||
549 | mcfg = (struct acpi_table_mcfg *)header; | ||
550 | |||
551 | /* how many config structures do we have */ | ||
552 | pci_mmcfg_config_num = 0; | ||
553 | i = header->length - sizeof(struct acpi_table_mcfg); | ||
554 | while (i >= sizeof(struct acpi_mcfg_allocation)) { | ||
555 | ++pci_mmcfg_config_num; | ||
556 | i -= sizeof(struct acpi_mcfg_allocation); | ||
557 | }; | ||
558 | if (pci_mmcfg_config_num == 0) { | ||
559 | printk(KERN_ERR PREFIX "MMCONFIG has no entries\n"); | ||
560 | return -ENODEV; | ||
561 | } | ||
562 | |||
563 | config_size = pci_mmcfg_config_num * sizeof(*pci_mmcfg_config); | ||
564 | pci_mmcfg_config = kmalloc(config_size, GFP_KERNEL); | ||
565 | if (!pci_mmcfg_config) { | ||
566 | printk(KERN_WARNING PREFIX | ||
567 | "No memory for MCFG config tables\n"); | ||
568 | return -ENOMEM; | ||
569 | } | ||
570 | |||
571 | memcpy(pci_mmcfg_config, &mcfg[1], config_size); | ||
572 | |||
573 | acpi_mcfg_oem_check(mcfg); | ||
574 | |||
575 | for (i = 0; i < pci_mmcfg_config_num; ++i) { | ||
576 | if ((pci_mmcfg_config[i].address > 0xFFFFFFFF) && | ||
577 | !acpi_mcfg_64bit_base_addr) { | ||
578 | printk(KERN_ERR PREFIX | ||
579 | "MMCONFIG not in low 4GB of memory\n"); | ||
580 | kfree(pci_mmcfg_config); | ||
581 | pci_mmcfg_config_num = 0; | ||
582 | return -ENODEV; | ||
583 | } | ||
584 | } | ||
585 | |||
586 | return 0; | ||
587 | } | ||
588 | |||
526 | static void __init __pci_mmcfg_init(int early) | 589 | static void __init __pci_mmcfg_init(int early) |
527 | { | 590 | { |
528 | /* MMCONFIG disabled */ | 591 | /* MMCONFIG disabled */ |
@@ -543,7 +606,7 @@ static void __init __pci_mmcfg_init(int early) | |||
543 | } | 606 | } |
544 | 607 | ||
545 | if (!known_bridge) | 608 | if (!known_bridge) |
546 | acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg); | 609 | acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg); |
547 | 610 | ||
548 | pci_mmcfg_reject_broken(early); | 611 | pci_mmcfg_reject_broken(early); |
549 | 612 | ||
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 88e42abf5d88..0df8fcb687d6 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c | |||
@@ -61,6 +61,7 @@ static int acpi_ac_open_fs(struct inode *inode, struct file *file); | |||
61 | static int acpi_ac_add(struct acpi_device *device); | 61 | static int acpi_ac_add(struct acpi_device *device); |
62 | static int acpi_ac_remove(struct acpi_device *device, int type); | 62 | static int acpi_ac_remove(struct acpi_device *device, int type); |
63 | static int acpi_ac_resume(struct acpi_device *device); | 63 | static int acpi_ac_resume(struct acpi_device *device); |
64 | static void acpi_ac_notify(struct acpi_device *device, u32 event); | ||
64 | 65 | ||
65 | static const struct acpi_device_id ac_device_ids[] = { | 66 | static const struct acpi_device_id ac_device_ids[] = { |
66 | {"ACPI0003", 0}, | 67 | {"ACPI0003", 0}, |
@@ -72,10 +73,12 @@ static struct acpi_driver acpi_ac_driver = { | |||
72 | .name = "ac", | 73 | .name = "ac", |
73 | .class = ACPI_AC_CLASS, | 74 | .class = ACPI_AC_CLASS, |
74 | .ids = ac_device_ids, | 75 | .ids = ac_device_ids, |
76 | .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, | ||
75 | .ops = { | 77 | .ops = { |
76 | .add = acpi_ac_add, | 78 | .add = acpi_ac_add, |
77 | .remove = acpi_ac_remove, | 79 | .remove = acpi_ac_remove, |
78 | .resume = acpi_ac_resume, | 80 | .resume = acpi_ac_resume, |
81 | .notify = acpi_ac_notify, | ||
79 | }, | 82 | }, |
80 | }; | 83 | }; |
81 | 84 | ||
@@ -220,16 +223,14 @@ static int acpi_ac_remove_fs(struct acpi_device *device) | |||
220 | Driver Model | 223 | Driver Model |
221 | -------------------------------------------------------------------------- */ | 224 | -------------------------------------------------------------------------- */ |
222 | 225 | ||
223 | static void acpi_ac_notify(acpi_handle handle, u32 event, void *data) | 226 | static void acpi_ac_notify(struct acpi_device *device, u32 event) |
224 | { | 227 | { |
225 | struct acpi_ac *ac = data; | 228 | struct acpi_ac *ac = acpi_driver_data(device); |
226 | struct acpi_device *device = NULL; | ||
227 | 229 | ||
228 | 230 | ||
229 | if (!ac) | 231 | if (!ac) |
230 | return; | 232 | return; |
231 | 233 | ||
232 | device = ac->device; | ||
233 | switch (event) { | 234 | switch (event) { |
234 | default: | 235 | default: |
235 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 236 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
@@ -253,7 +254,6 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data) | |||
253 | static int acpi_ac_add(struct acpi_device *device) | 254 | static int acpi_ac_add(struct acpi_device *device) |
254 | { | 255 | { |
255 | int result = 0; | 256 | int result = 0; |
256 | acpi_status status = AE_OK; | ||
257 | struct acpi_ac *ac = NULL; | 257 | struct acpi_ac *ac = NULL; |
258 | 258 | ||
259 | 259 | ||
@@ -286,13 +286,6 @@ static int acpi_ac_add(struct acpi_device *device) | |||
286 | ac->charger.get_property = get_ac_property; | 286 | ac->charger.get_property = get_ac_property; |
287 | power_supply_register(&ac->device->dev, &ac->charger); | 287 | power_supply_register(&ac->device->dev, &ac->charger); |
288 | #endif | 288 | #endif |
289 | status = acpi_install_notify_handler(device->handle, | ||
290 | ACPI_ALL_NOTIFY, acpi_ac_notify, | ||
291 | ac); | ||
292 | if (ACPI_FAILURE(status)) { | ||
293 | result = -ENODEV; | ||
294 | goto end; | ||
295 | } | ||
296 | 289 | ||
297 | printk(KERN_INFO PREFIX "%s [%s] (%s)\n", | 290 | printk(KERN_INFO PREFIX "%s [%s] (%s)\n", |
298 | acpi_device_name(device), acpi_device_bid(device), | 291 | acpi_device_name(device), acpi_device_bid(device), |
@@ -328,7 +321,6 @@ static int acpi_ac_resume(struct acpi_device *device) | |||
328 | 321 | ||
329 | static int acpi_ac_remove(struct acpi_device *device, int type) | 322 | static int acpi_ac_remove(struct acpi_device *device, int type) |
330 | { | 323 | { |
331 | acpi_status status = AE_OK; | ||
332 | struct acpi_ac *ac = NULL; | 324 | struct acpi_ac *ac = NULL; |
333 | 325 | ||
334 | 326 | ||
@@ -337,8 +329,6 @@ static int acpi_ac_remove(struct acpi_device *device, int type) | |||
337 | 329 | ||
338 | ac = acpi_driver_data(device); | 330 | ac = acpi_driver_data(device); |
339 | 331 | ||
340 | status = acpi_remove_notify_handler(device->handle, | ||
341 | ACPI_ALL_NOTIFY, acpi_ac_notify); | ||
342 | #ifdef CONFIG_ACPI_SYSFS_POWER | 332 | #ifdef CONFIG_ACPI_SYSFS_POWER |
343 | if (ac->charger.dev) | 333 | if (ac->charger.dev) |
344 | power_supply_unregister(&ac->charger); | 334 | power_supply_unregister(&ac->charger); |
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index b0de6312919a..58b4517ce712 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
@@ -796,13 +796,12 @@ static void acpi_battery_remove_fs(struct acpi_device *device) | |||
796 | Driver Interface | 796 | Driver Interface |
797 | -------------------------------------------------------------------------- */ | 797 | -------------------------------------------------------------------------- */ |
798 | 798 | ||
799 | static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) | 799 | static void acpi_battery_notify(struct acpi_device *device, u32 event) |
800 | { | 800 | { |
801 | struct acpi_battery *battery = data; | 801 | struct acpi_battery *battery = acpi_driver_data(device); |
802 | struct acpi_device *device; | 802 | |
803 | if (!battery) | 803 | if (!battery) |
804 | return; | 804 | return; |
805 | device = battery->device; | ||
806 | acpi_battery_update(battery); | 805 | acpi_battery_update(battery); |
807 | acpi_bus_generate_proc_event(device, event, | 806 | acpi_bus_generate_proc_event(device, event, |
808 | acpi_battery_present(battery)); | 807 | acpi_battery_present(battery)); |
@@ -819,7 +818,6 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) | |||
819 | static int acpi_battery_add(struct acpi_device *device) | 818 | static int acpi_battery_add(struct acpi_device *device) |
820 | { | 819 | { |
821 | int result = 0; | 820 | int result = 0; |
822 | acpi_status status = 0; | ||
823 | struct acpi_battery *battery = NULL; | 821 | struct acpi_battery *battery = NULL; |
824 | if (!device) | 822 | if (!device) |
825 | return -EINVAL; | 823 | return -EINVAL; |
@@ -834,22 +832,12 @@ static int acpi_battery_add(struct acpi_device *device) | |||
834 | acpi_battery_update(battery); | 832 | acpi_battery_update(battery); |
835 | #ifdef CONFIG_ACPI_PROCFS_POWER | 833 | #ifdef CONFIG_ACPI_PROCFS_POWER |
836 | result = acpi_battery_add_fs(device); | 834 | result = acpi_battery_add_fs(device); |
837 | if (result) | ||
838 | goto end; | ||
839 | #endif | 835 | #endif |
840 | status = acpi_install_notify_handler(device->handle, | 836 | if (!result) { |
841 | ACPI_ALL_NOTIFY, | 837 | printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", |
842 | acpi_battery_notify, battery); | 838 | ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), |
843 | if (ACPI_FAILURE(status)) { | 839 | device->status.battery_present ? "present" : "absent"); |
844 | ACPI_EXCEPTION((AE_INFO, status, "Installing notify handler")); | 840 | } else { |
845 | result = -ENODEV; | ||
846 | goto end; | ||
847 | } | ||
848 | printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", | ||
849 | ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), | ||
850 | device->status.battery_present ? "present" : "absent"); | ||
851 | end: | ||
852 | if (result) { | ||
853 | #ifdef CONFIG_ACPI_PROCFS_POWER | 841 | #ifdef CONFIG_ACPI_PROCFS_POWER |
854 | acpi_battery_remove_fs(device); | 842 | acpi_battery_remove_fs(device); |
855 | #endif | 843 | #endif |
@@ -860,15 +848,11 @@ static int acpi_battery_add(struct acpi_device *device) | |||
860 | 848 | ||
861 | static int acpi_battery_remove(struct acpi_device *device, int type) | 849 | static int acpi_battery_remove(struct acpi_device *device, int type) |
862 | { | 850 | { |
863 | acpi_status status = 0; | ||
864 | struct acpi_battery *battery = NULL; | 851 | struct acpi_battery *battery = NULL; |
865 | 852 | ||
866 | if (!device || !acpi_driver_data(device)) | 853 | if (!device || !acpi_driver_data(device)) |
867 | return -EINVAL; | 854 | return -EINVAL; |
868 | battery = acpi_driver_data(device); | 855 | battery = acpi_driver_data(device); |
869 | status = acpi_remove_notify_handler(device->handle, | ||
870 | ACPI_ALL_NOTIFY, | ||
871 | acpi_battery_notify); | ||
872 | #ifdef CONFIG_ACPI_PROCFS_POWER | 856 | #ifdef CONFIG_ACPI_PROCFS_POWER |
873 | acpi_battery_remove_fs(device); | 857 | acpi_battery_remove_fs(device); |
874 | #endif | 858 | #endif |
@@ -896,10 +880,12 @@ static struct acpi_driver acpi_battery_driver = { | |||
896 | .name = "battery", | 880 | .name = "battery", |
897 | .class = ACPI_BATTERY_CLASS, | 881 | .class = ACPI_BATTERY_CLASS, |
898 | .ids = battery_device_ids, | 882 | .ids = battery_device_ids, |
883 | .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, | ||
899 | .ops = { | 884 | .ops = { |
900 | .add = acpi_battery_add, | 885 | .add = acpi_battery_add, |
901 | .resume = acpi_battery_resume, | 886 | .resume = acpi_battery_resume, |
902 | .remove = acpi_battery_remove, | 887 | .remove = acpi_battery_remove, |
888 | .notify = acpi_battery_notify, | ||
903 | }, | 889 | }, |
904 | }; | 890 | }; |
905 | 891 | ||
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 09c69806c1fc..f6baa77deefb 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c | |||
@@ -192,6 +192,22 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { | |||
192 | DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"), | 192 | DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"), |
193 | }, | 193 | }, |
194 | }, | 194 | }, |
195 | { | ||
196 | .callback = dmi_disable_osi_vista, | ||
197 | .ident = "Sony VGN-NS10J_S", | ||
198 | .matches = { | ||
199 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
200 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS10J_S"), | ||
201 | }, | ||
202 | }, | ||
203 | { | ||
204 | .callback = dmi_disable_osi_vista, | ||
205 | .ident = "Sony VGN-SR290J", | ||
206 | .matches = { | ||
207 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
208 | DMI_MATCH(DMI_PRODUCT_NAME, "Sony VGN-SR290J"), | ||
209 | }, | ||
210 | }, | ||
195 | 211 | ||
196 | /* | 212 | /* |
197 | * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. | 213 | * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. |
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index ae862f1798dc..2876fc70c3a9 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -450,18 +450,16 @@ int acpi_bus_receive_event(struct acpi_bus_event *event) | |||
450 | Notification Handling | 450 | Notification Handling |
451 | -------------------------------------------------------------------------- */ | 451 | -------------------------------------------------------------------------- */ |
452 | 452 | ||
453 | static int | 453 | static void acpi_bus_check_device(acpi_handle handle) |
454 | acpi_bus_check_device(struct acpi_device *device, int *status_changed) | ||
455 | { | 454 | { |
456 | acpi_status status = 0; | 455 | struct acpi_device *device; |
456 | acpi_status status; | ||
457 | struct acpi_device_status old_status; | 457 | struct acpi_device_status old_status; |
458 | 458 | ||
459 | 459 | if (acpi_bus_get_device(handle, &device)) | |
460 | return; | ||
460 | if (!device) | 461 | if (!device) |
461 | return -EINVAL; | 462 | return; |
462 | |||
463 | if (status_changed) | ||
464 | *status_changed = 0; | ||
465 | 463 | ||
466 | old_status = device->status; | 464 | old_status = device->status; |
467 | 465 | ||
@@ -471,22 +469,15 @@ acpi_bus_check_device(struct acpi_device *device, int *status_changed) | |||
471 | */ | 469 | */ |
472 | if (device->parent && !device->parent->status.present) { | 470 | if (device->parent && !device->parent->status.present) { |
473 | device->status = device->parent->status; | 471 | device->status = device->parent->status; |
474 | if (STRUCT_TO_INT(old_status) != STRUCT_TO_INT(device->status)) { | 472 | return; |
475 | if (status_changed) | ||
476 | *status_changed = 1; | ||
477 | } | ||
478 | return 0; | ||
479 | } | 473 | } |
480 | 474 | ||
481 | status = acpi_bus_get_status(device); | 475 | status = acpi_bus_get_status(device); |
482 | if (ACPI_FAILURE(status)) | 476 | if (ACPI_FAILURE(status)) |
483 | return -ENODEV; | 477 | return; |
484 | 478 | ||
485 | if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status)) | 479 | if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status)) |
486 | return 0; | 480 | return; |
487 | |||
488 | if (status_changed) | ||
489 | *status_changed = 1; | ||
490 | 481 | ||
491 | /* | 482 | /* |
492 | * Device Insertion/Removal | 483 | * Device Insertion/Removal |
@@ -498,33 +489,17 @@ acpi_bus_check_device(struct acpi_device *device, int *status_changed) | |||
498 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n")); | 489 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n")); |
499 | /* TBD: Handle device removal */ | 490 | /* TBD: Handle device removal */ |
500 | } | 491 | } |
501 | |||
502 | return 0; | ||
503 | } | 492 | } |
504 | 493 | ||
505 | static int acpi_bus_check_scope(struct acpi_device *device) | 494 | static void acpi_bus_check_scope(acpi_handle handle) |
506 | { | 495 | { |
507 | int result = 0; | ||
508 | int status_changed = 0; | ||
509 | |||
510 | |||
511 | if (!device) | ||
512 | return -EINVAL; | ||
513 | |||
514 | /* Status Change? */ | 496 | /* Status Change? */ |
515 | result = acpi_bus_check_device(device, &status_changed); | 497 | acpi_bus_check_device(handle); |
516 | if (result) | ||
517 | return result; | ||
518 | |||
519 | if (!status_changed) | ||
520 | return 0; | ||
521 | 498 | ||
522 | /* | 499 | /* |
523 | * TBD: Enumerate child devices within this device's scope and | 500 | * TBD: Enumerate child devices within this device's scope and |
524 | * run acpi_bus_check_device()'s on them. | 501 | * run acpi_bus_check_device()'s on them. |
525 | */ | 502 | */ |
526 | |||
527 | return 0; | ||
528 | } | 503 | } |
529 | 504 | ||
530 | static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list); | 505 | static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list); |
@@ -547,22 +522,19 @@ EXPORT_SYMBOL_GPL(unregister_acpi_bus_notifier); | |||
547 | */ | 522 | */ |
548 | static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) | 523 | static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) |
549 | { | 524 | { |
550 | int result = 0; | ||
551 | struct acpi_device *device = NULL; | 525 | struct acpi_device *device = NULL; |
526 | struct acpi_driver *driver; | ||
527 | |||
528 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n", | ||
529 | type, handle)); | ||
552 | 530 | ||
553 | blocking_notifier_call_chain(&acpi_bus_notify_list, | 531 | blocking_notifier_call_chain(&acpi_bus_notify_list, |
554 | type, (void *)handle); | 532 | type, (void *)handle); |
555 | 533 | ||
556 | if (acpi_bus_get_device(handle, &device)) | ||
557 | return; | ||
558 | |||
559 | switch (type) { | 534 | switch (type) { |
560 | 535 | ||
561 | case ACPI_NOTIFY_BUS_CHECK: | 536 | case ACPI_NOTIFY_BUS_CHECK: |
562 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 537 | acpi_bus_check_scope(handle); |
563 | "Received BUS CHECK notification for device [%s]\n", | ||
564 | device->pnp.bus_id)); | ||
565 | result = acpi_bus_check_scope(device); | ||
566 | /* | 538 | /* |
567 | * TBD: We'll need to outsource certain events to non-ACPI | 539 | * TBD: We'll need to outsource certain events to non-ACPI |
568 | * drivers via the device manager (device.c). | 540 | * drivers via the device manager (device.c). |
@@ -570,10 +542,7 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) | |||
570 | break; | 542 | break; |
571 | 543 | ||
572 | case ACPI_NOTIFY_DEVICE_CHECK: | 544 | case ACPI_NOTIFY_DEVICE_CHECK: |
573 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 545 | acpi_bus_check_device(handle); |
574 | "Received DEVICE CHECK notification for device [%s]\n", | ||
575 | device->pnp.bus_id)); | ||
576 | result = acpi_bus_check_device(device, NULL); | ||
577 | /* | 546 | /* |
578 | * TBD: We'll need to outsource certain events to non-ACPI | 547 | * TBD: We'll need to outsource certain events to non-ACPI |
579 | * drivers via the device manager (device.c). | 548 | * drivers via the device manager (device.c). |
@@ -581,44 +550,26 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) | |||
581 | break; | 550 | break; |
582 | 551 | ||
583 | case ACPI_NOTIFY_DEVICE_WAKE: | 552 | case ACPI_NOTIFY_DEVICE_WAKE: |
584 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
585 | "Received DEVICE WAKE notification for device [%s]\n", | ||
586 | device->pnp.bus_id)); | ||
587 | /* TBD */ | 553 | /* TBD */ |
588 | break; | 554 | break; |
589 | 555 | ||
590 | case ACPI_NOTIFY_EJECT_REQUEST: | 556 | case ACPI_NOTIFY_EJECT_REQUEST: |
591 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
592 | "Received EJECT REQUEST notification for device [%s]\n", | ||
593 | device->pnp.bus_id)); | ||
594 | /* TBD */ | 557 | /* TBD */ |
595 | break; | 558 | break; |
596 | 559 | ||
597 | case ACPI_NOTIFY_DEVICE_CHECK_LIGHT: | 560 | case ACPI_NOTIFY_DEVICE_CHECK_LIGHT: |
598 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
599 | "Received DEVICE CHECK LIGHT notification for device [%s]\n", | ||
600 | device->pnp.bus_id)); | ||
601 | /* TBD: Exactly what does 'light' mean? */ | 561 | /* TBD: Exactly what does 'light' mean? */ |
602 | break; | 562 | break; |
603 | 563 | ||
604 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: | 564 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: |
605 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
606 | "Received FREQUENCY MISMATCH notification for device [%s]\n", | ||
607 | device->pnp.bus_id)); | ||
608 | /* TBD */ | 565 | /* TBD */ |
609 | break; | 566 | break; |
610 | 567 | ||
611 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: | 568 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: |
612 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
613 | "Received BUS MODE MISMATCH notification for device [%s]\n", | ||
614 | device->pnp.bus_id)); | ||
615 | /* TBD */ | 569 | /* TBD */ |
616 | break; | 570 | break; |
617 | 571 | ||
618 | case ACPI_NOTIFY_POWER_FAULT: | 572 | case ACPI_NOTIFY_POWER_FAULT: |
619 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
620 | "Received POWER FAULT notification for device [%s]\n", | ||
621 | device->pnp.bus_id)); | ||
622 | /* TBD */ | 573 | /* TBD */ |
623 | break; | 574 | break; |
624 | 575 | ||
@@ -629,7 +580,13 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) | |||
629 | break; | 580 | break; |
630 | } | 581 | } |
631 | 582 | ||
632 | return; | 583 | acpi_bus_get_device(handle, &device); |
584 | if (device) { | ||
585 | driver = device->driver; | ||
586 | if (driver && driver->ops.notify && | ||
587 | (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS)) | ||
588 | driver->ops.notify(device, type); | ||
589 | } | ||
633 | } | 590 | } |
634 | 591 | ||
635 | /* -------------------------------------------------------------------------- | 592 | /* -------------------------------------------------------------------------- |
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 8bd2c2a6884d..a8a5c29958c8 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
@@ -140,46 +140,6 @@ struct device *acpi_get_physical_device(acpi_handle handle) | |||
140 | 140 | ||
141 | EXPORT_SYMBOL(acpi_get_physical_device); | 141 | EXPORT_SYMBOL(acpi_get_physical_device); |
142 | 142 | ||
143 | /* ToDo: When a PCI bridge is found, return the PCI device behind the bridge | ||
144 | * This should work in general, but did not on a Lenovo T61 for the | ||
145 | * graphics card. But this must be fixed when the PCI device is | ||
146 | * bound and the kernel device struct is attached to the acpi device | ||
147 | * Note: A success call will increase reference count by one | ||
148 | * Do call put_device(dev) on the returned device then | ||
149 | */ | ||
150 | struct device *acpi_get_physical_pci_device(acpi_handle handle) | ||
151 | { | ||
152 | struct device *dev; | ||
153 | long long device_id; | ||
154 | acpi_status status; | ||
155 | |||
156 | status = | ||
157 | acpi_evaluate_integer(handle, "_ADR", NULL, &device_id); | ||
158 | |||
159 | if (ACPI_FAILURE(status)) | ||
160 | return NULL; | ||
161 | |||
162 | /* We need to attempt to determine whether the _ADR refers to a | ||
163 | PCI device or not. There's no terribly good way to do this, | ||
164 | so the best we can hope for is to assume that there'll never | ||
165 | be a device in the host bridge */ | ||
166 | if (device_id >= 0x10000) { | ||
167 | /* It looks like a PCI device. Does it exist? */ | ||
168 | dev = acpi_get_physical_device(handle); | ||
169 | } else { | ||
170 | /* It doesn't look like a PCI device. Does its parent | ||
171 | exist? */ | ||
172 | acpi_handle phandle; | ||
173 | if (acpi_get_parent(handle, &phandle)) | ||
174 | return NULL; | ||
175 | dev = acpi_get_physical_device(phandle); | ||
176 | } | ||
177 | if (!dev) | ||
178 | return NULL; | ||
179 | return dev; | ||
180 | } | ||
181 | EXPORT_SYMBOL(acpi_get_physical_pci_device); | ||
182 | |||
183 | static int acpi_bind_one(struct device *dev, acpi_handle handle) | 143 | static int acpi_bind_one(struct device *dev, acpi_handle handle) |
184 | { | 144 | { |
185 | struct acpi_device *acpi_dev; | 145 | struct acpi_device *acpi_dev; |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index d916bea729f1..71670719d61a 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -79,6 +79,7 @@ static acpi_osd_handler acpi_irq_handler; | |||
79 | static void *acpi_irq_context; | 79 | static void *acpi_irq_context; |
80 | static struct workqueue_struct *kacpid_wq; | 80 | static struct workqueue_struct *kacpid_wq; |
81 | static struct workqueue_struct *kacpi_notify_wq; | 81 | static struct workqueue_struct *kacpi_notify_wq; |
82 | static struct workqueue_struct *kacpi_hotplug_wq; | ||
82 | 83 | ||
83 | struct acpi_res_list { | 84 | struct acpi_res_list { |
84 | resource_size_t start; | 85 | resource_size_t start; |
@@ -192,8 +193,10 @@ acpi_status acpi_os_initialize1(void) | |||
192 | { | 193 | { |
193 | kacpid_wq = create_singlethread_workqueue("kacpid"); | 194 | kacpid_wq = create_singlethread_workqueue("kacpid"); |
194 | kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); | 195 | kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); |
196 | kacpi_hotplug_wq = create_singlethread_workqueue("kacpi_hotplug"); | ||
195 | BUG_ON(!kacpid_wq); | 197 | BUG_ON(!kacpid_wq); |
196 | BUG_ON(!kacpi_notify_wq); | 198 | BUG_ON(!kacpi_notify_wq); |
199 | BUG_ON(!kacpi_hotplug_wq); | ||
197 | return AE_OK; | 200 | return AE_OK; |
198 | } | 201 | } |
199 | 202 | ||
@@ -206,6 +209,7 @@ acpi_status acpi_os_terminate(void) | |||
206 | 209 | ||
207 | destroy_workqueue(kacpid_wq); | 210 | destroy_workqueue(kacpid_wq); |
208 | destroy_workqueue(kacpi_notify_wq); | 211 | destroy_workqueue(kacpi_notify_wq); |
212 | destroy_workqueue(kacpi_hotplug_wq); | ||
209 | 213 | ||
210 | return AE_OK; | 214 | return AE_OK; |
211 | } | 215 | } |
@@ -716,6 +720,7 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, | |||
716 | acpi_status status = AE_OK; | 720 | acpi_status status = AE_OK; |
717 | struct acpi_os_dpc *dpc; | 721 | struct acpi_os_dpc *dpc; |
718 | struct workqueue_struct *queue; | 722 | struct workqueue_struct *queue; |
723 | work_func_t func; | ||
719 | int ret; | 724 | int ret; |
720 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | 725 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
721 | "Scheduling function [%p(%p)] for deferred execution.\n", | 726 | "Scheduling function [%p(%p)] for deferred execution.\n", |
@@ -740,15 +745,17 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, | |||
740 | dpc->function = function; | 745 | dpc->function = function; |
741 | dpc->context = context; | 746 | dpc->context = context; |
742 | 747 | ||
743 | if (!hp) { | 748 | /* |
744 | INIT_WORK(&dpc->work, acpi_os_execute_deferred); | 749 | * We can't run hotplug code in keventd_wq/kacpid_wq/kacpid_notify_wq |
745 | queue = (type == OSL_NOTIFY_HANDLER) ? | 750 | * because the hotplug code may call driver .remove() functions, |
746 | kacpi_notify_wq : kacpid_wq; | 751 | * which invoke flush_scheduled_work/acpi_os_wait_events_complete |
747 | ret = queue_work(queue, &dpc->work); | 752 | * to flush these workqueues. |
748 | } else { | 753 | */ |
749 | INIT_WORK(&dpc->work, acpi_os_execute_hp_deferred); | 754 | queue = hp ? kacpi_hotplug_wq : |
750 | ret = schedule_work(&dpc->work); | 755 | (type == OSL_NOTIFY_HANDLER ? kacpi_notify_wq : kacpid_wq); |
751 | } | 756 | func = hp ? acpi_os_execute_hp_deferred : acpi_os_execute_deferred; |
757 | INIT_WORK(&dpc->work, func); | ||
758 | ret = queue_work(queue, &dpc->work); | ||
752 | 759 | ||
753 | if (!ret) { | 760 | if (!ret) { |
754 | printk(KERN_ERR PREFIX | 761 | printk(KERN_ERR PREFIX |
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c index bc46de3d967f..a5a77b78a723 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c | |||
@@ -24,12 +24,7 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/module.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/types.h> | 27 | #include <linux/types.h> |
30 | #include <linux/proc_fs.h> | ||
31 | #include <linux/spinlock.h> | ||
32 | #include <linux/pm.h> | ||
33 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
34 | #include <linux/acpi.h> | 29 | #include <linux/acpi.h> |
35 | #include <acpi/acpi_bus.h> | 30 | #include <acpi/acpi_bus.h> |
@@ -38,310 +33,76 @@ | |||
38 | #define _COMPONENT ACPI_PCI_COMPONENT | 33 | #define _COMPONENT ACPI_PCI_COMPONENT |
39 | ACPI_MODULE_NAME("pci_bind"); | 34 | ACPI_MODULE_NAME("pci_bind"); |
40 | 35 | ||
41 | struct acpi_pci_data { | 36 | static int acpi_pci_unbind(struct acpi_device *device) |
42 | struct acpi_pci_id id; | ||
43 | struct pci_bus *bus; | ||
44 | struct pci_dev *dev; | ||
45 | }; | ||
46 | |||
47 | static int acpi_pci_unbind(struct acpi_device *device); | ||
48 | |||
49 | static void acpi_pci_data_handler(acpi_handle handle, u32 function, | ||
50 | void *context) | ||
51 | { | ||
52 | |||
53 | /* TBD: Anything we need to do here? */ | ||
54 | |||
55 | return; | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * acpi_get_pci_id | ||
60 | * ------------------ | ||
61 | * This function is used by the ACPI Interpreter (a.k.a. Core Subsystem) | ||
62 | * to resolve PCI information for ACPI-PCI devices defined in the namespace. | ||
63 | * This typically occurs when resolving PCI operation region information. | ||
64 | */ | ||
65 | acpi_status acpi_get_pci_id(acpi_handle handle, struct acpi_pci_id *id) | ||
66 | { | 37 | { |
67 | int result = 0; | 38 | struct pci_dev *dev; |
68 | acpi_status status = AE_OK; | ||
69 | struct acpi_device *device = NULL; | ||
70 | struct acpi_pci_data *data = NULL; | ||
71 | |||
72 | |||
73 | if (!id) | ||
74 | return AE_BAD_PARAMETER; | ||
75 | |||
76 | result = acpi_bus_get_device(handle, &device); | ||
77 | if (result) { | ||
78 | printk(KERN_ERR PREFIX | ||
79 | "Invalid ACPI Bus context for device %s\n", | ||
80 | acpi_device_bid(device)); | ||
81 | return AE_NOT_EXIST; | ||
82 | } | ||
83 | |||
84 | status = acpi_get_data(handle, acpi_pci_data_handler, (void **)&data); | ||
85 | if (ACPI_FAILURE(status) || !data) { | ||
86 | ACPI_EXCEPTION((AE_INFO, status, | ||
87 | "Invalid ACPI-PCI context for device %s", | ||
88 | acpi_device_bid(device))); | ||
89 | return status; | ||
90 | } | ||
91 | 39 | ||
92 | *id = data->id; | 40 | dev = acpi_get_pci_dev(device->handle); |
41 | if (!dev || !dev->subordinate) | ||
42 | goto out; | ||
93 | 43 | ||
94 | /* | 44 | acpi_pci_irq_del_prt(dev->subordinate); |
95 | id->segment = data->id.segment; | ||
96 | id->bus = data->id.bus; | ||
97 | id->device = data->id.device; | ||
98 | id->function = data->id.function; | ||
99 | */ | ||
100 | 45 | ||
101 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 46 | device->ops.bind = NULL; |
102 | "Device %s has PCI address %04x:%02x:%02x.%d\n", | 47 | device->ops.unbind = NULL; |
103 | acpi_device_bid(device), id->segment, id->bus, | ||
104 | id->device, id->function)); | ||
105 | 48 | ||
106 | return AE_OK; | 49 | out: |
50 | pci_dev_put(dev); | ||
51 | return 0; | ||
107 | } | 52 | } |
108 | 53 | ||
109 | EXPORT_SYMBOL(acpi_get_pci_id); | 54 | static int acpi_pci_bind(struct acpi_device *device) |
110 | |||
111 | int acpi_pci_bind(struct acpi_device *device) | ||
112 | { | 55 | { |
113 | int result = 0; | ||
114 | acpi_status status; | 56 | acpi_status status; |
115 | struct acpi_pci_data *data; | ||
116 | struct acpi_pci_data *pdata; | ||
117 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
118 | acpi_handle handle; | 57 | acpi_handle handle; |
58 | struct pci_bus *bus; | ||
59 | struct pci_dev *dev; | ||
119 | 60 | ||
120 | if (!device || !device->parent) | 61 | dev = acpi_get_pci_dev(device->handle); |
121 | return -EINVAL; | 62 | if (!dev) |
122 | 63 | return 0; | |
123 | data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); | ||
124 | if (!data) | ||
125 | return -ENOMEM; | ||
126 | |||
127 | status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); | ||
128 | if (ACPI_FAILURE(status)) { | ||
129 | kfree(data); | ||
130 | return -ENODEV; | ||
131 | } | ||
132 | |||
133 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n", | ||
134 | (char *)buffer.pointer)); | ||
135 | |||
136 | /* | ||
137 | * Segment & Bus | ||
138 | * ------------- | ||
139 | * These are obtained via the parent device's ACPI-PCI context. | ||
140 | */ | ||
141 | status = acpi_get_data(device->parent->handle, acpi_pci_data_handler, | ||
142 | (void **)&pdata); | ||
143 | if (ACPI_FAILURE(status) || !pdata || !pdata->bus) { | ||
144 | ACPI_EXCEPTION((AE_INFO, status, | ||
145 | "Invalid ACPI-PCI context for parent device %s", | ||
146 | acpi_device_bid(device->parent))); | ||
147 | result = -ENODEV; | ||
148 | goto end; | ||
149 | } | ||
150 | data->id.segment = pdata->id.segment; | ||
151 | data->id.bus = pdata->bus->number; | ||
152 | |||
153 | /* | ||
154 | * Device & Function | ||
155 | * ----------------- | ||
156 | * These are simply obtained from the device's _ADR method. Note | ||
157 | * that a value of zero is valid. | ||
158 | */ | ||
159 | data->id.device = device->pnp.bus_address >> 16; | ||
160 | data->id.function = device->pnp.bus_address & 0xFFFF; | ||
161 | |||
162 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %04x:%02x:%02x.%d\n", | ||
163 | data->id.segment, data->id.bus, data->id.device, | ||
164 | data->id.function)); | ||
165 | |||
166 | /* | ||
167 | * TBD: Support slot devices (e.g. function=0xFFFF). | ||
168 | */ | ||
169 | |||
170 | /* | ||
171 | * Locate PCI Device | ||
172 | * ----------------- | ||
173 | * Locate matching device in PCI namespace. If it doesn't exist | ||
174 | * this typically means that the device isn't currently inserted | ||
175 | * (e.g. docking station, port replicator, etc.). | ||
176 | */ | ||
177 | data->dev = pci_get_slot(pdata->bus, | ||
178 | PCI_DEVFN(data->id.device, data->id.function)); | ||
179 | if (!data->dev) { | ||
180 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
181 | "Device %04x:%02x:%02x.%d not present in PCI namespace\n", | ||
182 | data->id.segment, data->id.bus, | ||
183 | data->id.device, data->id.function)); | ||
184 | result = -ENODEV; | ||
185 | goto end; | ||
186 | } | ||
187 | if (!data->dev->bus) { | ||
188 | printk(KERN_ERR PREFIX | ||
189 | "Device %04x:%02x:%02x.%d has invalid 'bus' field\n", | ||
190 | data->id.segment, data->id.bus, | ||
191 | data->id.device, data->id.function); | ||
192 | result = -ENODEV; | ||
193 | goto end; | ||
194 | } | ||
195 | 64 | ||
196 | /* | 65 | /* |
197 | * PCI Bridge? | 66 | * Install the 'bind' function to facilitate callbacks for |
198 | * ----------- | 67 | * children of the P2P bridge. |
199 | * If so, set the 'bus' field and install the 'bind' function to | ||
200 | * facilitate callbacks for all of its children. | ||
201 | */ | 68 | */ |
202 | if (data->dev->subordinate) { | 69 | if (dev->subordinate) { |
203 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 70 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
204 | "Device %04x:%02x:%02x.%d is a PCI bridge\n", | 71 | "Device %04x:%02x:%02x.%d is a PCI bridge\n", |
205 | data->id.segment, data->id.bus, | 72 | pci_domain_nr(dev->bus), dev->bus->number, |
206 | data->id.device, data->id.function)); | 73 | PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn))); |
207 | data->bus = data->dev->subordinate; | ||
208 | device->ops.bind = acpi_pci_bind; | 74 | device->ops.bind = acpi_pci_bind; |
209 | device->ops.unbind = acpi_pci_unbind; | 75 | device->ops.unbind = acpi_pci_unbind; |
210 | } | 76 | } |
211 | 77 | ||
212 | /* | 78 | /* |
213 | * Attach ACPI-PCI Context | 79 | * Evaluate and parse _PRT, if exists. This code allows parsing of |
214 | * ----------------------- | 80 | * _PRT objects within the scope of non-bridge devices. Note that |
215 | * Thus binding the ACPI and PCI devices. | 81 | * _PRTs within the scope of a PCI bridge assume the bridge's |
216 | */ | 82 | * subordinate bus number. |
217 | status = acpi_attach_data(device->handle, acpi_pci_data_handler, data); | ||
218 | if (ACPI_FAILURE(status)) { | ||
219 | ACPI_EXCEPTION((AE_INFO, status, | ||
220 | "Unable to attach ACPI-PCI context to device %s", | ||
221 | acpi_device_bid(device))); | ||
222 | result = -ENODEV; | ||
223 | goto end; | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * PCI Routing Table | ||
228 | * ----------------- | ||
229 | * Evaluate and parse _PRT, if exists. This code is independent of | ||
230 | * PCI bridges (above) to allow parsing of _PRT objects within the | ||
231 | * scope of non-bridge devices. Note that _PRTs within the scope of | ||
232 | * a PCI bridge assume the bridge's subordinate bus number. | ||
233 | * | 83 | * |
234 | * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? | 84 | * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? |
235 | */ | 85 | */ |
236 | status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); | 86 | status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); |
237 | if (ACPI_SUCCESS(status)) { | ||
238 | if (data->bus) /* PCI-PCI bridge */ | ||
239 | acpi_pci_irq_add_prt(device->handle, data->id.segment, | ||
240 | data->bus->number); | ||
241 | else /* non-bridge PCI device */ | ||
242 | acpi_pci_irq_add_prt(device->handle, data->id.segment, | ||
243 | data->id.bus); | ||
244 | } | ||
245 | |||
246 | end: | ||
247 | kfree(buffer.pointer); | ||
248 | if (result) { | ||
249 | pci_dev_put(data->dev); | ||
250 | kfree(data); | ||
251 | } | ||
252 | return result; | ||
253 | } | ||
254 | |||
255 | static int acpi_pci_unbind(struct acpi_device *device) | ||
256 | { | ||
257 | int result = 0; | ||
258 | acpi_status status; | ||
259 | struct acpi_pci_data *data; | ||
260 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
261 | |||
262 | |||
263 | if (!device || !device->parent) | ||
264 | return -EINVAL; | ||
265 | |||
266 | status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); | ||
267 | if (ACPI_FAILURE(status)) | 87 | if (ACPI_FAILURE(status)) |
268 | return -ENODEV; | 88 | goto out; |
269 | 89 | ||
270 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unbinding PCI device [%s]...\n", | 90 | if (dev->subordinate) |
271 | (char *) buffer.pointer)); | 91 | bus = dev->subordinate; |
272 | kfree(buffer.pointer); | 92 | else |
93 | bus = dev->bus; | ||
273 | 94 | ||
274 | status = | 95 | acpi_pci_irq_add_prt(device->handle, bus); |
275 | acpi_get_data(device->handle, acpi_pci_data_handler, | ||
276 | (void **)&data); | ||
277 | if (ACPI_FAILURE(status)) { | ||
278 | result = -ENODEV; | ||
279 | goto end; | ||
280 | } | ||
281 | 96 | ||
282 | status = acpi_detach_data(device->handle, acpi_pci_data_handler); | 97 | out: |
283 | if (ACPI_FAILURE(status)) { | 98 | pci_dev_put(dev); |
284 | ACPI_EXCEPTION((AE_INFO, status, | 99 | return 0; |
285 | "Unable to detach data from device %s", | ||
286 | acpi_device_bid(device))); | ||
287 | result = -ENODEV; | ||
288 | goto end; | ||
289 | } | ||
290 | if (data->dev->subordinate) { | ||
291 | acpi_pci_irq_del_prt(data->id.segment, data->bus->number); | ||
292 | } | ||
293 | pci_dev_put(data->dev); | ||
294 | kfree(data); | ||
295 | |||
296 | end: | ||
297 | return result; | ||
298 | } | 100 | } |
299 | 101 | ||
300 | int | 102 | int acpi_pci_bind_root(struct acpi_device *device) |
301 | acpi_pci_bind_root(struct acpi_device *device, | ||
302 | struct acpi_pci_id *id, struct pci_bus *bus) | ||
303 | { | 103 | { |
304 | int result = 0; | ||
305 | acpi_status status; | ||
306 | struct acpi_pci_data *data = NULL; | ||
307 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
308 | |||
309 | if (!device || !id || !bus) { | ||
310 | return -EINVAL; | ||
311 | } | ||
312 | |||
313 | data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); | ||
314 | if (!data) | ||
315 | return -ENOMEM; | ||
316 | |||
317 | data->id = *id; | ||
318 | data->bus = bus; | ||
319 | device->ops.bind = acpi_pci_bind; | 104 | device->ops.bind = acpi_pci_bind; |
320 | device->ops.unbind = acpi_pci_unbind; | 105 | device->ops.unbind = acpi_pci_unbind; |
321 | 106 | ||
322 | status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); | 107 | return 0; |
323 | if (ACPI_FAILURE(status)) { | ||
324 | kfree (data); | ||
325 | return -ENODEV; | ||
326 | } | ||
327 | |||
328 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI root bridge [%s] to " | ||
329 | "%04x:%02x\n", (char *)buffer.pointer, | ||
330 | id->segment, id->bus)); | ||
331 | |||
332 | status = acpi_attach_data(device->handle, acpi_pci_data_handler, data); | ||
333 | if (ACPI_FAILURE(status)) { | ||
334 | ACPI_EXCEPTION((AE_INFO, status, | ||
335 | "Unable to attach ACPI-PCI context to device %s", | ||
336 | (char *)buffer.pointer)); | ||
337 | result = -ENODEV; | ||
338 | goto end; | ||
339 | } | ||
340 | |||
341 | end: | ||
342 | kfree(buffer.pointer); | ||
343 | if (result != 0) | ||
344 | kfree(data); | ||
345 | |||
346 | return result; | ||
347 | } | 108 | } |
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 2faa9e2ac893..b794eb88ab90 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c | |||
@@ -182,7 +182,7 @@ static void do_prt_fixups(struct acpi_prt_entry *entry, | |||
182 | } | 182 | } |
183 | } | 183 | } |
184 | 184 | ||
185 | static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, | 185 | static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus, |
186 | struct acpi_pci_routing_table *prt) | 186 | struct acpi_pci_routing_table *prt) |
187 | { | 187 | { |
188 | struct acpi_prt_entry *entry; | 188 | struct acpi_prt_entry *entry; |
@@ -196,8 +196,8 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, | |||
196 | * 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert | 196 | * 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert |
197 | * it here. | 197 | * it here. |
198 | */ | 198 | */ |
199 | entry->id.segment = segment; | 199 | entry->id.segment = pci_domain_nr(bus); |
200 | entry->id.bus = bus; | 200 | entry->id.bus = bus->number; |
201 | entry->id.device = (prt->address >> 16) & 0xFFFF; | 201 | entry->id.device = (prt->address >> 16) & 0xFFFF; |
202 | entry->pin = prt->pin + 1; | 202 | entry->pin = prt->pin + 1; |
203 | 203 | ||
@@ -242,7 +242,7 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, | |||
242 | return 0; | 242 | return 0; |
243 | } | 243 | } |
244 | 244 | ||
245 | int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) | 245 | int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus) |
246 | { | 246 | { |
247 | acpi_status status; | 247 | acpi_status status; |
248 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 248 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
@@ -271,7 +271,7 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) | |||
271 | 271 | ||
272 | entry = buffer.pointer; | 272 | entry = buffer.pointer; |
273 | while (entry && (entry->length > 0)) { | 273 | while (entry && (entry->length > 0)) { |
274 | acpi_pci_irq_add_entry(handle, segment, bus, entry); | 274 | acpi_pci_irq_add_entry(handle, bus, entry); |
275 | entry = (struct acpi_pci_routing_table *) | 275 | entry = (struct acpi_pci_routing_table *) |
276 | ((unsigned long)entry + entry->length); | 276 | ((unsigned long)entry + entry->length); |
277 | } | 277 | } |
@@ -280,16 +280,17 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) | |||
280 | return 0; | 280 | return 0; |
281 | } | 281 | } |
282 | 282 | ||
283 | void acpi_pci_irq_del_prt(int segment, int bus) | 283 | void acpi_pci_irq_del_prt(struct pci_bus *bus) |
284 | { | 284 | { |
285 | struct acpi_prt_entry *entry, *tmp; | 285 | struct acpi_prt_entry *entry, *tmp; |
286 | 286 | ||
287 | printk(KERN_DEBUG | 287 | printk(KERN_DEBUG |
288 | "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n", | 288 | "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n", |
289 | segment, bus); | 289 | pci_domain_nr(bus), bus->number); |
290 | spin_lock(&acpi_prt_lock); | 290 | spin_lock(&acpi_prt_lock); |
291 | list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) { | 291 | list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) { |
292 | if (segment == entry->id.segment && bus == entry->id.bus) { | 292 | if (pci_domain_nr(bus) == entry->id.segment |
293 | && bus->number == entry->id.bus) { | ||
293 | list_del(&entry->list); | 294 | list_del(&entry->list); |
294 | kfree(entry); | 295 | kfree(entry); |
295 | } | 296 | } |
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 196f97d00956..8a5bf3b356fa 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -63,9 +63,10 @@ static struct acpi_driver acpi_pci_root_driver = { | |||
63 | 63 | ||
64 | struct acpi_pci_root { | 64 | struct acpi_pci_root { |
65 | struct list_head node; | 65 | struct list_head node; |
66 | struct acpi_device * device; | 66 | struct acpi_device *device; |
67 | struct acpi_pci_id id; | ||
68 | struct pci_bus *bus; | 67 | struct pci_bus *bus; |
68 | u16 segment; | ||
69 | u8 bus_nr; | ||
69 | 70 | ||
70 | u32 osc_support_set; /* _OSC state of support bits */ | 71 | u32 osc_support_set; /* _OSC state of support bits */ |
71 | u32 osc_control_set; /* _OSC state of control bits */ | 72 | u32 osc_control_set; /* _OSC state of control bits */ |
@@ -82,7 +83,7 @@ static DEFINE_MUTEX(osc_lock); | |||
82 | int acpi_pci_register_driver(struct acpi_pci_driver *driver) | 83 | int acpi_pci_register_driver(struct acpi_pci_driver *driver) |
83 | { | 84 | { |
84 | int n = 0; | 85 | int n = 0; |
85 | struct list_head *entry; | 86 | struct acpi_pci_root *root; |
86 | 87 | ||
87 | struct acpi_pci_driver **pptr = &sub_driver; | 88 | struct acpi_pci_driver **pptr = &sub_driver; |
88 | while (*pptr) | 89 | while (*pptr) |
@@ -92,9 +93,7 @@ int acpi_pci_register_driver(struct acpi_pci_driver *driver) | |||
92 | if (!driver->add) | 93 | if (!driver->add) |
93 | return 0; | 94 | return 0; |
94 | 95 | ||
95 | list_for_each(entry, &acpi_pci_roots) { | 96 | list_for_each_entry(root, &acpi_pci_roots, node) { |
96 | struct acpi_pci_root *root; | ||
97 | root = list_entry(entry, struct acpi_pci_root, node); | ||
98 | driver->add(root->device->handle); | 97 | driver->add(root->device->handle); |
99 | n++; | 98 | n++; |
100 | } | 99 | } |
@@ -106,7 +105,7 @@ EXPORT_SYMBOL(acpi_pci_register_driver); | |||
106 | 105 | ||
107 | void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) | 106 | void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) |
108 | { | 107 | { |
109 | struct list_head *entry; | 108 | struct acpi_pci_root *root; |
110 | 109 | ||
111 | struct acpi_pci_driver **pptr = &sub_driver; | 110 | struct acpi_pci_driver **pptr = &sub_driver; |
112 | while (*pptr) { | 111 | while (*pptr) { |
@@ -120,28 +119,48 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) | |||
120 | if (!driver->remove) | 119 | if (!driver->remove) |
121 | return; | 120 | return; |
122 | 121 | ||
123 | list_for_each(entry, &acpi_pci_roots) { | 122 | list_for_each_entry(root, &acpi_pci_roots, node) |
124 | struct acpi_pci_root *root; | ||
125 | root = list_entry(entry, struct acpi_pci_root, node); | ||
126 | driver->remove(root->device->handle); | 123 | driver->remove(root->device->handle); |
127 | } | ||
128 | } | 124 | } |
129 | 125 | ||
130 | EXPORT_SYMBOL(acpi_pci_unregister_driver); | 126 | EXPORT_SYMBOL(acpi_pci_unregister_driver); |
131 | 127 | ||
132 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) | 128 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) |
133 | { | 129 | { |
134 | struct acpi_pci_root *tmp; | 130 | struct acpi_pci_root *root; |
135 | 131 | ||
136 | list_for_each_entry(tmp, &acpi_pci_roots, node) { | 132 | list_for_each_entry(root, &acpi_pci_roots, node) |
137 | if ((tmp->id.segment == (u16) seg) && (tmp->id.bus == (u16) bus)) | 133 | if ((root->segment == (u16) seg) && (root->bus_nr == (u16) bus)) |
138 | return tmp->device->handle; | 134 | return root->device->handle; |
139 | } | ||
140 | return NULL; | 135 | return NULL; |
141 | } | 136 | } |
142 | 137 | ||
143 | EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); | 138 | EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); |
144 | 139 | ||
140 | /** | ||
141 | * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge | ||
142 | * @handle - the ACPI CA node in question. | ||
143 | * | ||
144 | * Note: we could make this API take a struct acpi_device * instead, but | ||
145 | * for now, it's more convenient to operate on an acpi_handle. | ||
146 | */ | ||
147 | int acpi_is_root_bridge(acpi_handle handle) | ||
148 | { | ||
149 | int ret; | ||
150 | struct acpi_device *device; | ||
151 | |||
152 | ret = acpi_bus_get_device(handle, &device); | ||
153 | if (ret) | ||
154 | return 0; | ||
155 | |||
156 | ret = acpi_match_device_ids(device, root_device_ids); | ||
157 | if (ret) | ||
158 | return 0; | ||
159 | else | ||
160 | return 1; | ||
161 | } | ||
162 | EXPORT_SYMBOL_GPL(acpi_is_root_bridge); | ||
163 | |||
145 | static acpi_status | 164 | static acpi_status |
146 | get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) | 165 | get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) |
147 | { | 166 | { |
@@ -161,19 +180,22 @@ get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) | |||
161 | return AE_OK; | 180 | return AE_OK; |
162 | } | 181 | } |
163 | 182 | ||
164 | static acpi_status try_get_root_bridge_busnr(acpi_handle handle, int *busnum) | 183 | static acpi_status try_get_root_bridge_busnr(acpi_handle handle, |
184 | unsigned long long *bus) | ||
165 | { | 185 | { |
166 | acpi_status status; | 186 | acpi_status status; |
187 | int busnum; | ||
167 | 188 | ||
168 | *busnum = -1; | 189 | busnum = -1; |
169 | status = | 190 | status = |
170 | acpi_walk_resources(handle, METHOD_NAME__CRS, | 191 | acpi_walk_resources(handle, METHOD_NAME__CRS, |
171 | get_root_bridge_busnr_callback, busnum); | 192 | get_root_bridge_busnr_callback, &busnum); |
172 | if (ACPI_FAILURE(status)) | 193 | if (ACPI_FAILURE(status)) |
173 | return status; | 194 | return status; |
174 | /* Check if we really get a bus number from _CRS */ | 195 | /* Check if we really get a bus number from _CRS */ |
175 | if (*busnum == -1) | 196 | if (busnum == -1) |
176 | return AE_ERROR; | 197 | return AE_ERROR; |
198 | *bus = busnum; | ||
177 | return AE_OK; | 199 | return AE_OK; |
178 | } | 200 | } |
179 | 201 | ||
@@ -298,6 +320,7 @@ static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags) | |||
298 | static struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle) | 320 | static struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle) |
299 | { | 321 | { |
300 | struct acpi_pci_root *root; | 322 | struct acpi_pci_root *root; |
323 | |||
301 | list_for_each_entry(root, &acpi_pci_roots, node) { | 324 | list_for_each_entry(root, &acpi_pci_roots, node) { |
302 | if (root->device->handle == handle) | 325 | if (root->device->handle == handle) |
303 | return root; | 326 | return root; |
@@ -305,6 +328,87 @@ static struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle) | |||
305 | return NULL; | 328 | return NULL; |
306 | } | 329 | } |
307 | 330 | ||
331 | struct acpi_handle_node { | ||
332 | struct list_head node; | ||
333 | acpi_handle handle; | ||
334 | }; | ||
335 | |||
336 | /** | ||
337 | * acpi_get_pci_dev - convert ACPI CA handle to struct pci_dev | ||
338 | * @handle: the handle in question | ||
339 | * | ||
340 | * Given an ACPI CA handle, the desired PCI device is located in the | ||
341 | * list of PCI devices. | ||
342 | * | ||
343 | * If the device is found, its reference count is increased and this | ||
344 | * function returns a pointer to its data structure. The caller must | ||
345 | * decrement the reference count by calling pci_dev_put(). | ||
346 | * If no device is found, %NULL is returned. | ||
347 | */ | ||
348 | struct pci_dev *acpi_get_pci_dev(acpi_handle handle) | ||
349 | { | ||
350 | int dev, fn; | ||
351 | unsigned long long adr; | ||
352 | acpi_status status; | ||
353 | acpi_handle phandle; | ||
354 | struct pci_bus *pbus; | ||
355 | struct pci_dev *pdev = NULL; | ||
356 | struct acpi_handle_node *node, *tmp; | ||
357 | struct acpi_pci_root *root; | ||
358 | LIST_HEAD(device_list); | ||
359 | |||
360 | /* | ||
361 | * Walk up the ACPI CA namespace until we reach a PCI root bridge. | ||
362 | */ | ||
363 | phandle = handle; | ||
364 | while (!acpi_is_root_bridge(phandle)) { | ||
365 | node = kzalloc(sizeof(struct acpi_handle_node), GFP_KERNEL); | ||
366 | if (!node) | ||
367 | goto out; | ||
368 | |||
369 | INIT_LIST_HEAD(&node->node); | ||
370 | node->handle = phandle; | ||
371 | list_add(&node->node, &device_list); | ||
372 | |||
373 | status = acpi_get_parent(phandle, &phandle); | ||
374 | if (ACPI_FAILURE(status)) | ||
375 | goto out; | ||
376 | } | ||
377 | |||
378 | root = acpi_pci_find_root(phandle); | ||
379 | if (!root) | ||
380 | goto out; | ||
381 | |||
382 | pbus = root->bus; | ||
383 | |||
384 | /* | ||
385 | * Now, walk back down the PCI device tree until we return to our | ||
386 | * original handle. Assumes that everything between the PCI root | ||
387 | * bridge and the device we're looking for must be a P2P bridge. | ||
388 | */ | ||
389 | list_for_each_entry(node, &device_list, node) { | ||
390 | acpi_handle hnd = node->handle; | ||
391 | status = acpi_evaluate_integer(hnd, "_ADR", NULL, &adr); | ||
392 | if (ACPI_FAILURE(status)) | ||
393 | goto out; | ||
394 | dev = (adr >> 16) & 0xffff; | ||
395 | fn = adr & 0xffff; | ||
396 | |||
397 | pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn)); | ||
398 | if (hnd == handle) | ||
399 | break; | ||
400 | |||
401 | pbus = pdev->subordinate; | ||
402 | pci_dev_put(pdev); | ||
403 | } | ||
404 | out: | ||
405 | list_for_each_entry_safe(node, tmp, &device_list, node) | ||
406 | kfree(node); | ||
407 | |||
408 | return pdev; | ||
409 | } | ||
410 | EXPORT_SYMBOL_GPL(acpi_get_pci_dev); | ||
411 | |||
308 | /** | 412 | /** |
309 | * acpi_pci_osc_control_set - commit requested control to Firmware | 413 | * acpi_pci_osc_control_set - commit requested control to Firmware |
310 | * @handle: acpi_handle for the target ACPI object | 414 | * @handle: acpi_handle for the target ACPI object |
@@ -363,31 +467,46 @@ EXPORT_SYMBOL(acpi_pci_osc_control_set); | |||
363 | 467 | ||
364 | static int __devinit acpi_pci_root_add(struct acpi_device *device) | 468 | static int __devinit acpi_pci_root_add(struct acpi_device *device) |
365 | { | 469 | { |
366 | int result = 0; | 470 | unsigned long long segment, bus; |
367 | struct acpi_pci_root *root = NULL; | 471 | acpi_status status; |
368 | struct acpi_pci_root *tmp; | 472 | int result; |
369 | acpi_status status = AE_OK; | 473 | struct acpi_pci_root *root; |
370 | unsigned long long value = 0; | 474 | acpi_handle handle; |
371 | acpi_handle handle = NULL; | ||
372 | struct acpi_device *child; | 475 | struct acpi_device *child; |
373 | u32 flags, base_flags; | 476 | u32 flags, base_flags; |
374 | 477 | ||
478 | segment = 0; | ||
479 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL, | ||
480 | &segment); | ||
481 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
482 | printk(KERN_ERR PREFIX "can't evaluate _SEG\n"); | ||
483 | return -ENODEV; | ||
484 | } | ||
375 | 485 | ||
376 | if (!device) | 486 | /* Check _CRS first, then _BBN. If no _BBN, default to zero. */ |
377 | return -EINVAL; | 487 | bus = 0; |
488 | status = try_get_root_bridge_busnr(device->handle, &bus); | ||
489 | if (ACPI_FAILURE(status)) { | ||
490 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, &bus); | ||
491 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
492 | printk(KERN_ERR PREFIX | ||
493 | "no bus number in _CRS and can't evaluate _BBN\n"); | ||
494 | return -ENODEV; | ||
495 | } | ||
496 | } | ||
378 | 497 | ||
379 | root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); | 498 | root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); |
380 | if (!root) | 499 | if (!root) |
381 | return -ENOMEM; | 500 | return -ENOMEM; |
382 | INIT_LIST_HEAD(&root->node); | ||
383 | 501 | ||
502 | INIT_LIST_HEAD(&root->node); | ||
384 | root->device = device; | 503 | root->device = device; |
504 | root->segment = segment & 0xFFFF; | ||
505 | root->bus_nr = bus & 0xFF; | ||
385 | strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); | 506 | strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); |
386 | strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); | 507 | strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); |
387 | device->driver_data = root; | 508 | device->driver_data = root; |
388 | 509 | ||
389 | device->ops.bind = acpi_pci_bind; | ||
390 | |||
391 | /* | 510 | /* |
392 | * All supported architectures that use ACPI have support for | 511 | * All supported architectures that use ACPI have support for |
393 | * PCI domains, so we indicate this in _OSC support capabilities. | 512 | * PCI domains, so we indicate this in _OSC support capabilities. |
@@ -395,79 +514,6 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
395 | flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; | 514 | flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; |
396 | acpi_pci_osc_support(root, flags); | 515 | acpi_pci_osc_support(root, flags); |
397 | 516 | ||
398 | /* | ||
399 | * Segment | ||
400 | * ------- | ||
401 | * Obtained via _SEG, if exists, otherwise assumed to be zero (0). | ||
402 | */ | ||
403 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL, | ||
404 | &value); | ||
405 | switch (status) { | ||
406 | case AE_OK: | ||
407 | root->id.segment = (u16) value; | ||
408 | break; | ||
409 | case AE_NOT_FOUND: | ||
410 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
411 | "Assuming segment 0 (no _SEG)\n")); | ||
412 | root->id.segment = 0; | ||
413 | break; | ||
414 | default: | ||
415 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _SEG")); | ||
416 | result = -ENODEV; | ||
417 | goto end; | ||
418 | } | ||
419 | |||
420 | /* | ||
421 | * Bus | ||
422 | * --- | ||
423 | * Obtained via _BBN, if exists, otherwise assumed to be zero (0). | ||
424 | */ | ||
425 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, | ||
426 | &value); | ||
427 | switch (status) { | ||
428 | case AE_OK: | ||
429 | root->id.bus = (u16) value; | ||
430 | break; | ||
431 | case AE_NOT_FOUND: | ||
432 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Assuming bus 0 (no _BBN)\n")); | ||
433 | root->id.bus = 0; | ||
434 | break; | ||
435 | default: | ||
436 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BBN")); | ||
437 | result = -ENODEV; | ||
438 | goto end; | ||
439 | } | ||
440 | |||
441 | /* Some systems have wrong _BBN */ | ||
442 | list_for_each_entry(tmp, &acpi_pci_roots, node) { | ||
443 | if ((tmp->id.segment == root->id.segment) | ||
444 | && (tmp->id.bus == root->id.bus)) { | ||
445 | int bus = 0; | ||
446 | acpi_status status; | ||
447 | |||
448 | printk(KERN_ERR PREFIX | ||
449 | "Wrong _BBN value, reboot" | ||
450 | " and use option 'pci=noacpi'\n"); | ||
451 | |||
452 | status = try_get_root_bridge_busnr(device->handle, &bus); | ||
453 | if (ACPI_FAILURE(status)) | ||
454 | break; | ||
455 | if (bus != root->id.bus) { | ||
456 | printk(KERN_INFO PREFIX | ||
457 | "PCI _CRS %d overrides _BBN 0\n", bus); | ||
458 | root->id.bus = bus; | ||
459 | } | ||
460 | break; | ||
461 | } | ||
462 | } | ||
463 | /* | ||
464 | * Device & Function | ||
465 | * ----------------- | ||
466 | * Obtained from _ADR (which has already been evaluated for us). | ||
467 | */ | ||
468 | root->id.device = device->pnp.bus_address >> 16; | ||
469 | root->id.function = device->pnp.bus_address & 0xFFFF; | ||
470 | |||
471 | /* | 517 | /* |
472 | * TBD: Need PCI interface for enumeration/configuration of roots. | 518 | * TBD: Need PCI interface for enumeration/configuration of roots. |
473 | */ | 519 | */ |
@@ -477,7 +523,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
477 | 523 | ||
478 | printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n", | 524 | printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n", |
479 | acpi_device_name(device), acpi_device_bid(device), | 525 | acpi_device_name(device), acpi_device_bid(device), |
480 | root->id.segment, root->id.bus); | 526 | root->segment, root->bus_nr); |
481 | 527 | ||
482 | /* | 528 | /* |
483 | * Scan the Root Bridge | 529 | * Scan the Root Bridge |
@@ -486,11 +532,11 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
486 | * PCI namespace does not get created until this call is made (and | 532 | * PCI namespace does not get created until this call is made (and |
487 | * thus the root bridge's pci_dev does not exist). | 533 | * thus the root bridge's pci_dev does not exist). |
488 | */ | 534 | */ |
489 | root->bus = pci_acpi_scan_root(device, root->id.segment, root->id.bus); | 535 | root->bus = pci_acpi_scan_root(device, segment, bus); |
490 | if (!root->bus) { | 536 | if (!root->bus) { |
491 | printk(KERN_ERR PREFIX | 537 | printk(KERN_ERR PREFIX |
492 | "Bus %04x:%02x not present in PCI namespace\n", | 538 | "Bus %04x:%02x not present in PCI namespace\n", |
493 | root->id.segment, root->id.bus); | 539 | root->segment, root->bus_nr); |
494 | result = -ENODEV; | 540 | result = -ENODEV; |
495 | goto end; | 541 | goto end; |
496 | } | 542 | } |
@@ -500,7 +546,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
500 | * ----------------------- | 546 | * ----------------------- |
501 | * Thus binding the ACPI and PCI devices. | 547 | * Thus binding the ACPI and PCI devices. |
502 | */ | 548 | */ |
503 | result = acpi_pci_bind_root(device, &root->id, root->bus); | 549 | result = acpi_pci_bind_root(device); |
504 | if (result) | 550 | if (result) |
505 | goto end; | 551 | goto end; |
506 | 552 | ||
@@ -511,8 +557,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
511 | */ | 557 | */ |
512 | status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); | 558 | status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); |
513 | if (ACPI_SUCCESS(status)) | 559 | if (ACPI_SUCCESS(status)) |
514 | result = acpi_pci_irq_add_prt(device->handle, root->id.segment, | 560 | result = acpi_pci_irq_add_prt(device->handle, root->bus); |
515 | root->id.bus); | ||
516 | 561 | ||
517 | /* | 562 | /* |
518 | * Scan and bind all _ADR-Based Devices | 563 | * Scan and bind all _ADR-Based Devices |
@@ -531,42 +576,28 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
531 | if (flags != base_flags) | 576 | if (flags != base_flags) |
532 | acpi_pci_osc_support(root, flags); | 577 | acpi_pci_osc_support(root, flags); |
533 | 578 | ||
534 | end: | 579 | return 0; |
535 | if (result) { | ||
536 | if (!list_empty(&root->node)) | ||
537 | list_del(&root->node); | ||
538 | kfree(root); | ||
539 | } | ||
540 | 580 | ||
581 | end: | ||
582 | if (!list_empty(&root->node)) | ||
583 | list_del(&root->node); | ||
584 | kfree(root); | ||
541 | return result; | 585 | return result; |
542 | } | 586 | } |
543 | 587 | ||
544 | static int acpi_pci_root_start(struct acpi_device *device) | 588 | static int acpi_pci_root_start(struct acpi_device *device) |
545 | { | 589 | { |
546 | struct acpi_pci_root *root; | 590 | struct acpi_pci_root *root = acpi_driver_data(device); |
547 | 591 | ||
548 | 592 | pci_bus_add_devices(root->bus); | |
549 | list_for_each_entry(root, &acpi_pci_roots, node) { | 593 | return 0; |
550 | if (root->device == device) { | ||
551 | pci_bus_add_devices(root->bus); | ||
552 | return 0; | ||
553 | } | ||
554 | } | ||
555 | return -ENODEV; | ||
556 | } | 594 | } |
557 | 595 | ||
558 | static int acpi_pci_root_remove(struct acpi_device *device, int type) | 596 | static int acpi_pci_root_remove(struct acpi_device *device, int type) |
559 | { | 597 | { |
560 | struct acpi_pci_root *root = NULL; | 598 | struct acpi_pci_root *root = acpi_driver_data(device); |
561 | |||
562 | |||
563 | if (!device || !acpi_driver_data(device)) | ||
564 | return -EINVAL; | ||
565 | |||
566 | root = acpi_driver_data(device); | ||
567 | 599 | ||
568 | kfree(root); | 600 | kfree(root); |
569 | |||
570 | return 0; | 601 | return 0; |
571 | } | 602 | } |
572 | 603 | ||
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 56665a63bf19..d74365d4a6e7 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
@@ -194,7 +194,7 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) | |||
194 | 194 | ||
195 | static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) | 195 | static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) |
196 | { | 196 | { |
197 | int result = 0, state; | 197 | int result = 0; |
198 | int found = 0; | 198 | int found = 0; |
199 | acpi_status status = AE_OK; | 199 | acpi_status status = AE_OK; |
200 | struct acpi_power_resource *resource = NULL; | 200 | struct acpi_power_resource *resource = NULL; |
@@ -236,18 +236,6 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) | |||
236 | if (ACPI_FAILURE(status)) | 236 | if (ACPI_FAILURE(status)) |
237 | return -ENODEV; | 237 | return -ENODEV; |
238 | 238 | ||
239 | if (!acpi_power_nocheck) { | ||
240 | /* | ||
241 | * If acpi_power_nocheck is set, it is unnecessary to check | ||
242 | * the power state after power transition. | ||
243 | */ | ||
244 | result = acpi_power_get_state(resource->device->handle, | ||
245 | &state); | ||
246 | if (result) | ||
247 | return result; | ||
248 | if (state != ACPI_POWER_RESOURCE_STATE_ON) | ||
249 | return -ENOEXEC; | ||
250 | } | ||
251 | /* Update the power resource's _device_ power state */ | 239 | /* Update the power resource's _device_ power state */ |
252 | resource->device->power.state = ACPI_STATE_D0; | 240 | resource->device->power.state = ACPI_STATE_D0; |
253 | 241 | ||
@@ -258,7 +246,7 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) | |||
258 | 246 | ||
259 | static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) | 247 | static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) |
260 | { | 248 | { |
261 | int result = 0, state; | 249 | int result = 0; |
262 | acpi_status status = AE_OK; | 250 | acpi_status status = AE_OK; |
263 | struct acpi_power_resource *resource = NULL; | 251 | struct acpi_power_resource *resource = NULL; |
264 | struct list_head *node, *next; | 252 | struct list_head *node, *next; |
@@ -293,18 +281,6 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) | |||
293 | if (ACPI_FAILURE(status)) | 281 | if (ACPI_FAILURE(status)) |
294 | return -ENODEV; | 282 | return -ENODEV; |
295 | 283 | ||
296 | if (!acpi_power_nocheck) { | ||
297 | /* | ||
298 | * If acpi_power_nocheck is set, it is unnecessary to check | ||
299 | * the power state after power transition. | ||
300 | */ | ||
301 | result = acpi_power_get_state(handle, &state); | ||
302 | if (result) | ||
303 | return result; | ||
304 | if (state != ACPI_POWER_RESOURCE_STATE_OFF) | ||
305 | return -ENOEXEC; | ||
306 | } | ||
307 | |||
308 | /* Update the power resource's _device_ power state */ | 284 | /* Update the power resource's _device_ power state */ |
309 | resource->device->power.state = ACPI_STATE_D3; | 285 | resource->device->power.state = ACPI_STATE_D3; |
310 | 286 | ||
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 23f0fb84f1c1..84e0f3c07442 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
@@ -89,7 +89,7 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr); | |||
89 | 89 | ||
90 | static const struct acpi_device_id processor_device_ids[] = { | 90 | static const struct acpi_device_id processor_device_ids[] = { |
91 | {ACPI_PROCESSOR_OBJECT_HID, 0}, | 91 | {ACPI_PROCESSOR_OBJECT_HID, 0}, |
92 | {ACPI_PROCESSOR_HID, 0}, | 92 | {"ACPI0007", 0}, |
93 | {"", 0}, | 93 | {"", 0}, |
94 | }; | 94 | }; |
95 | MODULE_DEVICE_TABLE(acpi, processor_device_ids); | 95 | MODULE_DEVICE_TABLE(acpi, processor_device_ids); |
@@ -596,7 +596,21 @@ static int acpi_processor_get_info(struct acpi_device *device) | |||
596 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 596 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
597 | "No bus mastering arbitration control\n")); | 597 | "No bus mastering arbitration control\n")); |
598 | 598 | ||
599 | if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_HID)) { | 599 | if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_OBJECT_HID)) { |
600 | /* Declared with "Processor" statement; match ProcessorID */ | ||
601 | status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); | ||
602 | if (ACPI_FAILURE(status)) { | ||
603 | printk(KERN_ERR PREFIX "Evaluating processor object\n"); | ||
604 | return -ENODEV; | ||
605 | } | ||
606 | |||
607 | /* | ||
608 | * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. | ||
609 | * >>> 'acpi_get_processor_id(acpi_id, &id)' in | ||
610 | * arch/xxx/acpi.c | ||
611 | */ | ||
612 | pr->acpi_id = object.processor.proc_id; | ||
613 | } else { | ||
600 | /* | 614 | /* |
601 | * Declared with "Device" statement; match _UID. | 615 | * Declared with "Device" statement; match _UID. |
602 | * Note that we don't handle string _UIDs yet. | 616 | * Note that we don't handle string _UIDs yet. |
@@ -611,20 +625,6 @@ static int acpi_processor_get_info(struct acpi_device *device) | |||
611 | } | 625 | } |
612 | device_declaration = 1; | 626 | device_declaration = 1; |
613 | pr->acpi_id = value; | 627 | pr->acpi_id = value; |
614 | } else { | ||
615 | /* Declared with "Processor" statement; match ProcessorID */ | ||
616 | status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); | ||
617 | if (ACPI_FAILURE(status)) { | ||
618 | printk(KERN_ERR PREFIX "Evaluating processor object\n"); | ||
619 | return -ENODEV; | ||
620 | } | ||
621 | |||
622 | /* | ||
623 | * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. | ||
624 | * >>> 'acpi_get_processor_id(acpi_id, &id)' in | ||
625 | * arch/xxx/acpi.c | ||
626 | */ | ||
627 | pr->acpi_id = object.processor.proc_id; | ||
628 | } | 628 | } |
629 | cpu_index = get_cpu_id(pr->handle, device_declaration, pr->acpi_id); | 629 | cpu_index = get_cpu_id(pr->handle, device_declaration, pr->acpi_id); |
630 | 630 | ||
@@ -649,7 +649,16 @@ static int acpi_processor_get_info(struct acpi_device *device) | |||
649 | return -ENODEV; | 649 | return -ENODEV; |
650 | } | 650 | } |
651 | } | 651 | } |
652 | 652 | /* | |
653 | * On some boxes several processors use the same processor bus id. | ||
654 | * But they are located in different scope. For example: | ||
655 | * \_SB.SCK0.CPU0 | ||
656 | * \_SB.SCK1.CPU0 | ||
657 | * Rename the processor device bus id. And the new bus id will be | ||
658 | * generated as the following format: | ||
659 | * CPU+CPU ID. | ||
660 | */ | ||
661 | sprintf(acpi_device_bid(device), "CPU%X", pr->id); | ||
653 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id, | 662 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id, |
654 | pr->acpi_id)); | 663 | pr->acpi_id)); |
655 | 664 | ||
@@ -731,6 +740,8 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) | |||
731 | /* _PDC call should be done before doing anything else (if reqd.). */ | 740 | /* _PDC call should be done before doing anything else (if reqd.). */ |
732 | arch_acpi_processor_init_pdc(pr); | 741 | arch_acpi_processor_init_pdc(pr); |
733 | acpi_processor_set_pdc(pr); | 742 | acpi_processor_set_pdc(pr); |
743 | arch_acpi_processor_cleanup_pdc(pr); | ||
744 | |||
734 | #ifdef CONFIG_CPU_FREQ | 745 | #ifdef CONFIG_CPU_FREQ |
735 | acpi_processor_ppc_has_changed(pr); | 746 | acpi_processor_ppc_has_changed(pr); |
736 | #endif | 747 | #endif |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 10a2d913635a..0efa59e7e3af 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -139,7 +139,7 @@ static void acpi_safe_halt(void) | |||
139 | * are affected too. We pick the most conservative approach: we assume | 139 | * are affected too. We pick the most conservative approach: we assume |
140 | * that the local APIC stops in both C2 and C3. | 140 | * that the local APIC stops in both C2 and C3. |
141 | */ | 141 | */ |
142 | static void acpi_timer_check_state(int state, struct acpi_processor *pr, | 142 | static void lapic_timer_check_state(int state, struct acpi_processor *pr, |
143 | struct acpi_processor_cx *cx) | 143 | struct acpi_processor_cx *cx) |
144 | { | 144 | { |
145 | struct acpi_processor_power *pwr = &pr->power; | 145 | struct acpi_processor_power *pwr = &pr->power; |
@@ -162,7 +162,7 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr, | |||
162 | pr->power.timer_broadcast_on_state = state; | 162 | pr->power.timer_broadcast_on_state = state; |
163 | } | 163 | } |
164 | 164 | ||
165 | static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) | 165 | static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) |
166 | { | 166 | { |
167 | unsigned long reason; | 167 | unsigned long reason; |
168 | 168 | ||
@@ -173,7 +173,7 @@ static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) | |||
173 | } | 173 | } |
174 | 174 | ||
175 | /* Power(C) State timer broadcast control */ | 175 | /* Power(C) State timer broadcast control */ |
176 | static void acpi_state_timer_broadcast(struct acpi_processor *pr, | 176 | static void lapic_timer_state_broadcast(struct acpi_processor *pr, |
177 | struct acpi_processor_cx *cx, | 177 | struct acpi_processor_cx *cx, |
178 | int broadcast) | 178 | int broadcast) |
179 | { | 179 | { |
@@ -190,10 +190,10 @@ static void acpi_state_timer_broadcast(struct acpi_processor *pr, | |||
190 | 190 | ||
191 | #else | 191 | #else |
192 | 192 | ||
193 | static void acpi_timer_check_state(int state, struct acpi_processor *pr, | 193 | static void lapic_timer_check_state(int state, struct acpi_processor *pr, |
194 | struct acpi_processor_cx *cstate) { } | 194 | struct acpi_processor_cx *cstate) { } |
195 | static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) { } | 195 | static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) { } |
196 | static void acpi_state_timer_broadcast(struct acpi_processor *pr, | 196 | static void lapic_timer_state_broadcast(struct acpi_processor *pr, |
197 | struct acpi_processor_cx *cx, | 197 | struct acpi_processor_cx *cx, |
198 | int broadcast) | 198 | int broadcast) |
199 | { | 199 | { |
@@ -515,7 +515,8 @@ static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx) | |||
515 | static void acpi_processor_power_verify_c3(struct acpi_processor *pr, | 515 | static void acpi_processor_power_verify_c3(struct acpi_processor *pr, |
516 | struct acpi_processor_cx *cx) | 516 | struct acpi_processor_cx *cx) |
517 | { | 517 | { |
518 | static int bm_check_flag; | 518 | static int bm_check_flag = -1; |
519 | static int bm_control_flag = -1; | ||
519 | 520 | ||
520 | 521 | ||
521 | if (!cx->address) | 522 | if (!cx->address) |
@@ -545,12 +546,14 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, | |||
545 | } | 546 | } |
546 | 547 | ||
547 | /* All the logic here assumes flags.bm_check is same across all CPUs */ | 548 | /* All the logic here assumes flags.bm_check is same across all CPUs */ |
548 | if (!bm_check_flag) { | 549 | if (bm_check_flag == -1) { |
549 | /* Determine whether bm_check is needed based on CPU */ | 550 | /* Determine whether bm_check is needed based on CPU */ |
550 | acpi_processor_power_init_bm_check(&(pr->flags), pr->id); | 551 | acpi_processor_power_init_bm_check(&(pr->flags), pr->id); |
551 | bm_check_flag = pr->flags.bm_check; | 552 | bm_check_flag = pr->flags.bm_check; |
553 | bm_control_flag = pr->flags.bm_control; | ||
552 | } else { | 554 | } else { |
553 | pr->flags.bm_check = bm_check_flag; | 555 | pr->flags.bm_check = bm_check_flag; |
556 | pr->flags.bm_control = bm_control_flag; | ||
554 | } | 557 | } |
555 | 558 | ||
556 | if (pr->flags.bm_check) { | 559 | if (pr->flags.bm_check) { |
@@ -614,29 +617,25 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) | |||
614 | switch (cx->type) { | 617 | switch (cx->type) { |
615 | case ACPI_STATE_C1: | 618 | case ACPI_STATE_C1: |
616 | cx->valid = 1; | 619 | cx->valid = 1; |
617 | acpi_timer_check_state(i, pr, cx); | ||
618 | break; | 620 | break; |
619 | 621 | ||
620 | case ACPI_STATE_C2: | 622 | case ACPI_STATE_C2: |
621 | acpi_processor_power_verify_c2(cx); | 623 | acpi_processor_power_verify_c2(cx); |
622 | if (cx->valid) | ||
623 | acpi_timer_check_state(i, pr, cx); | ||
624 | break; | 624 | break; |
625 | 625 | ||
626 | case ACPI_STATE_C3: | 626 | case ACPI_STATE_C3: |
627 | acpi_processor_power_verify_c3(pr, cx); | 627 | acpi_processor_power_verify_c3(pr, cx); |
628 | if (cx->valid) | ||
629 | acpi_timer_check_state(i, pr, cx); | ||
630 | break; | 628 | break; |
631 | } | 629 | } |
632 | if (cx->valid) | 630 | if (!cx->valid) |
633 | tsc_check_state(cx->type); | 631 | continue; |
634 | 632 | ||
635 | if (cx->valid) | 633 | lapic_timer_check_state(i, pr, cx); |
636 | working++; | 634 | tsc_check_state(cx->type); |
635 | working++; | ||
637 | } | 636 | } |
638 | 637 | ||
639 | acpi_propagate_timer_broadcast(pr); | 638 | lapic_timer_propagate_broadcast(pr); |
640 | 639 | ||
641 | return (working); | 640 | return (working); |
642 | } | 641 | } |
@@ -839,7 +838,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, | |||
839 | return 0; | 838 | return 0; |
840 | } | 839 | } |
841 | 840 | ||
842 | acpi_state_timer_broadcast(pr, cx, 1); | 841 | lapic_timer_state_broadcast(pr, cx, 1); |
843 | kt1 = ktime_get_real(); | 842 | kt1 = ktime_get_real(); |
844 | acpi_idle_do_entry(cx); | 843 | acpi_idle_do_entry(cx); |
845 | kt2 = ktime_get_real(); | 844 | kt2 = ktime_get_real(); |
@@ -847,7 +846,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, | |||
847 | 846 | ||
848 | local_irq_enable(); | 847 | local_irq_enable(); |
849 | cx->usage++; | 848 | cx->usage++; |
850 | acpi_state_timer_broadcast(pr, cx, 0); | 849 | lapic_timer_state_broadcast(pr, cx, 0); |
851 | 850 | ||
852 | return idle_time; | 851 | return idle_time; |
853 | } | 852 | } |
@@ -892,7 +891,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
892 | * Must be done before busmaster disable as we might need to | 891 | * Must be done before busmaster disable as we might need to |
893 | * access HPET ! | 892 | * access HPET ! |
894 | */ | 893 | */ |
895 | acpi_state_timer_broadcast(pr, cx, 1); | 894 | lapic_timer_state_broadcast(pr, cx, 1); |
896 | 895 | ||
897 | if (cx->type == ACPI_STATE_C3) | 896 | if (cx->type == ACPI_STATE_C3) |
898 | ACPI_FLUSH_CPU_CACHE(); | 897 | ACPI_FLUSH_CPU_CACHE(); |
@@ -914,7 +913,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
914 | 913 | ||
915 | cx->usage++; | 914 | cx->usage++; |
916 | 915 | ||
917 | acpi_state_timer_broadcast(pr, cx, 0); | 916 | lapic_timer_state_broadcast(pr, cx, 0); |
918 | cx->time += sleep_ticks; | 917 | cx->time += sleep_ticks; |
919 | return idle_time; | 918 | return idle_time; |
920 | } | 919 | } |
@@ -981,7 +980,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
981 | * Must be done before busmaster disable as we might need to | 980 | * Must be done before busmaster disable as we might need to |
982 | * access HPET ! | 981 | * access HPET ! |
983 | */ | 982 | */ |
984 | acpi_state_timer_broadcast(pr, cx, 1); | 983 | lapic_timer_state_broadcast(pr, cx, 1); |
985 | 984 | ||
986 | kt1 = ktime_get_real(); | 985 | kt1 = ktime_get_real(); |
987 | /* | 986 | /* |
@@ -1026,7 +1025,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
1026 | 1025 | ||
1027 | cx->usage++; | 1026 | cx->usage++; |
1028 | 1027 | ||
1029 | acpi_state_timer_broadcast(pr, cx, 0); | 1028 | lapic_timer_state_broadcast(pr, cx, 0); |
1030 | cx->time += sleep_ticks; | 1029 | cx->time += sleep_ticks; |
1031 | return idle_time; | 1030 | return idle_time; |
1032 | } | 1031 | } |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 8ff510b91d88..781435d7e369 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -95,7 +95,7 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha | |||
95 | } | 95 | } |
96 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); | 96 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); |
97 | 97 | ||
98 | static int acpi_bus_hot_remove_device(void *context) | 98 | static void acpi_bus_hot_remove_device(void *context) |
99 | { | 99 | { |
100 | struct acpi_device *device; | 100 | struct acpi_device *device; |
101 | acpi_handle handle = context; | 101 | acpi_handle handle = context; |
@@ -104,10 +104,10 @@ static int acpi_bus_hot_remove_device(void *context) | |||
104 | acpi_status status = AE_OK; | 104 | acpi_status status = AE_OK; |
105 | 105 | ||
106 | if (acpi_bus_get_device(handle, &device)) | 106 | if (acpi_bus_get_device(handle, &device)) |
107 | return 0; | 107 | return; |
108 | 108 | ||
109 | if (!device) | 109 | if (!device) |
110 | return 0; | 110 | return; |
111 | 111 | ||
112 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 112 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
113 | "Hot-removing device %s...\n", dev_name(&device->dev))); | 113 | "Hot-removing device %s...\n", dev_name(&device->dev))); |
@@ -115,7 +115,7 @@ static int acpi_bus_hot_remove_device(void *context) | |||
115 | if (acpi_bus_trim(device, 1)) { | 115 | if (acpi_bus_trim(device, 1)) { |
116 | printk(KERN_ERR PREFIX | 116 | printk(KERN_ERR PREFIX |
117 | "Removing device failed\n"); | 117 | "Removing device failed\n"); |
118 | return -1; | 118 | return; |
119 | } | 119 | } |
120 | 120 | ||
121 | /* power off device */ | 121 | /* power off device */ |
@@ -142,9 +142,10 @@ static int acpi_bus_hot_remove_device(void *context) | |||
142 | */ | 142 | */ |
143 | status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); | 143 | status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); |
144 | if (ACPI_FAILURE(status)) | 144 | if (ACPI_FAILURE(status)) |
145 | return -ENODEV; | 145 | printk(KERN_WARNING PREFIX |
146 | "Eject device failed\n"); | ||
146 | 147 | ||
147 | return 0; | 148 | return; |
148 | } | 149 | } |
149 | 150 | ||
150 | static ssize_t | 151 | static ssize_t |
@@ -155,7 +156,6 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
155 | acpi_status status; | 156 | acpi_status status; |
156 | acpi_object_type type = 0; | 157 | acpi_object_type type = 0; |
157 | struct acpi_device *acpi_device = to_acpi_device(d); | 158 | struct acpi_device *acpi_device = to_acpi_device(d); |
158 | struct task_struct *task; | ||
159 | 159 | ||
160 | if ((!count) || (buf[0] != '1')) { | 160 | if ((!count) || (buf[0] != '1')) { |
161 | return -EINVAL; | 161 | return -EINVAL; |
@@ -172,11 +172,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
172 | goto err; | 172 | goto err; |
173 | } | 173 | } |
174 | 174 | ||
175 | /* remove the device in another thread to fix the deadlock issue */ | 175 | acpi_os_hotplug_execute(acpi_bus_hot_remove_device, acpi_device->handle); |
176 | task = kthread_run(acpi_bus_hot_remove_device, | ||
177 | acpi_device->handle, "acpi_hot_remove_device"); | ||
178 | if (IS_ERR(task)) | ||
179 | ret = PTR_ERR(task); | ||
180 | err: | 176 | err: |
181 | return ret; | 177 | return ret; |
182 | } | 178 | } |
@@ -198,12 +194,12 @@ acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *b | |||
198 | int result; | 194 | int result; |
199 | 195 | ||
200 | result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path); | 196 | result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path); |
201 | if(result) | 197 | if (result) |
202 | goto end; | 198 | goto end; |
203 | 199 | ||
204 | result = sprintf(buf, "%s\n", (char*)path.pointer); | 200 | result = sprintf(buf, "%s\n", (char*)path.pointer); |
205 | kfree(path.pointer); | 201 | kfree(path.pointer); |
206 | end: | 202 | end: |
207 | return result; | 203 | return result; |
208 | } | 204 | } |
209 | static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL); | 205 | static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL); |
@@ -217,21 +213,21 @@ static int acpi_device_setup_files(struct acpi_device *dev) | |||
217 | /* | 213 | /* |
218 | * Devices gotten from FADT don't have a "path" attribute | 214 | * Devices gotten from FADT don't have a "path" attribute |
219 | */ | 215 | */ |
220 | if(dev->handle) { | 216 | if (dev->handle) { |
221 | result = device_create_file(&dev->dev, &dev_attr_path); | 217 | result = device_create_file(&dev->dev, &dev_attr_path); |
222 | if(result) | 218 | if (result) |
223 | goto end; | 219 | goto end; |
224 | } | 220 | } |
225 | 221 | ||
226 | if(dev->flags.hardware_id) { | 222 | if (dev->flags.hardware_id) { |
227 | result = device_create_file(&dev->dev, &dev_attr_hid); | 223 | result = device_create_file(&dev->dev, &dev_attr_hid); |
228 | if(result) | 224 | if (result) |
229 | goto end; | 225 | goto end; |
230 | } | 226 | } |
231 | 227 | ||
232 | if (dev->flags.hardware_id || dev->flags.compatible_ids){ | 228 | if (dev->flags.hardware_id || dev->flags.compatible_ids) { |
233 | result = device_create_file(&dev->dev, &dev_attr_modalias); | 229 | result = device_create_file(&dev->dev, &dev_attr_modalias); |
234 | if(result) | 230 | if (result) |
235 | goto end; | 231 | goto end; |
236 | } | 232 | } |
237 | 233 | ||
@@ -242,7 +238,7 @@ static int acpi_device_setup_files(struct acpi_device *dev) | |||
242 | status = acpi_get_handle(dev->handle, "_EJ0", &temp); | 238 | status = acpi_get_handle(dev->handle, "_EJ0", &temp); |
243 | if (ACPI_SUCCESS(status)) | 239 | if (ACPI_SUCCESS(status)) |
244 | result = device_create_file(&dev->dev, &dev_attr_eject); | 240 | result = device_create_file(&dev->dev, &dev_attr_eject); |
245 | end: | 241 | end: |
246 | return result; | 242 | return result; |
247 | } | 243 | } |
248 | 244 | ||
@@ -262,9 +258,9 @@ static void acpi_device_remove_files(struct acpi_device *dev) | |||
262 | if (dev->flags.hardware_id || dev->flags.compatible_ids) | 258 | if (dev->flags.hardware_id || dev->flags.compatible_ids) |
263 | device_remove_file(&dev->dev, &dev_attr_modalias); | 259 | device_remove_file(&dev->dev, &dev_attr_modalias); |
264 | 260 | ||
265 | if(dev->flags.hardware_id) | 261 | if (dev->flags.hardware_id) |
266 | device_remove_file(&dev->dev, &dev_attr_hid); | 262 | device_remove_file(&dev->dev, &dev_attr_hid); |
267 | if(dev->handle) | 263 | if (dev->handle) |
268 | device_remove_file(&dev->dev, &dev_attr_path); | 264 | device_remove_file(&dev->dev, &dev_attr_path); |
269 | } | 265 | } |
270 | /* -------------------------------------------------------------------------- | 266 | /* -------------------------------------------------------------------------- |
@@ -512,7 +508,7 @@ static int acpi_device_register(struct acpi_device *device, | |||
512 | break; | 508 | break; |
513 | } | 509 | } |
514 | } | 510 | } |
515 | if(!found) { | 511 | if (!found) { |
516 | acpi_device_bus_id = new_bus_id; | 512 | acpi_device_bus_id = new_bus_id; |
517 | strcpy(acpi_device_bus_id->bus_id, device->flags.hardware_id ? device->pnp.hardware_id : "device"); | 513 | strcpy(acpi_device_bus_id->bus_id, device->flags.hardware_id ? device->pnp.hardware_id : "device"); |
518 | acpi_device_bus_id->instance_no = 0; | 514 | acpi_device_bus_id->instance_no = 0; |
@@ -530,22 +526,21 @@ static int acpi_device_register(struct acpi_device *device, | |||
530 | if (device->parent) | 526 | if (device->parent) |
531 | device->dev.parent = &parent->dev; | 527 | device->dev.parent = &parent->dev; |
532 | device->dev.bus = &acpi_bus_type; | 528 | device->dev.bus = &acpi_bus_type; |
533 | device_initialize(&device->dev); | ||
534 | device->dev.release = &acpi_device_release; | 529 | device->dev.release = &acpi_device_release; |
535 | result = device_add(&device->dev); | 530 | result = device_register(&device->dev); |
536 | if(result) { | 531 | if (result) { |
537 | dev_err(&device->dev, "Error adding device\n"); | 532 | dev_err(&device->dev, "Error registering device\n"); |
538 | goto end; | 533 | goto end; |
539 | } | 534 | } |
540 | 535 | ||
541 | result = acpi_device_setup_files(device); | 536 | result = acpi_device_setup_files(device); |
542 | if(result) | 537 | if (result) |
543 | printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n", | 538 | printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n", |
544 | dev_name(&device->dev)); | 539 | dev_name(&device->dev)); |
545 | 540 | ||
546 | device->removal_type = ACPI_BUS_REMOVAL_NORMAL; | 541 | device->removal_type = ACPI_BUS_REMOVAL_NORMAL; |
547 | return 0; | 542 | return 0; |
548 | end: | 543 | end: |
549 | mutex_lock(&acpi_device_lock); | 544 | mutex_lock(&acpi_device_lock); |
550 | if (device->parent) | 545 | if (device->parent) |
551 | list_del(&device->node); | 546 | list_del(&device->node); |
@@ -577,7 +572,7 @@ static void acpi_device_unregister(struct acpi_device *device, int type) | |||
577 | * @device: the device to add and initialize | 572 | * @device: the device to add and initialize |
578 | * @driver: driver for the device | 573 | * @driver: driver for the device |
579 | * | 574 | * |
580 | * Used to initialize a device via its device driver. Called whenever a | 575 | * Used to initialize a device via its device driver. Called whenever a |
581 | * driver is bound to a device. Invokes the driver's add() ops. | 576 | * driver is bound to a device. Invokes the driver's add() ops. |
582 | */ | 577 | */ |
583 | static int | 578 | static int |
@@ -585,7 +580,6 @@ acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver) | |||
585 | { | 580 | { |
586 | int result = 0; | 581 | int result = 0; |
587 | 582 | ||
588 | |||
589 | if (!device || !driver) | 583 | if (!device || !driver) |
590 | return -EINVAL; | 584 | return -EINVAL; |
591 | 585 | ||
@@ -802,7 +796,7 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | |||
802 | if (!acpi_match_device_ids(device, button_device_ids)) | 796 | if (!acpi_match_device_ids(device, button_device_ids)) |
803 | device->wakeup.flags.run_wake = 1; | 797 | device->wakeup.flags.run_wake = 1; |
804 | 798 | ||
805 | end: | 799 | end: |
806 | if (ACPI_FAILURE(status)) | 800 | if (ACPI_FAILURE(status)) |
807 | device->flags.wake_capable = 0; | 801 | device->flags.wake_capable = 0; |
808 | return 0; | 802 | return 0; |
@@ -1070,7 +1064,7 @@ static void acpi_device_set_id(struct acpi_device *device, | |||
1070 | break; | 1064 | break; |
1071 | } | 1065 | } |
1072 | 1066 | ||
1073 | /* | 1067 | /* |
1074 | * \_SB | 1068 | * \_SB |
1075 | * ---- | 1069 | * ---- |
1076 | * Fix for the system root bus device -- the only root-level device. | 1070 | * Fix for the system root bus device -- the only root-level device. |
@@ -1320,7 +1314,7 @@ acpi_add_single_object(struct acpi_device **child, | |||
1320 | device->parent->ops.bind(device); | 1314 | device->parent->ops.bind(device); |
1321 | } | 1315 | } |
1322 | 1316 | ||
1323 | end: | 1317 | end: |
1324 | if (!result) | 1318 | if (!result) |
1325 | *child = device; | 1319 | *child = device; |
1326 | else { | 1320 | else { |
@@ -1464,7 +1458,6 @@ acpi_bus_add(struct acpi_device **child, | |||
1464 | 1458 | ||
1465 | return result; | 1459 | return result; |
1466 | } | 1460 | } |
1467 | |||
1468 | EXPORT_SYMBOL(acpi_bus_add); | 1461 | EXPORT_SYMBOL(acpi_bus_add); |
1469 | 1462 | ||
1470 | int acpi_bus_start(struct acpi_device *device) | 1463 | int acpi_bus_start(struct acpi_device *device) |
@@ -1484,7 +1477,6 @@ int acpi_bus_start(struct acpi_device *device) | |||
1484 | } | 1477 | } |
1485 | return result; | 1478 | return result; |
1486 | } | 1479 | } |
1487 | |||
1488 | EXPORT_SYMBOL(acpi_bus_start); | 1480 | EXPORT_SYMBOL(acpi_bus_start); |
1489 | 1481 | ||
1490 | int acpi_bus_trim(struct acpi_device *start, int rmdevice) | 1482 | int acpi_bus_trim(struct acpi_device *start, int rmdevice) |
@@ -1542,7 +1534,6 @@ int acpi_bus_trim(struct acpi_device *start, int rmdevice) | |||
1542 | } | 1534 | } |
1543 | EXPORT_SYMBOL_GPL(acpi_bus_trim); | 1535 | EXPORT_SYMBOL_GPL(acpi_bus_trim); |
1544 | 1536 | ||
1545 | |||
1546 | static int acpi_bus_scan_fixed(struct acpi_device *root) | 1537 | static int acpi_bus_scan_fixed(struct acpi_device *root) |
1547 | { | 1538 | { |
1548 | int result = 0; | 1539 | int result = 0; |
@@ -1610,6 +1601,6 @@ int __init acpi_scan_init(void) | |||
1610 | if (result) | 1601 | if (result) |
1611 | acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); | 1602 | acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); |
1612 | 1603 | ||
1613 | Done: | 1604 | Done: |
1614 | return result; | 1605 | return result; |
1615 | } | 1606 | } |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 1bdfb37377e3..8851315ce858 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -76,6 +76,7 @@ MODULE_LICENSE("GPL"); | |||
76 | static int brightness_switch_enabled = 1; | 76 | static int brightness_switch_enabled = 1; |
77 | module_param(brightness_switch_enabled, bool, 0644); | 77 | module_param(brightness_switch_enabled, bool, 0644); |
78 | 78 | ||
79 | static int register_count = 0; | ||
79 | static int acpi_video_bus_add(struct acpi_device *device); | 80 | static int acpi_video_bus_add(struct acpi_device *device); |
80 | static int acpi_video_bus_remove(struct acpi_device *device, int type); | 81 | static int acpi_video_bus_remove(struct acpi_device *device, int type); |
81 | static int acpi_video_resume(struct acpi_device *device); | 82 | static int acpi_video_resume(struct acpi_device *device); |
@@ -586,6 +587,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { | |||
586 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"), | 587 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"), |
587 | }, | 588 | }, |
588 | }, | 589 | }, |
590 | { | ||
591 | .callback = video_set_bqc_offset, | ||
592 | .ident = "Acer Aspire 7720", | ||
593 | .matches = { | ||
594 | DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), | ||
595 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"), | ||
596 | }, | ||
597 | }, | ||
589 | {} | 598 | {} |
590 | }; | 599 | }; |
591 | 600 | ||
@@ -976,6 +985,11 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
976 | device->backlight->props.max_brightness = device->brightness->count-3; | 985 | device->backlight->props.max_brightness = device->brightness->count-3; |
977 | kfree(name); | 986 | kfree(name); |
978 | 987 | ||
988 | result = sysfs_create_link(&device->backlight->dev.kobj, | ||
989 | &device->dev->dev.kobj, "device"); | ||
990 | if (result) | ||
991 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | ||
992 | |||
979 | device->cdev = thermal_cooling_device_register("LCD", | 993 | device->cdev = thermal_cooling_device_register("LCD", |
980 | device->dev, &video_cooling_ops); | 994 | device->dev, &video_cooling_ops); |
981 | if (IS_ERR(device->cdev)) | 995 | if (IS_ERR(device->cdev)) |
@@ -1054,15 +1068,15 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video) | |||
1054 | static int acpi_video_bus_check(struct acpi_video_bus *video) | 1068 | static int acpi_video_bus_check(struct acpi_video_bus *video) |
1055 | { | 1069 | { |
1056 | acpi_status status = -ENOENT; | 1070 | acpi_status status = -ENOENT; |
1057 | struct device *dev; | 1071 | struct pci_dev *dev; |
1058 | 1072 | ||
1059 | if (!video) | 1073 | if (!video) |
1060 | return -EINVAL; | 1074 | return -EINVAL; |
1061 | 1075 | ||
1062 | dev = acpi_get_physical_pci_device(video->device->handle); | 1076 | dev = acpi_get_pci_dev(video->device->handle); |
1063 | if (!dev) | 1077 | if (!dev) |
1064 | return -ENODEV; | 1078 | return -ENODEV; |
1065 | put_device(dev); | 1079 | pci_dev_put(dev); |
1066 | 1080 | ||
1067 | /* Since there is no HID, CID and so on for VGA driver, we have | 1081 | /* Since there is no HID, CID and so on for VGA driver, we have |
1068 | * to check well known required nodes. | 1082 | * to check well known required nodes. |
@@ -1990,6 +2004,7 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) | |||
1990 | status = acpi_remove_notify_handler(device->dev->handle, | 2004 | status = acpi_remove_notify_handler(device->dev->handle, |
1991 | ACPI_DEVICE_NOTIFY, | 2005 | ACPI_DEVICE_NOTIFY, |
1992 | acpi_video_device_notify); | 2006 | acpi_video_device_notify); |
2007 | sysfs_remove_link(&device->backlight->dev.kobj, "device"); | ||
1993 | backlight_device_unregister(device->backlight); | 2008 | backlight_device_unregister(device->backlight); |
1994 | if (device->cdev) { | 2009 | if (device->cdev) { |
1995 | sysfs_remove_link(&device->dev->dev.kobj, | 2010 | sysfs_remove_link(&device->dev->dev.kobj, |
@@ -2318,6 +2333,13 @@ static int __init intel_opregion_present(void) | |||
2318 | int acpi_video_register(void) | 2333 | int acpi_video_register(void) |
2319 | { | 2334 | { |
2320 | int result = 0; | 2335 | int result = 0; |
2336 | if (register_count) { | ||
2337 | /* | ||
2338 | * if the function of acpi_video_register is already called, | ||
2339 | * don't register the acpi_vide_bus again and return no error. | ||
2340 | */ | ||
2341 | return 0; | ||
2342 | } | ||
2321 | 2343 | ||
2322 | acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); | 2344 | acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); |
2323 | if (!acpi_video_dir) | 2345 | if (!acpi_video_dir) |
@@ -2329,10 +2351,35 @@ int acpi_video_register(void) | |||
2329 | return -ENODEV; | 2351 | return -ENODEV; |
2330 | } | 2352 | } |
2331 | 2353 | ||
2354 | /* | ||
2355 | * When the acpi_video_bus is loaded successfully, increase | ||
2356 | * the counter reference. | ||
2357 | */ | ||
2358 | register_count = 1; | ||
2359 | |||
2332 | return 0; | 2360 | return 0; |
2333 | } | 2361 | } |
2334 | EXPORT_SYMBOL(acpi_video_register); | 2362 | EXPORT_SYMBOL(acpi_video_register); |
2335 | 2363 | ||
2364 | void acpi_video_unregister(void) | ||
2365 | { | ||
2366 | if (!register_count) { | ||
2367 | /* | ||
2368 | * If the acpi video bus is already unloaded, don't | ||
2369 | * unload it again and return directly. | ||
2370 | */ | ||
2371 | return; | ||
2372 | } | ||
2373 | acpi_bus_unregister_driver(&acpi_video_bus); | ||
2374 | |||
2375 | remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir); | ||
2376 | |||
2377 | register_count = 0; | ||
2378 | |||
2379 | return; | ||
2380 | } | ||
2381 | EXPORT_SYMBOL(acpi_video_unregister); | ||
2382 | |||
2336 | /* | 2383 | /* |
2337 | * This is kind of nasty. Hardware using Intel chipsets may require | 2384 | * This is kind of nasty. Hardware using Intel chipsets may require |
2338 | * the video opregion code to be run first in order to initialise | 2385 | * the video opregion code to be run first in order to initialise |
@@ -2350,16 +2397,12 @@ static int __init acpi_video_init(void) | |||
2350 | return acpi_video_register(); | 2397 | return acpi_video_register(); |
2351 | } | 2398 | } |
2352 | 2399 | ||
2353 | void acpi_video_exit(void) | 2400 | static void __exit acpi_video_exit(void) |
2354 | { | 2401 | { |
2355 | 2402 | acpi_video_unregister(); | |
2356 | acpi_bus_unregister_driver(&acpi_video_bus); | ||
2357 | |||
2358 | remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir); | ||
2359 | 2403 | ||
2360 | return; | 2404 | return; |
2361 | } | 2405 | } |
2362 | EXPORT_SYMBOL(acpi_video_exit); | ||
2363 | 2406 | ||
2364 | module_init(acpi_video_init); | 2407 | module_init(acpi_video_init); |
2365 | module_exit(acpi_video_exit); | 2408 | module_exit(acpi_video_exit); |
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 09737275e25f..7cd2b63435ea 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c | |||
@@ -10,7 +10,7 @@ | |||
10 | * assinged | 10 | * assinged |
11 | * | 11 | * |
12 | * After PCI devices are glued with ACPI devices | 12 | * After PCI devices are glued with ACPI devices |
13 | * acpi_get_physical_pci_device() can be called to identify ACPI graphics | 13 | * acpi_get_pci_dev() can be called to identify ACPI graphics |
14 | * devices for which a real graphics card is plugged in | 14 | * devices for which a real graphics card is plugged in |
15 | * | 15 | * |
16 | * Now acpi_video_get_capabilities() can be called to check which | 16 | * Now acpi_video_get_capabilities() can be called to check which |
@@ -36,6 +36,7 @@ | |||
36 | 36 | ||
37 | #include <linux/acpi.h> | 37 | #include <linux/acpi.h> |
38 | #include <linux/dmi.h> | 38 | #include <linux/dmi.h> |
39 | #include <linux/pci.h> | ||
39 | 40 | ||
40 | ACPI_MODULE_NAME("video"); | 41 | ACPI_MODULE_NAME("video"); |
41 | #define _COMPONENT ACPI_VIDEO_COMPONENT | 42 | #define _COMPONENT ACPI_VIDEO_COMPONENT |
@@ -109,7 +110,7 @@ static acpi_status | |||
109 | find_video(acpi_handle handle, u32 lvl, void *context, void **rv) | 110 | find_video(acpi_handle handle, u32 lvl, void *context, void **rv) |
110 | { | 111 | { |
111 | long *cap = context; | 112 | long *cap = context; |
112 | struct device *dev; | 113 | struct pci_dev *dev; |
113 | struct acpi_device *acpi_dev; | 114 | struct acpi_device *acpi_dev; |
114 | 115 | ||
115 | const struct acpi_device_id video_ids[] = { | 116 | const struct acpi_device_id video_ids[] = { |
@@ -120,10 +121,10 @@ find_video(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
120 | return AE_OK; | 121 | return AE_OK; |
121 | 122 | ||
122 | if (!acpi_match_device_ids(acpi_dev, video_ids)) { | 123 | if (!acpi_match_device_ids(acpi_dev, video_ids)) { |
123 | dev = acpi_get_physical_pci_device(handle); | 124 | dev = acpi_get_pci_dev(handle); |
124 | if (!dev) | 125 | if (!dev) |
125 | return AE_OK; | 126 | return AE_OK; |
126 | put_device(dev); | 127 | pci_dev_put(dev); |
127 | *cap |= acpi_is_video_device(acpi_dev); | 128 | *cap |= acpi_is_video_device(acpi_dev); |
128 | } | 129 | } |
129 | return AE_OK; | 130 | return AE_OK; |
diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c index dc425e74a268..e4b4e8898e39 100644 --- a/drivers/gpu/drm/i915/i915_opregion.c +++ b/drivers/gpu/drm/i915/i915_opregion.c | |||
@@ -419,7 +419,7 @@ void intel_opregion_free(struct drm_device *dev, int suspend) | |||
419 | return; | 419 | return; |
420 | 420 | ||
421 | if (!suspend) | 421 | if (!suspend) |
422 | acpi_video_exit(); | 422 | acpi_video_unregister(); |
423 | 423 | ||
424 | opregion->acpi->drdy = 0; | 424 | opregion->acpi->drdy = 0; |
425 | 425 | ||
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index fbc63d5e459f..eb159587d0bf 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c | |||
@@ -354,7 +354,7 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, | |||
354 | status = acpi_run_hpp(handle, hpp); | 354 | status = acpi_run_hpp(handle, hpp); |
355 | if (ACPI_SUCCESS(status)) | 355 | if (ACPI_SUCCESS(status)) |
356 | break; | 356 | break; |
357 | if (acpi_root_bridge(handle)) | 357 | if (acpi_is_root_bridge(handle)) |
358 | break; | 358 | break; |
359 | status = acpi_get_parent(handle, &phandle); | 359 | status = acpi_get_parent(handle, &phandle); |
360 | if (ACPI_FAILURE(status)) | 360 | if (ACPI_FAILURE(status)) |
@@ -428,7 +428,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) | |||
428 | status = acpi_run_oshp(handle); | 428 | status = acpi_run_oshp(handle); |
429 | if (ACPI_SUCCESS(status)) | 429 | if (ACPI_SUCCESS(status)) |
430 | goto got_one; | 430 | goto got_one; |
431 | if (acpi_root_bridge(handle)) | 431 | if (acpi_is_root_bridge(handle)) |
432 | break; | 432 | break; |
433 | chandle = handle; | 433 | chandle = handle; |
434 | status = acpi_get_parent(chandle, &handle); | 434 | status = acpi_get_parent(chandle, &handle); |
@@ -449,42 +449,6 @@ got_one: | |||
449 | } | 449 | } |
450 | EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware); | 450 | EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware); |
451 | 451 | ||
452 | /* acpi_root_bridge - check to see if this acpi object is a root bridge | ||
453 | * | ||
454 | * @handle - the acpi object in question. | ||
455 | */ | ||
456 | int acpi_root_bridge(acpi_handle handle) | ||
457 | { | ||
458 | acpi_status status; | ||
459 | struct acpi_device_info *info; | ||
460 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
461 | int i; | ||
462 | |||
463 | status = acpi_get_object_info(handle, &buffer); | ||
464 | if (ACPI_SUCCESS(status)) { | ||
465 | info = buffer.pointer; | ||
466 | if ((info->valid & ACPI_VALID_HID) && | ||
467 | !strcmp(PCI_ROOT_HID_STRING, | ||
468 | info->hardware_id.value)) { | ||
469 | kfree(buffer.pointer); | ||
470 | return 1; | ||
471 | } | ||
472 | if (info->valid & ACPI_VALID_CID) { | ||
473 | for (i=0; i < info->compatibility_id.count; i++) { | ||
474 | if (!strcmp(PCI_ROOT_HID_STRING, | ||
475 | info->compatibility_id.id[i].value)) { | ||
476 | kfree(buffer.pointer); | ||
477 | return 1; | ||
478 | } | ||
479 | } | ||
480 | } | ||
481 | kfree(buffer.pointer); | ||
482 | } | ||
483 | return 0; | ||
484 | } | ||
485 | EXPORT_SYMBOL_GPL(acpi_root_bridge); | ||
486 | |||
487 | |||
488 | static int is_ejectable(acpi_handle handle) | 452 | static int is_ejectable(acpi_handle handle) |
489 | { | 453 | { |
490 | acpi_status status; | 454 | acpi_status status; |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 3a6064bce561..0cb0f830a993 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -678,18 +678,9 @@ static void remove_bridge(acpi_handle handle) | |||
678 | 678 | ||
679 | static struct pci_dev * get_apic_pci_info(acpi_handle handle) | 679 | static struct pci_dev * get_apic_pci_info(acpi_handle handle) |
680 | { | 680 | { |
681 | struct acpi_pci_id id; | ||
682 | struct pci_bus *bus; | ||
683 | struct pci_dev *dev; | 681 | struct pci_dev *dev; |
684 | 682 | ||
685 | if (ACPI_FAILURE(acpi_get_pci_id(handle, &id))) | 683 | dev = acpi_get_pci_dev(handle); |
686 | return NULL; | ||
687 | |||
688 | bus = pci_find_bus(id.segment, id.bus); | ||
689 | if (!bus) | ||
690 | return NULL; | ||
691 | |||
692 | dev = pci_get_slot(bus, PCI_DEVFN(id.device, id.function)); | ||
693 | if (!dev) | 684 | if (!dev) |
694 | return NULL; | 685 | return NULL; |
695 | 686 | ||
@@ -1396,19 +1387,16 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus) | |||
1396 | /* Program resources in newly inserted bridge */ | 1387 | /* Program resources in newly inserted bridge */ |
1397 | static int acpiphp_configure_bridge (acpi_handle handle) | 1388 | static int acpiphp_configure_bridge (acpi_handle handle) |
1398 | { | 1389 | { |
1399 | struct acpi_pci_id pci_id; | 1390 | struct pci_dev *dev; |
1400 | struct pci_bus *bus; | 1391 | struct pci_bus *bus; |
1401 | 1392 | ||
1402 | if (ACPI_FAILURE(acpi_get_pci_id(handle, &pci_id))) { | 1393 | dev = acpi_get_pci_dev(handle); |
1394 | if (!dev) { | ||
1403 | err("cannot get PCI domain and bus number for bridge\n"); | 1395 | err("cannot get PCI domain and bus number for bridge\n"); |
1404 | return -EINVAL; | 1396 | return -EINVAL; |
1405 | } | 1397 | } |
1406 | bus = pci_find_bus(pci_id.segment, pci_id.bus); | 1398 | |
1407 | if (!bus) { | 1399 | bus = dev->bus; |
1408 | err("cannot find bus %d:%d\n", | ||
1409 | pci_id.segment, pci_id.bus); | ||
1410 | return -EINVAL; | ||
1411 | } | ||
1412 | 1400 | ||
1413 | pci_bus_size_bridges(bus); | 1401 | pci_bus_size_bridges(bus); |
1414 | pci_bus_assign_resources(bus); | 1402 | pci_bus_assign_resources(bus); |
@@ -1416,6 +1404,7 @@ static int acpiphp_configure_bridge (acpi_handle handle) | |||
1416 | acpiphp_set_hpp_values(handle, bus); | 1404 | acpiphp_set_hpp_values(handle, bus); |
1417 | pci_enable_bridges(bus); | 1405 | pci_enable_bridges(bus); |
1418 | acpiphp_configure_ioapics(handle); | 1406 | acpiphp_configure_ioapics(handle); |
1407 | pci_dev_put(dev); | ||
1419 | return 0; | 1408 | return 0; |
1420 | } | 1409 | } |
1421 | 1410 | ||
@@ -1631,7 +1620,7 @@ find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
1631 | { | 1620 | { |
1632 | int *count = (int *)context; | 1621 | int *count = (int *)context; |
1633 | 1622 | ||
1634 | if (acpi_root_bridge(handle)) { | 1623 | if (acpi_is_root_bridge(handle)) { |
1635 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | 1624 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, |
1636 | handle_hotplug_event_bridge, NULL); | 1625 | handle_hotplug_event_bridge, NULL); |
1637 | (*count)++; | 1626 | (*count)++; |
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index c682ac536415..7232fe7104aa 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
@@ -34,10 +34,27 @@ config ACER_WMI | |||
34 | If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M | 34 | If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M |
35 | here. | 35 | here. |
36 | 36 | ||
37 | config ACERHDF | ||
38 | tristate "Acer Aspire One temperature and fan driver" | ||
39 | depends on THERMAL && THERMAL_HWMON && ACPI | ||
40 | ---help--- | ||
41 | This is a driver for Acer Aspire One netbooks. It allows to access | ||
42 | the temperature sensor and to control the fan. | ||
43 | |||
44 | After loading this driver the BIOS is still in control of the fan. | ||
45 | To let the kernel handle the fan, do: | ||
46 | echo -n enabled > /sys/class/thermal/thermal_zone0/mode | ||
47 | |||
48 | For more information about this driver see | ||
49 | <http://piie.net/files/acerhdf_README.txt> | ||
50 | |||
51 | If you have an Acer Aspire One netbook, say Y or M | ||
52 | here. | ||
53 | |||
37 | config ASUS_LAPTOP | 54 | config ASUS_LAPTOP |
38 | tristate "Asus Laptop Extras (EXPERIMENTAL)" | 55 | tristate "Asus Laptop Extras" |
39 | depends on ACPI | 56 | depends on ACPI |
40 | depends on EXPERIMENTAL && !ACPI_ASUS | 57 | depends on !ACPI_ASUS |
41 | select LEDS_CLASS | 58 | select LEDS_CLASS |
42 | select NEW_LEDS | 59 | select NEW_LEDS |
43 | select BACKLIGHT_CLASS_DEVICE | 60 | select BACKLIGHT_CLASS_DEVICE |
@@ -45,12 +62,12 @@ config ASUS_LAPTOP | |||
45 | ---help--- | 62 | ---help--- |
46 | This is the new Linux driver for Asus laptops. It may also support some | 63 | This is the new Linux driver for Asus laptops. It may also support some |
47 | MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate | 64 | MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate |
48 | standard ACPI events that go through /proc/acpi/events. It also adds | 65 | standard ACPI events and input events. It also adds |
49 | support for video output switching, LCD backlight control, Bluetooth and | 66 | support for video output switching, LCD backlight control, Bluetooth and |
50 | Wlan control, and most importantly, allows you to blink those fancy LEDs. | 67 | Wlan control, and most importantly, allows you to blink those fancy LEDs. |
51 | 68 | ||
52 | For more information and a userspace daemon for handling the extra | 69 | For more information and a userspace daemon for handling the extra |
53 | buttons see <http://acpi4asus.sf.net/>. | 70 | buttons see <http://acpi4asus.sf.net>. |
54 | 71 | ||
55 | If you have an ACPI-compatible ASUS laptop, say Y or M here. | 72 | If you have an ACPI-compatible ASUS laptop, say Y or M here. |
56 | 73 | ||
@@ -342,7 +359,10 @@ config EEEPC_LAPTOP | |||
342 | select HWMON | 359 | select HWMON |
343 | ---help--- | 360 | ---help--- |
344 | This driver supports the Fn-Fx keys on Eee PC laptops. | 361 | This driver supports the Fn-Fx keys on Eee PC laptops. |
345 | It also adds the ability to switch camera/wlan on/off. | 362 | |
363 | It also gives access to some extra laptop functionalities like | ||
364 | Bluetooth, backlight and allows powering on/off some other | ||
365 | devices. | ||
346 | 366 | ||
347 | If you have an Eee PC laptop, say Y or M here. | 367 | If you have an Eee PC laptop, say Y or M here. |
348 | 368 | ||
@@ -369,7 +389,7 @@ config ACPI_WMI | |||
369 | any ACPI-WMI devices. | 389 | any ACPI-WMI devices. |
370 | 390 | ||
371 | config ACPI_ASUS | 391 | config ACPI_ASUS |
372 | tristate "ASUS/Medion Laptop Extras" | 392 | tristate "ASUS/Medion Laptop Extras (DEPRECATED)" |
373 | depends on ACPI | 393 | depends on ACPI |
374 | select BACKLIGHT_CLASS_DEVICE | 394 | select BACKLIGHT_CLASS_DEVICE |
375 | ---help--- | 395 | ---help--- |
@@ -390,7 +410,7 @@ config ACPI_ASUS | |||
390 | parameters. | 410 | parameters. |
391 | 411 | ||
392 | More information and a userspace daemon for handling the extra buttons | 412 | More information and a userspace daemon for handling the extra buttons |
393 | at <http://sourceforge.net/projects/acpi4asus/>. | 413 | at <http://acpi4asus.sf.net>. |
394 | 414 | ||
395 | If you have an ACPI-compatible ASUS laptop, say Y or M here. This | 415 | If you have an ACPI-compatible ASUS laptop, say Y or M here. This |
396 | driver is still under development, so if your laptop is unsupported or | 416 | driver is still under development, so if your laptop is unsupported or |
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index e40c7bd1b87e..641b8bfa5538 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile | |||
@@ -9,6 +9,7 @@ obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o | |||
9 | obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o | 9 | obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o |
10 | obj-$(CONFIG_DELL_WMI) += dell-wmi.o | 10 | obj-$(CONFIG_DELL_WMI) += dell-wmi.o |
11 | obj-$(CONFIG_ACER_WMI) += acer-wmi.o | 11 | obj-$(CONFIG_ACER_WMI) += acer-wmi.o |
12 | obj-$(CONFIG_ACERHDF) += acerhdf.o | ||
12 | obj-$(CONFIG_HP_WMI) += hp-wmi.o | 13 | obj-$(CONFIG_HP_WMI) += hp-wmi.o |
13 | obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o | 14 | obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o |
14 | obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o | 15 | obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o |
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c new file mode 100644 index 000000000000..bdfee177eefb --- /dev/null +++ b/drivers/platform/x86/acerhdf.c | |||
@@ -0,0 +1,602 @@ | |||
1 | /* | ||
2 | * acerhdf - A driver which monitors the temperature | ||
3 | * of the aspire one netbook, turns on/off the fan | ||
4 | * as soon as the upper/lower threshold is reached. | ||
5 | * | ||
6 | * (C) 2009 - Peter Feuerer peter (a) piie.net | ||
7 | * http://piie.net | ||
8 | * 2009 Borislav Petkov <petkovbb@gmail.com> | ||
9 | * | ||
10 | * Inspired by and many thanks to: | ||
11 | * o acerfand - Rachel Greenham | ||
12 | * o acer_ec.pl - Michael Kurz michi.kurz (at) googlemail.com | ||
13 | * - Petr Tomasek tomasek (#) etf,cuni,cz | ||
14 | * - Carlos Corbacho cathectic (at) gmail.com | ||
15 | * o lkml - Matthew Garrett | ||
16 | * - Borislav Petkov | ||
17 | * - Andreas Mohr | ||
18 | * | ||
19 | * This program is free software; you can redistribute it and/or modify | ||
20 | * it under the terms of the GNU General Public License as published by | ||
21 | * the Free Software Foundation; either version 2 of the License, or | ||
22 | * (at your option) any later version. | ||
23 | * | ||
24 | * This program is distributed in the hope that it will be useful, | ||
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
27 | * GNU General Public License for more details. | ||
28 | * | ||
29 | * You should have received a copy of the GNU General Public License | ||
30 | * along with this program; if not, write to the Free Software | ||
31 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
32 | */ | ||
33 | |||
34 | #define pr_fmt(fmt) "acerhdf: " fmt | ||
35 | |||
36 | #include <linux/kernel.h> | ||
37 | #include <linux/module.h> | ||
38 | #include <linux/fs.h> | ||
39 | #include <linux/dmi.h> | ||
40 | #include <acpi/acpi_drivers.h> | ||
41 | #include <linux/sched.h> | ||
42 | #include <linux/thermal.h> | ||
43 | #include <linux/platform_device.h> | ||
44 | |||
45 | /* | ||
46 | * The driver is started with "kernel mode off" by default. That means, the BIOS | ||
47 | * is still in control of the fan. In this mode the driver allows to read the | ||
48 | * temperature of the cpu and a userspace tool may take over control of the fan. | ||
49 | * If the driver is switched to "kernel mode" (e.g. via module parameter) the | ||
50 | * driver is in full control of the fan. If you want the module to be started in | ||
51 | * kernel mode by default, define the following: | ||
52 | */ | ||
53 | #undef START_IN_KERNEL_MODE | ||
54 | |||
55 | #define DRV_VER "0.5.13" | ||
56 | |||
57 | /* | ||
58 | * According to the Atom N270 datasheet, | ||
59 | * (http://download.intel.com/design/processor/datashts/320032.pdf) the | ||
60 | * CPU's optimal operating limits denoted in junction temperature as | ||
61 | * measured by the on-die thermal monitor are within 0 <= Tj <= 90. So, | ||
62 | * assume 89°C is critical temperature. | ||
63 | */ | ||
64 | #define ACERHDF_TEMP_CRIT 89 | ||
65 | #define ACERHDF_FAN_OFF 0 | ||
66 | #define ACERHDF_FAN_AUTO 1 | ||
67 | |||
68 | /* | ||
69 | * No matter what value the user puts into the fanon variable, turn on the fan | ||
70 | * at 80 degree Celsius to prevent hardware damage | ||
71 | */ | ||
72 | #define ACERHDF_MAX_FANON 80 | ||
73 | |||
74 | /* | ||
75 | * Maximum interval between two temperature checks is 15 seconds, as the die | ||
76 | * can get hot really fast under heavy load (plus we shouldn't forget about | ||
77 | * possible impact of _external_ aggressive sources such as heaters, sun etc.) | ||
78 | */ | ||
79 | #define ACERHDF_MAX_INTERVAL 15 | ||
80 | |||
81 | #ifdef START_IN_KERNEL_MODE | ||
82 | static int kernelmode = 1; | ||
83 | #else | ||
84 | static int kernelmode; | ||
85 | #endif | ||
86 | |||
87 | static unsigned int interval = 10; | ||
88 | static unsigned int fanon = 63; | ||
89 | static unsigned int fanoff = 58; | ||
90 | static unsigned int verbose; | ||
91 | static unsigned int fanstate = ACERHDF_FAN_AUTO; | ||
92 | static char force_bios[16]; | ||
93 | static unsigned int prev_interval; | ||
94 | struct thermal_zone_device *thz_dev; | ||
95 | struct thermal_cooling_device *cl_dev; | ||
96 | struct platform_device *acerhdf_dev; | ||
97 | |||
98 | module_param(kernelmode, uint, 0); | ||
99 | MODULE_PARM_DESC(kernelmode, "Kernel mode fan control on / off"); | ||
100 | module_param(interval, uint, 0600); | ||
101 | MODULE_PARM_DESC(interval, "Polling interval of temperature check"); | ||
102 | module_param(fanon, uint, 0600); | ||
103 | MODULE_PARM_DESC(fanon, "Turn the fan on above this temperature"); | ||
104 | module_param(fanoff, uint, 0600); | ||
105 | MODULE_PARM_DESC(fanoff, "Turn the fan off below this temperature"); | ||
106 | module_param(verbose, uint, 0600); | ||
107 | MODULE_PARM_DESC(verbose, "Enable verbose dmesg output"); | ||
108 | module_param_string(force_bios, force_bios, 16, 0); | ||
109 | MODULE_PARM_DESC(force_bios, "Force BIOS version and omit BIOS check"); | ||
110 | |||
111 | /* BIOS settings */ | ||
112 | struct bios_settings_t { | ||
113 | const char *vendor; | ||
114 | const char *version; | ||
115 | unsigned char fanreg; | ||
116 | unsigned char tempreg; | ||
117 | unsigned char fancmd[2]; /* fan off and auto commands */ | ||
118 | }; | ||
119 | |||
120 | /* Register addresses and values for different BIOS versions */ | ||
121 | static const struct bios_settings_t bios_tbl[] = { | ||
122 | {"Acer", "v0.3109", 0x55, 0x58, {0x1f, 0x00} }, | ||
123 | {"Acer", "v0.3114", 0x55, 0x58, {0x1f, 0x00} }, | ||
124 | {"Acer", "v0.3301", 0x55, 0x58, {0xaf, 0x00} }, | ||
125 | {"Acer", "v0.3304", 0x55, 0x58, {0xaf, 0x00} }, | ||
126 | {"Acer", "v0.3305", 0x55, 0x58, {0xaf, 0x00} }, | ||
127 | {"Acer", "v0.3308", 0x55, 0x58, {0x21, 0x00} }, | ||
128 | {"Acer", "v0.3309", 0x55, 0x58, {0x21, 0x00} }, | ||
129 | {"Acer", "v0.3310", 0x55, 0x58, {0x21, 0x00} }, | ||
130 | {"Gateway", "v0.3103", 0x55, 0x58, {0x21, 0x00} }, | ||
131 | {"Packard Bell", "v0.3105", 0x55, 0x58, {0x21, 0x00} }, | ||
132 | {"", "", 0, 0, {0, 0} } | ||
133 | }; | ||
134 | |||
135 | static const struct bios_settings_t *bios_cfg __read_mostly; | ||
136 | |||
137 | |||
138 | static int acerhdf_get_temp(int *temp) | ||
139 | { | ||
140 | u8 read_temp; | ||
141 | |||
142 | if (ec_read(bios_cfg->tempreg, &read_temp)) | ||
143 | return -EINVAL; | ||
144 | |||
145 | *temp = read_temp; | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static int acerhdf_get_fanstate(int *state) | ||
151 | { | ||
152 | u8 fan; | ||
153 | bool tmp; | ||
154 | |||
155 | if (ec_read(bios_cfg->fanreg, &fan)) | ||
156 | return -EINVAL; | ||
157 | |||
158 | tmp = (fan == bios_cfg->fancmd[ACERHDF_FAN_OFF]); | ||
159 | *state = tmp ? ACERHDF_FAN_OFF : ACERHDF_FAN_AUTO; | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static void acerhdf_change_fanstate(int state) | ||
165 | { | ||
166 | unsigned char cmd; | ||
167 | |||
168 | if (verbose) | ||
169 | pr_notice("fan %s\n", (state == ACERHDF_FAN_OFF) ? | ||
170 | "OFF" : "ON"); | ||
171 | |||
172 | if ((state != ACERHDF_FAN_OFF) && (state != ACERHDF_FAN_AUTO)) { | ||
173 | pr_err("invalid fan state %d requested, setting to auto!\n", | ||
174 | state); | ||
175 | state = ACERHDF_FAN_AUTO; | ||
176 | } | ||
177 | |||
178 | cmd = bios_cfg->fancmd[state]; | ||
179 | fanstate = state; | ||
180 | |||
181 | ec_write(bios_cfg->fanreg, cmd); | ||
182 | } | ||
183 | |||
184 | static void acerhdf_check_param(struct thermal_zone_device *thermal) | ||
185 | { | ||
186 | if (fanon > ACERHDF_MAX_FANON) { | ||
187 | pr_err("fanon temperature too high, set to %d\n", | ||
188 | ACERHDF_MAX_FANON); | ||
189 | fanon = ACERHDF_MAX_FANON; | ||
190 | } | ||
191 | |||
192 | if (kernelmode && prev_interval != interval) { | ||
193 | if (interval > ACERHDF_MAX_INTERVAL) { | ||
194 | pr_err("interval too high, set to %d\n", | ||
195 | ACERHDF_MAX_INTERVAL); | ||
196 | interval = ACERHDF_MAX_INTERVAL; | ||
197 | } | ||
198 | if (verbose) | ||
199 | pr_notice("interval changed to: %d\n", | ||
200 | interval); | ||
201 | thermal->polling_delay = interval*1000; | ||
202 | prev_interval = interval; | ||
203 | } | ||
204 | } | ||
205 | |||
206 | /* | ||
207 | * This is the thermal zone callback which does the delayed polling of the fan | ||
208 | * state. We do check /sysfs-originating settings here in acerhdf_check_param() | ||
209 | * as late as the polling interval is since we can't do that in the respective | ||
210 | * accessors of the module parameters. | ||
211 | */ | ||
212 | static int acerhdf_get_ec_temp(struct thermal_zone_device *thermal, | ||
213 | unsigned long *t) | ||
214 | { | ||
215 | int temp, err = 0; | ||
216 | |||
217 | acerhdf_check_param(thermal); | ||
218 | |||
219 | err = acerhdf_get_temp(&temp); | ||
220 | if (err) | ||
221 | return err; | ||
222 | |||
223 | if (verbose) | ||
224 | pr_notice("temp %d\n", temp); | ||
225 | |||
226 | *t = temp; | ||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static int acerhdf_bind(struct thermal_zone_device *thermal, | ||
231 | struct thermal_cooling_device *cdev) | ||
232 | { | ||
233 | /* if the cooling device is the one from acerhdf bind it */ | ||
234 | if (cdev != cl_dev) | ||
235 | return 0; | ||
236 | |||
237 | if (thermal_zone_bind_cooling_device(thermal, 0, cdev)) { | ||
238 | pr_err("error binding cooling dev\n"); | ||
239 | return -EINVAL; | ||
240 | } | ||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static int acerhdf_unbind(struct thermal_zone_device *thermal, | ||
245 | struct thermal_cooling_device *cdev) | ||
246 | { | ||
247 | if (cdev != cl_dev) | ||
248 | return 0; | ||
249 | |||
250 | if (thermal_zone_unbind_cooling_device(thermal, 0, cdev)) { | ||
251 | pr_err("error unbinding cooling dev\n"); | ||
252 | return -EINVAL; | ||
253 | } | ||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | static inline void acerhdf_revert_to_bios_mode(void) | ||
258 | { | ||
259 | acerhdf_change_fanstate(ACERHDF_FAN_AUTO); | ||
260 | kernelmode = 0; | ||
261 | if (thz_dev) | ||
262 | thz_dev->polling_delay = 0; | ||
263 | pr_notice("kernel mode fan control OFF\n"); | ||
264 | } | ||
265 | static inline void acerhdf_enable_kernelmode(void) | ||
266 | { | ||
267 | kernelmode = 1; | ||
268 | |||
269 | thz_dev->polling_delay = interval*1000; | ||
270 | thermal_zone_device_update(thz_dev); | ||
271 | pr_notice("kernel mode fan control ON\n"); | ||
272 | } | ||
273 | |||
274 | static int acerhdf_get_mode(struct thermal_zone_device *thermal, | ||
275 | enum thermal_device_mode *mode) | ||
276 | { | ||
277 | if (verbose) | ||
278 | pr_notice("kernel mode fan control %d\n", kernelmode); | ||
279 | |||
280 | *mode = (kernelmode) ? THERMAL_DEVICE_ENABLED | ||
281 | : THERMAL_DEVICE_DISABLED; | ||
282 | |||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | /* | ||
287 | * set operation mode; | ||
288 | * enabled: the thermal layer of the kernel takes care about | ||
289 | * the temperature and the fan. | ||
290 | * disabled: the BIOS takes control of the fan. | ||
291 | */ | ||
292 | static int acerhdf_set_mode(struct thermal_zone_device *thermal, | ||
293 | enum thermal_device_mode mode) | ||
294 | { | ||
295 | if (mode == THERMAL_DEVICE_DISABLED && kernelmode) | ||
296 | acerhdf_revert_to_bios_mode(); | ||
297 | else if (mode == THERMAL_DEVICE_ENABLED && !kernelmode) | ||
298 | acerhdf_enable_kernelmode(); | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | static int acerhdf_get_trip_type(struct thermal_zone_device *thermal, int trip, | ||
304 | enum thermal_trip_type *type) | ||
305 | { | ||
306 | if (trip == 0) | ||
307 | *type = THERMAL_TRIP_ACTIVE; | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static int acerhdf_get_trip_temp(struct thermal_zone_device *thermal, int trip, | ||
313 | unsigned long *temp) | ||
314 | { | ||
315 | if (trip == 0) | ||
316 | *temp = fanon; | ||
317 | |||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static int acerhdf_get_crit_temp(struct thermal_zone_device *thermal, | ||
322 | unsigned long *temperature) | ||
323 | { | ||
324 | *temperature = ACERHDF_TEMP_CRIT; | ||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | /* bind callback functions to thermalzone */ | ||
329 | struct thermal_zone_device_ops acerhdf_dev_ops = { | ||
330 | .bind = acerhdf_bind, | ||
331 | .unbind = acerhdf_unbind, | ||
332 | .get_temp = acerhdf_get_ec_temp, | ||
333 | .get_mode = acerhdf_get_mode, | ||
334 | .set_mode = acerhdf_set_mode, | ||
335 | .get_trip_type = acerhdf_get_trip_type, | ||
336 | .get_trip_temp = acerhdf_get_trip_temp, | ||
337 | .get_crit_temp = acerhdf_get_crit_temp, | ||
338 | }; | ||
339 | |||
340 | |||
341 | /* | ||
342 | * cooling device callback functions | ||
343 | * get maximal fan cooling state | ||
344 | */ | ||
345 | static int acerhdf_get_max_state(struct thermal_cooling_device *cdev, | ||
346 | unsigned long *state) | ||
347 | { | ||
348 | *state = 1; | ||
349 | |||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static int acerhdf_get_cur_state(struct thermal_cooling_device *cdev, | ||
354 | unsigned long *state) | ||
355 | { | ||
356 | int err = 0, tmp; | ||
357 | |||
358 | err = acerhdf_get_fanstate(&tmp); | ||
359 | if (err) | ||
360 | return err; | ||
361 | |||
362 | *state = (tmp == ACERHDF_FAN_AUTO) ? 1 : 0; | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | /* change current fan state - is overwritten when running in kernel mode */ | ||
367 | static int acerhdf_set_cur_state(struct thermal_cooling_device *cdev, | ||
368 | unsigned long state) | ||
369 | { | ||
370 | int cur_temp, cur_state, err = 0; | ||
371 | |||
372 | if (!kernelmode) | ||
373 | return 0; | ||
374 | |||
375 | err = acerhdf_get_temp(&cur_temp); | ||
376 | if (err) { | ||
377 | pr_err("error reading temperature, hand off control to BIOS\n"); | ||
378 | goto err_out; | ||
379 | } | ||
380 | |||
381 | err = acerhdf_get_fanstate(&cur_state); | ||
382 | if (err) { | ||
383 | pr_err("error reading fan state, hand off control to BIOS\n"); | ||
384 | goto err_out; | ||
385 | } | ||
386 | |||
387 | if (state == 0) { | ||
388 | /* turn fan off only if below fanoff temperature */ | ||
389 | if ((cur_state == ACERHDF_FAN_AUTO) && | ||
390 | (cur_temp < fanoff)) | ||
391 | acerhdf_change_fanstate(ACERHDF_FAN_OFF); | ||
392 | } else { | ||
393 | if (cur_state == ACERHDF_FAN_OFF) | ||
394 | acerhdf_change_fanstate(ACERHDF_FAN_AUTO); | ||
395 | } | ||
396 | return 0; | ||
397 | |||
398 | err_out: | ||
399 | acerhdf_revert_to_bios_mode(); | ||
400 | return -EINVAL; | ||
401 | } | ||
402 | |||
403 | /* bind fan callbacks to fan device */ | ||
404 | struct thermal_cooling_device_ops acerhdf_cooling_ops = { | ||
405 | .get_max_state = acerhdf_get_max_state, | ||
406 | .get_cur_state = acerhdf_get_cur_state, | ||
407 | .set_cur_state = acerhdf_set_cur_state, | ||
408 | }; | ||
409 | |||
410 | /* suspend / resume functionality */ | ||
411 | static int acerhdf_suspend(struct platform_device *dev, pm_message_t state) | ||
412 | { | ||
413 | if (kernelmode) | ||
414 | acerhdf_change_fanstate(ACERHDF_FAN_AUTO); | ||
415 | |||
416 | if (verbose) | ||
417 | pr_notice("going suspend\n"); | ||
418 | |||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | static int acerhdf_resume(struct platform_device *device) | ||
423 | { | ||
424 | if (verbose) | ||
425 | pr_notice("resuming\n"); | ||
426 | |||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | static int __devinit acerhdf_probe(struct platform_device *device) | ||
431 | { | ||
432 | return 0; | ||
433 | } | ||
434 | |||
435 | static int acerhdf_remove(struct platform_device *device) | ||
436 | { | ||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | struct platform_driver acerhdf_drv = { | ||
441 | .driver = { | ||
442 | .name = "acerhdf", | ||
443 | .owner = THIS_MODULE, | ||
444 | }, | ||
445 | .probe = acerhdf_probe, | ||
446 | .remove = acerhdf_remove, | ||
447 | .suspend = acerhdf_suspend, | ||
448 | .resume = acerhdf_resume, | ||
449 | }; | ||
450 | |||
451 | |||
452 | /* check hardware */ | ||
453 | static int acerhdf_check_hardware(void) | ||
454 | { | ||
455 | char const *vendor, *version, *product; | ||
456 | int i; | ||
457 | |||
458 | /* get BIOS data */ | ||
459 | vendor = dmi_get_system_info(DMI_SYS_VENDOR); | ||
460 | version = dmi_get_system_info(DMI_BIOS_VERSION); | ||
461 | product = dmi_get_system_info(DMI_PRODUCT_NAME); | ||
462 | |||
463 | pr_info("Acer Aspire One Fan driver, v.%s\n", DRV_VER); | ||
464 | |||
465 | if (!force_bios[0]) { | ||
466 | if (strncmp(product, "AO", 2)) { | ||
467 | pr_err("no Aspire One hardware found\n"); | ||
468 | return -EINVAL; | ||
469 | } | ||
470 | } else { | ||
471 | pr_info("forcing BIOS version: %s\n", version); | ||
472 | version = force_bios; | ||
473 | kernelmode = 0; | ||
474 | } | ||
475 | |||
476 | if (verbose) | ||
477 | pr_info("BIOS info: %s %s, product: %s\n", | ||
478 | vendor, version, product); | ||
479 | |||
480 | /* search BIOS version and vendor in BIOS settings table */ | ||
481 | for (i = 0; bios_tbl[i].version[0]; i++) { | ||
482 | if (!strcmp(bios_tbl[i].vendor, vendor) && | ||
483 | !strcmp(bios_tbl[i].version, version)) { | ||
484 | bios_cfg = &bios_tbl[i]; | ||
485 | break; | ||
486 | } | ||
487 | } | ||
488 | |||
489 | if (!bios_cfg) { | ||
490 | pr_err("unknown (unsupported) BIOS version %s/%s, " | ||
491 | "please report, aborting!\n", vendor, version); | ||
492 | return -EINVAL; | ||
493 | } | ||
494 | |||
495 | /* | ||
496 | * if started with kernel mode off, prevent the kernel from switching | ||
497 | * off the fan | ||
498 | */ | ||
499 | if (!kernelmode) { | ||
500 | pr_notice("Fan control off, to enable do:\n"); | ||
501 | pr_notice("echo -n \"enabled\" > " | ||
502 | "/sys/class/thermal/thermal_zone0/mode\n"); | ||
503 | } | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | static int acerhdf_register_platform(void) | ||
509 | { | ||
510 | int err = 0; | ||
511 | |||
512 | err = platform_driver_register(&acerhdf_drv); | ||
513 | if (err) | ||
514 | return err; | ||
515 | |||
516 | acerhdf_dev = platform_device_alloc("acerhdf", -1); | ||
517 | platform_device_add(acerhdf_dev); | ||
518 | |||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | static void acerhdf_unregister_platform(void) | ||
523 | { | ||
524 | if (!acerhdf_dev) | ||
525 | return; | ||
526 | |||
527 | platform_device_del(acerhdf_dev); | ||
528 | platform_driver_unregister(&acerhdf_drv); | ||
529 | } | ||
530 | |||
531 | static int acerhdf_register_thermal(void) | ||
532 | { | ||
533 | cl_dev = thermal_cooling_device_register("acerhdf-fan", NULL, | ||
534 | &acerhdf_cooling_ops); | ||
535 | |||
536 | if (IS_ERR(cl_dev)) | ||
537 | return -EINVAL; | ||
538 | |||
539 | thz_dev = thermal_zone_device_register("acerhdf", 1, NULL, | ||
540 | &acerhdf_dev_ops, 0, 0, 0, | ||
541 | (kernelmode) ? interval*1000 : 0); | ||
542 | if (IS_ERR(thz_dev)) | ||
543 | return -EINVAL; | ||
544 | |||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | static void acerhdf_unregister_thermal(void) | ||
549 | { | ||
550 | if (cl_dev) { | ||
551 | thermal_cooling_device_unregister(cl_dev); | ||
552 | cl_dev = NULL; | ||
553 | } | ||
554 | |||
555 | if (thz_dev) { | ||
556 | thermal_zone_device_unregister(thz_dev); | ||
557 | thz_dev = NULL; | ||
558 | } | ||
559 | } | ||
560 | |||
561 | static int __init acerhdf_init(void) | ||
562 | { | ||
563 | int err = 0; | ||
564 | |||
565 | err = acerhdf_check_hardware(); | ||
566 | if (err) | ||
567 | goto out_err; | ||
568 | |||
569 | err = acerhdf_register_platform(); | ||
570 | if (err) | ||
571 | goto err_unreg; | ||
572 | |||
573 | err = acerhdf_register_thermal(); | ||
574 | if (err) | ||
575 | goto err_unreg; | ||
576 | |||
577 | return 0; | ||
578 | |||
579 | err_unreg: | ||
580 | acerhdf_unregister_thermal(); | ||
581 | acerhdf_unregister_platform(); | ||
582 | |||
583 | out_err: | ||
584 | return -ENODEV; | ||
585 | } | ||
586 | |||
587 | static void __exit acerhdf_exit(void) | ||
588 | { | ||
589 | acerhdf_change_fanstate(ACERHDF_FAN_AUTO); | ||
590 | acerhdf_unregister_thermal(); | ||
591 | acerhdf_unregister_platform(); | ||
592 | } | ||
593 | |||
594 | MODULE_LICENSE("GPL"); | ||
595 | MODULE_AUTHOR("Peter Feuerer"); | ||
596 | MODULE_DESCRIPTION("Aspire One temperature and fan driver"); | ||
597 | MODULE_ALIAS("dmi:*:*Acer*:*:"); | ||
598 | MODULE_ALIAS("dmi:*:*Gateway*:*:"); | ||
599 | MODULE_ALIAS("dmi:*:*Packard Bell*:*:"); | ||
600 | |||
601 | module_init(acerhdf_init); | ||
602 | module_exit(acerhdf_exit); | ||
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index bfc1a8892a32..db657bbeec90 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c | |||
@@ -33,6 +33,8 @@ | |||
33 | * Sam Lin - GPS support | 33 | * Sam Lin - GPS support |
34 | */ | 34 | */ |
35 | 35 | ||
36 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
37 | |||
36 | #include <linux/kernel.h> | 38 | #include <linux/kernel.h> |
37 | #include <linux/module.h> | 39 | #include <linux/module.h> |
38 | #include <linux/init.h> | 40 | #include <linux/init.h> |
@@ -53,9 +55,10 @@ | |||
53 | #define ASUS_HOTK_NAME "Asus Laptop Support" | 55 | #define ASUS_HOTK_NAME "Asus Laptop Support" |
54 | #define ASUS_HOTK_CLASS "hotkey" | 56 | #define ASUS_HOTK_CLASS "hotkey" |
55 | #define ASUS_HOTK_DEVICE_NAME "Hotkey" | 57 | #define ASUS_HOTK_DEVICE_NAME "Hotkey" |
56 | #define ASUS_HOTK_FILE "asus-laptop" | 58 | #define ASUS_HOTK_FILE KBUILD_MODNAME |
57 | #define ASUS_HOTK_PREFIX "\\_SB.ATKD." | 59 | #define ASUS_HOTK_PREFIX "\\_SB.ATKD." |
58 | 60 | ||
61 | |||
59 | /* | 62 | /* |
60 | * Some events we use, same for all Asus | 63 | * Some events we use, same for all Asus |
61 | */ | 64 | */ |
@@ -207,13 +210,17 @@ MODULE_DEVICE_TABLE(acpi, asus_device_ids); | |||
207 | 210 | ||
208 | static int asus_hotk_add(struct acpi_device *device); | 211 | static int asus_hotk_add(struct acpi_device *device); |
209 | static int asus_hotk_remove(struct acpi_device *device, int type); | 212 | static int asus_hotk_remove(struct acpi_device *device, int type); |
213 | static void asus_hotk_notify(struct acpi_device *device, u32 event); | ||
214 | |||
210 | static struct acpi_driver asus_hotk_driver = { | 215 | static struct acpi_driver asus_hotk_driver = { |
211 | .name = ASUS_HOTK_NAME, | 216 | .name = ASUS_HOTK_NAME, |
212 | .class = ASUS_HOTK_CLASS, | 217 | .class = ASUS_HOTK_CLASS, |
213 | .ids = asus_device_ids, | 218 | .ids = asus_device_ids, |
219 | .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, | ||
214 | .ops = { | 220 | .ops = { |
215 | .add = asus_hotk_add, | 221 | .add = asus_hotk_add, |
216 | .remove = asus_hotk_remove, | 222 | .remove = asus_hotk_remove, |
223 | .notify = asus_hotk_notify, | ||
217 | }, | 224 | }, |
218 | }; | 225 | }; |
219 | 226 | ||
@@ -323,7 +330,7 @@ static int read_wireless_status(int mask) | |||
323 | 330 | ||
324 | rv = acpi_evaluate_integer(wireless_status_handle, NULL, NULL, &status); | 331 | rv = acpi_evaluate_integer(wireless_status_handle, NULL, NULL, &status); |
325 | if (ACPI_FAILURE(rv)) | 332 | if (ACPI_FAILURE(rv)) |
326 | printk(ASUS_WARNING "Error reading Wireless status\n"); | 333 | pr_warning("Error reading Wireless status\n"); |
327 | else | 334 | else |
328 | return (status & mask) ? 1 : 0; | 335 | return (status & mask) ? 1 : 0; |
329 | 336 | ||
@@ -337,7 +344,7 @@ static int read_gps_status(void) | |||
337 | 344 | ||
338 | rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status); | 345 | rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status); |
339 | if (ACPI_FAILURE(rv)) | 346 | if (ACPI_FAILURE(rv)) |
340 | printk(ASUS_WARNING "Error reading GPS status\n"); | 347 | pr_warning("Error reading GPS status\n"); |
341 | else | 348 | else |
342 | return status ? 1 : 0; | 349 | return status ? 1 : 0; |
343 | 350 | ||
@@ -377,7 +384,7 @@ static void write_status(acpi_handle handle, int out, int mask) | |||
377 | } | 384 | } |
378 | 385 | ||
379 | if (write_acpi_int(handle, NULL, out, NULL)) | 386 | if (write_acpi_int(handle, NULL, out, NULL)) |
380 | printk(ASUS_WARNING " write failed %x\n", mask); | 387 | pr_warning(" write failed %x\n", mask); |
381 | } | 388 | } |
382 | 389 | ||
383 | /* /sys/class/led handlers */ | 390 | /* /sys/class/led handlers */ |
@@ -420,7 +427,7 @@ static int set_lcd_state(int value) | |||
420 | NULL, NULL, NULL); | 427 | NULL, NULL, NULL); |
421 | 428 | ||
422 | if (ACPI_FAILURE(status)) | 429 | if (ACPI_FAILURE(status)) |
423 | printk(ASUS_WARNING "Error switching LCD\n"); | 430 | pr_warning("Error switching LCD\n"); |
424 | } | 431 | } |
425 | 432 | ||
426 | write_status(NULL, lcd, LCD_ON); | 433 | write_status(NULL, lcd, LCD_ON); |
@@ -444,7 +451,7 @@ static int read_brightness(struct backlight_device *bd) | |||
444 | 451 | ||
445 | rv = acpi_evaluate_integer(brightness_get_handle, NULL, NULL, &value); | 452 | rv = acpi_evaluate_integer(brightness_get_handle, NULL, NULL, &value); |
446 | if (ACPI_FAILURE(rv)) | 453 | if (ACPI_FAILURE(rv)) |
447 | printk(ASUS_WARNING "Error reading brightness\n"); | 454 | pr_warning("Error reading brightness\n"); |
448 | 455 | ||
449 | return value; | 456 | return value; |
450 | } | 457 | } |
@@ -457,7 +464,7 @@ static int set_brightness(struct backlight_device *bd, int value) | |||
457 | /* 0 <= value <= 15 */ | 464 | /* 0 <= value <= 15 */ |
458 | 465 | ||
459 | if (write_acpi_int(brightness_set_handle, NULL, value, NULL)) { | 466 | if (write_acpi_int(brightness_set_handle, NULL, value, NULL)) { |
460 | printk(ASUS_WARNING "Error changing brightness\n"); | 467 | pr_warning("Error changing brightness\n"); |
461 | ret = -EIO; | 468 | ret = -EIO; |
462 | } | 469 | } |
463 | 470 | ||
@@ -587,7 +594,7 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr, | |||
587 | rv = parse_arg(buf, count, &value); | 594 | rv = parse_arg(buf, count, &value); |
588 | if (rv > 0) { | 595 | if (rv > 0) { |
589 | if (write_acpi_int(ledd_set_handle, NULL, value, NULL)) | 596 | if (write_acpi_int(ledd_set_handle, NULL, value, NULL)) |
590 | printk(ASUS_WARNING "LED display write failed\n"); | 597 | pr_warning("LED display write failed\n"); |
591 | else | 598 | else |
592 | hotk->ledd_status = (u32) value; | 599 | hotk->ledd_status = (u32) value; |
593 | } | 600 | } |
@@ -632,7 +639,7 @@ static void set_display(int value) | |||
632 | { | 639 | { |
633 | /* no sanity check needed for now */ | 640 | /* no sanity check needed for now */ |
634 | if (write_acpi_int(display_set_handle, NULL, value, NULL)) | 641 | if (write_acpi_int(display_set_handle, NULL, value, NULL)) |
635 | printk(ASUS_WARNING "Error setting display\n"); | 642 | pr_warning("Error setting display\n"); |
636 | return; | 643 | return; |
637 | } | 644 | } |
638 | 645 | ||
@@ -647,7 +654,7 @@ static int read_display(void) | |||
647 | rv = acpi_evaluate_integer(display_get_handle, NULL, | 654 | rv = acpi_evaluate_integer(display_get_handle, NULL, |
648 | NULL, &value); | 655 | NULL, &value); |
649 | if (ACPI_FAILURE(rv)) | 656 | if (ACPI_FAILURE(rv)) |
650 | printk(ASUS_WARNING "Error reading display status\n"); | 657 | pr_warning("Error reading display status\n"); |
651 | } | 658 | } |
652 | 659 | ||
653 | value &= 0x0F; /* needed for some models, shouldn't hurt others */ | 660 | value &= 0x0F; /* needed for some models, shouldn't hurt others */ |
@@ -689,7 +696,7 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr, | |||
689 | static void set_light_sens_switch(int value) | 696 | static void set_light_sens_switch(int value) |
690 | { | 697 | { |
691 | if (write_acpi_int(ls_switch_handle, NULL, value, NULL)) | 698 | if (write_acpi_int(ls_switch_handle, NULL, value, NULL)) |
692 | printk(ASUS_WARNING "Error setting light sensor switch\n"); | 699 | pr_warning("Error setting light sensor switch\n"); |
693 | hotk->light_switch = value; | 700 | hotk->light_switch = value; |
694 | } | 701 | } |
695 | 702 | ||
@@ -714,7 +721,7 @@ static ssize_t store_lssw(struct device *dev, struct device_attribute *attr, | |||
714 | static void set_light_sens_level(int value) | 721 | static void set_light_sens_level(int value) |
715 | { | 722 | { |
716 | if (write_acpi_int(ls_level_handle, NULL, value, NULL)) | 723 | if (write_acpi_int(ls_level_handle, NULL, value, NULL)) |
717 | printk(ASUS_WARNING "Error setting light sensor level\n"); | 724 | pr_warning("Error setting light sensor level\n"); |
718 | hotk->light_level = value; | 725 | hotk->light_level = value; |
719 | } | 726 | } |
720 | 727 | ||
@@ -812,7 +819,7 @@ static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode) | |||
812 | return -EINVAL; | 819 | return -EINVAL; |
813 | } | 820 | } |
814 | 821 | ||
815 | static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) | 822 | static void asus_hotk_notify(struct acpi_device *device, u32 event) |
816 | { | 823 | { |
817 | static struct key_entry *key; | 824 | static struct key_entry *key; |
818 | u16 count; | 825 | u16 count; |
@@ -975,11 +982,11 @@ static int asus_hotk_get_info(void) | |||
975 | */ | 982 | */ |
976 | status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus_info); | 983 | status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus_info); |
977 | if (ACPI_FAILURE(status)) | 984 | if (ACPI_FAILURE(status)) |
978 | printk(ASUS_WARNING "Couldn't get the DSDT table header\n"); | 985 | pr_warning("Couldn't get the DSDT table header\n"); |
979 | 986 | ||
980 | /* We have to write 0 on init this far for all ASUS models */ | 987 | /* We have to write 0 on init this far for all ASUS models */ |
981 | if (write_acpi_int(hotk->handle, "INIT", 0, &buffer)) { | 988 | if (write_acpi_int(hotk->handle, "INIT", 0, &buffer)) { |
982 | printk(ASUS_ERR "Hotkey initialization failed\n"); | 989 | pr_err("Hotkey initialization failed\n"); |
983 | return -ENODEV; | 990 | return -ENODEV; |
984 | } | 991 | } |
985 | 992 | ||
@@ -987,9 +994,9 @@ static int asus_hotk_get_info(void) | |||
987 | status = | 994 | status = |
988 | acpi_evaluate_integer(hotk->handle, "BSTS", NULL, &bsts_result); | 995 | acpi_evaluate_integer(hotk->handle, "BSTS", NULL, &bsts_result); |
989 | if (ACPI_FAILURE(status)) | 996 | if (ACPI_FAILURE(status)) |
990 | printk(ASUS_WARNING "Error calling BSTS\n"); | 997 | pr_warning("Error calling BSTS\n"); |
991 | else if (bsts_result) | 998 | else if (bsts_result) |
992 | printk(ASUS_NOTICE "BSTS called, 0x%02x returned\n", | 999 | pr_notice("BSTS called, 0x%02x returned\n", |
993 | (uint) bsts_result); | 1000 | (uint) bsts_result); |
994 | 1001 | ||
995 | /* This too ... */ | 1002 | /* This too ... */ |
@@ -1020,7 +1027,7 @@ static int asus_hotk_get_info(void) | |||
1020 | return -ENOMEM; | 1027 | return -ENOMEM; |
1021 | 1028 | ||
1022 | if (*string) | 1029 | if (*string) |
1023 | printk(ASUS_NOTICE " %s model detected\n", string); | 1030 | pr_notice(" %s model detected\n", string); |
1024 | 1031 | ||
1025 | ASUS_HANDLE_INIT(mled_set); | 1032 | ASUS_HANDLE_INIT(mled_set); |
1026 | ASUS_HANDLE_INIT(tled_set); | 1033 | ASUS_HANDLE_INIT(tled_set); |
@@ -1077,7 +1084,7 @@ static int asus_input_init(void) | |||
1077 | 1084 | ||
1078 | hotk->inputdev = input_allocate_device(); | 1085 | hotk->inputdev = input_allocate_device(); |
1079 | if (!hotk->inputdev) { | 1086 | if (!hotk->inputdev) { |
1080 | printk(ASUS_INFO "Unable to allocate input device\n"); | 1087 | pr_info("Unable to allocate input device\n"); |
1081 | return 0; | 1088 | return 0; |
1082 | } | 1089 | } |
1083 | hotk->inputdev->name = "Asus Laptop extra buttons"; | 1090 | hotk->inputdev->name = "Asus Laptop extra buttons"; |
@@ -1096,7 +1103,7 @@ static int asus_input_init(void) | |||
1096 | } | 1103 | } |
1097 | result = input_register_device(hotk->inputdev); | 1104 | result = input_register_device(hotk->inputdev); |
1098 | if (result) { | 1105 | if (result) { |
1099 | printk(ASUS_INFO "Unable to register input device\n"); | 1106 | pr_info("Unable to register input device\n"); |
1100 | input_free_device(hotk->inputdev); | 1107 | input_free_device(hotk->inputdev); |
1101 | } | 1108 | } |
1102 | return result; | 1109 | return result; |
@@ -1113,7 +1120,7 @@ static int asus_hotk_check(void) | |||
1113 | if (hotk->device->status.present) { | 1120 | if (hotk->device->status.present) { |
1114 | result = asus_hotk_get_info(); | 1121 | result = asus_hotk_get_info(); |
1115 | } else { | 1122 | } else { |
1116 | printk(ASUS_ERR "Hotkey device not present, aborting\n"); | 1123 | pr_err("Hotkey device not present, aborting\n"); |
1117 | return -EINVAL; | 1124 | return -EINVAL; |
1118 | } | 1125 | } |
1119 | 1126 | ||
@@ -1124,13 +1131,12 @@ static int asus_hotk_found; | |||
1124 | 1131 | ||
1125 | static int asus_hotk_add(struct acpi_device *device) | 1132 | static int asus_hotk_add(struct acpi_device *device) |
1126 | { | 1133 | { |
1127 | acpi_status status = AE_OK; | ||
1128 | int result; | 1134 | int result; |
1129 | 1135 | ||
1130 | if (!device) | 1136 | if (!device) |
1131 | return -EINVAL; | 1137 | return -EINVAL; |
1132 | 1138 | ||
1133 | printk(ASUS_NOTICE "Asus Laptop Support version %s\n", | 1139 | pr_notice("Asus Laptop Support version %s\n", |
1134 | ASUS_LAPTOP_VERSION); | 1140 | ASUS_LAPTOP_VERSION); |
1135 | 1141 | ||
1136 | hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL); | 1142 | hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL); |
@@ -1149,15 +1155,6 @@ static int asus_hotk_add(struct acpi_device *device) | |||
1149 | 1155 | ||
1150 | asus_hotk_add_fs(); | 1156 | asus_hotk_add_fs(); |
1151 | 1157 | ||
1152 | /* | ||
1153 | * We install the handler, it will receive the hotk in parameter, so, we | ||
1154 | * could add other data to the hotk struct | ||
1155 | */ | ||
1156 | status = acpi_install_notify_handler(hotk->handle, ACPI_ALL_NOTIFY, | ||
1157 | asus_hotk_notify, hotk); | ||
1158 | if (ACPI_FAILURE(status)) | ||
1159 | printk(ASUS_ERR "Error installing notify handler\n"); | ||
1160 | |||
1161 | asus_hotk_found = 1; | 1158 | asus_hotk_found = 1; |
1162 | 1159 | ||
1163 | /* WLED and BLED are on by default */ | 1160 | /* WLED and BLED are on by default */ |
@@ -1198,16 +1195,9 @@ end: | |||
1198 | 1195 | ||
1199 | static int asus_hotk_remove(struct acpi_device *device, int type) | 1196 | static int asus_hotk_remove(struct acpi_device *device, int type) |
1200 | { | 1197 | { |
1201 | acpi_status status = 0; | ||
1202 | |||
1203 | if (!device || !acpi_driver_data(device)) | 1198 | if (!device || !acpi_driver_data(device)) |
1204 | return -EINVAL; | 1199 | return -EINVAL; |
1205 | 1200 | ||
1206 | status = acpi_remove_notify_handler(hotk->handle, ACPI_ALL_NOTIFY, | ||
1207 | asus_hotk_notify); | ||
1208 | if (ACPI_FAILURE(status)) | ||
1209 | printk(ASUS_ERR "Error removing notify handler\n"); | ||
1210 | |||
1211 | kfree(hotk->name); | 1201 | kfree(hotk->name); |
1212 | kfree(hotk); | 1202 | kfree(hotk); |
1213 | 1203 | ||
@@ -1260,8 +1250,7 @@ static int asus_backlight_init(struct device *dev) | |||
1260 | bd = backlight_device_register(ASUS_HOTK_FILE, dev, | 1250 | bd = backlight_device_register(ASUS_HOTK_FILE, dev, |
1261 | NULL, &asusbl_ops); | 1251 | NULL, &asusbl_ops); |
1262 | if (IS_ERR(bd)) { | 1252 | if (IS_ERR(bd)) { |
1263 | printk(ASUS_ERR | 1253 | pr_err("Could not register asus backlight device\n"); |
1264 | "Could not register asus backlight device\n"); | ||
1265 | asus_backlight_device = NULL; | 1254 | asus_backlight_device = NULL; |
1266 | return PTR_ERR(bd); | 1255 | return PTR_ERR(bd); |
1267 | } | 1256 | } |
@@ -1334,7 +1323,6 @@ out: | |||
1334 | 1323 | ||
1335 | static int __init asus_laptop_init(void) | 1324 | static int __init asus_laptop_init(void) |
1336 | { | 1325 | { |
1337 | struct device *dev; | ||
1338 | int result; | 1326 | int result; |
1339 | 1327 | ||
1340 | if (acpi_disabled) | 1328 | if (acpi_disabled) |
@@ -1356,24 +1344,10 @@ static int __init asus_laptop_init(void) | |||
1356 | return -ENODEV; | 1344 | return -ENODEV; |
1357 | } | 1345 | } |
1358 | 1346 | ||
1359 | dev = acpi_get_physical_device(hotk->device->handle); | ||
1360 | |||
1361 | if (!acpi_video_backlight_support()) { | ||
1362 | result = asus_backlight_init(dev); | ||
1363 | if (result) | ||
1364 | goto fail_backlight; | ||
1365 | } else | ||
1366 | printk(ASUS_INFO "Brightness ignored, must be controlled by " | ||
1367 | "ACPI video driver\n"); | ||
1368 | |||
1369 | result = asus_input_init(); | 1347 | result = asus_input_init(); |
1370 | if (result) | 1348 | if (result) |
1371 | goto fail_input; | 1349 | goto fail_input; |
1372 | 1350 | ||
1373 | result = asus_led_init(dev); | ||
1374 | if (result) | ||
1375 | goto fail_led; | ||
1376 | |||
1377 | /* Register platform stuff */ | 1351 | /* Register platform stuff */ |
1378 | result = platform_driver_register(&asuspf_driver); | 1352 | result = platform_driver_register(&asuspf_driver); |
1379 | if (result) | 1353 | if (result) |
@@ -1394,8 +1368,27 @@ static int __init asus_laptop_init(void) | |||
1394 | if (result) | 1368 | if (result) |
1395 | goto fail_sysfs; | 1369 | goto fail_sysfs; |
1396 | 1370 | ||
1371 | result = asus_led_init(&asuspf_device->dev); | ||
1372 | if (result) | ||
1373 | goto fail_led; | ||
1374 | |||
1375 | if (!acpi_video_backlight_support()) { | ||
1376 | result = asus_backlight_init(&asuspf_device->dev); | ||
1377 | if (result) | ||
1378 | goto fail_backlight; | ||
1379 | } else | ||
1380 | pr_info("Brightness ignored, must be controlled by " | ||
1381 | "ACPI video driver\n"); | ||
1382 | |||
1397 | return 0; | 1383 | return 0; |
1398 | 1384 | ||
1385 | fail_backlight: | ||
1386 | asus_led_exit(); | ||
1387 | |||
1388 | fail_led: | ||
1389 | sysfs_remove_group(&asuspf_device->dev.kobj, | ||
1390 | &asuspf_attribute_group); | ||
1391 | |||
1399 | fail_sysfs: | 1392 | fail_sysfs: |
1400 | platform_device_del(asuspf_device); | 1393 | platform_device_del(asuspf_device); |
1401 | 1394 | ||
@@ -1406,15 +1399,9 @@ fail_platform_device1: | |||
1406 | platform_driver_unregister(&asuspf_driver); | 1399 | platform_driver_unregister(&asuspf_driver); |
1407 | 1400 | ||
1408 | fail_platform_driver: | 1401 | fail_platform_driver: |
1409 | asus_led_exit(); | ||
1410 | |||
1411 | fail_led: | ||
1412 | asus_input_exit(); | 1402 | asus_input_exit(); |
1413 | 1403 | ||
1414 | fail_input: | 1404 | fail_input: |
1415 | asus_backlight_exit(); | ||
1416 | |||
1417 | fail_backlight: | ||
1418 | 1405 | ||
1419 | return result; | 1406 | return result; |
1420 | } | 1407 | } |
diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c index ba1f7497e4b9..ddf5240ade8c 100644 --- a/drivers/platform/x86/asus_acpi.c +++ b/drivers/platform/x86/asus_acpi.c | |||
@@ -455,6 +455,8 @@ static struct asus_hotk *hotk; | |||
455 | */ | 455 | */ |
456 | static int asus_hotk_add(struct acpi_device *device); | 456 | static int asus_hotk_add(struct acpi_device *device); |
457 | static int asus_hotk_remove(struct acpi_device *device, int type); | 457 | static int asus_hotk_remove(struct acpi_device *device, int type); |
458 | static void asus_hotk_notify(struct acpi_device *device, u32 event); | ||
459 | |||
458 | static const struct acpi_device_id asus_device_ids[] = { | 460 | static const struct acpi_device_id asus_device_ids[] = { |
459 | {"ATK0100", 0}, | 461 | {"ATK0100", 0}, |
460 | {"", 0}, | 462 | {"", 0}, |
@@ -465,9 +467,11 @@ static struct acpi_driver asus_hotk_driver = { | |||
465 | .name = "asus_acpi", | 467 | .name = "asus_acpi", |
466 | .class = ACPI_HOTK_CLASS, | 468 | .class = ACPI_HOTK_CLASS, |
467 | .ids = asus_device_ids, | 469 | .ids = asus_device_ids, |
470 | .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, | ||
468 | .ops = { | 471 | .ops = { |
469 | .add = asus_hotk_add, | 472 | .add = asus_hotk_add, |
470 | .remove = asus_hotk_remove, | 473 | .remove = asus_hotk_remove, |
474 | .notify = asus_hotk_notify, | ||
471 | }, | 475 | }, |
472 | }; | 476 | }; |
473 | 477 | ||
@@ -1101,12 +1105,20 @@ static int asus_hotk_remove_fs(struct acpi_device *device) | |||
1101 | return 0; | 1105 | return 0; |
1102 | } | 1106 | } |
1103 | 1107 | ||
1104 | static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) | 1108 | static void asus_hotk_notify(struct acpi_device *device, u32 event) |
1105 | { | 1109 | { |
1106 | /* TODO Find a better way to handle events count. */ | 1110 | /* TODO Find a better way to handle events count. */ |
1107 | if (!hotk) | 1111 | if (!hotk) |
1108 | return; | 1112 | return; |
1109 | 1113 | ||
1114 | /* | ||
1115 | * The BIOS *should* be sending us device events, but apparently | ||
1116 | * Asus uses system events instead, so just ignore any device | ||
1117 | * events we get. | ||
1118 | */ | ||
1119 | if (event > ACPI_MAX_SYS_NOTIFY) | ||
1120 | return; | ||
1121 | |||
1110 | if ((event & ~((u32) BR_UP)) < 16) | 1122 | if ((event & ~((u32) BR_UP)) < 16) |
1111 | hotk->brightness = (event & ~((u32) BR_UP)); | 1123 | hotk->brightness = (event & ~((u32) BR_UP)); |
1112 | else if ((event & ~((u32) BR_DOWN)) < 16) | 1124 | else if ((event & ~((u32) BR_DOWN)) < 16) |
@@ -1346,15 +1358,6 @@ static int asus_hotk_add(struct acpi_device *device) | |||
1346 | if (result) | 1358 | if (result) |
1347 | goto end; | 1359 | goto end; |
1348 | 1360 | ||
1349 | /* | ||
1350 | * We install the handler, it will receive the hotk in parameter, so, we | ||
1351 | * could add other data to the hotk struct | ||
1352 | */ | ||
1353 | status = acpi_install_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY, | ||
1354 | asus_hotk_notify, hotk); | ||
1355 | if (ACPI_FAILURE(status)) | ||
1356 | printk(KERN_ERR " Error installing notify handler\n"); | ||
1357 | |||
1358 | /* For laptops without GPLV: init the hotk->brightness value */ | 1361 | /* For laptops without GPLV: init the hotk->brightness value */ |
1359 | if ((!hotk->methods->brightness_get) | 1362 | if ((!hotk->methods->brightness_get) |
1360 | && (!hotk->methods->brightness_status) | 1363 | && (!hotk->methods->brightness_status) |
@@ -1389,16 +1392,9 @@ end: | |||
1389 | 1392 | ||
1390 | static int asus_hotk_remove(struct acpi_device *device, int type) | 1393 | static int asus_hotk_remove(struct acpi_device *device, int type) |
1391 | { | 1394 | { |
1392 | acpi_status status = 0; | ||
1393 | |||
1394 | if (!device || !acpi_driver_data(device)) | 1395 | if (!device || !acpi_driver_data(device)) |
1395 | return -EINVAL; | 1396 | return -EINVAL; |
1396 | 1397 | ||
1397 | status = acpi_remove_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY, | ||
1398 | asus_hotk_notify); | ||
1399 | if (ACPI_FAILURE(status)) | ||
1400 | printk(KERN_ERR "Asus ACPI: Error removing notify handler\n"); | ||
1401 | |||
1402 | asus_hotk_remove_fs(device); | 1398 | asus_hotk_remove_fs(device); |
1403 | 1399 | ||
1404 | kfree(hotk); | 1400 | kfree(hotk); |
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 2fab94162147..0f900cc9fa7a 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c | |||
@@ -46,10 +46,53 @@ struct key_entry { | |||
46 | u16 keycode; | 46 | u16 keycode; |
47 | }; | 47 | }; |
48 | 48 | ||
49 | enum { KE_KEY, KE_SW, KE_END }; | 49 | enum { KE_KEY, KE_SW, KE_IGNORE, KE_END }; |
50 | |||
51 | /* | ||
52 | * Certain keys are flagged as KE_IGNORE. All of these are either | ||
53 | * notifications (rather than requests for change) or are also sent | ||
54 | * via the keyboard controller so should not be sent again. | ||
55 | */ | ||
50 | 56 | ||
51 | static struct key_entry dell_wmi_keymap[] = { | 57 | static struct key_entry dell_wmi_keymap[] = { |
52 | {KE_KEY, 0xe045, KEY_PROG1}, | 58 | {KE_KEY, 0xe045, KEY_PROG1}, |
59 | {KE_KEY, 0xe009, KEY_EJECTCD}, | ||
60 | |||
61 | /* These also contain the brightness level at offset 6 */ | ||
62 | {KE_KEY, 0xe006, KEY_BRIGHTNESSUP}, | ||
63 | {KE_KEY, 0xe005, KEY_BRIGHTNESSDOWN}, | ||
64 | |||
65 | /* Battery health status button */ | ||
66 | {KE_KEY, 0xe007, KEY_BATTERY}, | ||
67 | |||
68 | /* This is actually for all radios. Although physically a | ||
69 | * switch, the notification does not provide an indication of | ||
70 | * state and so it should be reported as a key */ | ||
71 | {KE_KEY, 0xe008, KEY_WLAN}, | ||
72 | |||
73 | /* The next device is at offset 6, the active devices are at | ||
74 | offset 8 and the attached devices at offset 10 */ | ||
75 | {KE_KEY, 0xe00b, KEY_DISPLAYTOGGLE}, | ||
76 | |||
77 | {KE_IGNORE, 0xe00c, KEY_KBDILLUMTOGGLE}, | ||
78 | |||
79 | /* BIOS error detected */ | ||
80 | {KE_IGNORE, 0xe00d, KEY_RESERVED}, | ||
81 | |||
82 | /* Wifi Catcher */ | ||
83 | {KE_KEY, 0xe011, KEY_PROG2}, | ||
84 | |||
85 | /* Ambient light sensor toggle */ | ||
86 | {KE_IGNORE, 0xe013, KEY_RESERVED}, | ||
87 | |||
88 | {KE_IGNORE, 0xe020, KEY_MUTE}, | ||
89 | {KE_IGNORE, 0xe02e, KEY_VOLUMEDOWN}, | ||
90 | {KE_IGNORE, 0xe030, KEY_VOLUMEUP}, | ||
91 | {KE_IGNORE, 0xe033, KEY_KBDILLUMUP}, | ||
92 | {KE_IGNORE, 0xe034, KEY_KBDILLUMDOWN}, | ||
93 | {KE_IGNORE, 0xe03a, KEY_CAPSLOCK}, | ||
94 | {KE_IGNORE, 0xe045, KEY_NUMLOCK}, | ||
95 | {KE_IGNORE, 0xe046, KEY_SCROLLLOCK}, | ||
53 | {KE_END, 0} | 96 | {KE_END, 0} |
54 | }; | 97 | }; |
55 | 98 | ||
@@ -122,15 +165,20 @@ static void dell_wmi_notify(u32 value, void *context) | |||
122 | 165 | ||
123 | if (obj && obj->type == ACPI_TYPE_BUFFER) { | 166 | if (obj && obj->type == ACPI_TYPE_BUFFER) { |
124 | int *buffer = (int *)obj->buffer.pointer; | 167 | int *buffer = (int *)obj->buffer.pointer; |
125 | key = dell_wmi_get_entry_by_scancode(buffer[1]); | 168 | /* |
169 | * The upper bytes of the event may contain | ||
170 | * additional information, so mask them off for the | ||
171 | * scancode lookup | ||
172 | */ | ||
173 | key = dell_wmi_get_entry_by_scancode(buffer[1] & 0xFFFF); | ||
126 | if (key) { | 174 | if (key) { |
127 | input_report_key(dell_wmi_input_dev, key->keycode, 1); | 175 | input_report_key(dell_wmi_input_dev, key->keycode, 1); |
128 | input_sync(dell_wmi_input_dev); | 176 | input_sync(dell_wmi_input_dev); |
129 | input_report_key(dell_wmi_input_dev, key->keycode, 0); | 177 | input_report_key(dell_wmi_input_dev, key->keycode, 0); |
130 | input_sync(dell_wmi_input_dev); | 178 | input_sync(dell_wmi_input_dev); |
131 | } else | 179 | } else if (buffer[1] & 0xFFFF) |
132 | printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n", | 180 | printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n", |
133 | buffer[1]); | 181 | buffer[1] & 0xFFFF); |
134 | } | 182 | } |
135 | } | 183 | } |
136 | 184 | ||
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 8153b3e59189..4207b26ff990 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
@@ -62,7 +62,10 @@ enum { | |||
62 | DISABLE_ASL_GPS = 0x0020, | 62 | DISABLE_ASL_GPS = 0x0020, |
63 | DISABLE_ASL_DISPLAYSWITCH = 0x0040, | 63 | DISABLE_ASL_DISPLAYSWITCH = 0x0040, |
64 | DISABLE_ASL_MODEM = 0x0080, | 64 | DISABLE_ASL_MODEM = 0x0080, |
65 | DISABLE_ASL_CARDREADER = 0x0100 | 65 | DISABLE_ASL_CARDREADER = 0x0100, |
66 | DISABLE_ASL_3G = 0x0200, | ||
67 | DISABLE_ASL_WIMAX = 0x0400, | ||
68 | DISABLE_ASL_HWCF = 0x0800 | ||
66 | }; | 69 | }; |
67 | 70 | ||
68 | enum { | 71 | enum { |
@@ -87,7 +90,13 @@ enum { | |||
87 | CM_ASL_USBPORT3, | 90 | CM_ASL_USBPORT3, |
88 | CM_ASL_MODEM, | 91 | CM_ASL_MODEM, |
89 | CM_ASL_CARDREADER, | 92 | CM_ASL_CARDREADER, |
90 | CM_ASL_LID | 93 | CM_ASL_3G, |
94 | CM_ASL_WIMAX, | ||
95 | CM_ASL_HWCF, | ||
96 | CM_ASL_LID, | ||
97 | CM_ASL_TYPE, | ||
98 | CM_ASL_PANELPOWER, /*P901*/ | ||
99 | CM_ASL_TPD | ||
91 | }; | 100 | }; |
92 | 101 | ||
93 | static const char *cm_getv[] = { | 102 | static const char *cm_getv[] = { |
@@ -96,7 +105,8 @@ static const char *cm_getv[] = { | |||
96 | NULL, "PBLG", NULL, NULL, | 105 | NULL, "PBLG", NULL, NULL, |
97 | "CFVG", NULL, NULL, NULL, | 106 | "CFVG", NULL, NULL, NULL, |
98 | "USBG", NULL, NULL, "MODG", | 107 | "USBG", NULL, NULL, "MODG", |
99 | "CRDG", "LIDG" | 108 | "CRDG", "M3GG", "WIMG", "HWCF", |
109 | "LIDG", "TYPE", "PBPG", "TPDG" | ||
100 | }; | 110 | }; |
101 | 111 | ||
102 | static const char *cm_setv[] = { | 112 | static const char *cm_setv[] = { |
@@ -105,7 +115,8 @@ static const char *cm_setv[] = { | |||
105 | "SDSP", "PBLS", "HDPS", NULL, | 115 | "SDSP", "PBLS", "HDPS", NULL, |
106 | "CFVS", NULL, NULL, NULL, | 116 | "CFVS", NULL, NULL, NULL, |
107 | "USBG", NULL, NULL, "MODS", | 117 | "USBG", NULL, NULL, "MODS", |
108 | "CRDS", NULL | 118 | "CRDS", "M3GS", "WIMS", NULL, |
119 | NULL, NULL, "PBPS", "TPDS" | ||
109 | }; | 120 | }; |
110 | 121 | ||
111 | #define EEEPC_EC "\\_SB.PCI0.SBRG.EC0." | 122 | #define EEEPC_EC "\\_SB.PCI0.SBRG.EC0." |
@@ -181,6 +192,7 @@ static struct key_entry eeepc_keymap[] = { | |||
181 | static int eeepc_hotk_add(struct acpi_device *device); | 192 | static int eeepc_hotk_add(struct acpi_device *device); |
182 | static int eeepc_hotk_remove(struct acpi_device *device, int type); | 193 | static int eeepc_hotk_remove(struct acpi_device *device, int type); |
183 | static int eeepc_hotk_resume(struct acpi_device *device); | 194 | static int eeepc_hotk_resume(struct acpi_device *device); |
195 | static void eeepc_hotk_notify(struct acpi_device *device, u32 event); | ||
184 | 196 | ||
185 | static const struct acpi_device_id eeepc_device_ids[] = { | 197 | static const struct acpi_device_id eeepc_device_ids[] = { |
186 | {EEEPC_HOTK_HID, 0}, | 198 | {EEEPC_HOTK_HID, 0}, |
@@ -192,10 +204,12 @@ static struct acpi_driver eeepc_hotk_driver = { | |||
192 | .name = EEEPC_HOTK_NAME, | 204 | .name = EEEPC_HOTK_NAME, |
193 | .class = EEEPC_HOTK_CLASS, | 205 | .class = EEEPC_HOTK_CLASS, |
194 | .ids = eeepc_device_ids, | 206 | .ids = eeepc_device_ids, |
207 | .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, | ||
195 | .ops = { | 208 | .ops = { |
196 | .add = eeepc_hotk_add, | 209 | .add = eeepc_hotk_add, |
197 | .remove = eeepc_hotk_remove, | 210 | .remove = eeepc_hotk_remove, |
198 | .resume = eeepc_hotk_resume, | 211 | .resume = eeepc_hotk_resume, |
212 | .notify = eeepc_hotk_notify, | ||
199 | }, | 213 | }, |
200 | }; | 214 | }; |
201 | 215 | ||
@@ -318,6 +332,15 @@ static const struct rfkill_ops eeepc_rfkill_ops = { | |||
318 | .set_block = eeepc_rfkill_set, | 332 | .set_block = eeepc_rfkill_set, |
319 | }; | 333 | }; |
320 | 334 | ||
335 | static void __init eeepc_enable_camera(void) | ||
336 | { | ||
337 | /* | ||
338 | * If the following call to set_acpi() fails, it's because there's no | ||
339 | * camera so we can ignore the error. | ||
340 | */ | ||
341 | set_acpi(CM_ASL_CAMERA, 1); | ||
342 | } | ||
343 | |||
321 | /* | 344 | /* |
322 | * Sys helpers | 345 | * Sys helpers |
323 | */ | 346 | */ |
@@ -369,13 +392,88 @@ static ssize_t show_sys_acpi(int cm, char *buf) | |||
369 | EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA); | 392 | EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA); |
370 | EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER); | 393 | EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER); |
371 | EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH); | 394 | EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH); |
372 | EEEPC_CREATE_DEVICE_ATTR(cpufv, CM_ASL_CPUFV); | 395 | |
396 | struct eeepc_cpufv { | ||
397 | int num; | ||
398 | int cur; | ||
399 | }; | ||
400 | |||
401 | static int get_cpufv(struct eeepc_cpufv *c) | ||
402 | { | ||
403 | c->cur = get_acpi(CM_ASL_CPUFV); | ||
404 | c->num = (c->cur >> 8) & 0xff; | ||
405 | c->cur &= 0xff; | ||
406 | if (c->cur < 0 || c->num <= 0 || c->num > 12) | ||
407 | return -ENODEV; | ||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | static ssize_t show_available_cpufv(struct device *dev, | ||
412 | struct device_attribute *attr, | ||
413 | char *buf) | ||
414 | { | ||
415 | struct eeepc_cpufv c; | ||
416 | int i; | ||
417 | ssize_t len = 0; | ||
418 | |||
419 | if (get_cpufv(&c)) | ||
420 | return -ENODEV; | ||
421 | for (i = 0; i < c.num; i++) | ||
422 | len += sprintf(buf + len, "%d ", i); | ||
423 | len += sprintf(buf + len, "\n"); | ||
424 | return len; | ||
425 | } | ||
426 | |||
427 | static ssize_t show_cpufv(struct device *dev, | ||
428 | struct device_attribute *attr, | ||
429 | char *buf) | ||
430 | { | ||
431 | struct eeepc_cpufv c; | ||
432 | |||
433 | if (get_cpufv(&c)) | ||
434 | return -ENODEV; | ||
435 | return sprintf(buf, "%#x\n", (c.num << 8) | c.cur); | ||
436 | } | ||
437 | |||
438 | static ssize_t store_cpufv(struct device *dev, | ||
439 | struct device_attribute *attr, | ||
440 | const char *buf, size_t count) | ||
441 | { | ||
442 | struct eeepc_cpufv c; | ||
443 | int rv, value; | ||
444 | |||
445 | if (get_cpufv(&c)) | ||
446 | return -ENODEV; | ||
447 | rv = parse_arg(buf, count, &value); | ||
448 | if (rv < 0) | ||
449 | return rv; | ||
450 | if (!rv || value < 0 || value >= c.num) | ||
451 | return -EINVAL; | ||
452 | set_acpi(CM_ASL_CPUFV, value); | ||
453 | return rv; | ||
454 | } | ||
455 | |||
456 | static struct device_attribute dev_attr_cpufv = { | ||
457 | .attr = { | ||
458 | .name = "cpufv", | ||
459 | .mode = 0644 }, | ||
460 | .show = show_cpufv, | ||
461 | .store = store_cpufv | ||
462 | }; | ||
463 | |||
464 | static struct device_attribute dev_attr_available_cpufv = { | ||
465 | .attr = { | ||
466 | .name = "available_cpufv", | ||
467 | .mode = 0444 }, | ||
468 | .show = show_available_cpufv | ||
469 | }; | ||
373 | 470 | ||
374 | static struct attribute *platform_attributes[] = { | 471 | static struct attribute *platform_attributes[] = { |
375 | &dev_attr_camera.attr, | 472 | &dev_attr_camera.attr, |
376 | &dev_attr_cardr.attr, | 473 | &dev_attr_cardr.attr, |
377 | &dev_attr_disp.attr, | 474 | &dev_attr_disp.attr, |
378 | &dev_attr_cpufv.attr, | 475 | &dev_attr_cpufv.attr, |
476 | &dev_attr_available_cpufv.attr, | ||
379 | NULL | 477 | NULL |
380 | }; | 478 | }; |
381 | 479 | ||
@@ -558,7 +656,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) | |||
558 | eeepc_rfkill_hotplug(); | 656 | eeepc_rfkill_hotplug(); |
559 | } | 657 | } |
560 | 658 | ||
561 | static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) | 659 | static void eeepc_hotk_notify(struct acpi_device *device, u32 event) |
562 | { | 660 | { |
563 | static struct key_entry *key; | 661 | static struct key_entry *key; |
564 | u16 count; | 662 | u16 count; |
@@ -566,6 +664,8 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) | |||
566 | 664 | ||
567 | if (!ehotk) | 665 | if (!ehotk) |
568 | return; | 666 | return; |
667 | if (event > ACPI_MAX_SYS_NOTIFY) | ||
668 | return; | ||
569 | if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) | 669 | if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) |
570 | brn = notify_brn(); | 670 | brn = notify_brn(); |
571 | count = ehotk->event_count[event % 128]++; | 671 | count = ehotk->event_count[event % 128]++; |
@@ -646,7 +746,6 @@ static void eeepc_unregister_rfkill_notifier(char *node) | |||
646 | 746 | ||
647 | static int eeepc_hotk_add(struct acpi_device *device) | 747 | static int eeepc_hotk_add(struct acpi_device *device) |
648 | { | 748 | { |
649 | acpi_status status = AE_OK; | ||
650 | int result; | 749 | int result; |
651 | 750 | ||
652 | if (!device) | 751 | if (!device) |
@@ -664,10 +763,6 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
664 | result = eeepc_hotk_check(); | 763 | result = eeepc_hotk_check(); |
665 | if (result) | 764 | if (result) |
666 | goto ehotk_fail; | 765 | goto ehotk_fail; |
667 | status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY, | ||
668 | eeepc_hotk_notify, ehotk); | ||
669 | if (ACPI_FAILURE(status)) | ||
670 | printk(EEEPC_ERR "Error installing notify handler\n"); | ||
671 | 766 | ||
672 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); | 767 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); |
673 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); | 768 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); |
@@ -725,14 +820,8 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
725 | 820 | ||
726 | static int eeepc_hotk_remove(struct acpi_device *device, int type) | 821 | static int eeepc_hotk_remove(struct acpi_device *device, int type) |
727 | { | 822 | { |
728 | acpi_status status = 0; | ||
729 | |||
730 | if (!device || !acpi_driver_data(device)) | 823 | if (!device || !acpi_driver_data(device)) |
731 | return -EINVAL; | 824 | return -EINVAL; |
732 | status = acpi_remove_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY, | ||
733 | eeepc_hotk_notify); | ||
734 | if (ACPI_FAILURE(status)) | ||
735 | printk(EEEPC_ERR "Error removing notify handler\n"); | ||
736 | 825 | ||
737 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); | 826 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); |
738 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); | 827 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); |
@@ -989,6 +1078,9 @@ static int __init eeepc_laptop_init(void) | |||
989 | result = eeepc_hwmon_init(dev); | 1078 | result = eeepc_hwmon_init(dev); |
990 | if (result) | 1079 | if (result) |
991 | goto fail_hwmon; | 1080 | goto fail_hwmon; |
1081 | |||
1082 | eeepc_enable_camera(); | ||
1083 | |||
992 | /* Register platform stuff */ | 1084 | /* Register platform stuff */ |
993 | result = platform_driver_register(&platform_driver); | 1085 | result = platform_driver_register(&platform_driver); |
994 | if (result) | 1086 | if (result) |
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 16fffe44e333..4ac2311c00af 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c | |||
@@ -47,7 +47,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4"); | |||
47 | #define HPWMI_DISPLAY_QUERY 0x1 | 47 | #define HPWMI_DISPLAY_QUERY 0x1 |
48 | #define HPWMI_HDDTEMP_QUERY 0x2 | 48 | #define HPWMI_HDDTEMP_QUERY 0x2 |
49 | #define HPWMI_ALS_QUERY 0x3 | 49 | #define HPWMI_ALS_QUERY 0x3 |
50 | #define HPWMI_DOCK_QUERY 0x4 | 50 | #define HPWMI_HARDWARE_QUERY 0x4 |
51 | #define HPWMI_WIRELESS_QUERY 0x5 | 51 | #define HPWMI_WIRELESS_QUERY 0x5 |
52 | #define HPWMI_HOTKEY_QUERY 0xc | 52 | #define HPWMI_HOTKEY_QUERY 0xc |
53 | 53 | ||
@@ -75,10 +75,9 @@ struct key_entry { | |||
75 | u16 keycode; | 75 | u16 keycode; |
76 | }; | 76 | }; |
77 | 77 | ||
78 | enum { KE_KEY, KE_SW, KE_END }; | 78 | enum { KE_KEY, KE_END }; |
79 | 79 | ||
80 | static struct key_entry hp_wmi_keymap[] = { | 80 | static struct key_entry hp_wmi_keymap[] = { |
81 | {KE_SW, 0x01, SW_DOCK}, | ||
82 | {KE_KEY, 0x02, KEY_BRIGHTNESSUP}, | 81 | {KE_KEY, 0x02, KEY_BRIGHTNESSUP}, |
83 | {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN}, | 82 | {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN}, |
84 | {KE_KEY, 0x20e6, KEY_PROG1}, | 83 | {KE_KEY, 0x20e6, KEY_PROG1}, |
@@ -151,7 +150,22 @@ static int hp_wmi_als_state(void) | |||
151 | 150 | ||
152 | static int hp_wmi_dock_state(void) | 151 | static int hp_wmi_dock_state(void) |
153 | { | 152 | { |
154 | return hp_wmi_perform_query(HPWMI_DOCK_QUERY, 0, 0); | 153 | int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, 0); |
154 | |||
155 | if (ret < 0) | ||
156 | return ret; | ||
157 | |||
158 | return ret & 0x1; | ||
159 | } | ||
160 | |||
161 | static int hp_wmi_tablet_state(void) | ||
162 | { | ||
163 | int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, 0); | ||
164 | |||
165 | if (ret < 0) | ||
166 | return ret; | ||
167 | |||
168 | return (ret & 0x4) ? 1 : 0; | ||
155 | } | 169 | } |
156 | 170 | ||
157 | static int hp_wmi_set_block(void *data, bool blocked) | 171 | static int hp_wmi_set_block(void *data, bool blocked) |
@@ -232,6 +246,15 @@ static ssize_t show_dock(struct device *dev, struct device_attribute *attr, | |||
232 | return sprintf(buf, "%d\n", value); | 246 | return sprintf(buf, "%d\n", value); |
233 | } | 247 | } |
234 | 248 | ||
249 | static ssize_t show_tablet(struct device *dev, struct device_attribute *attr, | ||
250 | char *buf) | ||
251 | { | ||
252 | int value = hp_wmi_tablet_state(); | ||
253 | if (value < 0) | ||
254 | return -EINVAL; | ||
255 | return sprintf(buf, "%d\n", value); | ||
256 | } | ||
257 | |||
235 | static ssize_t set_als(struct device *dev, struct device_attribute *attr, | 258 | static ssize_t set_als(struct device *dev, struct device_attribute *attr, |
236 | const char *buf, size_t count) | 259 | const char *buf, size_t count) |
237 | { | 260 | { |
@@ -244,6 +267,7 @@ static DEVICE_ATTR(display, S_IRUGO, show_display, NULL); | |||
244 | static DEVICE_ATTR(hddtemp, S_IRUGO, show_hddtemp, NULL); | 267 | static DEVICE_ATTR(hddtemp, S_IRUGO, show_hddtemp, NULL); |
245 | static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als); | 268 | static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als); |
246 | static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL); | 269 | static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL); |
270 | static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL); | ||
247 | 271 | ||
248 | static struct key_entry *hp_wmi_get_entry_by_scancode(int code) | 272 | static struct key_entry *hp_wmi_get_entry_by_scancode(int code) |
249 | { | 273 | { |
@@ -326,13 +350,13 @@ static void hp_wmi_notify(u32 value, void *context) | |||
326 | key->keycode, 0); | 350 | key->keycode, 0); |
327 | input_sync(hp_wmi_input_dev); | 351 | input_sync(hp_wmi_input_dev); |
328 | break; | 352 | break; |
329 | case KE_SW: | ||
330 | input_report_switch(hp_wmi_input_dev, | ||
331 | key->keycode, | ||
332 | hp_wmi_dock_state()); | ||
333 | input_sync(hp_wmi_input_dev); | ||
334 | break; | ||
335 | } | 353 | } |
354 | } else if (eventcode == 0x1) { | ||
355 | input_report_switch(hp_wmi_input_dev, SW_DOCK, | ||
356 | hp_wmi_dock_state()); | ||
357 | input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, | ||
358 | hp_wmi_tablet_state()); | ||
359 | input_sync(hp_wmi_input_dev); | ||
336 | } else if (eventcode == 0x5) { | 360 | } else if (eventcode == 0x5) { |
337 | if (wifi_rfkill) | 361 | if (wifi_rfkill) |
338 | rfkill_set_sw_state(wifi_rfkill, | 362 | rfkill_set_sw_state(wifi_rfkill, |
@@ -369,18 +393,19 @@ static int __init hp_wmi_input_setup(void) | |||
369 | set_bit(EV_KEY, hp_wmi_input_dev->evbit); | 393 | set_bit(EV_KEY, hp_wmi_input_dev->evbit); |
370 | set_bit(key->keycode, hp_wmi_input_dev->keybit); | 394 | set_bit(key->keycode, hp_wmi_input_dev->keybit); |
371 | break; | 395 | break; |
372 | case KE_SW: | ||
373 | set_bit(EV_SW, hp_wmi_input_dev->evbit); | ||
374 | set_bit(key->keycode, hp_wmi_input_dev->swbit); | ||
375 | |||
376 | /* Set initial dock state */ | ||
377 | input_report_switch(hp_wmi_input_dev, key->keycode, | ||
378 | hp_wmi_dock_state()); | ||
379 | input_sync(hp_wmi_input_dev); | ||
380 | break; | ||
381 | } | 396 | } |
382 | } | 397 | } |
383 | 398 | ||
399 | set_bit(EV_SW, hp_wmi_input_dev->evbit); | ||
400 | set_bit(SW_DOCK, hp_wmi_input_dev->swbit); | ||
401 | set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit); | ||
402 | |||
403 | /* Set initial hardware state */ | ||
404 | input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state()); | ||
405 | input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, | ||
406 | hp_wmi_tablet_state()); | ||
407 | input_sync(hp_wmi_input_dev); | ||
408 | |||
384 | err = input_register_device(hp_wmi_input_dev); | 409 | err = input_register_device(hp_wmi_input_dev); |
385 | 410 | ||
386 | if (err) { | 411 | if (err) { |
@@ -397,6 +422,7 @@ static void cleanup_sysfs(struct platform_device *device) | |||
397 | device_remove_file(&device->dev, &dev_attr_hddtemp); | 422 | device_remove_file(&device->dev, &dev_attr_hddtemp); |
398 | device_remove_file(&device->dev, &dev_attr_als); | 423 | device_remove_file(&device->dev, &dev_attr_als); |
399 | device_remove_file(&device->dev, &dev_attr_dock); | 424 | device_remove_file(&device->dev, &dev_attr_dock); |
425 | device_remove_file(&device->dev, &dev_attr_tablet); | ||
400 | } | 426 | } |
401 | 427 | ||
402 | static int __init hp_wmi_bios_setup(struct platform_device *device) | 428 | static int __init hp_wmi_bios_setup(struct platform_device *device) |
@@ -416,6 +442,9 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) | |||
416 | err = device_create_file(&device->dev, &dev_attr_dock); | 442 | err = device_create_file(&device->dev, &dev_attr_dock); |
417 | if (err) | 443 | if (err) |
418 | goto add_sysfs_error; | 444 | goto add_sysfs_error; |
445 | err = device_create_file(&device->dev, &dev_attr_tablet); | ||
446 | if (err) | ||
447 | goto add_sysfs_error; | ||
419 | 448 | ||
420 | if (wireless & 0x1) { | 449 | if (wireless & 0x1) { |
421 | wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev, | 450 | wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev, |
@@ -485,23 +514,17 @@ static int __exit hp_wmi_bios_remove(struct platform_device *device) | |||
485 | 514 | ||
486 | static int hp_wmi_resume_handler(struct platform_device *device) | 515 | static int hp_wmi_resume_handler(struct platform_device *device) |
487 | { | 516 | { |
488 | struct key_entry *key; | ||
489 | |||
490 | /* | 517 | /* |
491 | * Docking state may have changed while suspended, so trigger | 518 | * Hardware state may have changed while suspended, so trigger |
492 | * an input event for the current state. As this is a switch, | 519 | * input events for the current state. As this is a switch, |
493 | * the input layer will only actually pass it on if the state | 520 | * the input layer will only actually pass it on if the state |
494 | * changed. | 521 | * changed. |
495 | */ | 522 | */ |
496 | for (key = hp_wmi_keymap; key->type != KE_END; key++) { | 523 | |
497 | switch (key->type) { | 524 | input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state()); |
498 | case KE_SW: | 525 | input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, |
499 | input_report_switch(hp_wmi_input_dev, key->keycode, | 526 | hp_wmi_tablet_state()); |
500 | hp_wmi_dock_state()); | 527 | input_sync(hp_wmi_input_dev); |
501 | input_sync(hp_wmi_input_dev); | ||
502 | break; | ||
503 | } | ||
504 | } | ||
505 | 528 | ||
506 | return 0; | 529 | return 0; |
507 | } | 530 | } |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 40d64c03278c..a463fd72c495 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
@@ -22,7 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #define TPACPI_VERSION "0.23" | 24 | #define TPACPI_VERSION "0.23" |
25 | #define TPACPI_SYSFS_VERSION 0x020300 | 25 | #define TPACPI_SYSFS_VERSION 0x020400 |
26 | 26 | ||
27 | /* | 27 | /* |
28 | * Changelog: | 28 | * Changelog: |
@@ -257,6 +257,8 @@ static struct { | |||
257 | u32 wan:1; | 257 | u32 wan:1; |
258 | u32 uwb:1; | 258 | u32 uwb:1; |
259 | u32 fan_ctrl_status_undef:1; | 259 | u32 fan_ctrl_status_undef:1; |
260 | u32 second_fan:1; | ||
261 | u32 beep_needs_two_args:1; | ||
260 | u32 input_device_registered:1; | 262 | u32 input_device_registered:1; |
261 | u32 platform_drv_registered:1; | 263 | u32 platform_drv_registered:1; |
262 | u32 platform_drv_attrs_registered:1; | 264 | u32 platform_drv_attrs_registered:1; |
@@ -277,8 +279,10 @@ struct thinkpad_id_data { | |||
277 | char *bios_version_str; /* Something like 1ZET51WW (1.03z) */ | 279 | char *bios_version_str; /* Something like 1ZET51WW (1.03z) */ |
278 | char *ec_version_str; /* Something like 1ZHT51WW-1.04a */ | 280 | char *ec_version_str; /* Something like 1ZHT51WW-1.04a */ |
279 | 281 | ||
280 | u16 bios_model; /* Big Endian, TP-1Y = 0x5931, 0 = unknown */ | 282 | u16 bios_model; /* 1Y = 0x5931, 0 = unknown */ |
281 | u16 ec_model; | 283 | u16 ec_model; |
284 | u16 bios_release; /* 1ZETK1WW = 0x314b, 0 = unknown */ | ||
285 | u16 ec_release; | ||
282 | 286 | ||
283 | char *model_str; /* ThinkPad T43 */ | 287 | char *model_str; /* ThinkPad T43 */ |
284 | char *nummodel_str; /* 9384A9C for a 9384-A9C model */ | 288 | char *nummodel_str; /* 9384A9C for a 9384-A9C model */ |
@@ -355,6 +359,73 @@ static void tpacpi_log_usertask(const char * const what) | |||
355 | } \ | 359 | } \ |
356 | } while (0) | 360 | } while (0) |
357 | 361 | ||
362 | /* | ||
363 | * Quirk handling helpers | ||
364 | * | ||
365 | * ThinkPad IDs and versions seen in the field so far | ||
366 | * are two-characters from the set [0-9A-Z], i.e. base 36. | ||
367 | * | ||
368 | * We use values well outside that range as specials. | ||
369 | */ | ||
370 | |||
371 | #define TPACPI_MATCH_ANY 0xffffU | ||
372 | #define TPACPI_MATCH_UNKNOWN 0U | ||
373 | |||
374 | /* TPID('1', 'Y') == 0x5931 */ | ||
375 | #define TPID(__c1, __c2) (((__c2) << 8) | (__c1)) | ||
376 | |||
377 | #define TPACPI_Q_IBM(__id1, __id2, __quirk) \ | ||
378 | { .vendor = PCI_VENDOR_ID_IBM, \ | ||
379 | .bios = TPID(__id1, __id2), \ | ||
380 | .ec = TPACPI_MATCH_ANY, \ | ||
381 | .quirks = (__quirk) } | ||
382 | |||
383 | #define TPACPI_Q_LNV(__id1, __id2, __quirk) \ | ||
384 | { .vendor = PCI_VENDOR_ID_LENOVO, \ | ||
385 | .bios = TPID(__id1, __id2), \ | ||
386 | .ec = TPACPI_MATCH_ANY, \ | ||
387 | .quirks = (__quirk) } | ||
388 | |||
389 | struct tpacpi_quirk { | ||
390 | unsigned int vendor; | ||
391 | u16 bios; | ||
392 | u16 ec; | ||
393 | unsigned long quirks; | ||
394 | }; | ||
395 | |||
396 | /** | ||
397 | * tpacpi_check_quirks() - search BIOS/EC version on a list | ||
398 | * @qlist: array of &struct tpacpi_quirk | ||
399 | * @qlist_size: number of elements in @qlist | ||
400 | * | ||
401 | * Iterates over a quirks list until one is found that matches the | ||
402 | * ThinkPad's vendor, BIOS and EC model. | ||
403 | * | ||
404 | * Returns 0 if nothing matches, otherwise returns the quirks field of | ||
405 | * the matching &struct tpacpi_quirk entry. | ||
406 | * | ||
407 | * The match criteria is: vendor, ec and bios much match. | ||
408 | */ | ||
409 | static unsigned long __init tpacpi_check_quirks( | ||
410 | const struct tpacpi_quirk *qlist, | ||
411 | unsigned int qlist_size) | ||
412 | { | ||
413 | while (qlist_size) { | ||
414 | if ((qlist->vendor == thinkpad_id.vendor || | ||
415 | qlist->vendor == TPACPI_MATCH_ANY) && | ||
416 | (qlist->bios == thinkpad_id.bios_model || | ||
417 | qlist->bios == TPACPI_MATCH_ANY) && | ||
418 | (qlist->ec == thinkpad_id.ec_model || | ||
419 | qlist->ec == TPACPI_MATCH_ANY)) | ||
420 | return qlist->quirks; | ||
421 | |||
422 | qlist_size--; | ||
423 | qlist++; | ||
424 | } | ||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | |||
358 | /**************************************************************************** | 429 | /**************************************************************************** |
359 | **************************************************************************** | 430 | **************************************************************************** |
360 | * | 431 | * |
@@ -2880,7 +2951,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
2880 | /* update bright_acpimode... */ | 2951 | /* update bright_acpimode... */ |
2881 | tpacpi_check_std_acpi_brightness_support(); | 2952 | tpacpi_check_std_acpi_brightness_support(); |
2882 | 2953 | ||
2883 | if (tp_features.bright_acpimode) { | 2954 | if (tp_features.bright_acpimode && acpi_video_backlight_support()) { |
2884 | printk(TPACPI_INFO | 2955 | printk(TPACPI_INFO |
2885 | "This ThinkPad has standard ACPI backlight " | 2956 | "This ThinkPad has standard ACPI backlight " |
2886 | "brightness control, supported by the ACPI " | 2957 | "brightness control, supported by the ACPI " |
@@ -4773,7 +4844,7 @@ TPACPI_HANDLE(led, ec, "SLED", /* 570 */ | |||
4773 | "LED", /* all others */ | 4844 | "LED", /* all others */ |
4774 | ); /* R30, R31 */ | 4845 | ); /* R30, R31 */ |
4775 | 4846 | ||
4776 | #define TPACPI_LED_NUMLEDS 8 | 4847 | #define TPACPI_LED_NUMLEDS 16 |
4777 | static struct tpacpi_led_classdev *tpacpi_leds; | 4848 | static struct tpacpi_led_classdev *tpacpi_leds; |
4778 | static enum led_status_t tpacpi_led_state_cache[TPACPI_LED_NUMLEDS]; | 4849 | static enum led_status_t tpacpi_led_state_cache[TPACPI_LED_NUMLEDS]; |
4779 | static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = { | 4850 | static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = { |
@@ -4786,15 +4857,20 @@ static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = { | |||
4786 | "tpacpi::dock_batt", | 4857 | "tpacpi::dock_batt", |
4787 | "tpacpi::unknown_led", | 4858 | "tpacpi::unknown_led", |
4788 | "tpacpi::standby", | 4859 | "tpacpi::standby", |
4860 | "tpacpi::dock_status1", | ||
4861 | "tpacpi::dock_status2", | ||
4862 | "tpacpi::unknown_led2", | ||
4863 | "tpacpi::unknown_led3", | ||
4864 | "tpacpi::thinkvantage", | ||
4789 | }; | 4865 | }; |
4790 | #define TPACPI_SAFE_LEDS 0x0081U | 4866 | #define TPACPI_SAFE_LEDS 0x1081U |
4791 | 4867 | ||
4792 | static inline bool tpacpi_is_led_restricted(const unsigned int led) | 4868 | static inline bool tpacpi_is_led_restricted(const unsigned int led) |
4793 | { | 4869 | { |
4794 | #ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS | 4870 | #ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS |
4795 | return false; | 4871 | return false; |
4796 | #else | 4872 | #else |
4797 | return (TPACPI_SAFE_LEDS & (1 << led)) == 0; | 4873 | return (1U & (TPACPI_SAFE_LEDS >> led)) == 0; |
4798 | #endif | 4874 | #endif |
4799 | } | 4875 | } |
4800 | 4876 | ||
@@ -4956,6 +5032,10 @@ static int __init tpacpi_init_led(unsigned int led) | |||
4956 | 5032 | ||
4957 | tpacpi_leds[led].led = led; | 5033 | tpacpi_leds[led].led = led; |
4958 | 5034 | ||
5035 | /* LEDs with no name don't get registered */ | ||
5036 | if (!tpacpi_led_names[led]) | ||
5037 | return 0; | ||
5038 | |||
4959 | tpacpi_leds[led].led_classdev.brightness_set = &led_sysfs_set; | 5039 | tpacpi_leds[led].led_classdev.brightness_set = &led_sysfs_set; |
4960 | tpacpi_leds[led].led_classdev.blink_set = &led_sysfs_blink_set; | 5040 | tpacpi_leds[led].led_classdev.blink_set = &led_sysfs_blink_set; |
4961 | if (led_supported == TPACPI_LED_570) | 5041 | if (led_supported == TPACPI_LED_570) |
@@ -4974,10 +5054,59 @@ static int __init tpacpi_init_led(unsigned int led) | |||
4974 | return rc; | 5054 | return rc; |
4975 | } | 5055 | } |
4976 | 5056 | ||
5057 | static const struct tpacpi_quirk led_useful_qtable[] __initconst = { | ||
5058 | TPACPI_Q_IBM('1', 'E', 0x009f), /* A30 */ | ||
5059 | TPACPI_Q_IBM('1', 'N', 0x009f), /* A31 */ | ||
5060 | TPACPI_Q_IBM('1', 'G', 0x009f), /* A31 */ | ||
5061 | |||
5062 | TPACPI_Q_IBM('1', 'I', 0x0097), /* T30 */ | ||
5063 | TPACPI_Q_IBM('1', 'R', 0x0097), /* T40, T41, T42, R50, R51 */ | ||
5064 | TPACPI_Q_IBM('7', '0', 0x0097), /* T43, R52 */ | ||
5065 | TPACPI_Q_IBM('1', 'Y', 0x0097), /* T43 */ | ||
5066 | TPACPI_Q_IBM('1', 'W', 0x0097), /* R50e */ | ||
5067 | TPACPI_Q_IBM('1', 'V', 0x0097), /* R51 */ | ||
5068 | TPACPI_Q_IBM('7', '8', 0x0097), /* R51e */ | ||
5069 | TPACPI_Q_IBM('7', '6', 0x0097), /* R52 */ | ||
5070 | |||
5071 | TPACPI_Q_IBM('1', 'K', 0x00bf), /* X30 */ | ||
5072 | TPACPI_Q_IBM('1', 'Q', 0x00bf), /* X31, X32 */ | ||
5073 | TPACPI_Q_IBM('1', 'U', 0x00bf), /* X40 */ | ||
5074 | TPACPI_Q_IBM('7', '4', 0x00bf), /* X41 */ | ||
5075 | TPACPI_Q_IBM('7', '5', 0x00bf), /* X41t */ | ||
5076 | |||
5077 | TPACPI_Q_IBM('7', '9', 0x1f97), /* T60 (1) */ | ||
5078 | TPACPI_Q_IBM('7', '7', 0x1f97), /* Z60* (1) */ | ||
5079 | TPACPI_Q_IBM('7', 'F', 0x1f97), /* Z61* (1) */ | ||
5080 | TPACPI_Q_IBM('7', 'B', 0x1fb7), /* X60 (1) */ | ||
5081 | |||
5082 | /* (1) - may have excess leds enabled on MSB */ | ||
5083 | |||
5084 | /* Defaults (order matters, keep last, don't reorder!) */ | ||
5085 | { /* Lenovo */ | ||
5086 | .vendor = PCI_VENDOR_ID_LENOVO, | ||
5087 | .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_ANY, | ||
5088 | .quirks = 0x1fffU, | ||
5089 | }, | ||
5090 | { /* IBM ThinkPads with no EC version string */ | ||
5091 | .vendor = PCI_VENDOR_ID_IBM, | ||
5092 | .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_UNKNOWN, | ||
5093 | .quirks = 0x00ffU, | ||
5094 | }, | ||
5095 | { /* IBM ThinkPads with EC version string */ | ||
5096 | .vendor = PCI_VENDOR_ID_IBM, | ||
5097 | .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_ANY, | ||
5098 | .quirks = 0x00bfU, | ||
5099 | }, | ||
5100 | }; | ||
5101 | |||
5102 | #undef TPACPI_LEDQ_IBM | ||
5103 | #undef TPACPI_LEDQ_LNV | ||
5104 | |||
4977 | static int __init led_init(struct ibm_init_struct *iibm) | 5105 | static int __init led_init(struct ibm_init_struct *iibm) |
4978 | { | 5106 | { |
4979 | unsigned int i; | 5107 | unsigned int i; |
4980 | int rc; | 5108 | int rc; |
5109 | unsigned long useful_leds; | ||
4981 | 5110 | ||
4982 | vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n"); | 5111 | vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n"); |
4983 | 5112 | ||
@@ -4999,6 +5128,9 @@ static int __init led_init(struct ibm_init_struct *iibm) | |||
4999 | vdbg_printk(TPACPI_DBG_INIT, "LED commands are %s, mode %d\n", | 5128 | vdbg_printk(TPACPI_DBG_INIT, "LED commands are %s, mode %d\n", |
5000 | str_supported(led_supported), led_supported); | 5129 | str_supported(led_supported), led_supported); |
5001 | 5130 | ||
5131 | if (led_supported == TPACPI_LED_NONE) | ||
5132 | return 1; | ||
5133 | |||
5002 | tpacpi_leds = kzalloc(sizeof(*tpacpi_leds) * TPACPI_LED_NUMLEDS, | 5134 | tpacpi_leds = kzalloc(sizeof(*tpacpi_leds) * TPACPI_LED_NUMLEDS, |
5003 | GFP_KERNEL); | 5135 | GFP_KERNEL); |
5004 | if (!tpacpi_leds) { | 5136 | if (!tpacpi_leds) { |
@@ -5006,8 +5138,12 @@ static int __init led_init(struct ibm_init_struct *iibm) | |||
5006 | return -ENOMEM; | 5138 | return -ENOMEM; |
5007 | } | 5139 | } |
5008 | 5140 | ||
5141 | useful_leds = tpacpi_check_quirks(led_useful_qtable, | ||
5142 | ARRAY_SIZE(led_useful_qtable)); | ||
5143 | |||
5009 | for (i = 0; i < TPACPI_LED_NUMLEDS; i++) { | 5144 | for (i = 0; i < TPACPI_LED_NUMLEDS; i++) { |
5010 | if (!tpacpi_is_led_restricted(i)) { | 5145 | if (!tpacpi_is_led_restricted(i) && |
5146 | test_bit(i, &useful_leds)) { | ||
5011 | rc = tpacpi_init_led(i); | 5147 | rc = tpacpi_init_led(i); |
5012 | if (rc < 0) { | 5148 | if (rc < 0) { |
5013 | led_exit(); | 5149 | led_exit(); |
@@ -5017,12 +5153,11 @@ static int __init led_init(struct ibm_init_struct *iibm) | |||
5017 | } | 5153 | } |
5018 | 5154 | ||
5019 | #ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS | 5155 | #ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS |
5020 | if (led_supported != TPACPI_LED_NONE) | 5156 | printk(TPACPI_NOTICE |
5021 | printk(TPACPI_NOTICE | 5157 | "warning: userspace override of important " |
5022 | "warning: userspace override of important " | 5158 | "firmware LEDs is enabled\n"); |
5023 | "firmware LEDs is enabled\n"); | ||
5024 | #endif | 5159 | #endif |
5025 | return (led_supported != TPACPI_LED_NONE)? 0 : 1; | 5160 | return 0; |
5026 | } | 5161 | } |
5027 | 5162 | ||
5028 | #define str_led_status(s) \ | 5163 | #define str_led_status(s) \ |
@@ -5052,7 +5187,7 @@ static int led_read(char *p) | |||
5052 | } | 5187 | } |
5053 | 5188 | ||
5054 | len += sprintf(p + len, "commands:\t" | 5189 | len += sprintf(p + len, "commands:\t" |
5055 | "<led> on, <led> off, <led> blink (<led> is 0-7)\n"); | 5190 | "<led> on, <led> off, <led> blink (<led> is 0-15)\n"); |
5056 | 5191 | ||
5057 | return len; | 5192 | return len; |
5058 | } | 5193 | } |
@@ -5067,7 +5202,7 @@ static int led_write(char *buf) | |||
5067 | return -ENODEV; | 5202 | return -ENODEV; |
5068 | 5203 | ||
5069 | while ((cmd = next_cmd(&buf))) { | 5204 | while ((cmd = next_cmd(&buf))) { |
5070 | if (sscanf(cmd, "%d", &led) != 1 || led < 0 || led > 7) | 5205 | if (sscanf(cmd, "%d", &led) != 1 || led < 0 || led > 15) |
5071 | return -EINVAL; | 5206 | return -EINVAL; |
5072 | 5207 | ||
5073 | if (strstr(cmd, "off")) { | 5208 | if (strstr(cmd, "off")) { |
@@ -5101,8 +5236,17 @@ static struct ibm_struct led_driver_data = { | |||
5101 | 5236 | ||
5102 | TPACPI_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */ | 5237 | TPACPI_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */ |
5103 | 5238 | ||
5239 | #define TPACPI_BEEP_Q1 0x0001 | ||
5240 | |||
5241 | static const struct tpacpi_quirk beep_quirk_table[] __initconst = { | ||
5242 | TPACPI_Q_IBM('I', 'M', TPACPI_BEEP_Q1), /* 570 */ | ||
5243 | TPACPI_Q_IBM('I', 'U', TPACPI_BEEP_Q1), /* 570E - unverified */ | ||
5244 | }; | ||
5245 | |||
5104 | static int __init beep_init(struct ibm_init_struct *iibm) | 5246 | static int __init beep_init(struct ibm_init_struct *iibm) |
5105 | { | 5247 | { |
5248 | unsigned long quirks; | ||
5249 | |||
5106 | vdbg_printk(TPACPI_DBG_INIT, "initializing beep subdriver\n"); | 5250 | vdbg_printk(TPACPI_DBG_INIT, "initializing beep subdriver\n"); |
5107 | 5251 | ||
5108 | TPACPI_ACPIHANDLE_INIT(beep); | 5252 | TPACPI_ACPIHANDLE_INIT(beep); |
@@ -5110,6 +5254,11 @@ static int __init beep_init(struct ibm_init_struct *iibm) | |||
5110 | vdbg_printk(TPACPI_DBG_INIT, "beep is %s\n", | 5254 | vdbg_printk(TPACPI_DBG_INIT, "beep is %s\n", |
5111 | str_supported(beep_handle != NULL)); | 5255 | str_supported(beep_handle != NULL)); |
5112 | 5256 | ||
5257 | quirks = tpacpi_check_quirks(beep_quirk_table, | ||
5258 | ARRAY_SIZE(beep_quirk_table)); | ||
5259 | |||
5260 | tp_features.beep_needs_two_args = !!(quirks & TPACPI_BEEP_Q1); | ||
5261 | |||
5113 | return (beep_handle)? 0 : 1; | 5262 | return (beep_handle)? 0 : 1; |
5114 | } | 5263 | } |
5115 | 5264 | ||
@@ -5141,8 +5290,15 @@ static int beep_write(char *buf) | |||
5141 | /* beep_cmd set */ | 5290 | /* beep_cmd set */ |
5142 | } else | 5291 | } else |
5143 | return -EINVAL; | 5292 | return -EINVAL; |
5144 | if (!acpi_evalf(beep_handle, NULL, NULL, "vdd", beep_cmd, 0)) | 5293 | if (tp_features.beep_needs_two_args) { |
5145 | return -EIO; | 5294 | if (!acpi_evalf(beep_handle, NULL, NULL, "vdd", |
5295 | beep_cmd, 0)) | ||
5296 | return -EIO; | ||
5297 | } else { | ||
5298 | if (!acpi_evalf(beep_handle, NULL, NULL, "vd", | ||
5299 | beep_cmd)) | ||
5300 | return -EIO; | ||
5301 | } | ||
5146 | } | 5302 | } |
5147 | 5303 | ||
5148 | return 0; | 5304 | return 0; |
@@ -5569,6 +5725,10 @@ static struct ibm_struct ecdump_driver_data = { | |||
5569 | * Bit 3-0: backlight brightness level | 5725 | * Bit 3-0: backlight brightness level |
5570 | * | 5726 | * |
5571 | * brightness_get_raw returns status data in the HBRV layout | 5727 | * brightness_get_raw returns status data in the HBRV layout |
5728 | * | ||
5729 | * WARNING: The X61 has been verified to use HBRV for something else, so | ||
5730 | * this should be used _only_ on IBM ThinkPads, and maybe with some careful | ||
5731 | * testing on the very early *60 Lenovo models... | ||
5572 | */ | 5732 | */ |
5573 | 5733 | ||
5574 | enum { | 5734 | enum { |
@@ -5869,6 +6029,12 @@ static int __init brightness_init(struct ibm_init_struct *iibm) | |||
5869 | brightness_mode); | 6029 | brightness_mode); |
5870 | } | 6030 | } |
5871 | 6031 | ||
6032 | /* Safety */ | ||
6033 | if (thinkpad_id.vendor != PCI_VENDOR_ID_IBM && | ||
6034 | (brightness_mode == TPACPI_BRGHT_MODE_ECNVRAM || | ||
6035 | brightness_mode == TPACPI_BRGHT_MODE_EC)) | ||
6036 | return -EINVAL; | ||
6037 | |||
5872 | if (tpacpi_brightness_get_raw(&b) < 0) | 6038 | if (tpacpi_brightness_get_raw(&b) < 0) |
5873 | return 1; | 6039 | return 1; |
5874 | 6040 | ||
@@ -6161,6 +6327,21 @@ static struct ibm_struct volume_driver_data = { | |||
6161 | * For firmware bugs, refer to: | 6327 | * For firmware bugs, refer to: |
6162 | * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues | 6328 | * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues |
6163 | * | 6329 | * |
6330 | * ---- | ||
6331 | * | ||
6332 | * ThinkPad EC register 0x31 bit 0 (only on select models) | ||
6333 | * | ||
6334 | * When bit 0 of EC register 0x31 is zero, the tachometer registers | ||
6335 | * show the speed of the main fan. When bit 0 of EC register 0x31 | ||
6336 | * is one, the tachometer registers show the speed of the auxiliary | ||
6337 | * fan. | ||
6338 | * | ||
6339 | * Fan control seems to affect both fans, regardless of the state | ||
6340 | * of this bit. | ||
6341 | * | ||
6342 | * So far, only the firmware for the X60/X61 non-tablet versions | ||
6343 | * seem to support this (firmware TP-7M). | ||
6344 | * | ||
6164 | * TPACPI_FAN_WR_ACPI_FANS: | 6345 | * TPACPI_FAN_WR_ACPI_FANS: |
6165 | * ThinkPad X31, X40, X41. Not available in the X60. | 6346 | * ThinkPad X31, X40, X41. Not available in the X60. |
6166 | * | 6347 | * |
@@ -6187,6 +6368,8 @@ enum { /* Fan control constants */ | |||
6187 | fan_status_offset = 0x2f, /* EC register 0x2f */ | 6368 | fan_status_offset = 0x2f, /* EC register 0x2f */ |
6188 | fan_rpm_offset = 0x84, /* EC register 0x84: LSB, 0x85 MSB (RPM) | 6369 | fan_rpm_offset = 0x84, /* EC register 0x84: LSB, 0x85 MSB (RPM) |
6189 | * 0x84 must be read before 0x85 */ | 6370 | * 0x84 must be read before 0x85 */ |
6371 | fan_select_offset = 0x31, /* EC register 0x31 (Firmware 7M) | ||
6372 | bit 0 selects which fan is active */ | ||
6190 | 6373 | ||
6191 | TP_EC_FAN_FULLSPEED = 0x40, /* EC fan mode: full speed */ | 6374 | TP_EC_FAN_FULLSPEED = 0x40, /* EC fan mode: full speed */ |
6192 | TP_EC_FAN_AUTO = 0x80, /* EC fan mode: auto fan control */ | 6375 | TP_EC_FAN_AUTO = 0x80, /* EC fan mode: auto fan control */ |
@@ -6249,30 +6432,18 @@ TPACPI_HANDLE(sfan, ec, "SFAN", /* 570 */ | |||
6249 | * We assume 0x07 really means auto mode while this quirk is active, | 6432 | * We assume 0x07 really means auto mode while this quirk is active, |
6250 | * as this is far more likely than the ThinkPad being in level 7, | 6433 | * as this is far more likely than the ThinkPad being in level 7, |
6251 | * which is only used by the firmware during thermal emergencies. | 6434 | * which is only used by the firmware during thermal emergencies. |
6435 | * | ||
6436 | * Enable for TP-1Y (T43), TP-78 (R51e), TP-76 (R52), | ||
6437 | * TP-70 (T43, R52), which are known to be buggy. | ||
6252 | */ | 6438 | */ |
6253 | 6439 | ||
6254 | static void fan_quirk1_detect(void) | 6440 | static void fan_quirk1_setup(void) |
6255 | { | 6441 | { |
6256 | /* In some ThinkPads, neither the EC nor the ACPI | ||
6257 | * DSDT initialize the HFSP register, and it ends up | ||
6258 | * being initially set to 0x07 when it *could* be | ||
6259 | * either 0x07 or 0x80. | ||
6260 | * | ||
6261 | * Enable for TP-1Y (T43), TP-78 (R51e), | ||
6262 | * TP-76 (R52), TP-70 (T43, R52), which are known | ||
6263 | * to be buggy. */ | ||
6264 | if (fan_control_initial_status == 0x07) { | 6442 | if (fan_control_initial_status == 0x07) { |
6265 | switch (thinkpad_id.ec_model) { | 6443 | printk(TPACPI_NOTICE |
6266 | case 0x5931: /* TP-1Y */ | 6444 | "fan_init: initial fan status is unknown, " |
6267 | case 0x3837: /* TP-78 */ | 6445 | "assuming it is in auto mode\n"); |
6268 | case 0x3637: /* TP-76 */ | 6446 | tp_features.fan_ctrl_status_undef = 1; |
6269 | case 0x3037: /* TP-70 */ | ||
6270 | printk(TPACPI_NOTICE | ||
6271 | "fan_init: initial fan status is unknown, " | ||
6272 | "assuming it is in auto mode\n"); | ||
6273 | tp_features.fan_ctrl_status_undef = 1; | ||
6274 | ;; | ||
6275 | } | ||
6276 | } | 6447 | } |
6277 | } | 6448 | } |
6278 | 6449 | ||
@@ -6292,6 +6463,38 @@ static void fan_quirk1_handle(u8 *fan_status) | |||
6292 | } | 6463 | } |
6293 | } | 6464 | } |
6294 | 6465 | ||
6466 | /* Select main fan on X60/X61, NOOP on others */ | ||
6467 | static bool fan_select_fan1(void) | ||
6468 | { | ||
6469 | if (tp_features.second_fan) { | ||
6470 | u8 val; | ||
6471 | |||
6472 | if (ec_read(fan_select_offset, &val) < 0) | ||
6473 | return false; | ||
6474 | val &= 0xFEU; | ||
6475 | if (ec_write(fan_select_offset, val) < 0) | ||
6476 | return false; | ||
6477 | } | ||
6478 | return true; | ||
6479 | } | ||
6480 | |||
6481 | /* Select secondary fan on X60/X61 */ | ||
6482 | static bool fan_select_fan2(void) | ||
6483 | { | ||
6484 | u8 val; | ||
6485 | |||
6486 | if (!tp_features.second_fan) | ||
6487 | return false; | ||
6488 | |||
6489 | if (ec_read(fan_select_offset, &val) < 0) | ||
6490 | return false; | ||
6491 | val |= 0x01U; | ||
6492 | if (ec_write(fan_select_offset, val) < 0) | ||
6493 | return false; | ||
6494 | |||
6495 | return true; | ||
6496 | } | ||
6497 | |||
6295 | /* | 6498 | /* |
6296 | * Call with fan_mutex held | 6499 | * Call with fan_mutex held |
6297 | */ | 6500 | */ |
@@ -6369,6 +6572,8 @@ static int fan_get_speed(unsigned int *speed) | |||
6369 | switch (fan_status_access_mode) { | 6572 | switch (fan_status_access_mode) { |
6370 | case TPACPI_FAN_RD_TPEC: | 6573 | case TPACPI_FAN_RD_TPEC: |
6371 | /* all except 570, 600e/x, 770e, 770x */ | 6574 | /* all except 570, 600e/x, 770e, 770x */ |
6575 | if (unlikely(!fan_select_fan1())) | ||
6576 | return -EIO; | ||
6372 | if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) || | 6577 | if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) || |
6373 | !acpi_ec_read(fan_rpm_offset + 1, &hi))) | 6578 | !acpi_ec_read(fan_rpm_offset + 1, &hi))) |
6374 | return -EIO; | 6579 | return -EIO; |
@@ -6385,6 +6590,34 @@ static int fan_get_speed(unsigned int *speed) | |||
6385 | return 0; | 6590 | return 0; |
6386 | } | 6591 | } |
6387 | 6592 | ||
6593 | static int fan2_get_speed(unsigned int *speed) | ||
6594 | { | ||
6595 | u8 hi, lo; | ||
6596 | bool rc; | ||
6597 | |||
6598 | switch (fan_status_access_mode) { | ||
6599 | case TPACPI_FAN_RD_TPEC: | ||
6600 | /* all except 570, 600e/x, 770e, 770x */ | ||
6601 | if (unlikely(!fan_select_fan2())) | ||
6602 | return -EIO; | ||
6603 | rc = !acpi_ec_read(fan_rpm_offset, &lo) || | ||
6604 | !acpi_ec_read(fan_rpm_offset + 1, &hi); | ||
6605 | fan_select_fan1(); /* play it safe */ | ||
6606 | if (rc) | ||
6607 | return -EIO; | ||
6608 | |||
6609 | if (likely(speed)) | ||
6610 | *speed = (hi << 8) | lo; | ||
6611 | |||
6612 | break; | ||
6613 | |||
6614 | default: | ||
6615 | return -ENXIO; | ||
6616 | } | ||
6617 | |||
6618 | return 0; | ||
6619 | } | ||
6620 | |||
6388 | static int fan_set_level(int level) | 6621 | static int fan_set_level(int level) |
6389 | { | 6622 | { |
6390 | if (!fan_control_allowed) | 6623 | if (!fan_control_allowed) |
@@ -6790,6 +7023,25 @@ static struct device_attribute dev_attr_fan_fan1_input = | |||
6790 | __ATTR(fan1_input, S_IRUGO, | 7023 | __ATTR(fan1_input, S_IRUGO, |
6791 | fan_fan1_input_show, NULL); | 7024 | fan_fan1_input_show, NULL); |
6792 | 7025 | ||
7026 | /* sysfs fan fan2_input ------------------------------------------------ */ | ||
7027 | static ssize_t fan_fan2_input_show(struct device *dev, | ||
7028 | struct device_attribute *attr, | ||
7029 | char *buf) | ||
7030 | { | ||
7031 | int res; | ||
7032 | unsigned int speed; | ||
7033 | |||
7034 | res = fan2_get_speed(&speed); | ||
7035 | if (res < 0) | ||
7036 | return res; | ||
7037 | |||
7038 | return snprintf(buf, PAGE_SIZE, "%u\n", speed); | ||
7039 | } | ||
7040 | |||
7041 | static struct device_attribute dev_attr_fan_fan2_input = | ||
7042 | __ATTR(fan2_input, S_IRUGO, | ||
7043 | fan_fan2_input_show, NULL); | ||
7044 | |||
6793 | /* sysfs fan fan_watchdog (hwmon driver) ------------------------------- */ | 7045 | /* sysfs fan fan_watchdog (hwmon driver) ------------------------------- */ |
6794 | static ssize_t fan_fan_watchdog_show(struct device_driver *drv, | 7046 | static ssize_t fan_fan_watchdog_show(struct device_driver *drv, |
6795 | char *buf) | 7047 | char *buf) |
@@ -6823,6 +7075,7 @@ static DRIVER_ATTR(fan_watchdog, S_IWUSR | S_IRUGO, | |||
6823 | static struct attribute *fan_attributes[] = { | 7075 | static struct attribute *fan_attributes[] = { |
6824 | &dev_attr_fan_pwm1_enable.attr, &dev_attr_fan_pwm1.attr, | 7076 | &dev_attr_fan_pwm1_enable.attr, &dev_attr_fan_pwm1.attr, |
6825 | &dev_attr_fan_fan1_input.attr, | 7077 | &dev_attr_fan_fan1_input.attr, |
7078 | NULL, /* for fan2_input */ | ||
6826 | NULL | 7079 | NULL |
6827 | }; | 7080 | }; |
6828 | 7081 | ||
@@ -6830,9 +7083,36 @@ static const struct attribute_group fan_attr_group = { | |||
6830 | .attrs = fan_attributes, | 7083 | .attrs = fan_attributes, |
6831 | }; | 7084 | }; |
6832 | 7085 | ||
7086 | #define TPACPI_FAN_Q1 0x0001 /* Unitialized HFSP */ | ||
7087 | #define TPACPI_FAN_2FAN 0x0002 /* EC 0x31 bit 0 selects fan2 */ | ||
7088 | |||
7089 | #define TPACPI_FAN_QI(__id1, __id2, __quirks) \ | ||
7090 | { .vendor = PCI_VENDOR_ID_IBM, \ | ||
7091 | .bios = TPACPI_MATCH_ANY, \ | ||
7092 | .ec = TPID(__id1, __id2), \ | ||
7093 | .quirks = __quirks } | ||
7094 | |||
7095 | #define TPACPI_FAN_QL(__id1, __id2, __quirks) \ | ||
7096 | { .vendor = PCI_VENDOR_ID_LENOVO, \ | ||
7097 | .bios = TPACPI_MATCH_ANY, \ | ||
7098 | .ec = TPID(__id1, __id2), \ | ||
7099 | .quirks = __quirks } | ||
7100 | |||
7101 | static const struct tpacpi_quirk fan_quirk_table[] __initconst = { | ||
7102 | TPACPI_FAN_QI('1', 'Y', TPACPI_FAN_Q1), | ||
7103 | TPACPI_FAN_QI('7', '8', TPACPI_FAN_Q1), | ||
7104 | TPACPI_FAN_QI('7', '6', TPACPI_FAN_Q1), | ||
7105 | TPACPI_FAN_QI('7', '0', TPACPI_FAN_Q1), | ||
7106 | TPACPI_FAN_QL('7', 'M', TPACPI_FAN_2FAN), | ||
7107 | }; | ||
7108 | |||
7109 | #undef TPACPI_FAN_QL | ||
7110 | #undef TPACPI_FAN_QI | ||
7111 | |||
6833 | static int __init fan_init(struct ibm_init_struct *iibm) | 7112 | static int __init fan_init(struct ibm_init_struct *iibm) |
6834 | { | 7113 | { |
6835 | int rc; | 7114 | int rc; |
7115 | unsigned long quirks; | ||
6836 | 7116 | ||
6837 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN, | 7117 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN, |
6838 | "initializing fan subdriver\n"); | 7118 | "initializing fan subdriver\n"); |
@@ -6843,12 +7123,16 @@ static int __init fan_init(struct ibm_init_struct *iibm) | |||
6843 | fan_control_commands = 0; | 7123 | fan_control_commands = 0; |
6844 | fan_watchdog_maxinterval = 0; | 7124 | fan_watchdog_maxinterval = 0; |
6845 | tp_features.fan_ctrl_status_undef = 0; | 7125 | tp_features.fan_ctrl_status_undef = 0; |
7126 | tp_features.second_fan = 0; | ||
6846 | fan_control_desired_level = 7; | 7127 | fan_control_desired_level = 7; |
6847 | 7128 | ||
6848 | TPACPI_ACPIHANDLE_INIT(fans); | 7129 | TPACPI_ACPIHANDLE_INIT(fans); |
6849 | TPACPI_ACPIHANDLE_INIT(gfan); | 7130 | TPACPI_ACPIHANDLE_INIT(gfan); |
6850 | TPACPI_ACPIHANDLE_INIT(sfan); | 7131 | TPACPI_ACPIHANDLE_INIT(sfan); |
6851 | 7132 | ||
7133 | quirks = tpacpi_check_quirks(fan_quirk_table, | ||
7134 | ARRAY_SIZE(fan_quirk_table)); | ||
7135 | |||
6852 | if (gfan_handle) { | 7136 | if (gfan_handle) { |
6853 | /* 570, 600e/x, 770e, 770x */ | 7137 | /* 570, 600e/x, 770e, 770x */ |
6854 | fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN; | 7138 | fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN; |
@@ -6858,7 +7142,13 @@ static int __init fan_init(struct ibm_init_struct *iibm) | |||
6858 | if (likely(acpi_ec_read(fan_status_offset, | 7142 | if (likely(acpi_ec_read(fan_status_offset, |
6859 | &fan_control_initial_status))) { | 7143 | &fan_control_initial_status))) { |
6860 | fan_status_access_mode = TPACPI_FAN_RD_TPEC; | 7144 | fan_status_access_mode = TPACPI_FAN_RD_TPEC; |
6861 | fan_quirk1_detect(); | 7145 | if (quirks & TPACPI_FAN_Q1) |
7146 | fan_quirk1_setup(); | ||
7147 | if (quirks & TPACPI_FAN_2FAN) { | ||
7148 | tp_features.second_fan = 1; | ||
7149 | dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN, | ||
7150 | "secondary fan support enabled\n"); | ||
7151 | } | ||
6862 | } else { | 7152 | } else { |
6863 | printk(TPACPI_ERR | 7153 | printk(TPACPI_ERR |
6864 | "ThinkPad ACPI EC access misbehaving, " | 7154 | "ThinkPad ACPI EC access misbehaving, " |
@@ -6914,6 +7204,11 @@ static int __init fan_init(struct ibm_init_struct *iibm) | |||
6914 | 7204 | ||
6915 | if (fan_status_access_mode != TPACPI_FAN_NONE || | 7205 | if (fan_status_access_mode != TPACPI_FAN_NONE || |
6916 | fan_control_access_mode != TPACPI_FAN_WR_NONE) { | 7206 | fan_control_access_mode != TPACPI_FAN_WR_NONE) { |
7207 | if (tp_features.second_fan) { | ||
7208 | /* attach second fan tachometer */ | ||
7209 | fan_attributes[ARRAY_SIZE(fan_attributes)-2] = | ||
7210 | &dev_attr_fan_fan2_input.attr; | ||
7211 | } | ||
6917 | rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj, | 7212 | rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj, |
6918 | &fan_attr_group); | 7213 | &fan_attr_group); |
6919 | if (rc < 0) | 7214 | if (rc < 0) |
@@ -7385,6 +7680,24 @@ err_out: | |||
7385 | 7680 | ||
7386 | /* Probing */ | 7681 | /* Probing */ |
7387 | 7682 | ||
7683 | static bool __pure __init tpacpi_is_fw_digit(const char c) | ||
7684 | { | ||
7685 | return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z'); | ||
7686 | } | ||
7687 | |||
7688 | /* Most models: xxyTkkWW (#.##c); Ancient 570/600 and -SL lacks (#.##c) */ | ||
7689 | static bool __pure __init tpacpi_is_valid_fw_id(const char* const s, | ||
7690 | const char t) | ||
7691 | { | ||
7692 | return s && strlen(s) >= 8 && | ||
7693 | tpacpi_is_fw_digit(s[0]) && | ||
7694 | tpacpi_is_fw_digit(s[1]) && | ||
7695 | s[2] == t && s[3] == 'T' && | ||
7696 | tpacpi_is_fw_digit(s[4]) && | ||
7697 | tpacpi_is_fw_digit(s[5]) && | ||
7698 | s[6] == 'W' && s[7] == 'W'; | ||
7699 | } | ||
7700 | |||
7388 | /* returns 0 - probe ok, or < 0 - probe error. | 7701 | /* returns 0 - probe ok, or < 0 - probe error. |
7389 | * Probe ok doesn't mean thinkpad found. | 7702 | * Probe ok doesn't mean thinkpad found. |
7390 | * On error, kfree() cleanup on tp->* is not performed, caller must do it */ | 7703 | * On error, kfree() cleanup on tp->* is not performed, caller must do it */ |
@@ -7411,10 +7724,15 @@ static int __must_check __init get_thinkpad_model_data( | |||
7411 | tp->bios_version_str = kstrdup(s, GFP_KERNEL); | 7724 | tp->bios_version_str = kstrdup(s, GFP_KERNEL); |
7412 | if (s && !tp->bios_version_str) | 7725 | if (s && !tp->bios_version_str) |
7413 | return -ENOMEM; | 7726 | return -ENOMEM; |
7414 | if (!tp->bios_version_str) | 7727 | |
7728 | /* Really ancient ThinkPad 240X will fail this, which is fine */ | ||
7729 | if (!tpacpi_is_valid_fw_id(tp->bios_version_str, 'E')) | ||
7415 | return 0; | 7730 | return 0; |
7731 | |||
7416 | tp->bios_model = tp->bios_version_str[0] | 7732 | tp->bios_model = tp->bios_version_str[0] |
7417 | | (tp->bios_version_str[1] << 8); | 7733 | | (tp->bios_version_str[1] << 8); |
7734 | tp->bios_release = (tp->bios_version_str[4] << 8) | ||
7735 | | tp->bios_version_str[5]; | ||
7418 | 7736 | ||
7419 | /* | 7737 | /* |
7420 | * ThinkPad T23 or newer, A31 or newer, R50e or newer, | 7738 | * ThinkPad T23 or newer, A31 or newer, R50e or newer, |
@@ -7433,8 +7751,21 @@ static int __must_check __init get_thinkpad_model_data( | |||
7433 | tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL); | 7751 | tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL); |
7434 | if (!tp->ec_version_str) | 7752 | if (!tp->ec_version_str) |
7435 | return -ENOMEM; | 7753 | return -ENOMEM; |
7436 | tp->ec_model = ec_fw_string[0] | 7754 | |
7437 | | (ec_fw_string[1] << 8); | 7755 | if (tpacpi_is_valid_fw_id(ec_fw_string, 'H')) { |
7756 | tp->ec_model = ec_fw_string[0] | ||
7757 | | (ec_fw_string[1] << 8); | ||
7758 | tp->ec_release = (ec_fw_string[4] << 8) | ||
7759 | | ec_fw_string[5]; | ||
7760 | } else { | ||
7761 | printk(TPACPI_NOTICE | ||
7762 | "ThinkPad firmware release %s " | ||
7763 | "doesn't match the known patterns\n", | ||
7764 | ec_fw_string); | ||
7765 | printk(TPACPI_NOTICE | ||
7766 | "please report this to %s\n", | ||
7767 | TPACPI_MAIL); | ||
7768 | } | ||
7438 | break; | 7769 | break; |
7439 | } | 7770 | } |
7440 | } | 7771 | } |
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 7f207f335bec..ef3a2cd3a7a0 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c | |||
@@ -287,6 +287,25 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev, | |||
287 | ACPI_DECODE_16); | 287 | ACPI_DECODE_16); |
288 | } | 288 | } |
289 | 289 | ||
290 | static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev, | ||
291 | struct acpi_resource *res) | ||
292 | { | ||
293 | struct acpi_resource_extended_address64 *p = &res->data.ext_address64; | ||
294 | |||
295 | if (p->producer_consumer == ACPI_PRODUCER) | ||
296 | return; | ||
297 | |||
298 | if (p->resource_type == ACPI_MEMORY_RANGE) | ||
299 | pnpacpi_parse_allocated_memresource(dev, | ||
300 | p->minimum, p->address_length, | ||
301 | p->info.mem.write_protect); | ||
302 | else if (p->resource_type == ACPI_IO_RANGE) | ||
303 | pnpacpi_parse_allocated_ioresource(dev, | ||
304 | p->minimum, p->address_length, | ||
305 | p->granularity == 0xfff ? ACPI_DECODE_10 : | ||
306 | ACPI_DECODE_16); | ||
307 | } | ||
308 | |||
290 | static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | 309 | static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, |
291 | void *data) | 310 | void *data) |
292 | { | 311 | { |
@@ -400,8 +419,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | |||
400 | break; | 419 | break; |
401 | 420 | ||
402 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: | 421 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: |
403 | if (res->data.ext_address64.producer_consumer == ACPI_PRODUCER) | 422 | pnpacpi_parse_allocated_ext_address_space(dev, res); |
404 | return AE_OK; | ||
405 | break; | 423 | break; |
406 | 424 | ||
407 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | 425 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: |
@@ -630,6 +648,28 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev, | |||
630 | IORESOURCE_IO_FIXED); | 648 | IORESOURCE_IO_FIXED); |
631 | } | 649 | } |
632 | 650 | ||
651 | static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev, | ||
652 | unsigned int option_flags, | ||
653 | struct acpi_resource *r) | ||
654 | { | ||
655 | struct acpi_resource_extended_address64 *p = &r->data.ext_address64; | ||
656 | unsigned char flags = 0; | ||
657 | |||
658 | if (p->address_length == 0) | ||
659 | return; | ||
660 | |||
661 | if (p->resource_type == ACPI_MEMORY_RANGE) { | ||
662 | if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY) | ||
663 | flags = IORESOURCE_MEM_WRITEABLE; | ||
664 | pnp_register_mem_resource(dev, option_flags, p->minimum, | ||
665 | p->minimum, 0, p->address_length, | ||
666 | flags); | ||
667 | } else if (p->resource_type == ACPI_IO_RANGE) | ||
668 | pnp_register_port_resource(dev, option_flags, p->minimum, | ||
669 | p->minimum, 0, p->address_length, | ||
670 | IORESOURCE_IO_FIXED); | ||
671 | } | ||
672 | |||
633 | struct acpipnp_parse_option_s { | 673 | struct acpipnp_parse_option_s { |
634 | struct pnp_dev *dev; | 674 | struct pnp_dev *dev; |
635 | unsigned int option_flags; | 675 | unsigned int option_flags; |
@@ -711,6 +751,7 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, | |||
711 | break; | 751 | break; |
712 | 752 | ||
713 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: | 753 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: |
754 | pnpacpi_parse_ext_address_option(dev, option_flags, res); | ||
714 | break; | 755 | break; |
715 | 756 | ||
716 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | 757 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: |
@@ -765,6 +806,7 @@ static int pnpacpi_supported_resource(struct acpi_resource *res) | |||
765 | case ACPI_RESOURCE_TYPE_ADDRESS16: | 806 | case ACPI_RESOURCE_TYPE_ADDRESS16: |
766 | case ACPI_RESOURCE_TYPE_ADDRESS32: | 807 | case ACPI_RESOURCE_TYPE_ADDRESS32: |
767 | case ACPI_RESOURCE_TYPE_ADDRESS64: | 808 | case ACPI_RESOURCE_TYPE_ADDRESS64: |
809 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: | ||
768 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | 810 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: |
769 | return 1; | 811 | return 1; |
770 | } | 812 | } |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index c34b11022908..c65e4ce6c3af 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -114,10 +114,13 @@ struct acpi_device_ops { | |||
114 | acpi_op_notify notify; | 114 | acpi_op_notify notify; |
115 | }; | 115 | }; |
116 | 116 | ||
117 | #define ACPI_DRIVER_ALL_NOTIFY_EVENTS 0x1 /* system AND device events */ | ||
118 | |||
117 | struct acpi_driver { | 119 | struct acpi_driver { |
118 | char name[80]; | 120 | char name[80]; |
119 | char class[80]; | 121 | char class[80]; |
120 | const struct acpi_device_id *ids; /* Supported Hardware IDs */ | 122 | const struct acpi_device_id *ids; /* Supported Hardware IDs */ |
123 | unsigned int flags; | ||
121 | struct acpi_device_ops ops; | 124 | struct acpi_device_ops ops; |
122 | struct device_driver drv; | 125 | struct device_driver drv; |
123 | struct module *owner; | 126 | struct module *owner; |
@@ -168,7 +171,7 @@ struct acpi_device_dir { | |||
168 | 171 | ||
169 | /* Plug and Play */ | 172 | /* Plug and Play */ |
170 | 173 | ||
171 | typedef char acpi_bus_id[5]; | 174 | typedef char acpi_bus_id[8]; |
172 | typedef unsigned long acpi_bus_address; | 175 | typedef unsigned long acpi_bus_address; |
173 | typedef char acpi_hardware_id[15]; | 176 | typedef char acpi_hardware_id[15]; |
174 | typedef char acpi_unique_id[9]; | 177 | typedef char acpi_unique_id[9]; |
@@ -365,10 +368,10 @@ struct acpi_bus_type { | |||
365 | int register_acpi_bus_type(struct acpi_bus_type *); | 368 | int register_acpi_bus_type(struct acpi_bus_type *); |
366 | int unregister_acpi_bus_type(struct acpi_bus_type *); | 369 | int unregister_acpi_bus_type(struct acpi_bus_type *); |
367 | struct device *acpi_get_physical_device(acpi_handle); | 370 | struct device *acpi_get_physical_device(acpi_handle); |
368 | struct device *acpi_get_physical_pci_device(acpi_handle); | ||
369 | 371 | ||
370 | /* helper */ | 372 | /* helper */ |
371 | acpi_handle acpi_get_child(acpi_handle, acpi_integer); | 373 | acpi_handle acpi_get_child(acpi_handle, acpi_integer); |
374 | int acpi_is_root_bridge(acpi_handle); | ||
372 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); | 375 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); |
373 | #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle)) | 376 | #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle)) |
374 | 377 | ||
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index 0352c8f0b05b..f4906f6568d4 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h | |||
@@ -57,8 +57,7 @@ | |||
57 | */ | 57 | */ |
58 | 58 | ||
59 | #define ACPI_POWER_HID "LNXPOWER" | 59 | #define ACPI_POWER_HID "LNXPOWER" |
60 | #define ACPI_PROCESSOR_OBJECT_HID "ACPI_CPU" | 60 | #define ACPI_PROCESSOR_OBJECT_HID "LNXCPU" |
61 | #define ACPI_PROCESSOR_HID "ACPI0007" | ||
62 | #define ACPI_SYSTEM_HID "LNXSYSTM" | 61 | #define ACPI_SYSTEM_HID "LNXSYSTM" |
63 | #define ACPI_THERMAL_HID "LNXTHERM" | 62 | #define ACPI_THERMAL_HID "LNXTHERM" |
64 | #define ACPI_BUTTON_HID_POWERF "LNXPWRBN" | 63 | #define ACPI_BUTTON_HID_POWERF "LNXPWRBN" |
@@ -91,17 +90,15 @@ int acpi_pci_link_free_irq(acpi_handle handle); | |||
91 | 90 | ||
92 | /* ACPI PCI Interrupt Routing (pci_irq.c) */ | 91 | /* ACPI PCI Interrupt Routing (pci_irq.c) */ |
93 | 92 | ||
94 | int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus); | 93 | int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus); |
95 | void acpi_pci_irq_del_prt(int segment, int bus); | 94 | void acpi_pci_irq_del_prt(struct pci_bus *bus); |
96 | 95 | ||
97 | /* ACPI PCI Device Binding (pci_bind.c) */ | 96 | /* ACPI PCI Device Binding (pci_bind.c) */ |
98 | 97 | ||
99 | struct pci_bus; | 98 | struct pci_bus; |
100 | 99 | ||
101 | acpi_status acpi_get_pci_id(acpi_handle handle, struct acpi_pci_id *id); | 100 | struct pci_dev *acpi_get_pci_dev(acpi_handle); |
102 | int acpi_pci_bind(struct acpi_device *device); | 101 | int acpi_pci_bind_root(struct acpi_device *device); |
103 | int acpi_pci_bind_root(struct acpi_device *device, struct acpi_pci_id *id, | ||
104 | struct pci_bus *bus); | ||
105 | 102 | ||
106 | /* Arch-defined function to add a bus to the system */ | 103 | /* Arch-defined function to add a bus to the system */ |
107 | 104 | ||
diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 4927c063347c..baf1e0a9a7ee 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h | |||
@@ -258,6 +258,7 @@ DECLARE_PER_CPU(struct acpi_processor *, processors); | |||
258 | extern struct acpi_processor_errata errata; | 258 | extern struct acpi_processor_errata errata; |
259 | 259 | ||
260 | void arch_acpi_processor_init_pdc(struct acpi_processor *pr); | 260 | void arch_acpi_processor_init_pdc(struct acpi_processor *pr); |
261 | void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr); | ||
261 | 262 | ||
262 | #ifdef ARCH_HAS_POWER_INIT | 263 | #ifdef ARCH_HAS_POWER_INIT |
263 | void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, | 264 | void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, |
diff --git a/include/acpi/video.h b/include/acpi/video.h index af6fe95fd3d0..cf7be3dd157b 100644 --- a/include/acpi/video.h +++ b/include/acpi/video.h | |||
@@ -3,10 +3,10 @@ | |||
3 | 3 | ||
4 | #if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE) | 4 | #if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE) |
5 | extern int acpi_video_register(void); | 5 | extern int acpi_video_register(void); |
6 | extern int acpi_video_exit(void); | 6 | extern void acpi_video_unregister(void); |
7 | #else | 7 | #else |
8 | static inline int acpi_video_register(void) { return 0; } | 8 | static inline int acpi_video_register(void) { return 0; } |
9 | static inline void acpi_video_exit(void) { return; } | 9 | static inline void acpi_video_unregister(void) { return; } |
10 | #endif | 10 | #endif |
11 | 11 | ||
12 | #endif | 12 | #endif |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 51b4b0a5ce8c..34321cfffeab 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
@@ -113,9 +113,6 @@ void acpi_irq_stats_init(void); | |||
113 | extern u32 acpi_irq_handled; | 113 | extern u32 acpi_irq_handled; |
114 | extern u32 acpi_irq_not_handled; | 114 | extern u32 acpi_irq_not_handled; |
115 | 115 | ||
116 | extern struct acpi_mcfg_allocation *pci_mmcfg_config; | ||
117 | extern int pci_mmcfg_config_num; | ||
118 | |||
119 | extern int sbf_port; | 116 | extern int sbf_port; |
120 | extern unsigned long acpi_realmode_flags; | 117 | extern unsigned long acpi_realmode_flags; |
121 | 118 | ||
@@ -293,7 +290,10 @@ void __init acpi_s4_no_nvs(void); | |||
293 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL) | 290 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL) |
294 | 291 | ||
295 | extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags); | 292 | extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags); |
293 | extern void acpi_early_init(void); | ||
294 | |||
296 | #else /* CONFIG_ACPI */ | 295 | #else /* CONFIG_ACPI */ |
296 | static inline void acpi_early_init(void) { } | ||
297 | 297 | ||
298 | static inline int early_acpi_boot_init(void) | 298 | static inline int early_acpi_boot_init(void) |
299 | { | 299 | { |
diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h index b3646cd7fd5a..4391741b99dc 100644 --- a/include/linux/pci_hotplug.h +++ b/include/linux/pci_hotplug.h | |||
@@ -229,7 +229,6 @@ struct hotplug_params { | |||
229 | extern acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, | 229 | extern acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, |
230 | struct hotplug_params *hpp); | 230 | struct hotplug_params *hpp); |
231 | int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags); | 231 | int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags); |
232 | int acpi_root_bridge(acpi_handle handle); | ||
233 | int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle); | 232 | int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle); |
234 | int acpi_pci_detect_ejectable(struct pci_bus *pbus); | 233 | int acpi_pci_detect_ejectable(struct pci_bus *pbus); |
235 | #endif | 234 | #endif |
diff --git a/init/main.c b/init/main.c index 4870dfeb9ee5..2c5ade79eb81 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/smp_lock.h> | 24 | #include <linux/smp_lock.h> |
25 | #include <linux/initrd.h> | 25 | #include <linux/initrd.h> |
26 | #include <linux/bootmem.h> | 26 | #include <linux/bootmem.h> |
27 | #include <linux/acpi.h> | ||
27 | #include <linux/tty.h> | 28 | #include <linux/tty.h> |
28 | #include <linux/gfp.h> | 29 | #include <linux/gfp.h> |
29 | #include <linux/percpu.h> | 30 | #include <linux/percpu.h> |
@@ -88,11 +89,6 @@ extern void sbus_init(void); | |||
88 | extern void prio_tree_init(void); | 89 | extern void prio_tree_init(void); |
89 | extern void radix_tree_init(void); | 90 | extern void radix_tree_init(void); |
90 | extern void free_initmem(void); | 91 | extern void free_initmem(void); |
91 | #ifdef CONFIG_ACPI | ||
92 | extern void acpi_early_init(void); | ||
93 | #else | ||
94 | static inline void acpi_early_init(void) { } | ||
95 | #endif | ||
96 | #ifndef CONFIG_DEBUG_RODATA | 92 | #ifndef CONFIG_DEBUG_RODATA |
97 | static inline void mark_rodata_ro(void) { } | 93 | static inline void mark_rodata_ro(void) { } |
98 | #endif | 94 | #endif |