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