diff options
39 files changed, 1700 insertions, 843 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..7d9d3745aab9 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 |
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/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/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..5613483db141 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
@@ -34,6 +34,23 @@ 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 (EXPERIMENTAL)" |
39 | depends on ACPI | 56 | depends on ACPI |
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/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/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..bf1f43bd9016 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -168,7 +168,7 @@ struct acpi_device_dir { | |||
168 | 168 | ||
169 | /* Plug and Play */ | 169 | /* Plug and Play */ |
170 | 170 | ||
171 | typedef char acpi_bus_id[5]; | 171 | typedef char acpi_bus_id[8]; |
172 | typedef unsigned long acpi_bus_address; | 172 | typedef unsigned long acpi_bus_address; |
173 | typedef char acpi_hardware_id[15]; | 173 | typedef char acpi_hardware_id[15]; |
174 | typedef char acpi_unique_id[9]; | 174 | typedef char acpi_unique_id[9]; |
@@ -365,10 +365,10 @@ struct acpi_bus_type { | |||
365 | int register_acpi_bus_type(struct acpi_bus_type *); | 365 | int register_acpi_bus_type(struct acpi_bus_type *); |
366 | int unregister_acpi_bus_type(struct acpi_bus_type *); | 366 | int unregister_acpi_bus_type(struct acpi_bus_type *); |
367 | struct device *acpi_get_physical_device(acpi_handle); | 367 | struct device *acpi_get_physical_device(acpi_handle); |
368 | struct device *acpi_get_physical_pci_device(acpi_handle); | ||
369 | 368 | ||
370 | /* helper */ | 369 | /* helper */ |
371 | acpi_handle acpi_get_child(acpi_handle, acpi_integer); | 370 | acpi_handle acpi_get_child(acpi_handle, acpi_integer); |
371 | int acpi_is_root_bridge(acpi_handle); | ||
372 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); | 372 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); |
373 | #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle)) | 373 | #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle)) |
374 | 374 | ||
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 |