diff options
149 files changed, 3628 insertions, 2962 deletions
diff --git a/Documentation/devices.txt b/Documentation/devices.txt index 8de132a02ba9..6c46730c631a 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt | |||
| @@ -94,6 +94,8 @@ Your cooperation is appreciated. | |||
| 94 | 9 = /dev/urandom Faster, less secure random number gen. | 94 | 9 = /dev/urandom Faster, less secure random number gen. |
| 95 | 10 = /dev/aio Asynchronous I/O notification interface | 95 | 10 = /dev/aio Asynchronous I/O notification interface |
| 96 | 11 = /dev/kmsg Writes to this come out as printk's | 96 | 11 = /dev/kmsg Writes to this come out as printk's |
| 97 | 12 = /dev/oldmem Used by crashdump kernels to access | ||
| 98 | the memory of the kernel that crashed. | ||
| 97 | 99 | ||
| 98 | 1 block RAM disk | 100 | 1 block RAM disk |
| 99 | 0 = /dev/ram0 First RAM disk | 101 | 0 = /dev/ram0 First RAM disk |
diff --git a/Documentation/lockstat.txt b/Documentation/lockstat.txt new file mode 100644 index 000000000000..4ba4664ce5c3 --- /dev/null +++ b/Documentation/lockstat.txt | |||
| @@ -0,0 +1,120 @@ | |||
| 1 | |||
| 2 | LOCK STATISTICS | ||
| 3 | |||
| 4 | - WHAT | ||
| 5 | |||
| 6 | As the name suggests, it provides statistics on locks. | ||
| 7 | |||
| 8 | - WHY | ||
| 9 | |||
| 10 | Because things like lock contention can severely impact performance. | ||
| 11 | |||
| 12 | - HOW | ||
| 13 | |||
| 14 | Lockdep already has hooks in the lock functions and maps lock instances to | ||
| 15 | lock classes. We build on that. The graph below shows the relation between | ||
| 16 | the lock functions and the various hooks therein. | ||
| 17 | |||
| 18 | __acquire | ||
| 19 | | | ||
| 20 | lock _____ | ||
| 21 | | \ | ||
| 22 | | __contended | ||
| 23 | | | | ||
| 24 | | <wait> | ||
| 25 | | _______/ | ||
| 26 | |/ | ||
| 27 | | | ||
| 28 | __acquired | ||
| 29 | | | ||
| 30 | . | ||
| 31 | <hold> | ||
| 32 | . | ||
| 33 | | | ||
| 34 | __release | ||
| 35 | | | ||
| 36 | unlock | ||
| 37 | |||
| 38 | lock, unlock - the regular lock functions | ||
| 39 | __* - the hooks | ||
| 40 | <> - states | ||
| 41 | |||
| 42 | With these hooks we provide the following statistics: | ||
| 43 | |||
| 44 | con-bounces - number of lock contention that involved x-cpu data | ||
| 45 | contentions - number of lock acquisitions that had to wait | ||
| 46 | wait time min - shortest (non-0) time we ever had to wait for a lock | ||
| 47 | max - longest time we ever had to wait for a lock | ||
| 48 | total - total time we spend waiting on this lock | ||
| 49 | acq-bounces - number of lock acquisitions that involved x-cpu data | ||
| 50 | acquisitions - number of times we took the lock | ||
| 51 | hold time min - shortest (non-0) time we ever held the lock | ||
| 52 | max - longest time we ever held the lock | ||
| 53 | total - total time this lock was held | ||
| 54 | |||
| 55 | From these number various other statistics can be derived, such as: | ||
| 56 | |||
| 57 | hold time average = hold time total / acquisitions | ||
| 58 | |||
| 59 | These numbers are gathered per lock class, per read/write state (when | ||
| 60 | applicable). | ||
| 61 | |||
| 62 | It also tracks 4 contention points per class. A contention point is a call site | ||
| 63 | that had to wait on lock acquisition. | ||
| 64 | |||
| 65 | - USAGE | ||
| 66 | |||
| 67 | Look at the current lock statistics: | ||
| 68 | |||
| 69 | ( line numbers not part of actual output, done for clarity in the explanation | ||
| 70 | below ) | ||
| 71 | |||
| 72 | # less /proc/lock_stat | ||
| 73 | |||
| 74 | 01 lock_stat version 0.2 | ||
| 75 | 02 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
| 76 | 03 class name con-bounces contentions waittime-min waittime-max waittime-total acq-bounces acquisitions holdtime-min holdtime-max holdtime-total | ||
| 77 | 04 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
| 78 | 05 | ||
| 79 | 06 &inode->i_data.tree_lock-W: 15 21657 0.18 1093295.30 11547131054.85 58 10415 0.16 87.51 6387.60 | ||
| 80 | 07 &inode->i_data.tree_lock-R: 0 0 0.00 0.00 0.00 23302 231198 0.25 8.45 98023.38 | ||
| 81 | 08 -------------------------- | ||
| 82 | 09 &inode->i_data.tree_lock 0 [<ffffffff8027c08f>] add_to_page_cache+0x5f/0x190 | ||
| 83 | 10 | ||
| 84 | 11 ............................................................................................................................................................................................... | ||
| 85 | 12 | ||
| 86 | 13 dcache_lock: 1037 1161 0.38 45.32 774.51 6611 243371 0.15 306.48 77387.24 | ||
| 87 | 14 ----------- | ||
| 88 | 15 dcache_lock 180 [<ffffffff802c0d7e>] sys_getcwd+0x11e/0x230 | ||
| 89 | 16 dcache_lock 165 [<ffffffff802c002a>] d_alloc+0x15a/0x210 | ||
| 90 | 17 dcache_lock 33 [<ffffffff8035818d>] _atomic_dec_and_lock+0x4d/0x70 | ||
| 91 | 18 dcache_lock 1 [<ffffffff802beef8>] shrink_dcache_parent+0x18/0x130 | ||
| 92 | |||
| 93 | This excerpt shows the first two lock class statistics. Line 01 shows the | ||
| 94 | output version - each time the format changes this will be updated. Line 02-04 | ||
| 95 | show the header with column descriptions. Lines 05-10 and 13-18 show the actual | ||
| 96 | statistics. These statistics come in two parts; the actual stats separated by a | ||
| 97 | short separator (line 08, 14) from the contention points. | ||
| 98 | |||
| 99 | The first lock (05-10) is a read/write lock, and shows two lines above the | ||
| 100 | short separator. The contention points don't match the column descriptors, | ||
| 101 | they have two: contentions and [<IP>] symbol. | ||
| 102 | |||
| 103 | |||
| 104 | View the top contending locks: | ||
| 105 | |||
| 106 | # grep : /proc/lock_stat | head | ||
| 107 | &inode->i_data.tree_lock-W: 15 21657 0.18 1093295.30 11547131054.85 58 10415 0.16 87.51 6387.60 | ||
| 108 | &inode->i_data.tree_lock-R: 0 0 0.00 0.00 0.00 23302 231198 0.25 8.45 98023.38 | ||
| 109 | dcache_lock: 1037 1161 0.38 45.32 774.51 6611 243371 0.15 306.48 77387.24 | ||
| 110 | &inode->i_mutex: 161 286 18446744073709 62882.54 1244614.55 3653 20598 18446744073709 62318.60 1693822.74 | ||
| 111 | &zone->lru_lock: 94 94 0.53 7.33 92.10 4366 32690 0.29 59.81 16350.06 | ||
| 112 | &inode->i_data.i_mmap_lock: 79 79 0.40 3.77 53.03 11779 87755 0.28 116.93 29898.44 | ||
| 113 | &q->__queue_lock: 48 50 0.52 31.62 86.31 774 13131 0.17 113.08 12277.52 | ||
| 114 | &rq->rq_lock_key: 43 47 0.74 68.50 170.63 3706 33929 0.22 107.99 17460.62 | ||
| 115 | &rq->rq_lock_key#2: 39 46 0.75 6.68 49.03 2979 32292 0.17 125.17 17137.63 | ||
| 116 | tasklist_lock-W: 15 15 1.45 10.87 32.70 1201 7390 0.58 62.55 13648.47 | ||
| 117 | |||
| 118 | Clear the statistics: | ||
| 119 | |||
| 120 | # echo 0 > /proc/lock_stat | ||
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt index ef19142896ca..10c8f6922ef4 100644 --- a/Documentation/sysrq.txt +++ b/Documentation/sysrq.txt | |||
| @@ -43,7 +43,7 @@ On x86 - You press the key combo 'ALT-SysRq-<command key>'. Note - Some | |||
| 43 | keyboards may not have a key labeled 'SysRq'. The 'SysRq' key is | 43 | keyboards may not have a key labeled 'SysRq'. The 'SysRq' key is |
| 44 | also known as the 'Print Screen' key. Also some keyboards cannot | 44 | also known as the 'Print Screen' key. Also some keyboards cannot |
| 45 | handle so many keys being pressed at the same time, so you might | 45 | handle so many keys being pressed at the same time, so you might |
| 46 | have better luck with "press Alt", "press SysRq", "release Alt", | 46 | have better luck with "press Alt", "press SysRq", "release SysRq", |
| 47 | "press <command key>", release everything. | 47 | "press <command key>", release everything. |
| 48 | 48 | ||
| 49 | On SPARC - You press 'ALT-STOP-<command key>', I believe. | 49 | On SPARC - You press 'ALT-STOP-<command key>', I believe. |
diff --git a/Documentation/thinkpad-acpi.txt b/Documentation/thinkpad-acpi.txt index 60953d6c919d..3b95bbacc775 100644 --- a/Documentation/thinkpad-acpi.txt +++ b/Documentation/thinkpad-acpi.txt | |||
| @@ -105,10 +105,15 @@ The version of thinkpad-acpi's sysfs interface is exported by the driver | |||
| 105 | as a driver attribute (see below). | 105 | as a driver attribute (see below). |
| 106 | 106 | ||
| 107 | Sysfs driver attributes are on the driver's sysfs attribute space, | 107 | Sysfs driver attributes are on the driver's sysfs attribute space, |
| 108 | for 2.6.20 this is /sys/bus/platform/drivers/thinkpad_acpi/. | 108 | for 2.6.23 this is /sys/bus/platform/drivers/thinkpad_acpi/ and |
| 109 | /sys/bus/platform/drivers/thinkpad_hwmon/ | ||
| 109 | 110 | ||
| 110 | Sysfs device attributes are on the driver's sysfs attribute space, | 111 | Sysfs device attributes are on the thinkpad_acpi device sysfs attribute |
| 111 | for 2.6.20 this is /sys/devices/platform/thinkpad_acpi/. | 112 | space, for 2.6.23 this is /sys/devices/platform/thinkpad_acpi/. |
| 113 | |||
| 114 | Sysfs device attributes for the sensors and fan are on the | ||
| 115 | thinkpad_hwmon device's sysfs attribute space, but you should locate it | ||
| 116 | looking for a hwmon device with the name attribute of "thinkpad". | ||
| 112 | 117 | ||
| 113 | Driver version | 118 | Driver version |
| 114 | -------------- | 119 | -------------- |
| @@ -766,7 +771,7 @@ Temperature sensors | |||
| 766 | ------------------- | 771 | ------------------- |
| 767 | 772 | ||
| 768 | procfs: /proc/acpi/ibm/thermal | 773 | procfs: /proc/acpi/ibm/thermal |
| 769 | sysfs device attributes: (hwmon) temp*_input | 774 | sysfs device attributes: (hwmon "thinkpad") temp*_input |
| 770 | 775 | ||
| 771 | Most ThinkPads include six or more separate temperature sensors but only | 776 | Most ThinkPads include six or more separate temperature sensors but only |
| 772 | expose the CPU temperature through the standard ACPI methods. This | 777 | expose the CPU temperature through the standard ACPI methods. This |
| @@ -989,7 +994,9 @@ Fan control and monitoring: fan speed, fan enable/disable | |||
| 989 | --------------------------------------------------------- | 994 | --------------------------------------------------------- |
| 990 | 995 | ||
| 991 | procfs: /proc/acpi/ibm/fan | 996 | procfs: /proc/acpi/ibm/fan |
| 992 | sysfs device attributes: (hwmon) fan_input, pwm1, pwm1_enable | 997 | sysfs device attributes: (hwmon "thinkpad") fan1_input, pwm1, |
| 998 | pwm1_enable | ||
| 999 | sysfs hwmon driver attributes: fan_watchdog | ||
| 993 | 1000 | ||
| 994 | NOTE NOTE NOTE: fan control operations are disabled by default for | 1001 | NOTE NOTE NOTE: fan control operations are disabled by default for |
| 995 | safety reasons. To enable them, the module parameter "fan_control=1" | 1002 | safety reasons. To enable them, the module parameter "fan_control=1" |
| @@ -1131,7 +1138,7 @@ hwmon device attribute fan1_input: | |||
| 1131 | which can take up to two minutes. May return rubbish on older | 1138 | which can take up to two minutes. May return rubbish on older |
| 1132 | ThinkPads. | 1139 | ThinkPads. |
| 1133 | 1140 | ||
| 1134 | driver attribute fan_watchdog: | 1141 | hwmon driver attribute fan_watchdog: |
| 1135 | Fan safety watchdog timer interval, in seconds. Minimum is | 1142 | Fan safety watchdog timer interval, in seconds. Minimum is |
| 1136 | 1 second, maximum is 120 seconds. 0 disables the watchdog. | 1143 | 1 second, maximum is 120 seconds. 0 disables the watchdog. |
| 1137 | 1144 | ||
| @@ -1233,3 +1240,9 @@ Sysfs interface changelog: | |||
| 1233 | layer, the radio switch generates input event EV_RADIO, | 1240 | layer, the radio switch generates input event EV_RADIO, |
| 1234 | and the driver enables hot key handling by default in | 1241 | and the driver enables hot key handling by default in |
| 1235 | the firmware. | 1242 | the firmware. |
| 1243 | |||
| 1244 | 0x020000: ABI fix: added a separate hwmon platform device and | ||
| 1245 | driver, which must be located by name (thinkpad) | ||
| 1246 | and the hwmon class for libsensors4 (lm-sensors 3) | ||
| 1247 | compatibility. Moved all hwmon attributes to this | ||
| 1248 | new platform device. | ||
| @@ -1,7 +1,7 @@ | |||
| 1 | VERSION = 2 | 1 | VERSION = 2 |
| 2 | PATCHLEVEL = 6 | 2 | PATCHLEVEL = 6 |
| 3 | SUBLEVEL = 23 | 3 | SUBLEVEL = 23 |
| 4 | EXTRAVERSION =-rc8 | 4 | EXTRAVERSION = |
| 5 | NAME = Arr Matey! A Hairy Bilge Rat! | 5 | NAME = Arr Matey! A Hairy Bilge Rat! |
| 6 | 6 | ||
| 7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 240c448ec31c..a2dd930d11ef 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c | |||
| @@ -338,7 +338,7 @@ pbus_assign_bus_resources(struct pci_bus *bus, struct pci_sys_data *root) | |||
| 338 | * pcibios_fixup_bus - Called after each bus is probed, | 338 | * pcibios_fixup_bus - Called after each bus is probed, |
| 339 | * but before its children are examined. | 339 | * but before its children are examined. |
| 340 | */ | 340 | */ |
| 341 | void __devinit pcibios_fixup_bus(struct pci_bus *bus) | 341 | void pcibios_fixup_bus(struct pci_bus *bus) |
| 342 | { | 342 | { |
| 343 | struct pci_sys_data *root = bus->sysdata; | 343 | struct pci_sys_data *root = bus->sysdata; |
| 344 | struct pci_dev *dev; | 344 | struct pci_dev *dev; |
| @@ -419,7 +419,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) | |||
| 419 | /* | 419 | /* |
| 420 | * Convert from Linux-centric to bus-centric addresses for bridge devices. | 420 | * Convert from Linux-centric to bus-centric addresses for bridge devices. |
| 421 | */ | 421 | */ |
| 422 | void __devinit | 422 | void |
| 423 | pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, | 423 | pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, |
| 424 | struct resource *res) | 424 | struct resource *res) |
| 425 | { | 425 | { |
diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c index 0ba7e9060c7b..c326983f4a8f 100644 --- a/arch/arm/mach-s3c2440/mach-osiris.c +++ b/arch/arm/mach-s3c2440/mach-osiris.c | |||
| @@ -276,7 +276,21 @@ static unsigned char pm_osiris_ctrl0; | |||
| 276 | 276 | ||
| 277 | static int osiris_pm_suspend(struct sys_device *sd, pm_message_t state) | 277 | static int osiris_pm_suspend(struct sys_device *sd, pm_message_t state) |
| 278 | { | 278 | { |
| 279 | unsigned int tmp; | ||
| 280 | |||
| 279 | pm_osiris_ctrl0 = __raw_readb(OSIRIS_VA_CTRL0); | 281 | pm_osiris_ctrl0 = __raw_readb(OSIRIS_VA_CTRL0); |
| 282 | tmp = pm_osiris_ctrl0 & ~OSIRIS_CTRL0_NANDSEL; | ||
| 283 | |||
| 284 | /* ensure correct NAND slot is selected on resume */ | ||
| 285 | if ((pm_osiris_ctrl0 & OSIRIS_CTRL0_BOOT_INT) == 0) | ||
| 286 | tmp |= 2; | ||
| 287 | |||
| 288 | __raw_writeb(tmp, OSIRIS_VA_CTRL0); | ||
| 289 | |||
| 290 | /* ensure that an nRESET is not generated on resume. */ | ||
| 291 | s3c2410_gpio_setpin(S3C2410_GPA21, 1); | ||
| 292 | s3c2410_gpio_cfgpin(S3C2410_GPA21, S3C2410_GPA21_OUT); | ||
| 293 | |||
| 280 | return 0; | 294 | return 0; |
| 281 | } | 295 | } |
| 282 | 296 | ||
| @@ -285,6 +299,10 @@ static int osiris_pm_resume(struct sys_device *sd) | |||
| 285 | if (pm_osiris_ctrl0 & OSIRIS_CTRL0_FIX8) | 299 | if (pm_osiris_ctrl0 & OSIRIS_CTRL0_FIX8) |
| 286 | __raw_writeb(OSIRIS_CTRL1_FIX8, OSIRIS_VA_CTRL1); | 300 | __raw_writeb(OSIRIS_CTRL1_FIX8, OSIRIS_VA_CTRL1); |
| 287 | 301 | ||
| 302 | __raw_writeb(pm_osiris_ctrl0, OSIRIS_VA_CTRL0); | ||
| 303 | |||
| 304 | s3c2410_gpio_cfgpin(S3C2410_GPA21, S3C2410_GPA21_nRSTOUT); | ||
| 305 | |||
| 288 | return 0; | 306 | return 0; |
| 289 | } | 307 | } |
| 290 | 308 | ||
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index bafcfa52142b..5d488ef965ce 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c | |||
| @@ -84,6 +84,7 @@ | |||
| 84 | #include <linux/err.h> | 84 | #include <linux/err.h> |
| 85 | #include <asm/blackfin.h> | 85 | #include <asm/blackfin.h> |
| 86 | #include <asm/gpio.h> | 86 | #include <asm/gpio.h> |
| 87 | #include <asm/portmux.h> | ||
| 87 | #include <linux/irq.h> | 88 | #include <linux/irq.h> |
| 88 | 89 | ||
| 89 | #ifdef BF533_FAMILY | 90 | #ifdef BF533_FAMILY |
| @@ -115,7 +116,11 @@ static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = { | |||
| 115 | }; | 116 | }; |
| 116 | #endif | 117 | #endif |
| 117 | 118 | ||
| 118 | static unsigned short reserved_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; | 119 | static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; |
| 120 | static unsigned short reserved_peri_map[gpio_bank(MAX_BLACKFIN_GPIOS + 16)]; | ||
| 121 | char *str_ident = NULL; | ||
| 122 | |||
| 123 | #define RESOURCE_LABEL_SIZE 16 | ||
| 119 | 124 | ||
| 120 | #ifdef CONFIG_PM | 125 | #ifdef CONFIG_PM |
| 121 | static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; | 126 | static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; |
| @@ -143,22 +148,100 @@ inline int check_gpio(unsigned short gpio) | |||
| 143 | return 0; | 148 | return 0; |
| 144 | } | 149 | } |
| 145 | 150 | ||
| 151 | static void set_label(unsigned short ident, const char *label) | ||
| 152 | { | ||
| 153 | |||
| 154 | if (label && str_ident) { | ||
| 155 | strncpy(str_ident + ident * RESOURCE_LABEL_SIZE, label, | ||
| 156 | RESOURCE_LABEL_SIZE); | ||
| 157 | str_ident[ident * RESOURCE_LABEL_SIZE + | ||
| 158 | RESOURCE_LABEL_SIZE - 1] = 0; | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | static char *get_label(unsigned short ident) | ||
| 163 | { | ||
| 164 | if (!str_ident) | ||
| 165 | return "UNKNOWN"; | ||
| 166 | |||
| 167 | return (str_ident[ident * RESOURCE_LABEL_SIZE] ? | ||
| 168 | (str_ident + ident * RESOURCE_LABEL_SIZE) : "UNKNOWN"); | ||
| 169 | } | ||
| 170 | |||
| 171 | static int cmp_label(unsigned short ident, const char *label) | ||
| 172 | { | ||
| 173 | if (label && str_ident) | ||
| 174 | return strncmp(str_ident + ident * RESOURCE_LABEL_SIZE, | ||
| 175 | label, strlen(label)); | ||
| 176 | else | ||
| 177 | return -EINVAL; | ||
| 178 | } | ||
| 179 | |||
| 146 | #ifdef BF537_FAMILY | 180 | #ifdef BF537_FAMILY |
| 147 | static void port_setup(unsigned short gpio, unsigned short usage) | 181 | static void port_setup(unsigned short gpio, unsigned short usage) |
| 148 | { | 182 | { |
| 149 | if (usage == GPIO_USAGE) { | 183 | if (!check_gpio(gpio)) { |
| 150 | if (*port_fer[gpio_bank(gpio)] & gpio_bit(gpio)) | 184 | if (usage == GPIO_USAGE) { |
| 151 | printk(KERN_WARNING "bfin-gpio: Possible Conflict with Peripheral " | 185 | *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); |
| 152 | "usage and GPIO %d detected!\n", gpio); | 186 | } else |
| 153 | *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); | 187 | *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); |
| 154 | } else | 188 | SSYNC(); |
| 155 | *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); | 189 | } |
| 156 | SSYNC(); | ||
| 157 | } | 190 | } |
| 158 | #else | 191 | #else |
| 159 | # define port_setup(...) do { } while (0) | 192 | # define port_setup(...) do { } while (0) |
| 160 | #endif | 193 | #endif |
| 161 | 194 | ||
| 195 | #ifdef BF537_FAMILY | ||
| 196 | |||
| 197 | #define PMUX_LUT_RES 0 | ||
| 198 | #define PMUX_LUT_OFFSET 1 | ||
| 199 | #define PMUX_LUT_ENTRIES 41 | ||
| 200 | #define PMUX_LUT_SIZE 2 | ||
| 201 | |||
| 202 | static unsigned short port_mux_lut[PMUX_LUT_ENTRIES][PMUX_LUT_SIZE] = { | ||
| 203 | {P_PPI0_D13, 11}, {P_PPI0_D14, 11}, {P_PPI0_D15, 11}, | ||
| 204 | {P_SPORT1_TFS, 11}, {P_SPORT1_TSCLK, 11}, {P_SPORT1_DTPRI, 11}, | ||
| 205 | {P_PPI0_D10, 10}, {P_PPI0_D11, 10}, {P_PPI0_D12, 10}, | ||
| 206 | {P_SPORT1_RSCLK, 10}, {P_SPORT1_RFS, 10}, {P_SPORT1_DRPRI, 10}, | ||
| 207 | {P_PPI0_D8, 9}, {P_PPI0_D9, 9}, {P_SPORT1_DRSEC, 9}, | ||
| 208 | {P_SPORT1_DTSEC, 9}, {P_TMR2, 8}, {P_PPI0_FS3, 8}, {P_TMR3, 7}, | ||
| 209 | {P_SPI0_SSEL4, 7}, {P_TMR4, 6}, {P_SPI0_SSEL5, 6}, {P_TMR5, 5}, | ||
| 210 | {P_SPI0_SSEL6, 5}, {P_UART1_RX, 4}, {P_UART1_TX, 4}, {P_TMR6, 4}, | ||
| 211 | {P_TMR7, 4}, {P_UART0_RX, 3}, {P_UART0_TX, 3}, {P_DMAR0, 3}, | ||
| 212 | {P_DMAR1, 3}, {P_SPORT0_DTSEC, 1}, {P_SPORT0_DRSEC, 1}, | ||
| 213 | {P_CAN0_RX, 1}, {P_CAN0_TX, 1}, {P_SPI0_SSEL7, 1}, | ||
| 214 | {P_SPORT0_TFS, 0}, {P_SPORT0_DTPRI, 0}, {P_SPI0_SSEL2, 0}, | ||
| 215 | {P_SPI0_SSEL3, 0} | ||
| 216 | }; | ||
| 217 | |||
| 218 | static void portmux_setup(unsigned short per, unsigned short function) | ||
| 219 | { | ||
| 220 | u16 y, muxreg, offset; | ||
| 221 | |||
| 222 | for (y = 0; y < PMUX_LUT_ENTRIES; y++) { | ||
| 223 | if (port_mux_lut[y][PMUX_LUT_RES] == per) { | ||
| 224 | |||
| 225 | /* SET PORTMUX REG */ | ||
| 226 | |||
| 227 | offset = port_mux_lut[y][PMUX_LUT_OFFSET]; | ||
| 228 | muxreg = bfin_read_PORT_MUX(); | ||
| 229 | |||
| 230 | if (offset != 1) { | ||
| 231 | muxreg &= ~(1 << offset); | ||
| 232 | } else { | ||
| 233 | muxreg &= ~(3 << 1); | ||
| 234 | } | ||
| 235 | |||
| 236 | muxreg |= (function << offset); | ||
| 237 | bfin_write_PORT_MUX(muxreg); | ||
| 238 | } | ||
| 239 | } | ||
| 240 | } | ||
| 241 | |||
| 242 | #else | ||
| 243 | # define portmux_setup(...) do { } while (0) | ||
| 244 | #endif | ||
| 162 | 245 | ||
| 163 | static void default_gpio(unsigned short gpio) | 246 | static void default_gpio(unsigned short gpio) |
| 164 | { | 247 | { |
| @@ -179,22 +262,15 @@ static void default_gpio(unsigned short gpio) | |||
| 179 | 262 | ||
| 180 | static int __init bfin_gpio_init(void) | 263 | static int __init bfin_gpio_init(void) |
| 181 | { | 264 | { |
| 182 | int i; | ||
| 183 | |||
| 184 | printk(KERN_INFO "Blackfin GPIO Controller\n"); | ||
| 185 | 265 | ||
| 186 | for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) | 266 | str_ident = kzalloc(RESOURCE_LABEL_SIZE * 256, GFP_KERNEL); |
| 187 | reserved_map[gpio_bank(i)] = 0; | 267 | if (!str_ident) |
| 268 | return -ENOMEM; | ||
| 188 | 269 | ||
| 189 | #if defined(BF537_FAMILY) && (defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)) | 270 | printk(KERN_INFO "Blackfin GPIO Controller\n"); |
| 190 | # if defined(CONFIG_BFIN_MAC_RMII) | ||
| 191 | reserved_map[gpio_bank(PORT_H)] = 0xC373; | ||
| 192 | # else | ||
| 193 | reserved_map[gpio_bank(PORT_H)] = 0xFFFF; | ||
| 194 | # endif | ||
| 195 | #endif | ||
| 196 | 271 | ||
| 197 | return 0; | 272 | return 0; |
| 273 | |||
| 198 | } | 274 | } |
| 199 | 275 | ||
| 200 | arch_initcall(bfin_gpio_init); | 276 | arch_initcall(bfin_gpio_init); |
| @@ -223,7 +299,7 @@ arch_initcall(bfin_gpio_init); | |||
| 223 | void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ | 299 | void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ |
| 224 | { \ | 300 | { \ |
| 225 | unsigned long flags; \ | 301 | unsigned long flags; \ |
| 226 | BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); \ | 302 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); \ |
| 227 | local_irq_save(flags); \ | 303 | local_irq_save(flags); \ |
| 228 | if (arg) \ | 304 | if (arg) \ |
| 229 | gpio_bankb[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ | 305 | gpio_bankb[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ |
| @@ -243,7 +319,7 @@ SET_GPIO(both) | |||
| 243 | #define SET_GPIO_SC(name) \ | 319 | #define SET_GPIO_SC(name) \ |
| 244 | void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ | 320 | void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ |
| 245 | { \ | 321 | { \ |
| 246 | BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); \ | 322 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); \ |
| 247 | if (arg) \ | 323 | if (arg) \ |
| 248 | gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ | 324 | gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ |
| 249 | else \ | 325 | else \ |
| @@ -258,7 +334,7 @@ SET_GPIO_SC(maskb) | |||
| 258 | void set_gpio_data(unsigned short gpio, unsigned short arg) | 334 | void set_gpio_data(unsigned short gpio, unsigned short arg) |
| 259 | { | 335 | { |
| 260 | unsigned long flags; | 336 | unsigned long flags; |
| 261 | BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); | 337 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); |
| 262 | local_irq_save(flags); | 338 | local_irq_save(flags); |
| 263 | if (arg) | 339 | if (arg) |
| 264 | gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio); | 340 | gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio); |
| @@ -277,7 +353,7 @@ SET_GPIO_SC(data) | |||
| 277 | void set_gpio_toggle(unsigned short gpio) | 353 | void set_gpio_toggle(unsigned short gpio) |
| 278 | { | 354 | { |
| 279 | unsigned long flags; | 355 | unsigned long flags; |
| 280 | BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); | 356 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); |
| 281 | local_irq_save(flags); | 357 | local_irq_save(flags); |
| 282 | gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio); | 358 | gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio); |
| 283 | bfin_read_CHIPID(); | 359 | bfin_read_CHIPID(); |
| @@ -286,7 +362,7 @@ void set_gpio_toggle(unsigned short gpio) | |||
| 286 | #else | 362 | #else |
| 287 | void set_gpio_toggle(unsigned short gpio) | 363 | void set_gpio_toggle(unsigned short gpio) |
| 288 | { | 364 | { |
| 289 | BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); | 365 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); |
| 290 | gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio); | 366 | gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio); |
| 291 | } | 367 | } |
| 292 | #endif | 368 | #endif |
| @@ -350,7 +426,7 @@ unsigned short get_gpio_data(unsigned short gpio) | |||
| 350 | { | 426 | { |
| 351 | unsigned long flags; | 427 | unsigned long flags; |
| 352 | unsigned short ret; | 428 | unsigned short ret; |
| 353 | BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); | 429 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); |
| 354 | local_irq_save(flags); | 430 | local_irq_save(flags); |
| 355 | ret = 0x01 & (gpio_bankb[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)); | 431 | ret = 0x01 & (gpio_bankb[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)); |
| 356 | bfin_read_CHIPID(); | 432 | bfin_read_CHIPID(); |
| @@ -494,13 +570,14 @@ u32 gpio_pm_setup(void) | |||
| 494 | gpio_bank_saved[bank].dir = gpio_bankb[bank]->dir; | 570 | gpio_bank_saved[bank].dir = gpio_bankb[bank]->dir; |
| 495 | gpio_bank_saved[bank].edge = gpio_bankb[bank]->edge; | 571 | gpio_bank_saved[bank].edge = gpio_bankb[bank]->edge; |
| 496 | gpio_bank_saved[bank].both = gpio_bankb[bank]->both; | 572 | gpio_bank_saved[bank].both = gpio_bankb[bank]->both; |
| 497 | gpio_bank_saved[bank].reserved = reserved_map[bank]; | 573 | gpio_bank_saved[bank].reserved = |
| 574 | reserved_gpio_map[bank]; | ||
| 498 | 575 | ||
| 499 | gpio = i; | 576 | gpio = i; |
| 500 | 577 | ||
| 501 | while (mask) { | 578 | while (mask) { |
| 502 | if (mask & 1) { | 579 | if (mask & 1) { |
| 503 | reserved_map[gpio_bank(gpio)] |= | 580 | reserved_gpio_map[gpio_bank(gpio)] |= |
| 504 | gpio_bit(gpio); | 581 | gpio_bit(gpio); |
| 505 | bfin_gpio_wakeup_type(gpio, | 582 | bfin_gpio_wakeup_type(gpio, |
| 506 | wakeup_flags_map[gpio]); | 583 | wakeup_flags_map[gpio]); |
| @@ -540,7 +617,8 @@ void gpio_pm_restore(void) | |||
| 540 | gpio_bankb[bank]->edge = gpio_bank_saved[bank].edge; | 617 | gpio_bankb[bank]->edge = gpio_bank_saved[bank].edge; |
| 541 | gpio_bankb[bank]->both = gpio_bank_saved[bank].both; | 618 | gpio_bankb[bank]->both = gpio_bank_saved[bank].both; |
| 542 | 619 | ||
| 543 | reserved_map[bank] = gpio_bank_saved[bank].reserved; | 620 | reserved_gpio_map[bank] = |
| 621 | gpio_bank_saved[bank].reserved; | ||
| 544 | 622 | ||
| 545 | } | 623 | } |
| 546 | 624 | ||
| @@ -550,6 +628,141 @@ void gpio_pm_restore(void) | |||
| 550 | 628 | ||
| 551 | #endif | 629 | #endif |
| 552 | 630 | ||
| 631 | |||
| 632 | |||
| 633 | |||
| 634 | int peripheral_request(unsigned short per, const char *label) | ||
| 635 | { | ||
| 636 | unsigned long flags; | ||
| 637 | unsigned short ident = P_IDENT(per); | ||
| 638 | |||
| 639 | /* | ||
| 640 | * Don't cares are pins with only one dedicated function | ||
| 641 | */ | ||
| 642 | |||
| 643 | if (per & P_DONTCARE) | ||
| 644 | return 0; | ||
| 645 | |||
| 646 | if (!(per & P_DEFINED)) | ||
| 647 | return -ENODEV; | ||
| 648 | |||
| 649 | local_irq_save(flags); | ||
| 650 | |||
| 651 | if (!check_gpio(ident)) { | ||
| 652 | |||
| 653 | if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) { | ||
| 654 | printk(KERN_ERR | ||
| 655 | "%s: Peripheral %d is already reserved as GPIO by %s !\n", | ||
| 656 | __FUNCTION__, ident, get_label(ident)); | ||
| 657 | dump_stack(); | ||
| 658 | local_irq_restore(flags); | ||
| 659 | return -EBUSY; | ||
| 660 | } | ||
| 661 | |||
| 662 | } | ||
| 663 | |||
| 664 | if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) { | ||
| 665 | |||
| 666 | /* | ||
| 667 | * Pin functions like AMC address strobes my | ||
| 668 | * be requested and used by several drivers | ||
| 669 | */ | ||
| 670 | |||
| 671 | if (!(per & P_MAYSHARE)) { | ||
| 672 | |||
| 673 | /* | ||
| 674 | * Allow that the identical pin function can | ||
| 675 | * be requested from the same driver twice | ||
| 676 | */ | ||
| 677 | |||
| 678 | if (cmp_label(ident, label) == 0) | ||
| 679 | goto anyway; | ||
| 680 | |||
| 681 | printk(KERN_ERR | ||
| 682 | "%s: Peripheral %d function %d is already" | ||
| 683 | "reserved by %s !\n", | ||
| 684 | __FUNCTION__, ident, P_FUNCT2MUX(per), | ||
| 685 | get_label(ident)); | ||
| 686 | dump_stack(); | ||
| 687 | local_irq_restore(flags); | ||
| 688 | return -EBUSY; | ||
| 689 | } | ||
| 690 | |||
| 691 | } | ||
| 692 | |||
| 693 | anyway: | ||
| 694 | |||
| 695 | |||
| 696 | portmux_setup(per, P_FUNCT2MUX(per)); | ||
| 697 | |||
| 698 | port_setup(ident, PERIPHERAL_USAGE); | ||
| 699 | |||
| 700 | reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident); | ||
| 701 | local_irq_restore(flags); | ||
| 702 | set_label(ident, label); | ||
| 703 | |||
| 704 | return 0; | ||
| 705 | } | ||
| 706 | EXPORT_SYMBOL(peripheral_request); | ||
| 707 | |||
| 708 | int peripheral_request_list(unsigned short per[], const char *label) | ||
| 709 | { | ||
| 710 | u16 cnt; | ||
| 711 | int ret; | ||
| 712 | |||
| 713 | for (cnt = 0; per[cnt] != 0; cnt++) { | ||
| 714 | ret = peripheral_request(per[cnt], label); | ||
| 715 | if (ret < 0) | ||
| 716 | return ret; | ||
| 717 | } | ||
| 718 | |||
| 719 | return 0; | ||
| 720 | } | ||
| 721 | EXPORT_SYMBOL(peripheral_request_list); | ||
| 722 | |||
| 723 | void peripheral_free(unsigned short per) | ||
| 724 | { | ||
| 725 | unsigned long flags; | ||
| 726 | unsigned short ident = P_IDENT(per); | ||
| 727 | |||
| 728 | if (per & P_DONTCARE) | ||
| 729 | return; | ||
| 730 | |||
| 731 | if (!(per & P_DEFINED)) | ||
| 732 | return; | ||
| 733 | |||
| 734 | if (check_gpio(ident) < 0) | ||
| 735 | return; | ||
| 736 | |||
| 737 | local_irq_save(flags); | ||
| 738 | |||
| 739 | if (unlikely(!(reserved_peri_map[gpio_bank(ident)] | ||
| 740 | & gpio_bit(ident)))) { | ||
| 741 | local_irq_restore(flags); | ||
| 742 | return; | ||
| 743 | } | ||
| 744 | |||
| 745 | if (!(per & P_MAYSHARE)) { | ||
| 746 | port_setup(ident, GPIO_USAGE); | ||
| 747 | } | ||
| 748 | |||
| 749 | reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident); | ||
| 750 | |||
| 751 | local_irq_restore(flags); | ||
| 752 | } | ||
| 753 | EXPORT_SYMBOL(peripheral_free); | ||
| 754 | |||
| 755 | void peripheral_free_list(unsigned short per[]) | ||
| 756 | { | ||
| 757 | u16 cnt; | ||
| 758 | |||
| 759 | for (cnt = 0; per[cnt] != 0; cnt++) { | ||
| 760 | peripheral_free(per[cnt]); | ||
| 761 | } | ||
| 762 | |||
| 763 | } | ||
| 764 | EXPORT_SYMBOL(peripheral_free_list); | ||
| 765 | |||
| 553 | /*********************************************************** | 766 | /*********************************************************** |
| 554 | * | 767 | * |
| 555 | * FUNCTIONS: Blackfin GPIO Driver | 768 | * FUNCTIONS: Blackfin GPIO Driver |
| @@ -574,13 +787,13 @@ int gpio_request(unsigned short gpio, const char *label) | |||
| 574 | 787 | ||
| 575 | local_irq_save(flags); | 788 | local_irq_save(flags); |
| 576 | 789 | ||
| 577 | if (unlikely(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))) { | 790 | if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { |
| 578 | printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved!\n", gpio); | 791 | printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved!\n", gpio); |
| 579 | dump_stack(); | 792 | dump_stack(); |
| 580 | local_irq_restore(flags); | 793 | local_irq_restore(flags); |
| 581 | return -EBUSY; | 794 | return -EBUSY; |
| 582 | } | 795 | } |
| 583 | reserved_map[gpio_bank(gpio)] |= gpio_bit(gpio); | 796 | reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio); |
| 584 | 797 | ||
| 585 | local_irq_restore(flags); | 798 | local_irq_restore(flags); |
| 586 | 799 | ||
| @@ -599,7 +812,7 @@ void gpio_free(unsigned short gpio) | |||
| 599 | 812 | ||
| 600 | local_irq_save(flags); | 813 | local_irq_save(flags); |
| 601 | 814 | ||
| 602 | if (unlikely(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)))) { | 815 | if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) { |
| 603 | printk(KERN_ERR "bfin-gpio: GPIO %d wasn't reserved!\n", gpio); | 816 | printk(KERN_ERR "bfin-gpio: GPIO %d wasn't reserved!\n", gpio); |
| 604 | dump_stack(); | 817 | dump_stack(); |
| 605 | local_irq_restore(flags); | 818 | local_irq_restore(flags); |
| @@ -608,7 +821,7 @@ void gpio_free(unsigned short gpio) | |||
| 608 | 821 | ||
| 609 | default_gpio(gpio); | 822 | default_gpio(gpio); |
| 610 | 823 | ||
| 611 | reserved_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); | 824 | reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); |
| 612 | 825 | ||
| 613 | local_irq_restore(flags); | 826 | local_irq_restore(flags); |
| 614 | } | 827 | } |
| @@ -618,7 +831,7 @@ void gpio_direction_input(unsigned short gpio) | |||
| 618 | { | 831 | { |
| 619 | unsigned long flags; | 832 | unsigned long flags; |
| 620 | 833 | ||
| 621 | BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); | 834 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); |
| 622 | 835 | ||
| 623 | local_irq_save(flags); | 836 | local_irq_save(flags); |
| 624 | gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); | 837 | gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); |
| @@ -631,7 +844,7 @@ void gpio_direction_output(unsigned short gpio) | |||
| 631 | { | 844 | { |
| 632 | unsigned long flags; | 845 | unsigned long flags; |
| 633 | 846 | ||
| 634 | BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); | 847 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); |
| 635 | 848 | ||
| 636 | local_irq_save(flags); | 849 | local_irq_save(flags); |
| 637 | gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); | 850 | gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); |
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index d61bba98fb54..960458808344 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S | |||
| @@ -815,7 +815,7 @@ _extable: | |||
| 815 | 815 | ||
| 816 | ALIGN | 816 | ALIGN |
| 817 | ENTRY(_sys_call_table) | 817 | ENTRY(_sys_call_table) |
| 818 | .long _sys_ni_syscall /* 0 - old "setup()" system call*/ | 818 | .long _sys_restart_syscall /* 0 */ |
| 819 | .long _sys_exit | 819 | .long _sys_exit |
| 820 | .long _sys_fork | 820 | .long _sys_fork |
| 821 | .long _sys_read | 821 | .long _sys_read |
| @@ -978,13 +978,13 @@ ENTRY(_sys_call_table) | |||
| 978 | .long _sys_sched_get_priority_min /* 160 */ | 978 | .long _sys_sched_get_priority_min /* 160 */ |
| 979 | .long _sys_sched_rr_get_interval | 979 | .long _sys_sched_rr_get_interval |
| 980 | .long _sys_nanosleep | 980 | .long _sys_nanosleep |
| 981 | .long _sys_ni_syscall /* sys_mremap */ | 981 | .long _sys_mremap |
| 982 | .long _sys_setresuid /* setresuid16 */ | 982 | .long _sys_setresuid /* setresuid16 */ |
| 983 | .long _sys_getresuid /* getresuid16 */ /* 165 */ | 983 | .long _sys_getresuid /* getresuid16 */ /* 165 */ |
| 984 | .long _sys_ni_syscall /* for vm86 */ | 984 | .long _sys_ni_syscall /* for vm86 */ |
| 985 | .long _sys_ni_syscall /* old "query_module" */ | 985 | .long _sys_ni_syscall /* old "query_module" */ |
| 986 | .long _sys_ni_syscall /* sys_poll */ | 986 | .long _sys_ni_syscall /* sys_poll */ |
| 987 | .long _sys_ni_syscall /* sys_nfsservctl */ | 987 | .long _sys_nfsservctl |
| 988 | .long _sys_setresgid /* setresgid16 */ /* 170 */ | 988 | .long _sys_setresgid /* setresgid16 */ /* 170 */ |
| 989 | .long _sys_getresgid /* getresgid16 */ | 989 | .long _sys_getresgid /* getresgid16 */ |
| 990 | .long _sys_prctl | 990 | .long _sys_prctl |
| @@ -1040,7 +1040,7 @@ ENTRY(_sys_call_table) | |||
| 1040 | .long _sys_ni_syscall /* reserved for TUX */ | 1040 | .long _sys_ni_syscall /* reserved for TUX */ |
| 1041 | .long _sys_ni_syscall | 1041 | .long _sys_ni_syscall |
| 1042 | .long _sys_gettid | 1042 | .long _sys_gettid |
| 1043 | .long _sys_ni_syscall /* 225 */ /* sys_readahead */ | 1043 | .long _sys_readahead /* 225 */ |
| 1044 | .long _sys_setxattr | 1044 | .long _sys_setxattr |
| 1045 | .long _sys_lsetxattr | 1045 | .long _sys_lsetxattr |
| 1046 | .long _sys_fsetxattr | 1046 | .long _sys_fsetxattr |
| @@ -1157,6 +1157,21 @@ ENTRY(_sys_call_table) | |||
| 1157 | .long _sys_shmctl | 1157 | .long _sys_shmctl |
| 1158 | .long _sys_shmdt /* 340 */ | 1158 | .long _sys_shmdt /* 340 */ |
| 1159 | .long _sys_shmget | 1159 | .long _sys_shmget |
| 1160 | .long _sys_splice | ||
| 1161 | .long _sys_sync_file_range | ||
| 1162 | .long _sys_tee | ||
| 1163 | .long _sys_vmsplice /* 345 */ | ||
| 1164 | .long _sys_epoll_pwait | ||
| 1165 | .long _sys_utimensat | ||
| 1166 | .long _sys_signalfd | ||
| 1167 | .long _sys_timerfd | ||
| 1168 | .long _sys_eventfd /* 350 */ | ||
| 1169 | .long _sys_pread64 | ||
| 1170 | .long _sys_pwrite64 | ||
| 1171 | .long _sys_fadvise64 | ||
| 1172 | .long _sys_set_robust_list | ||
| 1173 | .long _sys_get_robust_list /* 355 */ | ||
| 1174 | .long _sys_fallocate | ||
| 1160 | .rept NR_syscalls-(.-_sys_call_table)/4 | 1175 | .rept NR_syscalls-(.-_sys_call_table)/4 |
| 1161 | .long _sys_ni_syscall | 1176 | .long _sys_ni_syscall |
| 1162 | .endr | 1177 | .endr |
diff --git a/arch/i386/boot/memory.c b/arch/i386/boot/memory.c index bccaa1cf6645..378353956b5d 100644 --- a/arch/i386/boot/memory.c +++ b/arch/i386/boot/memory.c | |||
| @@ -28,11 +28,14 @@ static int detect_memory_e820(void) | |||
| 28 | 28 | ||
| 29 | do { | 29 | do { |
| 30 | size = sizeof(struct e820entry); | 30 | size = sizeof(struct e820entry); |
| 31 | id = SMAP; | 31 | |
| 32 | /* Important: %edx is clobbered by some BIOSes, | ||
| 33 | so it must be either used for the error output | ||
| 34 | or explicitly marked clobbered. */ | ||
| 32 | asm("int $0x15; setc %0" | 35 | asm("int $0x15; setc %0" |
| 33 | : "=am" (err), "+b" (next), "+d" (id), "+c" (size), | 36 | : "=d" (err), "+b" (next), "=a" (id), "+c" (size), |
| 34 | "=m" (*desc) | 37 | "=m" (*desc) |
| 35 | : "D" (desc), "a" (0xe820)); | 38 | : "D" (desc), "d" (SMAP), "a" (0xe820)); |
| 36 | 39 | ||
| 37 | /* Some BIOSes stop returning SMAP in the middle of | 40 | /* Some BIOSes stop returning SMAP in the middle of |
| 38 | the search loop. We don't know exactly how the BIOS | 41 | the search loop. We don't know exactly how the BIOS |
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index ef8f0bc3fc71..f0cce3c2dc3a 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c | |||
| @@ -76,6 +76,7 @@ static unsigned int longhaul_index; | |||
| 76 | /* Module parameters */ | 76 | /* Module parameters */ |
| 77 | static int scale_voltage; | 77 | static int scale_voltage; |
| 78 | static int disable_acpi_c3; | 78 | static int disable_acpi_c3; |
| 79 | static int revid_errata; | ||
| 79 | 80 | ||
| 80 | #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg) | 81 | #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg) |
| 81 | 82 | ||
| @@ -168,7 +169,10 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index, | |||
| 168 | 169 | ||
| 169 | rdmsrl(MSR_VIA_LONGHAUL, longhaul.val); | 170 | rdmsrl(MSR_VIA_LONGHAUL, longhaul.val); |
| 170 | /* Setup new frequency */ | 171 | /* Setup new frequency */ |
| 171 | longhaul.bits.RevisionKey = longhaul.bits.RevisionID; | 172 | if (!revid_errata) |
| 173 | longhaul.bits.RevisionKey = longhaul.bits.RevisionID; | ||
| 174 | else | ||
| 175 | longhaul.bits.RevisionKey = 0; | ||
| 172 | longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf; | 176 | longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf; |
| 173 | longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; | 177 | longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; |
| 174 | /* Setup new voltage */ | 178 | /* Setup new voltage */ |
| @@ -272,7 +276,7 @@ static void longhaul_setstate(unsigned int table_index) | |||
| 272 | 276 | ||
| 273 | dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n", | 277 | dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n", |
| 274 | fsb, mult/10, mult%10, print_speed(speed/1000)); | 278 | fsb, mult/10, mult%10, print_speed(speed/1000)); |
| 275 | 279 | retry_loop: | |
| 276 | preempt_disable(); | 280 | preempt_disable(); |
| 277 | local_irq_save(flags); | 281 | local_irq_save(flags); |
| 278 | 282 | ||
| @@ -344,6 +348,47 @@ static void longhaul_setstate(unsigned int table_index) | |||
| 344 | preempt_enable(); | 348 | preempt_enable(); |
| 345 | 349 | ||
| 346 | freqs.new = calc_speed(longhaul_get_cpu_mult()); | 350 | freqs.new = calc_speed(longhaul_get_cpu_mult()); |
| 351 | /* Check if requested frequency is set. */ | ||
| 352 | if (unlikely(freqs.new != speed)) { | ||
| 353 | printk(KERN_INFO PFX "Failed to set requested frequency!\n"); | ||
| 354 | /* Revision ID = 1 but processor is expecting revision key | ||
| 355 | * equal to 0. Jumpers at the bottom of processor will change | ||
| 356 | * multiplier and FSB, but will not change bits in Longhaul | ||
| 357 | * MSR nor enable voltage scaling. */ | ||
| 358 | if (!revid_errata) { | ||
| 359 | printk(KERN_INFO PFX "Enabling \"Ignore Revision ID\" " | ||
| 360 | "option.\n"); | ||
| 361 | revid_errata = 1; | ||
| 362 | msleep(200); | ||
| 363 | goto retry_loop; | ||
| 364 | } | ||
| 365 | /* Why ACPI C3 sometimes doesn't work is a mystery for me. | ||
| 366 | * But it does happen. Processor is entering ACPI C3 state, | ||
| 367 | * but it doesn't change frequency. I tried poking various | ||
| 368 | * bits in northbridge registers, but without success. */ | ||
| 369 | if (longhaul_flags & USE_ACPI_C3) { | ||
| 370 | printk(KERN_INFO PFX "Disabling ACPI C3 support.\n"); | ||
| 371 | longhaul_flags &= ~USE_ACPI_C3; | ||
| 372 | if (revid_errata) { | ||
| 373 | printk(KERN_INFO PFX "Disabling \"Ignore " | ||
| 374 | "Revision ID\" option.\n"); | ||
| 375 | revid_errata = 0; | ||
| 376 | } | ||
| 377 | msleep(200); | ||
| 378 | goto retry_loop; | ||
| 379 | } | ||
| 380 | /* This shouldn't happen. Longhaul ver. 2 was reported not | ||
| 381 | * working on processors without voltage scaling, but with | ||
| 382 | * RevID = 1. RevID errata will make things right. Just | ||
| 383 | * to be 100% sure. */ | ||
| 384 | if (longhaul_version == TYPE_LONGHAUL_V2) { | ||
| 385 | printk(KERN_INFO PFX "Switching to Longhaul ver. 1\n"); | ||
| 386 | longhaul_version = TYPE_LONGHAUL_V1; | ||
| 387 | msleep(200); | ||
| 388 | goto retry_loop; | ||
| 389 | } | ||
| 390 | } | ||
| 391 | /* Report true CPU frequency */ | ||
| 347 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | 392 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); |
| 348 | 393 | ||
| 349 | if (!bm_timeout) | 394 | if (!bm_timeout) |
| @@ -956,11 +1001,20 @@ static void __exit longhaul_exit(void) | |||
| 956 | kfree(longhaul_table); | 1001 | kfree(longhaul_table); |
| 957 | } | 1002 | } |
| 958 | 1003 | ||
| 1004 | /* Even if BIOS is exporting ACPI C3 state, and it is used | ||
| 1005 | * with success when CPU is idle, this state doesn't | ||
| 1006 | * trigger frequency transition in some cases. */ | ||
| 959 | module_param (disable_acpi_c3, int, 0644); | 1007 | module_param (disable_acpi_c3, int, 0644); |
| 960 | MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support"); | 1008 | MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support"); |
| 961 | 1009 | /* Change CPU voltage with frequency. Very usefull to save | |
| 1010 | * power, but most VIA C3 processors aren't supporting it. */ | ||
| 962 | module_param (scale_voltage, int, 0644); | 1011 | module_param (scale_voltage, int, 0644); |
| 963 | MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor"); | 1012 | MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor"); |
| 1013 | /* Force revision key to 0 for processors which doesn't | ||
| 1014 | * support voltage scaling, but are introducing itself as | ||
| 1015 | * such. */ | ||
| 1016 | module_param(revid_errata, int, 0644); | ||
| 1017 | MODULE_PARM_DESC(revid_errata, "Ignore CPU Revision ID"); | ||
| 964 | 1018 | ||
| 965 | MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>"); | 1019 | MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>"); |
| 966 | MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); | 1020 | MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); |
diff --git a/arch/mips/au1000/common/pci.c b/arch/mips/au1000/common/pci.c index 6c25e6c09f78..9be99a68932a 100644 --- a/arch/mips/au1000/common/pci.c +++ b/arch/mips/au1000/common/pci.c | |||
| @@ -74,6 +74,7 @@ static int __init au1x_pci_setup(void) | |||
| 74 | printk(KERN_ERR "Unable to ioremap pci space\n"); | 74 | printk(KERN_ERR "Unable to ioremap pci space\n"); |
| 75 | return 1; | 75 | return 1; |
| 76 | } | 76 | } |
| 77 | au1x_controller.io_map_base = virt_io_addr; | ||
| 77 | 78 | ||
| 78 | #ifdef CONFIG_DMA_NONCOHERENT | 79 | #ifdef CONFIG_DMA_NONCOHERENT |
| 79 | { | 80 | { |
diff --git a/arch/mips/au1000/mtx-1/board_setup.c b/arch/mips/au1000/mtx-1/board_setup.c index 7bc5af8917da..2c460c116570 100644 --- a/arch/mips/au1000/mtx-1/board_setup.c +++ b/arch/mips/au1000/mtx-1/board_setup.c | |||
| @@ -54,11 +54,11 @@ void board_reset (void) | |||
| 54 | 54 | ||
| 55 | void __init board_setup(void) | 55 | void __init board_setup(void) |
| 56 | { | 56 | { |
| 57 | #ifdef CONFIG_USB_OHCI | 57 | #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) |
| 58 | // enable USB power switch | 58 | // enable USB power switch |
| 59 | au_writel( au_readl(GPIO2_DIR) | 0x10, GPIO2_DIR ); | 59 | au_writel( au_readl(GPIO2_DIR) | 0x10, GPIO2_DIR ); |
| 60 | au_writel( 0x100000, GPIO2_OUTPUT ); | 60 | au_writel( 0x100000, GPIO2_OUTPUT ); |
| 61 | #endif // defined (CONFIG_USB_OHCI) | 61 | #endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ |
| 62 | 62 | ||
| 63 | #ifdef CONFIG_PCI | 63 | #ifdef CONFIG_PCI |
| 64 | #if defined(__MIPSEB__) | 64 | #if defined(__MIPSEB__) |
diff --git a/arch/mips/au1000/pb1000/board_setup.c b/arch/mips/au1000/pb1000/board_setup.c index 824cfafaff92..0aed89114bfc 100644 --- a/arch/mips/au1000/pb1000/board_setup.c +++ b/arch/mips/au1000/pb1000/board_setup.c | |||
| @@ -54,7 +54,7 @@ void __init board_setup(void) | |||
| 54 | au_writel(0, SYS_PINSTATERD); | 54 | au_writel(0, SYS_PINSTATERD); |
| 55 | udelay(100); | 55 | udelay(100); |
| 56 | 56 | ||
| 57 | #ifdef CONFIG_USB_OHCI | 57 | #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) |
| 58 | /* zero and disable FREQ2 */ | 58 | /* zero and disable FREQ2 */ |
| 59 | sys_freqctrl = au_readl(SYS_FREQCTRL0); | 59 | sys_freqctrl = au_readl(SYS_FREQCTRL0); |
| 60 | sys_freqctrl &= ~0xFFF00000; | 60 | sys_freqctrl &= ~0xFFF00000; |
| @@ -102,7 +102,7 @@ void __init board_setup(void) | |||
| 102 | /* | 102 | /* |
| 103 | * Route 48MHz FREQ2 into USB Host and/or Device | 103 | * Route 48MHz FREQ2 into USB Host and/or Device |
| 104 | */ | 104 | */ |
| 105 | #ifdef CONFIG_USB_OHCI | 105 | #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) |
| 106 | sys_clksrc |= ((4<<12) | (0<<11) | (0<<10)); | 106 | sys_clksrc |= ((4<<12) | (0<<11) | (0<<10)); |
| 107 | #endif | 107 | #endif |
| 108 | au_writel(sys_clksrc, SYS_CLKSRC); | 108 | au_writel(sys_clksrc, SYS_CLKSRC); |
| @@ -116,7 +116,7 @@ void __init board_setup(void) | |||
| 116 | au_writel(pin_func, SYS_PINFUNC); | 116 | au_writel(pin_func, SYS_PINFUNC); |
| 117 | au_writel(0x2800, SYS_TRIOUTCLR); | 117 | au_writel(0x2800, SYS_TRIOUTCLR); |
| 118 | au_writel(0x0030, SYS_OUTPUTCLR); | 118 | au_writel(0x0030, SYS_OUTPUTCLR); |
| 119 | #endif // defined (CONFIG_USB_OHCI) | 119 | #endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ |
| 120 | 120 | ||
| 121 | // make gpio 15 an input (for interrupt line) | 121 | // make gpio 15 an input (for interrupt line) |
| 122 | pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x100); | 122 | pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x100); |
diff --git a/arch/mips/au1000/pb1100/board_setup.c b/arch/mips/au1000/pb1100/board_setup.c index 6bc1f8e1b608..259ca05860c3 100644 --- a/arch/mips/au1000/pb1100/board_setup.c +++ b/arch/mips/au1000/pb1100/board_setup.c | |||
| @@ -54,7 +54,7 @@ void __init board_setup(void) | |||
| 54 | au_writel(0, SYS_PININPUTEN); | 54 | au_writel(0, SYS_PININPUTEN); |
| 55 | udelay(100); | 55 | udelay(100); |
| 56 | 56 | ||
| 57 | #ifdef CONFIG_USB_OHCI | 57 | #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) |
| 58 | { | 58 | { |
| 59 | u32 pin_func, sys_freqctrl, sys_clksrc; | 59 | u32 pin_func, sys_freqctrl, sys_clksrc; |
| 60 | 60 | ||
| @@ -98,7 +98,7 @@ void __init board_setup(void) | |||
| 98 | pin_func |= 0x8000; | 98 | pin_func |= 0x8000; |
| 99 | au_writel(pin_func, SYS_PINFUNC); | 99 | au_writel(pin_func, SYS_PINFUNC); |
| 100 | } | 100 | } |
| 101 | #endif // defined (CONFIG_USB_OHCI) | 101 | #endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ |
| 102 | 102 | ||
| 103 | /* Enable sys bus clock divider when IDLE state or no bus activity. */ | 103 | /* Enable sys bus clock divider when IDLE state or no bus activity. */ |
| 104 | au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL); | 104 | au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL); |
diff --git a/arch/mips/au1000/pb1500/board_setup.c b/arch/mips/au1000/pb1500/board_setup.c index c9b655616fb3..a2d850db8902 100644 --- a/arch/mips/au1000/pb1500/board_setup.c +++ b/arch/mips/au1000/pb1500/board_setup.c | |||
| @@ -56,7 +56,7 @@ void __init board_setup(void) | |||
| 56 | au_writel(0, SYS_PINSTATERD); | 56 | au_writel(0, SYS_PINSTATERD); |
| 57 | udelay(100); | 57 | udelay(100); |
| 58 | 58 | ||
| 59 | #ifdef CONFIG_USB_OHCI | 59 | #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) |
| 60 | 60 | ||
| 61 | /* GPIO201 is input for PCMCIA card detect */ | 61 | /* GPIO201 is input for PCMCIA card detect */ |
| 62 | /* GPIO203 is input for PCMCIA interrupt request */ | 62 | /* GPIO203 is input for PCMCIA interrupt request */ |
| @@ -85,7 +85,7 @@ void __init board_setup(void) | |||
| 85 | /* | 85 | /* |
| 86 | * Route 48MHz FREQ2 into USB Host and/or Device | 86 | * Route 48MHz FREQ2 into USB Host and/or Device |
| 87 | */ | 87 | */ |
| 88 | #ifdef CONFIG_USB_OHCI | 88 | #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) |
| 89 | sys_clksrc |= ((4<<12) | (0<<11) | (0<<10)); | 89 | sys_clksrc |= ((4<<12) | (0<<11) | (0<<10)); |
| 90 | #endif | 90 | #endif |
| 91 | au_writel(sys_clksrc, SYS_CLKSRC); | 91 | au_writel(sys_clksrc, SYS_CLKSRC); |
| @@ -95,7 +95,7 @@ void __init board_setup(void) | |||
| 95 | // 2nd USB port is USB host | 95 | // 2nd USB port is USB host |
| 96 | pin_func |= 0x8000; | 96 | pin_func |= 0x8000; |
| 97 | au_writel(pin_func, SYS_PINFUNC); | 97 | au_writel(pin_func, SYS_PINFUNC); |
| 98 | #endif // defined (CONFIG_USB_OHCI) | 98 | #endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ |
| 99 | 99 | ||
| 100 | 100 | ||
| 101 | 101 | ||
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index b3ed731a24c6..dd68afce7da5 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S | |||
| @@ -525,5 +525,5 @@ sys_call_table: | |||
| 525 | PTR compat_sys_signalfd | 525 | PTR compat_sys_signalfd |
| 526 | PTR compat_sys_timerfd | 526 | PTR compat_sys_timerfd |
| 527 | PTR sys_eventfd | 527 | PTR sys_eventfd |
| 528 | PTR sys_fallocate /* 4320 */ | 528 | PTR sys32_fallocate /* 4320 */ |
| 529 | .size sys_call_table,.-sys_call_table | 529 | .size sys_call_table,.-sys_call_table |
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 60bbaecde187..087ab997487d 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S | |||
| @@ -45,6 +45,8 @@ SECTIONS | |||
| 45 | __dbe_table : { *(__dbe_table) } | 45 | __dbe_table : { *(__dbe_table) } |
| 46 | __stop___dbe_table = .; | 46 | __stop___dbe_table = .; |
| 47 | 47 | ||
| 48 | NOTES | ||
| 49 | |||
| 48 | RODATA | 50 | RODATA |
| 49 | 51 | ||
| 50 | /* writeable */ | 52 | /* writeable */ |
diff --git a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c index dc795be62807..e47e9e9486bf 100644 --- a/arch/mips/mm/pg-r4k.c +++ b/arch/mips/mm/pg-r4k.c | |||
| @@ -209,7 +209,7 @@ static inline void build_cdex_p(void) | |||
| 209 | } | 209 | } |
| 210 | 210 | ||
| 211 | if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) | 211 | if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) |
| 212 | build_insn_word(0x3c01a000); /* lui $at, 0xa000 */ | 212 | build_insn_word(0x8c200000); /* lw $zero, ($at) */ |
| 213 | 213 | ||
| 214 | mi.c_format.opcode = cache_op; | 214 | mi.c_format.opcode = cache_op; |
| 215 | mi.c_format.rs = 4; /* $a0 */ | 215 | mi.c_format.rs = 4; /* $a0 */ |
diff --git a/arch/mips/pci/ops-mace.c b/arch/mips/pci/ops-mace.c index 8008e31c5e81..fe5451449304 100644 --- a/arch/mips/pci/ops-mace.c +++ b/arch/mips/pci/ops-mace.c | |||
| @@ -29,22 +29,20 @@ | |||
| 29 | * 4 N/C | 29 | * 4 N/C |
| 30 | */ | 30 | */ |
| 31 | 31 | ||
| 32 | #define chkslot(_bus,_devfn) \ | 32 | static inline int mkaddr(struct pci_bus *bus, unsigned int devfn, |
| 33 | do { \ | 33 | unsigned int reg) |
| 34 | if ((_bus)->number > 0 || PCI_SLOT (_devfn) < 1 \ | 34 | { |
| 35 | || PCI_SLOT (_devfn) > 3) \ | 35 | return ((bus->number & 0xff) << 16) | |
| 36 | return PCIBIOS_DEVICE_NOT_FOUND; \ | 36 | ((devfn & 0xff) << 8) | |
| 37 | } while (0) | 37 | (reg & 0xfc); |
| 38 | } | ||
| 38 | 39 | ||
| 39 | #define mkaddr(_devfn, _reg) \ | ||
| 40 | ((((_devfn) & 0xffUL) << 8) | ((_reg) & 0xfcUL)) | ||
| 41 | 40 | ||
| 42 | static int | 41 | static int |
| 43 | mace_pci_read_config(struct pci_bus *bus, unsigned int devfn, | 42 | mace_pci_read_config(struct pci_bus *bus, unsigned int devfn, |
| 44 | int reg, int size, u32 *val) | 43 | int reg, int size, u32 *val) |
| 45 | { | 44 | { |
| 46 | chkslot(bus, devfn); | 45 | mace->pci.config_addr = mkaddr(bus, devfn, reg); |
| 47 | mace->pci.config_addr = mkaddr(devfn, reg); | ||
| 48 | switch (size) { | 46 | switch (size) { |
| 49 | case 1: | 47 | case 1: |
| 50 | *val = mace->pci.config_data.b[(reg & 3) ^ 3]; | 48 | *val = mace->pci.config_data.b[(reg & 3) ^ 3]; |
| @@ -66,8 +64,7 @@ static int | |||
| 66 | mace_pci_write_config(struct pci_bus *bus, unsigned int devfn, | 64 | mace_pci_write_config(struct pci_bus *bus, unsigned int devfn, |
| 67 | int reg, int size, u32 val) | 65 | int reg, int size, u32 val) |
| 68 | { | 66 | { |
| 69 | chkslot(bus, devfn); | 67 | mace->pci.config_addr = mkaddr(bus, devfn, reg); |
| 70 | mace->pci.config_addr = mkaddr(devfn, reg); | ||
| 71 | switch (size) { | 68 | switch (size) { |
| 72 | case 1: | 69 | case 1: |
| 73 | mace->pci.config_data.b[(reg & 3) ^ 3] = val; | 70 | mace->pci.config_data.b[(reg & 3) ^ 3] = val; |
diff --git a/arch/mips/sgi-ip32/ip32-platform.c b/arch/mips/sgi-ip32/ip32-platform.c index ba3697ee7ff6..7309e48d163d 100644 --- a/arch/mips/sgi-ip32/ip32-platform.c +++ b/arch/mips/sgi-ip32/ip32-platform.c | |||
| @@ -41,8 +41,8 @@ static struct platform_device uart8250_device = { | |||
| 41 | 41 | ||
| 42 | static int __init uart8250_init(void) | 42 | static int __init uart8250_init(void) |
| 43 | { | 43 | { |
| 44 | uart8250_data[0].iobase = (unsigned long) &mace->isa.serial1; | 44 | uart8250_data[0].membase = (void __iomem *) &mace->isa.serial1; |
| 45 | uart8250_data[1].iobase = (unsigned long) &mace->isa.serial1; | 45 | uart8250_data[1].membase = (void __iomem *) &mace->isa.serial1; |
| 46 | 46 | ||
| 47 | return platform_device_register(&uart8250_device); | 47 | return platform_device_register(&uart8250_device); |
| 48 | } | 48 | } |
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts index 502f47c01797..44c065a6b5e7 100644 --- a/arch/powerpc/boot/dts/mpc8349emitx.dts +++ b/arch/powerpc/boot/dts/mpc8349emitx.dts | |||
| @@ -99,6 +99,7 @@ | |||
| 99 | #size-cells = <0>; | 99 | #size-cells = <0>; |
| 100 | interrupt-parent = < &ipic >; | 100 | interrupt-parent = < &ipic >; |
| 101 | interrupts = <26 8>; | 101 | interrupts = <26 8>; |
| 102 | dr_mode = "peripheral"; | ||
| 102 | phy_type = "ulpi"; | 103 | phy_type = "ulpi"; |
| 103 | }; | 104 | }; |
| 104 | 105 | ||
diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c index e7fdf013cd39..eafe7605cdac 100644 --- a/arch/powerpc/platforms/83xx/usb.c +++ b/arch/powerpc/platforms/83xx/usb.c | |||
| @@ -76,14 +76,14 @@ int mpc834x_usb_cfg(void) | |||
| 76 | if (port0_is_dr) | 76 | if (port0_is_dr) |
| 77 | printk(KERN_WARNING | 77 | printk(KERN_WARNING |
| 78 | "834x USB port0 can't be used by both DR and MPH!\n"); | 78 | "834x USB port0 can't be used by both DR and MPH!\n"); |
| 79 | sicrl |= MPC834X_SICRL_USB0; | 79 | sicrl &= ~MPC834X_SICRL_USB0; |
| 80 | } | 80 | } |
| 81 | prop = of_get_property(np, "port1", NULL); | 81 | prop = of_get_property(np, "port1", NULL); |
| 82 | if (prop) { | 82 | if (prop) { |
| 83 | if (port1_is_dr) | 83 | if (port1_is_dr) |
| 84 | printk(KERN_WARNING | 84 | printk(KERN_WARNING |
| 85 | "834x USB port1 can't be used by both DR and MPH!\n"); | 85 | "834x USB port1 can't be used by both DR and MPH!\n"); |
| 86 | sicrl |= MPC834X_SICRL_USB1; | 86 | sicrl &= ~MPC834X_SICRL_USB1; |
| 87 | } | 87 | } |
| 88 | of_node_put(np); | 88 | of_node_put(np); |
| 89 | } | 89 | } |
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 5bd90a7eb763..f0b5ff17d860 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
| @@ -419,7 +419,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) | |||
| 419 | * For the moment only implement delivery to all cpus or one cpu. | 419 | * For the moment only implement delivery to all cpus or one cpu. |
| 420 | * Get current irq_server for the given irq | 420 | * Get current irq_server for the given irq |
| 421 | */ | 421 | */ |
| 422 | irq_server = get_irq_server(irq, 1); | 422 | irq_server = get_irq_server(virq, 1); |
| 423 | if (irq_server == -1) { | 423 | if (irq_server == -1) { |
| 424 | char cpulist[128]; | 424 | char cpulist[128]; |
| 425 | cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask); | 425 | cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask); |
diff --git a/arch/powerpc/sysdev/commproc.c b/arch/powerpc/sysdev/commproc.c index 4f67b89ba1d0..dd5417aec1b4 100644 --- a/arch/powerpc/sysdev/commproc.c +++ b/arch/powerpc/sysdev/commproc.c | |||
| @@ -395,4 +395,4 @@ uint cpm_dpram_phys(u8* addr) | |||
| 395 | { | 395 | { |
| 396 | return (dpram_pbase + (uint)(addr - dpram_vbase)); | 396 | return (dpram_pbase + (uint)(addr - dpram_vbase)); |
| 397 | } | 397 | } |
| 398 | EXPORT_SYMBOL(cpm_dpram_addr); | 398 | EXPORT_SYMBOL(cpm_dpram_phys); |
diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c index 7088428e1fe2..9da880be4dc0 100644 --- a/arch/ppc/8xx_io/commproc.c +++ b/arch/ppc/8xx_io/commproc.c | |||
| @@ -459,7 +459,7 @@ EXPORT_SYMBOL(cpm_dpdump); | |||
| 459 | 459 | ||
| 460 | void *cpm_dpram_addr(unsigned long offset) | 460 | void *cpm_dpram_addr(unsigned long offset) |
| 461 | { | 461 | { |
| 462 | return ((immap_t *)IMAP_ADDR)->im_cpm.cp_dpmem + offset; | 462 | return (void *)(dpram_vbase + offset); |
| 463 | } | 463 | } |
| 464 | EXPORT_SYMBOL(cpm_dpram_addr); | 464 | EXPORT_SYMBOL(cpm_dpram_addr); |
| 465 | 465 | ||
diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c index e2d02fd13f35..d850785b2080 100644 --- a/arch/sparc/kernel/ebus.c +++ b/arch/sparc/kernel/ebus.c | |||
| @@ -156,6 +156,8 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d | |||
| 156 | dev->prom_node = dp; | 156 | dev->prom_node = dp; |
| 157 | 157 | ||
| 158 | regs = of_get_property(dp, "reg", &len); | 158 | regs = of_get_property(dp, "reg", &len); |
| 159 | if (!regs) | ||
| 160 | len = 0; | ||
| 159 | if (len % sizeof(struct linux_prom_registers)) { | 161 | if (len % sizeof(struct linux_prom_registers)) { |
| 160 | prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", | 162 | prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", |
| 161 | dev->prom_node->name, len, | 163 | dev->prom_node->name, len, |
diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c index f205fc7cbcd0..d208cc7804f2 100644 --- a/arch/sparc64/kernel/binfmt_aout32.c +++ b/arch/sparc64/kernel/binfmt_aout32.c | |||
| @@ -177,7 +177,7 @@ static u32 __user *create_aout32_tables(char __user *p, struct linux_binprm *bpr | |||
| 177 | get_user(c,p++); | 177 | get_user(c,p++); |
| 178 | } while (c); | 178 | } while (c); |
| 179 | } | 179 | } |
| 180 | put_user(NULL,argv); | 180 | put_user(0,argv); |
| 181 | current->mm->arg_end = current->mm->env_start = (unsigned long) p; | 181 | current->mm->arg_end = current->mm->env_start = (unsigned long) p; |
| 182 | while (envc-->0) { | 182 | while (envc-->0) { |
| 183 | char c; | 183 | char c; |
| @@ -186,7 +186,7 @@ static u32 __user *create_aout32_tables(char __user *p, struct linux_binprm *bpr | |||
| 186 | get_user(c,p++); | 186 | get_user(c,p++); |
| 187 | } while (c); | 187 | } while (c); |
| 188 | } | 188 | } |
| 189 | put_user(NULL,envp); | 189 | put_user(0,envp); |
| 190 | current->mm->env_end = (unsigned long) p; | 190 | current->mm->env_end = (unsigned long) p; |
| 191 | return sp; | 191 | return sp; |
| 192 | } | 192 | } |
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index bc9ae36f7a43..04ab81cb4f48 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c | |||
| @@ -375,7 +375,10 @@ static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_de | |||
| 375 | dev->num_addrs = 0; | 375 | dev->num_addrs = 0; |
| 376 | dev->num_irqs = 0; | 376 | dev->num_irqs = 0; |
| 377 | } else { | 377 | } else { |
| 378 | (void) of_get_property(dp, "reg", &len); | 378 | const int *regs = of_get_property(dp, "reg", &len); |
| 379 | |||
| 380 | if (!regs) | ||
| 381 | len = 0; | ||
| 379 | dev->num_addrs = len / sizeof(struct linux_prom_registers); | 382 | dev->num_addrs = len / sizeof(struct linux_prom_registers); |
| 380 | 383 | ||
| 381 | for (i = 0; i < dev->num_addrs; i++) | 384 | for (i = 0; i < dev->num_addrs; i++) |
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 2f61c4b12596..c76bfbb7da08 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c | |||
| @@ -264,7 +264,7 @@ static int sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | |||
| 264 | unsigned int func = PCI_FUNC(devfn); | 264 | unsigned int func = PCI_FUNC(devfn); |
| 265 | unsigned long ret; | 265 | unsigned long ret; |
| 266 | 266 | ||
| 267 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | 267 | if (!bus && devfn == 0x00) |
| 268 | return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, | 268 | return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, |
| 269 | size, value); | 269 | size, value); |
| 270 | if (config_out_of_range(pbm, bus, devfn, where)) { | 270 | if (config_out_of_range(pbm, bus, devfn, where)) { |
| @@ -300,7 +300,7 @@ static int sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | |||
| 300 | unsigned int func = PCI_FUNC(devfn); | 300 | unsigned int func = PCI_FUNC(devfn); |
| 301 | unsigned long ret; | 301 | unsigned long ret; |
| 302 | 302 | ||
| 303 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | 303 | if (!bus && devfn == 0x00) |
| 304 | return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, | 304 | return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, |
| 305 | size, value); | 305 | size, value); |
| 306 | if (config_out_of_range(pbm, bus, devfn, where)) { | 306 | if (config_out_of_range(pbm, bus, devfn, where)) { |
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 0614dff63d7c..a246e962e5a7 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c | |||
| @@ -1046,7 +1046,8 @@ static void __init irq_trans_init(struct device_node *dp) | |||
| 1046 | if (!strcmp(dp->name, "fhc") && | 1046 | if (!strcmp(dp->name, "fhc") && |
| 1047 | !strcmp(dp->parent->name, "central")) | 1047 | !strcmp(dp->parent->name, "central")) |
| 1048 | return central_irq_trans_init(dp); | 1048 | return central_irq_trans_init(dp); |
| 1049 | if (!strcmp(dp->name, "virtual-devices")) | 1049 | if (!strcmp(dp->name, "virtual-devices") || |
| 1050 | !strcmp(dp->name, "niu")) | ||
| 1050 | return sun4v_vdev_irq_trans_init(dp); | 1051 | return sun4v_vdev_irq_trans_init(dp); |
| 1051 | } | 1052 | } |
| 1052 | 1053 | ||
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index b84c49e3697c..c73b7a48b036 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c | |||
| @@ -353,6 +353,8 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu) | |||
| 353 | int timeout, ret; | 353 | int timeout, ret; |
| 354 | 354 | ||
| 355 | p = fork_idle(cpu); | 355 | p = fork_idle(cpu); |
| 356 | if (IS_ERR(p)) | ||
| 357 | return PTR_ERR(p); | ||
| 356 | callin_flag = 0; | 358 | callin_flag = 0; |
| 357 | cpu_new_thread = task_thread_info(p); | 359 | cpu_new_thread = task_thread_info(p); |
| 358 | 360 | ||
diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c index 1550ac5673da..0c1ee619d814 100644 --- a/arch/sparc64/kernel/vio.c +++ b/arch/sparc64/kernel/vio.c | |||
| @@ -292,7 +292,7 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, | |||
| 292 | } | 292 | } |
| 293 | vdev->dp = dp; | 293 | vdev->dp = dp; |
| 294 | 294 | ||
| 295 | printk(KERN_ERR "VIO: Adding device %s\n", vdev->dev.bus_id); | 295 | printk(KERN_INFO "VIO: Adding device %s\n", vdev->dev.bus_id); |
| 296 | 296 | ||
| 297 | err = device_register(&vdev->dev); | 297 | err = device_register(&vdev->dev); |
| 298 | if (err) { | 298 | if (err) { |
| @@ -342,8 +342,33 @@ static struct mdesc_notifier_client vio_device_notifier = { | |||
| 342 | .node_name = "virtual-device-port", | 342 | .node_name = "virtual-device-port", |
| 343 | }; | 343 | }; |
| 344 | 344 | ||
| 345 | /* We are only interested in domain service ports under the | ||
| 346 | * "domain-services" node. On control nodes there is another port | ||
| 347 | * under "openboot" that we should not mess with as aparently that is | ||
| 348 | * reserved exclusively for OBP use. | ||
| 349 | */ | ||
| 350 | static void vio_add_ds(struct mdesc_handle *hp, u64 node) | ||
| 351 | { | ||
| 352 | int found; | ||
| 353 | u64 a; | ||
| 354 | |||
| 355 | found = 0; | ||
| 356 | mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) { | ||
| 357 | u64 target = mdesc_arc_target(hp, a); | ||
| 358 | const char *name = mdesc_node_name(hp, target); | ||
| 359 | |||
| 360 | if (!strcmp(name, "domain-services")) { | ||
| 361 | found = 1; | ||
| 362 | break; | ||
| 363 | } | ||
| 364 | } | ||
| 365 | |||
| 366 | if (found) | ||
| 367 | (void) vio_create_one(hp, node, &root_vdev->dev); | ||
| 368 | } | ||
| 369 | |||
| 345 | static struct mdesc_notifier_client vio_ds_notifier = { | 370 | static struct mdesc_notifier_client vio_ds_notifier = { |
| 346 | .add = vio_add, | 371 | .add = vio_add_ds, |
| 347 | .remove = vio_remove, | 372 | .remove = vio_remove, |
| 348 | .node_name = "domain-services-port", | 373 | .node_name = "domain-services-port", |
| 349 | }; | 374 | }; |
diff --git a/arch/sparc64/lib/NGcopy_from_user.S b/arch/sparc64/lib/NGcopy_from_user.S index 2d93456f76dd..e7f433f71b42 100644 --- a/arch/sparc64/lib/NGcopy_from_user.S +++ b/arch/sparc64/lib/NGcopy_from_user.S | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* NGcopy_from_user.S: Niagara optimized copy from userspace. | 1 | /* NGcopy_from_user.S: Niagara optimized copy from userspace. |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2006 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net) |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #define EX_LD(x) \ | 6 | #define EX_LD(x) \ |
| @@ -8,8 +8,8 @@ | |||
| 8 | .section .fixup; \ | 8 | .section .fixup; \ |
| 9 | .align 4; \ | 9 | .align 4; \ |
| 10 | 99: wr %g0, ASI_AIUS, %asi;\ | 10 | 99: wr %g0, ASI_AIUS, %asi;\ |
| 11 | retl; \ | 11 | ret; \ |
| 12 | mov 1, %o0; \ | 12 | restore %g0, 1, %o0; \ |
| 13 | .section __ex_table,"a";\ | 13 | .section __ex_table,"a";\ |
| 14 | .align 4; \ | 14 | .align 4; \ |
| 15 | .word 98b, 99b; \ | 15 | .word 98b, 99b; \ |
| @@ -24,7 +24,7 @@ | |||
| 24 | #define LOAD(type,addr,dest) type##a [addr] ASI_AIUS, dest | 24 | #define LOAD(type,addr,dest) type##a [addr] ASI_AIUS, dest |
| 25 | #define LOAD_TWIN(addr_reg,dest0,dest1) \ | 25 | #define LOAD_TWIN(addr_reg,dest0,dest1) \ |
| 26 | ldda [addr_reg] ASI_BLK_INIT_QUAD_LDD_AIUS, dest0 | 26 | ldda [addr_reg] ASI_BLK_INIT_QUAD_LDD_AIUS, dest0 |
| 27 | #define EX_RETVAL(x) 0 | 27 | #define EX_RETVAL(x) %g0 |
| 28 | 28 | ||
| 29 | #ifdef __KERNEL__ | 29 | #ifdef __KERNEL__ |
| 30 | #define PREAMBLE \ | 30 | #define PREAMBLE \ |
diff --git a/arch/sparc64/lib/NGcopy_to_user.S b/arch/sparc64/lib/NGcopy_to_user.S index 34112d5054ef..6ea01c5532a0 100644 --- a/arch/sparc64/lib/NGcopy_to_user.S +++ b/arch/sparc64/lib/NGcopy_to_user.S | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* NGcopy_to_user.S: Niagara optimized copy to userspace. | 1 | /* NGcopy_to_user.S: Niagara optimized copy to userspace. |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2006 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net) |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #define EX_ST(x) \ | 6 | #define EX_ST(x) \ |
| @@ -8,8 +8,8 @@ | |||
| 8 | .section .fixup; \ | 8 | .section .fixup; \ |
| 9 | .align 4; \ | 9 | .align 4; \ |
| 10 | 99: wr %g0, ASI_AIUS, %asi;\ | 10 | 99: wr %g0, ASI_AIUS, %asi;\ |
| 11 | retl; \ | 11 | ret; \ |
| 12 | mov 1, %o0; \ | 12 | restore %g0, 1, %o0; \ |
| 13 | .section __ex_table,"a";\ | 13 | .section __ex_table,"a";\ |
| 14 | .align 4; \ | 14 | .align 4; \ |
| 15 | .word 98b, 99b; \ | 15 | .word 98b, 99b; \ |
| @@ -23,7 +23,7 @@ | |||
| 23 | #define FUNC_NAME NGcopy_to_user | 23 | #define FUNC_NAME NGcopy_to_user |
| 24 | #define STORE(type,src,addr) type##a src, [addr] ASI_AIUS | 24 | #define STORE(type,src,addr) type##a src, [addr] ASI_AIUS |
| 25 | #define STORE_ASI ASI_BLK_INIT_QUAD_LDD_AIUS | 25 | #define STORE_ASI ASI_BLK_INIT_QUAD_LDD_AIUS |
| 26 | #define EX_RETVAL(x) 0 | 26 | #define EX_RETVAL(x) %g0 |
| 27 | 27 | ||
| 28 | #ifdef __KERNEL__ | 28 | #ifdef __KERNEL__ |
| 29 | /* Writing to %asi is _expensive_ so we hardcode it. | 29 | /* Writing to %asi is _expensive_ so we hardcode it. |
diff --git a/arch/sparc64/lib/NGmemcpy.S b/arch/sparc64/lib/NGmemcpy.S index 66063a9a66b8..96a14caf6966 100644 --- a/arch/sparc64/lib/NGmemcpy.S +++ b/arch/sparc64/lib/NGmemcpy.S | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* NGmemcpy.S: Niagara optimized memcpy. | 1 | /* NGmemcpy.S: Niagara optimized memcpy. |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2006 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net) |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #ifdef __KERNEL__ | 6 | #ifdef __KERNEL__ |
| @@ -16,6 +16,12 @@ | |||
| 16 | wr %g0, ASI_PNF, %asi | 16 | wr %g0, ASI_PNF, %asi |
| 17 | #endif | 17 | #endif |
| 18 | 18 | ||
| 19 | #ifdef __sparc_v9__ | ||
| 20 | #define SAVE_AMOUNT 128 | ||
| 21 | #else | ||
| 22 | #define SAVE_AMOUNT 64 | ||
| 23 | #endif | ||
| 24 | |||
| 19 | #ifndef STORE_ASI | 25 | #ifndef STORE_ASI |
| 20 | #define STORE_ASI ASI_BLK_INIT_QUAD_LDD_P | 26 | #define STORE_ASI ASI_BLK_INIT_QUAD_LDD_P |
| 21 | #endif | 27 | #endif |
| @@ -50,7 +56,11 @@ | |||
| 50 | #endif | 56 | #endif |
| 51 | 57 | ||
| 52 | #ifndef STORE_INIT | 58 | #ifndef STORE_INIT |
| 59 | #ifndef SIMULATE_NIAGARA_ON_NON_NIAGARA | ||
| 53 | #define STORE_INIT(src,addr) stxa src, [addr] %asi | 60 | #define STORE_INIT(src,addr) stxa src, [addr] %asi |
| 61 | #else | ||
| 62 | #define STORE_INIT(src,addr) stx src, [addr + 0x00] | ||
| 63 | #endif | ||
| 54 | #endif | 64 | #endif |
| 55 | 65 | ||
| 56 | #ifndef FUNC_NAME | 66 | #ifndef FUNC_NAME |
| @@ -73,18 +83,19 @@ | |||
| 73 | 83 | ||
| 74 | .globl FUNC_NAME | 84 | .globl FUNC_NAME |
| 75 | .type FUNC_NAME,#function | 85 | .type FUNC_NAME,#function |
| 76 | FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ | 86 | FUNC_NAME: /* %i0=dst, %i1=src, %i2=len */ |
| 77 | srlx %o2, 31, %g2 | 87 | PREAMBLE |
| 88 | save %sp, -SAVE_AMOUNT, %sp | ||
| 89 | srlx %i2, 31, %g2 | ||
| 78 | cmp %g2, 0 | 90 | cmp %g2, 0 |
| 79 | tne %xcc, 5 | 91 | tne %xcc, 5 |
| 80 | PREAMBLE | 92 | mov %i0, %o0 |
| 81 | mov %o0, GLOBAL_SPARE | 93 | cmp %i2, 0 |
| 82 | cmp %o2, 0 | ||
| 83 | be,pn %XCC, 85f | 94 | be,pn %XCC, 85f |
| 84 | or %o0, %o1, %o3 | 95 | or %o0, %i1, %i3 |
| 85 | cmp %o2, 16 | 96 | cmp %i2, 16 |
| 86 | blu,a,pn %XCC, 80f | 97 | blu,a,pn %XCC, 80f |
| 87 | or %o3, %o2, %o3 | 98 | or %i3, %i2, %i3 |
| 88 | 99 | ||
| 89 | /* 2 blocks (128 bytes) is the minimum we can do the block | 100 | /* 2 blocks (128 bytes) is the minimum we can do the block |
| 90 | * copy with. We need to ensure that we'll iterate at least | 101 | * copy with. We need to ensure that we'll iterate at least |
| @@ -93,31 +104,31 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ | |||
| 93 | * to (64 - 1) bytes from the length before we perform the | 104 | * to (64 - 1) bytes from the length before we perform the |
| 94 | * block copy loop. | 105 | * block copy loop. |
| 95 | */ | 106 | */ |
| 96 | cmp %o2, (2 * 64) | 107 | cmp %i2, (2 * 64) |
| 97 | blu,pt %XCC, 70f | 108 | blu,pt %XCC, 70f |
| 98 | andcc %o3, 0x7, %g0 | 109 | andcc %i3, 0x7, %g0 |
| 99 | 110 | ||
| 100 | /* %o0: dst | 111 | /* %o0: dst |
| 101 | * %o1: src | 112 | * %i1: src |
| 102 | * %o2: len (known to be >= 128) | 113 | * %i2: len (known to be >= 128) |
| 103 | * | 114 | * |
| 104 | * The block copy loops will use %o4/%o5,%g2/%g3 as | 115 | * The block copy loops will use %i4/%i5,%g2/%g3 as |
| 105 | * temporaries while copying the data. | 116 | * temporaries while copying the data. |
| 106 | */ | 117 | */ |
| 107 | 118 | ||
| 108 | LOAD(prefetch, %o1, #one_read) | 119 | LOAD(prefetch, %i1, #one_read) |
| 109 | wr %g0, STORE_ASI, %asi | 120 | wr %g0, STORE_ASI, %asi |
| 110 | 121 | ||
| 111 | /* Align destination on 64-byte boundary. */ | 122 | /* Align destination on 64-byte boundary. */ |
| 112 | andcc %o0, (64 - 1), %o4 | 123 | andcc %o0, (64 - 1), %i4 |
| 113 | be,pt %XCC, 2f | 124 | be,pt %XCC, 2f |
| 114 | sub %o4, 64, %o4 | 125 | sub %i4, 64, %i4 |
| 115 | sub %g0, %o4, %o4 ! bytes to align dst | 126 | sub %g0, %i4, %i4 ! bytes to align dst |
| 116 | sub %o2, %o4, %o2 | 127 | sub %i2, %i4, %i2 |
| 117 | 1: subcc %o4, 1, %o4 | 128 | 1: subcc %i4, 1, %i4 |
| 118 | EX_LD(LOAD(ldub, %o1, %g1)) | 129 | EX_LD(LOAD(ldub, %i1, %g1)) |
| 119 | EX_ST(STORE(stb, %g1, %o0)) | 130 | EX_ST(STORE(stb, %g1, %o0)) |
| 120 | add %o1, 1, %o1 | 131 | add %i1, 1, %i1 |
| 121 | bne,pt %XCC, 1b | 132 | bne,pt %XCC, 1b |
| 122 | add %o0, 1, %o0 | 133 | add %o0, 1, %o0 |
| 123 | 134 | ||
| @@ -136,111 +147,155 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ | |||
| 136 | * aligned store data at a time, this is easy to ensure. | 147 | * aligned store data at a time, this is easy to ensure. |
| 137 | */ | 148 | */ |
| 138 | 2: | 149 | 2: |
| 139 | andcc %o1, (16 - 1), %o4 | 150 | andcc %i1, (16 - 1), %i4 |
| 140 | andn %o2, (64 - 1), %g1 ! block copy loop iterator | 151 | andn %i2, (64 - 1), %g1 ! block copy loop iterator |
| 141 | sub %o2, %g1, %o2 ! final sub-block copy bytes | ||
| 142 | be,pt %XCC, 50f | 152 | be,pt %XCC, 50f |
| 143 | cmp %o4, 8 | 153 | sub %i2, %g1, %i2 ! final sub-block copy bytes |
| 144 | be,a,pt %XCC, 10f | 154 | |
| 145 | sub %o1, 0x8, %o1 | 155 | cmp %i4, 8 |
| 156 | be,pt %XCC, 10f | ||
| 157 | sub %i1, %i4, %i1 | ||
| 146 | 158 | ||
| 147 | /* Neither 8-byte nor 16-byte aligned, shift and mask. */ | 159 | /* Neither 8-byte nor 16-byte aligned, shift and mask. */ |
| 148 | mov %g1, %o4 | 160 | and %i4, 0x7, GLOBAL_SPARE |
| 149 | and %o1, 0x7, %g1 | 161 | sll GLOBAL_SPARE, 3, GLOBAL_SPARE |
| 150 | sll %g1, 3, %g1 | 162 | mov 64, %i5 |
| 151 | mov 64, %o3 | 163 | EX_LD(LOAD_TWIN(%i1, %g2, %g3)) |
| 152 | andn %o1, 0x7, %o1 | 164 | sub %i5, GLOBAL_SPARE, %i5 |
| 153 | EX_LD(LOAD(ldx, %o1, %g2)) | 165 | mov 16, %o4 |
| 154 | sub %o3, %g1, %o3 | 166 | mov 32, %o5 |
| 155 | sllx %g2, %g1, %g2 | 167 | mov 48, %o7 |
| 168 | mov 64, %i3 | ||
| 169 | |||
| 170 | bg,pn %XCC, 9f | ||
| 171 | nop | ||
| 156 | 172 | ||
| 157 | #define SWIVEL_ONE_DWORD(SRC, TMP1, TMP2, PRE_VAL, PRE_SHIFT, POST_SHIFT, DST)\ | 173 | #define MIX_THREE_WORDS(WORD1, WORD2, WORD3, PRE_SHIFT, POST_SHIFT, TMP) \ |
| 158 | EX_LD(LOAD(ldx, SRC, TMP1)); \ | 174 | sllx WORD1, POST_SHIFT, WORD1; \ |
| 159 | srlx TMP1, PRE_SHIFT, TMP2; \ | 175 | srlx WORD2, PRE_SHIFT, TMP; \ |
| 160 | or TMP2, PRE_VAL, TMP2; \ | 176 | sllx WORD2, POST_SHIFT, WORD2; \ |
| 161 | EX_ST(STORE_INIT(TMP2, DST)); \ | 177 | or WORD1, TMP, WORD1; \ |
| 162 | sllx TMP1, POST_SHIFT, PRE_VAL; | 178 | srlx WORD3, PRE_SHIFT, TMP; \ |
| 163 | 179 | or WORD2, TMP, WORD2; | |
| 164 | 1: add %o1, 0x8, %o1 | 180 | |
| 165 | SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x00) | 181 | 8: EX_LD(LOAD_TWIN(%i1 + %o4, %o2, %o3)) |
| 166 | add %o1, 0x8, %o1 | 182 | MIX_THREE_WORDS(%g2, %g3, %o2, %i5, GLOBAL_SPARE, %o1) |
| 167 | SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x08) | 183 | LOAD(prefetch, %i1 + %i3, #one_read) |
| 168 | add %o1, 0x8, %o1 | 184 | |
| 169 | SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x10) | 185 | EX_ST(STORE_INIT(%g2, %o0 + 0x00)) |
| 170 | add %o1, 0x8, %o1 | 186 | EX_ST(STORE_INIT(%g3, %o0 + 0x08)) |
| 171 | SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x18) | 187 | |
| 172 | add %o1, 32, %o1 | 188 | EX_LD(LOAD_TWIN(%i1 + %o5, %g2, %g3)) |
| 173 | LOAD(prefetch, %o1, #one_read) | 189 | MIX_THREE_WORDS(%o2, %o3, %g2, %i5, GLOBAL_SPARE, %o1) |
| 174 | sub %o1, 32 - 8, %o1 | 190 | |
| 175 | SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x20) | 191 | EX_ST(STORE_INIT(%o2, %o0 + 0x10)) |
| 176 | add %o1, 8, %o1 | 192 | EX_ST(STORE_INIT(%o3, %o0 + 0x18)) |
| 177 | SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x28) | 193 | |
| 178 | add %o1, 8, %o1 | 194 | EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3)) |
| 179 | SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x30) | 195 | MIX_THREE_WORDS(%g2, %g3, %o2, %i5, GLOBAL_SPARE, %o1) |
| 180 | add %o1, 8, %o1 | 196 | |
| 181 | SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x38) | 197 | EX_ST(STORE_INIT(%g2, %o0 + 0x20)) |
| 182 | subcc %o4, 64, %o4 | 198 | EX_ST(STORE_INIT(%g3, %o0 + 0x28)) |
| 183 | bne,pt %XCC, 1b | 199 | |
| 200 | EX_LD(LOAD_TWIN(%i1 + %i3, %g2, %g3)) | ||
| 201 | add %i1, 64, %i1 | ||
| 202 | MIX_THREE_WORDS(%o2, %o3, %g2, %i5, GLOBAL_SPARE, %o1) | ||
| 203 | |||
| 204 | EX_ST(STORE_INIT(%o2, %o0 + 0x30)) | ||
| 205 | EX_ST(STORE_INIT(%o3, %o0 + 0x38)) | ||
| 206 | |||
| 207 | subcc %g1, 64, %g1 | ||
| 208 | bne,pt %XCC, 8b | ||
| 184 | add %o0, 64, %o0 | 209 | add %o0, 64, %o0 |
| 185 | 210 | ||
| 186 | #undef SWIVEL_ONE_DWORD | 211 | ba,pt %XCC, 60f |
| 212 | add %i1, %i4, %i1 | ||
| 213 | |||
| 214 | 9: EX_LD(LOAD_TWIN(%i1 + %o4, %o2, %o3)) | ||
| 215 | MIX_THREE_WORDS(%g3, %o2, %o3, %i5, GLOBAL_SPARE, %o1) | ||
| 216 | LOAD(prefetch, %i1 + %i3, #one_read) | ||
| 217 | |||
| 218 | EX_ST(STORE_INIT(%g3, %o0 + 0x00)) | ||
| 219 | EX_ST(STORE_INIT(%o2, %o0 + 0x08)) | ||
| 220 | |||
| 221 | EX_LD(LOAD_TWIN(%i1 + %o5, %g2, %g3)) | ||
| 222 | MIX_THREE_WORDS(%o3, %g2, %g3, %i5, GLOBAL_SPARE, %o1) | ||
| 223 | |||
| 224 | EX_ST(STORE_INIT(%o3, %o0 + 0x10)) | ||
| 225 | EX_ST(STORE_INIT(%g2, %o0 + 0x18)) | ||
| 226 | |||
| 227 | EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3)) | ||
| 228 | MIX_THREE_WORDS(%g3, %o2, %o3, %i5, GLOBAL_SPARE, %o1) | ||
| 229 | |||
| 230 | EX_ST(STORE_INIT(%g3, %o0 + 0x20)) | ||
| 231 | EX_ST(STORE_INIT(%o2, %o0 + 0x28)) | ||
| 232 | |||
| 233 | EX_LD(LOAD_TWIN(%i1 + %i3, %g2, %g3)) | ||
| 234 | add %i1, 64, %i1 | ||
| 235 | MIX_THREE_WORDS(%o3, %g2, %g3, %i5, GLOBAL_SPARE, %o1) | ||
| 236 | |||
| 237 | EX_ST(STORE_INIT(%o3, %o0 + 0x30)) | ||
| 238 | EX_ST(STORE_INIT(%g2, %o0 + 0x38)) | ||
| 239 | |||
| 240 | subcc %g1, 64, %g1 | ||
| 241 | bne,pt %XCC, 9b | ||
| 242 | add %o0, 64, %o0 | ||
| 187 | 243 | ||
| 188 | srl %g1, 3, %g1 | ||
| 189 | ba,pt %XCC, 60f | 244 | ba,pt %XCC, 60f |
| 190 | add %o1, %g1, %o1 | 245 | add %i1, %i4, %i1 |
| 191 | 246 | ||
| 192 | 10: /* Destination is 64-byte aligned, source was only 8-byte | 247 | 10: /* Destination is 64-byte aligned, source was only 8-byte |
| 193 | * aligned but it has been subtracted by 8 and we perform | 248 | * aligned but it has been subtracted by 8 and we perform |
| 194 | * one twin load ahead, then add 8 back into source when | 249 | * one twin load ahead, then add 8 back into source when |
| 195 | * we finish the loop. | 250 | * we finish the loop. |
| 196 | */ | 251 | */ |
| 197 | EX_LD(LOAD_TWIN(%o1, %o4, %o5)) | 252 | EX_LD(LOAD_TWIN(%i1, %o4, %o5)) |
| 198 | 1: add %o1, 16, %o1 | 253 | mov 16, %o7 |
| 199 | EX_LD(LOAD_TWIN(%o1, %g2, %g3)) | 254 | mov 32, %g2 |
| 200 | add %o1, 16 + 32, %o1 | 255 | mov 48, %g3 |
| 201 | LOAD(prefetch, %o1, #one_read) | 256 | mov 64, %o1 |
| 202 | sub %o1, 32, %o1 | 257 | 1: EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3)) |
| 258 | LOAD(prefetch, %i1 + %o1, #one_read) | ||
| 203 | EX_ST(STORE_INIT(%o5, %o0 + 0x00)) ! initializes cache line | 259 | EX_ST(STORE_INIT(%o5, %o0 + 0x00)) ! initializes cache line |
| 204 | EX_ST(STORE_INIT(%g2, %o0 + 0x08)) | 260 | EX_ST(STORE_INIT(%o2, %o0 + 0x08)) |
| 205 | EX_LD(LOAD_TWIN(%o1, %o4, %o5)) | 261 | EX_LD(LOAD_TWIN(%i1 + %g2, %o4, %o5)) |
| 206 | add %o1, 16, %o1 | 262 | EX_ST(STORE_INIT(%o3, %o0 + 0x10)) |
| 207 | EX_ST(STORE_INIT(%g3, %o0 + 0x10)) | ||
| 208 | EX_ST(STORE_INIT(%o4, %o0 + 0x18)) | 263 | EX_ST(STORE_INIT(%o4, %o0 + 0x18)) |
| 209 | EX_LD(LOAD_TWIN(%o1, %g2, %g3)) | 264 | EX_LD(LOAD_TWIN(%i1 + %g3, %o2, %o3)) |
| 210 | add %o1, 16, %o1 | ||
| 211 | EX_ST(STORE_INIT(%o5, %o0 + 0x20)) | 265 | EX_ST(STORE_INIT(%o5, %o0 + 0x20)) |
| 212 | EX_ST(STORE_INIT(%g2, %o0 + 0x28)) | 266 | EX_ST(STORE_INIT(%o2, %o0 + 0x28)) |
| 213 | EX_LD(LOAD_TWIN(%o1, %o4, %o5)) | 267 | EX_LD(LOAD_TWIN(%i1 + %o1, %o4, %o5)) |
| 214 | EX_ST(STORE_INIT(%g3, %o0 + 0x30)) | 268 | add %i1, 64, %i1 |
| 269 | EX_ST(STORE_INIT(%o3, %o0 + 0x30)) | ||
| 215 | EX_ST(STORE_INIT(%o4, %o0 + 0x38)) | 270 | EX_ST(STORE_INIT(%o4, %o0 + 0x38)) |
| 216 | subcc %g1, 64, %g1 | 271 | subcc %g1, 64, %g1 |
| 217 | bne,pt %XCC, 1b | 272 | bne,pt %XCC, 1b |
| 218 | add %o0, 64, %o0 | 273 | add %o0, 64, %o0 |
| 219 | 274 | ||
| 220 | ba,pt %XCC, 60f | 275 | ba,pt %XCC, 60f |
| 221 | add %o1, 0x8, %o1 | 276 | add %i1, 0x8, %i1 |
| 222 | 277 | ||
| 223 | 50: /* Destination is 64-byte aligned, and source is 16-byte | 278 | 50: /* Destination is 64-byte aligned, and source is 16-byte |
| 224 | * aligned. | 279 | * aligned. |
| 225 | */ | 280 | */ |
| 226 | 1: EX_LD(LOAD_TWIN(%o1, %o4, %o5)) | 281 | mov 16, %o7 |
| 227 | add %o1, 16, %o1 | 282 | mov 32, %g2 |
| 228 | EX_LD(LOAD_TWIN(%o1, %g2, %g3)) | 283 | mov 48, %g3 |
| 229 | add %o1, 16 + 32, %o1 | 284 | mov 64, %o1 |
| 230 | LOAD(prefetch, %o1, #one_read) | 285 | 1: EX_LD(LOAD_TWIN(%i1 + %g0, %o4, %o5)) |
| 231 | sub %o1, 32, %o1 | 286 | EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3)) |
| 287 | LOAD(prefetch, %i1 + %o1, #one_read) | ||
| 232 | EX_ST(STORE_INIT(%o4, %o0 + 0x00)) ! initializes cache line | 288 | EX_ST(STORE_INIT(%o4, %o0 + 0x00)) ! initializes cache line |
| 233 | EX_ST(STORE_INIT(%o5, %o0 + 0x08)) | 289 | EX_ST(STORE_INIT(%o5, %o0 + 0x08)) |
| 234 | EX_LD(LOAD_TWIN(%o1, %o4, %o5)) | 290 | EX_LD(LOAD_TWIN(%i1 + %g2, %o4, %o5)) |
| 235 | add %o1, 16, %o1 | 291 | EX_ST(STORE_INIT(%o2, %o0 + 0x10)) |
| 236 | EX_ST(STORE_INIT(%g2, %o0 + 0x10)) | 292 | EX_ST(STORE_INIT(%o3, %o0 + 0x18)) |
| 237 | EX_ST(STORE_INIT(%g3, %o0 + 0x18)) | 293 | EX_LD(LOAD_TWIN(%i1 + %g3, %o2, %o3)) |
| 238 | EX_LD(LOAD_TWIN(%o1, %g2, %g3)) | 294 | add %i1, 64, %i1 |
| 239 | add %o1, 16, %o1 | ||
| 240 | EX_ST(STORE_INIT(%o4, %o0 + 0x20)) | 295 | EX_ST(STORE_INIT(%o4, %o0 + 0x20)) |
| 241 | EX_ST(STORE_INIT(%o5, %o0 + 0x28)) | 296 | EX_ST(STORE_INIT(%o5, %o0 + 0x28)) |
| 242 | EX_ST(STORE_INIT(%g2, %o0 + 0x30)) | 297 | EX_ST(STORE_INIT(%o2, %o0 + 0x30)) |
| 243 | EX_ST(STORE_INIT(%g3, %o0 + 0x38)) | 298 | EX_ST(STORE_INIT(%o3, %o0 + 0x38)) |
| 244 | subcc %g1, 64, %g1 | 299 | subcc %g1, 64, %g1 |
| 245 | bne,pt %XCC, 1b | 300 | bne,pt %XCC, 1b |
| 246 | add %o0, 64, %o0 | 301 | add %o0, 64, %o0 |
| @@ -249,47 +304,47 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ | |||
| 249 | 60: | 304 | 60: |
| 250 | membar #Sync | 305 | membar #Sync |
| 251 | 306 | ||
| 252 | /* %o2 contains any final bytes still needed to be copied | 307 | /* %i2 contains any final bytes still needed to be copied |
| 253 | * over. If anything is left, we copy it one byte at a time. | 308 | * over. If anything is left, we copy it one byte at a time. |
| 254 | */ | 309 | */ |
| 255 | RESTORE_ASI(%o3) | 310 | RESTORE_ASI(%i3) |
| 256 | brz,pt %o2, 85f | 311 | brz,pt %i2, 85f |
| 257 | sub %o0, %o1, %o3 | 312 | sub %o0, %i1, %i3 |
| 258 | ba,a,pt %XCC, 90f | 313 | ba,a,pt %XCC, 90f |
| 259 | 314 | ||
| 260 | .align 64 | 315 | .align 64 |
| 261 | 70: /* 16 < len <= 64 */ | 316 | 70: /* 16 < len <= 64 */ |
| 262 | bne,pn %XCC, 75f | 317 | bne,pn %XCC, 75f |
| 263 | sub %o0, %o1, %o3 | 318 | sub %o0, %i1, %i3 |
| 264 | 319 | ||
| 265 | 72: | 320 | 72: |
| 266 | andn %o2, 0xf, %o4 | 321 | andn %i2, 0xf, %i4 |
| 267 | and %o2, 0xf, %o2 | 322 | and %i2, 0xf, %i2 |
| 268 | 1: subcc %o4, 0x10, %o4 | 323 | 1: subcc %i4, 0x10, %i4 |
| 269 | EX_LD(LOAD(ldx, %o1, %o5)) | 324 | EX_LD(LOAD(ldx, %i1, %o4)) |
| 270 | add %o1, 0x08, %o1 | 325 | add %i1, 0x08, %i1 |
| 271 | EX_LD(LOAD(ldx, %o1, %g1)) | 326 | EX_LD(LOAD(ldx, %i1, %g1)) |
| 272 | sub %o1, 0x08, %o1 | 327 | sub %i1, 0x08, %i1 |
| 273 | EX_ST(STORE(stx, %o5, %o1 + %o3)) | 328 | EX_ST(STORE(stx, %o4, %i1 + %i3)) |
| 274 | add %o1, 0x8, %o1 | 329 | add %i1, 0x8, %i1 |
| 275 | EX_ST(STORE(stx, %g1, %o1 + %o3)) | 330 | EX_ST(STORE(stx, %g1, %i1 + %i3)) |
| 276 | bgu,pt %XCC, 1b | 331 | bgu,pt %XCC, 1b |
| 277 | add %o1, 0x8, %o1 | 332 | add %i1, 0x8, %i1 |
| 278 | 73: andcc %o2, 0x8, %g0 | 333 | 73: andcc %i2, 0x8, %g0 |
| 279 | be,pt %XCC, 1f | 334 | be,pt %XCC, 1f |
| 280 | nop | 335 | nop |
| 281 | sub %o2, 0x8, %o2 | 336 | sub %i2, 0x8, %i2 |
| 282 | EX_LD(LOAD(ldx, %o1, %o5)) | 337 | EX_LD(LOAD(ldx, %i1, %o4)) |
| 283 | EX_ST(STORE(stx, %o5, %o1 + %o3)) | 338 | EX_ST(STORE(stx, %o4, %i1 + %i3)) |
| 284 | add %o1, 0x8, %o1 | 339 | add %i1, 0x8, %i1 |
| 285 | 1: andcc %o2, 0x4, %g0 | 340 | 1: andcc %i2, 0x4, %g0 |
| 286 | be,pt %XCC, 1f | 341 | be,pt %XCC, 1f |
| 287 | nop | 342 | nop |
| 288 | sub %o2, 0x4, %o2 | 343 | sub %i2, 0x4, %i2 |
| 289 | EX_LD(LOAD(lduw, %o1, %o5)) | 344 | EX_LD(LOAD(lduw, %i1, %i5)) |
| 290 | EX_ST(STORE(stw, %o5, %o1 + %o3)) | 345 | EX_ST(STORE(stw, %i5, %i1 + %i3)) |
| 291 | add %o1, 0x4, %o1 | 346 | add %i1, 0x4, %i1 |
| 292 | 1: cmp %o2, 0 | 347 | 1: cmp %i2, 0 |
| 293 | be,pt %XCC, 85f | 348 | be,pt %XCC, 85f |
| 294 | nop | 349 | nop |
| 295 | ba,pt %xcc, 90f | 350 | ba,pt %xcc, 90f |
| @@ -300,71 +355,71 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ | |||
| 300 | sub %g1, 0x8, %g1 | 355 | sub %g1, 0x8, %g1 |
| 301 | be,pn %icc, 2f | 356 | be,pn %icc, 2f |
| 302 | sub %g0, %g1, %g1 | 357 | sub %g0, %g1, %g1 |
| 303 | sub %o2, %g1, %o2 | 358 | sub %i2, %g1, %i2 |
| 304 | 359 | ||
| 305 | 1: subcc %g1, 1, %g1 | 360 | 1: subcc %g1, 1, %g1 |
| 306 | EX_LD(LOAD(ldub, %o1, %o5)) | 361 | EX_LD(LOAD(ldub, %i1, %i5)) |
| 307 | EX_ST(STORE(stb, %o5, %o1 + %o3)) | 362 | EX_ST(STORE(stb, %i5, %i1 + %i3)) |
| 308 | bgu,pt %icc, 1b | 363 | bgu,pt %icc, 1b |
| 309 | add %o1, 1, %o1 | 364 | add %i1, 1, %i1 |
| 310 | 365 | ||
| 311 | 2: add %o1, %o3, %o0 | 366 | 2: add %i1, %i3, %o0 |
| 312 | andcc %o1, 0x7, %g1 | 367 | andcc %i1, 0x7, %g1 |
| 313 | bne,pt %icc, 8f | 368 | bne,pt %icc, 8f |
| 314 | sll %g1, 3, %g1 | 369 | sll %g1, 3, %g1 |
| 315 | 370 | ||
| 316 | cmp %o2, 16 | 371 | cmp %i2, 16 |
| 317 | bgeu,pt %icc, 72b | 372 | bgeu,pt %icc, 72b |
| 318 | nop | 373 | nop |
| 319 | ba,a,pt %xcc, 73b | 374 | ba,a,pt %xcc, 73b |
| 320 | 375 | ||
| 321 | 8: mov 64, %o3 | 376 | 8: mov 64, %i3 |
| 322 | andn %o1, 0x7, %o1 | 377 | andn %i1, 0x7, %i1 |
| 323 | EX_LD(LOAD(ldx, %o1, %g2)) | 378 | EX_LD(LOAD(ldx, %i1, %g2)) |
| 324 | sub %o3, %g1, %o3 | 379 | sub %i3, %g1, %i3 |
| 325 | andn %o2, 0x7, %o4 | 380 | andn %i2, 0x7, %i4 |
| 326 | sllx %g2, %g1, %g2 | 381 | sllx %g2, %g1, %g2 |
| 327 | 1: add %o1, 0x8, %o1 | 382 | 1: add %i1, 0x8, %i1 |
| 328 | EX_LD(LOAD(ldx, %o1, %g3)) | 383 | EX_LD(LOAD(ldx, %i1, %g3)) |
| 329 | subcc %o4, 0x8, %o4 | 384 | subcc %i4, 0x8, %i4 |
| 330 | srlx %g3, %o3, %o5 | 385 | srlx %g3, %i3, %i5 |
| 331 | or %o5, %g2, %o5 | 386 | or %i5, %g2, %i5 |
| 332 | EX_ST(STORE(stx, %o5, %o0)) | 387 | EX_ST(STORE(stx, %i5, %o0)) |
| 333 | add %o0, 0x8, %o0 | 388 | add %o0, 0x8, %o0 |
| 334 | bgu,pt %icc, 1b | 389 | bgu,pt %icc, 1b |
| 335 | sllx %g3, %g1, %g2 | 390 | sllx %g3, %g1, %g2 |
| 336 | 391 | ||
| 337 | srl %g1, 3, %g1 | 392 | srl %g1, 3, %g1 |
| 338 | andcc %o2, 0x7, %o2 | 393 | andcc %i2, 0x7, %i2 |
| 339 | be,pn %icc, 85f | 394 | be,pn %icc, 85f |
| 340 | add %o1, %g1, %o1 | 395 | add %i1, %g1, %i1 |
| 341 | ba,pt %xcc, 90f | 396 | ba,pt %xcc, 90f |
| 342 | sub %o0, %o1, %o3 | 397 | sub %o0, %i1, %i3 |
| 343 | 398 | ||
| 344 | .align 64 | 399 | .align 64 |
| 345 | 80: /* 0 < len <= 16 */ | 400 | 80: /* 0 < len <= 16 */ |
| 346 | andcc %o3, 0x3, %g0 | 401 | andcc %i3, 0x3, %g0 |
| 347 | bne,pn %XCC, 90f | 402 | bne,pn %XCC, 90f |
| 348 | sub %o0, %o1, %o3 | 403 | sub %o0, %i1, %i3 |
| 349 | 404 | ||
| 350 | 1: | 405 | 1: |
| 351 | subcc %o2, 4, %o2 | 406 | subcc %i2, 4, %i2 |
| 352 | EX_LD(LOAD(lduw, %o1, %g1)) | 407 | EX_LD(LOAD(lduw, %i1, %g1)) |
| 353 | EX_ST(STORE(stw, %g1, %o1 + %o3)) | 408 | EX_ST(STORE(stw, %g1, %i1 + %i3)) |
| 354 | bgu,pt %XCC, 1b | 409 | bgu,pt %XCC, 1b |
| 355 | add %o1, 4, %o1 | 410 | add %i1, 4, %i1 |
| 356 | 411 | ||
| 357 | 85: retl | 412 | 85: ret |
| 358 | mov EX_RETVAL(GLOBAL_SPARE), %o0 | 413 | restore EX_RETVAL(%i0), %g0, %o0 |
| 359 | 414 | ||
| 360 | .align 32 | 415 | .align 32 |
| 361 | 90: | 416 | 90: |
| 362 | subcc %o2, 1, %o2 | 417 | subcc %i2, 1, %i2 |
| 363 | EX_LD(LOAD(ldub, %o1, %g1)) | 418 | EX_LD(LOAD(ldub, %i1, %g1)) |
| 364 | EX_ST(STORE(stb, %g1, %o1 + %o3)) | 419 | EX_ST(STORE(stb, %g1, %i1 + %i3)) |
| 365 | bgu,pt %XCC, 90b | 420 | bgu,pt %XCC, 90b |
| 366 | add %o1, 1, %o1 | 421 | add %i1, 1, %i1 |
| 367 | retl | 422 | ret |
| 368 | mov EX_RETVAL(GLOBAL_SPARE), %o0 | 423 | restore EX_RETVAL(%i0), %g0, %o0 |
| 369 | 424 | ||
| 370 | .size FUNC_NAME, .-FUNC_NAME | 425 | .size FUNC_NAME, .-FUNC_NAME |
diff --git a/arch/x86_64/vdso/voffset.h b/arch/x86_64/vdso/voffset.h index 5304204911f2..4af67c79085f 100644 --- a/arch/x86_64/vdso/voffset.h +++ b/arch/x86_64/vdso/voffset.h | |||
| @@ -1 +1 @@ | |||
| #define VDSO_TEXT_OFFSET 0x500 | #define VDSO_TEXT_OFFSET 0x600 | ||
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 4875f0149eb4..b83389145f28 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
| @@ -88,7 +88,7 @@ config ACPI_PROC_EVENT | |||
| 88 | 88 | ||
| 89 | config ACPI_AC | 89 | config ACPI_AC |
| 90 | tristate "AC Adapter" | 90 | tristate "AC Adapter" |
| 91 | depends on X86 | 91 | depends on X86 && POWER_SUPPLY |
| 92 | default y | 92 | default y |
| 93 | help | 93 | help |
| 94 | This driver adds support for the AC Adapter object, which indicates | 94 | This driver adds support for the AC Adapter object, which indicates |
| @@ -97,7 +97,7 @@ config ACPI_AC | |||
| 97 | 97 | ||
| 98 | config ACPI_BATTERY | 98 | config ACPI_BATTERY |
| 99 | tristate "Battery" | 99 | tristate "Battery" |
| 100 | depends on X86 | 100 | depends on X86 && POWER_SUPPLY |
| 101 | default y | 101 | default y |
| 102 | help | 102 | help |
| 103 | This driver adds support for battery information through | 103 | This driver adds support for battery information through |
| @@ -117,6 +117,7 @@ config ACPI_BUTTON | |||
| 117 | config ACPI_VIDEO | 117 | config ACPI_VIDEO |
| 118 | tristate "Video" | 118 | tristate "Video" |
| 119 | depends on X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL | 119 | depends on X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL |
| 120 | depends on INPUT | ||
| 120 | help | 121 | help |
| 121 | This driver implement the ACPI Extensions For Display Adapters | 122 | This driver implement the ACPI Extensions For Display Adapters |
| 122 | for integrated graphics devices on motherboard, as specified in | 123 | for integrated graphics devices on motherboard, as specified in |
| @@ -349,12 +350,11 @@ config ACPI_HOTPLUG_MEMORY | |||
| 349 | $>modprobe acpi_memhotplug | 350 | $>modprobe acpi_memhotplug |
| 350 | 351 | ||
| 351 | config ACPI_SBS | 352 | config ACPI_SBS |
| 352 | tristate "Smart Battery System (EXPERIMENTAL)" | 353 | tristate "Smart Battery System" |
| 353 | depends on X86 | 354 | depends on X86 |
| 354 | depends on EXPERIMENTAL | 355 | depends on POWER_SUPPLY |
| 355 | help | 356 | help |
| 356 | This driver adds support for the Smart Battery System. | 357 | This driver adds support for the Smart Battery System, another |
| 357 | A "Smart Battery" is quite old and quite rare compared | 358 | type of access to battery information, found on some laptops. |
| 358 | to today's ACPI "Control Method" battery. | ||
| 359 | 359 | ||
| 360 | endif # ACPI | 360 | endif # ACPI |
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index d4336f1730e9..54e3ab0e5fc0 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile | |||
| @@ -60,3 +60,4 @@ obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o | |||
| 60 | obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o | 60 | obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o |
| 61 | obj-y += cm_sbs.o | 61 | obj-y += cm_sbs.o |
| 62 | obj-$(CONFIG_ACPI_SBS) += sbs.o | 62 | obj-$(CONFIG_ACPI_SBS) += sbs.o |
| 63 | obj-$(CONFIG_ACPI_SBS) += sbshc.o | ||
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 26d70702b313..e03de37a750d 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/types.h> | 29 | #include <linux/types.h> |
| 30 | #include <linux/proc_fs.h> | 30 | #include <linux/proc_fs.h> |
| 31 | #include <linux/seq_file.h> | 31 | #include <linux/seq_file.h> |
| 32 | #include <linux/power_supply.h> | ||
| 32 | #include <acpi/acpi_bus.h> | 33 | #include <acpi/acpi_bus.h> |
| 33 | #include <acpi/acpi_drivers.h> | 34 | #include <acpi/acpi_drivers.h> |
| 34 | 35 | ||
| @@ -72,16 +73,37 @@ static struct acpi_driver acpi_ac_driver = { | |||
| 72 | }; | 73 | }; |
| 73 | 74 | ||
| 74 | struct acpi_ac { | 75 | struct acpi_ac { |
| 76 | struct power_supply charger; | ||
| 75 | struct acpi_device * device; | 77 | struct acpi_device * device; |
| 76 | unsigned long state; | 78 | unsigned long state; |
| 77 | }; | 79 | }; |
| 78 | 80 | ||
| 81 | #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger); | ||
| 82 | |||
| 79 | static const struct file_operations acpi_ac_fops = { | 83 | static const struct file_operations acpi_ac_fops = { |
| 80 | .open = acpi_ac_open_fs, | 84 | .open = acpi_ac_open_fs, |
| 81 | .read = seq_read, | 85 | .read = seq_read, |
| 82 | .llseek = seq_lseek, | 86 | .llseek = seq_lseek, |
| 83 | .release = single_release, | 87 | .release = single_release, |
| 84 | }; | 88 | }; |
| 89 | static int get_ac_property(struct power_supply *psy, | ||
| 90 | enum power_supply_property psp, | ||
| 91 | union power_supply_propval *val) | ||
| 92 | { | ||
| 93 | struct acpi_ac *ac = to_acpi_ac(psy); | ||
| 94 | switch (psp) { | ||
| 95 | case POWER_SUPPLY_PROP_ONLINE: | ||
| 96 | val->intval = ac->state; | ||
| 97 | break; | ||
| 98 | default: | ||
| 99 | return -EINVAL; | ||
| 100 | } | ||
| 101 | return 0; | ||
| 102 | } | ||
| 103 | |||
| 104 | static enum power_supply_property ac_props[] = { | ||
| 105 | POWER_SUPPLY_PROP_ONLINE, | ||
| 106 | }; | ||
| 85 | 107 | ||
| 86 | /* -------------------------------------------------------------------------- | 108 | /* -------------------------------------------------------------------------- |
| 87 | AC Adapter Management | 109 | AC Adapter Management |
| @@ -208,6 +230,7 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data) | |||
| 208 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 230 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
| 209 | device->dev.bus_id, event, | 231 | device->dev.bus_id, event, |
| 210 | (u32) ac->state); | 232 | (u32) ac->state); |
| 233 | kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); | ||
| 211 | break; | 234 | break; |
| 212 | default: | 235 | default: |
| 213 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 236 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| @@ -244,7 +267,12 @@ static int acpi_ac_add(struct acpi_device *device) | |||
| 244 | result = acpi_ac_add_fs(device); | 267 | result = acpi_ac_add_fs(device); |
| 245 | if (result) | 268 | if (result) |
| 246 | goto end; | 269 | goto end; |
| 247 | 270 | ac->charger.name = acpi_device_bid(device); | |
| 271 | ac->charger.type = POWER_SUPPLY_TYPE_MAINS; | ||
| 272 | ac->charger.properties = ac_props; | ||
| 273 | ac->charger.num_properties = ARRAY_SIZE(ac_props); | ||
| 274 | ac->charger.get_property = get_ac_property; | ||
| 275 | power_supply_register(&ac->device->dev, &ac->charger); | ||
| 248 | status = acpi_install_notify_handler(device->handle, | 276 | status = acpi_install_notify_handler(device->handle, |
| 249 | ACPI_ALL_NOTIFY, acpi_ac_notify, | 277 | ACPI_ALL_NOTIFY, acpi_ac_notify, |
| 250 | ac); | 278 | ac); |
| @@ -279,7 +307,8 @@ static int acpi_ac_remove(struct acpi_device *device, int type) | |||
| 279 | 307 | ||
| 280 | status = acpi_remove_notify_handler(device->handle, | 308 | status = acpi_remove_notify_handler(device->handle, |
| 281 | ACPI_ALL_NOTIFY, acpi_ac_notify); | 309 | ACPI_ALL_NOTIFY, acpi_ac_notify); |
| 282 | 310 | if (ac->charger.dev) | |
| 311 | power_supply_unregister(&ac->charger); | ||
| 283 | acpi_ac_remove_fs(device); | 312 | acpi_ac_remove_fs(device); |
| 284 | 313 | ||
| 285 | kfree(ac); | 314 | kfree(ac); |
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 9b2c0f74f869..681e26b56b11 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * acpi_battery.c - ACPI Battery Driver ($Revision: 37 $) | 2 | * battery.c - ACPI Battery Driver (Revision: 2.0) |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2007 Alexey Starikovskiy <astarikovskiy@suse.de> | ||
| 5 | * Copyright (C) 2004-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com> | ||
| 4 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> | 6 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> |
| 5 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> | 7 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> |
| 6 | * | 8 | * |
| @@ -27,244 +29,288 @@ | |||
| 27 | #include <linux/module.h> | 29 | #include <linux/module.h> |
| 28 | #include <linux/init.h> | 30 | #include <linux/init.h> |
| 29 | #include <linux/types.h> | 31 | #include <linux/types.h> |
| 32 | #include <linux/jiffies.h> | ||
| 33 | |||
| 34 | #ifdef CONFIG_ACPI_PROCFS | ||
| 30 | #include <linux/proc_fs.h> | 35 | #include <linux/proc_fs.h> |
| 31 | #include <linux/seq_file.h> | 36 | #include <linux/seq_file.h> |
| 32 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
| 38 | #endif | ||
| 33 | 39 | ||
| 34 | #include <acpi/acpi_bus.h> | 40 | #include <acpi/acpi_bus.h> |
| 35 | #include <acpi/acpi_drivers.h> | 41 | #include <acpi/acpi_drivers.h> |
| 36 | 42 | ||
| 37 | #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF | 43 | #include <linux/power_supply.h> |
| 38 | 44 | ||
| 39 | #define ACPI_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS" | 45 | #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF |
| 40 | #define ACPI_BATTERY_FORMAT_BST "NNNN" | ||
| 41 | 46 | ||
| 42 | #define ACPI_BATTERY_COMPONENT 0x00040000 | 47 | #define ACPI_BATTERY_COMPONENT 0x00040000 |
| 43 | #define ACPI_BATTERY_CLASS "battery" | 48 | #define ACPI_BATTERY_CLASS "battery" |
| 44 | #define ACPI_BATTERY_DEVICE_NAME "Battery" | 49 | #define ACPI_BATTERY_DEVICE_NAME "Battery" |
| 45 | #define ACPI_BATTERY_NOTIFY_STATUS 0x80 | 50 | #define ACPI_BATTERY_NOTIFY_STATUS 0x80 |
| 46 | #define ACPI_BATTERY_NOTIFY_INFO 0x81 | 51 | #define ACPI_BATTERY_NOTIFY_INFO 0x81 |
| 47 | #define ACPI_BATTERY_UNITS_WATTS "mW" | ||
| 48 | #define ACPI_BATTERY_UNITS_AMPS "mA" | ||
| 49 | 52 | ||
| 50 | #define _COMPONENT ACPI_BATTERY_COMPONENT | 53 | #define _COMPONENT ACPI_BATTERY_COMPONENT |
| 51 | 54 | ||
| 52 | #define ACPI_BATTERY_UPDATE_TIME 0 | ||
| 53 | |||
| 54 | #define ACPI_BATTERY_NONE_UPDATE 0 | ||
| 55 | #define ACPI_BATTERY_EASY_UPDATE 1 | ||
| 56 | #define ACPI_BATTERY_INIT_UPDATE 2 | ||
| 57 | |||
| 58 | ACPI_MODULE_NAME("battery"); | 55 | ACPI_MODULE_NAME("battery"); |
| 59 | 56 | ||
| 60 | MODULE_AUTHOR("Paul Diefenbaugh"); | 57 | MODULE_AUTHOR("Paul Diefenbaugh"); |
| 58 | MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>"); | ||
| 61 | MODULE_DESCRIPTION("ACPI Battery Driver"); | 59 | MODULE_DESCRIPTION("ACPI Battery Driver"); |
| 62 | MODULE_LICENSE("GPL"); | 60 | MODULE_LICENSE("GPL"); |
| 63 | 61 | ||
| 64 | static unsigned int update_time = ACPI_BATTERY_UPDATE_TIME; | 62 | static unsigned int cache_time = 1000; |
| 65 | 63 | module_param(cache_time, uint, 0644); | |
| 66 | /* 0 - every time, > 0 - by update_time */ | 64 | MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); |
| 67 | module_param(update_time, uint, 0644); | ||
| 68 | 65 | ||
| 66 | #ifdef CONFIG_ACPI_PROCFS | ||
| 69 | extern struct proc_dir_entry *acpi_lock_battery_dir(void); | 67 | extern struct proc_dir_entry *acpi_lock_battery_dir(void); |
| 70 | extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); | 68 | extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); |
| 71 | 69 | ||
| 72 | static int acpi_battery_add(struct acpi_device *device); | 70 | enum acpi_battery_files { |
| 73 | static int acpi_battery_remove(struct acpi_device *device, int type); | 71 | info_tag = 0, |
| 74 | static int acpi_battery_resume(struct acpi_device *device); | 72 | state_tag, |
| 73 | alarm_tag, | ||
| 74 | ACPI_BATTERY_NUMFILES, | ||
| 75 | }; | ||
| 76 | |||
| 77 | #endif | ||
| 75 | 78 | ||
| 76 | static const struct acpi_device_id battery_device_ids[] = { | 79 | static const struct acpi_device_id battery_device_ids[] = { |
| 77 | {"PNP0C0A", 0}, | 80 | {"PNP0C0A", 0}, |
| 78 | {"", 0}, | 81 | {"", 0}, |
| 79 | }; | 82 | }; |
| 80 | MODULE_DEVICE_TABLE(acpi, battery_device_ids); | ||
| 81 | |||
| 82 | static struct acpi_driver acpi_battery_driver = { | ||
| 83 | .name = "battery", | ||
| 84 | .class = ACPI_BATTERY_CLASS, | ||
| 85 | .ids = battery_device_ids, | ||
| 86 | .ops = { | ||
| 87 | .add = acpi_battery_add, | ||
| 88 | .resume = acpi_battery_resume, | ||
| 89 | .remove = acpi_battery_remove, | ||
| 90 | }, | ||
| 91 | }; | ||
| 92 | 83 | ||
| 93 | struct acpi_battery_state { | 84 | MODULE_DEVICE_TABLE(acpi, battery_device_ids); |
| 94 | acpi_integer state; | ||
| 95 | acpi_integer present_rate; | ||
| 96 | acpi_integer remaining_capacity; | ||
| 97 | acpi_integer present_voltage; | ||
| 98 | }; | ||
| 99 | |||
| 100 | struct acpi_battery_info { | ||
| 101 | acpi_integer power_unit; | ||
| 102 | acpi_integer design_capacity; | ||
| 103 | acpi_integer last_full_capacity; | ||
| 104 | acpi_integer battery_technology; | ||
| 105 | acpi_integer design_voltage; | ||
| 106 | acpi_integer design_capacity_warning; | ||
| 107 | acpi_integer design_capacity_low; | ||
| 108 | acpi_integer battery_capacity_granularity_1; | ||
| 109 | acpi_integer battery_capacity_granularity_2; | ||
| 110 | acpi_string model_number; | ||
| 111 | acpi_string serial_number; | ||
| 112 | acpi_string battery_type; | ||
| 113 | acpi_string oem_info; | ||
| 114 | }; | ||
| 115 | |||
| 116 | enum acpi_battery_files{ | ||
| 117 | ACPI_BATTERY_INFO = 0, | ||
| 118 | ACPI_BATTERY_STATE, | ||
| 119 | ACPI_BATTERY_ALARM, | ||
| 120 | ACPI_BATTERY_NUMFILES, | ||
| 121 | }; | ||
| 122 | 85 | ||
| 123 | struct acpi_battery_flags { | ||
| 124 | u8 battery_present_prev; | ||
| 125 | u8 alarm_present; | ||
| 126 | u8 init_update; | ||
| 127 | u8 update[ACPI_BATTERY_NUMFILES]; | ||
| 128 | u8 power_unit; | ||
| 129 | }; | ||
| 130 | 86 | ||
| 131 | struct acpi_battery { | 87 | struct acpi_battery { |
| 132 | struct mutex mutex; | 88 | struct mutex lock; |
| 89 | struct power_supply bat; | ||
| 133 | struct acpi_device *device; | 90 | struct acpi_device *device; |
| 134 | struct acpi_battery_flags flags; | 91 | unsigned long update_time; |
| 135 | struct acpi_buffer bif_data; | 92 | int current_now; |
| 136 | struct acpi_buffer bst_data; | 93 | int capacity_now; |
| 137 | unsigned long alarm; | 94 | int voltage_now; |
| 138 | unsigned long update_time[ACPI_BATTERY_NUMFILES]; | 95 | int design_capacity; |
| 96 | int full_charge_capacity; | ||
| 97 | int technology; | ||
| 98 | int design_voltage; | ||
| 99 | int design_capacity_warning; | ||
| 100 | int design_capacity_low; | ||
| 101 | int capacity_granularity_1; | ||
| 102 | int capacity_granularity_2; | ||
| 103 | int alarm; | ||
| 104 | char model_number[32]; | ||
| 105 | char serial_number[32]; | ||
| 106 | char type[32]; | ||
| 107 | char oem_info[32]; | ||
| 108 | int state; | ||
| 109 | int power_unit; | ||
| 110 | u8 alarm_present; | ||
| 139 | }; | 111 | }; |
| 140 | 112 | ||
| 113 | #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat); | ||
| 114 | |||
| 141 | inline int acpi_battery_present(struct acpi_battery *battery) | 115 | inline int acpi_battery_present(struct acpi_battery *battery) |
| 142 | { | 116 | { |
| 143 | return battery->device->status.battery_present; | 117 | return battery->device->status.battery_present; |
| 144 | } | 118 | } |
| 145 | inline char *acpi_battery_power_units(struct acpi_battery *battery) | ||
| 146 | { | ||
| 147 | if (battery->flags.power_unit) | ||
| 148 | return ACPI_BATTERY_UNITS_AMPS; | ||
| 149 | else | ||
| 150 | return ACPI_BATTERY_UNITS_WATTS; | ||
| 151 | } | ||
| 152 | 119 | ||
| 153 | inline acpi_handle acpi_battery_handle(struct acpi_battery *battery) | 120 | static int acpi_battery_technology(struct acpi_battery *battery) |
| 154 | { | 121 | { |
| 155 | return battery->device->handle; | 122 | if (!strcasecmp("NiCd", battery->type)) |
| 123 | return POWER_SUPPLY_TECHNOLOGY_NiCd; | ||
| 124 | if (!strcasecmp("NiMH", battery->type)) | ||
| 125 | return POWER_SUPPLY_TECHNOLOGY_NiMH; | ||
| 126 | if (!strcasecmp("LION", battery->type)) | ||
| 127 | return POWER_SUPPLY_TECHNOLOGY_LION; | ||
| 128 | if (!strcasecmp("LiP", battery->type)) | ||
| 129 | return POWER_SUPPLY_TECHNOLOGY_LIPO; | ||
| 130 | return POWER_SUPPLY_TECHNOLOGY_UNKNOWN; | ||
| 156 | } | 131 | } |
| 157 | 132 | ||
| 158 | /* -------------------------------------------------------------------------- | 133 | static int acpi_battery_get_property(struct power_supply *psy, |
| 159 | Battery Management | 134 | enum power_supply_property psp, |
| 160 | -------------------------------------------------------------------------- */ | 135 | union power_supply_propval *val) |
| 161 | |||
| 162 | static void acpi_battery_check_result(struct acpi_battery *battery, int result) | ||
| 163 | { | 136 | { |
| 164 | if (!battery) | 137 | struct acpi_battery *battery = to_acpi_battery(psy); |
| 165 | return; | ||
| 166 | 138 | ||
| 167 | if (result) { | 139 | if ((!acpi_battery_present(battery)) && |
| 168 | battery->flags.init_update = 1; | 140 | psp != POWER_SUPPLY_PROP_PRESENT) |
| 141 | return -ENODEV; | ||
| 142 | switch (psp) { | ||
| 143 | case POWER_SUPPLY_PROP_STATUS: | ||
| 144 | if (battery->state & 0x01) | ||
| 145 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
| 146 | else if (battery->state & 0x02) | ||
| 147 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
| 148 | else if (battery->state == 0) | ||
| 149 | val->intval = POWER_SUPPLY_STATUS_FULL; | ||
| 150 | break; | ||
| 151 | case POWER_SUPPLY_PROP_PRESENT: | ||
| 152 | val->intval = acpi_battery_present(battery); | ||
| 153 | break; | ||
| 154 | case POWER_SUPPLY_PROP_TECHNOLOGY: | ||
| 155 | val->intval = acpi_battery_technology(battery); | ||
| 156 | break; | ||
| 157 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: | ||
| 158 | val->intval = battery->design_voltage * 1000; | ||
| 159 | break; | ||
| 160 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
| 161 | val->intval = battery->voltage_now * 1000; | ||
| 162 | break; | ||
| 163 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
| 164 | val->intval = battery->current_now * 1000; | ||
| 165 | break; | ||
| 166 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | ||
| 167 | case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: | ||
| 168 | val->intval = battery->design_capacity * 1000; | ||
| 169 | break; | ||
| 170 | case POWER_SUPPLY_PROP_CHARGE_FULL: | ||
| 171 | case POWER_SUPPLY_PROP_ENERGY_FULL: | ||
| 172 | val->intval = battery->full_charge_capacity * 1000; | ||
| 173 | break; | ||
| 174 | case POWER_SUPPLY_PROP_CHARGE_NOW: | ||
| 175 | case POWER_SUPPLY_PROP_ENERGY_NOW: | ||
| 176 | val->intval = battery->capacity_now * 1000; | ||
| 177 | break; | ||
| 178 | case POWER_SUPPLY_PROP_MODEL_NAME: | ||
| 179 | val->strval = battery->model_number; | ||
| 180 | break; | ||
| 181 | case POWER_SUPPLY_PROP_MANUFACTURER: | ||
| 182 | val->strval = battery->oem_info; | ||
| 183 | break; | ||
| 184 | default: | ||
| 185 | return -EINVAL; | ||
| 169 | } | 186 | } |
| 187 | return 0; | ||
| 170 | } | 188 | } |
| 171 | 189 | ||
| 172 | static int acpi_battery_extract_package(struct acpi_battery *battery, | 190 | static enum power_supply_property charge_battery_props[] = { |
| 173 | union acpi_object *package, | 191 | POWER_SUPPLY_PROP_STATUS, |
| 174 | struct acpi_buffer *format, | 192 | POWER_SUPPLY_PROP_PRESENT, |
| 175 | struct acpi_buffer *data, | 193 | POWER_SUPPLY_PROP_TECHNOLOGY, |
| 176 | char *package_name) | 194 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, |
| 195 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
| 196 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
| 197 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
| 198 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
| 199 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
| 200 | POWER_SUPPLY_PROP_MODEL_NAME, | ||
| 201 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
| 202 | }; | ||
| 203 | |||
| 204 | static enum power_supply_property energy_battery_props[] = { | ||
| 205 | POWER_SUPPLY_PROP_STATUS, | ||
| 206 | POWER_SUPPLY_PROP_PRESENT, | ||
| 207 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
| 208 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, | ||
| 209 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
| 210 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
| 211 | POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, | ||
| 212 | POWER_SUPPLY_PROP_ENERGY_FULL, | ||
| 213 | POWER_SUPPLY_PROP_ENERGY_NOW, | ||
| 214 | POWER_SUPPLY_PROP_MODEL_NAME, | ||
| 215 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
| 216 | }; | ||
| 217 | |||
| 218 | #ifdef CONFIG_ACPI_PROCFS | ||
| 219 | inline char *acpi_battery_units(struct acpi_battery *battery) | ||
| 177 | { | 220 | { |
| 178 | acpi_status status = AE_OK; | 221 | return (battery->power_unit)?"mA":"mW"; |
| 179 | struct acpi_buffer data_null = { 0, NULL }; | 222 | } |
| 223 | #endif | ||
| 180 | 224 | ||
| 181 | status = acpi_extract_package(package, format, &data_null); | 225 | /* -------------------------------------------------------------------------- |
| 182 | if (status != AE_BUFFER_OVERFLOW) { | 226 | Battery Management |
| 183 | ACPI_EXCEPTION((AE_INFO, status, "Extracting size %s", | 227 | -------------------------------------------------------------------------- */ |
| 184 | package_name)); | 228 | struct acpi_offsets { |
| 185 | return -ENODEV; | 229 | size_t offset; /* offset inside struct acpi_sbs_battery */ |
| 186 | } | 230 | u8 mode; /* int or string? */ |
| 231 | }; | ||
| 187 | 232 | ||
| 188 | if (data_null.length != data->length) { | 233 | static struct acpi_offsets state_offsets[] = { |
| 189 | kfree(data->pointer); | 234 | {offsetof(struct acpi_battery, state), 0}, |
| 190 | data->pointer = kzalloc(data_null.length, GFP_KERNEL); | 235 | {offsetof(struct acpi_battery, current_now), 0}, |
| 191 | if (!data->pointer) { | 236 | {offsetof(struct acpi_battery, capacity_now), 0}, |
| 192 | ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "kzalloc()")); | 237 | {offsetof(struct acpi_battery, voltage_now), 0}, |
| 193 | return -ENOMEM; | 238 | }; |
| 194 | } | ||
| 195 | data->length = data_null.length; | ||
| 196 | } | ||
| 197 | 239 | ||
| 198 | status = acpi_extract_package(package, format, data); | 240 | static struct acpi_offsets info_offsets[] = { |
| 199 | if (ACPI_FAILURE(status)) { | 241 | {offsetof(struct acpi_battery, power_unit), 0}, |
| 200 | ACPI_EXCEPTION((AE_INFO, status, "Extracting %s", | 242 | {offsetof(struct acpi_battery, design_capacity), 0}, |
| 201 | package_name)); | 243 | {offsetof(struct acpi_battery, full_charge_capacity), 0}, |
| 202 | return -ENODEV; | 244 | {offsetof(struct acpi_battery, technology), 0}, |
| 203 | } | 245 | {offsetof(struct acpi_battery, design_voltage), 0}, |
| 246 | {offsetof(struct acpi_battery, design_capacity_warning), 0}, | ||
| 247 | {offsetof(struct acpi_battery, design_capacity_low), 0}, | ||
| 248 | {offsetof(struct acpi_battery, capacity_granularity_1), 0}, | ||
| 249 | {offsetof(struct acpi_battery, capacity_granularity_2), 0}, | ||
| 250 | {offsetof(struct acpi_battery, model_number), 1}, | ||
| 251 | {offsetof(struct acpi_battery, serial_number), 1}, | ||
| 252 | {offsetof(struct acpi_battery, type), 1}, | ||
| 253 | {offsetof(struct acpi_battery, oem_info), 1}, | ||
| 254 | }; | ||
| 204 | 255 | ||
| 256 | static int extract_package(struct acpi_battery *battery, | ||
| 257 | union acpi_object *package, | ||
| 258 | struct acpi_offsets *offsets, int num) | ||
| 259 | { | ||
| 260 | int i, *x; | ||
| 261 | union acpi_object *element; | ||
| 262 | if (package->type != ACPI_TYPE_PACKAGE) | ||
| 263 | return -EFAULT; | ||
| 264 | for (i = 0; i < num; ++i) { | ||
| 265 | if (package->package.count <= i) | ||
| 266 | return -EFAULT; | ||
| 267 | element = &package->package.elements[i]; | ||
| 268 | if (offsets[i].mode) { | ||
| 269 | if (element->type != ACPI_TYPE_STRING && | ||
| 270 | element->type != ACPI_TYPE_BUFFER) | ||
| 271 | return -EFAULT; | ||
| 272 | strncpy((u8 *)battery + offsets[i].offset, | ||
| 273 | element->string.pointer, 32); | ||
| 274 | } else { | ||
| 275 | if (element->type != ACPI_TYPE_INTEGER) | ||
| 276 | return -EFAULT; | ||
| 277 | x = (int *)((u8 *)battery + offsets[i].offset); | ||
| 278 | *x = element->integer.value; | ||
| 279 | } | ||
| 280 | } | ||
| 205 | return 0; | 281 | return 0; |
| 206 | } | 282 | } |
| 207 | 283 | ||
| 208 | static int acpi_battery_get_status(struct acpi_battery *battery) | 284 | static int acpi_battery_get_status(struct acpi_battery *battery) |
| 209 | { | 285 | { |
| 210 | int result = 0; | 286 | if (acpi_bus_get_status(battery->device)) { |
| 211 | |||
| 212 | result = acpi_bus_get_status(battery->device); | ||
| 213 | if (result) { | ||
| 214 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA")); | 287 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA")); |
| 215 | return -ENODEV; | 288 | return -ENODEV; |
| 216 | } | 289 | } |
| 217 | return result; | 290 | return 0; |
| 218 | } | 291 | } |
| 219 | 292 | ||
| 220 | static int acpi_battery_get_info(struct acpi_battery *battery) | 293 | static int acpi_battery_get_info(struct acpi_battery *battery) |
| 221 | { | 294 | { |
| 222 | int result = 0; | 295 | int result = -EFAULT; |
| 223 | acpi_status status = 0; | 296 | acpi_status status = 0; |
| 224 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 297 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 225 | struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF), | ||
| 226 | ACPI_BATTERY_FORMAT_BIF | ||
| 227 | }; | ||
| 228 | union acpi_object *package = NULL; | ||
| 229 | struct acpi_buffer *data = NULL; | ||
| 230 | struct acpi_battery_info *bif = NULL; | ||
| 231 | |||
| 232 | battery->update_time[ACPI_BATTERY_INFO] = get_seconds(); | ||
| 233 | 298 | ||
| 234 | if (!acpi_battery_present(battery)) | 299 | if (!acpi_battery_present(battery)) |
| 235 | return 0; | 300 | return 0; |
| 301 | mutex_lock(&battery->lock); | ||
| 302 | status = acpi_evaluate_object(battery->device->handle, "_BIF", | ||
| 303 | NULL, &buffer); | ||
| 304 | mutex_unlock(&battery->lock); | ||
| 236 | 305 | ||
| 237 | /* Evaluate _BIF */ | ||
| 238 | |||
| 239 | status = | ||
| 240 | acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", NULL, | ||
| 241 | &buffer); | ||
| 242 | if (ACPI_FAILURE(status)) { | 306 | if (ACPI_FAILURE(status)) { |
| 243 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF")); | 307 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF")); |
| 244 | return -ENODEV; | 308 | return -ENODEV; |
| 245 | } | 309 | } |
| 246 | 310 | ||
| 247 | package = buffer.pointer; | 311 | result = extract_package(battery, buffer.pointer, |
| 248 | 312 | info_offsets, ARRAY_SIZE(info_offsets)); | |
| 249 | data = &battery->bif_data; | ||
| 250 | |||
| 251 | /* Extract Package Data */ | ||
| 252 | |||
| 253 | result = | ||
| 254 | acpi_battery_extract_package(battery, package, &format, data, | ||
| 255 | "_BIF"); | ||
| 256 | if (result) | ||
| 257 | goto end; | ||
| 258 | |||
| 259 | end: | ||
| 260 | |||
| 261 | kfree(buffer.pointer); | 313 | kfree(buffer.pointer); |
| 262 | |||
| 263 | if (!result) { | ||
| 264 | bif = data->pointer; | ||
| 265 | battery->flags.power_unit = bif->power_unit; | ||
| 266 | } | ||
| 267 | |||
| 268 | return result; | 314 | return result; |
| 269 | } | 315 | } |
| 270 | 316 | ||
| @@ -273,342 +319,203 @@ static int acpi_battery_get_state(struct acpi_battery *battery) | |||
| 273 | int result = 0; | 319 | int result = 0; |
| 274 | acpi_status status = 0; | 320 | acpi_status status = 0; |
| 275 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 321 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 276 | struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST), | ||
| 277 | ACPI_BATTERY_FORMAT_BST | ||
| 278 | }; | ||
| 279 | union acpi_object *package = NULL; | ||
| 280 | struct acpi_buffer *data = NULL; | ||
| 281 | |||
| 282 | battery->update_time[ACPI_BATTERY_STATE] = get_seconds(); | ||
| 283 | 322 | ||
| 284 | if (!acpi_battery_present(battery)) | 323 | if (!acpi_battery_present(battery)) |
| 285 | return 0; | 324 | return 0; |
| 286 | 325 | ||
| 287 | /* Evaluate _BST */ | 326 | if (battery->update_time && |
| 327 | time_before(jiffies, battery->update_time + | ||
| 328 | msecs_to_jiffies(cache_time))) | ||
| 329 | return 0; | ||
| 330 | |||
| 331 | mutex_lock(&battery->lock); | ||
| 332 | status = acpi_evaluate_object(battery->device->handle, "_BST", | ||
| 333 | NULL, &buffer); | ||
| 334 | mutex_unlock(&battery->lock); | ||
| 288 | 335 | ||
| 289 | status = | ||
| 290 | acpi_evaluate_object(acpi_battery_handle(battery), "_BST", NULL, | ||
| 291 | &buffer); | ||
| 292 | if (ACPI_FAILURE(status)) { | 336 | if (ACPI_FAILURE(status)) { |
| 293 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST")); | 337 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST")); |
| 294 | return -ENODEV; | 338 | return -ENODEV; |
| 295 | } | 339 | } |
| 296 | 340 | ||
| 297 | package = buffer.pointer; | 341 | result = extract_package(battery, buffer.pointer, |
| 298 | 342 | state_offsets, ARRAY_SIZE(state_offsets)); | |
| 299 | data = &battery->bst_data; | 343 | battery->update_time = jiffies; |
| 300 | |||
| 301 | /* Extract Package Data */ | ||
| 302 | |||
| 303 | result = | ||
| 304 | acpi_battery_extract_package(battery, package, &format, data, | ||
| 305 | "_BST"); | ||
| 306 | if (result) | ||
| 307 | goto end; | ||
| 308 | |||
| 309 | end: | ||
| 310 | kfree(buffer.pointer); | 344 | kfree(buffer.pointer); |
| 311 | |||
| 312 | return result; | 345 | return result; |
| 313 | } | 346 | } |
| 314 | 347 | ||
| 315 | static int acpi_battery_get_alarm(struct acpi_battery *battery) | 348 | static int acpi_battery_set_alarm(struct acpi_battery *battery) |
| 316 | { | ||
| 317 | battery->update_time[ACPI_BATTERY_ALARM] = get_seconds(); | ||
| 318 | |||
| 319 | return 0; | ||
| 320 | } | ||
| 321 | |||
| 322 | static int acpi_battery_set_alarm(struct acpi_battery *battery, | ||
| 323 | unsigned long alarm) | ||
| 324 | { | 349 | { |
| 325 | acpi_status status = 0; | 350 | acpi_status status = 0; |
| 326 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | 351 | union acpi_object arg0 = { .type = ACPI_TYPE_INTEGER }; |
| 327 | struct acpi_object_list arg_list = { 1, &arg0 }; | 352 | struct acpi_object_list arg_list = { 1, &arg0 }; |
| 328 | 353 | ||
| 329 | battery->update_time[ACPI_BATTERY_ALARM] = get_seconds(); | 354 | if (!acpi_battery_present(battery)|| !battery->alarm_present) |
| 330 | |||
| 331 | if (!acpi_battery_present(battery)) | ||
| 332 | return -ENODEV; | 355 | return -ENODEV; |
| 333 | 356 | ||
| 334 | if (!battery->flags.alarm_present) | 357 | arg0.integer.value = battery->alarm; |
| 335 | return -ENODEV; | ||
| 336 | |||
| 337 | arg0.integer.value = alarm; | ||
| 338 | 358 | ||
| 339 | status = | 359 | mutex_lock(&battery->lock); |
| 340 | acpi_evaluate_object(acpi_battery_handle(battery), "_BTP", | 360 | status = acpi_evaluate_object(battery->device->handle, "_BTP", |
| 341 | &arg_list, NULL); | 361 | &arg_list, NULL); |
| 362 | mutex_unlock(&battery->lock); | ||
| 363 | |||
| 342 | if (ACPI_FAILURE(status)) | 364 | if (ACPI_FAILURE(status)) |
| 343 | return -ENODEV; | 365 | return -ENODEV; |
| 344 | 366 | ||
| 345 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", (u32) alarm)); | 367 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", battery->alarm)); |
| 346 | |||
| 347 | battery->alarm = alarm; | ||
| 348 | |||
| 349 | return 0; | 368 | return 0; |
| 350 | } | 369 | } |
| 351 | 370 | ||
| 352 | static int acpi_battery_init_alarm(struct acpi_battery *battery) | 371 | static int acpi_battery_init_alarm(struct acpi_battery *battery) |
| 353 | { | 372 | { |
| 354 | int result = 0; | ||
| 355 | acpi_status status = AE_OK; | 373 | acpi_status status = AE_OK; |
| 356 | acpi_handle handle = NULL; | 374 | acpi_handle handle = NULL; |
| 357 | struct acpi_battery_info *bif = battery->bif_data.pointer; | ||
| 358 | unsigned long alarm = battery->alarm; | ||
| 359 | 375 | ||
| 360 | /* See if alarms are supported, and if so, set default */ | 376 | /* See if alarms are supported, and if so, set default */ |
| 361 | 377 | status = acpi_get_handle(battery->device->handle, "_BTP", &handle); | |
| 362 | status = acpi_get_handle(acpi_battery_handle(battery), "_BTP", &handle); | 378 | if (ACPI_FAILURE(status)) { |
| 363 | if (ACPI_SUCCESS(status)) { | 379 | battery->alarm_present = 0; |
| 364 | battery->flags.alarm_present = 1; | 380 | return 0; |
| 365 | if (!alarm && bif) { | ||
| 366 | alarm = bif->design_capacity_warning; | ||
| 367 | } | ||
| 368 | result = acpi_battery_set_alarm(battery, alarm); | ||
| 369 | if (result) | ||
| 370 | goto end; | ||
| 371 | } else { | ||
| 372 | battery->flags.alarm_present = 0; | ||
| 373 | } | 381 | } |
| 374 | 382 | battery->alarm_present = 1; | |
| 375 | end: | 383 | if (!battery->alarm) |
| 376 | 384 | battery->alarm = battery->design_capacity_warning; | |
| 377 | return result; | 385 | return acpi_battery_set_alarm(battery); |
| 378 | } | 386 | } |
| 379 | 387 | ||
| 380 | static int acpi_battery_init_update(struct acpi_battery *battery) | 388 | static int acpi_battery_update(struct acpi_battery *battery) |
| 381 | { | 389 | { |
| 382 | int result = 0; | 390 | int saved_present = acpi_battery_present(battery); |
| 383 | 391 | int result = acpi_battery_get_status(battery); | |
| 384 | result = acpi_battery_get_status(battery); | 392 | if (result || !acpi_battery_present(battery)) |
| 385 | if (result) | ||
| 386 | return result; | 393 | return result; |
| 387 | 394 | if (saved_present != acpi_battery_present(battery) || | |
| 388 | battery->flags.battery_present_prev = acpi_battery_present(battery); | 395 | !battery->update_time) { |
| 389 | 396 | battery->update_time = 0; | |
| 390 | if (acpi_battery_present(battery)) { | ||
| 391 | result = acpi_battery_get_info(battery); | 397 | result = acpi_battery_get_info(battery); |
| 392 | if (result) | 398 | if (result) |
| 393 | return result; | 399 | return result; |
| 394 | result = acpi_battery_get_state(battery); | 400 | if (battery->power_unit) { |
| 395 | if (result) | 401 | battery->bat.properties = charge_battery_props; |
| 396 | return result; | 402 | battery->bat.num_properties = |
| 397 | 403 | ARRAY_SIZE(charge_battery_props); | |
| 398 | acpi_battery_init_alarm(battery); | ||
| 399 | } | ||
| 400 | |||
| 401 | return result; | ||
| 402 | } | ||
| 403 | |||
| 404 | static int acpi_battery_update(struct acpi_battery *battery, | ||
| 405 | int update, int *update_result_ptr) | ||
| 406 | { | ||
| 407 | int result = 0; | ||
| 408 | int update_result = ACPI_BATTERY_NONE_UPDATE; | ||
| 409 | |||
| 410 | if (!acpi_battery_present(battery)) { | ||
| 411 | update = 1; | ||
| 412 | } | ||
| 413 | |||
| 414 | if (battery->flags.init_update) { | ||
| 415 | result = acpi_battery_init_update(battery); | ||
| 416 | if (result) | ||
| 417 | goto end; | ||
| 418 | update_result = ACPI_BATTERY_INIT_UPDATE; | ||
| 419 | } else if (update) { | ||
| 420 | result = acpi_battery_get_status(battery); | ||
| 421 | if (result) | ||
| 422 | goto end; | ||
| 423 | if ((!battery->flags.battery_present_prev & acpi_battery_present(battery)) | ||
| 424 | || (battery->flags.battery_present_prev & !acpi_battery_present(battery))) { | ||
| 425 | result = acpi_battery_init_update(battery); | ||
| 426 | if (result) | ||
| 427 | goto end; | ||
| 428 | update_result = ACPI_BATTERY_INIT_UPDATE; | ||
| 429 | } else { | 404 | } else { |
| 430 | update_result = ACPI_BATTERY_EASY_UPDATE; | 405 | battery->bat.properties = energy_battery_props; |
| 406 | battery->bat.num_properties = | ||
| 407 | ARRAY_SIZE(energy_battery_props); | ||
| 431 | } | 408 | } |
| 409 | acpi_battery_init_alarm(battery); | ||
| 432 | } | 410 | } |
| 433 | 411 | return acpi_battery_get_state(battery); | |
| 434 | end: | ||
| 435 | |||
| 436 | battery->flags.init_update = (result != 0); | ||
| 437 | |||
| 438 | *update_result_ptr = update_result; | ||
| 439 | |||
| 440 | return result; | ||
| 441 | } | ||
| 442 | |||
| 443 | static void acpi_battery_notify_update(struct acpi_battery *battery) | ||
| 444 | { | ||
| 445 | acpi_battery_get_status(battery); | ||
| 446 | |||
| 447 | if (battery->flags.init_update) { | ||
| 448 | return; | ||
| 449 | } | ||
| 450 | |||
| 451 | if ((!battery->flags.battery_present_prev & | ||
| 452 | acpi_battery_present(battery)) || | ||
| 453 | (battery->flags.battery_present_prev & | ||
| 454 | !acpi_battery_present(battery))) { | ||
| 455 | battery->flags.init_update = 1; | ||
| 456 | } else { | ||
| 457 | battery->flags.update[ACPI_BATTERY_INFO] = 1; | ||
| 458 | battery->flags.update[ACPI_BATTERY_STATE] = 1; | ||
| 459 | battery->flags.update[ACPI_BATTERY_ALARM] = 1; | ||
| 460 | } | ||
| 461 | } | 412 | } |
| 462 | 413 | ||
| 463 | /* -------------------------------------------------------------------------- | 414 | /* -------------------------------------------------------------------------- |
| 464 | FS Interface (/proc) | 415 | FS Interface (/proc) |
| 465 | -------------------------------------------------------------------------- */ | 416 | -------------------------------------------------------------------------- */ |
| 466 | 417 | ||
| 418 | #ifdef CONFIG_ACPI_PROCFS | ||
| 467 | static struct proc_dir_entry *acpi_battery_dir; | 419 | static struct proc_dir_entry *acpi_battery_dir; |
| 468 | 420 | ||
| 469 | static int acpi_battery_print_info(struct seq_file *seq, int result) | 421 | static int acpi_battery_print_info(struct seq_file *seq, int result) |
| 470 | { | 422 | { |
| 471 | struct acpi_battery *battery = seq->private; | 423 | struct acpi_battery *battery = seq->private; |
| 472 | struct acpi_battery_info *bif = NULL; | ||
| 473 | char *units = "?"; | ||
| 474 | 424 | ||
| 475 | if (result) | 425 | if (result) |
| 476 | goto end; | 426 | goto end; |
| 477 | 427 | ||
| 478 | if (acpi_battery_present(battery)) | 428 | seq_printf(seq, "present: %s\n", |
| 479 | seq_printf(seq, "present: yes\n"); | 429 | acpi_battery_present(battery)?"yes":"no"); |
| 480 | else { | 430 | if (!acpi_battery_present(battery)) |
| 481 | seq_printf(seq, "present: no\n"); | ||
| 482 | goto end; | ||
| 483 | } | ||
| 484 | |||
| 485 | bif = battery->bif_data.pointer; | ||
| 486 | if (!bif) { | ||
| 487 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BIF buffer is NULL")); | ||
| 488 | result = -ENODEV; | ||
| 489 | goto end; | 431 | goto end; |
| 490 | } | 432 | if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) |
| 491 | |||
| 492 | /* Battery Units */ | ||
| 493 | |||
| 494 | units = acpi_battery_power_units(battery); | ||
| 495 | |||
| 496 | if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) | ||
| 497 | seq_printf(seq, "design capacity: unknown\n"); | 433 | seq_printf(seq, "design capacity: unknown\n"); |
| 498 | else | 434 | else |
| 499 | seq_printf(seq, "design capacity: %d %sh\n", | 435 | seq_printf(seq, "design capacity: %d %sh\n", |
| 500 | (u32) bif->design_capacity, units); | 436 | battery->design_capacity, |
| 437 | acpi_battery_units(battery)); | ||
| 501 | 438 | ||
| 502 | if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN) | 439 | if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN) |
| 503 | seq_printf(seq, "last full capacity: unknown\n"); | 440 | seq_printf(seq, "last full capacity: unknown\n"); |
| 504 | else | 441 | else |
| 505 | seq_printf(seq, "last full capacity: %d %sh\n", | 442 | seq_printf(seq, "last full capacity: %d %sh\n", |
| 506 | (u32) bif->last_full_capacity, units); | 443 | battery->full_charge_capacity, |
| 444 | acpi_battery_units(battery)); | ||
| 507 | 445 | ||
| 508 | switch ((u32) bif->battery_technology) { | 446 | seq_printf(seq, "battery technology: %srechargeable\n", |
| 509 | case 0: | 447 | (!battery->technology)?"non-":""); |
| 510 | seq_printf(seq, "battery technology: non-rechargeable\n"); | ||
| 511 | break; | ||
| 512 | case 1: | ||
| 513 | seq_printf(seq, "battery technology: rechargeable\n"); | ||
| 514 | break; | ||
| 515 | default: | ||
| 516 | seq_printf(seq, "battery technology: unknown\n"); | ||
| 517 | break; | ||
| 518 | } | ||
| 519 | 448 | ||
| 520 | if (bif->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) | 449 | if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) |
| 521 | seq_printf(seq, "design voltage: unknown\n"); | 450 | seq_printf(seq, "design voltage: unknown\n"); |
| 522 | else | 451 | else |
| 523 | seq_printf(seq, "design voltage: %d mV\n", | 452 | seq_printf(seq, "design voltage: %d mV\n", |
| 524 | (u32) bif->design_voltage); | 453 | battery->design_voltage); |
| 525 | seq_printf(seq, "design capacity warning: %d %sh\n", | 454 | seq_printf(seq, "design capacity warning: %d %sh\n", |
| 526 | (u32) bif->design_capacity_warning, units); | 455 | battery->design_capacity_warning, |
| 456 | acpi_battery_units(battery)); | ||
| 527 | seq_printf(seq, "design capacity low: %d %sh\n", | 457 | seq_printf(seq, "design capacity low: %d %sh\n", |
| 528 | (u32) bif->design_capacity_low, units); | 458 | battery->design_capacity_low, |
| 459 | acpi_battery_units(battery)); | ||
| 529 | seq_printf(seq, "capacity granularity 1: %d %sh\n", | 460 | seq_printf(seq, "capacity granularity 1: %d %sh\n", |
| 530 | (u32) bif->battery_capacity_granularity_1, units); | 461 | battery->capacity_granularity_1, |
| 462 | acpi_battery_units(battery)); | ||
| 531 | seq_printf(seq, "capacity granularity 2: %d %sh\n", | 463 | seq_printf(seq, "capacity granularity 2: %d %sh\n", |
| 532 | (u32) bif->battery_capacity_granularity_2, units); | 464 | battery->capacity_granularity_2, |
| 533 | seq_printf(seq, "model number: %s\n", bif->model_number); | 465 | acpi_battery_units(battery)); |
| 534 | seq_printf(seq, "serial number: %s\n", bif->serial_number); | 466 | seq_printf(seq, "model number: %s\n", battery->model_number); |
| 535 | seq_printf(seq, "battery type: %s\n", bif->battery_type); | 467 | seq_printf(seq, "serial number: %s\n", battery->serial_number); |
| 536 | seq_printf(seq, "OEM info: %s\n", bif->oem_info); | 468 | seq_printf(seq, "battery type: %s\n", battery->type); |
| 537 | 469 | seq_printf(seq, "OEM info: %s\n", battery->oem_info); | |
| 538 | end: | 470 | end: |
| 539 | |||
| 540 | if (result) | 471 | if (result) |
| 541 | seq_printf(seq, "ERROR: Unable to read battery info\n"); | 472 | seq_printf(seq, "ERROR: Unable to read battery info\n"); |
| 542 | |||
| 543 | return result; | 473 | return result; |
| 544 | } | 474 | } |
| 545 | 475 | ||
| 546 | static int acpi_battery_print_state(struct seq_file *seq, int result) | 476 | static int acpi_battery_print_state(struct seq_file *seq, int result) |
| 547 | { | 477 | { |
| 548 | struct acpi_battery *battery = seq->private; | 478 | struct acpi_battery *battery = seq->private; |
| 549 | struct acpi_battery_state *bst = NULL; | ||
| 550 | char *units = "?"; | ||
| 551 | 479 | ||
| 552 | if (result) | 480 | if (result) |
| 553 | goto end; | 481 | goto end; |
| 554 | 482 | ||
| 555 | if (acpi_battery_present(battery)) | 483 | seq_printf(seq, "present: %s\n", |
| 556 | seq_printf(seq, "present: yes\n"); | 484 | acpi_battery_present(battery)?"yes":"no"); |
| 557 | else { | 485 | if (!acpi_battery_present(battery)) |
| 558 | seq_printf(seq, "present: no\n"); | ||
| 559 | goto end; | ||
| 560 | } | ||
| 561 | |||
| 562 | bst = battery->bst_data.pointer; | ||
| 563 | if (!bst) { | ||
| 564 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BST buffer is NULL")); | ||
| 565 | result = -ENODEV; | ||
| 566 | goto end; | 486 | goto end; |
| 567 | } | ||
| 568 | |||
| 569 | /* Battery Units */ | ||
| 570 | |||
| 571 | units = acpi_battery_power_units(battery); | ||
| 572 | |||
| 573 | if (!(bst->state & 0x04)) | ||
| 574 | seq_printf(seq, "capacity state: ok\n"); | ||
| 575 | else | ||
| 576 | seq_printf(seq, "capacity state: critical\n"); | ||
| 577 | 487 | ||
| 578 | if ((bst->state & 0x01) && (bst->state & 0x02)) { | 488 | seq_printf(seq, "capacity state: %s\n", |
| 489 | (battery->state & 0x04)?"critical":"ok"); | ||
| 490 | if ((battery->state & 0x01) && (battery->state & 0x02)) | ||
| 579 | seq_printf(seq, | 491 | seq_printf(seq, |
| 580 | "charging state: charging/discharging\n"); | 492 | "charging state: charging/discharging\n"); |
| 581 | } else if (bst->state & 0x01) | 493 | else if (battery->state & 0x01) |
| 582 | seq_printf(seq, "charging state: discharging\n"); | 494 | seq_printf(seq, "charging state: discharging\n"); |
| 583 | else if (bst->state & 0x02) | 495 | else if (battery->state & 0x02) |
| 584 | seq_printf(seq, "charging state: charging\n"); | 496 | seq_printf(seq, "charging state: charging\n"); |
| 585 | else { | 497 | else |
| 586 | seq_printf(seq, "charging state: charged\n"); | 498 | seq_printf(seq, "charging state: charged\n"); |
| 587 | } | ||
| 588 | 499 | ||
| 589 | if (bst->present_rate == ACPI_BATTERY_VALUE_UNKNOWN) | 500 | if (battery->current_now == ACPI_BATTERY_VALUE_UNKNOWN) |
| 590 | seq_printf(seq, "present rate: unknown\n"); | 501 | seq_printf(seq, "present rate: unknown\n"); |
| 591 | else | 502 | else |
| 592 | seq_printf(seq, "present rate: %d %s\n", | 503 | seq_printf(seq, "present rate: %d %s\n", |
| 593 | (u32) bst->present_rate, units); | 504 | battery->current_now, acpi_battery_units(battery)); |
| 594 | 505 | ||
| 595 | if (bst->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN) | 506 | if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN) |
| 596 | seq_printf(seq, "remaining capacity: unknown\n"); | 507 | seq_printf(seq, "remaining capacity: unknown\n"); |
| 597 | else | 508 | else |
| 598 | seq_printf(seq, "remaining capacity: %d %sh\n", | 509 | seq_printf(seq, "remaining capacity: %d %sh\n", |
| 599 | (u32) bst->remaining_capacity, units); | 510 | battery->capacity_now, acpi_battery_units(battery)); |
| 600 | 511 | if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN) | |
| 601 | if (bst->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN) | ||
| 602 | seq_printf(seq, "present voltage: unknown\n"); | 512 | seq_printf(seq, "present voltage: unknown\n"); |
| 603 | else | 513 | else |
| 604 | seq_printf(seq, "present voltage: %d mV\n", | 514 | seq_printf(seq, "present voltage: %d mV\n", |
| 605 | (u32) bst->present_voltage); | 515 | battery->voltage_now); |
| 606 | |||
| 607 | end: | 516 | end: |
| 608 | 517 | if (result) | |
| 609 | if (result) { | ||
| 610 | seq_printf(seq, "ERROR: Unable to read battery state\n"); | 518 | seq_printf(seq, "ERROR: Unable to read battery state\n"); |
| 611 | } | ||
| 612 | 519 | ||
| 613 | return result; | 520 | return result; |
| 614 | } | 521 | } |
| @@ -616,7 +523,6 @@ static int acpi_battery_print_state(struct seq_file *seq, int result) | |||
| 616 | static int acpi_battery_print_alarm(struct seq_file *seq, int result) | 523 | static int acpi_battery_print_alarm(struct seq_file *seq, int result) |
| 617 | { | 524 | { |
| 618 | struct acpi_battery *battery = seq->private; | 525 | struct acpi_battery *battery = seq->private; |
| 619 | char *units = "?"; | ||
| 620 | 526 | ||
| 621 | if (result) | 527 | if (result) |
| 622 | goto end; | 528 | goto end; |
| @@ -625,189 +531,121 @@ static int acpi_battery_print_alarm(struct seq_file *seq, int result) | |||
| 625 | seq_printf(seq, "present: no\n"); | 531 | seq_printf(seq, "present: no\n"); |
| 626 | goto end; | 532 | goto end; |
| 627 | } | 533 | } |
| 628 | |||
| 629 | /* Battery Units */ | ||
| 630 | |||
| 631 | units = acpi_battery_power_units(battery); | ||
| 632 | |||
| 633 | seq_printf(seq, "alarm: "); | 534 | seq_printf(seq, "alarm: "); |
| 634 | if (!battery->alarm) | 535 | if (!battery->alarm) |
| 635 | seq_printf(seq, "unsupported\n"); | 536 | seq_printf(seq, "unsupported\n"); |
| 636 | else | 537 | else |
| 637 | seq_printf(seq, "%lu %sh\n", battery->alarm, units); | 538 | seq_printf(seq, "%u %sh\n", battery->alarm, |
| 638 | 539 | acpi_battery_units(battery)); | |
| 639 | end: | 540 | end: |
| 640 | |||
| 641 | if (result) | 541 | if (result) |
| 642 | seq_printf(seq, "ERROR: Unable to read battery alarm\n"); | 542 | seq_printf(seq, "ERROR: Unable to read battery alarm\n"); |
| 643 | |||
| 644 | return result; | 543 | return result; |
| 645 | } | 544 | } |
| 646 | 545 | ||
| 647 | static ssize_t | 546 | static ssize_t acpi_battery_write_alarm(struct file *file, |
| 648 | acpi_battery_write_alarm(struct file *file, | 547 | const char __user * buffer, |
| 649 | const char __user * buffer, | 548 | size_t count, loff_t * ppos) |
| 650 | size_t count, loff_t * ppos) | ||
| 651 | { | 549 | { |
| 652 | int result = 0; | 550 | int result = 0; |
| 653 | char alarm_string[12] = { '\0' }; | 551 | char alarm_string[12] = { '\0' }; |
| 654 | struct seq_file *m = file->private_data; | 552 | struct seq_file *m = file->private_data; |
| 655 | struct acpi_battery *battery = m->private; | 553 | struct acpi_battery *battery = m->private; |
| 656 | int update_result = ACPI_BATTERY_NONE_UPDATE; | ||
| 657 | 554 | ||
| 658 | if (!battery || (count > sizeof(alarm_string) - 1)) | 555 | if (!battery || (count > sizeof(alarm_string) - 1)) |
| 659 | return -EINVAL; | 556 | return -EINVAL; |
| 660 | |||
| 661 | mutex_lock(&battery->mutex); | ||
| 662 | |||
| 663 | result = acpi_battery_update(battery, 1, &update_result); | ||
| 664 | if (result) { | 557 | if (result) { |
| 665 | result = -ENODEV; | 558 | result = -ENODEV; |
| 666 | goto end; | 559 | goto end; |
| 667 | } | 560 | } |
| 668 | |||
| 669 | if (!acpi_battery_present(battery)) { | 561 | if (!acpi_battery_present(battery)) { |
| 670 | result = -ENODEV; | 562 | result = -ENODEV; |
| 671 | goto end; | 563 | goto end; |
| 672 | } | 564 | } |
| 673 | |||
| 674 | if (copy_from_user(alarm_string, buffer, count)) { | 565 | if (copy_from_user(alarm_string, buffer, count)) { |
| 675 | result = -EFAULT; | 566 | result = -EFAULT; |
| 676 | goto end; | 567 | goto end; |
| 677 | } | 568 | } |
| 678 | |||
| 679 | alarm_string[count] = '\0'; | 569 | alarm_string[count] = '\0'; |
| 680 | 570 | battery->alarm = simple_strtol(alarm_string, NULL, 0); | |
| 681 | result = acpi_battery_set_alarm(battery, | 571 | result = acpi_battery_set_alarm(battery); |
| 682 | simple_strtoul(alarm_string, NULL, 0)); | ||
| 683 | if (result) | ||
| 684 | goto end; | ||
| 685 | |||
| 686 | end: | 572 | end: |
| 687 | |||
| 688 | acpi_battery_check_result(battery, result); | ||
| 689 | |||
| 690 | if (!result) | 573 | if (!result) |
| 691 | result = count; | 574 | return count; |
| 692 | |||
| 693 | mutex_unlock(&battery->mutex); | ||
| 694 | |||
| 695 | return result; | 575 | return result; |
| 696 | } | 576 | } |
| 697 | 577 | ||
| 698 | typedef int(*print_func)(struct seq_file *seq, int result); | 578 | typedef int(*print_func)(struct seq_file *seq, int result); |
| 699 | typedef int(*get_func)(struct acpi_battery *battery); | 579 | |
| 700 | 580 | static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = { | |
| 701 | static struct acpi_read_mux { | 581 | acpi_battery_print_info, |
| 702 | print_func print; | 582 | acpi_battery_print_state, |
| 703 | get_func get; | 583 | acpi_battery_print_alarm, |
| 704 | } acpi_read_funcs[ACPI_BATTERY_NUMFILES] = { | ||
| 705 | {.get = acpi_battery_get_info, .print = acpi_battery_print_info}, | ||
| 706 | {.get = acpi_battery_get_state, .print = acpi_battery_print_state}, | ||
| 707 | {.get = acpi_battery_get_alarm, .print = acpi_battery_print_alarm}, | ||
| 708 | }; | 584 | }; |
| 709 | 585 | ||
| 710 | static int acpi_battery_read(int fid, struct seq_file *seq) | 586 | static int acpi_battery_read(int fid, struct seq_file *seq) |
| 711 | { | 587 | { |
| 712 | struct acpi_battery *battery = seq->private; | 588 | struct acpi_battery *battery = seq->private; |
| 713 | int result = 0; | 589 | int result = acpi_battery_update(battery); |
| 714 | int update_result = ACPI_BATTERY_NONE_UPDATE; | 590 | return acpi_print_funcs[fid](seq, result); |
| 715 | int update = 0; | 591 | } |
| 716 | 592 | ||
| 717 | mutex_lock(&battery->mutex); | 593 | #define DECLARE_FILE_FUNCTIONS(_name) \ |
| 718 | 594 | static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \ | |
| 719 | update = (get_seconds() - battery->update_time[fid] >= update_time); | 595 | { \ |
| 720 | update = (update | battery->flags.update[fid]); | 596 | return acpi_battery_read(_name##_tag, seq); \ |
| 721 | 597 | } \ | |
| 722 | result = acpi_battery_update(battery, update, &update_result); | 598 | static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \ |
| 723 | if (result) | 599 | { \ |
| 724 | goto end; | 600 | return single_open(file, acpi_battery_read_##_name, PDE(inode)->data); \ |
| 725 | 601 | } | |
| 726 | if (update_result == ACPI_BATTERY_EASY_UPDATE) { | 602 | |
| 727 | result = acpi_read_funcs[fid].get(battery); | 603 | DECLARE_FILE_FUNCTIONS(info); |
| 728 | if (result) | 604 | DECLARE_FILE_FUNCTIONS(state); |
| 729 | goto end; | 605 | DECLARE_FILE_FUNCTIONS(alarm); |
| 606 | |||
| 607 | #undef DECLARE_FILE_FUNCTIONS | ||
| 608 | |||
| 609 | #define FILE_DESCRIPTION_RO(_name) \ | ||
| 610 | { \ | ||
| 611 | .name = __stringify(_name), \ | ||
| 612 | .mode = S_IRUGO, \ | ||
| 613 | .ops = { \ | ||
| 614 | .open = acpi_battery_##_name##_open_fs, \ | ||
| 615 | .read = seq_read, \ | ||
| 616 | .llseek = seq_lseek, \ | ||
| 617 | .release = single_release, \ | ||
| 618 | .owner = THIS_MODULE, \ | ||
| 619 | }, \ | ||
| 620 | } | ||
| 621 | |||
| 622 | #define FILE_DESCRIPTION_RW(_name) \ | ||
| 623 | { \ | ||
| 624 | .name = __stringify(_name), \ | ||
| 625 | .mode = S_IFREG | S_IRUGO | S_IWUSR, \ | ||
| 626 | .ops = { \ | ||
| 627 | .open = acpi_battery_##_name##_open_fs, \ | ||
| 628 | .read = seq_read, \ | ||
| 629 | .llseek = seq_lseek, \ | ||
| 630 | .write = acpi_battery_write_##_name, \ | ||
| 631 | .release = single_release, \ | ||
| 632 | .owner = THIS_MODULE, \ | ||
| 633 | }, \ | ||
| 730 | } | 634 | } |
| 731 | 635 | ||
| 732 | end: | ||
| 733 | result = acpi_read_funcs[fid].print(seq, result); | ||
| 734 | acpi_battery_check_result(battery, result); | ||
| 735 | battery->flags.update[fid] = result; | ||
| 736 | mutex_unlock(&battery->mutex); | ||
| 737 | return result; | ||
| 738 | } | ||
| 739 | |||
| 740 | static int acpi_battery_read_info(struct seq_file *seq, void *offset) | ||
| 741 | { | ||
| 742 | return acpi_battery_read(ACPI_BATTERY_INFO, seq); | ||
| 743 | } | ||
| 744 | |||
| 745 | static int acpi_battery_read_state(struct seq_file *seq, void *offset) | ||
| 746 | { | ||
| 747 | return acpi_battery_read(ACPI_BATTERY_STATE, seq); | ||
| 748 | } | ||
| 749 | |||
| 750 | static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) | ||
| 751 | { | ||
| 752 | return acpi_battery_read(ACPI_BATTERY_ALARM, seq); | ||
| 753 | } | ||
| 754 | |||
| 755 | static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) | ||
| 756 | { | ||
| 757 | return single_open(file, acpi_battery_read_info, PDE(inode)->data); | ||
| 758 | } | ||
| 759 | |||
| 760 | static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) | ||
| 761 | { | ||
| 762 | return single_open(file, acpi_battery_read_state, PDE(inode)->data); | ||
| 763 | } | ||
| 764 | |||
| 765 | static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) | ||
| 766 | { | ||
| 767 | return single_open(file, acpi_battery_read_alarm, PDE(inode)->data); | ||
| 768 | } | ||
| 769 | |||
| 770 | static struct battery_file { | 636 | static struct battery_file { |
| 771 | struct file_operations ops; | 637 | struct file_operations ops; |
| 772 | mode_t mode; | 638 | mode_t mode; |
| 773 | char *name; | 639 | char *name; |
| 774 | } acpi_battery_file[] = { | 640 | } acpi_battery_file[] = { |
| 775 | { | 641 | FILE_DESCRIPTION_RO(info), |
| 776 | .name = "info", | 642 | FILE_DESCRIPTION_RO(state), |
| 777 | .mode = S_IRUGO, | 643 | FILE_DESCRIPTION_RW(alarm), |
| 778 | .ops = { | ||
| 779 | .open = acpi_battery_info_open_fs, | ||
| 780 | .read = seq_read, | ||
| 781 | .llseek = seq_lseek, | ||
| 782 | .release = single_release, | ||
| 783 | .owner = THIS_MODULE, | ||
| 784 | }, | ||
| 785 | }, | ||
| 786 | { | ||
| 787 | .name = "state", | ||
| 788 | .mode = S_IRUGO, | ||
| 789 | .ops = { | ||
| 790 | .open = acpi_battery_state_open_fs, | ||
| 791 | .read = seq_read, | ||
| 792 | .llseek = seq_lseek, | ||
| 793 | .release = single_release, | ||
| 794 | .owner = THIS_MODULE, | ||
| 795 | }, | ||
| 796 | }, | ||
| 797 | { | ||
| 798 | .name = "alarm", | ||
| 799 | .mode = S_IFREG | S_IRUGO | S_IWUSR, | ||
| 800 | .ops = { | ||
| 801 | .open = acpi_battery_alarm_open_fs, | ||
| 802 | .read = seq_read, | ||
| 803 | .write = acpi_battery_write_alarm, | ||
| 804 | .llseek = seq_lseek, | ||
| 805 | .release = single_release, | ||
| 806 | .owner = THIS_MODULE, | ||
| 807 | }, | ||
| 808 | }, | ||
| 809 | }; | 644 | }; |
| 810 | 645 | ||
| 646 | #undef FILE_DESCRIPTION_RO | ||
| 647 | #undef FILE_DESCRIPTION_RW | ||
| 648 | |||
| 811 | static int acpi_battery_add_fs(struct acpi_device *device) | 649 | static int acpi_battery_add_fs(struct acpi_device *device) |
| 812 | { | 650 | { |
| 813 | struct proc_dir_entry *entry = NULL; | 651 | struct proc_dir_entry *entry = NULL; |
| @@ -832,25 +670,51 @@ static int acpi_battery_add_fs(struct acpi_device *device) | |||
| 832 | entry->owner = THIS_MODULE; | 670 | entry->owner = THIS_MODULE; |
| 833 | } | 671 | } |
| 834 | } | 672 | } |
| 835 | |||
| 836 | return 0; | 673 | return 0; |
| 837 | } | 674 | } |
| 838 | 675 | ||
| 839 | static int acpi_battery_remove_fs(struct acpi_device *device) | 676 | static void acpi_battery_remove_fs(struct acpi_device *device) |
| 840 | { | 677 | { |
| 841 | int i; | 678 | int i; |
| 842 | if (acpi_device_dir(device)) { | 679 | if (!acpi_device_dir(device)) |
| 843 | for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) { | 680 | return; |
| 844 | remove_proc_entry(acpi_battery_file[i].name, | 681 | for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) |
| 682 | remove_proc_entry(acpi_battery_file[i].name, | ||
| 845 | acpi_device_dir(device)); | 683 | acpi_device_dir(device)); |
| 846 | } | ||
| 847 | remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); | ||
| 848 | acpi_device_dir(device) = NULL; | ||
| 849 | } | ||
| 850 | 684 | ||
| 851 | return 0; | 685 | remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); |
| 686 | acpi_device_dir(device) = NULL; | ||
| 687 | } | ||
| 688 | |||
| 689 | #endif | ||
| 690 | |||
| 691 | static ssize_t acpi_battery_alarm_show(struct device *dev, | ||
| 692 | struct device_attribute *attr, | ||
| 693 | char *buf) | ||
| 694 | { | ||
| 695 | struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); | ||
| 696 | return sprintf(buf, "%d\n", battery->alarm * 1000); | ||
| 697 | } | ||
| 698 | |||
| 699 | static ssize_t acpi_battery_alarm_store(struct device *dev, | ||
| 700 | struct device_attribute *attr, | ||
| 701 | const char *buf, size_t count) | ||
| 702 | { | ||
| 703 | unsigned long x; | ||
| 704 | struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); | ||
| 705 | if (sscanf(buf, "%ld\n", &x) == 1) | ||
| 706 | battery->alarm = x/1000; | ||
| 707 | if (acpi_battery_present(battery)) | ||
| 708 | acpi_battery_set_alarm(battery); | ||
| 709 | return count; | ||
| 852 | } | 710 | } |
| 853 | 711 | ||
| 712 | static struct device_attribute alarm_attr = { | ||
| 713 | .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE}, | ||
| 714 | .show = acpi_battery_alarm_show, | ||
| 715 | .store = acpi_battery_alarm_store, | ||
| 716 | }; | ||
| 717 | |||
| 854 | /* -------------------------------------------------------------------------- | 718 | /* -------------------------------------------------------------------------- |
| 855 | Driver Interface | 719 | Driver Interface |
| 856 | -------------------------------------------------------------------------- */ | 720 | -------------------------------------------------------------------------- */ |
| @@ -858,33 +722,17 @@ static int acpi_battery_remove_fs(struct acpi_device *device) | |||
| 858 | static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) | 722 | static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) |
| 859 | { | 723 | { |
| 860 | struct acpi_battery *battery = data; | 724 | struct acpi_battery *battery = data; |
| 861 | struct acpi_device *device = NULL; | 725 | struct acpi_device *device; |
| 862 | |||
| 863 | if (!battery) | 726 | if (!battery) |
| 864 | return; | 727 | return; |
| 865 | |||
| 866 | device = battery->device; | 728 | device = battery->device; |
| 867 | 729 | acpi_battery_update(battery); | |
| 868 | switch (event) { | 730 | acpi_bus_generate_proc_event(device, event, |
| 869 | case ACPI_BATTERY_NOTIFY_STATUS: | 731 | acpi_battery_present(battery)); |
| 870 | case ACPI_BATTERY_NOTIFY_INFO: | 732 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
| 871 | case ACPI_NOTIFY_BUS_CHECK: | 733 | device->dev.bus_id, event, |
| 872 | case ACPI_NOTIFY_DEVICE_CHECK: | ||
| 873 | device = battery->device; | ||
| 874 | acpi_battery_notify_update(battery); | ||
| 875 | acpi_bus_generate_proc_event(device, event, | ||
| 876 | acpi_battery_present(battery)); | 734 | acpi_battery_present(battery)); |
| 877 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 735 | kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE); |
| 878 | device->dev.bus_id, event, | ||
| 879 | acpi_battery_present(battery)); | ||
| 880 | break; | ||
| 881 | default: | ||
| 882 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 883 | "Unsupported event [0x%x]\n", event)); | ||
| 884 | break; | ||
| 885 | } | ||
| 886 | |||
| 887 | return; | ||
| 888 | } | 736 | } |
| 889 | 737 | ||
| 890 | static int acpi_battery_add(struct acpi_device *device) | 738 | static int acpi_battery_add(struct acpi_device *device) |
| @@ -892,33 +740,27 @@ static int acpi_battery_add(struct acpi_device *device) | |||
| 892 | int result = 0; | 740 | int result = 0; |
| 893 | acpi_status status = 0; | 741 | acpi_status status = 0; |
| 894 | struct acpi_battery *battery = NULL; | 742 | struct acpi_battery *battery = NULL; |
| 895 | |||
| 896 | if (!device) | 743 | if (!device) |
| 897 | return -EINVAL; | 744 | return -EINVAL; |
| 898 | |||
| 899 | battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL); | 745 | battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL); |
| 900 | if (!battery) | 746 | if (!battery) |
| 901 | return -ENOMEM; | 747 | return -ENOMEM; |
| 902 | |||
| 903 | mutex_init(&battery->mutex); | ||
| 904 | |||
| 905 | mutex_lock(&battery->mutex); | ||
| 906 | |||
| 907 | battery->device = device; | 748 | battery->device = device; |
| 908 | strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); | 749 | strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); |
| 909 | strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); | 750 | strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); |
| 910 | acpi_driver_data(device) = battery; | 751 | acpi_driver_data(device) = battery; |
| 911 | 752 | mutex_init(&battery->lock); | |
| 912 | result = acpi_battery_get_status(battery); | 753 | acpi_battery_update(battery); |
| 913 | if (result) | 754 | #ifdef CONFIG_ACPI_PROCFS |
| 914 | goto end; | ||
| 915 | |||
| 916 | battery->flags.init_update = 1; | ||
| 917 | |||
| 918 | result = acpi_battery_add_fs(device); | 755 | result = acpi_battery_add_fs(device); |
| 919 | if (result) | 756 | if (result) |
| 920 | goto end; | 757 | goto end; |
| 921 | 758 | #endif | |
| 759 | battery->bat.name = acpi_device_bid(device); | ||
| 760 | battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; | ||
| 761 | battery->bat.get_property = acpi_battery_get_property; | ||
| 762 | result = power_supply_register(&battery->device->dev, &battery->bat); | ||
| 763 | result = device_create_file(battery->bat.dev, &alarm_attr); | ||
| 922 | status = acpi_install_notify_handler(device->handle, | 764 | status = acpi_install_notify_handler(device->handle, |
| 923 | ACPI_ALL_NOTIFY, | 765 | ACPI_ALL_NOTIFY, |
| 924 | acpi_battery_notify, battery); | 766 | acpi_battery_notify, battery); |
| @@ -927,20 +769,16 @@ static int acpi_battery_add(struct acpi_device *device) | |||
| 927 | result = -ENODEV; | 769 | result = -ENODEV; |
| 928 | goto end; | 770 | goto end; |
| 929 | } | 771 | } |
| 930 | |||
| 931 | printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", | 772 | printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", |
| 932 | ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), | 773 | ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), |
| 933 | device->status.battery_present ? "present" : "absent"); | 774 | device->status.battery_present ? "present" : "absent"); |
| 934 | |||
| 935 | end: | 775 | end: |
| 936 | |||
| 937 | if (result) { | 776 | if (result) { |
| 777 | #ifdef CONFIG_ACPI_PROCFS | ||
| 938 | acpi_battery_remove_fs(device); | 778 | acpi_battery_remove_fs(device); |
| 779 | #endif | ||
| 939 | kfree(battery); | 780 | kfree(battery); |
| 940 | } | 781 | } |
| 941 | |||
| 942 | mutex_unlock(&battery->mutex); | ||
| 943 | |||
| 944 | return result; | 782 | return result; |
| 945 | } | 783 | } |
| 946 | 784 | ||
| @@ -951,27 +789,19 @@ static int acpi_battery_remove(struct acpi_device *device, int type) | |||
| 951 | 789 | ||
| 952 | if (!device || !acpi_driver_data(device)) | 790 | if (!device || !acpi_driver_data(device)) |
| 953 | return -EINVAL; | 791 | return -EINVAL; |
| 954 | |||
| 955 | battery = acpi_driver_data(device); | 792 | battery = acpi_driver_data(device); |
| 956 | |||
| 957 | mutex_lock(&battery->mutex); | ||
| 958 | |||
| 959 | status = acpi_remove_notify_handler(device->handle, | 793 | status = acpi_remove_notify_handler(device->handle, |
| 960 | ACPI_ALL_NOTIFY, | 794 | ACPI_ALL_NOTIFY, |
| 961 | acpi_battery_notify); | 795 | acpi_battery_notify); |
| 962 | 796 | #ifdef CONFIG_ACPI_PROCFS | |
| 963 | acpi_battery_remove_fs(device); | 797 | acpi_battery_remove_fs(device); |
| 964 | 798 | #endif | |
| 965 | kfree(battery->bif_data.pointer); | 799 | if (battery->bat.dev) { |
| 966 | 800 | device_remove_file(battery->bat.dev, &alarm_attr); | |
| 967 | kfree(battery->bst_data.pointer); | 801 | power_supply_unregister(&battery->bat); |
| 968 | 802 | } | |
| 969 | mutex_unlock(&battery->mutex); | 803 | mutex_destroy(&battery->lock); |
| 970 | |||
| 971 | mutex_destroy(&battery->mutex); | ||
| 972 | |||
| 973 | kfree(battery); | 804 | kfree(battery); |
| 974 | |||
| 975 | return 0; | 805 | return 0; |
| 976 | } | 806 | } |
| 977 | 807 | ||
| @@ -979,44 +809,48 @@ static int acpi_battery_remove(struct acpi_device *device, int type) | |||
| 979 | static int acpi_battery_resume(struct acpi_device *device) | 809 | static int acpi_battery_resume(struct acpi_device *device) |
| 980 | { | 810 | { |
| 981 | struct acpi_battery *battery; | 811 | struct acpi_battery *battery; |
| 982 | |||
| 983 | if (!device) | 812 | if (!device) |
| 984 | return -EINVAL; | 813 | return -EINVAL; |
| 985 | 814 | battery = acpi_driver_data(device); | |
| 986 | battery = device->driver_data; | 815 | battery->update_time = 0; |
| 987 | |||
| 988 | battery->flags.init_update = 1; | ||
| 989 | |||
| 990 | return 0; | 816 | return 0; |
| 991 | } | 817 | } |
| 992 | 818 | ||
| 819 | static struct acpi_driver acpi_battery_driver = { | ||
| 820 | .name = "battery", | ||
| 821 | .class = ACPI_BATTERY_CLASS, | ||
| 822 | .ids = battery_device_ids, | ||
| 823 | .ops = { | ||
| 824 | .add = acpi_battery_add, | ||
| 825 | .resume = acpi_battery_resume, | ||
| 826 | .remove = acpi_battery_remove, | ||
| 827 | }, | ||
| 828 | }; | ||
| 829 | |||
| 993 | static int __init acpi_battery_init(void) | 830 | static int __init acpi_battery_init(void) |
| 994 | { | 831 | { |
| 995 | int result; | ||
| 996 | |||
| 997 | if (acpi_disabled) | 832 | if (acpi_disabled) |
| 998 | return -ENODEV; | 833 | return -ENODEV; |
| 999 | 834 | #ifdef CONFIG_ACPI_PROCFS | |
| 1000 | acpi_battery_dir = acpi_lock_battery_dir(); | 835 | acpi_battery_dir = acpi_lock_battery_dir(); |
| 1001 | if (!acpi_battery_dir) | 836 | if (!acpi_battery_dir) |
| 1002 | return -ENODEV; | 837 | return -ENODEV; |
| 1003 | 838 | #endif | |
| 1004 | result = acpi_bus_register_driver(&acpi_battery_driver); | 839 | if (acpi_bus_register_driver(&acpi_battery_driver) < 0) { |
| 1005 | if (result < 0) { | 840 | #ifdef CONFIG_ACPI_PROCFS |
| 1006 | acpi_unlock_battery_dir(acpi_battery_dir); | 841 | acpi_unlock_battery_dir(acpi_battery_dir); |
| 842 | #endif | ||
| 1007 | return -ENODEV; | 843 | return -ENODEV; |
| 1008 | } | 844 | } |
| 1009 | |||
| 1010 | return 0; | 845 | return 0; |
| 1011 | } | 846 | } |
| 1012 | 847 | ||
| 1013 | static void __exit acpi_battery_exit(void) | 848 | static void __exit acpi_battery_exit(void) |
| 1014 | { | 849 | { |
| 1015 | acpi_bus_unregister_driver(&acpi_battery_driver); | 850 | acpi_bus_unregister_driver(&acpi_battery_driver); |
| 1016 | 851 | #ifdef CONFIG_ACPI_PROCFS | |
| 1017 | acpi_unlock_battery_dir(acpi_battery_dir); | 852 | acpi_unlock_battery_dir(acpi_battery_dir); |
| 1018 | 853 | #endif | |
| 1019 | return; | ||
| 1020 | } | 854 | } |
| 1021 | 855 | ||
| 1022 | module_init(acpi_battery_init); | 856 | module_init(acpi_battery_init); |
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 9ba778a2b484..a54234d3aac1 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
| @@ -284,15 +284,11 @@ DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue); | |||
| 284 | 284 | ||
| 285 | extern int event_is_open; | 285 | extern int event_is_open; |
| 286 | 286 | ||
| 287 | int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) | 287 | int acpi_bus_generate_proc_event4(const char *device_class, const char *bus_id, u8 type, int data) |
| 288 | { | 288 | { |
| 289 | struct acpi_bus_event *event = NULL; | 289 | struct acpi_bus_event *event; |
| 290 | unsigned long flags = 0; | 290 | unsigned long flags = 0; |
| 291 | 291 | ||
| 292 | |||
| 293 | if (!device) | ||
| 294 | return -EINVAL; | ||
| 295 | |||
| 296 | /* drop event on the floor if no one's listening */ | 292 | /* drop event on the floor if no one's listening */ |
| 297 | if (!event_is_open) | 293 | if (!event_is_open) |
| 298 | return 0; | 294 | return 0; |
| @@ -301,8 +297,8 @@ int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) | |||
| 301 | if (!event) | 297 | if (!event) |
| 302 | return -ENOMEM; | 298 | return -ENOMEM; |
| 303 | 299 | ||
| 304 | strcpy(event->device_class, device->pnp.device_class); | 300 | strcpy(event->device_class, device_class); |
| 305 | strcpy(event->bus_id, device->pnp.bus_id); | 301 | strcpy(event->bus_id, bus_id); |
| 306 | event->type = type; | 302 | event->type = type; |
| 307 | event->data = data; | 303 | event->data = data; |
| 308 | 304 | ||
| @@ -313,6 +309,17 @@ int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) | |||
| 313 | wake_up_interruptible(&acpi_bus_event_queue); | 309 | wake_up_interruptible(&acpi_bus_event_queue); |
| 314 | 310 | ||
| 315 | return 0; | 311 | return 0; |
| 312 | |||
| 313 | } | ||
| 314 | |||
| 315 | EXPORT_SYMBOL_GPL(acpi_bus_generate_proc_event4); | ||
| 316 | |||
| 317 | int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) | ||
| 318 | { | ||
| 319 | if (!device) | ||
| 320 | return -EINVAL; | ||
| 321 | return acpi_bus_generate_proc_event4(device->pnp.device_class, | ||
| 322 | device->pnp.bus_id, type, data); | ||
| 316 | } | 323 | } |
| 317 | 324 | ||
| 318 | EXPORT_SYMBOL(acpi_bus_generate_proc_event); | 325 | EXPORT_SYMBOL(acpi_bus_generate_proc_event); |
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 3f7935ab0cf5..e9a04052084b 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
| @@ -425,7 +425,7 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, | |||
| 425 | handler->func = func; | 425 | handler->func = func; |
| 426 | handler->data = data; | 426 | handler->data = data; |
| 427 | mutex_lock(&ec->lock); | 427 | mutex_lock(&ec->lock); |
| 428 | list_add_tail(&handler->node, &ec->list); | 428 | list_add(&handler->node, &ec->list); |
| 429 | mutex_unlock(&ec->lock); | 429 | mutex_unlock(&ec->lock); |
| 430 | return 0; | 430 | return 0; |
| 431 | } | 431 | } |
| @@ -440,7 +440,6 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) | |||
| 440 | if (query_bit == handler->query_bit) { | 440 | if (query_bit == handler->query_bit) { |
| 441 | list_del(&handler->node); | 441 | list_del(&handler->node); |
| 442 | kfree(handler); | 442 | kfree(handler); |
| 443 | break; | ||
| 444 | } | 443 | } |
| 445 | } | 444 | } |
| 446 | mutex_unlock(&ec->lock); | 445 | mutex_unlock(&ec->lock); |
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index cf69c0040a39..8181afbd1d4d 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c | |||
| @@ -234,15 +234,11 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) | |||
| 234 | "While executing method _SST")); | 234 | "While executing method _SST")); |
| 235 | } | 235 | } |
| 236 | 236 | ||
| 237 | /* | 237 | /* Disable/Clear all GPEs */ |
| 238 | * 1) Disable/Clear all GPEs | 238 | |
| 239 | */ | ||
| 240 | status = acpi_hw_disable_all_gpes(); | 239 | status = acpi_hw_disable_all_gpes(); |
| 241 | if (ACPI_FAILURE(status)) { | ||
| 242 | return_ACPI_STATUS(status); | ||
| 243 | } | ||
| 244 | 240 | ||
| 245 | return_ACPI_STATUS(AE_OK); | 241 | return_ACPI_STATUS(status); |
| 246 | } | 242 | } |
| 247 | 243 | ||
| 248 | ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) | 244 | ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) |
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index a578986e3214..90fd09c65f95 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * acpi_sbs.c - ACPI Smart Battery System Driver ($Revision: 1.16 $) | 2 | * sbs.c - ACPI Smart Battery System Driver ($Revision: 2.0 $) |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2007 Alexey Starikovskiy <astarikovskiy@suse.de> | ||
| 5 | * Copyright (c) 2005-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com> | ||
| 4 | * Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu> | 6 | * Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu> |
| 5 | * | 7 | * |
| 6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| @@ -26,15 +28,22 @@ | |||
| 26 | #include <linux/module.h> | 28 | #include <linux/module.h> |
| 27 | #include <linux/moduleparam.h> | 29 | #include <linux/moduleparam.h> |
| 28 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
| 31 | |||
| 32 | #ifdef CONFIG_ACPI_PROCFS | ||
| 29 | #include <linux/proc_fs.h> | 33 | #include <linux/proc_fs.h> |
| 30 | #include <linux/seq_file.h> | 34 | #include <linux/seq_file.h> |
| 31 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
| 36 | #endif | ||
| 37 | |||
| 32 | #include <linux/acpi.h> | 38 | #include <linux/acpi.h> |
| 33 | #include <linux/timer.h> | 39 | #include <linux/timer.h> |
| 34 | #include <linux/jiffies.h> | 40 | #include <linux/jiffies.h> |
| 35 | #include <linux/delay.h> | 41 | #include <linux/delay.h> |
| 36 | 42 | ||
| 37 | #define ACPI_SBS_COMPONENT 0x00080000 | 43 | #include <linux/power_supply.h> |
| 44 | |||
| 45 | #include "sbshc.h" | ||
| 46 | |||
| 38 | #define ACPI_SBS_CLASS "sbs" | 47 | #define ACPI_SBS_CLASS "sbs" |
| 39 | #define ACPI_AC_CLASS "ac_adapter" | 48 | #define ACPI_AC_CLASS "ac_adapter" |
| 40 | #define ACPI_BATTERY_CLASS "battery" | 49 | #define ACPI_BATTERY_CLASS "battery" |
| @@ -44,836 +53,436 @@ | |||
| 44 | #define ACPI_SBS_FILE_ALARM "alarm" | 53 | #define ACPI_SBS_FILE_ALARM "alarm" |
| 45 | #define ACPI_BATTERY_DIR_NAME "BAT%i" | 54 | #define ACPI_BATTERY_DIR_NAME "BAT%i" |
| 46 | #define ACPI_AC_DIR_NAME "AC0" | 55 | #define ACPI_AC_DIR_NAME "AC0" |
| 47 | #define ACPI_SBC_SMBUS_ADDR 0x9 | ||
| 48 | #define ACPI_SBSM_SMBUS_ADDR 0xa | ||
| 49 | #define ACPI_SB_SMBUS_ADDR 0xb | ||
| 50 | #define ACPI_SBS_AC_NOTIFY_STATUS 0x80 | ||
| 51 | #define ACPI_SBS_BATTERY_NOTIFY_STATUS 0x80 | ||
| 52 | #define ACPI_SBS_BATTERY_NOTIFY_INFO 0x81 | ||
| 53 | 56 | ||
| 54 | #define _COMPONENT ACPI_SBS_COMPONENT | 57 | enum acpi_sbs_device_addr { |
| 58 | ACPI_SBS_CHARGER = 0x9, | ||
| 59 | ACPI_SBS_MANAGER = 0xa, | ||
| 60 | ACPI_SBS_BATTERY = 0xb, | ||
| 61 | }; | ||
| 55 | 62 | ||
| 56 | ACPI_MODULE_NAME("sbs"); | 63 | #define ACPI_SBS_NOTIFY_STATUS 0x80 |
| 64 | #define ACPI_SBS_NOTIFY_INFO 0x81 | ||
| 57 | 65 | ||
| 58 | MODULE_AUTHOR("Rich Townsend"); | 66 | MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>"); |
| 59 | MODULE_DESCRIPTION("Smart Battery System ACPI interface driver"); | 67 | MODULE_DESCRIPTION("Smart Battery System ACPI interface driver"); |
| 60 | MODULE_LICENSE("GPL"); | 68 | MODULE_LICENSE("GPL"); |
| 61 | 69 | ||
| 62 | #define xmsleep(t) msleep(t) | 70 | static unsigned int cache_time = 1000; |
| 63 | 71 | module_param(cache_time, uint, 0644); | |
| 64 | #define ACPI_EC_SMB_PRTCL 0x00 /* protocol, PEC */ | 72 | MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); |
| 65 | |||
| 66 | #define ACPI_EC_SMB_STS 0x01 /* status */ | ||
| 67 | #define ACPI_EC_SMB_ADDR 0x02 /* address */ | ||
| 68 | #define ACPI_EC_SMB_CMD 0x03 /* command */ | ||
| 69 | #define ACPI_EC_SMB_DATA 0x04 /* 32 data registers */ | ||
| 70 | #define ACPI_EC_SMB_BCNT 0x24 /* number of data bytes */ | ||
| 71 | |||
| 72 | #define ACPI_EC_SMB_STS_DONE 0x80 | ||
| 73 | #define ACPI_EC_SMB_STS_STATUS 0x1f | ||
| 74 | |||
| 75 | #define ACPI_EC_SMB_PRTCL_WRITE 0x00 | ||
| 76 | #define ACPI_EC_SMB_PRTCL_READ 0x01 | ||
| 77 | #define ACPI_EC_SMB_PRTCL_WORD_DATA 0x08 | ||
| 78 | #define ACPI_EC_SMB_PRTCL_BLOCK_DATA 0x0a | ||
| 79 | |||
| 80 | #define ACPI_EC_SMB_TRANSACTION_SLEEP 1 | ||
| 81 | #define ACPI_EC_SMB_ACCESS_SLEEP1 1 | ||
| 82 | #define ACPI_EC_SMB_ACCESS_SLEEP2 10 | ||
| 83 | |||
| 84 | #define DEF_CAPACITY_UNIT 3 | ||
| 85 | #define MAH_CAPACITY_UNIT 1 | ||
| 86 | #define MWH_CAPACITY_UNIT 2 | ||
| 87 | #define CAPACITY_UNIT DEF_CAPACITY_UNIT | ||
| 88 | |||
| 89 | #define REQUEST_UPDATE_MODE 1 | ||
| 90 | #define QUEUE_UPDATE_MODE 2 | ||
| 91 | |||
| 92 | #define DATA_TYPE_COMMON 0 | ||
| 93 | #define DATA_TYPE_INFO 1 | ||
| 94 | #define DATA_TYPE_STATE 2 | ||
| 95 | #define DATA_TYPE_ALARM 3 | ||
| 96 | #define DATA_TYPE_AC_STATE 4 | ||
| 97 | 73 | ||
| 98 | extern struct proc_dir_entry *acpi_lock_ac_dir(void); | 74 | extern struct proc_dir_entry *acpi_lock_ac_dir(void); |
| 99 | extern struct proc_dir_entry *acpi_lock_battery_dir(void); | 75 | extern struct proc_dir_entry *acpi_lock_battery_dir(void); |
| 100 | extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); | 76 | extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); |
| 101 | extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); | 77 | extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); |
| 102 | 78 | ||
| 103 | #define MAX_SBS_BAT 4 | 79 | #define MAX_SBS_BAT 4 |
| 104 | #define ACPI_SBS_BLOCK_MAX 32 | 80 | #define ACPI_SBS_BLOCK_MAX 32 |
| 105 | 81 | ||
| 106 | #define ACPI_SBS_SMBUS_READ 1 | ||
| 107 | #define ACPI_SBS_SMBUS_WRITE 2 | ||
| 108 | |||
| 109 | #define ACPI_SBS_WORD_DATA 1 | ||
| 110 | #define ACPI_SBS_BLOCK_DATA 2 | ||
| 111 | |||
| 112 | #define UPDATE_DELAY 10 | ||
| 113 | |||
| 114 | /* 0 - every time, > 0 - by update_time */ | ||
| 115 | static unsigned int update_time = 120; | ||
| 116 | |||
| 117 | static unsigned int capacity_mode = CAPACITY_UNIT; | ||
| 118 | |||
| 119 | module_param(update_time, uint, 0644); | ||
| 120 | module_param(capacity_mode, uint, 0444); | ||
| 121 | |||
| 122 | static int acpi_sbs_add(struct acpi_device *device); | ||
| 123 | static int acpi_sbs_remove(struct acpi_device *device, int type); | ||
| 124 | static int acpi_sbs_resume(struct acpi_device *device); | ||
| 125 | |||
| 126 | static const struct acpi_device_id sbs_device_ids[] = { | 82 | static const struct acpi_device_id sbs_device_ids[] = { |
| 127 | {"ACPI0001", 0}, | 83 | {"ACPI0002", 0}, |
| 128 | {"ACPI0005", 0}, | ||
| 129 | {"", 0}, | 84 | {"", 0}, |
| 130 | }; | 85 | }; |
| 131 | MODULE_DEVICE_TABLE(acpi, sbs_device_ids); | 86 | MODULE_DEVICE_TABLE(acpi, sbs_device_ids); |
| 132 | 87 | ||
| 133 | static struct acpi_driver acpi_sbs_driver = { | ||
| 134 | .name = "sbs", | ||
| 135 | .class = ACPI_SBS_CLASS, | ||
| 136 | .ids = sbs_device_ids, | ||
| 137 | .ops = { | ||
| 138 | .add = acpi_sbs_add, | ||
| 139 | .remove = acpi_sbs_remove, | ||
| 140 | .resume = acpi_sbs_resume, | ||
| 141 | }, | ||
| 142 | }; | ||
| 143 | |||
| 144 | struct acpi_ac { | ||
| 145 | int ac_present; | ||
| 146 | }; | ||
| 147 | |||
| 148 | struct acpi_battery_info { | ||
| 149 | int capacity_mode; | ||
| 150 | s16 full_charge_capacity; | ||
| 151 | s16 design_capacity; | ||
| 152 | s16 design_voltage; | ||
| 153 | int vscale; | ||
| 154 | int ipscale; | ||
| 155 | s16 serial_number; | ||
| 156 | char manufacturer_name[ACPI_SBS_BLOCK_MAX + 3]; | ||
| 157 | char device_name[ACPI_SBS_BLOCK_MAX + 3]; | ||
| 158 | char device_chemistry[ACPI_SBS_BLOCK_MAX + 3]; | ||
| 159 | }; | ||
| 160 | |||
| 161 | struct acpi_battery_state { | ||
| 162 | s16 voltage; | ||
| 163 | s16 amperage; | ||
| 164 | s16 remaining_capacity; | ||
| 165 | s16 battery_state; | ||
| 166 | }; | ||
| 167 | |||
| 168 | struct acpi_battery_alarm { | ||
| 169 | s16 remaining_capacity; | ||
| 170 | }; | ||
| 171 | |||
| 172 | struct acpi_battery { | 88 | struct acpi_battery { |
| 173 | int alive; | 89 | struct power_supply bat; |
| 174 | int id; | ||
| 175 | int init_state; | ||
| 176 | int battery_present; | ||
| 177 | struct acpi_sbs *sbs; | 90 | struct acpi_sbs *sbs; |
| 178 | struct acpi_battery_info info; | 91 | #ifdef CONFIG_ACPI_PROCFS |
| 179 | struct acpi_battery_state state; | 92 | struct proc_dir_entry *proc_entry; |
| 180 | struct acpi_battery_alarm alarm; | 93 | #endif |
| 181 | struct proc_dir_entry *battery_entry; | 94 | unsigned long update_time; |
| 95 | char name[8]; | ||
| 96 | char manufacturer_name[ACPI_SBS_BLOCK_MAX]; | ||
| 97 | char device_name[ACPI_SBS_BLOCK_MAX]; | ||
| 98 | char device_chemistry[ACPI_SBS_BLOCK_MAX]; | ||
| 99 | u16 alarm_capacity; | ||
| 100 | u16 full_charge_capacity; | ||
| 101 | u16 design_capacity; | ||
| 102 | u16 design_voltage; | ||
| 103 | u16 serial_number; | ||
| 104 | u16 cycle_count; | ||
| 105 | u16 temp_now; | ||
| 106 | u16 voltage_now; | ||
| 107 | s16 current_now; | ||
| 108 | s16 current_avg; | ||
| 109 | u16 capacity_now; | ||
| 110 | u16 state_of_charge; | ||
| 111 | u16 state; | ||
| 112 | u16 mode; | ||
| 113 | u16 spec; | ||
| 114 | u8 id; | ||
| 115 | u8 present:1; | ||
| 182 | }; | 116 | }; |
| 183 | 117 | ||
| 118 | #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat); | ||
| 119 | |||
| 184 | struct acpi_sbs { | 120 | struct acpi_sbs { |
| 185 | int base; | 121 | struct power_supply charger; |
| 186 | struct acpi_device *device; | 122 | struct acpi_device *device; |
| 187 | struct mutex mutex; | 123 | struct acpi_smb_hc *hc; |
| 188 | int sbsm_present; | 124 | struct mutex lock; |
| 189 | int sbsm_batteries_supported; | 125 | #ifdef CONFIG_ACPI_PROCFS |
| 190 | struct proc_dir_entry *ac_entry; | 126 | struct proc_dir_entry *charger_entry; |
| 191 | struct acpi_ac ac; | 127 | #endif |
| 192 | struct acpi_battery battery[MAX_SBS_BAT]; | 128 | struct acpi_battery battery[MAX_SBS_BAT]; |
| 193 | int zombie; | 129 | u8 batteries_supported:4; |
| 194 | struct timer_list update_timer; | 130 | u8 manager_present:1; |
| 195 | int run_cnt; | 131 | u8 charger_present:1; |
| 196 | int update_proc_flg; | ||
| 197 | }; | 132 | }; |
| 198 | 133 | ||
| 199 | static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type); | 134 | #define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger) |
| 200 | static void acpi_sbs_update_time(void *data); | ||
| 201 | 135 | ||
| 202 | union sbs_rw_data { | 136 | static inline int battery_scale(int log) |
| 203 | u16 word; | ||
| 204 | u8 block[ACPI_SBS_BLOCK_MAX + 2]; | ||
| 205 | }; | ||
| 206 | |||
| 207 | static int acpi_ec_sbs_access(struct acpi_sbs *sbs, u16 addr, | ||
| 208 | char read_write, u8 command, int size, | ||
| 209 | union sbs_rw_data *data); | ||
| 210 | |||
| 211 | /* -------------------------------------------------------------------------- | ||
| 212 | SMBus Communication | ||
| 213 | -------------------------------------------------------------------------- */ | ||
| 214 | |||
| 215 | static int acpi_ec_sbs_read(struct acpi_sbs *sbs, u8 address, u8 * data) | ||
| 216 | { | 137 | { |
| 217 | u8 val; | 138 | int scale = 1; |
| 218 | int err; | 139 | while (log--) |
| 219 | 140 | scale *= 10; | |
| 220 | err = ec_read(sbs->base + address, &val); | 141 | return scale; |
| 221 | if (!err) { | ||
| 222 | *data = val; | ||
| 223 | } | ||
| 224 | xmsleep(ACPI_EC_SMB_TRANSACTION_SLEEP); | ||
| 225 | return (err); | ||
| 226 | } | ||
| 227 | |||
| 228 | static int acpi_ec_sbs_write(struct acpi_sbs *sbs, u8 address, u8 data) | ||
| 229 | { | ||
| 230 | int err; | ||
| 231 | |||
| 232 | err = ec_write(sbs->base + address, data); | ||
| 233 | return (err); | ||
| 234 | } | ||
| 235 | |||
| 236 | static int | ||
| 237 | acpi_ec_sbs_access(struct acpi_sbs *sbs, u16 addr, | ||
| 238 | char read_write, u8 command, int size, | ||
| 239 | union sbs_rw_data *data) | ||
| 240 | { | ||
| 241 | unsigned char protocol, len = 0, temp[2] = { 0, 0 }; | ||
| 242 | int i; | ||
| 243 | |||
| 244 | if (read_write == ACPI_SBS_SMBUS_READ) { | ||
| 245 | protocol = ACPI_EC_SMB_PRTCL_READ; | ||
| 246 | } else { | ||
| 247 | protocol = ACPI_EC_SMB_PRTCL_WRITE; | ||
| 248 | } | ||
| 249 | |||
| 250 | switch (size) { | ||
| 251 | |||
| 252 | case ACPI_SBS_WORD_DATA: | ||
| 253 | acpi_ec_sbs_write(sbs, ACPI_EC_SMB_CMD, command); | ||
| 254 | if (read_write == ACPI_SBS_SMBUS_WRITE) { | ||
| 255 | acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA, data->word); | ||
| 256 | acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA + 1, | ||
| 257 | data->word >> 8); | ||
| 258 | } | ||
| 259 | protocol |= ACPI_EC_SMB_PRTCL_WORD_DATA; | ||
| 260 | break; | ||
| 261 | case ACPI_SBS_BLOCK_DATA: | ||
| 262 | acpi_ec_sbs_write(sbs, ACPI_EC_SMB_CMD, command); | ||
| 263 | if (read_write == ACPI_SBS_SMBUS_WRITE) { | ||
| 264 | len = min_t(u8, data->block[0], 32); | ||
| 265 | acpi_ec_sbs_write(sbs, ACPI_EC_SMB_BCNT, len); | ||
| 266 | for (i = 0; i < len; i++) | ||
| 267 | acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA + i, | ||
| 268 | data->block[i + 1]); | ||
| 269 | } | ||
| 270 | protocol |= ACPI_EC_SMB_PRTCL_BLOCK_DATA; | ||
| 271 | break; | ||
| 272 | default: | ||
| 273 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 274 | "unsupported transaction %d", size)); | ||
| 275 | return (-1); | ||
| 276 | } | ||
| 277 | |||
| 278 | acpi_ec_sbs_write(sbs, ACPI_EC_SMB_ADDR, addr << 1); | ||
| 279 | acpi_ec_sbs_write(sbs, ACPI_EC_SMB_PRTCL, protocol); | ||
| 280 | |||
| 281 | acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp); | ||
| 282 | |||
| 283 | if (~temp[0] & ACPI_EC_SMB_STS_DONE) { | ||
| 284 | xmsleep(ACPI_EC_SMB_ACCESS_SLEEP1); | ||
| 285 | acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp); | ||
| 286 | } | ||
| 287 | if (~temp[0] & ACPI_EC_SMB_STS_DONE) { | ||
| 288 | xmsleep(ACPI_EC_SMB_ACCESS_SLEEP2); | ||
| 289 | acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp); | ||
| 290 | } | ||
| 291 | if ((~temp[0] & ACPI_EC_SMB_STS_DONE) | ||
| 292 | || (temp[0] & ACPI_EC_SMB_STS_STATUS)) { | ||
| 293 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 294 | "transaction %d error", size)); | ||
| 295 | return (-1); | ||
| 296 | } | ||
| 297 | |||
| 298 | if (read_write == ACPI_SBS_SMBUS_WRITE) { | ||
| 299 | return (0); | ||
| 300 | } | ||
| 301 | |||
| 302 | switch (size) { | ||
| 303 | |||
| 304 | case ACPI_SBS_WORD_DATA: | ||
| 305 | acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA, temp); | ||
| 306 | acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA + 1, temp + 1); | ||
| 307 | data->word = (temp[1] << 8) | temp[0]; | ||
| 308 | break; | ||
| 309 | |||
| 310 | case ACPI_SBS_BLOCK_DATA: | ||
| 311 | len = 0; | ||
| 312 | acpi_ec_sbs_read(sbs, ACPI_EC_SMB_BCNT, &len); | ||
| 313 | len = min_t(u8, len, 32); | ||
| 314 | for (i = 0; i < len; i++) | ||
| 315 | acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA + i, | ||
| 316 | data->block + i + 1); | ||
| 317 | data->block[0] = len; | ||
| 318 | break; | ||
| 319 | default: | ||
| 320 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 321 | "unsupported transaction %d", size)); | ||
| 322 | return (-1); | ||
| 323 | } | ||
| 324 | |||
| 325 | return (0); | ||
| 326 | } | 142 | } |
| 327 | 143 | ||
| 328 | static int | 144 | static inline int acpi_battery_vscale(struct acpi_battery *battery) |
| 329 | acpi_sbs_read_word(struct acpi_sbs *sbs, int addr, int func, u16 * word) | ||
| 330 | { | 145 | { |
| 331 | union sbs_rw_data data; | 146 | return battery_scale((battery->spec & 0x0f00) >> 8); |
| 332 | int result = 0; | ||
| 333 | |||
| 334 | result = acpi_ec_sbs_access(sbs, addr, | ||
| 335 | ACPI_SBS_SMBUS_READ, func, | ||
| 336 | ACPI_SBS_WORD_DATA, &data); | ||
| 337 | if (result) { | ||
| 338 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 339 | "acpi_ec_sbs_access() failed")); | ||
| 340 | } else { | ||
| 341 | *word = data.word; | ||
| 342 | } | ||
| 343 | |||
| 344 | return result; | ||
| 345 | } | 147 | } |
| 346 | 148 | ||
| 347 | static int | 149 | static inline int acpi_battery_ipscale(struct acpi_battery *battery) |
| 348 | acpi_sbs_read_str(struct acpi_sbs *sbs, int addr, int func, char *str) | ||
| 349 | { | 150 | { |
| 350 | union sbs_rw_data data; | 151 | return battery_scale((battery->spec & 0xf000) >> 12); |
| 351 | int result = 0; | ||
| 352 | |||
| 353 | result = acpi_ec_sbs_access(sbs, addr, | ||
| 354 | ACPI_SBS_SMBUS_READ, func, | ||
| 355 | ACPI_SBS_BLOCK_DATA, &data); | ||
| 356 | if (result) { | ||
| 357 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 358 | "acpi_ec_sbs_access() failed")); | ||
| 359 | } else { | ||
| 360 | strncpy(str, (const char *)data.block + 1, data.block[0]); | ||
| 361 | str[data.block[0]] = 0; | ||
| 362 | } | ||
| 363 | |||
| 364 | return result; | ||
| 365 | } | 152 | } |
| 366 | 153 | ||
| 367 | static int | 154 | static inline int acpi_battery_mode(struct acpi_battery *battery) |
| 368 | acpi_sbs_write_word(struct acpi_sbs *sbs, int addr, int func, int word) | ||
| 369 | { | 155 | { |
| 370 | union sbs_rw_data data; | 156 | return (battery->mode & 0x8000); |
| 371 | int result = 0; | ||
| 372 | |||
| 373 | data.word = word; | ||
| 374 | |||
| 375 | result = acpi_ec_sbs_access(sbs, addr, | ||
| 376 | ACPI_SBS_SMBUS_WRITE, func, | ||
| 377 | ACPI_SBS_WORD_DATA, &data); | ||
| 378 | if (result) { | ||
| 379 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 380 | "acpi_ec_sbs_access() failed")); | ||
| 381 | } | ||
| 382 | |||
| 383 | return result; | ||
| 384 | } | 157 | } |
| 385 | 158 | ||
| 386 | static int sbs_zombie(struct acpi_sbs *sbs) | 159 | static inline int acpi_battery_scale(struct acpi_battery *battery) |
| 387 | { | 160 | { |
| 388 | return (sbs->zombie); | 161 | return (acpi_battery_mode(battery) ? 10 : 1) * |
| 162 | acpi_battery_ipscale(battery); | ||
| 389 | } | 163 | } |
| 390 | 164 | ||
| 391 | static int sbs_mutex_lock(struct acpi_sbs *sbs) | 165 | static int sbs_get_ac_property(struct power_supply *psy, |
| 166 | enum power_supply_property psp, | ||
| 167 | union power_supply_propval *val) | ||
| 392 | { | 168 | { |
| 393 | if (sbs_zombie(sbs)) { | 169 | struct acpi_sbs *sbs = to_acpi_sbs(psy); |
| 394 | return -ENODEV; | 170 | switch (psp) { |
| 171 | case POWER_SUPPLY_PROP_ONLINE: | ||
| 172 | val->intval = sbs->charger_present; | ||
| 173 | break; | ||
| 174 | default: | ||
| 175 | return -EINVAL; | ||
| 395 | } | 176 | } |
| 396 | mutex_lock(&sbs->mutex); | ||
| 397 | return 0; | 177 | return 0; |
| 398 | } | 178 | } |
| 399 | 179 | ||
| 400 | static void sbs_mutex_unlock(struct acpi_sbs *sbs) | 180 | static int acpi_battery_technology(struct acpi_battery *battery) |
| 401 | { | 181 | { |
| 402 | mutex_unlock(&sbs->mutex); | 182 | if (!strcasecmp("NiCd", battery->device_chemistry)) |
| 183 | return POWER_SUPPLY_TECHNOLOGY_NiCd; | ||
| 184 | if (!strcasecmp("NiMH", battery->device_chemistry)) | ||
| 185 | return POWER_SUPPLY_TECHNOLOGY_NiMH; | ||
| 186 | if (!strcasecmp("LION", battery->device_chemistry)) | ||
| 187 | return POWER_SUPPLY_TECHNOLOGY_LION; | ||
| 188 | if (!strcasecmp("LiP", battery->device_chemistry)) | ||
| 189 | return POWER_SUPPLY_TECHNOLOGY_LIPO; | ||
| 190 | return POWER_SUPPLY_TECHNOLOGY_UNKNOWN; | ||
| 403 | } | 191 | } |
| 404 | 192 | ||
| 405 | /* -------------------------------------------------------------------------- | 193 | static int acpi_sbs_battery_get_property(struct power_supply *psy, |
| 406 | Smart Battery System Management | 194 | enum power_supply_property psp, |
| 407 | -------------------------------------------------------------------------- */ | 195 | union power_supply_propval *val) |
| 408 | |||
| 409 | static int acpi_check_update_proc(struct acpi_sbs *sbs) | ||
| 410 | { | 196 | { |
| 411 | acpi_status status = AE_OK; | 197 | struct acpi_battery *battery = to_acpi_battery(psy); |
| 412 | 198 | ||
| 413 | if (update_time == 0) { | 199 | if ((!battery->present) && psp != POWER_SUPPLY_PROP_PRESENT) |
| 414 | sbs->update_proc_flg = 0; | 200 | return -ENODEV; |
| 415 | return 0; | 201 | switch (psp) { |
| 416 | } | 202 | case POWER_SUPPLY_PROP_STATUS: |
| 417 | if (sbs->update_proc_flg == 0) { | 203 | if (battery->current_now < 0) |
| 418 | status = acpi_os_execute(OSL_GPE_HANDLER, | 204 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; |
| 419 | acpi_sbs_update_time, sbs); | 205 | else if (battery->current_now > 0) |
| 420 | if (status != AE_OK) { | 206 | val->intval = POWER_SUPPLY_STATUS_CHARGING; |
| 421 | ACPI_EXCEPTION((AE_INFO, status, | 207 | else |
| 422 | "acpi_os_execute() failed")); | 208 | val->intval = POWER_SUPPLY_STATUS_FULL; |
| 423 | return 1; | 209 | break; |
| 424 | } | 210 | case POWER_SUPPLY_PROP_PRESENT: |
| 425 | sbs->update_proc_flg = 1; | 211 | val->intval = battery->present; |
| 212 | break; | ||
| 213 | case POWER_SUPPLY_PROP_TECHNOLOGY: | ||
| 214 | val->intval = acpi_battery_technology(battery); | ||
| 215 | break; | ||
| 216 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: | ||
| 217 | val->intval = battery->design_voltage * | ||
| 218 | acpi_battery_vscale(battery) * 1000; | ||
| 219 | break; | ||
| 220 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
| 221 | val->intval = battery->voltage_now * | ||
| 222 | acpi_battery_vscale(battery) * 1000; | ||
| 223 | break; | ||
| 224 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
| 225 | val->intval = abs(battery->current_now) * | ||
| 226 | acpi_battery_ipscale(battery) * 1000; | ||
| 227 | break; | ||
| 228 | case POWER_SUPPLY_PROP_CURRENT_AVG: | ||
| 229 | val->intval = abs(battery->current_avg) * | ||
| 230 | acpi_battery_ipscale(battery) * 1000; | ||
| 231 | break; | ||
| 232 | case POWER_SUPPLY_PROP_CAPACITY: | ||
| 233 | val->intval = battery->state_of_charge; | ||
| 234 | break; | ||
| 235 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | ||
| 236 | case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: | ||
| 237 | val->intval = battery->design_capacity * | ||
| 238 | acpi_battery_scale(battery) * 1000; | ||
| 239 | break; | ||
| 240 | case POWER_SUPPLY_PROP_CHARGE_FULL: | ||
| 241 | case POWER_SUPPLY_PROP_ENERGY_FULL: | ||
| 242 | val->intval = battery->full_charge_capacity * | ||
| 243 | acpi_battery_scale(battery) * 1000; | ||
| 244 | break; | ||
| 245 | case POWER_SUPPLY_PROP_CHARGE_NOW: | ||
| 246 | case POWER_SUPPLY_PROP_ENERGY_NOW: | ||
| 247 | val->intval = battery->capacity_now * | ||
| 248 | acpi_battery_scale(battery) * 1000; | ||
| 249 | break; | ||
| 250 | case POWER_SUPPLY_PROP_TEMP: | ||
| 251 | val->intval = battery->temp_now - 2730; // dK -> dC | ||
| 252 | break; | ||
| 253 | case POWER_SUPPLY_PROP_MODEL_NAME: | ||
| 254 | val->strval = battery->device_name; | ||
| 255 | break; | ||
| 256 | case POWER_SUPPLY_PROP_MANUFACTURER: | ||
| 257 | val->strval = battery->manufacturer_name; | ||
| 258 | break; | ||
| 259 | default: | ||
| 260 | return -EINVAL; | ||
| 426 | } | 261 | } |
| 427 | return 0; | 262 | return 0; |
| 428 | } | 263 | } |
| 429 | 264 | ||
| 430 | static int acpi_sbs_generate_event(struct acpi_device *device, | 265 | static enum power_supply_property sbs_ac_props[] = { |
| 431 | int event, int state, char *bid, char *class) | 266 | POWER_SUPPLY_PROP_ONLINE, |
| 432 | { | 267 | }; |
| 433 | char bid_saved[5]; | ||
| 434 | char class_saved[20]; | ||
| 435 | int result = 0; | ||
| 436 | |||
| 437 | strcpy(bid_saved, acpi_device_bid(device)); | ||
| 438 | strcpy(class_saved, acpi_device_class(device)); | ||
| 439 | |||
| 440 | strcpy(acpi_device_bid(device), bid); | ||
| 441 | strcpy(acpi_device_class(device), class); | ||
| 442 | |||
| 443 | result = acpi_bus_generate_proc_event(device, event, state); | ||
| 444 | |||
| 445 | strcpy(acpi_device_bid(device), bid_saved); | ||
| 446 | strcpy(acpi_device_class(device), class_saved); | ||
| 447 | |||
| 448 | acpi_bus_generate_netlink_event(class, bid, event, state); | ||
| 449 | return result; | ||
| 450 | } | ||
| 451 | |||
| 452 | static int acpi_battery_get_present(struct acpi_battery *battery) | ||
| 453 | { | ||
| 454 | s16 state; | ||
| 455 | int result = 0; | ||
| 456 | int is_present = 0; | ||
| 457 | |||
| 458 | result = acpi_sbs_read_word(battery->sbs, | ||
| 459 | ACPI_SBSM_SMBUS_ADDR, 0x01, &state); | ||
| 460 | if (result) { | ||
| 461 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 462 | "acpi_sbs_read_word() failed")); | ||
| 463 | } | ||
| 464 | if (!result) { | ||
| 465 | is_present = (state & 0x000f) & (1 << battery->id); | ||
| 466 | } | ||
| 467 | battery->battery_present = is_present; | ||
| 468 | |||
| 469 | return result; | ||
| 470 | } | ||
| 471 | 268 | ||
| 472 | static int acpi_battery_select(struct acpi_battery *battery) | 269 | static enum power_supply_property sbs_charge_battery_props[] = { |
| 473 | { | 270 | POWER_SUPPLY_PROP_STATUS, |
| 474 | struct acpi_sbs *sbs = battery->sbs; | 271 | POWER_SUPPLY_PROP_PRESENT, |
| 475 | int result = 0; | 272 | POWER_SUPPLY_PROP_TECHNOLOGY, |
| 476 | s16 state; | 273 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, |
| 477 | int foo; | 274 | POWER_SUPPLY_PROP_VOLTAGE_NOW, |
| 275 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
| 276 | POWER_SUPPLY_PROP_CURRENT_AVG, | ||
| 277 | POWER_SUPPLY_PROP_CAPACITY, | ||
| 278 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
| 279 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
| 280 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
| 281 | POWER_SUPPLY_PROP_TEMP, | ||
| 282 | POWER_SUPPLY_PROP_MODEL_NAME, | ||
| 283 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
| 284 | }; | ||
| 478 | 285 | ||
| 479 | if (sbs->sbsm_present) { | 286 | static enum power_supply_property sbs_energy_battery_props[] = { |
| 287 | POWER_SUPPLY_PROP_STATUS, | ||
| 288 | POWER_SUPPLY_PROP_PRESENT, | ||
| 289 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
| 290 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, | ||
| 291 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
| 292 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
| 293 | POWER_SUPPLY_PROP_CURRENT_AVG, | ||
| 294 | POWER_SUPPLY_PROP_CAPACITY, | ||
| 295 | POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, | ||
| 296 | POWER_SUPPLY_PROP_ENERGY_FULL, | ||
| 297 | POWER_SUPPLY_PROP_ENERGY_NOW, | ||
| 298 | POWER_SUPPLY_PROP_TEMP, | ||
| 299 | POWER_SUPPLY_PROP_MODEL_NAME, | ||
| 300 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
| 301 | }; | ||
| 480 | 302 | ||
| 481 | /* Take special care not to knobble other nibbles of | 303 | /* -------------------------------------------------------------------------- |
| 482 | * state (aka selector_state), since | 304 | Smart Battery System Management |
| 483 | * it causes charging to halt on SBSELs */ | 305 | -------------------------------------------------------------------------- */ |
| 484 | 306 | ||
| 485 | result = | 307 | struct acpi_battery_reader { |
| 486 | acpi_sbs_read_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x01, &state); | 308 | u8 command; /* command for battery */ |
| 487 | if (result) { | 309 | u8 mode; /* word or block? */ |
| 488 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 310 | size_t offset; /* offset inside struct acpi_sbs_battery */ |
| 489 | "acpi_sbs_read_word() failed")); | 311 | }; |
| 490 | goto end; | ||
| 491 | } | ||
| 492 | 312 | ||
| 493 | foo = (state & 0x0fff) | (1 << (battery->id + 12)); | 313 | static struct acpi_battery_reader info_readers[] = { |
| 494 | result = | 314 | {0x01, SMBUS_READ_WORD, offsetof(struct acpi_battery, alarm_capacity)}, |
| 495 | acpi_sbs_write_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x01, foo); | 315 | {0x03, SMBUS_READ_WORD, offsetof(struct acpi_battery, mode)}, |
| 496 | if (result) { | 316 | {0x10, SMBUS_READ_WORD, offsetof(struct acpi_battery, full_charge_capacity)}, |
| 497 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 317 | {0x17, SMBUS_READ_WORD, offsetof(struct acpi_battery, cycle_count)}, |
| 498 | "acpi_sbs_write_word() failed")); | 318 | {0x18, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_capacity)}, |
| 499 | goto end; | 319 | {0x19, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_voltage)}, |
| 500 | } | 320 | {0x1a, SMBUS_READ_WORD, offsetof(struct acpi_battery, spec)}, |
| 501 | } | 321 | {0x1c, SMBUS_READ_WORD, offsetof(struct acpi_battery, serial_number)}, |
| 322 | {0x20, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, manufacturer_name)}, | ||
| 323 | {0x21, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_name)}, | ||
| 324 | {0x22, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_chemistry)}, | ||
| 325 | }; | ||
| 502 | 326 | ||
| 503 | end: | 327 | static struct acpi_battery_reader state_readers[] = { |
| 504 | return result; | 328 | {0x08, SMBUS_READ_WORD, offsetof(struct acpi_battery, temp_now)}, |
| 505 | } | 329 | {0x09, SMBUS_READ_WORD, offsetof(struct acpi_battery, voltage_now)}, |
| 330 | {0x0a, SMBUS_READ_WORD, offsetof(struct acpi_battery, current_now)}, | ||
| 331 | {0x0b, SMBUS_READ_WORD, offsetof(struct acpi_battery, current_avg)}, | ||
| 332 | {0x0f, SMBUS_READ_WORD, offsetof(struct acpi_battery, capacity_now)}, | ||
| 333 | {0x0e, SMBUS_READ_WORD, offsetof(struct acpi_battery, state_of_charge)}, | ||
| 334 | {0x16, SMBUS_READ_WORD, offsetof(struct acpi_battery, state)}, | ||
| 335 | }; | ||
| 506 | 336 | ||
| 507 | static int acpi_sbsm_get_info(struct acpi_sbs *sbs) | 337 | static int acpi_manager_get_info(struct acpi_sbs *sbs) |
| 508 | { | 338 | { |
| 509 | int result = 0; | 339 | int result = 0; |
| 510 | s16 battery_system_info; | 340 | u16 battery_system_info; |
| 511 | |||
| 512 | result = acpi_sbs_read_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x04, | ||
| 513 | &battery_system_info); | ||
| 514 | if (result) { | ||
| 515 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 516 | "acpi_sbs_read_word() failed")); | ||
| 517 | goto end; | ||
| 518 | } | ||
| 519 | sbs->sbsm_present = 1; | ||
| 520 | sbs->sbsm_batteries_supported = battery_system_info & 0x000f; | ||
| 521 | |||
| 522 | end: | ||
| 523 | 341 | ||
| 342 | result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER, | ||
| 343 | 0x04, (u8 *)&battery_system_info); | ||
| 344 | if (!result) | ||
| 345 | sbs->batteries_supported = battery_system_info & 0x000f; | ||
| 524 | return result; | 346 | return result; |
| 525 | } | 347 | } |
| 526 | 348 | ||
| 527 | static int acpi_battery_get_info(struct acpi_battery *battery) | 349 | static int acpi_battery_get_info(struct acpi_battery *battery) |
| 528 | { | 350 | { |
| 529 | struct acpi_sbs *sbs = battery->sbs; | 351 | int i, result = 0; |
| 530 | int result = 0; | 352 | |
| 531 | s16 battery_mode; | 353 | for (i = 0; i < ARRAY_SIZE(info_readers); ++i) { |
| 532 | s16 specification_info; | 354 | result = acpi_smbus_read(battery->sbs->hc, |
| 533 | 355 | info_readers[i].mode, | |
| 534 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x03, | 356 | ACPI_SBS_BATTERY, |
| 535 | &battery_mode); | 357 | info_readers[i].command, |
| 536 | if (result) { | 358 | (u8 *) battery + |
| 537 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 359 | info_readers[i].offset); |
| 538 | "acpi_sbs_read_word() failed")); | 360 | if (result) |
| 539 | goto end; | 361 | break; |
| 540 | } | ||
| 541 | battery->info.capacity_mode = (battery_mode & 0x8000) >> 15; | ||
| 542 | |||
| 543 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x10, | ||
| 544 | &battery->info.full_charge_capacity); | ||
| 545 | if (result) { | ||
| 546 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 547 | "acpi_sbs_read_word() failed")); | ||
| 548 | goto end; | ||
| 549 | } | ||
| 550 | |||
| 551 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x18, | ||
| 552 | &battery->info.design_capacity); | ||
| 553 | |||
| 554 | if (result) { | ||
| 555 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 556 | "acpi_sbs_read_word() failed")); | ||
| 557 | goto end; | ||
| 558 | } | ||
| 559 | |||
| 560 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x19, | ||
| 561 | &battery->info.design_voltage); | ||
| 562 | if (result) { | ||
| 563 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 564 | "acpi_sbs_read_word() failed")); | ||
| 565 | goto end; | ||
| 566 | } | 362 | } |
| 567 | |||
| 568 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x1a, | ||
| 569 | &specification_info); | ||
| 570 | if (result) { | ||
| 571 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 572 | "acpi_sbs_read_word() failed")); | ||
| 573 | goto end; | ||
| 574 | } | ||
| 575 | |||
| 576 | switch ((specification_info & 0x0f00) >> 8) { | ||
| 577 | case 1: | ||
| 578 | battery->info.vscale = 10; | ||
| 579 | break; | ||
| 580 | case 2: | ||
| 581 | battery->info.vscale = 100; | ||
| 582 | break; | ||
| 583 | case 3: | ||
| 584 | battery->info.vscale = 1000; | ||
| 585 | break; | ||
| 586 | default: | ||
| 587 | battery->info.vscale = 1; | ||
| 588 | } | ||
| 589 | |||
| 590 | switch ((specification_info & 0xf000) >> 12) { | ||
| 591 | case 1: | ||
| 592 | battery->info.ipscale = 10; | ||
| 593 | break; | ||
| 594 | case 2: | ||
| 595 | battery->info.ipscale = 100; | ||
| 596 | break; | ||
| 597 | case 3: | ||
| 598 | battery->info.ipscale = 1000; | ||
| 599 | break; | ||
| 600 | default: | ||
| 601 | battery->info.ipscale = 1; | ||
| 602 | } | ||
| 603 | |||
| 604 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x1c, | ||
| 605 | &battery->info.serial_number); | ||
| 606 | if (result) { | ||
| 607 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 608 | "acpi_sbs_read_word() failed")); | ||
| 609 | goto end; | ||
| 610 | } | ||
| 611 | |||
| 612 | result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x20, | ||
| 613 | battery->info.manufacturer_name); | ||
| 614 | if (result) { | ||
| 615 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 616 | "acpi_sbs_read_str() failed")); | ||
| 617 | goto end; | ||
| 618 | } | ||
| 619 | |||
| 620 | result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x21, | ||
| 621 | battery->info.device_name); | ||
| 622 | if (result) { | ||
| 623 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 624 | "acpi_sbs_read_str() failed")); | ||
| 625 | goto end; | ||
| 626 | } | ||
| 627 | |||
| 628 | result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x22, | ||
| 629 | battery->info.device_chemistry); | ||
| 630 | if (result) { | ||
| 631 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 632 | "acpi_sbs_read_str() failed")); | ||
| 633 | goto end; | ||
| 634 | } | ||
| 635 | |||
| 636 | end: | ||
| 637 | return result; | 363 | return result; |
| 638 | } | 364 | } |
| 639 | 365 | ||
| 640 | static int acpi_battery_get_state(struct acpi_battery *battery) | 366 | static int acpi_battery_get_state(struct acpi_battery *battery) |
| 641 | { | 367 | { |
| 642 | struct acpi_sbs *sbs = battery->sbs; | 368 | int i, result = 0; |
| 643 | int result = 0; | ||
| 644 | 369 | ||
| 645 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x09, | 370 | if (battery->update_time && |
| 646 | &battery->state.voltage); | 371 | time_before(jiffies, battery->update_time + |
| 647 | if (result) { | 372 | msecs_to_jiffies(cache_time))) |
| 648 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 373 | return 0; |
| 649 | "acpi_sbs_read_word() failed")); | 374 | for (i = 0; i < ARRAY_SIZE(state_readers); ++i) { |
| 650 | goto end; | 375 | result = acpi_smbus_read(battery->sbs->hc, |
| 651 | } | 376 | state_readers[i].mode, |
| 652 | 377 | ACPI_SBS_BATTERY, | |
| 653 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x0a, | 378 | state_readers[i].command, |
| 654 | &battery->state.amperage); | 379 | (u8 *)battery + |
| 655 | if (result) { | 380 | state_readers[i].offset); |
| 656 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 381 | if (result) |
| 657 | "acpi_sbs_read_word() failed")); | 382 | goto end; |
| 658 | goto end; | ||
| 659 | } | ||
| 660 | |||
| 661 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x0f, | ||
| 662 | &battery->state.remaining_capacity); | ||
| 663 | if (result) { | ||
| 664 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 665 | "acpi_sbs_read_word() failed")); | ||
| 666 | goto end; | ||
| 667 | } | ||
| 668 | |||
| 669 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x16, | ||
| 670 | &battery->state.battery_state); | ||
| 671 | if (result) { | ||
| 672 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 673 | "acpi_sbs_read_word() failed")); | ||
| 674 | goto end; | ||
| 675 | } | 383 | } |
| 676 | |||
| 677 | end: | 384 | end: |
| 385 | battery->update_time = jiffies; | ||
| 678 | return result; | 386 | return result; |
| 679 | } | 387 | } |
| 680 | 388 | ||
| 681 | static int acpi_battery_get_alarm(struct acpi_battery *battery) | 389 | static int acpi_battery_get_alarm(struct acpi_battery *battery) |
| 682 | { | 390 | { |
| 683 | struct acpi_sbs *sbs = battery->sbs; | 391 | return acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, |
| 684 | int result = 0; | 392 | ACPI_SBS_BATTERY, 0x01, |
| 685 | 393 | (u8 *)&battery->alarm_capacity); | |
| 686 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01, | ||
| 687 | &battery->alarm.remaining_capacity); | ||
| 688 | if (result) { | ||
| 689 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 690 | "acpi_sbs_read_word() failed")); | ||
| 691 | goto end; | ||
| 692 | } | ||
| 693 | |||
| 694 | end: | ||
| 695 | |||
| 696 | return result; | ||
| 697 | } | 394 | } |
| 698 | 395 | ||
| 699 | static int acpi_battery_set_alarm(struct acpi_battery *battery, | 396 | static int acpi_battery_set_alarm(struct acpi_battery *battery) |
| 700 | unsigned long alarm) | ||
| 701 | { | 397 | { |
| 702 | struct acpi_sbs *sbs = battery->sbs; | 398 | struct acpi_sbs *sbs = battery->sbs; |
| 703 | int result = 0; | 399 | u16 value, sel = 1 << (battery->id + 12); |
| 704 | s16 battery_mode; | ||
| 705 | int foo; | ||
| 706 | 400 | ||
| 707 | result = acpi_battery_select(battery); | 401 | int ret; |
| 708 | if (result) { | ||
| 709 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 710 | "acpi_battery_select() failed")); | ||
| 711 | goto end; | ||
| 712 | } | ||
| 713 | 402 | ||
| 714 | /* If necessary, enable the alarm */ | ||
| 715 | 403 | ||
| 716 | if (alarm > 0) { | 404 | if (sbs->manager_present) { |
| 717 | result = | 405 | ret = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER, |
| 718 | acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x03, | 406 | 0x01, (u8 *)&value); |
| 719 | &battery_mode); | 407 | if (ret) |
| 720 | if (result) { | ||
| 721 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 722 | "acpi_sbs_read_word() failed")); | ||
| 723 | goto end; | 408 | goto end; |
| 724 | } | 409 | if ((value & 0xf000) != sel) { |
| 725 | 410 | value &= 0x0fff; | |
| 726 | result = | 411 | value |= sel; |
| 727 | acpi_sbs_write_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01, | 412 | ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, |
| 728 | battery_mode & 0xbfff); | 413 | ACPI_SBS_MANAGER, |
| 729 | if (result) { | 414 | 0x01, (u8 *)&value, 2); |
| 730 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 415 | if (ret) |
| 731 | "acpi_sbs_write_word() failed")); | ||
| 732 | goto end; | 416 | goto end; |
| 733 | } | 417 | } |
| 734 | } | 418 | } |
| 735 | 419 | ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, | |
| 736 | foo = alarm / (battery->info.capacity_mode ? 10 : 1); | 420 | 0x01, (u8 *)&battery->alarm_capacity, 2); |
| 737 | result = acpi_sbs_write_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01, foo); | ||
| 738 | if (result) { | ||
| 739 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 740 | "acpi_sbs_write_word() failed")); | ||
| 741 | goto end; | ||
| 742 | } | ||
| 743 | |||
| 744 | end: | 421 | end: |
| 745 | 422 | return ret; | |
| 746 | return result; | ||
| 747 | } | 423 | } |
| 748 | 424 | ||
| 749 | static int acpi_battery_set_mode(struct acpi_battery *battery) | 425 | static int acpi_ac_get_present(struct acpi_sbs *sbs) |
| 750 | { | 426 | { |
| 751 | struct acpi_sbs *sbs = battery->sbs; | 427 | int result; |
| 752 | int result = 0; | 428 | u16 status; |
| 753 | s16 battery_mode; | ||
| 754 | |||
| 755 | if (capacity_mode == DEF_CAPACITY_UNIT) { | ||
| 756 | goto end; | ||
| 757 | } | ||
| 758 | |||
| 759 | result = acpi_sbs_read_word(sbs, | ||
| 760 | ACPI_SB_SMBUS_ADDR, 0x03, &battery_mode); | ||
| 761 | if (result) { | ||
| 762 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 763 | "acpi_sbs_read_word() failed")); | ||
| 764 | goto end; | ||
| 765 | } | ||
| 766 | |||
| 767 | if (capacity_mode == MAH_CAPACITY_UNIT) { | ||
| 768 | battery_mode &= 0x7fff; | ||
| 769 | } else { | ||
| 770 | battery_mode |= 0x8000; | ||
| 771 | } | ||
| 772 | result = acpi_sbs_write_word(sbs, | ||
| 773 | ACPI_SB_SMBUS_ADDR, 0x03, battery_mode); | ||
| 774 | if (result) { | ||
| 775 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 776 | "acpi_sbs_write_word() failed")); | ||
| 777 | goto end; | ||
| 778 | } | ||
| 779 | |||
| 780 | result = acpi_sbs_read_word(sbs, | ||
| 781 | ACPI_SB_SMBUS_ADDR, 0x03, &battery_mode); | ||
| 782 | if (result) { | ||
| 783 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 784 | "acpi_sbs_read_word() failed")); | ||
| 785 | goto end; | ||
| 786 | } | ||
| 787 | 429 | ||
| 788 | end: | 430 | result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER, |
| 431 | 0x13, (u8 *) & status); | ||
| 432 | if (!result) | ||
| 433 | sbs->charger_present = (status >> 15) & 0x1; | ||
| 789 | return result; | 434 | return result; |
| 790 | } | 435 | } |
| 791 | 436 | ||
| 792 | static int acpi_battery_init(struct acpi_battery *battery) | 437 | static ssize_t acpi_battery_alarm_show(struct device *dev, |
| 438 | struct device_attribute *attr, | ||
| 439 | char *buf) | ||
| 793 | { | 440 | { |
| 794 | int result = 0; | 441 | struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); |
| 795 | 442 | acpi_battery_get_alarm(battery); | |
| 796 | result = acpi_battery_select(battery); | 443 | return sprintf(buf, "%d\n", battery->alarm_capacity * |
| 797 | if (result) { | 444 | acpi_battery_scale(battery) * 1000); |
| 798 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 799 | "acpi_battery_select() failed")); | ||
| 800 | goto end; | ||
| 801 | } | ||
| 802 | |||
| 803 | result = acpi_battery_set_mode(battery); | ||
| 804 | if (result) { | ||
| 805 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 806 | "acpi_battery_set_mode() failed")); | ||
| 807 | goto end; | ||
| 808 | } | ||
| 809 | |||
| 810 | result = acpi_battery_get_info(battery); | ||
| 811 | if (result) { | ||
| 812 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 813 | "acpi_battery_get_info() failed")); | ||
| 814 | goto end; | ||
| 815 | } | ||
| 816 | |||
| 817 | result = acpi_battery_get_state(battery); | ||
| 818 | if (result) { | ||
| 819 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 820 | "acpi_battery_get_state() failed")); | ||
| 821 | goto end; | ||
| 822 | } | ||
| 823 | |||
| 824 | result = acpi_battery_get_alarm(battery); | ||
| 825 | if (result) { | ||
| 826 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 827 | "acpi_battery_get_alarm() failed")); | ||
| 828 | goto end; | ||
| 829 | } | ||
| 830 | |||
| 831 | end: | ||
| 832 | return result; | ||
| 833 | } | 445 | } |
| 834 | 446 | ||
| 835 | static int acpi_ac_get_present(struct acpi_sbs *sbs) | 447 | static ssize_t acpi_battery_alarm_store(struct device *dev, |
| 448 | struct device_attribute *attr, | ||
| 449 | const char *buf, size_t count) | ||
| 836 | { | 450 | { |
| 837 | int result = 0; | 451 | unsigned long x; |
| 838 | s16 charger_status; | 452 | struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); |
| 839 | 453 | if (sscanf(buf, "%ld\n", &x) == 1) | |
| 840 | result = acpi_sbs_read_word(sbs, ACPI_SBC_SMBUS_ADDR, 0x13, | 454 | battery->alarm_capacity = x / |
| 841 | &charger_status); | 455 | (1000 * acpi_battery_scale(battery)); |
| 842 | 456 | if (battery->present) | |
| 843 | if (result) { | 457 | acpi_battery_set_alarm(battery); |
| 844 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 458 | return count; |
| 845 | "acpi_sbs_read_word() failed")); | ||
| 846 | goto end; | ||
| 847 | } | ||
| 848 | |||
| 849 | sbs->ac.ac_present = (charger_status & 0x8000) >> 15; | ||
| 850 | |||
| 851 | end: | ||
| 852 | |||
| 853 | return result; | ||
| 854 | } | 459 | } |
| 855 | 460 | ||
| 461 | static struct device_attribute alarm_attr = { | ||
| 462 | .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE}, | ||
| 463 | .show = acpi_battery_alarm_show, | ||
| 464 | .store = acpi_battery_alarm_store, | ||
| 465 | }; | ||
| 466 | |||
| 856 | /* -------------------------------------------------------------------------- | 467 | /* -------------------------------------------------------------------------- |
| 857 | FS Interface (/proc/acpi) | 468 | FS Interface (/proc/acpi) |
| 858 | -------------------------------------------------------------------------- */ | 469 | -------------------------------------------------------------------------- */ |
| 859 | 470 | ||
| 471 | #ifdef CONFIG_ACPI_PROCFS | ||
| 860 | /* Generic Routines */ | 472 | /* Generic Routines */ |
| 861 | |||
| 862 | static int | 473 | static int |
| 863 | acpi_sbs_generic_add_fs(struct proc_dir_entry **dir, | 474 | acpi_sbs_add_fs(struct proc_dir_entry **dir, |
| 864 | struct proc_dir_entry *parent_dir, | 475 | struct proc_dir_entry *parent_dir, |
| 865 | char *dir_name, | 476 | char *dir_name, |
| 866 | struct file_operations *info_fops, | 477 | struct file_operations *info_fops, |
| 867 | struct file_operations *state_fops, | 478 | struct file_operations *state_fops, |
| 868 | struct file_operations *alarm_fops, void *data) | 479 | struct file_operations *alarm_fops, void *data) |
| 869 | { | 480 | { |
| 870 | struct proc_dir_entry *entry = NULL; | 481 | struct proc_dir_entry *entry = NULL; |
| 871 | 482 | ||
| 872 | if (!*dir) { | 483 | if (!*dir) { |
| 873 | *dir = proc_mkdir(dir_name, parent_dir); | 484 | *dir = proc_mkdir(dir_name, parent_dir); |
| 874 | if (!*dir) { | 485 | if (!*dir) { |
| 875 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 876 | "proc_mkdir() failed")); | ||
| 877 | return -ENODEV; | 486 | return -ENODEV; |
| 878 | } | 487 | } |
| 879 | (*dir)->owner = THIS_MODULE; | 488 | (*dir)->owner = THIS_MODULE; |
| @@ -882,10 +491,7 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir, | |||
| 882 | /* 'info' [R] */ | 491 | /* 'info' [R] */ |
| 883 | if (info_fops) { | 492 | if (info_fops) { |
| 884 | entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir); | 493 | entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir); |
| 885 | if (!entry) { | 494 | if (entry) { |
| 886 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 887 | "create_proc_entry() failed")); | ||
| 888 | } else { | ||
| 889 | entry->proc_fops = info_fops; | 495 | entry->proc_fops = info_fops; |
| 890 | entry->data = data; | 496 | entry->data = data; |
| 891 | entry->owner = THIS_MODULE; | 497 | entry->owner = THIS_MODULE; |
| @@ -895,10 +501,7 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir, | |||
| 895 | /* 'state' [R] */ | 501 | /* 'state' [R] */ |
| 896 | if (state_fops) { | 502 | if (state_fops) { |
| 897 | entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir); | 503 | entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir); |
| 898 | if (!entry) { | 504 | if (entry) { |
| 899 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 900 | "create_proc_entry() failed")); | ||
| 901 | } else { | ||
| 902 | entry->proc_fops = state_fops; | 505 | entry->proc_fops = state_fops; |
| 903 | entry->data = data; | 506 | entry->data = data; |
| 904 | entry->owner = THIS_MODULE; | 507 | entry->owner = THIS_MODULE; |
| @@ -908,24 +511,19 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir, | |||
| 908 | /* 'alarm' [R/W] */ | 511 | /* 'alarm' [R/W] */ |
| 909 | if (alarm_fops) { | 512 | if (alarm_fops) { |
| 910 | entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir); | 513 | entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir); |
| 911 | if (!entry) { | 514 | if (entry) { |
| 912 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 913 | "create_proc_entry() failed")); | ||
| 914 | } else { | ||
| 915 | entry->proc_fops = alarm_fops; | 515 | entry->proc_fops = alarm_fops; |
| 916 | entry->data = data; | 516 | entry->data = data; |
| 917 | entry->owner = THIS_MODULE; | 517 | entry->owner = THIS_MODULE; |
| 918 | } | 518 | } |
| 919 | } | 519 | } |
| 920 | |||
| 921 | return 0; | 520 | return 0; |
| 922 | } | 521 | } |
| 923 | 522 | ||
| 924 | static void | 523 | static void |
| 925 | acpi_sbs_generic_remove_fs(struct proc_dir_entry **dir, | 524 | acpi_sbs_remove_fs(struct proc_dir_entry **dir, |
| 926 | struct proc_dir_entry *parent_dir) | 525 | struct proc_dir_entry *parent_dir) |
| 927 | { | 526 | { |
| 928 | |||
| 929 | if (*dir) { | 527 | if (*dir) { |
| 930 | remove_proc_entry(ACPI_SBS_FILE_INFO, *dir); | 528 | remove_proc_entry(ACPI_SBS_FILE_INFO, *dir); |
| 931 | remove_proc_entry(ACPI_SBS_FILE_STATE, *dir); | 529 | remove_proc_entry(ACPI_SBS_FILE_STATE, *dir); |
| @@ -933,82 +531,52 @@ acpi_sbs_generic_remove_fs(struct proc_dir_entry **dir, | |||
| 933 | remove_proc_entry((*dir)->name, parent_dir); | 531 | remove_proc_entry((*dir)->name, parent_dir); |
| 934 | *dir = NULL; | 532 | *dir = NULL; |
| 935 | } | 533 | } |
| 936 | |||
| 937 | } | 534 | } |
| 938 | 535 | ||
| 939 | /* Smart Battery Interface */ | 536 | /* Smart Battery Interface */ |
| 940 | |||
| 941 | static struct proc_dir_entry *acpi_battery_dir = NULL; | 537 | static struct proc_dir_entry *acpi_battery_dir = NULL; |
| 942 | 538 | ||
| 539 | static inline char *acpi_battery_units(struct acpi_battery *battery) | ||
| 540 | { | ||
| 541 | return acpi_battery_mode(battery) ? " mWh" : " mAh"; | ||
| 542 | } | ||
| 543 | |||
| 544 | |||
| 943 | static int acpi_battery_read_info(struct seq_file *seq, void *offset) | 545 | static int acpi_battery_read_info(struct seq_file *seq, void *offset) |
| 944 | { | 546 | { |
| 945 | struct acpi_battery *battery = seq->private; | 547 | struct acpi_battery *battery = seq->private; |
| 946 | struct acpi_sbs *sbs = battery->sbs; | 548 | struct acpi_sbs *sbs = battery->sbs; |
| 947 | int cscale; | ||
| 948 | int result = 0; | 549 | int result = 0; |
| 949 | 550 | ||
| 950 | if (sbs_mutex_lock(sbs)) { | 551 | mutex_lock(&sbs->lock); |
| 951 | return -ENODEV; | ||
| 952 | } | ||
| 953 | |||
| 954 | result = acpi_check_update_proc(sbs); | ||
| 955 | if (result) | ||
| 956 | goto end; | ||
| 957 | |||
| 958 | if (update_time == 0) { | ||
| 959 | result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_INFO); | ||
| 960 | if (result) { | ||
| 961 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 962 | "acpi_sbs_update_run() failed")); | ||
| 963 | } | ||
| 964 | } | ||
| 965 | 552 | ||
| 966 | if (battery->battery_present) { | 553 | seq_printf(seq, "present: %s\n", |
| 967 | seq_printf(seq, "present: yes\n"); | 554 | (battery->present) ? "yes" : "no"); |
| 968 | } else { | 555 | if (!battery->present) |
| 969 | seq_printf(seq, "present: no\n"); | ||
| 970 | goto end; | 556 | goto end; |
| 971 | } | ||
| 972 | 557 | ||
| 973 | if (battery->info.capacity_mode) { | ||
| 974 | cscale = battery->info.vscale * battery->info.ipscale; | ||
| 975 | } else { | ||
| 976 | cscale = battery->info.ipscale; | ||
| 977 | } | ||
| 978 | seq_printf(seq, "design capacity: %i%s\n", | 558 | seq_printf(seq, "design capacity: %i%s\n", |
| 979 | battery->info.design_capacity * cscale, | 559 | battery->design_capacity * acpi_battery_scale(battery), |
| 980 | battery->info.capacity_mode ? "0 mWh" : " mAh"); | 560 | acpi_battery_units(battery)); |
| 981 | |||
| 982 | seq_printf(seq, "last full capacity: %i%s\n", | 561 | seq_printf(seq, "last full capacity: %i%s\n", |
| 983 | battery->info.full_charge_capacity * cscale, | 562 | battery->full_charge_capacity * acpi_battery_scale(battery), |
| 984 | battery->info.capacity_mode ? "0 mWh" : " mAh"); | 563 | acpi_battery_units(battery)); |
| 985 | |||
| 986 | seq_printf(seq, "battery technology: rechargeable\n"); | 564 | seq_printf(seq, "battery technology: rechargeable\n"); |
| 987 | |||
| 988 | seq_printf(seq, "design voltage: %i mV\n", | 565 | seq_printf(seq, "design voltage: %i mV\n", |
| 989 | battery->info.design_voltage * battery->info.vscale); | 566 | battery->design_voltage * acpi_battery_vscale(battery)); |
| 990 | |||
| 991 | seq_printf(seq, "design capacity warning: unknown\n"); | 567 | seq_printf(seq, "design capacity warning: unknown\n"); |
| 992 | seq_printf(seq, "design capacity low: unknown\n"); | 568 | seq_printf(seq, "design capacity low: unknown\n"); |
| 993 | seq_printf(seq, "capacity granularity 1: unknown\n"); | 569 | seq_printf(seq, "capacity granularity 1: unknown\n"); |
| 994 | seq_printf(seq, "capacity granularity 2: unknown\n"); | 570 | seq_printf(seq, "capacity granularity 2: unknown\n"); |
| 995 | 571 | seq_printf(seq, "model number: %s\n", battery->device_name); | |
| 996 | seq_printf(seq, "model number: %s\n", | ||
| 997 | battery->info.device_name); | ||
| 998 | |||
| 999 | seq_printf(seq, "serial number: %i\n", | 572 | seq_printf(seq, "serial number: %i\n", |
| 1000 | battery->info.serial_number); | 573 | battery->serial_number); |
| 1001 | |||
| 1002 | seq_printf(seq, "battery type: %s\n", | 574 | seq_printf(seq, "battery type: %s\n", |
| 1003 | battery->info.device_chemistry); | 575 | battery->device_chemistry); |
| 1004 | |||
| 1005 | seq_printf(seq, "OEM info: %s\n", | 576 | seq_printf(seq, "OEM info: %s\n", |
| 1006 | battery->info.manufacturer_name); | 577 | battery->manufacturer_name); |
| 1007 | |||
| 1008 | end: | 578 | end: |
| 1009 | 579 | mutex_unlock(&sbs->lock); | |
| 1010 | sbs_mutex_unlock(sbs); | ||
| 1011 | |||
| 1012 | return result; | 580 | return result; |
| 1013 | } | 581 | } |
| 1014 | 582 | ||
| @@ -1022,73 +590,29 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset) | |||
| 1022 | struct acpi_battery *battery = seq->private; | 590 | struct acpi_battery *battery = seq->private; |
| 1023 | struct acpi_sbs *sbs = battery->sbs; | 591 | struct acpi_sbs *sbs = battery->sbs; |
| 1024 | int result = 0; | 592 | int result = 0; |
| 1025 | int cscale; | ||
| 1026 | int foo; | ||
| 1027 | |||
| 1028 | if (sbs_mutex_lock(sbs)) { | ||
| 1029 | return -ENODEV; | ||
| 1030 | } | ||
| 1031 | 593 | ||
| 1032 | result = acpi_check_update_proc(sbs); | 594 | mutex_lock(&sbs->lock); |
| 1033 | if (result) | 595 | seq_printf(seq, "present: %s\n", |
| 596 | (battery->present) ? "yes" : "no"); | ||
| 597 | if (!battery->present) | ||
| 1034 | goto end; | 598 | goto end; |
| 1035 | 599 | ||
| 1036 | if (update_time == 0) { | 600 | acpi_battery_get_state(battery); |
| 1037 | result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_STATE); | 601 | seq_printf(seq, "capacity state: %s\n", |
| 1038 | if (result) { | 602 | (battery->state & 0x0010) ? "critical" : "ok"); |
| 1039 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 603 | seq_printf(seq, "charging state: %s\n", |
| 1040 | "acpi_sbs_update_run() failed")); | 604 | (battery->current_now < 0) ? "discharging" : |
| 1041 | } | 605 | ((battery->current_now > 0) ? "charging" : "charged")); |
| 1042 | } | 606 | seq_printf(seq, "present rate: %d mA\n", |
| 1043 | 607 | abs(battery->current_now) * acpi_battery_ipscale(battery)); | |
| 1044 | if (battery->battery_present) { | ||
| 1045 | seq_printf(seq, "present: yes\n"); | ||
| 1046 | } else { | ||
| 1047 | seq_printf(seq, "present: no\n"); | ||
| 1048 | goto end; | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | if (battery->info.capacity_mode) { | ||
| 1052 | cscale = battery->info.vscale * battery->info.ipscale; | ||
| 1053 | } else { | ||
| 1054 | cscale = battery->info.ipscale; | ||
| 1055 | } | ||
| 1056 | |||
| 1057 | if (battery->state.battery_state & 0x0010) { | ||
| 1058 | seq_printf(seq, "capacity state: critical\n"); | ||
| 1059 | } else { | ||
| 1060 | seq_printf(seq, "capacity state: ok\n"); | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | foo = (s16) battery->state.amperage * battery->info.ipscale; | ||
| 1064 | if (battery->info.capacity_mode) { | ||
| 1065 | foo = foo * battery->info.design_voltage / 1000; | ||
| 1066 | } | ||
| 1067 | if (battery->state.amperage < 0) { | ||
| 1068 | seq_printf(seq, "charging state: discharging\n"); | ||
| 1069 | seq_printf(seq, "present rate: %d %s\n", | ||
| 1070 | -foo, battery->info.capacity_mode ? "mW" : "mA"); | ||
| 1071 | } else if (battery->state.amperage > 0) { | ||
| 1072 | seq_printf(seq, "charging state: charging\n"); | ||
| 1073 | seq_printf(seq, "present rate: %d %s\n", | ||
| 1074 | foo, battery->info.capacity_mode ? "mW" : "mA"); | ||
| 1075 | } else { | ||
| 1076 | seq_printf(seq, "charging state: charged\n"); | ||
| 1077 | seq_printf(seq, "present rate: 0 %s\n", | ||
| 1078 | battery->info.capacity_mode ? "mW" : "mA"); | ||
| 1079 | } | ||
| 1080 | |||
| 1081 | seq_printf(seq, "remaining capacity: %i%s\n", | 608 | seq_printf(seq, "remaining capacity: %i%s\n", |
| 1082 | battery->state.remaining_capacity * cscale, | 609 | battery->capacity_now * acpi_battery_scale(battery), |
| 1083 | battery->info.capacity_mode ? "0 mWh" : " mAh"); | 610 | acpi_battery_units(battery)); |
| 1084 | |||
| 1085 | seq_printf(seq, "present voltage: %i mV\n", | 611 | seq_printf(seq, "present voltage: %i mV\n", |
| 1086 | battery->state.voltage * battery->info.vscale); | 612 | battery->voltage_now * acpi_battery_vscale(battery)); |
| 1087 | 613 | ||
| 1088 | end: | 614 | end: |
| 1089 | 615 | mutex_unlock(&sbs->lock); | |
| 1090 | sbs_mutex_unlock(sbs); | ||
| 1091 | |||
| 1092 | return result; | 616 | return result; |
| 1093 | } | 617 | } |
| 1094 | 618 | ||
| @@ -1102,48 +626,25 @@ static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) | |||
| 1102 | struct acpi_battery *battery = seq->private; | 626 | struct acpi_battery *battery = seq->private; |
| 1103 | struct acpi_sbs *sbs = battery->sbs; | 627 | struct acpi_sbs *sbs = battery->sbs; |
| 1104 | int result = 0; | 628 | int result = 0; |
| 1105 | int cscale; | ||
| 1106 | |||
| 1107 | if (sbs_mutex_lock(sbs)) { | ||
| 1108 | return -ENODEV; | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | result = acpi_check_update_proc(sbs); | ||
| 1112 | if (result) | ||
| 1113 | goto end; | ||
| 1114 | 629 | ||
| 1115 | if (update_time == 0) { | 630 | mutex_lock(&sbs->lock); |
| 1116 | result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_ALARM); | ||
| 1117 | if (result) { | ||
| 1118 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1119 | "acpi_sbs_update_run() failed")); | ||
| 1120 | } | ||
| 1121 | } | ||
| 1122 | 631 | ||
| 1123 | if (!battery->battery_present) { | 632 | if (!battery->present) { |
| 1124 | seq_printf(seq, "present: no\n"); | 633 | seq_printf(seq, "present: no\n"); |
| 1125 | goto end; | 634 | goto end; |
| 1126 | } | 635 | } |
| 1127 | 636 | ||
| 1128 | if (battery->info.capacity_mode) { | 637 | acpi_battery_get_alarm(battery); |
| 1129 | cscale = battery->info.vscale * battery->info.ipscale; | ||
| 1130 | } else { | ||
| 1131 | cscale = battery->info.ipscale; | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | seq_printf(seq, "alarm: "); | 638 | seq_printf(seq, "alarm: "); |
| 1135 | if (battery->alarm.remaining_capacity) { | 639 | if (battery->alarm_capacity) |
| 1136 | seq_printf(seq, "%i%s\n", | 640 | seq_printf(seq, "%i%s\n", |
| 1137 | battery->alarm.remaining_capacity * cscale, | 641 | battery->alarm_capacity * |
| 1138 | battery->info.capacity_mode ? "0 mWh" : " mAh"); | 642 | acpi_battery_scale(battery), |
| 1139 | } else { | 643 | acpi_battery_units(battery)); |
| 644 | else | ||
| 1140 | seq_printf(seq, "disabled\n"); | 645 | seq_printf(seq, "disabled\n"); |
| 1141 | } | ||
| 1142 | |||
| 1143 | end: | 646 | end: |
| 1144 | 647 | mutex_unlock(&sbs->lock); | |
| 1145 | sbs_mutex_unlock(sbs); | ||
| 1146 | |||
| 1147 | return result; | 648 | return result; |
| 1148 | } | 649 | } |
| 1149 | 650 | ||
| @@ -1155,59 +656,29 @@ acpi_battery_write_alarm(struct file *file, const char __user * buffer, | |||
| 1155 | struct acpi_battery *battery = seq->private; | 656 | struct acpi_battery *battery = seq->private; |
| 1156 | struct acpi_sbs *sbs = battery->sbs; | 657 | struct acpi_sbs *sbs = battery->sbs; |
| 1157 | char alarm_string[12] = { '\0' }; | 658 | char alarm_string[12] = { '\0' }; |
| 1158 | int result, old_alarm, new_alarm; | 659 | int result = 0; |
| 1159 | 660 | mutex_lock(&sbs->lock); | |
| 1160 | if (sbs_mutex_lock(sbs)) { | 661 | if (!battery->present) { |
| 1161 | return -ENODEV; | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | result = acpi_check_update_proc(sbs); | ||
| 1165 | if (result) | ||
| 1166 | goto end; | ||
| 1167 | |||
| 1168 | if (!battery->battery_present) { | ||
| 1169 | result = -ENODEV; | 662 | result = -ENODEV; |
| 1170 | goto end; | 663 | goto end; |
| 1171 | } | 664 | } |
| 1172 | |||
| 1173 | if (count > sizeof(alarm_string) - 1) { | 665 | if (count > sizeof(alarm_string) - 1) { |
| 1174 | result = -EINVAL; | 666 | result = -EINVAL; |
| 1175 | goto end; | 667 | goto end; |
| 1176 | } | 668 | } |
| 1177 | |||
| 1178 | if (copy_from_user(alarm_string, buffer, count)) { | 669 | if (copy_from_user(alarm_string, buffer, count)) { |
| 1179 | result = -EFAULT; | 670 | result = -EFAULT; |
| 1180 | goto end; | 671 | goto end; |
| 1181 | } | 672 | } |
| 1182 | |||
| 1183 | alarm_string[count] = 0; | 673 | alarm_string[count] = 0; |
| 1184 | 674 | battery->alarm_capacity = simple_strtoul(alarm_string, NULL, 0) / | |
| 1185 | old_alarm = battery->alarm.remaining_capacity; | 675 | acpi_battery_scale(battery); |
| 1186 | new_alarm = simple_strtoul(alarm_string, NULL, 0); | 676 | acpi_battery_set_alarm(battery); |
| 1187 | |||
| 1188 | result = acpi_battery_set_alarm(battery, new_alarm); | ||
| 1189 | if (result) { | ||
| 1190 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1191 | "acpi_battery_set_alarm() failed")); | ||
| 1192 | acpi_battery_set_alarm(battery, old_alarm); | ||
| 1193 | goto end; | ||
| 1194 | } | ||
| 1195 | result = acpi_battery_get_alarm(battery); | ||
| 1196 | if (result) { | ||
| 1197 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1198 | "acpi_battery_get_alarm() failed")); | ||
| 1199 | acpi_battery_set_alarm(battery, old_alarm); | ||
| 1200 | goto end; | ||
| 1201 | } | ||
| 1202 | |||
| 1203 | end: | 677 | end: |
| 1204 | sbs_mutex_unlock(sbs); | 678 | mutex_unlock(&sbs->lock); |
| 1205 | 679 | if (result) | |
| 1206 | if (result) { | ||
| 1207 | return result; | 680 | return result; |
| 1208 | } else { | 681 | return count; |
| 1209 | return count; | ||
| 1210 | } | ||
| 1211 | } | 682 | } |
| 1212 | 683 | ||
| 1213 | static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) | 684 | static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) |
| @@ -1246,26 +717,15 @@ static struct proc_dir_entry *acpi_ac_dir = NULL; | |||
| 1246 | 717 | ||
| 1247 | static int acpi_ac_read_state(struct seq_file *seq, void *offset) | 718 | static int acpi_ac_read_state(struct seq_file *seq, void *offset) |
| 1248 | { | 719 | { |
| 1249 | struct acpi_sbs *sbs = seq->private; | ||
| 1250 | int result; | ||
| 1251 | 720 | ||
| 1252 | if (sbs_mutex_lock(sbs)) { | 721 | struct acpi_sbs *sbs = seq->private; |
| 1253 | return -ENODEV; | ||
| 1254 | } | ||
| 1255 | 722 | ||
| 1256 | if (update_time == 0) { | 723 | mutex_lock(&sbs->lock); |
| 1257 | result = acpi_sbs_update_run(sbs, -1, DATA_TYPE_AC_STATE); | ||
| 1258 | if (result) { | ||
| 1259 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1260 | "acpi_sbs_update_run() failed")); | ||
| 1261 | } | ||
| 1262 | } | ||
| 1263 | 724 | ||
| 1264 | seq_printf(seq, "state: %s\n", | 725 | seq_printf(seq, "state: %s\n", |
| 1265 | sbs->ac.ac_present ? "on-line" : "off-line"); | 726 | sbs->charger_present ? "on-line" : "off-line"); |
| 1266 | |||
| 1267 | sbs_mutex_unlock(sbs); | ||
| 1268 | 727 | ||
| 728 | mutex_unlock(&sbs->lock); | ||
| 1269 | return 0; | 729 | return 0; |
| 1270 | } | 730 | } |
| 1271 | 731 | ||
| @@ -1282,429 +742,203 @@ static struct file_operations acpi_ac_state_fops = { | |||
| 1282 | .owner = THIS_MODULE, | 742 | .owner = THIS_MODULE, |
| 1283 | }; | 743 | }; |
| 1284 | 744 | ||
| 745 | #endif | ||
| 746 | |||
| 1285 | /* -------------------------------------------------------------------------- | 747 | /* -------------------------------------------------------------------------- |
| 1286 | Driver Interface | 748 | Driver Interface |
| 1287 | -------------------------------------------------------------------------- */ | 749 | -------------------------------------------------------------------------- */ |
| 750 | static int acpi_battery_read(struct acpi_battery *battery) | ||
| 751 | { | ||
| 752 | int result = 0, saved_present = battery->present; | ||
| 753 | u16 state; | ||
| 754 | |||
| 755 | if (battery->sbs->manager_present) { | ||
| 756 | result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, | ||
| 757 | ACPI_SBS_MANAGER, 0x01, (u8 *)&state); | ||
| 758 | if (!result) | ||
| 759 | battery->present = state & (1 << battery->id); | ||
| 760 | state &= 0x0fff; | ||
| 761 | state |= 1 << (battery->id + 12); | ||
| 762 | acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, | ||
| 763 | ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2); | ||
| 764 | } else if (battery->id == 0) | ||
| 765 | battery->present = 1; | ||
| 766 | if (result || !battery->present) | ||
| 767 | return result; | ||
| 1288 | 768 | ||
| 1289 | /* Smart Battery */ | 769 | if (saved_present != battery->present) { |
| 770 | battery->update_time = 0; | ||
| 771 | result = acpi_battery_get_info(battery); | ||
| 772 | if (result) | ||
| 773 | return result; | ||
| 774 | } | ||
| 775 | result = acpi_battery_get_state(battery); | ||
| 776 | return result; | ||
| 777 | } | ||
| 1290 | 778 | ||
| 779 | /* Smart Battery */ | ||
| 1291 | static int acpi_battery_add(struct acpi_sbs *sbs, int id) | 780 | static int acpi_battery_add(struct acpi_sbs *sbs, int id) |
| 1292 | { | 781 | { |
| 1293 | int is_present; | 782 | struct acpi_battery *battery = &sbs->battery[id]; |
| 1294 | int result; | 783 | int result; |
| 1295 | char dir_name[32]; | ||
| 1296 | struct acpi_battery *battery; | ||
| 1297 | |||
| 1298 | battery = &sbs->battery[id]; | ||
| 1299 | |||
| 1300 | battery->alive = 0; | ||
| 1301 | 784 | ||
| 1302 | battery->init_state = 0; | ||
| 1303 | battery->id = id; | 785 | battery->id = id; |
| 1304 | battery->sbs = sbs; | 786 | battery->sbs = sbs; |
| 787 | result = acpi_battery_read(battery); | ||
| 788 | if (result) | ||
| 789 | return result; | ||
| 1305 | 790 | ||
| 1306 | result = acpi_battery_select(battery); | 791 | sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id); |
| 1307 | if (result) { | 792 | #ifdef CONFIG_ACPI_PROCFS |
| 1308 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 793 | acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir, |
| 1309 | "acpi_battery_select() failed")); | 794 | battery->name, &acpi_battery_info_fops, |
| 1310 | goto end; | 795 | &acpi_battery_state_fops, &acpi_battery_alarm_fops, |
| 1311 | } | 796 | battery); |
| 1312 | 797 | #endif | |
| 1313 | result = acpi_battery_get_present(battery); | 798 | battery->bat.name = battery->name; |
| 1314 | if (result) { | 799 | battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; |
| 1315 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 800 | if (!acpi_battery_mode(battery)) { |
| 1316 | "acpi_battery_get_present() failed")); | 801 | battery->bat.properties = sbs_charge_battery_props; |
| 1317 | goto end; | 802 | battery->bat.num_properties = |
| 1318 | } | 803 | ARRAY_SIZE(sbs_charge_battery_props); |
| 1319 | 804 | } else { | |
| 1320 | is_present = battery->battery_present; | 805 | battery->bat.properties = sbs_energy_battery_props; |
| 1321 | 806 | battery->bat.num_properties = | |
| 1322 | if (is_present) { | 807 | ARRAY_SIZE(sbs_energy_battery_props); |
| 1323 | result = acpi_battery_init(battery); | ||
| 1324 | if (result) { | ||
| 1325 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1326 | "acpi_battery_init() failed")); | ||
| 1327 | goto end; | ||
| 1328 | } | ||
| 1329 | battery->init_state = 1; | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id); | ||
| 1333 | |||
| 1334 | result = acpi_sbs_generic_add_fs(&battery->battery_entry, | ||
| 1335 | acpi_battery_dir, | ||
| 1336 | dir_name, | ||
| 1337 | &acpi_battery_info_fops, | ||
| 1338 | &acpi_battery_state_fops, | ||
| 1339 | &acpi_battery_alarm_fops, battery); | ||
| 1340 | if (result) { | ||
| 1341 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1342 | "acpi_sbs_generic_add_fs() failed")); | ||
| 1343 | goto end; | ||
| 1344 | } | 808 | } |
| 1345 | battery->alive = 1; | 809 | battery->bat.get_property = acpi_sbs_battery_get_property; |
| 1346 | 810 | result = power_supply_register(&sbs->device->dev, &battery->bat); | |
| 811 | device_create_file(battery->bat.dev, &alarm_attr); | ||
| 1347 | printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n", | 812 | printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n", |
| 1348 | ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), dir_name, | 813 | ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), |
| 1349 | sbs->battery->battery_present ? "present" : "absent"); | 814 | battery->name, sbs->battery->present ? "present" : "absent"); |
| 1350 | |||
| 1351 | end: | ||
| 1352 | return result; | 815 | return result; |
| 1353 | } | 816 | } |
| 1354 | 817 | ||
| 1355 | static void acpi_battery_remove(struct acpi_sbs *sbs, int id) | 818 | static void acpi_battery_remove(struct acpi_sbs *sbs, int id) |
| 1356 | { | 819 | { |
| 1357 | 820 | if (sbs->battery[id].bat.dev) | |
| 1358 | if (sbs->battery[id].battery_entry) { | 821 | device_remove_file(sbs->battery[id].bat.dev, &alarm_attr); |
| 1359 | acpi_sbs_generic_remove_fs(&(sbs->battery[id].battery_entry), | 822 | power_supply_unregister(&sbs->battery[id].bat); |
| 1360 | acpi_battery_dir); | 823 | #ifdef CONFIG_ACPI_PROCFS |
| 1361 | } | 824 | if (sbs->battery[id].proc_entry) { |
| 825 | acpi_sbs_remove_fs(&(sbs->battery[id].proc_entry), | ||
| 826 | acpi_battery_dir); | ||
| 827 | } | ||
| 828 | #endif | ||
| 1362 | } | 829 | } |
| 1363 | 830 | ||
| 1364 | static int acpi_ac_add(struct acpi_sbs *sbs) | 831 | static int acpi_charger_add(struct acpi_sbs *sbs) |
| 1365 | { | 832 | { |
| 1366 | int result; | 833 | int result; |
| 1367 | 834 | ||
| 1368 | result = acpi_ac_get_present(sbs); | 835 | result = acpi_ac_get_present(sbs); |
| 1369 | if (result) { | 836 | if (result) |
| 1370 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1371 | "acpi_ac_get_present() failed")); | ||
| 1372 | goto end; | 837 | goto end; |
| 1373 | } | 838 | #ifdef CONFIG_ACPI_PROCFS |
| 1374 | 839 | result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir, | |
| 1375 | result = acpi_sbs_generic_add_fs(&sbs->ac_entry, | 840 | ACPI_AC_DIR_NAME, NULL, |
| 1376 | acpi_ac_dir, | 841 | &acpi_ac_state_fops, NULL, sbs); |
| 1377 | ACPI_AC_DIR_NAME, | 842 | if (result) |
| 1378 | NULL, &acpi_ac_state_fops, NULL, sbs); | ||
| 1379 | if (result) { | ||
| 1380 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1381 | "acpi_sbs_generic_add_fs() failed")); | ||
| 1382 | goto end; | 843 | goto end; |
| 1383 | } | 844 | #endif |
| 1384 | 845 | sbs->charger.name = "sbs-charger"; | |
| 846 | sbs->charger.type = POWER_SUPPLY_TYPE_MAINS; | ||
| 847 | sbs->charger.properties = sbs_ac_props; | ||
| 848 | sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props); | ||
| 849 | sbs->charger.get_property = sbs_get_ac_property; | ||
| 850 | power_supply_register(&sbs->device->dev, &sbs->charger); | ||
| 1385 | printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n", | 851 | printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n", |
| 1386 | ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), | 852 | ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), |
| 1387 | ACPI_AC_DIR_NAME, sbs->ac.ac_present ? "on-line" : "off-line"); | 853 | ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line"); |
| 1388 | |||
| 1389 | end: | 854 | end: |
| 1390 | |||
| 1391 | return result; | 855 | return result; |
| 1392 | } | 856 | } |
| 1393 | 857 | ||
| 1394 | static void acpi_ac_remove(struct acpi_sbs *sbs) | 858 | static void acpi_charger_remove(struct acpi_sbs *sbs) |
| 1395 | { | 859 | { |
| 1396 | 860 | if (sbs->charger.dev) | |
| 1397 | if (sbs->ac_entry) { | 861 | power_supply_unregister(&sbs->charger); |
| 1398 | acpi_sbs_generic_remove_fs(&sbs->ac_entry, acpi_ac_dir); | 862 | #ifdef CONFIG_ACPI_PROCFS |
| 1399 | } | 863 | if (sbs->charger_entry) |
| 864 | acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir); | ||
| 865 | #endif | ||
| 1400 | } | 866 | } |
| 1401 | 867 | ||
| 1402 | static void acpi_sbs_update_time_run(unsigned long data) | 868 | void acpi_sbs_callback(void *context) |
| 1403 | { | 869 | { |
| 1404 | acpi_os_execute(OSL_GPE_HANDLER, acpi_sbs_update_time, (void *)data); | 870 | int id; |
| 1405 | } | 871 | struct acpi_sbs *sbs = context; |
| 1406 | 872 | struct acpi_battery *bat; | |
| 1407 | static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type) | 873 | u8 saved_charger_state = sbs->charger_present; |
| 1408 | { | 874 | u8 saved_battery_state; |
| 1409 | struct acpi_battery *battery; | 875 | acpi_ac_get_present(sbs); |
| 1410 | int result = 0, cnt; | 876 | if (sbs->charger_present != saved_charger_state) { |
| 1411 | int old_ac_present = -1; | 877 | #ifdef CONFIG_ACPI_PROC_EVENT |
| 1412 | int old_battery_present = -1; | 878 | acpi_bus_generate_proc_event4(ACPI_AC_CLASS, ACPI_AC_DIR_NAME, |
| 1413 | int new_ac_present = -1; | 879 | ACPI_SBS_NOTIFY_STATUS, |
| 1414 | int new_battery_present = -1; | 880 | sbs->charger_present); |
| 1415 | int id_min = 0, id_max = MAX_SBS_BAT - 1; | 881 | #endif |
| 1416 | char dir_name[32]; | 882 | kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE); |
| 1417 | int do_battery_init = 0, do_ac_init = 0; | 883 | } |
| 1418 | int old_remaining_capacity = 0; | 884 | if (sbs->manager_present) { |
| 1419 | int update_battery = 1; | 885 | for (id = 0; id < MAX_SBS_BAT; ++id) { |
| 1420 | int up_tm = update_time; | 886 | if (!(sbs->batteries_supported & (1 << id))) |
| 1421 | 887 | continue; | |
| 1422 | if (sbs_zombie(sbs)) { | 888 | bat = &sbs->battery[id]; |
| 1423 | goto end; | 889 | saved_battery_state = bat->present; |
| 1424 | } | 890 | acpi_battery_read(bat); |
| 1425 | 891 | if (saved_battery_state == bat->present) | |
| 1426 | if (id >= 0) { | 892 | continue; |
| 1427 | id_min = id_max = id; | 893 | #ifdef CONFIG_ACPI_PROC_EVENT |
| 1428 | } | 894 | acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS, |
| 1429 | 895 | bat->name, | |
| 1430 | if (data_type == DATA_TYPE_COMMON && up_tm > 0) { | 896 | ACPI_SBS_NOTIFY_STATUS, |
| 1431 | cnt = up_tm / (up_tm > UPDATE_DELAY ? UPDATE_DELAY : up_tm); | 897 | bat->present); |
| 1432 | if (sbs->run_cnt % cnt != 0) { | 898 | #endif |
| 1433 | update_battery = 0; | 899 | kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE); |
| 1434 | } | ||
| 1435 | } | ||
| 1436 | |||
| 1437 | sbs->run_cnt++; | ||
| 1438 | |||
| 1439 | old_ac_present = sbs->ac.ac_present; | ||
| 1440 | |||
| 1441 | result = acpi_ac_get_present(sbs); | ||
| 1442 | if (result) { | ||
| 1443 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1444 | "acpi_ac_get_present() failed")); | ||
| 1445 | } | ||
| 1446 | |||
| 1447 | new_ac_present = sbs->ac.ac_present; | ||
| 1448 | |||
| 1449 | do_ac_init = (old_ac_present != new_ac_present); | ||
| 1450 | if (sbs->run_cnt == 1 && data_type == DATA_TYPE_COMMON) { | ||
| 1451 | do_ac_init = 1; | ||
| 1452 | } | ||
| 1453 | |||
| 1454 | if (do_ac_init) { | ||
| 1455 | result = acpi_sbs_generate_event(sbs->device, | ||
| 1456 | ACPI_SBS_AC_NOTIFY_STATUS, | ||
| 1457 | new_ac_present, | ||
| 1458 | ACPI_AC_DIR_NAME, | ||
| 1459 | ACPI_AC_CLASS); | ||
| 1460 | if (result) { | ||
| 1461 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1462 | "acpi_sbs_generate_event() failed")); | ||
| 1463 | } | ||
| 1464 | } | ||
| 1465 | |||
| 1466 | if (data_type == DATA_TYPE_COMMON) { | ||
| 1467 | if (!do_ac_init && !update_battery) { | ||
| 1468 | goto end; | ||
| 1469 | } | ||
| 1470 | } | ||
| 1471 | |||
| 1472 | if (data_type == DATA_TYPE_AC_STATE && !do_ac_init) { | ||
| 1473 | goto end; | ||
| 1474 | } | ||
| 1475 | |||
| 1476 | for (id = id_min; id <= id_max; id++) { | ||
| 1477 | battery = &sbs->battery[id]; | ||
| 1478 | if (battery->alive == 0) { | ||
| 1479 | continue; | ||
| 1480 | } | ||
| 1481 | |||
| 1482 | old_remaining_capacity = battery->state.remaining_capacity; | ||
| 1483 | |||
| 1484 | old_battery_present = battery->battery_present; | ||
| 1485 | |||
| 1486 | result = acpi_battery_select(battery); | ||
| 1487 | if (result) { | ||
| 1488 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1489 | "acpi_battery_select() failed")); | ||
| 1490 | } | ||
| 1491 | |||
| 1492 | result = acpi_battery_get_present(battery); | ||
| 1493 | if (result) { | ||
| 1494 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1495 | "acpi_battery_get_present() failed")); | ||
| 1496 | } | ||
| 1497 | |||
| 1498 | new_battery_present = battery->battery_present; | ||
| 1499 | |||
| 1500 | do_battery_init = ((old_battery_present != new_battery_present) | ||
| 1501 | && new_battery_present); | ||
| 1502 | if (!new_battery_present) | ||
| 1503 | goto event; | ||
| 1504 | if (do_ac_init || do_battery_init) { | ||
| 1505 | result = acpi_battery_init(battery); | ||
| 1506 | if (result) { | ||
| 1507 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1508 | "acpi_battery_init() " | ||
| 1509 | "failed")); | ||
| 1510 | } | ||
| 1511 | } | ||
| 1512 | if (sbs_zombie(sbs)) { | ||
| 1513 | goto end; | ||
| 1514 | } | ||
| 1515 | |||
| 1516 | if ((data_type == DATA_TYPE_COMMON | ||
| 1517 | || data_type == DATA_TYPE_INFO) | ||
| 1518 | && new_battery_present) { | ||
| 1519 | result = acpi_battery_get_info(battery); | ||
| 1520 | if (result) { | ||
| 1521 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1522 | "acpi_battery_get_info() failed")); | ||
| 1523 | } | ||
| 1524 | } | ||
| 1525 | if (data_type == DATA_TYPE_INFO) { | ||
| 1526 | continue; | ||
| 1527 | } | ||
| 1528 | if (sbs_zombie(sbs)) { | ||
| 1529 | goto end; | ||
| 1530 | } | ||
| 1531 | |||
| 1532 | if ((data_type == DATA_TYPE_COMMON | ||
| 1533 | || data_type == DATA_TYPE_STATE) | ||
| 1534 | && new_battery_present) { | ||
| 1535 | result = acpi_battery_get_state(battery); | ||
| 1536 | if (result) { | ||
| 1537 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1538 | "acpi_battery_get_state() failed")); | ||
| 1539 | } | ||
| 1540 | } | ||
| 1541 | if (data_type == DATA_TYPE_STATE) { | ||
| 1542 | goto event; | ||
| 1543 | } | ||
| 1544 | if (sbs_zombie(sbs)) { | ||
| 1545 | goto end; | ||
| 1546 | } | ||
| 1547 | |||
| 1548 | if ((data_type == DATA_TYPE_COMMON | ||
| 1549 | || data_type == DATA_TYPE_ALARM) | ||
| 1550 | && new_battery_present) { | ||
| 1551 | result = acpi_battery_get_alarm(battery); | ||
| 1552 | if (result) { | ||
| 1553 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1554 | "acpi_battery_get_alarm() " | ||
| 1555 | "failed")); | ||
| 1556 | } | ||
| 1557 | } | ||
| 1558 | if (data_type == DATA_TYPE_ALARM) { | ||
| 1559 | continue; | ||
| 1560 | } | ||
| 1561 | if (sbs_zombie(sbs)) { | ||
| 1562 | goto end; | ||
| 1563 | } | ||
| 1564 | |||
| 1565 | event: | ||
| 1566 | |||
| 1567 | if (old_battery_present != new_battery_present || do_ac_init || | ||
| 1568 | old_remaining_capacity != | ||
| 1569 | battery->state.remaining_capacity) { | ||
| 1570 | sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id); | ||
| 1571 | result = acpi_sbs_generate_event(sbs->device, | ||
| 1572 | ACPI_SBS_BATTERY_NOTIFY_STATUS, | ||
| 1573 | new_battery_present, | ||
| 1574 | dir_name, | ||
| 1575 | ACPI_BATTERY_CLASS); | ||
| 1576 | if (result) { | ||
| 1577 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1578 | "acpi_sbs_generate_event() " | ||
| 1579 | "failed")); | ||
| 1580 | } | ||
| 1581 | } | 900 | } |
| 1582 | } | 901 | } |
| 1583 | |||
| 1584 | end: | ||
| 1585 | |||
| 1586 | return result; | ||
| 1587 | } | 902 | } |
| 1588 | 903 | ||
| 1589 | static void acpi_sbs_update_time(void *data) | 904 | static int acpi_sbs_remove(struct acpi_device *device, int type); |
| 1590 | { | ||
| 1591 | struct acpi_sbs *sbs = data; | ||
| 1592 | unsigned long delay = -1; | ||
| 1593 | int result; | ||
| 1594 | unsigned int up_tm = update_time; | ||
| 1595 | |||
| 1596 | if (sbs_mutex_lock(sbs)) | ||
| 1597 | return; | ||
| 1598 | |||
| 1599 | result = acpi_sbs_update_run(sbs, -1, DATA_TYPE_COMMON); | ||
| 1600 | if (result) { | ||
| 1601 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1602 | "acpi_sbs_update_run() failed")); | ||
| 1603 | } | ||
| 1604 | |||
| 1605 | if (sbs_zombie(sbs)) { | ||
| 1606 | goto end; | ||
| 1607 | } | ||
| 1608 | |||
| 1609 | if (!up_tm) { | ||
| 1610 | if (timer_pending(&sbs->update_timer)) | ||
| 1611 | del_timer(&sbs->update_timer); | ||
| 1612 | } else { | ||
| 1613 | delay = (up_tm > UPDATE_DELAY ? UPDATE_DELAY : up_tm); | ||
| 1614 | delay = jiffies + HZ * delay; | ||
| 1615 | if (timer_pending(&sbs->update_timer)) { | ||
| 1616 | mod_timer(&sbs->update_timer, delay); | ||
| 1617 | } else { | ||
| 1618 | sbs->update_timer.data = (unsigned long)data; | ||
| 1619 | sbs->update_timer.function = acpi_sbs_update_time_run; | ||
| 1620 | sbs->update_timer.expires = delay; | ||
| 1621 | add_timer(&sbs->update_timer); | ||
| 1622 | } | ||
| 1623 | } | ||
| 1624 | |||
| 1625 | end: | ||
| 1626 | |||
| 1627 | sbs_mutex_unlock(sbs); | ||
| 1628 | } | ||
| 1629 | 905 | ||
| 1630 | static int acpi_sbs_add(struct acpi_device *device) | 906 | static int acpi_sbs_add(struct acpi_device *device) |
| 1631 | { | 907 | { |
| 1632 | struct acpi_sbs *sbs = NULL; | 908 | struct acpi_sbs *sbs; |
| 1633 | int result = 0, remove_result = 0; | 909 | int result = 0; |
| 1634 | int id; | 910 | int id; |
| 1635 | acpi_status status = AE_OK; | ||
| 1636 | unsigned long val; | ||
| 1637 | |||
| 1638 | status = | ||
| 1639 | acpi_evaluate_integer(device->handle, "_EC", NULL, &val); | ||
| 1640 | if (ACPI_FAILURE(status)) { | ||
| 1641 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Error obtaining _EC")); | ||
| 1642 | return -EIO; | ||
| 1643 | } | ||
| 1644 | 911 | ||
| 1645 | sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); | 912 | sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); |
| 1646 | if (!sbs) { | 913 | if (!sbs) { |
| 1647 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "kzalloc() failed")); | ||
| 1648 | result = -ENOMEM; | 914 | result = -ENOMEM; |
| 1649 | goto end; | 915 | goto end; |
| 1650 | } | 916 | } |
| 1651 | 917 | ||
| 1652 | mutex_init(&sbs->mutex); | 918 | mutex_init(&sbs->lock); |
| 1653 | |||
| 1654 | sbs_mutex_lock(sbs); | ||
| 1655 | 919 | ||
| 1656 | sbs->base = 0xff & (val >> 8); | 920 | sbs->hc = acpi_driver_data(device->parent); |
| 1657 | sbs->device = device; | 921 | sbs->device = device; |
| 1658 | |||
| 1659 | strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); | 922 | strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); |
| 1660 | strcpy(acpi_device_class(device), ACPI_SBS_CLASS); | 923 | strcpy(acpi_device_class(device), ACPI_SBS_CLASS); |
| 1661 | acpi_driver_data(device) = sbs; | 924 | acpi_driver_data(device) = sbs; |
| 1662 | 925 | ||
| 1663 | result = acpi_ac_add(sbs); | 926 | result = acpi_charger_add(sbs); |
| 1664 | if (result) { | ||
| 1665 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_ac_add() failed")); | ||
| 1666 | goto end; | ||
| 1667 | } | ||
| 1668 | |||
| 1669 | acpi_sbsm_get_info(sbs); | ||
| 1670 | |||
| 1671 | if (!sbs->sbsm_present) { | ||
| 1672 | result = acpi_battery_add(sbs, 0); | ||
| 1673 | if (result) { | ||
| 1674 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1675 | "acpi_battery_add() failed")); | ||
| 1676 | goto end; | ||
| 1677 | } | ||
| 1678 | } else { | ||
| 1679 | for (id = 0; id < MAX_SBS_BAT; id++) { | ||
| 1680 | if ((sbs->sbsm_batteries_supported & (1 << id))) { | ||
| 1681 | result = acpi_battery_add(sbs, id); | ||
| 1682 | if (result) { | ||
| 1683 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1684 | "acpi_battery_add() failed")); | ||
| 1685 | goto end; | ||
| 1686 | } | ||
| 1687 | } | ||
| 1688 | } | ||
| 1689 | } | ||
| 1690 | |||
| 1691 | init_timer(&sbs->update_timer); | ||
| 1692 | result = acpi_check_update_proc(sbs); | ||
| 1693 | if (result) | 927 | if (result) |
| 1694 | goto end; | 928 | goto end; |
| 1695 | 929 | ||
| 930 | result = acpi_manager_get_info(sbs); | ||
| 931 | if (!result) { | ||
| 932 | sbs->manager_present = 1; | ||
| 933 | for (id = 0; id < MAX_SBS_BAT; ++id) | ||
| 934 | if ((sbs->batteries_supported & (1 << id))) | ||
| 935 | acpi_battery_add(sbs, id); | ||
| 936 | } else | ||
| 937 | acpi_battery_add(sbs, 0); | ||
| 938 | acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs); | ||
| 1696 | end: | 939 | end: |
| 1697 | 940 | if (result) | |
| 1698 | sbs_mutex_unlock(sbs); | 941 | acpi_sbs_remove(device, 0); |
| 1699 | |||
| 1700 | if (result) { | ||
| 1701 | remove_result = acpi_sbs_remove(device, 0); | ||
| 1702 | if (remove_result) { | ||
| 1703 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1704 | "acpi_sbs_remove() failed")); | ||
| 1705 | } | ||
| 1706 | } | ||
| 1707 | |||
| 1708 | return result; | 942 | return result; |
| 1709 | } | 943 | } |
| 1710 | 944 | ||
| @@ -1713,39 +947,25 @@ static int acpi_sbs_remove(struct acpi_device *device, int type) | |||
| 1713 | struct acpi_sbs *sbs; | 947 | struct acpi_sbs *sbs; |
| 1714 | int id; | 948 | int id; |
| 1715 | 949 | ||
| 1716 | if (!device) { | 950 | if (!device) |
| 1717 | return -EINVAL; | 951 | return -EINVAL; |
| 1718 | } | ||
| 1719 | |||
| 1720 | sbs = acpi_driver_data(device); | 952 | sbs = acpi_driver_data(device); |
| 1721 | if (!sbs) { | 953 | if (!sbs) |
| 1722 | return -EINVAL; | 954 | return -EINVAL; |
| 1723 | } | 955 | mutex_lock(&sbs->lock); |
| 1724 | 956 | acpi_smbus_unregister_callback(sbs->hc); | |
| 1725 | sbs_mutex_lock(sbs); | 957 | for (id = 0; id < MAX_SBS_BAT; ++id) |
| 1726 | |||
| 1727 | sbs->zombie = 1; | ||
| 1728 | del_timer_sync(&sbs->update_timer); | ||
| 1729 | acpi_os_wait_events_complete(NULL); | ||
| 1730 | del_timer_sync(&sbs->update_timer); | ||
| 1731 | |||
| 1732 | for (id = 0; id < MAX_SBS_BAT; id++) { | ||
| 1733 | acpi_battery_remove(sbs, id); | 958 | acpi_battery_remove(sbs, id); |
| 1734 | } | 959 | acpi_charger_remove(sbs); |
| 1735 | 960 | mutex_unlock(&sbs->lock); | |
| 1736 | acpi_ac_remove(sbs); | 961 | mutex_destroy(&sbs->lock); |
| 1737 | |||
| 1738 | sbs_mutex_unlock(sbs); | ||
| 1739 | |||
| 1740 | mutex_destroy(&sbs->mutex); | ||
| 1741 | |||
| 1742 | kfree(sbs); | 962 | kfree(sbs); |
| 1743 | |||
| 1744 | return 0; | 963 | return 0; |
| 1745 | } | 964 | } |
| 1746 | 965 | ||
| 1747 | static void acpi_sbs_rmdirs(void) | 966 | static void acpi_sbs_rmdirs(void) |
| 1748 | { | 967 | { |
| 968 | #ifdef CONFIG_ACPI_PROCFS | ||
| 1749 | if (acpi_ac_dir) { | 969 | if (acpi_ac_dir) { |
| 1750 | acpi_unlock_ac_dir(acpi_ac_dir); | 970 | acpi_unlock_ac_dir(acpi_ac_dir); |
| 1751 | acpi_ac_dir = NULL; | 971 | acpi_ac_dir = NULL; |
| @@ -1754,69 +974,58 @@ static void acpi_sbs_rmdirs(void) | |||
| 1754 | acpi_unlock_battery_dir(acpi_battery_dir); | 974 | acpi_unlock_battery_dir(acpi_battery_dir); |
| 1755 | acpi_battery_dir = NULL; | 975 | acpi_battery_dir = NULL; |
| 1756 | } | 976 | } |
| 977 | #endif | ||
| 1757 | } | 978 | } |
| 1758 | 979 | ||
| 1759 | static int acpi_sbs_resume(struct acpi_device *device) | 980 | static int acpi_sbs_resume(struct acpi_device *device) |
| 1760 | { | 981 | { |
| 1761 | struct acpi_sbs *sbs; | 982 | struct acpi_sbs *sbs; |
| 1762 | |||
| 1763 | if (!device) | 983 | if (!device) |
| 1764 | return -EINVAL; | 984 | return -EINVAL; |
| 1765 | |||
| 1766 | sbs = device->driver_data; | 985 | sbs = device->driver_data; |
| 1767 | 986 | acpi_sbs_callback(sbs); | |
| 1768 | sbs->run_cnt = 0; | ||
| 1769 | |||
| 1770 | return 0; | 987 | return 0; |
| 1771 | } | 988 | } |
| 1772 | 989 | ||
| 990 | static struct acpi_driver acpi_sbs_driver = { | ||
| 991 | .name = "sbs", | ||
| 992 | .class = ACPI_SBS_CLASS, | ||
| 993 | .ids = sbs_device_ids, | ||
| 994 | .ops = { | ||
| 995 | .add = acpi_sbs_add, | ||
| 996 | .remove = acpi_sbs_remove, | ||
| 997 | .resume = acpi_sbs_resume, | ||
| 998 | }, | ||
| 999 | }; | ||
| 1000 | |||
| 1773 | static int __init acpi_sbs_init(void) | 1001 | static int __init acpi_sbs_init(void) |
| 1774 | { | 1002 | { |
| 1775 | int result = 0; | 1003 | int result = 0; |
| 1776 | 1004 | ||
| 1777 | if (acpi_disabled) | 1005 | if (acpi_disabled) |
| 1778 | return -ENODEV; | 1006 | return -ENODEV; |
| 1779 | 1007 | #ifdef CONFIG_ACPI_PROCFS | |
| 1780 | if (capacity_mode != DEF_CAPACITY_UNIT | ||
| 1781 | && capacity_mode != MAH_CAPACITY_UNIT | ||
| 1782 | && capacity_mode != MWH_CAPACITY_UNIT) { | ||
| 1783 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1784 | "invalid capacity_mode = %d", capacity_mode)); | ||
| 1785 | return -EINVAL; | ||
| 1786 | } | ||
| 1787 | |||
| 1788 | acpi_ac_dir = acpi_lock_ac_dir(); | 1008 | acpi_ac_dir = acpi_lock_ac_dir(); |
| 1789 | if (!acpi_ac_dir) { | 1009 | if (!acpi_ac_dir) |
| 1790 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1791 | "acpi_lock_ac_dir() failed")); | ||
| 1792 | return -ENODEV; | 1010 | return -ENODEV; |
| 1793 | } | ||
| 1794 | |||
| 1795 | acpi_battery_dir = acpi_lock_battery_dir(); | 1011 | acpi_battery_dir = acpi_lock_battery_dir(); |
| 1796 | if (!acpi_battery_dir) { | 1012 | if (!acpi_battery_dir) { |
| 1797 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1798 | "acpi_lock_battery_dir() failed")); | ||
| 1799 | acpi_sbs_rmdirs(); | 1013 | acpi_sbs_rmdirs(); |
| 1800 | return -ENODEV; | 1014 | return -ENODEV; |
| 1801 | } | 1015 | } |
| 1802 | 1016 | #endif | |
| 1803 | result = acpi_bus_register_driver(&acpi_sbs_driver); | 1017 | result = acpi_bus_register_driver(&acpi_sbs_driver); |
| 1804 | if (result < 0) { | 1018 | if (result < 0) { |
| 1805 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1806 | "acpi_bus_register_driver() failed")); | ||
| 1807 | acpi_sbs_rmdirs(); | 1019 | acpi_sbs_rmdirs(); |
| 1808 | return -ENODEV; | 1020 | return -ENODEV; |
| 1809 | } | 1021 | } |
| 1810 | |||
| 1811 | return 0; | 1022 | return 0; |
| 1812 | } | 1023 | } |
| 1813 | 1024 | ||
| 1814 | static void __exit acpi_sbs_exit(void) | 1025 | static void __exit acpi_sbs_exit(void) |
| 1815 | { | 1026 | { |
| 1816 | acpi_bus_unregister_driver(&acpi_sbs_driver); | 1027 | acpi_bus_unregister_driver(&acpi_sbs_driver); |
| 1817 | |||
| 1818 | acpi_sbs_rmdirs(); | 1028 | acpi_sbs_rmdirs(); |
| 1819 | |||
| 1820 | return; | 1029 | return; |
| 1821 | } | 1030 | } |
| 1822 | 1031 | ||
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c new file mode 100644 index 000000000000..046d7c3ed356 --- /dev/null +++ b/drivers/acpi/sbshc.c | |||
| @@ -0,0 +1,309 @@ | |||
| 1 | /* | ||
| 2 | * SMBus driver for ACPI Embedded Controller (v0.1) | ||
| 3 | * | ||
| 4 | * Copyright (c) 2007 Alexey Starikovskiy | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation version 2. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <acpi/acpi_bus.h> | ||
| 12 | #include <acpi/acpi_drivers.h> | ||
| 13 | #include <acpi/actypes.h> | ||
| 14 | #include <linux/wait.h> | ||
| 15 | #include <linux/delay.h> | ||
| 16 | #include <linux/interrupt.h> | ||
| 17 | #include "sbshc.h" | ||
| 18 | |||
| 19 | #define ACPI_SMB_HC_CLASS "smbus_host_controller" | ||
| 20 | #define ACPI_SMB_HC_DEVICE_NAME "ACPI SMBus HC" | ||
| 21 | |||
| 22 | struct acpi_smb_hc { | ||
| 23 | struct acpi_ec *ec; | ||
| 24 | struct mutex lock; | ||
| 25 | wait_queue_head_t wait; | ||
| 26 | u8 offset; | ||
| 27 | u8 query_bit; | ||
| 28 | smbus_alarm_callback callback; | ||
| 29 | void *context; | ||
| 30 | }; | ||
| 31 | |||
| 32 | static int acpi_smbus_hc_add(struct acpi_device *device); | ||
| 33 | static int acpi_smbus_hc_remove(struct acpi_device *device, int type); | ||
| 34 | |||
| 35 | static const struct acpi_device_id sbs_device_ids[] = { | ||
| 36 | {"ACPI0001", 0}, | ||
| 37 | {"ACPI0005", 0}, | ||
| 38 | {"", 0}, | ||
| 39 | }; | ||
| 40 | |||
| 41 | MODULE_DEVICE_TABLE(acpi, sbs_device_ids); | ||
| 42 | |||
| 43 | static struct acpi_driver acpi_smb_hc_driver = { | ||
| 44 | .name = "smbus_hc", | ||
| 45 | .class = ACPI_SMB_HC_CLASS, | ||
| 46 | .ids = sbs_device_ids, | ||
| 47 | .ops = { | ||
| 48 | .add = acpi_smbus_hc_add, | ||
| 49 | .remove = acpi_smbus_hc_remove, | ||
| 50 | }, | ||
| 51 | }; | ||
| 52 | |||
| 53 | union acpi_smb_status { | ||
| 54 | u8 raw; | ||
| 55 | struct { | ||
| 56 | u8 status:5; | ||
| 57 | u8 reserved:1; | ||
| 58 | u8 alarm:1; | ||
| 59 | u8 done:1; | ||
| 60 | } fields; | ||
| 61 | }; | ||
| 62 | |||
| 63 | enum acpi_smb_status_codes { | ||
| 64 | SMBUS_OK = 0, | ||
| 65 | SMBUS_UNKNOWN_FAILURE = 0x07, | ||
| 66 | SMBUS_DEVICE_ADDRESS_NACK = 0x10, | ||
| 67 | SMBUS_DEVICE_ERROR = 0x11, | ||
| 68 | SMBUS_DEVICE_COMMAND_ACCESS_DENIED = 0x12, | ||
| 69 | SMBUS_UNKNOWN_ERROR = 0x13, | ||
| 70 | SMBUS_DEVICE_ACCESS_DENIED = 0x17, | ||
| 71 | SMBUS_TIMEOUT = 0x18, | ||
| 72 | SMBUS_HOST_UNSUPPORTED_PROTOCOL = 0x19, | ||
| 73 | SMBUS_BUSY = 0x1a, | ||
| 74 | SMBUS_PEC_ERROR = 0x1f, | ||
| 75 | }; | ||
| 76 | |||
| 77 | enum acpi_smb_offset { | ||
| 78 | ACPI_SMB_PROTOCOL = 0, /* protocol, PEC */ | ||
| 79 | ACPI_SMB_STATUS = 1, /* status */ | ||
| 80 | ACPI_SMB_ADDRESS = 2, /* address */ | ||
| 81 | ACPI_SMB_COMMAND = 3, /* command */ | ||
| 82 | ACPI_SMB_DATA = 4, /* 32 data registers */ | ||
| 83 | ACPI_SMB_BLOCK_COUNT = 0x24, /* number of data bytes */ | ||
| 84 | ACPI_SMB_ALARM_ADDRESS = 0x25, /* alarm address */ | ||
| 85 | ACPI_SMB_ALARM_DATA = 0x26, /* 2 bytes alarm data */ | ||
| 86 | }; | ||
| 87 | |||
| 88 | static inline int smb_hc_read(struct acpi_smb_hc *hc, u8 address, u8 *data) | ||
| 89 | { | ||
| 90 | return ec_read(hc->offset + address, data); | ||
| 91 | } | ||
| 92 | |||
| 93 | static inline int smb_hc_write(struct acpi_smb_hc *hc, u8 address, u8 data) | ||
| 94 | { | ||
| 95 | return ec_write(hc->offset + address, data); | ||
| 96 | } | ||
| 97 | |||
| 98 | static inline int smb_check_done(struct acpi_smb_hc *hc) | ||
| 99 | { | ||
| 100 | union acpi_smb_status status = {.raw = 0}; | ||
| 101 | smb_hc_read(hc, ACPI_SMB_STATUS, &status.raw); | ||
| 102 | return status.fields.done && (status.fields.status == SMBUS_OK); | ||
| 103 | } | ||
| 104 | |||
| 105 | static int wait_transaction_complete(struct acpi_smb_hc *hc, int timeout) | ||
| 106 | { | ||
| 107 | if (wait_event_timeout(hc->wait, smb_check_done(hc), | ||
| 108 | msecs_to_jiffies(timeout))) | ||
| 109 | return 0; | ||
| 110 | else | ||
| 111 | return -ETIME; | ||
| 112 | } | ||
| 113 | |||
| 114 | int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol, u8 address, | ||
| 115 | u8 command, u8 *data, u8 length) | ||
| 116 | { | ||
| 117 | int ret = -EFAULT, i; | ||
| 118 | u8 temp, sz = 0; | ||
| 119 | |||
| 120 | mutex_lock(&hc->lock); | ||
| 121 | if (smb_hc_read(hc, ACPI_SMB_PROTOCOL, &temp)) | ||
| 122 | goto end; | ||
| 123 | if (temp) { | ||
| 124 | ret = -EBUSY; | ||
| 125 | goto end; | ||
| 126 | } | ||
| 127 | smb_hc_write(hc, ACPI_SMB_COMMAND, command); | ||
| 128 | smb_hc_write(hc, ACPI_SMB_COMMAND, command); | ||
| 129 | if (!(protocol & 0x01)) { | ||
| 130 | smb_hc_write(hc, ACPI_SMB_BLOCK_COUNT, length); | ||
| 131 | for (i = 0; i < length; ++i) | ||
| 132 | smb_hc_write(hc, ACPI_SMB_DATA + i, data[i]); | ||
| 133 | } | ||
| 134 | smb_hc_write(hc, ACPI_SMB_ADDRESS, address << 1); | ||
| 135 | smb_hc_write(hc, ACPI_SMB_PROTOCOL, protocol); | ||
| 136 | /* | ||
| 137 | * Wait for completion. Save the status code, data size, | ||
| 138 | * and data into the return package (if required by the protocol). | ||
| 139 | */ | ||
| 140 | ret = wait_transaction_complete(hc, 1000); | ||
| 141 | if (ret || !(protocol & 0x01)) | ||
| 142 | goto end; | ||
| 143 | switch (protocol) { | ||
| 144 | case SMBUS_RECEIVE_BYTE: | ||
| 145 | case SMBUS_READ_BYTE: | ||
| 146 | sz = 1; | ||
| 147 | break; | ||
| 148 | case SMBUS_READ_WORD: | ||
| 149 | sz = 2; | ||
| 150 | break; | ||
| 151 | case SMBUS_READ_BLOCK: | ||
| 152 | if (smb_hc_read(hc, ACPI_SMB_BLOCK_COUNT, &sz)) { | ||
| 153 | ret = -EFAULT; | ||
| 154 | goto end; | ||
| 155 | } | ||
| 156 | sz &= 0x1f; | ||
| 157 | break; | ||
| 158 | } | ||
| 159 | for (i = 0; i < sz; ++i) | ||
| 160 | smb_hc_read(hc, ACPI_SMB_DATA + i, &data[i]); | ||
| 161 | end: | ||
| 162 | mutex_unlock(&hc->lock); | ||
| 163 | return ret; | ||
| 164 | } | ||
| 165 | |||
| 166 | int acpi_smbus_read(struct acpi_smb_hc *hc, u8 protocol, u8 address, | ||
| 167 | u8 command, u8 *data) | ||
| 168 | { | ||
| 169 | return acpi_smbus_transaction(hc, protocol, address, command, data, 0); | ||
| 170 | } | ||
| 171 | |||
| 172 | EXPORT_SYMBOL_GPL(acpi_smbus_read); | ||
| 173 | |||
| 174 | int acpi_smbus_write(struct acpi_smb_hc *hc, u8 protocol, u8 address, | ||
| 175 | u8 command, u8 *data, u8 length) | ||
| 176 | { | ||
| 177 | return acpi_smbus_transaction(hc, protocol, address, command, data, length); | ||
| 178 | } | ||
| 179 | |||
| 180 | EXPORT_SYMBOL_GPL(acpi_smbus_write); | ||
| 181 | |||
| 182 | int acpi_smbus_register_callback(struct acpi_smb_hc *hc, | ||
| 183 | smbus_alarm_callback callback, void *context) | ||
| 184 | { | ||
| 185 | mutex_lock(&hc->lock); | ||
| 186 | hc->callback = callback; | ||
| 187 | hc->context = context; | ||
| 188 | mutex_unlock(&hc->lock); | ||
| 189 | return 0; | ||
| 190 | } | ||
| 191 | |||
| 192 | EXPORT_SYMBOL_GPL(acpi_smbus_register_callback); | ||
| 193 | |||
| 194 | int acpi_smbus_unregister_callback(struct acpi_smb_hc *hc) | ||
| 195 | { | ||
| 196 | mutex_lock(&hc->lock); | ||
| 197 | hc->callback = NULL; | ||
| 198 | hc->context = NULL; | ||
| 199 | mutex_unlock(&hc->lock); | ||
| 200 | return 0; | ||
| 201 | } | ||
| 202 | |||
| 203 | EXPORT_SYMBOL_GPL(acpi_smbus_unregister_callback); | ||
| 204 | |||
| 205 | static void acpi_smbus_callback(void *context) | ||
| 206 | { | ||
| 207 | struct acpi_smb_hc *hc = context; | ||
| 208 | |||
| 209 | if (hc->callback) | ||
| 210 | hc->callback(hc->context); | ||
| 211 | } | ||
| 212 | |||
| 213 | static int smbus_alarm(void *context) | ||
| 214 | { | ||
| 215 | struct acpi_smb_hc *hc = context; | ||
| 216 | union acpi_smb_status status; | ||
| 217 | if (smb_hc_read(hc, ACPI_SMB_STATUS, &status.raw)) | ||
| 218 | return 0; | ||
| 219 | /* Check if it is only a completion notify */ | ||
| 220 | if (status.fields.done) | ||
| 221 | wake_up(&hc->wait); | ||
| 222 | if (!status.fields.alarm) | ||
| 223 | return 0; | ||
| 224 | mutex_lock(&hc->lock); | ||
| 225 | smb_hc_write(hc, ACPI_SMB_STATUS, status.raw); | ||
| 226 | if (hc->callback) | ||
| 227 | acpi_os_execute(OSL_GPE_HANDLER, acpi_smbus_callback, hc); | ||
| 228 | mutex_unlock(&hc->lock); | ||
| 229 | return 0; | ||
| 230 | } | ||
| 231 | |||
| 232 | typedef int (*acpi_ec_query_func) (void *data); | ||
| 233 | |||
| 234 | extern int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, | ||
| 235 | acpi_handle handle, acpi_ec_query_func func, | ||
| 236 | void *data); | ||
| 237 | |||
| 238 | static int acpi_smbus_hc_add(struct acpi_device *device) | ||
| 239 | { | ||
| 240 | int status; | ||
| 241 | unsigned long val; | ||
| 242 | struct acpi_smb_hc *hc; | ||
| 243 | |||
| 244 | if (!device) | ||
| 245 | return -EINVAL; | ||
| 246 | |||
| 247 | status = acpi_evaluate_integer(device->handle, "_EC", NULL, &val); | ||
| 248 | if (ACPI_FAILURE(status)) { | ||
| 249 | printk(KERN_ERR PREFIX "error obtaining _EC.\n"); | ||
| 250 | return -EIO; | ||
| 251 | } | ||
| 252 | |||
| 253 | strcpy(acpi_device_name(device), ACPI_SMB_HC_DEVICE_NAME); | ||
| 254 | strcpy(acpi_device_class(device), ACPI_SMB_HC_CLASS); | ||
| 255 | |||
| 256 | hc = kzalloc(sizeof(struct acpi_smb_hc), GFP_KERNEL); | ||
| 257 | if (!hc) | ||
| 258 | return -ENOMEM; | ||
| 259 | mutex_init(&hc->lock); | ||
| 260 | init_waitqueue_head(&hc->wait); | ||
| 261 | |||
| 262 | hc->ec = acpi_driver_data(device->parent); | ||
| 263 | hc->offset = (val >> 8) & 0xff; | ||
| 264 | hc->query_bit = val & 0xff; | ||
| 265 | acpi_driver_data(device) = hc; | ||
| 266 | |||
| 267 | acpi_ec_add_query_handler(hc->ec, hc->query_bit, NULL, smbus_alarm, hc); | ||
| 268 | printk(KERN_INFO PREFIX "SBS HC: EC = 0x%p, offset = 0x%0x, query_bit = 0x%0x\n", | ||
| 269 | hc->ec, hc->offset, hc->query_bit); | ||
| 270 | |||
| 271 | return 0; | ||
| 272 | } | ||
| 273 | |||
| 274 | extern void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit); | ||
| 275 | |||
| 276 | static int acpi_smbus_hc_remove(struct acpi_device *device, int type) | ||
| 277 | { | ||
| 278 | struct acpi_smb_hc *hc; | ||
| 279 | |||
| 280 | if (!device) | ||
| 281 | return -EINVAL; | ||
| 282 | |||
| 283 | hc = acpi_driver_data(device); | ||
| 284 | acpi_ec_remove_query_handler(hc->ec, hc->query_bit); | ||
| 285 | kfree(hc); | ||
| 286 | return 0; | ||
| 287 | } | ||
| 288 | |||
| 289 | static int __init acpi_smb_hc_init(void) | ||
| 290 | { | ||
| 291 | int result; | ||
| 292 | |||
| 293 | result = acpi_bus_register_driver(&acpi_smb_hc_driver); | ||
| 294 | if (result < 0) | ||
| 295 | return -ENODEV; | ||
| 296 | return 0; | ||
| 297 | } | ||
| 298 | |||
| 299 | static void __exit acpi_smb_hc_exit(void) | ||
| 300 | { | ||
| 301 | acpi_bus_unregister_driver(&acpi_smb_hc_driver); | ||
| 302 | } | ||
| 303 | |||
| 304 | module_init(acpi_smb_hc_init); | ||
| 305 | module_exit(acpi_smb_hc_exit); | ||
| 306 | |||
| 307 | MODULE_LICENSE("GPL"); | ||
| 308 | MODULE_AUTHOR("Alexey Starikovskiy"); | ||
| 309 | MODULE_DESCRIPTION("ACPI SMBus HC driver"); | ||
diff --git a/drivers/acpi/sbshc.h b/drivers/acpi/sbshc.h new file mode 100644 index 000000000000..3bda3491a97b --- /dev/null +++ b/drivers/acpi/sbshc.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | struct acpi_smb_hc; | ||
| 2 | enum acpi_smb_protocol { | ||
| 3 | SMBUS_WRITE_QUICK = 2, | ||
| 4 | SMBUS_READ_QUICK = 3, | ||
| 5 | SMBUS_SEND_BYTE = 4, | ||
| 6 | SMBUS_RECEIVE_BYTE = 5, | ||
| 7 | SMBUS_WRITE_BYTE = 6, | ||
| 8 | SMBUS_READ_BYTE = 7, | ||
| 9 | SMBUS_WRITE_WORD = 8, | ||
| 10 | SMBUS_READ_WORD = 9, | ||
| 11 | SMBUS_WRITE_BLOCK = 0xa, | ||
| 12 | SMBUS_READ_BLOCK = 0xb, | ||
| 13 | SMBUS_PROCESS_CALL = 0xc, | ||
| 14 | SMBUS_BLOCK_PROCESS_CALL = 0xd, | ||
| 15 | }; | ||
| 16 | |||
| 17 | static const u8 SMBUS_PEC = 0x80; | ||
| 18 | |||
| 19 | typedef void (*smbus_alarm_callback)(void *context); | ||
| 20 | |||
| 21 | extern int acpi_smbus_read(struct acpi_smb_hc *hc, u8 protocol, u8 address, | ||
| 22 | u8 command, u8 * data); | ||
| 23 | extern int acpi_smbus_write(struct acpi_smb_hc *hc, u8 protocol, u8 slave_address, | ||
| 24 | u8 command, u8 * data, u8 length); | ||
| 25 | extern int acpi_smbus_register_callback(struct acpi_smb_hc *hc, | ||
| 26 | smbus_alarm_callback callback, void *context); | ||
| 27 | extern int acpi_smbus_unregister_callback(struct acpi_smb_hc *hc); | ||
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 9426ac1fc86b..be616317fe53 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c | |||
| @@ -255,6 +255,11 @@ static int acpi_hibernation_enter(void) | |||
| 255 | 255 | ||
| 256 | static void acpi_hibernation_finish(void) | 256 | static void acpi_hibernation_finish(void) |
| 257 | { | 257 | { |
| 258 | /* | ||
| 259 | * If ACPI is not enabled by the BIOS and the boot kernel, we need to | ||
| 260 | * enable it here. | ||
| 261 | */ | ||
| 262 | acpi_enable(); | ||
| 258 | acpi_leave_sleep_state(ACPI_STATE_S4); | 263 | acpi_leave_sleep_state(ACPI_STATE_S4); |
| 259 | acpi_disable_wakeup_device(ACPI_STATE_S4); | 264 | acpi_disable_wakeup_device(ACPI_STATE_S4); |
| 260 | 265 | ||
diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index 8cc9492ffbf2..5f1d85f2ffe4 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c | |||
| @@ -400,7 +400,7 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) | |||
| 400 | u32 table_count; | 400 | u32 table_count; |
| 401 | struct acpi_table_header *table; | 401 | struct acpi_table_header *table; |
| 402 | acpi_physical_address address; | 402 | acpi_physical_address address; |
| 403 | acpi_physical_address rsdt_address; | 403 | acpi_physical_address uninitialized_var(rsdt_address); |
| 404 | u32 length; | 404 | u32 length; |
| 405 | u8 *table_entry; | 405 | u8 *table_entry; |
| 406 | acpi_status status; | 406 | acpi_status status; |
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index bc6d5866ef98..69ec73b0239d 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c | |||
| @@ -195,6 +195,7 @@ struct acpi_thermal { | |||
| 195 | struct acpi_thermal_trips trips; | 195 | struct acpi_thermal_trips trips; |
| 196 | struct acpi_handle_list devices; | 196 | struct acpi_handle_list devices; |
| 197 | struct timer_list timer; | 197 | struct timer_list timer; |
| 198 | struct mutex lock; | ||
| 198 | }; | 199 | }; |
| 199 | 200 | ||
| 200 | static const struct file_operations acpi_thermal_state_fops = { | 201 | static const struct file_operations acpi_thermal_state_fops = { |
| @@ -711,6 +712,7 @@ static void acpi_thermal_check(void *data) | |||
| 711 | int result = 0; | 712 | int result = 0; |
| 712 | struct acpi_thermal *tz = data; | 713 | struct acpi_thermal *tz = data; |
| 713 | unsigned long sleep_time = 0; | 714 | unsigned long sleep_time = 0; |
| 715 | unsigned long timeout_jiffies = 0; | ||
| 714 | int i = 0; | 716 | int i = 0; |
| 715 | struct acpi_thermal_state state; | 717 | struct acpi_thermal_state state; |
| 716 | 718 | ||
| @@ -720,11 +722,15 @@ static void acpi_thermal_check(void *data) | |||
| 720 | return; | 722 | return; |
| 721 | } | 723 | } |
| 722 | 724 | ||
| 725 | /* Check if someone else is already running */ | ||
| 726 | if (!mutex_trylock(&tz->lock)) | ||
| 727 | return; | ||
| 728 | |||
| 723 | state = tz->state; | 729 | state = tz->state; |
| 724 | 730 | ||
| 725 | result = acpi_thermal_get_temperature(tz); | 731 | result = acpi_thermal_get_temperature(tz); |
| 726 | if (result) | 732 | if (result) |
| 727 | return; | 733 | goto unlock; |
| 728 | 734 | ||
| 729 | memset(&tz->state, 0, sizeof(tz->state)); | 735 | memset(&tz->state, 0, sizeof(tz->state)); |
| 730 | 736 | ||
| @@ -787,10 +793,13 @@ static void acpi_thermal_check(void *data) | |||
| 787 | * a thermal event occurs). Note that _TSP and _TZD values are | 793 | * a thermal event occurs). Note that _TSP and _TZD values are |
| 788 | * given in 1/10th seconds (we must covert to milliseconds). | 794 | * given in 1/10th seconds (we must covert to milliseconds). |
| 789 | */ | 795 | */ |
| 790 | if (tz->state.passive) | 796 | if (tz->state.passive) { |
| 791 | sleep_time = tz->trips.passive.tsp * 100; | 797 | sleep_time = tz->trips.passive.tsp * 100; |
| 792 | else if (tz->polling_frequency > 0) | 798 | timeout_jiffies = jiffies + (HZ * sleep_time) / 1000; |
| 799 | } else if (tz->polling_frequency > 0) { | ||
| 793 | sleep_time = tz->polling_frequency * 100; | 800 | sleep_time = tz->polling_frequency * 100; |
| 801 | timeout_jiffies = round_jiffies(jiffies + (HZ * sleep_time) / 1000); | ||
| 802 | } | ||
| 794 | 803 | ||
| 795 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: temperature[%lu] sleep[%lu]\n", | 804 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: temperature[%lu] sleep[%lu]\n", |
| 796 | tz->name, tz->temperature, sleep_time)); | 805 | tz->name, tz->temperature, sleep_time)); |
| @@ -804,17 +813,16 @@ static void acpi_thermal_check(void *data) | |||
| 804 | del_timer(&(tz->timer)); | 813 | del_timer(&(tz->timer)); |
| 805 | } else { | 814 | } else { |
| 806 | if (timer_pending(&(tz->timer))) | 815 | if (timer_pending(&(tz->timer))) |
| 807 | mod_timer(&(tz->timer), | 816 | mod_timer(&(tz->timer), timeout_jiffies); |
| 808 | jiffies + (HZ * sleep_time) / 1000); | ||
| 809 | else { | 817 | else { |
| 810 | tz->timer.data = (unsigned long)tz; | 818 | tz->timer.data = (unsigned long)tz; |
| 811 | tz->timer.function = acpi_thermal_run; | 819 | tz->timer.function = acpi_thermal_run; |
| 812 | tz->timer.expires = jiffies + (HZ * sleep_time) / 1000; | 820 | tz->timer.expires = timeout_jiffies; |
| 813 | add_timer(&(tz->timer)); | 821 | add_timer(&(tz->timer)); |
| 814 | } | 822 | } |
| 815 | } | 823 | } |
| 816 | 824 | unlock: | |
| 817 | return; | 825 | mutex_unlock(&tz->lock); |
| 818 | } | 826 | } |
| 819 | 827 | ||
| 820 | /* -------------------------------------------------------------------------- | 828 | /* -------------------------------------------------------------------------- |
| @@ -1251,7 +1259,7 @@ static int acpi_thermal_add(struct acpi_device *device) | |||
| 1251 | strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME); | 1259 | strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME); |
| 1252 | strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS); | 1260 | strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS); |
| 1253 | acpi_driver_data(device) = tz; | 1261 | acpi_driver_data(device) = tz; |
| 1254 | 1262 | mutex_init(&tz->lock); | |
| 1255 | result = acpi_thermal_get_info(tz); | 1263 | result = acpi_thermal_get_info(tz); |
| 1256 | if (result) | 1264 | if (result) |
| 1257 | goto end; | 1265 | goto end; |
| @@ -1321,7 +1329,7 @@ static int acpi_thermal_remove(struct acpi_device *device, int type) | |||
| 1321 | } | 1329 | } |
| 1322 | 1330 | ||
| 1323 | acpi_thermal_remove_fs(device); | 1331 | acpi_thermal_remove_fs(device); |
| 1324 | 1332 | mutex_destroy(&tz->lock); | |
| 1325 | kfree(tz); | 1333 | kfree(tz); |
| 1326 | return 0; | 1334 | return 0; |
| 1327 | } | 1335 | } |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index d05891f16282..f31e3c8749e0 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
| @@ -409,14 +409,17 @@ acpi_video_device_lcd_query_levels(struct acpi_video_device *device, | |||
| 409 | static int | 409 | static int |
| 410 | acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level) | 410 | acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level) |
| 411 | { | 411 | { |
| 412 | int status; | 412 | int status = AE_OK; |
| 413 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | 413 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; |
| 414 | struct acpi_object_list args = { 1, &arg0 }; | 414 | struct acpi_object_list args = { 1, &arg0 }; |
| 415 | 415 | ||
| 416 | 416 | ||
| 417 | arg0.integer.value = level; | 417 | arg0.integer.value = level; |
| 418 | status = acpi_evaluate_object(device->dev->handle, "_BCM", &args, NULL); | ||
| 419 | 418 | ||
| 419 | if (device->cap._BCM) | ||
| 420 | status = acpi_evaluate_object(device->dev->handle, "_BCM", | ||
| 421 | &args, NULL); | ||
| 422 | device->brightness->curr = level; | ||
| 420 | return status; | 423 | return status; |
| 421 | } | 424 | } |
| 422 | 425 | ||
| @@ -424,11 +427,11 @@ static int | |||
| 424 | acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, | 427 | acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, |
| 425 | unsigned long *level) | 428 | unsigned long *level) |
| 426 | { | 429 | { |
| 427 | int status; | 430 | if (device->cap._BQC) |
| 428 | 431 | return acpi_evaluate_integer(device->dev->handle, "_BQC", NULL, | |
| 429 | status = acpi_evaluate_integer(device->dev->handle, "_BQC", NULL, level); | 432 | level); |
| 430 | 433 | *level = device->brightness->curr; | |
| 431 | return status; | 434 | return AE_OK; |
| 432 | } | 435 | } |
| 433 | 436 | ||
| 434 | static int | 437 | static int |
| @@ -1633,9 +1636,20 @@ static int | |||
| 1633 | acpi_video_get_next_level(struct acpi_video_device *device, | 1636 | acpi_video_get_next_level(struct acpi_video_device *device, |
| 1634 | u32 level_current, u32 event) | 1637 | u32 level_current, u32 event) |
| 1635 | { | 1638 | { |
| 1636 | int min, max, min_above, max_below, i, l; | 1639 | int min, max, min_above, max_below, i, l, delta = 255; |
| 1637 | max = max_below = 0; | 1640 | max = max_below = 0; |
| 1638 | min = min_above = 255; | 1641 | min = min_above = 255; |
| 1642 | /* Find closest level to level_current */ | ||
| 1643 | for (i = 0; i < device->brightness->count; i++) { | ||
| 1644 | l = device->brightness->levels[i]; | ||
| 1645 | if (abs(l - level_current) < abs(delta)) { | ||
| 1646 | delta = l - level_current; | ||
| 1647 | if (!delta) | ||
| 1648 | break; | ||
| 1649 | } | ||
| 1650 | } | ||
| 1651 | /* Ajust level_current to closest available level */ | ||
| 1652 | level_current += delta; | ||
| 1639 | for (i = 0; i < device->brightness->count; i++) { | 1653 | for (i = 0; i < device->brightness->count; i++) { |
| 1640 | l = device->brightness->levels[i]; | 1654 | l = device->brightness->levels[i]; |
| 1641 | if (l < min) | 1655 | if (l < min) |
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 3b8bf1812dc8..6996eb5b7506 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c | |||
| @@ -921,6 +921,13 @@ static int piix_broken_suspend(void) | |||
| 921 | { | 921 | { |
| 922 | static struct dmi_system_id sysids[] = { | 922 | static struct dmi_system_id sysids[] = { |
| 923 | { | 923 | { |
| 924 | .ident = "TECRA M3", | ||
| 925 | .matches = { | ||
| 926 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
| 927 | DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M3"), | ||
| 928 | }, | ||
| 929 | }, | ||
| 930 | { | ||
| 924 | .ident = "TECRA M5", | 931 | .ident = "TECRA M5", |
| 925 | .matches = { | 932 | .matches = { |
| 926 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 933 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), |
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c index 4ca7fd6118d5..5dea3584c6c2 100644 --- a/drivers/ata/pata_ixp4xx_cf.c +++ b/drivers/ata/pata_ixp4xx_cf.c | |||
| @@ -189,6 +189,9 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev) | |||
| 189 | data->cs0 = devm_ioremap(&pdev->dev, cs0->start, 0x1000); | 189 | data->cs0 = devm_ioremap(&pdev->dev, cs0->start, 0x1000); |
| 190 | data->cs1 = devm_ioremap(&pdev->dev, cs1->start, 0x1000); | 190 | data->cs1 = devm_ioremap(&pdev->dev, cs1->start, 0x1000); |
| 191 | 191 | ||
| 192 | if (!data->cs0 || !data->cs1) | ||
| 193 | return -ENOMEM; | ||
| 194 | |||
| 192 | irq = platform_get_irq(pdev, 0); | 195 | irq = platform_get_irq(pdev, 0); |
| 193 | if (irq) | 196 | if (irq) |
| 194 | set_irq_type(irq, IRQT_RISING); | 197 | set_irq_type(irq, IRQT_RISING); |
diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index ae206f35f747..b45506f1ef73 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c | |||
| @@ -44,10 +44,10 @@ static int marvell_pre_reset(struct ata_port *ap, unsigned long deadline) | |||
| 44 | return -ENOMEM; | 44 | return -ENOMEM; |
| 45 | printk("BAR5:"); | 45 | printk("BAR5:"); |
| 46 | for(i = 0; i <= 0x0F; i++) | 46 | for(i = 0; i <= 0x0F; i++) |
| 47 | printk("%02X:%02X ", i, readb(barp + i)); | 47 | printk("%02X:%02X ", i, ioread8(barp + i)); |
| 48 | printk("\n"); | 48 | printk("\n"); |
| 49 | 49 | ||
| 50 | devices = readl(barp + 0x0C); | 50 | devices = ioread32(barp + 0x0C); |
| 51 | pci_iounmap(pdev, barp); | 51 | pci_iounmap(pdev, barp); |
| 52 | 52 | ||
| 53 | if ((pdev->device == 0x6145) && (ap->port_no == 0) && | 53 | if ((pdev->device == 0x6145) && (ap->port_no == 0) && |
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 11bf6c7ac122..cb7dec97fee6 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c | |||
| @@ -313,7 +313,10 @@ enum { | |||
| 313 | #define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE) | 313 | #define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE) |
| 314 | 314 | ||
| 315 | enum { | 315 | enum { |
| 316 | MV_DMA_BOUNDARY = 0xffffffffU, | 316 | /* DMA boundary 0xffff is required by the s/g splitting |
| 317 | * we need on /length/ in mv_fill-sg(). | ||
| 318 | */ | ||
| 319 | MV_DMA_BOUNDARY = 0xffffU, | ||
| 317 | 320 | ||
| 318 | /* mask of register bits containing lower 32 bits | 321 | /* mask of register bits containing lower 32 bits |
| 319 | * of EDMA request queue DMA address | 322 | * of EDMA request queue DMA address |
| @@ -448,7 +451,7 @@ static struct scsi_host_template mv5_sht = { | |||
| 448 | .queuecommand = ata_scsi_queuecmd, | 451 | .queuecommand = ata_scsi_queuecmd, |
| 449 | .can_queue = ATA_DEF_QUEUE, | 452 | .can_queue = ATA_DEF_QUEUE, |
| 450 | .this_id = ATA_SHT_THIS_ID, | 453 | .this_id = ATA_SHT_THIS_ID, |
| 451 | .sg_tablesize = MV_MAX_SG_CT, | 454 | .sg_tablesize = MV_MAX_SG_CT / 2, |
| 452 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 455 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
| 453 | .emulated = ATA_SHT_EMULATED, | 456 | .emulated = ATA_SHT_EMULATED, |
| 454 | .use_clustering = 1, | 457 | .use_clustering = 1, |
| @@ -466,7 +469,7 @@ static struct scsi_host_template mv6_sht = { | |||
| 466 | .queuecommand = ata_scsi_queuecmd, | 469 | .queuecommand = ata_scsi_queuecmd, |
| 467 | .can_queue = ATA_DEF_QUEUE, | 470 | .can_queue = ATA_DEF_QUEUE, |
| 468 | .this_id = ATA_SHT_THIS_ID, | 471 | .this_id = ATA_SHT_THIS_ID, |
| 469 | .sg_tablesize = MV_MAX_SG_CT, | 472 | .sg_tablesize = MV_MAX_SG_CT / 2, |
| 470 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 473 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
| 471 | .emulated = ATA_SHT_EMULATED, | 474 | .emulated = ATA_SHT_EMULATED, |
| 472 | .use_clustering = 1, | 475 | .use_clustering = 1, |
| @@ -1139,15 +1142,27 @@ static unsigned int mv_fill_sg(struct ata_queued_cmd *qc) | |||
| 1139 | dma_addr_t addr = sg_dma_address(sg); | 1142 | dma_addr_t addr = sg_dma_address(sg); |
| 1140 | u32 sg_len = sg_dma_len(sg); | 1143 | u32 sg_len = sg_dma_len(sg); |
| 1141 | 1144 | ||
| 1142 | mv_sg->addr = cpu_to_le32(addr & 0xffffffff); | 1145 | while (sg_len) { |
| 1143 | mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16); | 1146 | u32 offset = addr & 0xffff; |
| 1144 | mv_sg->flags_size = cpu_to_le32(sg_len & 0xffff); | 1147 | u32 len = sg_len; |
| 1148 | |||
| 1149 | if ((offset + sg_len > 0x10000)) | ||
| 1150 | len = 0x10000 - offset; | ||
| 1151 | |||
| 1152 | mv_sg->addr = cpu_to_le32(addr & 0xffffffff); | ||
| 1153 | mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16); | ||
| 1154 | mv_sg->flags_size = cpu_to_le32(len); | ||
| 1145 | 1155 | ||
| 1146 | if (ata_sg_is_last(sg, qc)) | 1156 | sg_len -= len; |
| 1147 | mv_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); | 1157 | addr += len; |
| 1158 | |||
| 1159 | if (!sg_len && ata_sg_is_last(sg, qc)) | ||
| 1160 | mv_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); | ||
| 1161 | |||
| 1162 | mv_sg++; | ||
| 1163 | n_sg++; | ||
| 1164 | } | ||
| 1148 | 1165 | ||
| 1149 | mv_sg++; | ||
| 1150 | n_sg++; | ||
| 1151 | } | 1166 | } |
| 1152 | 1167 | ||
| 1153 | return n_sg; | 1168 | return n_sg; |
diff --git a/drivers/base/core.c b/drivers/base/core.c index 67c92582d6ef..ec86d6fc2360 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
| @@ -586,9 +586,13 @@ void device_initialize(struct device *dev) | |||
| 586 | static struct kobject * get_device_parent(struct device *dev, | 586 | static struct kobject * get_device_parent(struct device *dev, |
| 587 | struct device *parent) | 587 | struct device *parent) |
| 588 | { | 588 | { |
| 589 | /* Set the parent to the class, not the parent device */ | 589 | /* |
| 590 | /* this keeps sysfs from having a symlink to make old udevs happy */ | 590 | * Set the parent to the class, not the parent device |
| 591 | if (dev->class) | 591 | * for topmost devices in class hierarchy. |
| 592 | * This keeps sysfs from having a symlink to make old | ||
| 593 | * udevs happy | ||
| 594 | */ | ||
| 595 | if (dev->class && (!parent || parent->class != dev->class)) | ||
| 592 | return &dev->class->subsys.kobj; | 596 | return &dev->class->subsys.kobj; |
| 593 | else if (parent) | 597 | else if (parent) |
| 594 | return &parent->kobj; | 598 | return &parent->kobj; |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index d68ddbe70f73..c78ff26647ee 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
| @@ -129,7 +129,7 @@ $(obj)/defkeymap.o: $(obj)/defkeymap.c | |||
| 129 | 129 | ||
| 130 | ifdef GENERATE_KEYMAP | 130 | ifdef GENERATE_KEYMAP |
| 131 | 131 | ||
| 132 | $(obj)/defkeymap.c $(obj)/%.c: $(src)/%.map | 132 | $(obj)/defkeymap.c: $(obj)/%.c: $(src)/%.map |
| 133 | loadkeys --mktable $< > $@.tmp | 133 | loadkeys --mktable $< > $@.tmp |
| 134 | sed -e 's/^static *//' $@.tmp > $@ | 134 | sed -e 's/^static *//' $@.tmp > $@ |
| 135 | rm $@.tmp | 135 | rm $@.tmp |
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index a5d0e95a227a..141ca176c397 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c | |||
| @@ -506,11 +506,6 @@ static void intel_i830_init_gtt_entries(void) | |||
| 506 | break; | 506 | break; |
| 507 | } | 507 | } |
| 508 | } else { | 508 | } else { |
| 509 | /* G33's GTT stolen memory is separate from gfx data | ||
| 510 | * stolen memory. | ||
| 511 | */ | ||
| 512 | if (IS_G33) | ||
| 513 | size = 0; | ||
| 514 | switch (gmch_ctrl & I855_GMCH_GMS_MASK) { | 509 | switch (gmch_ctrl & I855_GMCH_GMS_MASK) { |
| 515 | case I855_GMCH_GMS_STOLEN_1M: | 510 | case I855_GMCH_GMS_STOLEN_1M: |
| 516 | gtt_entries = MB(1) - KB(size); | 511 | gtt_entries = MB(1) - KB(size); |
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index 737088bd0780..28b98733beb8 100644 --- a/drivers/char/drm/i915_drv.h +++ b/drivers/char/drm/i915_drv.h | |||
| @@ -210,6 +210,12 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); | |||
| 210 | #define I915REG_INT_MASK_R 0x020a8 | 210 | #define I915REG_INT_MASK_R 0x020a8 |
| 211 | #define I915REG_INT_ENABLE_R 0x020a0 | 211 | #define I915REG_INT_ENABLE_R 0x020a0 |
| 212 | 212 | ||
| 213 | #define I915REG_PIPEASTAT 0x70024 | ||
| 214 | #define I915REG_PIPEBSTAT 0x71024 | ||
| 215 | |||
| 216 | #define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17) | ||
| 217 | #define I915_VBLANK_CLEAR (1UL<<1) | ||
| 218 | |||
| 213 | #define SRX_INDEX 0x3c4 | 219 | #define SRX_INDEX 0x3c4 |
| 214 | #define SRX_DATA 0x3c5 | 220 | #define SRX_DATA 0x3c5 |
| 215 | #define SR01 1 | 221 | #define SR01 1 |
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c index 4b4b2ce89863..bb8e9e9c8201 100644 --- a/drivers/char/drm/i915_irq.c +++ b/drivers/char/drm/i915_irq.c | |||
| @@ -214,6 +214,10 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
| 214 | struct drm_device *dev = (struct drm_device *) arg; | 214 | struct drm_device *dev = (struct drm_device *) arg; |
| 215 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 215 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| 216 | u16 temp; | 216 | u16 temp; |
| 217 | u32 pipea_stats, pipeb_stats; | ||
| 218 | |||
| 219 | pipea_stats = I915_READ(I915REG_PIPEASTAT); | ||
| 220 | pipeb_stats = I915_READ(I915REG_PIPEBSTAT); | ||
| 217 | 221 | ||
| 218 | temp = I915_READ16(I915REG_INT_IDENTITY_R); | 222 | temp = I915_READ16(I915REG_INT_IDENTITY_R); |
| 219 | 223 | ||
| @@ -225,6 +229,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
| 225 | return IRQ_NONE; | 229 | return IRQ_NONE; |
| 226 | 230 | ||
| 227 | I915_WRITE16(I915REG_INT_IDENTITY_R, temp); | 231 | I915_WRITE16(I915REG_INT_IDENTITY_R, temp); |
| 232 | (void) I915_READ16(I915REG_INT_IDENTITY_R); | ||
| 233 | DRM_READMEMORYBARRIER(); | ||
| 228 | 234 | ||
| 229 | dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); | 235 | dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); |
| 230 | 236 | ||
| @@ -252,6 +258,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
| 252 | 258 | ||
| 253 | if (dev_priv->swaps_pending > 0) | 259 | if (dev_priv->swaps_pending > 0) |
| 254 | drm_locked_tasklet(dev, i915_vblank_tasklet); | 260 | drm_locked_tasklet(dev, i915_vblank_tasklet); |
| 261 | I915_WRITE(I915REG_PIPEASTAT, | ||
| 262 | pipea_stats|I915_VBLANK_INTERRUPT_ENABLE| | ||
| 263 | I915_VBLANK_CLEAR); | ||
| 264 | I915_WRITE(I915REG_PIPEBSTAT, | ||
| 265 | pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE| | ||
| 266 | I915_VBLANK_CLEAR); | ||
| 255 | } | 267 | } |
| 256 | 268 | ||
| 257 | return IRQ_HANDLED; | 269 | return IRQ_HANDLED; |
diff --git a/drivers/char/random.c b/drivers/char/random.c index 397c714cf2ba..af274e5a25ee 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
| @@ -1550,11 +1550,13 @@ __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, | |||
| 1550 | * As close as possible to RFC 793, which | 1550 | * As close as possible to RFC 793, which |
| 1551 | * suggests using a 250 kHz clock. | 1551 | * suggests using a 250 kHz clock. |
| 1552 | * Further reading shows this assumes 2 Mb/s networks. | 1552 | * Further reading shows this assumes 2 Mb/s networks. |
| 1553 | * For 10 Gb/s Ethernet, a 1 GHz clock is appropriate. | 1553 | * For 10 Mb/s Ethernet, a 1 MHz clock is appropriate. |
| 1554 | * That's funny, Linux has one built in! Use it! | 1554 | * For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but |
| 1555 | * (Networks are faster now - should this be increased?) | 1555 | * we also need to limit the resolution so that the u32 seq |
| 1556 | * overlaps less than one time per MSL (2 minutes). | ||
| 1557 | * Choosing a clock of 64 ns period is OK. (period of 274 s) | ||
| 1556 | */ | 1558 | */ |
| 1557 | seq += ktime_get_real().tv64; | 1559 | seq += ktime_get_real().tv64 >> 6; |
| 1558 | #if 0 | 1560 | #if 0 |
| 1559 | printk("init_seq(%lx, %lx, %d, %d) = %d\n", | 1561 | printk("init_seq(%lx, %lx, %d, %d) = %d\n", |
| 1560 | saddr, daddr, sport, dport, seq); | 1562 | saddr, daddr, sport, dport, seq); |
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index c6f6f4209739..7a61a2a9aafe 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c | |||
| @@ -770,6 +770,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
| 770 | /* | 770 | /* |
| 771 | * Switching-from response | 771 | * Switching-from response |
| 772 | */ | 772 | */ |
| 773 | acquire_console_sem(); | ||
| 773 | if (vc->vt_newvt >= 0) { | 774 | if (vc->vt_newvt >= 0) { |
| 774 | if (arg == 0) | 775 | if (arg == 0) |
| 775 | /* | 776 | /* |
| @@ -784,7 +785,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
| 784 | * complete the switch. | 785 | * complete the switch. |
| 785 | */ | 786 | */ |
| 786 | int newvt; | 787 | int newvt; |
| 787 | acquire_console_sem(); | ||
| 788 | newvt = vc->vt_newvt; | 788 | newvt = vc->vt_newvt; |
| 789 | vc->vt_newvt = -1; | 789 | vc->vt_newvt = -1; |
| 790 | i = vc_allocate(newvt); | 790 | i = vc_allocate(newvt); |
| @@ -798,7 +798,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
| 798 | * other console switches.. | 798 | * other console switches.. |
| 799 | */ | 799 | */ |
| 800 | complete_change_console(vc_cons[newvt].d); | 800 | complete_change_console(vc_cons[newvt].d); |
| 801 | release_console_sem(); | ||
| 802 | } | 801 | } |
| 803 | } | 802 | } |
| 804 | 803 | ||
| @@ -810,9 +809,12 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
| 810 | /* | 809 | /* |
| 811 | * If it's just an ACK, ignore it | 810 | * If it's just an ACK, ignore it |
| 812 | */ | 811 | */ |
| 813 | if (arg != VT_ACKACQ) | 812 | if (arg != VT_ACKACQ) { |
| 813 | release_console_sem(); | ||
| 814 | return -EINVAL; | 814 | return -EINVAL; |
| 815 | } | ||
| 815 | } | 816 | } |
| 817 | release_console_sem(); | ||
| 816 | 818 | ||
| 817 | return 0; | 819 | return 0; |
| 818 | 820 | ||
| @@ -1030,7 +1032,7 @@ static DECLARE_WAIT_QUEUE_HEAD(vt_activate_queue); | |||
| 1030 | 1032 | ||
| 1031 | /* | 1033 | /* |
| 1032 | * Sleeps until a vt is activated, or the task is interrupted. Returns | 1034 | * Sleeps until a vt is activated, or the task is interrupted. Returns |
| 1033 | * 0 if activation, -EINTR if interrupted. | 1035 | * 0 if activation, -EINTR if interrupted by a signal handler. |
| 1034 | */ | 1036 | */ |
| 1035 | int vt_waitactive(int vt) | 1037 | int vt_waitactive(int vt) |
| 1036 | { | 1038 | { |
| @@ -1055,7 +1057,7 @@ int vt_waitactive(int vt) | |||
| 1055 | break; | 1057 | break; |
| 1056 | } | 1058 | } |
| 1057 | release_console_sem(); | 1059 | release_console_sem(); |
| 1058 | retval = -EINTR; | 1060 | retval = -ERESTARTNOHAND; |
| 1059 | if (signal_pending(current)) | 1061 | if (signal_pending(current)) |
| 1060 | break; | 1062 | break; |
| 1061 | schedule(); | 1063 | schedule(); |
| @@ -1208,15 +1210,18 @@ void change_console(struct vc_data *new_vc) | |||
| 1208 | /* | 1210 | /* |
| 1209 | * Send the signal as privileged - kill_pid() will | 1211 | * Send the signal as privileged - kill_pid() will |
| 1210 | * tell us if the process has gone or something else | 1212 | * tell us if the process has gone or something else |
| 1211 | * is awry | 1213 | * is awry. |
| 1214 | * | ||
| 1215 | * We need to set vt_newvt *before* sending the signal or we | ||
| 1216 | * have a race. | ||
| 1212 | */ | 1217 | */ |
| 1218 | vc->vt_newvt = new_vc->vc_num; | ||
| 1213 | if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) { | 1219 | if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) { |
| 1214 | /* | 1220 | /* |
| 1215 | * It worked. Mark the vt to switch to and | 1221 | * It worked. Mark the vt to switch to and |
| 1216 | * return. The process needs to send us a | 1222 | * return. The process needs to send us a |
| 1217 | * VT_RELDISP ioctl to complete the switch. | 1223 | * VT_RELDISP ioctl to complete the switch. |
| 1218 | */ | 1224 | */ |
| 1219 | vc->vt_newvt = new_vc->vc_num; | ||
| 1220 | return; | 1225 | return; |
| 1221 | } | 1226 | } |
| 1222 | 1227 | ||
diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig index d011a76f8e7a..fe9e768cfbc4 100644 --- a/drivers/firewire/Kconfig +++ b/drivers/firewire/Kconfig | |||
| @@ -11,7 +11,8 @@ config FIREWIRE | |||
| 11 | This is the "Juju" FireWire stack, a new alternative implementation | 11 | This is the "Juju" FireWire stack, a new alternative implementation |
| 12 | designed for robustness and simplicity. You can build either this | 12 | designed for robustness and simplicity. You can build either this |
| 13 | stack, or the classic stack (the ieee1394 driver, ohci1394 etc.) | 13 | stack, or the classic stack (the ieee1394 driver, ohci1394 etc.) |
| 14 | or both. | 14 | or both. Please read http://wiki.linux1394.org/JujuMigration before |
| 15 | you enable the new stack. | ||
| 15 | 16 | ||
| 16 | To compile this driver as a module, say M here: the module will be | 17 | To compile this driver as a module, say M here: the module will be |
| 17 | called firewire-core. It functionally replaces ieee1394, raw1394, | 18 | called firewire-core. It functionally replaces ieee1394, raw1394, |
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index f19eb6daeefd..2fb047b898aa 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c | |||
| @@ -1546,6 +1546,7 @@ static struct pci_device_id pmac_ide_pci_match[] = { | |||
| 1546 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1546 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
| 1547 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA, | 1547 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA, |
| 1548 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1548 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
| 1549 | {}, | ||
| 1549 | }; | 1550 | }; |
| 1550 | 1551 | ||
| 1551 | static struct pci_driver pmac_ide_pci_driver = { | 1552 | static struct pci_driver pmac_ide_pci_driver = { |
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig index e2abe18e575d..7c662ee594a3 100644 --- a/drivers/input/joystick/Kconfig +++ b/drivers/input/joystick/Kconfig | |||
| @@ -277,7 +277,7 @@ config JOYSTICK_XPAD_FF | |||
| 277 | 277 | ||
| 278 | config JOYSTICK_XPAD_LEDS | 278 | config JOYSTICK_XPAD_LEDS |
| 279 | bool "LED Support for Xbox360 controller 'BigX' LED" | 279 | bool "LED Support for Xbox360 controller 'BigX' LED" |
| 280 | depends on LEDS_CLASS && JOYSTICK_XPAD | 280 | depends on JOYSTICK_XPAD && (LEDS_CLASS=y || LEDS_CLASS=JOYSTICK_XPAD) |
| 281 | ---help--- | 281 | ---help--- |
| 282 | This option enables support for the LED which surrounds the Big X on | 282 | This option enables support for the LED which surrounds the Big X on |
| 283 | XBox 360 controller. | 283 | XBox 360 controller. |
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index ec5f4046412f..4910bca52640 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c | |||
| @@ -1135,7 +1135,7 @@ isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off) | |||
| 1135 | if (count > dev->drv[drvidx]->stavail) | 1135 | if (count > dev->drv[drvidx]->stavail) |
| 1136 | count = dev->drv[drvidx]->stavail; | 1136 | count = dev->drv[drvidx]->stavail; |
| 1137 | len = dev->drv[drvidx]->interface->readstat(buf, count, | 1137 | len = dev->drv[drvidx]->interface->readstat(buf, count, |
| 1138 | drvidx, isdn_minor2chan(minor)); | 1138 | drvidx, isdn_minor2chan(minor - ISDN_MINOR_CTRL)); |
| 1139 | if (len < 0) { | 1139 | if (len < 0) { |
| 1140 | retval = len; | 1140 | retval = len; |
| 1141 | goto out; | 1141 | goto out; |
| @@ -1207,7 +1207,8 @@ isdn_write(struct file *file, const char __user *buf, size_t count, loff_t * off | |||
| 1207 | */ | 1207 | */ |
| 1208 | if (dev->drv[drvidx]->interface->writecmd) | 1208 | if (dev->drv[drvidx]->interface->writecmd) |
| 1209 | retval = dev->drv[drvidx]->interface-> | 1209 | retval = dev->drv[drvidx]->interface-> |
| 1210 | writecmd(buf, count, drvidx, isdn_minor2chan(minor)); | 1210 | writecmd(buf, count, drvidx, |
| 1211 | isdn_minor2chan(minor - ISDN_MINOR_CTRL)); | ||
| 1211 | else | 1212 | else |
| 1212 | retval = count; | 1213 | retval = count; |
| 1213 | goto out; | 1214 | goto out; |
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 0285c4a830eb..66ea3cbc369c 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c | |||
| @@ -754,9 +754,11 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts) | |||
| 754 | ivtv_yuv_close(itv); | 754 | ivtv_yuv_close(itv); |
| 755 | } | 755 | } |
| 756 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV && itv->output_mode == OUT_YUV) | 756 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV && itv->output_mode == OUT_YUV) |
| 757 | itv->output_mode = OUT_NONE; | 757 | itv->output_mode = OUT_NONE; |
| 758 | else if (s->type == IVTV_DEC_STREAM_TYPE_YUV && itv->output_mode == OUT_UDMA_YUV) | ||
| 759 | itv->output_mode = OUT_NONE; | ||
| 758 | else if (s->type == IVTV_DEC_STREAM_TYPE_MPG && itv->output_mode == OUT_MPG) | 760 | else if (s->type == IVTV_DEC_STREAM_TYPE_MPG && itv->output_mode == OUT_MPG) |
| 759 | itv->output_mode = OUT_NONE; | 761 | itv->output_mode = OUT_NONE; |
| 760 | 762 | ||
| 761 | itv->speed = 0; | 763 | itv->speed = 0; |
| 762 | clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags); | 764 | clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags); |
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 73e248fb2ff1..e0a1ff927a5b 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
| @@ -111,6 +111,21 @@ config ASUS_LAPTOP | |||
| 111 | 111 | ||
| 112 | If you have an ACPI-compatible ASUS laptop, say Y or M here. | 112 | If you have an ACPI-compatible ASUS laptop, say Y or M here. |
| 113 | 113 | ||
| 114 | config FUJITSU_LAPTOP | ||
| 115 | tristate "Fujitsu Laptop Extras" | ||
| 116 | depends on X86 | ||
| 117 | depends on ACPI | ||
| 118 | depends on BACKLIGHT_CLASS_DEVICE | ||
| 119 | ---help--- | ||
| 120 | This is a driver for laptops built by Fujitsu: | ||
| 121 | |||
| 122 | * P2xxx/P5xxx/S6xxx/S7xxx series Lifebooks | ||
| 123 | * Possibly other Fujitsu laptop models | ||
| 124 | |||
| 125 | It adds support for LCD brightness control. | ||
| 126 | |||
| 127 | If you have a Fujitsu laptop, say Y or M here. | ||
| 128 | |||
| 114 | config MSI_LAPTOP | 129 | config MSI_LAPTOP |
| 115 | tristate "MSI Laptop Extras" | 130 | tristate "MSI Laptop Extras" |
| 116 | depends on X86 | 131 | depends on X86 |
| @@ -134,6 +149,7 @@ config SONY_LAPTOP | |||
| 134 | tristate "Sony Laptop Extras" | 149 | tristate "Sony Laptop Extras" |
| 135 | depends on X86 && ACPI | 150 | depends on X86 && ACPI |
| 136 | select BACKLIGHT_CLASS_DEVICE | 151 | select BACKLIGHT_CLASS_DEVICE |
| 152 | depends on INPUT | ||
| 137 | ---help--- | 153 | ---help--- |
| 138 | This mini-driver drives the SNC and SPIC devices present in the ACPI | 154 | This mini-driver drives the SNC and SPIC devices present in the ACPI |
| 139 | BIOS of the Sony Vaio laptops. | 155 | BIOS of the Sony Vaio laptops. |
| @@ -156,6 +172,7 @@ config THINKPAD_ACPI | |||
| 156 | select BACKLIGHT_CLASS_DEVICE | 172 | select BACKLIGHT_CLASS_DEVICE |
| 157 | select HWMON | 173 | select HWMON |
| 158 | select NVRAM | 174 | select NVRAM |
| 175 | depends on INPUT | ||
| 159 | ---help--- | 176 | ---help--- |
| 160 | This is a driver for the IBM and Lenovo ThinkPad laptops. It adds | 177 | This is a driver for the IBM and Lenovo ThinkPad laptops. It adds |
| 161 | support for Fn-Fx key combinations, Bluetooth control, video | 178 | support for Fn-Fx key combinations, Bluetooth control, video |
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index b5ce0e3dba86..be90d483d2f9 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
| @@ -14,4 +14,5 @@ obj-$(CONFIG_PHANTOM) += phantom.o | |||
| 14 | obj-$(CONFIG_SGI_IOC4) += ioc4.o | 14 | obj-$(CONFIG_SGI_IOC4) += ioc4.o |
| 15 | obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o | 15 | obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o |
| 16 | obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o | 16 | obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o |
| 17 | obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o | ||
| 17 | obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o | 18 | obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o |
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c new file mode 100644 index 000000000000..d366a6cc1fd9 --- /dev/null +++ b/drivers/misc/fujitsu-laptop.c | |||
| @@ -0,0 +1,358 @@ | |||
| 1 | /*-*-linux-c-*-*/ | ||
| 2 | |||
| 3 | /* | ||
| 4 | Copyright (C) 2007 Jonathan Woithe <jwoithe@physics.adelaide.edu.au> | ||
| 5 | Based on earlier work: | ||
| 6 | Copyright (C) 2003 Shane Spencer <shane@bogomip.com> | ||
| 7 | Adrian Yee <brewt-fujitsu@brewt.org> | ||
| 8 | |||
| 9 | Templated from msi-laptop.c which is copyright by its respective authors. | ||
| 10 | |||
| 11 | This program is free software; you can redistribute it and/or modify | ||
| 12 | it under the terms of the GNU General Public License as published by | ||
| 13 | the Free Software Foundation; either version 2 of the License, or | ||
| 14 | (at your option) any later version. | ||
| 15 | |||
| 16 | This program is distributed in the hope that it will be useful, but | ||
| 17 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 19 | General Public License for more details. | ||
| 20 | |||
| 21 | You should have received a copy of the GNU General Public License | ||
| 22 | along with this program; if not, write to the Free Software | ||
| 23 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
| 24 | 02110-1301, USA. | ||
| 25 | */ | ||
| 26 | |||
| 27 | /* | ||
| 28 | * fujitsu-laptop.c - Fujitsu laptop support, providing access to additional | ||
| 29 | * features made available on a range of Fujitsu laptops including the | ||
| 30 | * P2xxx/P5xxx/S6xxx/S7xxx series. | ||
| 31 | * | ||
| 32 | * This driver exports a few files in /sys/devices/platform/fujitsu-laptop/; | ||
| 33 | * others may be added at a later date. | ||
| 34 | * | ||
| 35 | * lcd_level - Screen brightness: contains a single integer in the | ||
| 36 | * range 0..7. (rw) | ||
| 37 | * | ||
| 38 | * In addition to these platform device attributes the driver | ||
| 39 | * registers itself in the Linux backlight control subsystem and is | ||
| 40 | * available to userspace under /sys/class/backlight/fujitsu-laptop/. | ||
| 41 | * | ||
| 42 | * This driver has been tested on a Fujitsu Lifebook S7020. It should | ||
| 43 | * work on most P-series and S-series Lifebooks, but YMMV. | ||
| 44 | */ | ||
| 45 | |||
| 46 | #include <linux/module.h> | ||
| 47 | #include <linux/kernel.h> | ||
| 48 | #include <linux/init.h> | ||
| 49 | #include <linux/acpi.h> | ||
| 50 | #include <linux/dmi.h> | ||
| 51 | #include <linux/backlight.h> | ||
| 52 | #include <linux/platform_device.h> | ||
| 53 | #include <linux/autoconf.h> | ||
| 54 | |||
| 55 | #define FUJITSU_DRIVER_VERSION "0.3" | ||
| 56 | |||
| 57 | #define FUJITSU_LCD_N_LEVELS 8 | ||
| 58 | |||
| 59 | #define ACPI_FUJITSU_CLASS "fujitsu" | ||
| 60 | #define ACPI_FUJITSU_HID "FUJ02B1" | ||
| 61 | #define ACPI_FUJITSU_DRIVER_NAME "Fujitsu laptop FUJ02B1 ACPI extras driver" | ||
| 62 | #define ACPI_FUJITSU_DEVICE_NAME "Fujitsu FUJ02B1" | ||
| 63 | |||
| 64 | struct fujitsu_t { | ||
| 65 | acpi_handle acpi_handle; | ||
| 66 | struct backlight_device *bl_device; | ||
| 67 | struct platform_device *pf_device; | ||
| 68 | |||
| 69 | unsigned long fuj02b1_state; | ||
| 70 | unsigned int brightness_changed; | ||
| 71 | unsigned int brightness_level; | ||
| 72 | }; | ||
| 73 | |||
| 74 | static struct fujitsu_t *fujitsu; | ||
| 75 | |||
| 76 | /* Hardware access */ | ||
| 77 | |||
| 78 | static int set_lcd_level(int level) | ||
| 79 | { | ||
| 80 | acpi_status status = AE_OK; | ||
| 81 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | ||
| 82 | struct acpi_object_list arg_list = { 1, &arg0 }; | ||
| 83 | acpi_handle handle = NULL; | ||
| 84 | |||
| 85 | if (level < 0 || level >= FUJITSU_LCD_N_LEVELS) | ||
| 86 | return -EINVAL; | ||
| 87 | |||
| 88 | if (!fujitsu) | ||
| 89 | return -EINVAL; | ||
| 90 | |||
| 91 | status = acpi_get_handle(fujitsu->acpi_handle, "SBLL", &handle); | ||
| 92 | if (ACPI_FAILURE(status)) { | ||
| 93 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SBLL not present\n")); | ||
| 94 | return -ENODEV; | ||
| 95 | } | ||
| 96 | |||
| 97 | arg0.integer.value = level; | ||
| 98 | |||
| 99 | status = acpi_evaluate_object(handle, NULL, &arg_list, NULL); | ||
| 100 | if (ACPI_FAILURE(status)) | ||
| 101 | return -ENODEV; | ||
| 102 | |||
| 103 | return 0; | ||
| 104 | } | ||
| 105 | |||
| 106 | static int get_lcd_level(void) | ||
| 107 | { | ||
| 108 | unsigned long state = 0; | ||
| 109 | acpi_status status = AE_OK; | ||
| 110 | |||
| 111 | // Get the Brightness | ||
| 112 | status = | ||
| 113 | acpi_evaluate_integer(fujitsu->acpi_handle, "GBLL", NULL, &state); | ||
| 114 | if (status < 0) | ||
| 115 | return status; | ||
| 116 | |||
| 117 | fujitsu->fuj02b1_state = state; | ||
| 118 | fujitsu->brightness_level = state & 0x0fffffff; | ||
| 119 | |||
| 120 | if (state & 0x80000000) | ||
| 121 | fujitsu->brightness_changed = 1; | ||
| 122 | else | ||
| 123 | fujitsu->brightness_changed = 0; | ||
| 124 | |||
| 125 | if (status < 0) | ||
| 126 | return status; | ||
| 127 | |||
| 128 | return fujitsu->brightness_level; | ||
| 129 | } | ||
| 130 | |||
| 131 | /* Backlight device stuff */ | ||
| 132 | |||
| 133 | static int bl_get_brightness(struct backlight_device *b) | ||
| 134 | { | ||
| 135 | return get_lcd_level(); | ||
| 136 | } | ||
| 137 | |||
| 138 | static int bl_update_status(struct backlight_device *b) | ||
| 139 | { | ||
| 140 | return set_lcd_level(b->props.brightness); | ||
| 141 | } | ||
| 142 | |||
| 143 | static struct backlight_ops fujitsubl_ops = { | ||
| 144 | .get_brightness = bl_get_brightness, | ||
| 145 | .update_status = bl_update_status, | ||
| 146 | }; | ||
| 147 | |||
| 148 | /* Platform device */ | ||
| 149 | |||
| 150 | static ssize_t show_lcd_level(struct device *dev, | ||
| 151 | struct device_attribute *attr, char *buf) | ||
| 152 | { | ||
| 153 | |||
| 154 | int ret; | ||
| 155 | |||
| 156 | ret = get_lcd_level(); | ||
| 157 | if (ret < 0) | ||
| 158 | return ret; | ||
| 159 | |||
| 160 | return sprintf(buf, "%i\n", ret); | ||
| 161 | } | ||
| 162 | |||
| 163 | static ssize_t store_lcd_level(struct device *dev, | ||
| 164 | struct device_attribute *attr, const char *buf, | ||
| 165 | size_t count) | ||
| 166 | { | ||
| 167 | |||
| 168 | int level, ret; | ||
| 169 | |||
| 170 | if (sscanf(buf, "%i", &level) != 1 | ||
| 171 | || (level < 0 || level >= FUJITSU_LCD_N_LEVELS)) | ||
| 172 | return -EINVAL; | ||
| 173 | |||
| 174 | ret = set_lcd_level(level); | ||
| 175 | if (ret < 0) | ||
| 176 | return ret; | ||
| 177 | |||
| 178 | return count; | ||
| 179 | } | ||
| 180 | |||
| 181 | static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level); | ||
| 182 | |||
| 183 | static struct attribute *fujitsupf_attributes[] = { | ||
| 184 | &dev_attr_lcd_level.attr, | ||
| 185 | NULL | ||
| 186 | }; | ||
| 187 | |||
| 188 | static struct attribute_group fujitsupf_attribute_group = { | ||
| 189 | .attrs = fujitsupf_attributes | ||
| 190 | }; | ||
| 191 | |||
| 192 | static struct platform_driver fujitsupf_driver = { | ||
| 193 | .driver = { | ||
| 194 | .name = "fujitsu-laptop", | ||
| 195 | .owner = THIS_MODULE, | ||
| 196 | } | ||
| 197 | }; | ||
| 198 | |||
| 199 | /* ACPI device */ | ||
| 200 | |||
| 201 | int acpi_fujitsu_add(struct acpi_device *device) | ||
| 202 | { | ||
| 203 | int result = 0; | ||
| 204 | int state = 0; | ||
| 205 | |||
| 206 | ACPI_FUNCTION_TRACE("acpi_fujitsu_add"); | ||
| 207 | |||
| 208 | if (!device) | ||
| 209 | return -EINVAL; | ||
| 210 | |||
| 211 | fujitsu->acpi_handle = device->handle; | ||
| 212 | sprintf(acpi_device_name(device), "%s", ACPI_FUJITSU_DEVICE_NAME); | ||
| 213 | sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS); | ||
| 214 | acpi_driver_data(device) = fujitsu; | ||
| 215 | |||
| 216 | result = acpi_bus_get_power(fujitsu->acpi_handle, &state); | ||
| 217 | if (result) { | ||
| 218 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
| 219 | "Error reading power state\n")); | ||
| 220 | goto end; | ||
| 221 | } | ||
| 222 | |||
| 223 | printk(KERN_INFO PREFIX "%s [%s] (%s)\n", | ||
| 224 | acpi_device_name(device), acpi_device_bid(device), | ||
| 225 | !device->power.state ? "on" : "off"); | ||
| 226 | |||
| 227 | end: | ||
| 228 | |||
| 229 | return result; | ||
| 230 | } | ||
| 231 | |||
| 232 | int acpi_fujitsu_remove(struct acpi_device *device, int type) | ||
| 233 | { | ||
| 234 | ACPI_FUNCTION_TRACE("acpi_fujitsu_remove"); | ||
| 235 | |||
| 236 | if (!device || !acpi_driver_data(device)) | ||
| 237 | return -EINVAL; | ||
| 238 | fujitsu->acpi_handle = 0; | ||
| 239 | |||
| 240 | return 0; | ||
| 241 | } | ||
| 242 | |||
| 243 | static const struct acpi_device_id fujitsu_device_ids[] = { | ||
| 244 | {ACPI_FUJITSU_HID, 0}, | ||
| 245 | {"", 0}, | ||
| 246 | }; | ||
| 247 | |||
| 248 | static struct acpi_driver acpi_fujitsu_driver = { | ||
| 249 | .name = ACPI_FUJITSU_DRIVER_NAME, | ||
| 250 | .class = ACPI_FUJITSU_CLASS, | ||
| 251 | .ids = fujitsu_device_ids, | ||
| 252 | .ops = { | ||
| 253 | .add = acpi_fujitsu_add, | ||
| 254 | .remove = acpi_fujitsu_remove, | ||
| 255 | }, | ||
| 256 | }; | ||
| 257 | |||
| 258 | /* Initialization */ | ||
| 259 | |||
| 260 | static int __init fujitsu_init(void) | ||
| 261 | { | ||
| 262 | int ret, result; | ||
| 263 | |||
| 264 | if (acpi_disabled) | ||
| 265 | return -ENODEV; | ||
| 266 | |||
| 267 | fujitsu = kmalloc(sizeof(struct fujitsu_t), GFP_KERNEL); | ||
| 268 | if (!fujitsu) | ||
| 269 | return -ENOMEM; | ||
| 270 | memset(fujitsu, 0, sizeof(struct fujitsu_t)); | ||
| 271 | |||
| 272 | result = acpi_bus_register_driver(&acpi_fujitsu_driver); | ||
| 273 | if (result < 0) { | ||
| 274 | ret = -ENODEV; | ||
| 275 | goto fail_acpi; | ||
| 276 | } | ||
| 277 | |||
| 278 | /* Register backlight stuff */ | ||
| 279 | |||
| 280 | fujitsu->bl_device = | ||
| 281 | backlight_device_register("fujitsu-laptop", NULL, NULL, | ||
| 282 | &fujitsubl_ops); | ||
| 283 | if (IS_ERR(fujitsu->bl_device)) | ||
| 284 | return PTR_ERR(fujitsu->bl_device); | ||
| 285 | |||
| 286 | fujitsu->bl_device->props.max_brightness = FUJITSU_LCD_N_LEVELS - 1; | ||
| 287 | ret = platform_driver_register(&fujitsupf_driver); | ||
| 288 | if (ret) | ||
| 289 | goto fail_backlight; | ||
| 290 | |||
| 291 | /* Register platform stuff */ | ||
| 292 | |||
| 293 | fujitsu->pf_device = platform_device_alloc("fujitsu-laptop", -1); | ||
| 294 | if (!fujitsu->pf_device) { | ||
| 295 | ret = -ENOMEM; | ||
| 296 | goto fail_platform_driver; | ||
| 297 | } | ||
| 298 | |||
| 299 | ret = platform_device_add(fujitsu->pf_device); | ||
| 300 | if (ret) | ||
| 301 | goto fail_platform_device1; | ||
| 302 | |||
| 303 | ret = | ||
| 304 | sysfs_create_group(&fujitsu->pf_device->dev.kobj, | ||
| 305 | &fujitsupf_attribute_group); | ||
| 306 | if (ret) | ||
| 307 | goto fail_platform_device2; | ||
| 308 | |||
| 309 | printk(KERN_INFO "fujitsu-laptop: driver " FUJITSU_DRIVER_VERSION | ||
| 310 | " successfully loaded.\n"); | ||
| 311 | |||
| 312 | return 0; | ||
| 313 | |||
| 314 | fail_platform_device2: | ||
| 315 | |||
| 316 | platform_device_del(fujitsu->pf_device); | ||
| 317 | |||
| 318 | fail_platform_device1: | ||
| 319 | |||
| 320 | platform_device_put(fujitsu->pf_device); | ||
| 321 | |||
| 322 | fail_platform_driver: | ||
| 323 | |||
| 324 | platform_driver_unregister(&fujitsupf_driver); | ||
| 325 | |||
| 326 | fail_backlight: | ||
| 327 | |||
| 328 | backlight_device_unregister(fujitsu->bl_device); | ||
| 329 | |||
| 330 | fail_acpi: | ||
| 331 | |||
| 332 | kfree(fujitsu); | ||
| 333 | |||
| 334 | return ret; | ||
| 335 | } | ||
| 336 | |||
| 337 | static void __exit fujitsu_cleanup(void) | ||
| 338 | { | ||
| 339 | sysfs_remove_group(&fujitsu->pf_device->dev.kobj, | ||
| 340 | &fujitsupf_attribute_group); | ||
| 341 | platform_device_unregister(fujitsu->pf_device); | ||
| 342 | platform_driver_unregister(&fujitsupf_driver); | ||
| 343 | backlight_device_unregister(fujitsu->bl_device); | ||
| 344 | |||
| 345 | acpi_bus_unregister_driver(&acpi_fujitsu_driver); | ||
| 346 | |||
| 347 | kfree(fujitsu); | ||
| 348 | |||
| 349 | printk(KERN_INFO "fujitsu-laptop: driver unloaded.\n"); | ||
| 350 | } | ||
| 351 | |||
| 352 | module_init(fujitsu_init); | ||
| 353 | module_exit(fujitsu_cleanup); | ||
| 354 | |||
| 355 | MODULE_AUTHOR("Jonathan Woithe"); | ||
| 356 | MODULE_DESCRIPTION("Fujitsu laptop extras support"); | ||
| 357 | MODULE_VERSION(FUJITSU_DRIVER_VERSION); | ||
| 358 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index d38ddce592c0..f248080828f2 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c | |||
| @@ -1173,7 +1173,8 @@ static struct acpi_driver sony_nc_driver = { | |||
| 1173 | #define SONYPI_TYPE3_OFFSET 0x12 | 1173 | #define SONYPI_TYPE3_OFFSET 0x12 |
| 1174 | 1174 | ||
| 1175 | struct sony_pic_ioport { | 1175 | struct sony_pic_ioport { |
| 1176 | struct acpi_resource_io io; | 1176 | struct acpi_resource_io io1; |
| 1177 | struct acpi_resource_io io2; | ||
| 1177 | struct list_head list; | 1178 | struct list_head list; |
| 1178 | }; | 1179 | }; |
| 1179 | 1180 | ||
| @@ -1443,11 +1444,11 @@ static u8 sony_pic_call1(u8 dev) | |||
| 1443 | { | 1444 | { |
| 1444 | u8 v1, v2; | 1445 | u8 v1, v2; |
| 1445 | 1446 | ||
| 1446 | wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, | 1447 | wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, |
| 1447 | ITERATIONS_LONG); | 1448 | ITERATIONS_LONG); |
| 1448 | outb(dev, spic_dev.cur_ioport->io.minimum + 4); | 1449 | outb(dev, spic_dev.cur_ioport->io1.minimum + 4); |
| 1449 | v1 = inb_p(spic_dev.cur_ioport->io.minimum + 4); | 1450 | v1 = inb_p(spic_dev.cur_ioport->io1.minimum + 4); |
| 1450 | v2 = inb_p(spic_dev.cur_ioport->io.minimum); | 1451 | v2 = inb_p(spic_dev.cur_ioport->io1.minimum); |
| 1451 | dprintk("sony_pic_call1: 0x%.4x\n", (v2 << 8) | v1); | 1452 | dprintk("sony_pic_call1: 0x%.4x\n", (v2 << 8) | v1); |
| 1452 | return v2; | 1453 | return v2; |
| 1453 | } | 1454 | } |
| @@ -1456,13 +1457,13 @@ static u8 sony_pic_call2(u8 dev, u8 fn) | |||
| 1456 | { | 1457 | { |
| 1457 | u8 v1; | 1458 | u8 v1; |
| 1458 | 1459 | ||
| 1459 | wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, | 1460 | wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, |
| 1460 | ITERATIONS_LONG); | 1461 | ITERATIONS_LONG); |
| 1461 | outb(dev, spic_dev.cur_ioport->io.minimum + 4); | 1462 | outb(dev, spic_dev.cur_ioport->io1.minimum + 4); |
| 1462 | wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, | 1463 | wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, |
| 1463 | ITERATIONS_LONG); | 1464 | ITERATIONS_LONG); |
| 1464 | outb(fn, spic_dev.cur_ioport->io.minimum); | 1465 | outb(fn, spic_dev.cur_ioport->io1.minimum); |
| 1465 | v1 = inb_p(spic_dev.cur_ioport->io.minimum); | 1466 | v1 = inb_p(spic_dev.cur_ioport->io1.minimum); |
| 1466 | dprintk("sony_pic_call2: 0x%.4x\n", v1); | 1467 | dprintk("sony_pic_call2: 0x%.4x\n", v1); |
| 1467 | return v1; | 1468 | return v1; |
| 1468 | } | 1469 | } |
| @@ -1471,13 +1472,13 @@ static u8 sony_pic_call3(u8 dev, u8 fn, u8 v) | |||
| 1471 | { | 1472 | { |
| 1472 | u8 v1; | 1473 | u8 v1; |
| 1473 | 1474 | ||
| 1474 | wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG); | 1475 | wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG); |
| 1475 | outb(dev, spic_dev.cur_ioport->io.minimum + 4); | 1476 | outb(dev, spic_dev.cur_ioport->io1.minimum + 4); |
| 1476 | wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG); | 1477 | wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG); |
| 1477 | outb(fn, spic_dev.cur_ioport->io.minimum); | 1478 | outb(fn, spic_dev.cur_ioport->io1.minimum); |
| 1478 | wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG); | 1479 | wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG); |
| 1479 | outb(v, spic_dev.cur_ioport->io.minimum); | 1480 | outb(v, spic_dev.cur_ioport->io1.minimum); |
| 1480 | v1 = inb_p(spic_dev.cur_ioport->io.minimum); | 1481 | v1 = inb_p(spic_dev.cur_ioport->io1.minimum); |
| 1481 | dprintk("sony_pic_call3: 0x%.4x\n", v1); | 1482 | dprintk("sony_pic_call3: 0x%.4x\n", v1); |
| 1482 | return v1; | 1483 | return v1; |
| 1483 | } | 1484 | } |
| @@ -2074,7 +2075,18 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context) | |||
| 2074 | 2075 | ||
| 2075 | switch (resource->type) { | 2076 | switch (resource->type) { |
| 2076 | case ACPI_RESOURCE_TYPE_START_DEPENDENT: | 2077 | case ACPI_RESOURCE_TYPE_START_DEPENDENT: |
| 2078 | { | ||
| 2079 | /* start IO enumeration */ | ||
| 2080 | struct sony_pic_ioport *ioport = kzalloc(sizeof(*ioport), GFP_KERNEL); | ||
| 2081 | if (!ioport) | ||
| 2082 | return AE_ERROR; | ||
| 2083 | |||
| 2084 | list_add(&ioport->list, &dev->ioports); | ||
| 2085 | return AE_OK; | ||
| 2086 | } | ||
| 2087 | |||
| 2077 | case ACPI_RESOURCE_TYPE_END_DEPENDENT: | 2088 | case ACPI_RESOURCE_TYPE_END_DEPENDENT: |
| 2089 | /* end IO enumeration */ | ||
| 2078 | return AE_OK; | 2090 | return AE_OK; |
| 2079 | 2091 | ||
| 2080 | case ACPI_RESOURCE_TYPE_IRQ: | 2092 | case ACPI_RESOURCE_TYPE_IRQ: |
| @@ -2101,7 +2113,7 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context) | |||
| 2101 | if (!interrupt) | 2113 | if (!interrupt) |
| 2102 | return AE_ERROR; | 2114 | return AE_ERROR; |
| 2103 | 2115 | ||
| 2104 | list_add_tail(&interrupt->list, &dev->interrupts); | 2116 | list_add(&interrupt->list, &dev->interrupts); |
| 2105 | interrupt->irq.triggering = p->triggering; | 2117 | interrupt->irq.triggering = p->triggering; |
| 2106 | interrupt->irq.polarity = p->polarity; | 2118 | interrupt->irq.polarity = p->polarity; |
| 2107 | interrupt->irq.sharable = p->sharable; | 2119 | interrupt->irq.sharable = p->sharable; |
| @@ -2113,18 +2125,27 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context) | |||
| 2113 | case ACPI_RESOURCE_TYPE_IO: | 2125 | case ACPI_RESOURCE_TYPE_IO: |
| 2114 | { | 2126 | { |
| 2115 | struct acpi_resource_io *io = &resource->data.io; | 2127 | struct acpi_resource_io *io = &resource->data.io; |
| 2116 | struct sony_pic_ioport *ioport = NULL; | 2128 | struct sony_pic_ioport *ioport = |
| 2129 | list_first_entry(&dev->ioports, struct sony_pic_ioport, list); | ||
| 2117 | if (!io) { | 2130 | if (!io) { |
| 2118 | dprintk("Blank IO resource\n"); | 2131 | dprintk("Blank IO resource\n"); |
| 2119 | return AE_OK; | 2132 | return AE_OK; |
| 2120 | } | 2133 | } |
| 2121 | 2134 | ||
| 2122 | ioport = kzalloc(sizeof(*ioport), GFP_KERNEL); | 2135 | if (!ioport->io1.minimum) { |
| 2123 | if (!ioport) | 2136 | memcpy(&ioport->io1, io, sizeof(*io)); |
| 2137 | dprintk("IO1 at 0x%.4x (0x%.2x)\n", ioport->io1.minimum, | ||
| 2138 | ioport->io1.address_length); | ||
| 2139 | } | ||
| 2140 | else if (!ioport->io2.minimum) { | ||
| 2141 | memcpy(&ioport->io2, io, sizeof(*io)); | ||
| 2142 | dprintk("IO2 at 0x%.4x (0x%.2x)\n", ioport->io2.minimum, | ||
| 2143 | ioport->io2.address_length); | ||
| 2144 | } | ||
| 2145 | else { | ||
| 2146 | printk(KERN_ERR DRV_PFX "Unknown SPIC Type, more than 2 IO Ports\n"); | ||
| 2124 | return AE_ERROR; | 2147 | return AE_ERROR; |
| 2125 | 2148 | } | |
| 2126 | list_add_tail(&ioport->list, &dev->ioports); | ||
| 2127 | memcpy(&ioport->io, io, sizeof(*io)); | ||
| 2128 | return AE_OK; | 2149 | return AE_OK; |
| 2129 | } | 2150 | } |
| 2130 | default: | 2151 | default: |
| @@ -2199,10 +2220,22 @@ static int sony_pic_enable(struct acpi_device *device, | |||
| 2199 | { | 2220 | { |
| 2200 | acpi_status status; | 2221 | acpi_status status; |
| 2201 | int result = 0; | 2222 | int result = 0; |
| 2223 | /* Type 1 resource layout is: | ||
| 2224 | * IO | ||
| 2225 | * IO | ||
| 2226 | * IRQNoFlags | ||
| 2227 | * End | ||
| 2228 | * | ||
| 2229 | * Type 2 and 3 resource layout is: | ||
| 2230 | * IO | ||
| 2231 | * IRQNoFlags | ||
| 2232 | * End | ||
| 2233 | */ | ||
| 2202 | struct { | 2234 | struct { |
| 2203 | struct acpi_resource io_res; | 2235 | struct acpi_resource res1; |
| 2204 | struct acpi_resource irq_res; | 2236 | struct acpi_resource res2; |
| 2205 | struct acpi_resource end; | 2237 | struct acpi_resource res3; |
| 2238 | struct acpi_resource res4; | ||
| 2206 | } *resource; | 2239 | } *resource; |
| 2207 | struct acpi_buffer buffer = { 0, NULL }; | 2240 | struct acpi_buffer buffer = { 0, NULL }; |
| 2208 | 2241 | ||
| @@ -2217,21 +2250,49 @@ static int sony_pic_enable(struct acpi_device *device, | |||
| 2217 | buffer.length = sizeof(*resource) + 1; | 2250 | buffer.length = sizeof(*resource) + 1; |
| 2218 | buffer.pointer = resource; | 2251 | buffer.pointer = resource; |
| 2219 | 2252 | ||
| 2220 | /* setup io resource */ | 2253 | /* setup Type 1 resources */ |
| 2221 | resource->io_res.type = ACPI_RESOURCE_TYPE_IO; | 2254 | if (spic_dev.model == SONYPI_DEVICE_TYPE1) { |
| 2222 | resource->io_res.length = sizeof(struct acpi_resource); | ||
| 2223 | memcpy(&resource->io_res.data.io, &ioport->io, | ||
| 2224 | sizeof(struct acpi_resource_io)); | ||
| 2225 | 2255 | ||
| 2226 | /* setup irq resource */ | 2256 | /* setup io resources */ |
| 2227 | resource->irq_res.type = ACPI_RESOURCE_TYPE_IRQ; | 2257 | resource->res1.type = ACPI_RESOURCE_TYPE_IO; |
| 2228 | resource->irq_res.length = sizeof(struct acpi_resource); | 2258 | resource->res1.length = sizeof(struct acpi_resource); |
| 2229 | memcpy(&resource->irq_res.data.irq, &irq->irq, | 2259 | memcpy(&resource->res1.data.io, &ioport->io1, |
| 2230 | sizeof(struct acpi_resource_irq)); | 2260 | sizeof(struct acpi_resource_io)); |
| 2231 | /* we requested a shared irq */ | ||
| 2232 | resource->irq_res.data.irq.sharable = ACPI_SHARED; | ||
| 2233 | 2261 | ||
| 2234 | resource->end.type = ACPI_RESOURCE_TYPE_END_TAG; | 2262 | resource->res2.type = ACPI_RESOURCE_TYPE_IO; |
| 2263 | resource->res2.length = sizeof(struct acpi_resource); | ||
| 2264 | memcpy(&resource->res2.data.io, &ioport->io2, | ||
| 2265 | sizeof(struct acpi_resource_io)); | ||
| 2266 | |||
| 2267 | /* setup irq resource */ | ||
| 2268 | resource->res3.type = ACPI_RESOURCE_TYPE_IRQ; | ||
| 2269 | resource->res3.length = sizeof(struct acpi_resource); | ||
| 2270 | memcpy(&resource->res3.data.irq, &irq->irq, | ||
| 2271 | sizeof(struct acpi_resource_irq)); | ||
| 2272 | /* we requested a shared irq */ | ||
| 2273 | resource->res3.data.irq.sharable = ACPI_SHARED; | ||
| 2274 | |||
| 2275 | resource->res4.type = ACPI_RESOURCE_TYPE_END_TAG; | ||
| 2276 | |||
| 2277 | } | ||
| 2278 | /* setup Type 2/3 resources */ | ||
| 2279 | else { | ||
| 2280 | /* setup io resource */ | ||
| 2281 | resource->res1.type = ACPI_RESOURCE_TYPE_IO; | ||
| 2282 | resource->res1.length = sizeof(struct acpi_resource); | ||
| 2283 | memcpy(&resource->res1.data.io, &ioport->io1, | ||
| 2284 | sizeof(struct acpi_resource_io)); | ||
| 2285 | |||
| 2286 | /* setup irq resource */ | ||
| 2287 | resource->res2.type = ACPI_RESOURCE_TYPE_IRQ; | ||
| 2288 | resource->res2.length = sizeof(struct acpi_resource); | ||
| 2289 | memcpy(&resource->res2.data.irq, &irq->irq, | ||
| 2290 | sizeof(struct acpi_resource_irq)); | ||
| 2291 | /* we requested a shared irq */ | ||
| 2292 | resource->res2.data.irq.sharable = ACPI_SHARED; | ||
| 2293 | |||
| 2294 | resource->res3.type = ACPI_RESOURCE_TYPE_END_TAG; | ||
| 2295 | } | ||
| 2235 | 2296 | ||
| 2236 | /* Attempt to set the resource */ | 2297 | /* Attempt to set the resource */ |
| 2237 | dprintk("Evaluating _SRS\n"); | 2298 | dprintk("Evaluating _SRS\n"); |
| @@ -2239,7 +2300,7 @@ static int sony_pic_enable(struct acpi_device *device, | |||
| 2239 | 2300 | ||
| 2240 | /* check for total failure */ | 2301 | /* check for total failure */ |
| 2241 | if (ACPI_FAILURE(status)) { | 2302 | if (ACPI_FAILURE(status)) { |
| 2242 | printk(KERN_ERR DRV_PFX "Error evaluating _SRS"); | 2303 | printk(KERN_ERR DRV_PFX "Error evaluating _SRS\n"); |
| 2243 | result = -ENODEV; | 2304 | result = -ENODEV; |
| 2244 | goto end; | 2305 | goto end; |
| 2245 | } | 2306 | } |
| @@ -2268,11 +2329,14 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id) | |||
| 2268 | 2329 | ||
| 2269 | struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id; | 2330 | struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id; |
| 2270 | 2331 | ||
| 2271 | ev = inb_p(dev->cur_ioport->io.minimum); | 2332 | ev = inb_p(dev->cur_ioport->io1.minimum); |
| 2272 | data_mask = inb_p(dev->cur_ioport->io.minimum + dev->evport_offset); | 2333 | if (dev->cur_ioport->io2.minimum) |
| 2334 | data_mask = inb_p(dev->cur_ioport->io2.minimum); | ||
| 2335 | else | ||
| 2336 | data_mask = inb_p(dev->cur_ioport->io1.minimum + dev->evport_offset); | ||
| 2273 | 2337 | ||
| 2274 | dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", | 2338 | dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", |
| 2275 | ev, data_mask, dev->cur_ioport->io.minimum, dev->evport_offset); | 2339 | ev, data_mask, dev->cur_ioport->io1.minimum, dev->evport_offset); |
| 2276 | 2340 | ||
| 2277 | if (ev == 0x00 || ev == 0xff) | 2341 | if (ev == 0x00 || ev == 0xff) |
| 2278 | return IRQ_HANDLED; | 2342 | return IRQ_HANDLED; |
| @@ -2323,8 +2387,11 @@ static int sony_pic_remove(struct acpi_device *device, int type) | |||
| 2323 | } | 2387 | } |
| 2324 | 2388 | ||
| 2325 | free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev); | 2389 | free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev); |
| 2326 | release_region(spic_dev.cur_ioport->io.minimum, | 2390 | release_region(spic_dev.cur_ioport->io1.minimum, |
| 2327 | spic_dev.cur_ioport->io.address_length); | 2391 | spic_dev.cur_ioport->io1.address_length); |
| 2392 | if (spic_dev.cur_ioport->io2.minimum) | ||
| 2393 | release_region(spic_dev.cur_ioport->io2.minimum, | ||
| 2394 | spic_dev.cur_ioport->io2.address_length); | ||
| 2328 | 2395 | ||
| 2329 | sonypi_compat_exit(); | 2396 | sonypi_compat_exit(); |
| 2330 | 2397 | ||
| @@ -2397,14 +2464,36 @@ static int sony_pic_add(struct acpi_device *device) | |||
| 2397 | goto err_remove_input; | 2464 | goto err_remove_input; |
| 2398 | 2465 | ||
| 2399 | /* request io port */ | 2466 | /* request io port */ |
| 2400 | list_for_each_entry(io, &spic_dev.ioports, list) { | 2467 | list_for_each_entry_reverse(io, &spic_dev.ioports, list) { |
| 2401 | if (request_region(io->io.minimum, io->io.address_length, | 2468 | if (request_region(io->io1.minimum, io->io1.address_length, |
| 2402 | "Sony Programable I/O Device")) { | 2469 | "Sony Programable I/O Device")) { |
| 2403 | dprintk("I/O port: 0x%.4x (0x%.4x) + 0x%.2x\n", | 2470 | dprintk("I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n", |
| 2404 | io->io.minimum, io->io.maximum, | 2471 | io->io1.minimum, io->io1.maximum, |
| 2405 | io->io.address_length); | 2472 | io->io1.address_length); |
| 2406 | spic_dev.cur_ioport = io; | 2473 | /* Type 1 have 2 ioports */ |
| 2407 | break; | 2474 | if (io->io2.minimum) { |
| 2475 | if (request_region(io->io2.minimum, | ||
| 2476 | io->io2.address_length, | ||
| 2477 | "Sony Programable I/O Device")) { | ||
| 2478 | dprintk("I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n", | ||
| 2479 | io->io2.minimum, io->io2.maximum, | ||
| 2480 | io->io2.address_length); | ||
| 2481 | spic_dev.cur_ioport = io; | ||
| 2482 | break; | ||
| 2483 | } | ||
| 2484 | else { | ||
| 2485 | dprintk("Unable to get I/O port2: " | ||
| 2486 | "0x%.4x (0x%.4x) + 0x%.2x\n", | ||
| 2487 | io->io2.minimum, io->io2.maximum, | ||
| 2488 | io->io2.address_length); | ||
| 2489 | release_region(io->io1.minimum, | ||
| 2490 | io->io1.address_length); | ||
| 2491 | } | ||
| 2492 | } | ||
| 2493 | else { | ||
| 2494 | spic_dev.cur_ioport = io; | ||
| 2495 | break; | ||
| 2496 | } | ||
| 2408 | } | 2497 | } |
| 2409 | } | 2498 | } |
| 2410 | if (!spic_dev.cur_ioport) { | 2499 | if (!spic_dev.cur_ioport) { |
| @@ -2414,7 +2503,7 @@ static int sony_pic_add(struct acpi_device *device) | |||
| 2414 | } | 2503 | } |
| 2415 | 2504 | ||
| 2416 | /* request IRQ */ | 2505 | /* request IRQ */ |
| 2417 | list_for_each_entry(irq, &spic_dev.interrupts, list) { | 2506 | list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) { |
| 2418 | if (!request_irq(irq->irq.interrupts[0], sony_pic_irq, | 2507 | if (!request_irq(irq->irq.interrupts[0], sony_pic_irq, |
| 2419 | IRQF_SHARED, "sony-laptop", &spic_dev)) { | 2508 | IRQF_SHARED, "sony-laptop", &spic_dev)) { |
| 2420 | dprintk("IRQ: %d - triggering: %d - " | 2509 | dprintk("IRQ: %d - triggering: %d - " |
| @@ -2462,8 +2551,11 @@ err_free_irq: | |||
| 2462 | free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev); | 2551 | free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev); |
| 2463 | 2552 | ||
| 2464 | err_release_region: | 2553 | err_release_region: |
| 2465 | release_region(spic_dev.cur_ioport->io.minimum, | 2554 | release_region(spic_dev.cur_ioport->io1.minimum, |
| 2466 | spic_dev.cur_ioport->io.address_length); | 2555 | spic_dev.cur_ioport->io1.address_length); |
| 2556 | if (spic_dev.cur_ioport->io2.minimum) | ||
| 2557 | release_region(spic_dev.cur_ioport->io2.minimum, | ||
| 2558 | spic_dev.cur_ioport->io2.address_length); | ||
| 2467 | 2559 | ||
| 2468 | err_remove_compat: | 2560 | err_remove_compat: |
| 2469 | sonypi_compat_exit(); | 2561 | sonypi_compat_exit(); |
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 0222bbaf7b76..37891a8c030a 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | #define IBM_VERSION "0.16" | 24 | #define IBM_VERSION "0.16" |
| 25 | #define TPACPI_SYSFS_VERSION 0x010000 | 25 | #define TPACPI_SYSFS_VERSION 0x020000 |
| 26 | 26 | ||
| 27 | /* | 27 | /* |
| 28 | * Changelog: | 28 | * Changelog: |
| @@ -117,6 +117,12 @@ IBM_BIOS_MODULE_ALIAS("K[U,X-Z]"); | |||
| 117 | 117 | ||
| 118 | #define __unused __attribute__ ((unused)) | 118 | #define __unused __attribute__ ((unused)) |
| 119 | 119 | ||
| 120 | static enum { | ||
| 121 | TPACPI_LIFE_INIT = 0, | ||
| 122 | TPACPI_LIFE_RUNNING, | ||
| 123 | TPACPI_LIFE_EXITING, | ||
| 124 | } tpacpi_lifecycle; | ||
| 125 | |||
| 120 | /**************************************************************************** | 126 | /**************************************************************************** |
| 121 | **************************************************************************** | 127 | **************************************************************************** |
| 122 | * | 128 | * |
| @@ -342,6 +348,9 @@ static void dispatch_acpi_notify(acpi_handle handle, u32 event, void *data) | |||
| 342 | { | 348 | { |
| 343 | struct ibm_struct *ibm = data; | 349 | struct ibm_struct *ibm = data; |
| 344 | 350 | ||
| 351 | if (tpacpi_lifecycle != TPACPI_LIFE_RUNNING) | ||
| 352 | return; | ||
| 353 | |||
| 345 | if (!ibm || !ibm->acpi || !ibm->acpi->notify) | 354 | if (!ibm || !ibm->acpi || !ibm->acpi->notify) |
| 346 | return; | 355 | return; |
| 347 | 356 | ||
| @@ -517,8 +526,10 @@ static char *next_cmd(char **cmds) | |||
| 517 | ****************************************************************************/ | 526 | ****************************************************************************/ |
| 518 | 527 | ||
| 519 | static struct platform_device *tpacpi_pdev; | 528 | static struct platform_device *tpacpi_pdev; |
| 529 | static struct platform_device *tpacpi_sensors_pdev; | ||
| 520 | static struct class_device *tpacpi_hwmon; | 530 | static struct class_device *tpacpi_hwmon; |
| 521 | static struct input_dev *tpacpi_inputdev; | 531 | static struct input_dev *tpacpi_inputdev; |
| 532 | static struct mutex tpacpi_inputdev_send_mutex; | ||
| 522 | 533 | ||
| 523 | 534 | ||
| 524 | static int tpacpi_resume_handler(struct platform_device *pdev) | 535 | static int tpacpi_resume_handler(struct platform_device *pdev) |
| @@ -543,6 +554,12 @@ static struct platform_driver tpacpi_pdriver = { | |||
| 543 | .resume = tpacpi_resume_handler, | 554 | .resume = tpacpi_resume_handler, |
| 544 | }; | 555 | }; |
| 545 | 556 | ||
| 557 | static struct platform_driver tpacpi_hwmon_pdriver = { | ||
| 558 | .driver = { | ||
| 559 | .name = IBM_HWMON_DRVR_NAME, | ||
| 560 | .owner = THIS_MODULE, | ||
| 561 | }, | ||
| 562 | }; | ||
| 546 | 563 | ||
| 547 | /************************************************************************* | 564 | /************************************************************************* |
| 548 | * thinkpad-acpi driver attributes | 565 | * thinkpad-acpi driver attributes |
| @@ -692,6 +709,8 @@ static int parse_strtoul(const char *buf, | |||
| 692 | { | 709 | { |
| 693 | char *endp; | 710 | char *endp; |
| 694 | 711 | ||
| 712 | while (*buf && isspace(*buf)) | ||
| 713 | buf++; | ||
| 695 | *value = simple_strtoul(buf, &endp, 0); | 714 | *value = simple_strtoul(buf, &endp, 0); |
| 696 | while (*endp && isspace(*endp)) | 715 | while (*endp && isspace(*endp)) |
| 697 | endp++; | 716 | endp++; |
| @@ -989,6 +1008,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
| 989 | 1008 | ||
| 990 | int res, i; | 1009 | int res, i; |
| 991 | int status; | 1010 | int status; |
| 1011 | int hkeyv; | ||
| 992 | 1012 | ||
| 993 | vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); | 1013 | vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); |
| 994 | 1014 | ||
| @@ -1014,18 +1034,35 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
| 1014 | return res; | 1034 | return res; |
| 1015 | 1035 | ||
| 1016 | /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, | 1036 | /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, |
| 1017 | A30, R30, R31, T20-22, X20-21, X22-24 */ | 1037 | A30, R30, R31, T20-22, X20-21, X22-24. Detected by checking |
| 1018 | tp_features.hotkey_mask = | 1038 | for HKEY interface version 0x100 */ |
| 1019 | acpi_evalf(hkey_handle, NULL, "DHKN", "qv"); | 1039 | if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) { |
| 1040 | if ((hkeyv >> 8) != 1) { | ||
| 1041 | printk(IBM_ERR "unknown version of the " | ||
| 1042 | "HKEY interface: 0x%x\n", hkeyv); | ||
| 1043 | printk(IBM_ERR "please report this to %s\n", | ||
| 1044 | IBM_MAIL); | ||
| 1045 | } else { | ||
| 1046 | /* | ||
| 1047 | * MHKV 0x100 in A31, R40, R40e, | ||
| 1048 | * T4x, X31, and later | ||
| 1049 | * */ | ||
| 1050 | tp_features.hotkey_mask = 1; | ||
| 1051 | } | ||
| 1052 | } | ||
| 1020 | 1053 | ||
| 1021 | vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", | 1054 | vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", |
| 1022 | str_supported(tp_features.hotkey_mask)); | 1055 | str_supported(tp_features.hotkey_mask)); |
| 1023 | 1056 | ||
| 1024 | if (tp_features.hotkey_mask) { | 1057 | if (tp_features.hotkey_mask) { |
| 1025 | /* MHKA available in A31, R40, R40e, T4x, X31, and later */ | ||
| 1026 | if (!acpi_evalf(hkey_handle, &hotkey_all_mask, | 1058 | if (!acpi_evalf(hkey_handle, &hotkey_all_mask, |
| 1027 | "MHKA", "qd")) | 1059 | "MHKA", "qd")) { |
| 1060 | printk(IBM_ERR | ||
| 1061 | "missing MHKA handler, " | ||
| 1062 | "please report this to %s\n", | ||
| 1063 | IBM_MAIL); | ||
| 1028 | hotkey_all_mask = 0x080cU; /* FN+F12, FN+F4, FN+F3 */ | 1064 | hotkey_all_mask = 0x080cU; /* FN+F12, FN+F4, FN+F3 */ |
| 1065 | } | ||
| 1029 | } | 1066 | } |
| 1030 | 1067 | ||
| 1031 | res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask); | 1068 | res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask); |
| @@ -1131,6 +1168,8 @@ static void tpacpi_input_send_key(unsigned int scancode, | |||
| 1131 | unsigned int keycode) | 1168 | unsigned int keycode) |
| 1132 | { | 1169 | { |
| 1133 | if (keycode != KEY_RESERVED) { | 1170 | if (keycode != KEY_RESERVED) { |
| 1171 | mutex_lock(&tpacpi_inputdev_send_mutex); | ||
| 1172 | |||
| 1134 | input_report_key(tpacpi_inputdev, keycode, 1); | 1173 | input_report_key(tpacpi_inputdev, keycode, 1); |
| 1135 | if (keycode == KEY_UNKNOWN) | 1174 | if (keycode == KEY_UNKNOWN) |
| 1136 | input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, | 1175 | input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, |
| @@ -1142,6 +1181,8 @@ static void tpacpi_input_send_key(unsigned int scancode, | |||
| 1142 | input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, | 1181 | input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, |
| 1143 | scancode); | 1182 | scancode); |
| 1144 | input_sync(tpacpi_inputdev); | 1183 | input_sync(tpacpi_inputdev); |
| 1184 | |||
| 1185 | mutex_unlock(&tpacpi_inputdev_send_mutex); | ||
| 1145 | } | 1186 | } |
| 1146 | } | 1187 | } |
| 1147 | 1188 | ||
| @@ -1149,18 +1190,47 @@ static void tpacpi_input_send_radiosw(void) | |||
| 1149 | { | 1190 | { |
| 1150 | int wlsw; | 1191 | int wlsw; |
| 1151 | 1192 | ||
| 1152 | if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) | 1193 | mutex_lock(&tpacpi_inputdev_send_mutex); |
| 1194 | |||
| 1195 | if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) { | ||
| 1153 | input_report_switch(tpacpi_inputdev, | 1196 | input_report_switch(tpacpi_inputdev, |
| 1154 | SW_RADIO, !!wlsw); | 1197 | SW_RADIO, !!wlsw); |
| 1198 | input_sync(tpacpi_inputdev); | ||
| 1199 | } | ||
| 1200 | |||
| 1201 | mutex_unlock(&tpacpi_inputdev_send_mutex); | ||
| 1155 | } | 1202 | } |
| 1156 | 1203 | ||
| 1157 | static void hotkey_notify(struct ibm_struct *ibm, u32 event) | 1204 | static void hotkey_notify(struct ibm_struct *ibm, u32 event) |
| 1158 | { | 1205 | { |
| 1159 | u32 hkey; | 1206 | u32 hkey; |
| 1160 | unsigned int keycode, scancode; | 1207 | unsigned int keycode, scancode; |
| 1161 | int send_acpi_ev = 0; | 1208 | int send_acpi_ev; |
| 1209 | int ignore_acpi_ev; | ||
| 1210 | |||
| 1211 | if (event != 0x80) { | ||
| 1212 | printk(IBM_ERR "unknown HKEY notification event %d\n", event); | ||
| 1213 | /* forward it to userspace, maybe it knows how to handle it */ | ||
| 1214 | acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class, | ||
| 1215 | ibm->acpi->device->dev.bus_id, | ||
| 1216 | event, 0); | ||
| 1217 | return; | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | while (1) { | ||
| 1221 | if (!acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) { | ||
| 1222 | printk(IBM_ERR "failed to retrieve HKEY event\n"); | ||
| 1223 | return; | ||
| 1224 | } | ||
| 1225 | |||
| 1226 | if (hkey == 0) { | ||
| 1227 | /* queue empty */ | ||
| 1228 | return; | ||
| 1229 | } | ||
| 1230 | |||
| 1231 | send_acpi_ev = 0; | ||
| 1232 | ignore_acpi_ev = 0; | ||
| 1162 | 1233 | ||
| 1163 | if (event == 0x80 && acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) { | ||
| 1164 | switch (hkey >> 12) { | 1234 | switch (hkey >> 12) { |
| 1165 | case 1: | 1235 | case 1: |
| 1166 | /* 0x1000-0x1FFF: key presses */ | 1236 | /* 0x1000-0x1FFF: key presses */ |
| @@ -1182,9 +1252,11 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event) | |||
| 1182 | * eat up known LID events */ | 1252 | * eat up known LID events */ |
| 1183 | if (hkey != 0x5001 && hkey != 0x5002) { | 1253 | if (hkey != 0x5001 && hkey != 0x5002) { |
| 1184 | printk(IBM_ERR | 1254 | printk(IBM_ERR |
| 1185 | "unknown LID-related hotkey event: 0x%04x\n", | 1255 | "unknown LID-related HKEY event: 0x%04x\n", |
| 1186 | hkey); | 1256 | hkey); |
| 1187 | send_acpi_ev = 1; | 1257 | send_acpi_ev = 1; |
| 1258 | } else { | ||
| 1259 | ignore_acpi_ev = 1; | ||
| 1188 | } | 1260 | } |
| 1189 | break; | 1261 | break; |
| 1190 | case 7: | 1262 | case 7: |
| @@ -1202,21 +1274,18 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event) | |||
| 1202 | printk(IBM_NOTICE "unhandled HKEY event 0x%04x\n", hkey); | 1274 | printk(IBM_NOTICE "unhandled HKEY event 0x%04x\n", hkey); |
| 1203 | send_acpi_ev = 1; | 1275 | send_acpi_ev = 1; |
| 1204 | } | 1276 | } |
| 1205 | } else { | ||
| 1206 | printk(IBM_ERR "unknown hotkey notification event %d\n", event); | ||
| 1207 | hkey = 0; | ||
| 1208 | send_acpi_ev = 1; | ||
| 1209 | } | ||
| 1210 | 1277 | ||
| 1211 | /* Legacy events */ | 1278 | /* Legacy events */ |
| 1212 | if (send_acpi_ev || hotkey_report_mode < 2) | 1279 | if (!ignore_acpi_ev && (send_acpi_ev || hotkey_report_mode < 2)) { |
| 1213 | acpi_bus_generate_proc_event(ibm->acpi->device, event, hkey); | 1280 | acpi_bus_generate_proc_event(ibm->acpi->device, event, hkey); |
| 1281 | } | ||
| 1214 | 1282 | ||
| 1215 | /* netlink events */ | 1283 | /* netlink events */ |
| 1216 | if (send_acpi_ev) { | 1284 | if (!ignore_acpi_ev && send_acpi_ev) { |
| 1217 | acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class, | 1285 | acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class, |
| 1218 | ibm->acpi->device->dev.bus_id, | 1286 | ibm->acpi->device->dev.bus_id, |
| 1219 | event, hkey); | 1287 | event, hkey); |
| 1288 | } | ||
| 1220 | } | 1289 | } |
| 1221 | } | 1290 | } |
| 1222 | 1291 | ||
| @@ -2812,7 +2881,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm) | |||
| 2812 | 2881 | ||
| 2813 | switch(thermal_read_mode) { | 2882 | switch(thermal_read_mode) { |
| 2814 | case TPACPI_THERMAL_TPEC_16: | 2883 | case TPACPI_THERMAL_TPEC_16: |
| 2815 | res = sysfs_create_group(&tpacpi_pdev->dev.kobj, | 2884 | res = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj, |
| 2816 | &thermal_temp_input16_group); | 2885 | &thermal_temp_input16_group); |
| 2817 | if (res) | 2886 | if (res) |
| 2818 | return res; | 2887 | return res; |
| @@ -2820,7 +2889,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm) | |||
| 2820 | case TPACPI_THERMAL_TPEC_8: | 2889 | case TPACPI_THERMAL_TPEC_8: |
| 2821 | case TPACPI_THERMAL_ACPI_TMP07: | 2890 | case TPACPI_THERMAL_ACPI_TMP07: |
| 2822 | case TPACPI_THERMAL_ACPI_UPDT: | 2891 | case TPACPI_THERMAL_ACPI_UPDT: |
| 2823 | res = sysfs_create_group(&tpacpi_pdev->dev.kobj, | 2892 | res = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj, |
| 2824 | &thermal_temp_input8_group); | 2893 | &thermal_temp_input8_group); |
| 2825 | if (res) | 2894 | if (res) |
| 2826 | return res; | 2895 | return res; |
| @@ -2837,13 +2906,13 @@ static void thermal_exit(void) | |||
| 2837 | { | 2906 | { |
| 2838 | switch(thermal_read_mode) { | 2907 | switch(thermal_read_mode) { |
| 2839 | case TPACPI_THERMAL_TPEC_16: | 2908 | case TPACPI_THERMAL_TPEC_16: |
| 2840 | sysfs_remove_group(&tpacpi_pdev->dev.kobj, | 2909 | sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, |
| 2841 | &thermal_temp_input16_group); | 2910 | &thermal_temp_input16_group); |
| 2842 | break; | 2911 | break; |
| 2843 | case TPACPI_THERMAL_TPEC_8: | 2912 | case TPACPI_THERMAL_TPEC_8: |
| 2844 | case TPACPI_THERMAL_ACPI_TMP07: | 2913 | case TPACPI_THERMAL_ACPI_TMP07: |
| 2845 | case TPACPI_THERMAL_ACPI_UPDT: | 2914 | case TPACPI_THERMAL_ACPI_UPDT: |
| 2846 | sysfs_remove_group(&tpacpi_pdev->dev.kobj, | 2915 | sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, |
| 2847 | &thermal_temp_input16_group); | 2916 | &thermal_temp_input16_group); |
| 2848 | break; | 2917 | break; |
| 2849 | case TPACPI_THERMAL_NONE: | 2918 | case TPACPI_THERMAL_NONE: |
| @@ -3626,7 +3695,7 @@ static struct device_attribute dev_attr_fan_fan1_input = | |||
| 3626 | __ATTR(fan1_input, S_IRUGO, | 3695 | __ATTR(fan1_input, S_IRUGO, |
| 3627 | fan_fan1_input_show, NULL); | 3696 | fan_fan1_input_show, NULL); |
| 3628 | 3697 | ||
| 3629 | /* sysfs fan fan_watchdog (driver) ------------------------------------- */ | 3698 | /* sysfs fan fan_watchdog (hwmon driver) ------------------------------- */ |
| 3630 | static ssize_t fan_fan_watchdog_show(struct device_driver *drv, | 3699 | static ssize_t fan_fan_watchdog_show(struct device_driver *drv, |
| 3631 | char *buf) | 3700 | char *buf) |
| 3632 | { | 3701 | { |
| @@ -3768,10 +3837,10 @@ static int __init fan_init(struct ibm_init_struct *iibm) | |||
| 3768 | 3837 | ||
| 3769 | if (fan_status_access_mode != TPACPI_FAN_NONE || | 3838 | if (fan_status_access_mode != TPACPI_FAN_NONE || |
| 3770 | fan_control_access_mode != TPACPI_FAN_WR_NONE) { | 3839 | fan_control_access_mode != TPACPI_FAN_WR_NONE) { |
| 3771 | rc = sysfs_create_group(&tpacpi_pdev->dev.kobj, | 3840 | rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj, |
| 3772 | &fan_attr_group); | 3841 | &fan_attr_group); |
| 3773 | if (!(rc < 0)) | 3842 | if (!(rc < 0)) |
| 3774 | rc = driver_create_file(&tpacpi_pdriver.driver, | 3843 | rc = driver_create_file(&tpacpi_hwmon_pdriver.driver, |
| 3775 | &driver_attr_fan_watchdog); | 3844 | &driver_attr_fan_watchdog); |
| 3776 | if (rc < 0) | 3845 | if (rc < 0) |
| 3777 | return rc; | 3846 | return rc; |
| @@ -3854,8 +3923,8 @@ static void fan_exit(void) | |||
| 3854 | vdbg_printk(TPACPI_DBG_EXIT, "cancelling any pending fan watchdog tasks\n"); | 3923 | vdbg_printk(TPACPI_DBG_EXIT, "cancelling any pending fan watchdog tasks\n"); |
| 3855 | 3924 | ||
| 3856 | /* FIXME: can we really do this unconditionally? */ | 3925 | /* FIXME: can we really do this unconditionally? */ |
| 3857 | sysfs_remove_group(&tpacpi_pdev->dev.kobj, &fan_attr_group); | 3926 | sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, &fan_attr_group); |
| 3858 | driver_remove_file(&tpacpi_pdriver.driver, &driver_attr_fan_watchdog); | 3927 | driver_remove_file(&tpacpi_hwmon_pdriver.driver, &driver_attr_fan_watchdog); |
| 3859 | 3928 | ||
| 3860 | cancel_delayed_work(&fan_watchdog_task); | 3929 | cancel_delayed_work(&fan_watchdog_task); |
| 3861 | flush_scheduled_work(); | 3930 | flush_scheduled_work(); |
| @@ -3888,6 +3957,9 @@ static void fan_watchdog_fire(struct work_struct *ignored) | |||
| 3888 | { | 3957 | { |
| 3889 | int rc; | 3958 | int rc; |
| 3890 | 3959 | ||
| 3960 | if (tpacpi_lifecycle != TPACPI_LIFE_RUNNING) | ||
| 3961 | return; | ||
| 3962 | |||
| 3891 | printk(IBM_NOTICE "fan watchdog: enabling fan\n"); | 3963 | printk(IBM_NOTICE "fan watchdog: enabling fan\n"); |
| 3892 | rc = fan_set_enable(); | 3964 | rc = fan_set_enable(); |
| 3893 | if (rc < 0) { | 3965 | if (rc < 0) { |
| @@ -3908,7 +3980,8 @@ static void fan_watchdog_reset(void) | |||
| 3908 | if (fan_watchdog_active) | 3980 | if (fan_watchdog_active) |
| 3909 | cancel_delayed_work(&fan_watchdog_task); | 3981 | cancel_delayed_work(&fan_watchdog_task); |
| 3910 | 3982 | ||
| 3911 | if (fan_watchdog_maxinterval > 0) { | 3983 | if (fan_watchdog_maxinterval > 0 && |
| 3984 | tpacpi_lifecycle != TPACPI_LIFE_EXITING) { | ||
| 3912 | fan_watchdog_active = 1; | 3985 | fan_watchdog_active = 1; |
| 3913 | if (!schedule_delayed_work(&fan_watchdog_task, | 3986 | if (!schedule_delayed_work(&fan_watchdog_task, |
| 3914 | msecs_to_jiffies(fan_watchdog_maxinterval | 3987 | msecs_to_jiffies(fan_watchdog_maxinterval |
| @@ -4302,6 +4375,19 @@ static struct ibm_struct fan_driver_data = { | |||
| 4302 | **************************************************************************** | 4375 | **************************************************************************** |
| 4303 | ****************************************************************************/ | 4376 | ****************************************************************************/ |
| 4304 | 4377 | ||
| 4378 | /* sysfs name ---------------------------------------------------------- */ | ||
| 4379 | static ssize_t thinkpad_acpi_pdev_name_show(struct device *dev, | ||
| 4380 | struct device_attribute *attr, | ||
| 4381 | char *buf) | ||
| 4382 | { | ||
| 4383 | return snprintf(buf, PAGE_SIZE, "%s\n", IBM_NAME); | ||
| 4384 | } | ||
| 4385 | |||
| 4386 | static struct device_attribute dev_attr_thinkpad_acpi_pdev_name = | ||
| 4387 | __ATTR(name, S_IRUGO, thinkpad_acpi_pdev_name_show, NULL); | ||
| 4388 | |||
| 4389 | /* --------------------------------------------------------------------- */ | ||
| 4390 | |||
| 4305 | /* /proc support */ | 4391 | /* /proc support */ |
| 4306 | static struct proc_dir_entry *proc_dir; | 4392 | static struct proc_dir_entry *proc_dir; |
| 4307 | 4393 | ||
| @@ -4674,6 +4760,8 @@ static int __init thinkpad_acpi_module_init(void) | |||
| 4674 | { | 4760 | { |
| 4675 | int ret, i; | 4761 | int ret, i; |
| 4676 | 4762 | ||
| 4763 | tpacpi_lifecycle = TPACPI_LIFE_INIT; | ||
| 4764 | |||
| 4677 | /* Parameter checking */ | 4765 | /* Parameter checking */ |
| 4678 | if (hotkey_report_mode > 2) | 4766 | if (hotkey_report_mode > 2) |
| 4679 | return -EINVAL; | 4767 | return -EINVAL; |
| @@ -4702,19 +4790,31 @@ static int __init thinkpad_acpi_module_init(void) | |||
| 4702 | 4790 | ||
| 4703 | ret = platform_driver_register(&tpacpi_pdriver); | 4791 | ret = platform_driver_register(&tpacpi_pdriver); |
| 4704 | if (ret) { | 4792 | if (ret) { |
| 4705 | printk(IBM_ERR "unable to register platform driver\n"); | 4793 | printk(IBM_ERR "unable to register main platform driver\n"); |
| 4706 | thinkpad_acpi_module_exit(); | 4794 | thinkpad_acpi_module_exit(); |
| 4707 | return ret; | 4795 | return ret; |
| 4708 | } | 4796 | } |
| 4709 | tp_features.platform_drv_registered = 1; | 4797 | tp_features.platform_drv_registered = 1; |
| 4710 | 4798 | ||
| 4799 | ret = platform_driver_register(&tpacpi_hwmon_pdriver); | ||
| 4800 | if (ret) { | ||
| 4801 | printk(IBM_ERR "unable to register hwmon platform driver\n"); | ||
| 4802 | thinkpad_acpi_module_exit(); | ||
| 4803 | return ret; | ||
| 4804 | } | ||
| 4805 | tp_features.sensors_pdrv_registered = 1; | ||
| 4806 | |||
| 4711 | ret = tpacpi_create_driver_attributes(&tpacpi_pdriver.driver); | 4807 | ret = tpacpi_create_driver_attributes(&tpacpi_pdriver.driver); |
| 4808 | if (!ret) { | ||
| 4809 | tp_features.platform_drv_attrs_registered = 1; | ||
| 4810 | ret = tpacpi_create_driver_attributes(&tpacpi_hwmon_pdriver.driver); | ||
| 4811 | } | ||
| 4712 | if (ret) { | 4812 | if (ret) { |
| 4713 | printk(IBM_ERR "unable to create sysfs driver attributes\n"); | 4813 | printk(IBM_ERR "unable to create sysfs driver attributes\n"); |
| 4714 | thinkpad_acpi_module_exit(); | 4814 | thinkpad_acpi_module_exit(); |
| 4715 | return ret; | 4815 | return ret; |
| 4716 | } | 4816 | } |
| 4717 | tp_features.platform_drv_attrs_registered = 1; | 4817 | tp_features.sensors_pdrv_attrs_registered = 1; |
| 4718 | 4818 | ||
| 4719 | 4819 | ||
| 4720 | /* Device initialization */ | 4820 | /* Device initialization */ |
| @@ -4727,7 +4827,26 @@ static int __init thinkpad_acpi_module_init(void) | |||
| 4727 | thinkpad_acpi_module_exit(); | 4827 | thinkpad_acpi_module_exit(); |
| 4728 | return ret; | 4828 | return ret; |
| 4729 | } | 4829 | } |
| 4730 | tpacpi_hwmon = hwmon_device_register(&tpacpi_pdev->dev); | 4830 | tpacpi_sensors_pdev = platform_device_register_simple( |
| 4831 | IBM_HWMON_DRVR_NAME, | ||
| 4832 | -1, NULL, 0); | ||
| 4833 | if (IS_ERR(tpacpi_sensors_pdev)) { | ||
| 4834 | ret = PTR_ERR(tpacpi_sensors_pdev); | ||
| 4835 | tpacpi_sensors_pdev = NULL; | ||
| 4836 | printk(IBM_ERR "unable to register hwmon platform device\n"); | ||
| 4837 | thinkpad_acpi_module_exit(); | ||
| 4838 | return ret; | ||
| 4839 | } | ||
| 4840 | ret = device_create_file(&tpacpi_sensors_pdev->dev, | ||
| 4841 | &dev_attr_thinkpad_acpi_pdev_name); | ||
| 4842 | if (ret) { | ||
| 4843 | printk(IBM_ERR | ||
| 4844 | "unable to create sysfs hwmon device attributes\n"); | ||
| 4845 | thinkpad_acpi_module_exit(); | ||
| 4846 | return ret; | ||
| 4847 | } | ||
| 4848 | tp_features.sensors_pdev_attrs_registered = 1; | ||
| 4849 | tpacpi_hwmon = hwmon_device_register(&tpacpi_sensors_pdev->dev); | ||
| 4731 | if (IS_ERR(tpacpi_hwmon)) { | 4850 | if (IS_ERR(tpacpi_hwmon)) { |
| 4732 | ret = PTR_ERR(tpacpi_hwmon); | 4851 | ret = PTR_ERR(tpacpi_hwmon); |
| 4733 | tpacpi_hwmon = NULL; | 4852 | tpacpi_hwmon = NULL; |
| @@ -4735,6 +4854,7 @@ static int __init thinkpad_acpi_module_init(void) | |||
| 4735 | thinkpad_acpi_module_exit(); | 4854 | thinkpad_acpi_module_exit(); |
| 4736 | return ret; | 4855 | return ret; |
| 4737 | } | 4856 | } |
| 4857 | mutex_init(&tpacpi_inputdev_send_mutex); | ||
| 4738 | tpacpi_inputdev = input_allocate_device(); | 4858 | tpacpi_inputdev = input_allocate_device(); |
| 4739 | if (!tpacpi_inputdev) { | 4859 | if (!tpacpi_inputdev) { |
| 4740 | printk(IBM_ERR "unable to allocate input device\n"); | 4860 | printk(IBM_ERR "unable to allocate input device\n"); |
| @@ -4769,6 +4889,7 @@ static int __init thinkpad_acpi_module_init(void) | |||
| 4769 | tp_features.input_device_registered = 1; | 4889 | tp_features.input_device_registered = 1; |
| 4770 | } | 4890 | } |
| 4771 | 4891 | ||
| 4892 | tpacpi_lifecycle = TPACPI_LIFE_RUNNING; | ||
| 4772 | return 0; | 4893 | return 0; |
| 4773 | } | 4894 | } |
| 4774 | 4895 | ||
| @@ -4776,6 +4897,8 @@ static void thinkpad_acpi_module_exit(void) | |||
| 4776 | { | 4897 | { |
| 4777 | struct ibm_struct *ibm, *itmp; | 4898 | struct ibm_struct *ibm, *itmp; |
| 4778 | 4899 | ||
| 4900 | tpacpi_lifecycle = TPACPI_LIFE_EXITING; | ||
| 4901 | |||
| 4779 | list_for_each_entry_safe_reverse(ibm, itmp, | 4902 | list_for_each_entry_safe_reverse(ibm, itmp, |
| 4780 | &tpacpi_all_drivers, | 4903 | &tpacpi_all_drivers, |
| 4781 | all_drivers) { | 4904 | all_drivers) { |
| @@ -4794,12 +4917,22 @@ static void thinkpad_acpi_module_exit(void) | |||
| 4794 | if (tpacpi_hwmon) | 4917 | if (tpacpi_hwmon) |
| 4795 | hwmon_device_unregister(tpacpi_hwmon); | 4918 | hwmon_device_unregister(tpacpi_hwmon); |
| 4796 | 4919 | ||
| 4920 | if (tp_features.sensors_pdev_attrs_registered) | ||
| 4921 | device_remove_file(&tpacpi_sensors_pdev->dev, | ||
| 4922 | &dev_attr_thinkpad_acpi_pdev_name); | ||
| 4923 | if (tpacpi_sensors_pdev) | ||
| 4924 | platform_device_unregister(tpacpi_sensors_pdev); | ||
| 4797 | if (tpacpi_pdev) | 4925 | if (tpacpi_pdev) |
| 4798 | platform_device_unregister(tpacpi_pdev); | 4926 | platform_device_unregister(tpacpi_pdev); |
| 4799 | 4927 | ||
| 4928 | if (tp_features.sensors_pdrv_attrs_registered) | ||
| 4929 | tpacpi_remove_driver_attributes(&tpacpi_hwmon_pdriver.driver); | ||
| 4800 | if (tp_features.platform_drv_attrs_registered) | 4930 | if (tp_features.platform_drv_attrs_registered) |
| 4801 | tpacpi_remove_driver_attributes(&tpacpi_pdriver.driver); | 4931 | tpacpi_remove_driver_attributes(&tpacpi_pdriver.driver); |
| 4802 | 4932 | ||
| 4933 | if (tp_features.sensors_pdrv_registered) | ||
| 4934 | platform_driver_unregister(&tpacpi_hwmon_pdriver); | ||
| 4935 | |||
| 4803 | if (tp_features.platform_drv_registered) | 4936 | if (tp_features.platform_drv_registered) |
| 4804 | platform_driver_unregister(&tpacpi_pdriver); | 4937 | platform_driver_unregister(&tpacpi_pdriver); |
| 4805 | 4938 | ||
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h index 082a1cbc16c0..c5fdd688cc99 100644 --- a/drivers/misc/thinkpad_acpi.h +++ b/drivers/misc/thinkpad_acpi.h | |||
| @@ -58,13 +58,14 @@ | |||
| 58 | 58 | ||
| 59 | #define IBM_NAME "thinkpad" | 59 | #define IBM_NAME "thinkpad" |
| 60 | #define IBM_DESC "ThinkPad ACPI Extras" | 60 | #define IBM_DESC "ThinkPad ACPI Extras" |
| 61 | #define IBM_FILE "thinkpad_acpi" | 61 | #define IBM_FILE IBM_NAME "_acpi" |
| 62 | #define IBM_URL "http://ibm-acpi.sf.net/" | 62 | #define IBM_URL "http://ibm-acpi.sf.net/" |
| 63 | #define IBM_MAIL "ibm-acpi-devel@lists.sourceforge.net" | 63 | #define IBM_MAIL "ibm-acpi-devel@lists.sourceforge.net" |
| 64 | 64 | ||
| 65 | #define IBM_PROC_DIR "ibm" | 65 | #define IBM_PROC_DIR "ibm" |
| 66 | #define IBM_ACPI_EVENT_PREFIX "ibm" | 66 | #define IBM_ACPI_EVENT_PREFIX "ibm" |
| 67 | #define IBM_DRVR_NAME IBM_FILE | 67 | #define IBM_DRVR_NAME IBM_FILE |
| 68 | #define IBM_HWMON_DRVR_NAME IBM_NAME "_hwmon" | ||
| 68 | 69 | ||
| 69 | #define IBM_LOG IBM_FILE ": " | 70 | #define IBM_LOG IBM_FILE ": " |
| 70 | #define IBM_ERR KERN_ERR IBM_LOG | 71 | #define IBM_ERR KERN_ERR IBM_LOG |
| @@ -171,6 +172,7 @@ static int parse_strtoul(const char *buf, unsigned long max, | |||
| 171 | 172 | ||
| 172 | /* Device model */ | 173 | /* Device model */ |
| 173 | static struct platform_device *tpacpi_pdev; | 174 | static struct platform_device *tpacpi_pdev; |
| 175 | static struct platform_device *tpacpi_sensors_pdev; | ||
| 174 | static struct class_device *tpacpi_hwmon; | 176 | static struct class_device *tpacpi_hwmon; |
| 175 | static struct platform_driver tpacpi_pdriver; | 177 | static struct platform_driver tpacpi_pdriver; |
| 176 | static struct input_dev *tpacpi_inputdev; | 178 | static struct input_dev *tpacpi_inputdev; |
| @@ -233,22 +235,25 @@ struct ibm_init_struct { | |||
| 233 | 235 | ||
| 234 | static struct { | 236 | static struct { |
| 235 | #ifdef CONFIG_THINKPAD_ACPI_BAY | 237 | #ifdef CONFIG_THINKPAD_ACPI_BAY |
| 236 | u16 bay_status:1; | 238 | u32 bay_status:1; |
| 237 | u16 bay_eject:1; | 239 | u32 bay_eject:1; |
| 238 | u16 bay_status2:1; | 240 | u32 bay_status2:1; |
| 239 | u16 bay_eject2:1; | 241 | u32 bay_eject2:1; |
| 240 | #endif | 242 | #endif |
| 241 | u16 bluetooth:1; | 243 | u32 bluetooth:1; |
| 242 | u16 hotkey:1; | 244 | u32 hotkey:1; |
| 243 | u16 hotkey_mask:1; | 245 | u32 hotkey_mask:1; |
| 244 | u16 hotkey_wlsw:1; | 246 | u32 hotkey_wlsw:1; |
| 245 | u16 light:1; | 247 | u32 light:1; |
| 246 | u16 light_status:1; | 248 | u32 light_status:1; |
| 247 | u16 wan:1; | 249 | u32 wan:1; |
| 248 | u16 fan_ctrl_status_undef:1; | 250 | u32 fan_ctrl_status_undef:1; |
| 249 | u16 input_device_registered:1; | 251 | u32 input_device_registered:1; |
| 250 | u16 platform_drv_registered:1; | 252 | u32 platform_drv_registered:1; |
| 251 | u16 platform_drv_attrs_registered:1; | 253 | u32 platform_drv_attrs_registered:1; |
| 254 | u32 sensors_pdrv_registered:1; | ||
| 255 | u32 sensors_pdrv_attrs_registered:1; | ||
| 256 | u32 sensors_pdev_attrs_registered:1; | ||
| 252 | } tp_features; | 257 | } tp_features; |
| 253 | 258 | ||
| 254 | struct thinkpad_id_data { | 259 | struct thinkpad_id_data { |
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 4c3785c9d4b8..9ecc3adcf6c1 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c | |||
| @@ -1726,6 +1726,7 @@ static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wol | |||
| 1726 | case E1000_DEV_ID_82571EB_QUAD_COPPER: | 1726 | case E1000_DEV_ID_82571EB_QUAD_COPPER: |
| 1727 | case E1000_DEV_ID_82571EB_QUAD_FIBER: | 1727 | case E1000_DEV_ID_82571EB_QUAD_FIBER: |
| 1728 | case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE: | 1728 | case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE: |
| 1729 | case E1000_DEV_ID_82571PT_QUAD_COPPER: | ||
| 1729 | case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: | 1730 | case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: |
| 1730 | /* quad port adapters only support WoL on port A */ | 1731 | /* quad port adapters only support WoL on port A */ |
| 1731 | if (!adapter->quad_port_a) { | 1732 | if (!adapter->quad_port_a) { |
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index ba120f7fb0be..8604adbe351c 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c | |||
| @@ -387,6 +387,7 @@ e1000_set_mac_type(struct e1000_hw *hw) | |||
| 387 | case E1000_DEV_ID_82571EB_SERDES_DUAL: | 387 | case E1000_DEV_ID_82571EB_SERDES_DUAL: |
| 388 | case E1000_DEV_ID_82571EB_SERDES_QUAD: | 388 | case E1000_DEV_ID_82571EB_SERDES_QUAD: |
| 389 | case E1000_DEV_ID_82571EB_QUAD_COPPER: | 389 | case E1000_DEV_ID_82571EB_QUAD_COPPER: |
| 390 | case E1000_DEV_ID_82571PT_QUAD_COPPER: | ||
| 390 | case E1000_DEV_ID_82571EB_QUAD_FIBER: | 391 | case E1000_DEV_ID_82571EB_QUAD_FIBER: |
| 391 | case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE: | 392 | case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE: |
| 392 | hw->mac_type = e1000_82571; | 393 | hw->mac_type = e1000_82571; |
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index fe8714655c90..07f0ea73676e 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h | |||
| @@ -475,6 +475,7 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw); | |||
| 475 | #define E1000_DEV_ID_82571EB_FIBER 0x105F | 475 | #define E1000_DEV_ID_82571EB_FIBER 0x105F |
| 476 | #define E1000_DEV_ID_82571EB_SERDES 0x1060 | 476 | #define E1000_DEV_ID_82571EB_SERDES 0x1060 |
| 477 | #define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4 | 477 | #define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4 |
| 478 | #define E1000_DEV_ID_82571PT_QUAD_COPPER 0x10D5 | ||
| 478 | #define E1000_DEV_ID_82571EB_QUAD_FIBER 0x10A5 | 479 | #define E1000_DEV_ID_82571EB_QUAD_FIBER 0x10A5 |
| 479 | #define E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE 0x10BC | 480 | #define E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE 0x10BC |
| 480 | #define E1000_DEV_ID_82571EB_SERDES_DUAL 0x10D9 | 481 | #define E1000_DEV_ID_82571EB_SERDES_DUAL 0x10D9 |
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 4a225950fb43..e7c8951f47fa 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
| @@ -108,6 +108,7 @@ static struct pci_device_id e1000_pci_tbl[] = { | |||
| 108 | INTEL_E1000_ETHERNET_DEVICE(0x10BC), | 108 | INTEL_E1000_ETHERNET_DEVICE(0x10BC), |
| 109 | INTEL_E1000_ETHERNET_DEVICE(0x10C4), | 109 | INTEL_E1000_ETHERNET_DEVICE(0x10C4), |
| 110 | INTEL_E1000_ETHERNET_DEVICE(0x10C5), | 110 | INTEL_E1000_ETHERNET_DEVICE(0x10C5), |
| 111 | INTEL_E1000_ETHERNET_DEVICE(0x10D5), | ||
| 111 | INTEL_E1000_ETHERNET_DEVICE(0x10D9), | 112 | INTEL_E1000_ETHERNET_DEVICE(0x10D9), |
| 112 | INTEL_E1000_ETHERNET_DEVICE(0x10DA), | 113 | INTEL_E1000_ETHERNET_DEVICE(0x10DA), |
| 113 | /* required last entry */ | 114 | /* required last entry */ |
| @@ -1101,6 +1102,7 @@ e1000_probe(struct pci_dev *pdev, | |||
| 1101 | case E1000_DEV_ID_82571EB_QUAD_COPPER: | 1102 | case E1000_DEV_ID_82571EB_QUAD_COPPER: |
| 1102 | case E1000_DEV_ID_82571EB_QUAD_FIBER: | 1103 | case E1000_DEV_ID_82571EB_QUAD_FIBER: |
| 1103 | case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE: | 1104 | case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE: |
| 1105 | case E1000_DEV_ID_82571PT_QUAD_COPPER: | ||
| 1104 | /* if quad port adapter, disable WoL on all but port A */ | 1106 | /* if quad port adapter, disable WoL on all but port A */ |
| 1105 | if (global_quad_port_a != 0) | 1107 | if (global_quad_port_a != 0) |
| 1106 | adapter->eeprom_wol = 0; | 1108 | adapter->eeprom_wol = 0; |
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 456d1e1c98bd..315335671f0f 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
| @@ -534,7 +534,7 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id) | |||
| 534 | } | 534 | } |
| 535 | 535 | ||
| 536 | /* PHY status changed */ | 536 | /* PHY status changed */ |
| 537 | if (eth_int_cause_ext & ETH_INT_CAUSE_PHY) { | 537 | if (eth_int_cause_ext & (ETH_INT_CAUSE_PHY | ETH_INT_CAUSE_STATE)) { |
| 538 | struct ethtool_cmd cmd; | 538 | struct ethtool_cmd cmd; |
| 539 | 539 | ||
| 540 | if (mii_link_ok(&mp->mii)) { | 540 | if (mii_link_ok(&mp->mii)) { |
| @@ -1357,7 +1357,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev) | |||
| 1357 | #endif | 1357 | #endif |
| 1358 | 1358 | ||
| 1359 | dev->watchdog_timeo = 2 * HZ; | 1359 | dev->watchdog_timeo = 2 * HZ; |
| 1360 | dev->tx_queue_len = mp->tx_ring_size; | ||
| 1361 | dev->base_addr = 0; | 1360 | dev->base_addr = 0; |
| 1362 | dev->change_mtu = mv643xx_eth_change_mtu; | 1361 | dev->change_mtu = mv643xx_eth_change_mtu; |
| 1363 | dev->do_ioctl = mv643xx_eth_do_ioctl; | 1362 | dev->do_ioctl = mv643xx_eth_do_ioctl; |
diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index 82f8c0cbfb64..565b96696aca 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h | |||
| @@ -64,7 +64,9 @@ | |||
| 64 | #define ETH_INT_CAUSE_TX_ERROR (ETH_TX_QUEUES_ENABLED << 8) | 64 | #define ETH_INT_CAUSE_TX_ERROR (ETH_TX_QUEUES_ENABLED << 8) |
| 65 | #define ETH_INT_CAUSE_TX (ETH_INT_CAUSE_TX_DONE | ETH_INT_CAUSE_TX_ERROR) | 65 | #define ETH_INT_CAUSE_TX (ETH_INT_CAUSE_TX_DONE | ETH_INT_CAUSE_TX_ERROR) |
| 66 | #define ETH_INT_CAUSE_PHY 0x00010000 | 66 | #define ETH_INT_CAUSE_PHY 0x00010000 |
| 67 | #define ETH_INT_UNMASK_ALL_EXT (ETH_INT_CAUSE_TX | ETH_INT_CAUSE_PHY) | 67 | #define ETH_INT_CAUSE_STATE 0x00100000 |
| 68 | #define ETH_INT_UNMASK_ALL_EXT (ETH_INT_CAUSE_TX | ETH_INT_CAUSE_PHY | \ | ||
| 69 | ETH_INT_CAUSE_STATE) | ||
| 68 | 70 | ||
| 69 | #define ETH_INT_MASK_ALL 0x00000000 | 71 | #define ETH_INT_MASK_ALL 0x00000000 |
| 70 | #define ETH_INT_MASK_ALL_EXT 0x00000000 | 72 | #define ETH_INT_MASK_ALL_EXT 0x00000000 |
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 69da95b5ad0c..ea151315050c 100755 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c | |||
| @@ -2248,6 +2248,13 @@ static int ql_tx_rx_clean(struct ql3_adapter *qdev, | |||
| 2248 | qdev->rsp_consumer_index) && (work_done < work_to_do)) { | 2248 | qdev->rsp_consumer_index) && (work_done < work_to_do)) { |
| 2249 | 2249 | ||
| 2250 | net_rsp = qdev->rsp_current; | 2250 | net_rsp = qdev->rsp_current; |
| 2251 | rmb(); | ||
| 2252 | /* | ||
| 2253 | * Fix 4032 chipe undocumented "feature" where bit-8 is set if the | ||
| 2254 | * inbound completion is for a VLAN. | ||
| 2255 | */ | ||
| 2256 | if (qdev->device_id == QL3032_DEVICE_ID) | ||
| 2257 | net_rsp->opcode &= 0x7f; | ||
| 2251 | switch (net_rsp->opcode) { | 2258 | switch (net_rsp->opcode) { |
| 2252 | 2259 | ||
| 2253 | case OPCODE_OB_MAC_IOCB_FN0: | 2260 | case OPCODE_OB_MAC_IOCB_FN0: |
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index c921ec32c232..c76dd29c8e9a 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
| @@ -1918,7 +1918,11 @@ static void rtl_hw_start_8169(struct net_device *dev) | |||
| 1918 | 1918 | ||
| 1919 | rtl_set_rx_max_size(ioaddr); | 1919 | rtl_set_rx_max_size(ioaddr); |
| 1920 | 1920 | ||
| 1921 | rtl_set_rx_tx_config_registers(tp); | 1921 | if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || |
| 1922 | (tp->mac_version == RTL_GIGA_MAC_VER_02) || | ||
| 1923 | (tp->mac_version == RTL_GIGA_MAC_VER_03) || | ||
| 1924 | (tp->mac_version == RTL_GIGA_MAC_VER_04)) | ||
| 1925 | rtl_set_rx_tx_config_registers(tp); | ||
| 1922 | 1926 | ||
| 1923 | tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; | 1927 | tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; |
| 1924 | 1928 | ||
| @@ -1941,6 +1945,14 @@ static void rtl_hw_start_8169(struct net_device *dev) | |||
| 1941 | 1945 | ||
| 1942 | rtl_set_rx_tx_desc_registers(tp, ioaddr); | 1946 | rtl_set_rx_tx_desc_registers(tp, ioaddr); |
| 1943 | 1947 | ||
| 1948 | if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && | ||
| 1949 | (tp->mac_version != RTL_GIGA_MAC_VER_02) && | ||
| 1950 | (tp->mac_version != RTL_GIGA_MAC_VER_03) && | ||
| 1951 | (tp->mac_version != RTL_GIGA_MAC_VER_04)) { | ||
| 1952 | RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); | ||
| 1953 | rtl_set_rx_tx_config_registers(tp); | ||
| 1954 | } | ||
| 1955 | |||
| 1944 | RTL_W8(Cfg9346, Cfg9346_Lock); | 1956 | RTL_W8(Cfg9346, Cfg9346_Lock); |
| 1945 | 1957 | ||
| 1946 | /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ | 1958 | /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ |
| @@ -1955,8 +1967,6 @@ static void rtl_hw_start_8169(struct net_device *dev) | |||
| 1955 | 1967 | ||
| 1956 | /* Enable all known interrupts by setting the interrupt mask. */ | 1968 | /* Enable all known interrupts by setting the interrupt mask. */ |
| 1957 | RTL_W16(IntrMask, tp->intr_event); | 1969 | RTL_W16(IntrMask, tp->intr_event); |
| 1958 | |||
| 1959 | RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); | ||
| 1960 | } | 1970 | } |
| 1961 | 1971 | ||
| 1962 | static void rtl_hw_start_8168(struct net_device *dev) | 1972 | static void rtl_hw_start_8168(struct net_device *dev) |
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 0792031a5cf9..ea117fc3d5e3 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
| @@ -910,6 +910,20 @@ static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2) | |||
| 910 | return le; | 910 | return le; |
| 911 | } | 911 | } |
| 912 | 912 | ||
| 913 | static void tx_init(struct sky2_port *sky2) | ||
| 914 | { | ||
| 915 | struct sky2_tx_le *le; | ||
| 916 | |||
| 917 | sky2->tx_prod = sky2->tx_cons = 0; | ||
| 918 | sky2->tx_tcpsum = 0; | ||
| 919 | sky2->tx_last_mss = 0; | ||
| 920 | |||
| 921 | le = get_tx_le(sky2); | ||
| 922 | le->addr = 0; | ||
| 923 | le->opcode = OP_ADDR64 | HW_OWNER; | ||
| 924 | sky2->tx_addr64 = 0; | ||
| 925 | } | ||
| 926 | |||
| 913 | static inline struct tx_ring_info *tx_le_re(struct sky2_port *sky2, | 927 | static inline struct tx_ring_info *tx_le_re(struct sky2_port *sky2, |
| 914 | struct sky2_tx_le *le) | 928 | struct sky2_tx_le *le) |
| 915 | { | 929 | { |
| @@ -1320,7 +1334,8 @@ static int sky2_up(struct net_device *dev) | |||
| 1320 | GFP_KERNEL); | 1334 | GFP_KERNEL); |
| 1321 | if (!sky2->tx_ring) | 1335 | if (!sky2->tx_ring) |
| 1322 | goto err_out; | 1336 | goto err_out; |
| 1323 | sky2->tx_prod = sky2->tx_cons = 0; | 1337 | |
| 1338 | tx_init(sky2); | ||
| 1324 | 1339 | ||
| 1325 | sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES, | 1340 | sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES, |
| 1326 | &sky2->rx_le_map); | 1341 | &sky2->rx_le_map); |
| @@ -2148,6 +2163,15 @@ static struct sk_buff *sky2_receive(struct net_device *dev, | |||
| 2148 | sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending; | 2163 | sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending; |
| 2149 | prefetch(sky2->rx_ring + sky2->rx_next); | 2164 | prefetch(sky2->rx_ring + sky2->rx_next); |
| 2150 | 2165 | ||
| 2166 | /* This chip has hardware problems that generates bogus status. | ||
| 2167 | * So do only marginal checking and expect higher level protocols | ||
| 2168 | * to handle crap frames. | ||
| 2169 | */ | ||
| 2170 | if (sky2->hw->chip_id == CHIP_ID_YUKON_FE_P && | ||
| 2171 | sky2->hw->chip_rev == CHIP_REV_YU_FE2_A0 && | ||
| 2172 | length != count) | ||
| 2173 | goto okay; | ||
| 2174 | |||
| 2151 | if (status & GMR_FS_ANY_ERR) | 2175 | if (status & GMR_FS_ANY_ERR) |
| 2152 | goto error; | 2176 | goto error; |
| 2153 | 2177 | ||
| @@ -2156,8 +2180,9 @@ static struct sk_buff *sky2_receive(struct net_device *dev, | |||
| 2156 | 2180 | ||
| 2157 | /* if length reported by DMA does not match PHY, packet was truncated */ | 2181 | /* if length reported by DMA does not match PHY, packet was truncated */ |
| 2158 | if (length != count) | 2182 | if (length != count) |
| 2159 | goto len_mismatch; | 2183 | goto len_error; |
| 2160 | 2184 | ||
| 2185 | okay: | ||
| 2161 | if (length < copybreak) | 2186 | if (length < copybreak) |
| 2162 | skb = receive_copy(sky2, re, length); | 2187 | skb = receive_copy(sky2, re, length); |
| 2163 | else | 2188 | else |
| @@ -2167,13 +2192,13 @@ resubmit: | |||
| 2167 | 2192 | ||
| 2168 | return skb; | 2193 | return skb; |
| 2169 | 2194 | ||
| 2170 | len_mismatch: | 2195 | len_error: |
| 2171 | /* Truncation of overlength packets | 2196 | /* Truncation of overlength packets |
| 2172 | causes PHY length to not match MAC length */ | 2197 | causes PHY length to not match MAC length */ |
| 2173 | ++sky2->net_stats.rx_length_errors; | 2198 | ++sky2->net_stats.rx_length_errors; |
| 2174 | if (netif_msg_rx_err(sky2) && net_ratelimit()) | 2199 | if (netif_msg_rx_err(sky2) && net_ratelimit()) |
| 2175 | pr_info(PFX "%s: rx length mismatch: length %d status %#x\n", | 2200 | pr_info(PFX "%s: rx length error: status %#x length %d\n", |
| 2176 | dev->name, length, status); | 2201 | dev->name, status, length); |
| 2177 | goto resubmit; | 2202 | goto resubmit; |
| 2178 | 2203 | ||
| 2179 | error: | 2204 | error: |
| @@ -3934,13 +3959,6 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
| 3934 | sky2->hw = hw; | 3959 | sky2->hw = hw; |
| 3935 | sky2->msg_enable = netif_msg_init(debug, default_msg); | 3960 | sky2->msg_enable = netif_msg_init(debug, default_msg); |
| 3936 | 3961 | ||
| 3937 | /* This chip has hardware problems that generates | ||
| 3938 | * bogus PHY receive status so by default shut up the message. | ||
| 3939 | */ | ||
| 3940 | if (hw->chip_id == CHIP_ID_YUKON_FE_P && | ||
| 3941 | hw->chip_rev == CHIP_REV_YU_FE2_A0) | ||
| 3942 | sky2->msg_enable &= ~NETIF_MSG_RX_ERR; | ||
| 3943 | |||
| 3944 | /* Auto speed and flow control */ | 3962 | /* Auto speed and flow control */ |
| 3945 | sky2->autoneg = AUTONEG_ENABLE; | 3963 | sky2->autoneg = AUTONEG_ENABLE; |
| 3946 | sky2->flow_mode = FC_BOTH; | 3964 | sky2->flow_mode = FC_BOTH; |
| @@ -3964,8 +3982,12 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
| 3964 | dev->features |= NETIF_F_HIGHDMA; | 3982 | dev->features |= NETIF_F_HIGHDMA; |
| 3965 | 3983 | ||
| 3966 | #ifdef SKY2_VLAN_TAG_USED | 3984 | #ifdef SKY2_VLAN_TAG_USED |
| 3967 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; | 3985 | /* The workaround for FE+ status conflicts with VLAN tag detection. */ |
| 3968 | dev->vlan_rx_register = sky2_vlan_rx_register; | 3986 | if (!(sky2->hw->chip_id == CHIP_ID_YUKON_FE_P && |
| 3987 | sky2->hw->chip_rev == CHIP_REV_YU_FE2_A0)) { | ||
| 3988 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; | ||
| 3989 | dev->vlan_rx_register = sky2_vlan_rx_register; | ||
| 3990 | } | ||
| 3969 | #endif | 3991 | #endif |
| 3970 | 3992 | ||
| 3971 | /* read the mac address */ | 3993 | /* read the mac address */ |
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 16c7a0e87850..a2de32fabc17 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c | |||
| @@ -405,7 +405,7 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) | |||
| 405 | dev->net->ethtool_ops = &dm9601_ethtool_ops; | 405 | dev->net->ethtool_ops = &dm9601_ethtool_ops; |
| 406 | dev->net->hard_header_len += DM_TX_OVERHEAD; | 406 | dev->net->hard_header_len += DM_TX_OVERHEAD; |
| 407 | dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; | 407 | dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; |
| 408 | dev->rx_urb_size = dev->net->mtu + DM_RX_OVERHEAD; | 408 | dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD; |
| 409 | 409 | ||
| 410 | dev->mii.dev = dev->net; | 410 | dev->mii.dev = dev->net; |
| 411 | dev->mii.mdio_read = dm9601_mdio_read; | 411 | dev->mii.mdio_read = dm9601_mdio_read; |
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index ef35bc6c4a22..4eb6d9752881 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile | |||
| @@ -43,7 +43,7 @@ obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o | |||
| 43 | obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o | 43 | obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o |
| 44 | 44 | ||
| 45 | obj-$(CONFIG_USB_ZD1201) += zd1201.o | 45 | obj-$(CONFIG_USB_ZD1201) += zd1201.o |
| 46 | obj-$(CONFIG_LIBERTAS_USB) += libertas/ | 46 | obj-$(CONFIG_LIBERTAS) += libertas/ |
| 47 | 47 | ||
| 48 | rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o | 48 | rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o |
| 49 | obj-$(CONFIG_RTL8187) += rtl8187.o | 49 | obj-$(CONFIG_RTL8187) += rtl8187.o |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index d6d9413d7f23..6acfdc49dccd 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c | |||
| @@ -444,7 +444,7 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, | |||
| 444 | u16 maxpower; | 444 | u16 maxpower; |
| 445 | 445 | ||
| 446 | if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) { | 446 | if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) { |
| 447 | printk(PFX KERN_ERR "TX power not in dBm.\n"); | 447 | printk(KERN_ERR PFX "TX power not in dBm.\n"); |
| 448 | return -EOPNOTSUPP; | 448 | return -EOPNOTSUPP; |
| 449 | } | 449 | } |
| 450 | 450 | ||
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 7dcaa09b3c20..50f2dd9e1bb2 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
| @@ -1444,7 +1444,6 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos); | |||
| 1444 | static void __devinit quirk_e100_interrupt(struct pci_dev *dev) | 1444 | static void __devinit quirk_e100_interrupt(struct pci_dev *dev) |
| 1445 | { | 1445 | { |
| 1446 | u16 command; | 1446 | u16 command; |
| 1447 | u32 bar; | ||
| 1448 | u8 __iomem *csr; | 1447 | u8 __iomem *csr; |
| 1449 | u8 cmd_hi; | 1448 | u8 cmd_hi; |
| 1450 | 1449 | ||
| @@ -1476,12 +1475,12 @@ static void __devinit quirk_e100_interrupt(struct pci_dev *dev) | |||
| 1476 | * re-enable them when it's ready. | 1475 | * re-enable them when it's ready. |
| 1477 | */ | 1476 | */ |
| 1478 | pci_read_config_word(dev, PCI_COMMAND, &command); | 1477 | pci_read_config_word(dev, PCI_COMMAND, &command); |
| 1479 | pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar); | ||
| 1480 | 1478 | ||
| 1481 | if (!(command & PCI_COMMAND_MEMORY) || !bar) | 1479 | if (!(command & PCI_COMMAND_MEMORY) || !pci_resource_start(dev, 0)) |
| 1482 | return; | 1480 | return; |
| 1483 | 1481 | ||
| 1484 | csr = ioremap(bar, 8); | 1482 | /* Convert from PCI bus to resource space. */ |
| 1483 | csr = ioremap(pci_resource_start(dev, 0), 8); | ||
| 1485 | if (!csr) { | 1484 | if (!csr) { |
| 1486 | printk(KERN_WARNING "PCI: Can't map %s e100 registers\n", | 1485 | printk(KERN_WARNING "PCI: Can't map %s e100 registers\n", |
| 1487 | pci_name(dev)); | 1486 | pci_name(dev)); |
diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c index d5d8caba3560..ab13824df856 100644 --- a/drivers/scsi/aic94xx/aic94xx_task.c +++ b/drivers/scsi/aic94xx/aic94xx_task.c | |||
| @@ -451,7 +451,7 @@ static int asd_build_smp_ascb(struct asd_ascb *ascb, struct sas_task *task, | |||
| 451 | struct scb *scb; | 451 | struct scb *scb; |
| 452 | 452 | ||
| 453 | pci_map_sg(asd_ha->pcidev, &task->smp_task.smp_req, 1, | 453 | pci_map_sg(asd_ha->pcidev, &task->smp_task.smp_req, 1, |
| 454 | PCI_DMA_FROMDEVICE); | 454 | PCI_DMA_TODEVICE); |
| 455 | pci_map_sg(asd_ha->pcidev, &task->smp_task.smp_resp, 1, | 455 | pci_map_sg(asd_ha->pcidev, &task->smp_task.smp_resp, 1, |
| 456 | PCI_DMA_FROMDEVICE); | 456 | PCI_DMA_FROMDEVICE); |
| 457 | 457 | ||
| @@ -486,7 +486,7 @@ static void asd_unbuild_smp_ascb(struct asd_ascb *a) | |||
| 486 | 486 | ||
| 487 | BUG_ON(!task); | 487 | BUG_ON(!task); |
| 488 | pci_unmap_sg(a->ha->pcidev, &task->smp_task.smp_req, 1, | 488 | pci_unmap_sg(a->ha->pcidev, &task->smp_task.smp_req, 1, |
| 489 | PCI_DMA_FROMDEVICE); | 489 | PCI_DMA_TODEVICE); |
| 490 | pci_unmap_sg(a->ha->pcidev, &task->smp_task.smp_resp, 1, | 490 | pci_unmap_sg(a->ha->pcidev, &task->smp_task.smp_resp, 1, |
| 491 | PCI_DMA_FROMDEVICE); | 491 | PCI_DMA_FROMDEVICE); |
| 492 | } | 492 | } |
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 3907f6718ede..da56163c30a8 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c | |||
| @@ -1753,6 +1753,14 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len) | |||
| 1753 | 1753 | ||
| 1754 | *len = 0; | 1754 | *len = 0; |
| 1755 | 1755 | ||
| 1756 | if (scsi_sg_count(cmd) == 1 && !adapter->has_64bit_addr) { | ||
| 1757 | sg = scsi_sglist(cmd); | ||
| 1758 | scb->dma_h_bulkdata = sg_dma_address(sg); | ||
| 1759 | *buf = (u32)scb->dma_h_bulkdata; | ||
| 1760 | *len = sg_dma_len(sg); | ||
| 1761 | return 0; | ||
| 1762 | } | ||
| 1763 | |||
| 1756 | scsi_for_each_sg(cmd, sg, sgcnt, idx) { | 1764 | scsi_for_each_sg(cmd, sg, sgcnt, idx) { |
| 1757 | if (adapter->has_64bit_addr) { | 1765 | if (adapter->has_64bit_addr) { |
| 1758 | scb->sgl64[idx].address = sg_dma_address(sg); | 1766 | scb->sgl64[idx].address = sg_dma_address(sg); |
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.h b/drivers/serial/cpm_uart/cpm_uart_cpm1.h index a99e45e2b6d8..2a6477834c3e 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm1.h +++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.h | |||
| @@ -37,6 +37,6 @@ static inline void cpm_set_smc_fcr(volatile smc_uart_t * up) | |||
| 37 | up->smc_tfcr = SMC_EB; | 37 | up->smc_tfcr = SMC_EB; |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | #define DPRAM_BASE ((unsigned char *)&cpmp->cp_dpmem[0]) | 40 | #define DPRAM_BASE ((unsigned char *)cpm_dpram_addr(0)) |
| 41 | 41 | ||
| 42 | #endif | 42 | #endif |
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index a0ea43598515..7c8d78fbbbfb 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c | |||
| @@ -943,6 +943,7 @@ static struct pcmcia_device_id serial_ids[] = { | |||
| 943 | PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), | 943 | PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), |
| 944 | PCMCIA_MFC_DEVICE_PROD_ID12(2,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), | 944 | PCMCIA_MFC_DEVICE_PROD_ID12(2,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), |
| 945 | PCMCIA_MFC_DEVICE_PROD_ID12(3,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), | 945 | PCMCIA_MFC_DEVICE_PROD_ID12(3,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), |
| 946 | PCMCIA_DEVICE_MANF_CARD(0x0279, 0x950b), | ||
| 946 | /* too generic */ | 947 | /* too generic */ |
| 947 | /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */ | 948 | /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */ |
| 948 | /* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */ | 949 | /* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */ |
| @@ -1562,6 +1562,7 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, | |||
| 1562 | fput(file); | 1562 | fput(file); |
| 1563 | return -EAGAIN; | 1563 | return -EAGAIN; |
| 1564 | } | 1564 | } |
| 1565 | req->ki_filp = file; | ||
| 1565 | if (iocb->aio_flags & IOCB_FLAG_RESFD) { | 1566 | if (iocb->aio_flags & IOCB_FLAG_RESFD) { |
| 1566 | /* | 1567 | /* |
| 1567 | * If the IOCB_FLAG_RESFD flag of aio_flags is set, get an | 1568 | * If the IOCB_FLAG_RESFD flag of aio_flags is set, get an |
| @@ -1576,7 +1577,6 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, | |||
| 1576 | } | 1577 | } |
| 1577 | } | 1578 | } |
| 1578 | 1579 | ||
| 1579 | req->ki_filp = file; | ||
| 1580 | ret = put_user(req->ki_key, &user_iocb->aio_key); | 1580 | ret = put_user(req->ki_key, &user_iocb->aio_key); |
| 1581 | if (unlikely(ret)) { | 1581 | if (unlikely(ret)) { |
| 1582 | dprintk("EFAULT: aio_key\n"); | 1582 | dprintk("EFAULT: aio_key\n"); |
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 861141b4f6d6..fcb3405bb14e 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c | |||
| @@ -742,6 +742,7 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
| 742 | * __start to address 4 so that is okay). | 742 | * __start to address 4 so that is okay). |
| 743 | */ | 743 | */ |
| 744 | if (rev > OLD_FLAT_VERSION) { | 744 | if (rev > OLD_FLAT_VERSION) { |
| 745 | unsigned long persistent = 0; | ||
| 745 | for (i=0; i < relocs; i++) { | 746 | for (i=0; i < relocs; i++) { |
| 746 | unsigned long addr, relval; | 747 | unsigned long addr, relval; |
| 747 | 748 | ||
| @@ -749,6 +750,8 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
| 749 | relocated (of course, the address has to be | 750 | relocated (of course, the address has to be |
| 750 | relocated first). */ | 751 | relocated first). */ |
| 751 | relval = ntohl(reloc[i]); | 752 | relval = ntohl(reloc[i]); |
| 753 | if (flat_set_persistent (relval, &persistent)) | ||
| 754 | continue; | ||
| 752 | addr = flat_get_relocate_addr(relval); | 755 | addr = flat_get_relocate_addr(relval); |
| 753 | rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1); | 756 | rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1); |
| 754 | if (rp == (unsigned long *)RELOC_FAILED) { | 757 | if (rp == (unsigned long *)RELOC_FAILED) { |
| @@ -757,7 +760,8 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
| 757 | } | 760 | } |
| 758 | 761 | ||
| 759 | /* Get the pointer's value. */ | 762 | /* Get the pointer's value. */ |
| 760 | addr = flat_get_addr_from_rp(rp, relval, flags); | 763 | addr = flat_get_addr_from_rp(rp, relval, flags, |
| 764 | &persistent); | ||
| 761 | if (addr != 0) { | 765 | if (addr != 0) { |
| 762 | /* | 766 | /* |
| 763 | * Do the relocation. PIC relocs in the data section are | 767 | * Do the relocation. PIC relocs in the data section are |
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index d098c7af0d22..d120ec39bcb0 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
| @@ -485,8 +485,10 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file, | |||
| 485 | return nlm_granted; | 485 | return nlm_granted; |
| 486 | /* Create host handle for callback */ | 486 | /* Create host handle for callback */ |
| 487 | host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len); | 487 | host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len); |
| 488 | if (host == NULL) | 488 | if (host == NULL) { |
| 489 | kfree(conf); | ||
| 489 | return nlm_lck_denied_nolocks; | 490 | return nlm_lck_denied_nolocks; |
| 491 | } | ||
| 490 | block = nlmsvc_create_block(rqstp, host, file, lock, cookie); | 492 | block = nlmsvc_create_block(rqstp, host, file, lock, cookie); |
| 491 | if (block == NULL) { | 493 | if (block == NULL) { |
| 492 | kfree(conf); | 494 | kfree(conf); |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index a49f9feff776..a204484072f3 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
| @@ -588,16 +588,6 @@ static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_dat | |||
| 588 | server->namelen = data->namlen; | 588 | server->namelen = data->namlen; |
| 589 | /* Create a client RPC handle for the NFSv3 ACL management interface */ | 589 | /* Create a client RPC handle for the NFSv3 ACL management interface */ |
| 590 | nfs_init_server_aclclient(server); | 590 | nfs_init_server_aclclient(server); |
| 591 | if (clp->cl_nfsversion == 3) { | ||
| 592 | if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) | ||
| 593 | server->namelen = NFS3_MAXNAMLEN; | ||
| 594 | if (!(data->flags & NFS_MOUNT_NORDIRPLUS)) | ||
| 595 | server->caps |= NFS_CAP_READDIRPLUS; | ||
| 596 | } else { | ||
| 597 | if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) | ||
| 598 | server->namelen = NFS2_MAXNAMLEN; | ||
| 599 | } | ||
| 600 | |||
| 601 | dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp); | 591 | dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp); |
| 602 | return 0; | 592 | return 0; |
| 603 | 593 | ||
| @@ -794,6 +784,16 @@ struct nfs_server *nfs_create_server(const struct nfs_mount_data *data, | |||
| 794 | error = nfs_probe_fsinfo(server, mntfh, &fattr); | 784 | error = nfs_probe_fsinfo(server, mntfh, &fattr); |
| 795 | if (error < 0) | 785 | if (error < 0) |
| 796 | goto error; | 786 | goto error; |
| 787 | if (server->nfs_client->rpc_ops->version == 3) { | ||
| 788 | if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) | ||
| 789 | server->namelen = NFS3_MAXNAMLEN; | ||
| 790 | if (!(data->flags & NFS_MOUNT_NORDIRPLUS)) | ||
| 791 | server->caps |= NFS_CAP_READDIRPLUS; | ||
| 792 | } else { | ||
| 793 | if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) | ||
| 794 | server->namelen = NFS2_MAXNAMLEN; | ||
| 795 | } | ||
| 796 | |||
| 797 | if (!(fattr.valid & NFS_ATTR_FATTR)) { | 797 | if (!(fattr.valid & NFS_ATTR_FATTR)) { |
| 798 | error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr); | 798 | error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr); |
| 799 | if (error < 0) { | 799 | if (error < 0) { |
| @@ -984,6 +984,9 @@ struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data, | |||
| 984 | if (error < 0) | 984 | if (error < 0) |
| 985 | goto error; | 985 | goto error; |
| 986 | 986 | ||
| 987 | if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) | ||
| 988 | server->namelen = NFS4_MAXNAMLEN; | ||
| 989 | |||
| 987 | BUG_ON(!server->nfs_client); | 990 | BUG_ON(!server->nfs_client); |
| 988 | BUG_ON(!server->nfs_client->rpc_ops); | 991 | BUG_ON(!server->nfs_client->rpc_ops); |
| 989 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | 992 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); |
| @@ -1056,6 +1059,9 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | |||
| 1056 | if (error < 0) | 1059 | if (error < 0) |
| 1057 | goto error; | 1060 | goto error; |
| 1058 | 1061 | ||
| 1062 | if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) | ||
| 1063 | server->namelen = NFS4_MAXNAMLEN; | ||
| 1064 | |||
| 1059 | dprintk("Referral FSID: %llx:%llx\n", | 1065 | dprintk("Referral FSID: %llx:%llx\n", |
| 1060 | (unsigned long long) server->fsid.major, | 1066 | (unsigned long long) server->fsid.major, |
| 1061 | (unsigned long long) server->fsid.minor); | 1067 | (unsigned long long) server->fsid.minor); |
| @@ -1115,6 +1121,9 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source, | |||
| 1115 | if (error < 0) | 1121 | if (error < 0) |
| 1116 | goto out_free_server; | 1122 | goto out_free_server; |
| 1117 | 1123 | ||
| 1124 | if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) | ||
| 1125 | server->namelen = NFS4_MAXNAMLEN; | ||
| 1126 | |||
| 1118 | dprintk("Cloned FSID: %llx:%llx\n", | 1127 | dprintk("Cloned FSID: %llx:%llx\n", |
| 1119 | (unsigned long long) server->fsid.major, | 1128 | (unsigned long long) server->fsid.major, |
| 1120 | (unsigned long long) server->fsid.minor); | 1129 | (unsigned long long) server->fsid.minor); |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index ea97408e423e..e4a04d16b8b0 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -1162,6 +1162,8 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) | |||
| 1162 | } | 1162 | } |
| 1163 | if (!desc->plus || !(entry->fattr->valid & NFS_ATTR_FATTR)) | 1163 | if (!desc->plus || !(entry->fattr->valid & NFS_ATTR_FATTR)) |
| 1164 | return NULL; | 1164 | return NULL; |
| 1165 | if (name.len > NFS_SERVER(dir)->namelen) | ||
| 1166 | return NULL; | ||
| 1165 | /* Note: caller is already holding the dir->i_mutex! */ | 1167 | /* Note: caller is already holding the dir->i_mutex! */ |
| 1166 | dentry = d_alloc(parent, &name); | 1168 | dentry = d_alloc(parent, &name); |
| 1167 | if (dentry == NULL) | 1169 | if (dentry == NULL) |
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index d1cbf0a0fbb2..522e5ad4d8ad 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c | |||
| @@ -175,6 +175,9 @@ next_component: | |||
| 175 | path++; | 175 | path++; |
| 176 | name.len = path - (const char *) name.name; | 176 | name.len = path - (const char *) name.name; |
| 177 | 177 | ||
| 178 | if (name.len > NFS4_MAXNAMLEN) | ||
| 179 | return -ENAMETOOLONG; | ||
| 180 | |||
| 178 | eat_dot_dir: | 181 | eat_dot_dir: |
| 179 | while (*path == '/') | 182 | while (*path == '/') |
| 180 | path++; | 183 | path++; |
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index de984d272576..d272847d5a07 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c | |||
| @@ -514,8 +514,10 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, | |||
| 514 | ac->ac_bh = osb->local_alloc_bh; | 514 | ac->ac_bh = osb->local_alloc_bh; |
| 515 | status = 0; | 515 | status = 0; |
| 516 | bail: | 516 | bail: |
| 517 | if (status < 0 && local_alloc_inode) | 517 | if (status < 0 && local_alloc_inode) { |
| 518 | mutex_unlock(&local_alloc_inode->i_mutex); | ||
| 518 | iput(local_alloc_inode); | 519 | iput(local_alloc_inode); |
| 520 | } | ||
| 519 | 521 | ||
| 520 | mlog_exit(status); | 522 | mlog_exit(status); |
| 521 | return status; | 523 | return status; |
diff --git a/fs/splice.c b/fs/splice.c index c010a72ca2d2..e95a36228863 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
| @@ -1224,6 +1224,33 @@ static long do_splice(struct file *in, loff_t __user *off_in, | |||
| 1224 | } | 1224 | } |
| 1225 | 1225 | ||
| 1226 | /* | 1226 | /* |
| 1227 | * Do a copy-from-user while holding the mmap_semaphore for reading, in a | ||
| 1228 | * manner safe from deadlocking with simultaneous mmap() (grabbing mmap_sem | ||
| 1229 | * for writing) and page faulting on the user memory pointed to by src. | ||
| 1230 | * This assumes that we will very rarely hit the partial != 0 path, or this | ||
| 1231 | * will not be a win. | ||
| 1232 | */ | ||
| 1233 | static int copy_from_user_mmap_sem(void *dst, const void __user *src, size_t n) | ||
| 1234 | { | ||
| 1235 | int partial; | ||
| 1236 | |||
| 1237 | pagefault_disable(); | ||
| 1238 | partial = __copy_from_user_inatomic(dst, src, n); | ||
| 1239 | pagefault_enable(); | ||
| 1240 | |||
| 1241 | /* | ||
| 1242 | * Didn't copy everything, drop the mmap_sem and do a faulting copy | ||
| 1243 | */ | ||
| 1244 | if (unlikely(partial)) { | ||
| 1245 | up_read(¤t->mm->mmap_sem); | ||
| 1246 | partial = copy_from_user(dst, src, n); | ||
| 1247 | down_read(¤t->mm->mmap_sem); | ||
| 1248 | } | ||
| 1249 | |||
| 1250 | return partial; | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | /* | ||
| 1227 | * Map an iov into an array of pages and offset/length tupples. With the | 1254 | * Map an iov into an array of pages and offset/length tupples. With the |
| 1228 | * partial_page structure, we can map several non-contiguous ranges into | 1255 | * partial_page structure, we can map several non-contiguous ranges into |
| 1229 | * our ones pages[] map instead of splitting that operation into pieces. | 1256 | * our ones pages[] map instead of splitting that operation into pieces. |
| @@ -1236,31 +1263,26 @@ static int get_iovec_page_array(const struct iovec __user *iov, | |||
| 1236 | { | 1263 | { |
| 1237 | int buffers = 0, error = 0; | 1264 | int buffers = 0, error = 0; |
| 1238 | 1265 | ||
| 1239 | /* | ||
| 1240 | * It's ok to take the mmap_sem for reading, even | ||
| 1241 | * across a "get_user()". | ||
| 1242 | */ | ||
| 1243 | down_read(¤t->mm->mmap_sem); | 1266 | down_read(¤t->mm->mmap_sem); |
| 1244 | 1267 | ||
| 1245 | while (nr_vecs) { | 1268 | while (nr_vecs) { |
| 1246 | unsigned long off, npages; | 1269 | unsigned long off, npages; |
| 1270 | struct iovec entry; | ||
| 1247 | void __user *base; | 1271 | void __user *base; |
| 1248 | size_t len; | 1272 | size_t len; |
| 1249 | int i; | 1273 | int i; |
| 1250 | 1274 | ||
| 1251 | /* | 1275 | error = -EFAULT; |
| 1252 | * Get user address base and length for this iovec. | 1276 | if (copy_from_user_mmap_sem(&entry, iov, sizeof(entry))) |
| 1253 | */ | ||
| 1254 | error = get_user(base, &iov->iov_base); | ||
| 1255 | if (unlikely(error)) | ||
| 1256 | break; | ||
| 1257 | error = get_user(len, &iov->iov_len); | ||
| 1258 | if (unlikely(error)) | ||
| 1259 | break; | 1277 | break; |
| 1260 | 1278 | ||
| 1279 | base = entry.iov_base; | ||
| 1280 | len = entry.iov_len; | ||
| 1281 | |||
| 1261 | /* | 1282 | /* |
| 1262 | * Sanity check this iovec. 0 read succeeds. | 1283 | * Sanity check this iovec. 0 read succeeds. |
| 1263 | */ | 1284 | */ |
| 1285 | error = 0; | ||
| 1264 | if (unlikely(!len)) | 1286 | if (unlikely(!len)) |
| 1265 | break; | 1287 | break; |
| 1266 | error = -EFAULT; | 1288 | error = -EFAULT; |
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h index fa25b7dcc6c3..d7e136143066 100644 --- a/fs/xfs/xfs_buf_item.h +++ b/fs/xfs/xfs_buf_item.h | |||
| @@ -52,11 +52,6 @@ typedef struct xfs_buf_log_format_t { | |||
| 52 | #define XFS_BLI_UDQUOT_BUF 0x4 | 52 | #define XFS_BLI_UDQUOT_BUF 0x4 |
| 53 | #define XFS_BLI_PDQUOT_BUF 0x8 | 53 | #define XFS_BLI_PDQUOT_BUF 0x8 |
| 54 | #define XFS_BLI_GDQUOT_BUF 0x10 | 54 | #define XFS_BLI_GDQUOT_BUF 0x10 |
| 55 | /* | ||
| 56 | * This flag indicates that the buffer contains newly allocated | ||
| 57 | * inodes. | ||
| 58 | */ | ||
| 59 | #define XFS_BLI_INODE_NEW_BUF 0x20 | ||
| 60 | 55 | ||
| 61 | #define XFS_BLI_CHUNK 128 | 56 | #define XFS_BLI_CHUNK 128 |
| 62 | #define XFS_BLI_SHIFT 7 | 57 | #define XFS_BLI_SHIFT 7 |
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 7174991f4bef..8ae6e8e5f3db 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
| @@ -1874,7 +1874,6 @@ xlog_recover_do_inode_buffer( | |||
| 1874 | /*ARGSUSED*/ | 1874 | /*ARGSUSED*/ |
| 1875 | STATIC void | 1875 | STATIC void |
| 1876 | xlog_recover_do_reg_buffer( | 1876 | xlog_recover_do_reg_buffer( |
| 1877 | xfs_mount_t *mp, | ||
| 1878 | xlog_recover_item_t *item, | 1877 | xlog_recover_item_t *item, |
| 1879 | xfs_buf_t *bp, | 1878 | xfs_buf_t *bp, |
| 1880 | xfs_buf_log_format_t *buf_f) | 1879 | xfs_buf_log_format_t *buf_f) |
| @@ -1885,50 +1884,6 @@ xlog_recover_do_reg_buffer( | |||
| 1885 | unsigned int *data_map = NULL; | 1884 | unsigned int *data_map = NULL; |
| 1886 | unsigned int map_size = 0; | 1885 | unsigned int map_size = 0; |
| 1887 | int error; | 1886 | int error; |
| 1888 | int stale_buf = 1; | ||
| 1889 | |||
| 1890 | /* | ||
| 1891 | * Scan through the on-disk inode buffer and attempt to | ||
| 1892 | * determine if it has been written to since it was logged. | ||
| 1893 | * | ||
| 1894 | * - If any of the magic numbers are incorrect then the buffer is stale | ||
| 1895 | * - If any of the modes are non-zero then the buffer is not stale | ||
| 1896 | * - If all of the modes are zero and at least one of the generation | ||
| 1897 | * counts is non-zero then the buffer is stale | ||
| 1898 | * | ||
| 1899 | * If the end result is a stale buffer then the log buffer is replayed | ||
| 1900 | * otherwise it is skipped. | ||
| 1901 | * | ||
| 1902 | * This heuristic is not perfect. It can be improved by scanning the | ||
| 1903 | * entire inode chunk for evidence that any of the inode clusters have | ||
| 1904 | * been updated. To fix this problem completely we will need a major | ||
| 1905 | * architectural change to the logging system. | ||
| 1906 | */ | ||
| 1907 | if (buf_f->blf_flags & XFS_BLI_INODE_NEW_BUF) { | ||
| 1908 | xfs_dinode_t *dip; | ||
| 1909 | int inodes_per_buf; | ||
| 1910 | int mode_count = 0; | ||
| 1911 | int gen_count = 0; | ||
| 1912 | |||
| 1913 | stale_buf = 0; | ||
| 1914 | inodes_per_buf = XFS_BUF_COUNT(bp) >> mp->m_sb.sb_inodelog; | ||
| 1915 | for (i = 0; i < inodes_per_buf; i++) { | ||
| 1916 | dip = (xfs_dinode_t *)xfs_buf_offset(bp, | ||
| 1917 | i * mp->m_sb.sb_inodesize); | ||
| 1918 | if (be16_to_cpu(dip->di_core.di_magic) != | ||
| 1919 | XFS_DINODE_MAGIC) { | ||
| 1920 | stale_buf = 1; | ||
| 1921 | break; | ||
| 1922 | } | ||
| 1923 | if (dip->di_core.di_mode) | ||
| 1924 | mode_count++; | ||
| 1925 | if (dip->di_core.di_gen) | ||
| 1926 | gen_count++; | ||
| 1927 | } | ||
| 1928 | |||
| 1929 | if (!mode_count && gen_count) | ||
| 1930 | stale_buf = 1; | ||
| 1931 | } | ||
| 1932 | 1887 | ||
| 1933 | switch (buf_f->blf_type) { | 1888 | switch (buf_f->blf_type) { |
| 1934 | case XFS_LI_BUF: | 1889 | case XFS_LI_BUF: |
| @@ -1962,7 +1917,7 @@ xlog_recover_do_reg_buffer( | |||
| 1962 | -1, 0, XFS_QMOPT_DOWARN, | 1917 | -1, 0, XFS_QMOPT_DOWARN, |
| 1963 | "dquot_buf_recover"); | 1918 | "dquot_buf_recover"); |
| 1964 | } | 1919 | } |
| 1965 | if (!error && stale_buf) | 1920 | if (!error) |
| 1966 | memcpy(xfs_buf_offset(bp, | 1921 | memcpy(xfs_buf_offset(bp, |
| 1967 | (uint)bit << XFS_BLI_SHIFT), /* dest */ | 1922 | (uint)bit << XFS_BLI_SHIFT), /* dest */ |
| 1968 | item->ri_buf[i].i_addr, /* source */ | 1923 | item->ri_buf[i].i_addr, /* source */ |
| @@ -2134,7 +2089,7 @@ xlog_recover_do_dquot_buffer( | |||
| 2134 | if (log->l_quotaoffs_flag & type) | 2089 | if (log->l_quotaoffs_flag & type) |
| 2135 | return; | 2090 | return; |
| 2136 | 2091 | ||
| 2137 | xlog_recover_do_reg_buffer(mp, item, bp, buf_f); | 2092 | xlog_recover_do_reg_buffer(item, bp, buf_f); |
| 2138 | } | 2093 | } |
| 2139 | 2094 | ||
| 2140 | /* | 2095 | /* |
| @@ -2235,7 +2190,7 @@ xlog_recover_do_buffer_trans( | |||
| 2235 | (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) { | 2190 | (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) { |
| 2236 | xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f); | 2191 | xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f); |
| 2237 | } else { | 2192 | } else { |
| 2238 | xlog_recover_do_reg_buffer(mp, item, bp, buf_f); | 2193 | xlog_recover_do_reg_buffer(item, bp, buf_f); |
| 2239 | } | 2194 | } |
| 2240 | if (error) | 2195 | if (error) |
| 2241 | return XFS_ERROR(error); | 2196 | return XFS_ERROR(error); |
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index 95fff6872a2f..60b6b898022b 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c | |||
| @@ -966,7 +966,6 @@ xfs_trans_inode_alloc_buf( | |||
| 966 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | 966 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
| 967 | 967 | ||
| 968 | bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF; | 968 | bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF; |
| 969 | bip->bli_format.blf_flags |= XFS_BLI_INODE_NEW_BUF; | ||
| 970 | } | 969 | } |
| 971 | 970 | ||
| 972 | 971 | ||
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 17500a118782..7b74b60a68a4 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
| @@ -332,6 +332,7 @@ int acpi_bus_get_power(acpi_handle handle, int *state); | |||
| 332 | int acpi_bus_set_power(acpi_handle handle, int state); | 332 | int acpi_bus_set_power(acpi_handle handle, int state); |
| 333 | #ifdef CONFIG_ACPI_PROC_EVENT | 333 | #ifdef CONFIG_ACPI_PROC_EVENT |
| 334 | int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data); | 334 | int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data); |
| 335 | int acpi_bus_generate_proc_event4(const char *class, const char *bid, u8 type, int data); | ||
| 335 | int acpi_bus_receive_event(struct acpi_bus_event *event); | 336 | int acpi_bus_receive_event(struct acpi_bus_event *event); |
| 336 | #else | 337 | #else |
| 337 | static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) | 338 | static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) |
diff --git a/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h index e043cafa3c42..69b9f8e120e9 100644 --- a/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h +++ b/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | #include <linux/serial.h> | 1 | #include <linux/serial.h> |
| 2 | #include <asm/dma.h> | 2 | #include <asm/dma.h> |
| 3 | #include <asm/portmux.h> | ||
| 3 | 4 | ||
| 4 | #define NR_PORTS 1 | 5 | #define NR_PORTS 1 |
| 5 | 6 | ||
| @@ -92,18 +93,24 @@ struct bfin_serial_res bfin_serial_resource[] = { | |||
| 92 | } | 93 | } |
| 93 | }; | 94 | }; |
| 94 | 95 | ||
| 96 | #define DRIVER_NAME "bfin-uart" | ||
| 95 | 97 | ||
| 96 | int nr_ports = NR_PORTS; | 98 | int nr_ports = NR_PORTS; |
| 97 | static void bfin_serial_hw_init(struct bfin_serial_port *uart) | 99 | static void bfin_serial_hw_init(struct bfin_serial_port *uart) |
| 98 | { | 100 | { |
| 99 | 101 | ||
| 102 | #ifdef CONFIG_SERIAL_BFIN_UART0 | ||
| 103 | peripheral_request(P_UART0_TX, DRIVER_NAME); | ||
| 104 | peripheral_request(P_UART0_RX, DRIVER_NAME); | ||
| 105 | #endif | ||
| 106 | |||
| 100 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS | 107 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS |
| 101 | if (uart->cts_pin >= 0) { | 108 | if (uart->cts_pin >= 0) { |
| 102 | gpio_request(uart->cts_pin, NULL); | 109 | gpio_request(uart->cts_pin, DRIVER_NAME); |
| 103 | gpio_direction_input(uart->cts_pin); | 110 | gpio_direction_input(uart->cts_pin); |
| 104 | } | 111 | } |
| 105 | if (uart->rts_pin >= 0) { | 112 | if (uart->rts_pin >= 0) { |
| 106 | gpio_request(uart->rts_pin, NULL); | 113 | gpio_request(uart->rts_pin, DRIVER_NAME); |
| 107 | gpio_direction_input(uart->rts_pin); | 114 | gpio_direction_input(uart->rts_pin); |
| 108 | } | 115 | } |
| 109 | #endif | 116 | #endif |
diff --git a/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h index 8f5d9c4d8d5b..6fb328f5186a 100644 --- a/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h +++ b/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | #include <linux/serial.h> | 1 | #include <linux/serial.h> |
| 2 | #include <asm/dma.h> | 2 | #include <asm/dma.h> |
| 3 | #include <asm/portmux.h> | ||
| 3 | 4 | ||
| 4 | #define NR_PORTS 2 | 5 | #define NR_PORTS 2 |
| 5 | 6 | ||
| @@ -122,25 +123,29 @@ struct bfin_serial_res bfin_serial_resource[] = { | |||
| 122 | 123 | ||
| 123 | int nr_ports = ARRAY_SIZE(bfin_serial_resource); | 124 | int nr_ports = ARRAY_SIZE(bfin_serial_resource); |
| 124 | 125 | ||
| 126 | #define DRIVER_NAME "bfin-uart" | ||
| 127 | |||
| 125 | static void bfin_serial_hw_init(struct bfin_serial_port *uart) | 128 | static void bfin_serial_hw_init(struct bfin_serial_port *uart) |
| 126 | { | 129 | { |
| 127 | unsigned short val; | ||
| 128 | val = bfin_read16(BFIN_PORT_MUX); | ||
| 129 | val &= ~(PFDE | PFTE); | ||
| 130 | bfin_write16(BFIN_PORT_MUX, val); | ||
| 131 | 130 | ||
| 132 | val = bfin_read16(PORTF_FER); | 131 | #ifdef CONFIG_SERIAL_BFIN_UART0 |
| 133 | val |= 0xF; | 132 | peripheral_request(P_UART0_TX, DRIVER_NAME); |
| 134 | bfin_write16(PORTF_FER, val); | 133 | peripheral_request(P_UART0_RX, DRIVER_NAME); |
| 134 | #endif | ||
| 135 | |||
| 136 | #ifdef CONFIG_SERIAL_BFIN_UART1 | ||
| 137 | peripheral_request(P_UART1_TX, DRIVER_NAME); | ||
| 138 | peripheral_request(P_UART1_RX, DRIVER_NAME); | ||
| 139 | #endif | ||
| 135 | 140 | ||
| 136 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS | 141 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS |
| 137 | if (uart->cts_pin >= 0) { | 142 | if (uart->cts_pin >= 0) { |
| 138 | gpio_request(uart->cts_pin, NULL); | 143 | gpio_request(uart->cts_pin, DRIVER_NAME); |
| 139 | gpio_direction_input(uart->cts_pin); | 144 | gpio_direction_input(uart->cts_pin); |
| 140 | } | 145 | } |
| 141 | 146 | ||
| 142 | if (uart->rts_pin >= 0) { | 147 | if (uart->rts_pin >= 0) { |
| 143 | gpio_request(uart->rts_pin, NULL); | 148 | gpio_request(uart->rts_pin, DRIVER_NAME); |
| 144 | gpio_direction_output(uart->rts_pin); | 149 | gpio_direction_output(uart->rts_pin); |
| 145 | } | 150 | } |
| 146 | #endif | 151 | #endif |
diff --git a/include/asm-blackfin/mach-bf537/portmux.h b/include/asm-blackfin/mach-bf537/portmux.h index 23e13c5abc4d..ae6c53b28452 100644 --- a/include/asm-blackfin/mach-bf537/portmux.h +++ b/include/asm-blackfin/mach-bf537/portmux.h | |||
| @@ -106,4 +106,37 @@ | |||
| 106 | #define P_SPI0_SSEL2 (P_DEFINED | P_IDENT(PORT_PJ11) | P_FUNCT(1)) | 106 | #define P_SPI0_SSEL2 (P_DEFINED | P_IDENT(PORT_PJ11) | P_FUNCT(1)) |
| 107 | #define P_SPI0_SSEL7 (P_DEFINED | P_IDENT(PORT_PJ5) | P_FUNCT(2)) | 107 | #define P_SPI0_SSEL7 (P_DEFINED | P_IDENT(PORT_PJ5) | P_FUNCT(2)) |
| 108 | 108 | ||
| 109 | #endif /* _MACH_PORTMUX_H_ */ | 109 | #define P_MII0 {\ |
| 110 | P_MII0_ETxD0, \ | ||
| 111 | P_MII0_ETxD1, \ | ||
| 112 | P_MII0_ETxD2, \ | ||
| 113 | P_MII0_ETxD3, \ | ||
| 114 | P_MII0_ETxEN, \ | ||
| 115 | P_MII0_TxCLK, \ | ||
| 116 | P_MII0_PHYINT, \ | ||
| 117 | P_MII0_COL, \ | ||
| 118 | P_MII0_ERxD0, \ | ||
| 119 | P_MII0_ERxD1, \ | ||
| 120 | P_MII0_ERxD2, \ | ||
| 121 | P_MII0_ERxD3, \ | ||
| 122 | P_MII0_ERxDV, \ | ||
| 123 | P_MII0_ERxCLK, \ | ||
| 124 | P_MII0_ERxER, \ | ||
| 125 | P_MII0_CRS, \ | ||
| 126 | P_MDC, \ | ||
| 127 | P_MDIO, 0} | ||
| 128 | |||
| 129 | |||
| 130 | #define P_RMII0 {\ | ||
| 131 | P_MII0_ETxD0, \ | ||
| 132 | P_MII0_ETxD1, \ | ||
| 133 | P_MII0_ETxEN, \ | ||
| 134 | P_MII0_ERxD0, \ | ||
| 135 | P_MII0_ERxD1, \ | ||
| 136 | P_MII0_ERxER, \ | ||
| 137 | P_RMII0_REF_CLK, \ | ||
| 138 | P_RMII0_MDINT, \ | ||
| 139 | P_RMII0_CRS_DV, \ | ||
| 140 | P_MDC, \ | ||
| 141 | P_MDIO, 0} | ||
| 142 | #endif /* _MACH_PORTMUX_H_ */ | ||
diff --git a/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h index e043cafa3c42..69b9f8e120e9 100644 --- a/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h +++ b/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | #include <linux/serial.h> | 1 | #include <linux/serial.h> |
| 2 | #include <asm/dma.h> | 2 | #include <asm/dma.h> |
| 3 | #include <asm/portmux.h> | ||
| 3 | 4 | ||
| 4 | #define NR_PORTS 1 | 5 | #define NR_PORTS 1 |
| 5 | 6 | ||
| @@ -92,18 +93,24 @@ struct bfin_serial_res bfin_serial_resource[] = { | |||
| 92 | } | 93 | } |
| 93 | }; | 94 | }; |
| 94 | 95 | ||
| 96 | #define DRIVER_NAME "bfin-uart" | ||
| 95 | 97 | ||
| 96 | int nr_ports = NR_PORTS; | 98 | int nr_ports = NR_PORTS; |
| 97 | static void bfin_serial_hw_init(struct bfin_serial_port *uart) | 99 | static void bfin_serial_hw_init(struct bfin_serial_port *uart) |
| 98 | { | 100 | { |
| 99 | 101 | ||
| 102 | #ifdef CONFIG_SERIAL_BFIN_UART0 | ||
| 103 | peripheral_request(P_UART0_TX, DRIVER_NAME); | ||
| 104 | peripheral_request(P_UART0_RX, DRIVER_NAME); | ||
| 105 | #endif | ||
| 106 | |||
| 100 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS | 107 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS |
| 101 | if (uart->cts_pin >= 0) { | 108 | if (uart->cts_pin >= 0) { |
| 102 | gpio_request(uart->cts_pin, NULL); | 109 | gpio_request(uart->cts_pin, DRIVER_NAME); |
| 103 | gpio_direction_input(uart->cts_pin); | 110 | gpio_direction_input(uart->cts_pin); |
| 104 | } | 111 | } |
| 105 | if (uart->rts_pin >= 0) { | 112 | if (uart->rts_pin >= 0) { |
| 106 | gpio_request(uart->rts_pin, NULL); | 113 | gpio_request(uart->rts_pin, DRIVER_NAME); |
| 107 | gpio_direction_input(uart->rts_pin); | 114 | gpio_direction_input(uart->rts_pin); |
| 108 | } | 115 | } |
| 109 | #endif | 116 | #endif |
diff --git a/include/asm-blackfin/portmux.h b/include/asm-blackfin/portmux.h index 9d3681e42111..0d3f650d2d99 100644 --- a/include/asm-blackfin/portmux.h +++ b/include/asm-blackfin/portmux.h | |||
| @@ -14,6 +14,12 @@ | |||
| 14 | #define P_MAYSHARE 0x2000 | 14 | #define P_MAYSHARE 0x2000 |
| 15 | #define P_DONTCARE 0x1000 | 15 | #define P_DONTCARE 0x1000 |
| 16 | 16 | ||
| 17 | |||
| 18 | int peripheral_request(unsigned short per, const char *label); | ||
| 19 | void peripheral_free(unsigned short per); | ||
| 20 | int peripheral_request_list(unsigned short per[], const char *label); | ||
| 21 | void peripheral_free_list(unsigned short per[]); | ||
| 22 | |||
| 17 | #include <asm/gpio.h> | 23 | #include <asm/gpio.h> |
| 18 | #include <asm/mach/portmux.h> | 24 | #include <asm/mach/portmux.h> |
| 19 | 25 | ||
| @@ -145,6 +151,22 @@ | |||
| 145 | #define P_SPI2_SSEL3 P_UNDEF | 151 | #define P_SPI2_SSEL3 P_UNDEF |
| 146 | #endif | 152 | #endif |
| 147 | 153 | ||
| 154 | #ifndef P_SPI2_SSEL4 | ||
| 155 | #define P_SPI2_SSEL4 P_UNDEF | ||
| 156 | #endif | ||
| 157 | |||
| 158 | #ifndef P_SPI2_SSEL5 | ||
| 159 | #define P_SPI2_SSEL5 P_UNDEF | ||
| 160 | #endif | ||
| 161 | |||
| 162 | #ifndef P_SPI2_SSEL6 | ||
| 163 | #define P_SPI2_SSEL6 P_UNDEF | ||
| 164 | #endif | ||
| 165 | |||
| 166 | #ifndef P_SPI2_SSEL7 | ||
| 167 | #define P_SPI2_SSEL7 P_UNDEF | ||
| 168 | #endif | ||
| 169 | |||
| 148 | #ifndef P_SPI2_SCK | 170 | #ifndef P_SPI2_SCK |
| 149 | #define P_SPI2_SCK P_UNDEF | 171 | #define P_SPI2_SCK P_UNDEF |
| 150 | #endif | 172 | #endif |
| @@ -513,6 +535,22 @@ | |||
| 513 | #define P_SPI0_SSEL3 P_UNDEF | 535 | #define P_SPI0_SSEL3 P_UNDEF |
| 514 | #endif | 536 | #endif |
| 515 | 537 | ||
| 538 | #ifndef P_SPI0_SSEL4 | ||
| 539 | #define P_SPI0_SSEL4 P_UNDEF | ||
| 540 | #endif | ||
| 541 | |||
| 542 | #ifndef P_SPI0_SSEL5 | ||
| 543 | #define P_SPI0_SSEL5 P_UNDEF | ||
| 544 | #endif | ||
| 545 | |||
| 546 | #ifndef P_SPI0_SSEL6 | ||
| 547 | #define P_SPI0_SSEL6 P_UNDEF | ||
| 548 | #endif | ||
| 549 | |||
| 550 | #ifndef P_SPI0_SSEL7 | ||
| 551 | #define P_SPI0_SSEL7 P_UNDEF | ||
| 552 | #endif | ||
| 553 | |||
| 516 | #ifndef P_UART0_TX | 554 | #ifndef P_UART0_TX |
| 517 | #define P_UART0_TX P_UNDEF | 555 | #define P_UART0_TX P_UNDEF |
| 518 | #endif | 556 | #endif |
| @@ -741,6 +779,23 @@ | |||
| 741 | #define P_SPI1_SSEL3 P_UNDEF | 779 | #define P_SPI1_SSEL3 P_UNDEF |
| 742 | #endif | 780 | #endif |
| 743 | 781 | ||
| 782 | |||
| 783 | #ifndef P_SPI1_SSEL4 | ||
| 784 | #define P_SPI1_SSEL4 P_UNDEF | ||
| 785 | #endif | ||
| 786 | |||
| 787 | #ifndef P_SPI1_SSEL5 | ||
| 788 | #define P_SPI1_SSEL5 P_UNDEF | ||
| 789 | #endif | ||
| 790 | |||
| 791 | #ifndef P_SPI1_SSEL6 | ||
| 792 | #define P_SPI1_SSEL6 P_UNDEF | ||
| 793 | #endif | ||
| 794 | |||
| 795 | #ifndef P_SPI1_SSEL7 | ||
| 796 | #define P_SPI1_SSEL7 P_UNDEF | ||
| 797 | #endif | ||
| 798 | |||
| 744 | #ifndef P_SPI1_SCK | 799 | #ifndef P_SPI1_SCK |
| 745 | #define P_SPI1_SCK P_UNDEF | 800 | #define P_SPI1_SCK P_UNDEF |
| 746 | #endif | 801 | #endif |
diff --git a/include/asm-blackfin/unistd.h b/include/asm-blackfin/unistd.h index 0df9f2d322a3..07ffe8b718c5 100644 --- a/include/asm-blackfin/unistd.h +++ b/include/asm-blackfin/unistd.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | /* | 3 | /* |
| 4 | * This file contains the system call numbers. | 4 | * This file contains the system call numbers. |
| 5 | */ | 5 | */ |
| 6 | #define __NR_restart_syscall 0 | ||
| 6 | #define __NR_exit 1 | 7 | #define __NR_exit 1 |
| 7 | #define __NR_fork 2 | 8 | #define __NR_fork 2 |
| 8 | #define __NR_read 3 | 9 | #define __NR_read 3 |
| @@ -165,13 +166,13 @@ | |||
| 165 | #define __NR_sched_get_priority_min 160 | 166 | #define __NR_sched_get_priority_min 160 |
| 166 | #define __NR_sched_rr_get_interval 161 | 167 | #define __NR_sched_rr_get_interval 161 |
| 167 | #define __NR_nanosleep 162 | 168 | #define __NR_nanosleep 162 |
| 168 | /* 163 __NR_mremap */ | 169 | #define __NR_mremap 163 |
| 169 | #define __NR_setresuid 164 | 170 | #define __NR_setresuid 164 |
| 170 | #define __NR_getresuid 165 | 171 | #define __NR_getresuid 165 |
| 171 | /* 166 __NR_vm86 */ | 172 | /* 166 __NR_vm86 */ |
| 172 | /* 167 __NR_query_module */ | 173 | /* 167 __NR_query_module */ |
| 173 | /* 168 __NR_poll */ | 174 | /* 168 __NR_poll */ |
| 174 | /* 169 __NR_nfsservctl */ | 175 | #define __NR_nfsservctl 169 |
| 175 | #define __NR_setresgid 170 | 176 | #define __NR_setresgid 170 |
| 176 | #define __NR_getresgid 171 | 177 | #define __NR_getresgid 171 |
| 177 | #define __NR_prctl 172 | 178 | #define __NR_prctl 172 |
| @@ -227,7 +228,7 @@ | |||
| 227 | /* 222 reserved for TUX */ | 228 | /* 222 reserved for TUX */ |
| 228 | /* 223 reserved for TUX */ | 229 | /* 223 reserved for TUX */ |
| 229 | #define __NR_gettid 224 | 230 | #define __NR_gettid 224 |
| 230 | /* 225 __NR_readahead */ | 231 | #define __NR_readahead 225 |
| 231 | #define __NR_setxattr 226 | 232 | #define __NR_setxattr 226 |
| 232 | #define __NR_lsetxattr 227 | 233 | #define __NR_lsetxattr 227 |
| 233 | #define __NR_fsetxattr 228 | 234 | #define __NR_fsetxattr 228 |
| @@ -287,7 +288,7 @@ | |||
| 287 | #define __NR_mq_timedreceive (__NR_mq_open+3) | 288 | #define __NR_mq_timedreceive (__NR_mq_open+3) |
| 288 | #define __NR_mq_notify (__NR_mq_open+4) | 289 | #define __NR_mq_notify (__NR_mq_open+4) |
| 289 | #define __NR_mq_getsetattr (__NR_mq_open+5) | 290 | #define __NR_mq_getsetattr (__NR_mq_open+5) |
| 290 | /* 284 __NR_sys_kexec_load */ | 291 | #define __NR_kexec_load 284 |
| 291 | #define __NR_waitid 285 | 292 | #define __NR_waitid 285 |
| 292 | #define __NR_add_key 286 | 293 | #define __NR_add_key 286 |
| 293 | #define __NR_request_key 287 | 294 | #define __NR_request_key 287 |
| @@ -352,9 +353,54 @@ | |||
| 352 | #define __NR_shmdt 340 | 353 | #define __NR_shmdt 340 |
| 353 | #define __NR_shmget 341 | 354 | #define __NR_shmget 341 |
| 354 | 355 | ||
| 355 | #define __NR_syscall 342 | 356 | #define __NR_splice 342 |
| 357 | #define __NR_sync_file_range 343 | ||
| 358 | #define __NR_tee 344 | ||
| 359 | #define __NR_vmsplice 345 | ||
| 360 | |||
| 361 | #define __NR_epoll_pwait 346 | ||
| 362 | #define __NR_utimensat 347 | ||
| 363 | #define __NR_signalfd 348 | ||
| 364 | #define __NR_timerfd 349 | ||
| 365 | #define __NR_eventfd 350 | ||
| 366 | #define __NR_pread64 351 | ||
| 367 | #define __NR_pwrite64 352 | ||
| 368 | #define __NR_fadvise64 353 | ||
| 369 | #define __NR_set_robust_list 354 | ||
| 370 | #define __NR_get_robust_list 355 | ||
| 371 | #define __NR_fallocate 356 | ||
| 372 | |||
| 373 | #define __NR_syscall 357 | ||
| 356 | #define NR_syscalls __NR_syscall | 374 | #define NR_syscalls __NR_syscall |
| 357 | 375 | ||
| 376 | /* Old optional stuff no one actually uses */ | ||
| 377 | #define __IGNORE_sysfs | ||
| 378 | #define __IGNORE_uselib | ||
| 379 | |||
| 380 | /* Implement the newer interfaces */ | ||
| 381 | #define __IGNORE_mmap | ||
| 382 | #define __IGNORE_poll | ||
| 383 | #define __IGNORE_select | ||
| 384 | #define __IGNORE_utime | ||
| 385 | |||
| 386 | /* Not relevant on no-mmu */ | ||
| 387 | #define __IGNORE_swapon | ||
| 388 | #define __IGNORE_swapoff | ||
| 389 | #define __IGNORE_msync | ||
| 390 | #define __IGNORE_mlock | ||
| 391 | #define __IGNORE_munlock | ||
| 392 | #define __IGNORE_mlockall | ||
| 393 | #define __IGNORE_munlockall | ||
| 394 | #define __IGNORE_mincore | ||
| 395 | #define __IGNORE_madvise | ||
| 396 | #define __IGNORE_remap_file_pages | ||
| 397 | #define __IGNORE_mbind | ||
| 398 | #define __IGNORE_get_mempolicy | ||
| 399 | #define __IGNORE_set_mempolicy | ||
| 400 | #define __IGNORE_migrate_pages | ||
| 401 | #define __IGNORE_move_pages | ||
| 402 | #define __IGNORE_getcpu | ||
| 403 | |||
| 358 | #ifdef __KERNEL__ | 404 | #ifdef __KERNEL__ |
| 359 | #define __ARCH_WANT_IPC_PARSE_VERSION | 405 | #define __ARCH_WANT_IPC_PARSE_VERSION |
| 360 | #define __ARCH_WANT_STAT64 | 406 | #define __ARCH_WANT_STAT64 |
diff --git a/include/asm-h8300/flat.h b/include/asm-h8300/flat.h index c20eee767d6f..2a873508a9a1 100644 --- a/include/asm-h8300/flat.h +++ b/include/asm-h8300/flat.h | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #define flat_argvp_envp_on_stack() 1 | 9 | #define flat_argvp_envp_on_stack() 1 |
| 10 | #define flat_old_ram_flag(flags) 1 | 10 | #define flat_old_ram_flag(flags) 1 |
| 11 | #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) | 11 | #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) |
| 12 | #define flat_set_persistent(relval, p) 0 | ||
| 12 | 13 | ||
| 13 | /* | 14 | /* |
| 14 | * on the H8 a couple of the relocations have an instruction in the | 15 | * on the H8 a couple of the relocations have an instruction in the |
| @@ -18,7 +19,7 @@ | |||
| 18 | */ | 19 | */ |
| 19 | 20 | ||
| 20 | #define flat_get_relocate_addr(rel) (rel) | 21 | #define flat_get_relocate_addr(rel) (rel) |
| 21 | #define flat_get_addr_from_rp(rp, relval, flags) \ | 22 | #define flat_get_addr_from_rp(rp, relval, flags, persistent) \ |
| 22 | (get_unaligned(rp) & ((flags & FLAT_FLAG_GOTPIC) ? 0xffffffff: 0x00ffffff)) | 23 | (get_unaligned(rp) & ((flags & FLAT_FLAG_GOTPIC) ? 0xffffffff: 0x00ffffff)) |
| 23 | #define flat_put_addr_at_rp(rp, addr, rel) \ | 24 | #define flat_put_addr_at_rp(rp, addr, rel) \ |
| 24 | put_unaligned (((*(char *)(rp)) << 24) | ((addr) & 0x00ffffff), rp) | 25 | put_unaligned (((*(char *)(rp)) << 24) | ((addr) & 0x00ffffff), rp) |
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h index 609756c61676..d69ba937e092 100644 --- a/include/asm-i386/system.h +++ b/include/asm-i386/system.h | |||
| @@ -214,11 +214,6 @@ static inline unsigned long get_limit(unsigned long segment) | |||
| 214 | */ | 214 | */ |
| 215 | 215 | ||
| 216 | 216 | ||
| 217 | /* | ||
| 218 | * Actually only lfence would be needed for mb() because all stores done | ||
| 219 | * by the kernel should be already ordered. But keep a full barrier for now. | ||
| 220 | */ | ||
| 221 | |||
| 222 | #define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2) | 217 | #define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2) |
| 223 | #define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2) | 218 | #define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2) |
| 224 | 219 | ||
diff --git a/include/asm-m32r/flat.h b/include/asm-m32r/flat.h index 1b285f65cab6..d851cf0c4aa5 100644 --- a/include/asm-m32r/flat.h +++ b/include/asm-m32r/flat.h | |||
| @@ -15,9 +15,10 @@ | |||
| 15 | #define flat_stack_align(sp) (*sp += (*sp & 3 ? (4 - (*sp & 3)): 0)) | 15 | #define flat_stack_align(sp) (*sp += (*sp & 3 ? (4 - (*sp & 3)): 0)) |
| 16 | #define flat_argvp_envp_on_stack() 0 | 16 | #define flat_argvp_envp_on_stack() 0 |
| 17 | #define flat_old_ram_flag(flags) (flags) | 17 | #define flat_old_ram_flag(flags) (flags) |
| 18 | #define flat_set_persistent(relval, p) 0 | ||
| 18 | #define flat_reloc_valid(reloc, size) \ | 19 | #define flat_reloc_valid(reloc, size) \ |
| 19 | (((reloc) - textlen_for_m32r_lo16_data) <= (size)) | 20 | (((reloc) - textlen_for_m32r_lo16_data) <= (size)) |
| 20 | #define flat_get_addr_from_rp(rp, relval, flags) \ | 21 | #define flat_get_addr_from_rp(rp, relval, flags, persistent) \ |
| 21 | m32r_flat_get_addr_from_rp(rp, relval, (text_len) ) | 22 | m32r_flat_get_addr_from_rp(rp, relval, (text_len) ) |
| 22 | 23 | ||
| 23 | #define flat_put_addr_at_rp(rp, addr, relval) \ | 24 | #define flat_put_addr_at_rp(rp, addr, relval) \ |
diff --git a/include/asm-m68knommu/flat.h b/include/asm-m68knommu/flat.h index 2d836edc4344..814b5174a8e0 100644 --- a/include/asm-m68knommu/flat.h +++ b/include/asm-m68knommu/flat.h | |||
| @@ -9,8 +9,9 @@ | |||
| 9 | #define flat_argvp_envp_on_stack() 1 | 9 | #define flat_argvp_envp_on_stack() 1 |
| 10 | #define flat_old_ram_flag(flags) (flags) | 10 | #define flat_old_ram_flag(flags) (flags) |
| 11 | #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) | 11 | #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) |
| 12 | #define flat_get_addr_from_rp(rp, relval, flags) get_unaligned(rp) | 12 | #define flat_get_addr_from_rp(rp, relval, flags, p) get_unaligned(rp) |
| 13 | #define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp) | 13 | #define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp) |
| 14 | #define flat_get_relocate_addr(rel) (rel) | 14 | #define flat_get_relocate_addr(rel) (rel) |
| 15 | #define flat_set_persistent(relval, p) 0 | ||
| 15 | 16 | ||
| 16 | #endif /* __M68KNOMMU_FLAT_H__ */ | 17 | #endif /* __M68KNOMMU_FLAT_H__ */ |
diff --git a/include/asm-mips/cmpxchg.h b/include/asm-mips/cmpxchg.h new file mode 100644 index 000000000000..c5b4708e003b --- /dev/null +++ b/include/asm-mips/cmpxchg.h | |||
| @@ -0,0 +1,107 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2003, 06, 07 by Ralf Baechle (ralf@linux-mips.org) | ||
| 7 | */ | ||
| 8 | #ifndef __ASM_CMPXCHG_H | ||
| 9 | #define __ASM_CMPXCHG_H | ||
| 10 | |||
| 11 | #include <linux/irqflags.h> | ||
| 12 | |||
| 13 | #define __HAVE_ARCH_CMPXCHG 1 | ||
| 14 | |||
| 15 | #define __cmpxchg_asm(ld, st, m, old, new) \ | ||
| 16 | ({ \ | ||
| 17 | __typeof(*(m)) __ret; \ | ||
| 18 | \ | ||
| 19 | if (cpu_has_llsc && R10000_LLSC_WAR) { \ | ||
| 20 | __asm__ __volatile__( \ | ||
| 21 | " .set push \n" \ | ||
| 22 | " .set noat \n" \ | ||
| 23 | " .set mips3 \n" \ | ||
| 24 | "1: " ld " %0, %2 # __cmpxchg_asm \n" \ | ||
| 25 | " bne %0, %z3, 2f \n" \ | ||
| 26 | " .set mips0 \n" \ | ||
| 27 | " move $1, %z4 \n" \ | ||
| 28 | " .set mips3 \n" \ | ||
| 29 | " " st " $1, %1 \n" \ | ||
| 30 | " beqzl $1, 1b \n" \ | ||
| 31 | "2: \n" \ | ||
| 32 | " .set pop \n" \ | ||
| 33 | : "=&r" (__ret), "=R" (*m) \ | ||
| 34 | : "R" (*m), "Jr" (old), "Jr" (new) \ | ||
| 35 | : "memory"); \ | ||
| 36 | } else if (cpu_has_llsc) { \ | ||
| 37 | __asm__ __volatile__( \ | ||
| 38 | " .set push \n" \ | ||
| 39 | " .set noat \n" \ | ||
| 40 | " .set mips3 \n" \ | ||
| 41 | "1: " ld " %0, %2 # __cmpxchg_asm \n" \ | ||
| 42 | " bne %0, %z3, 2f \n" \ | ||
| 43 | " .set mips0 \n" \ | ||
| 44 | " move $1, %z4 \n" \ | ||
| 45 | " .set mips3 \n" \ | ||
| 46 | " " st " $1, %1 \n" \ | ||
| 47 | " beqz $1, 3f \n" \ | ||
| 48 | "2: \n" \ | ||
| 49 | " .subsection 2 \n" \ | ||
| 50 | "3: b 1b \n" \ | ||
| 51 | " .previous \n" \ | ||
| 52 | " .set pop \n" \ | ||
| 53 | : "=&r" (__ret), "=R" (*m) \ | ||
| 54 | : "R" (*m), "Jr" (old), "Jr" (new) \ | ||
| 55 | : "memory"); \ | ||
| 56 | } else { \ | ||
| 57 | unsigned long __flags; \ | ||
| 58 | \ | ||
| 59 | raw_local_irq_save(__flags); \ | ||
| 60 | __ret = *m; \ | ||
| 61 | if (__ret == old) \ | ||
| 62 | *m = new; \ | ||
| 63 | raw_local_irq_restore(__flags); \ | ||
| 64 | } \ | ||
| 65 | \ | ||
| 66 | __ret; \ | ||
| 67 | }) | ||
| 68 | |||
| 69 | /* | ||
| 70 | * This function doesn't exist, so you'll get a linker error | ||
| 71 | * if something tries to do an invalid cmpxchg(). | ||
| 72 | */ | ||
| 73 | extern void __cmpxchg_called_with_bad_pointer(void); | ||
| 74 | |||
| 75 | #define __cmpxchg(ptr,old,new,barrier) \ | ||
| 76 | ({ \ | ||
| 77 | __typeof__(ptr) __ptr = (ptr); \ | ||
| 78 | __typeof__(*(ptr)) __old = (old); \ | ||
| 79 | __typeof__(*(ptr)) __new = (new); \ | ||
| 80 | __typeof__(*(ptr)) __res = 0; \ | ||
| 81 | \ | ||
| 82 | barrier; \ | ||
| 83 | \ | ||
| 84 | switch (sizeof(*(__ptr))) { \ | ||
| 85 | case 4: \ | ||
| 86 | __res = __cmpxchg_asm("ll", "sc", __ptr, __old, __new); \ | ||
| 87 | break; \ | ||
| 88 | case 8: \ | ||
| 89 | if (sizeof(long) == 8) { \ | ||
| 90 | __res = __cmpxchg_asm("lld", "scd", __ptr, \ | ||
| 91 | __old, __new); \ | ||
| 92 | break; \ | ||
| 93 | } \ | ||
| 94 | default: \ | ||
| 95 | __cmpxchg_called_with_bad_pointer(); \ | ||
| 96 | break; \ | ||
| 97 | } \ | ||
| 98 | \ | ||
| 99 | barrier; \ | ||
| 100 | \ | ||
| 101 | __res; \ | ||
| 102 | }) | ||
| 103 | |||
| 104 | #define cmpxchg(ptr, old, new) __cmpxchg(ptr, old, new, smp_llsc_mb()) | ||
| 105 | #define cmpxchg_local(ptr, old, new) __cmpxchg(ptr, old, new,) | ||
| 106 | |||
| 107 | #endif /* __ASM_CMPXCHG_H */ | ||
diff --git a/include/asm-mips/fcntl.h b/include/asm-mips/fcntl.h index 00a50ec1c19f..2a52333a062d 100644 --- a/include/asm-mips/fcntl.h +++ b/include/asm-mips/fcntl.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #define O_SYNC 0x0010 | 13 | #define O_SYNC 0x0010 |
| 14 | #define O_NONBLOCK 0x0080 | 14 | #define O_NONBLOCK 0x0080 |
| 15 | #define O_CREAT 0x0100 /* not fcntl */ | 15 | #define O_CREAT 0x0100 /* not fcntl */ |
| 16 | #define O_TRUNC 0x0200 /* not fcntl */ | ||
| 16 | #define O_EXCL 0x0400 /* not fcntl */ | 17 | #define O_EXCL 0x0400 /* not fcntl */ |
| 17 | #define O_NOCTTY 0x0800 /* not fcntl */ | 18 | #define O_NOCTTY 0x0800 /* not fcntl */ |
| 18 | #define FASYNC 0x1000 /* fcntl, for BSD compatibility */ | 19 | #define FASYNC 0x1000 /* fcntl, for BSD compatibility */ |
diff --git a/include/asm-mips/local.h b/include/asm-mips/local.h index ed882c88e0ca..f9a5ce5c9af1 100644 --- a/include/asm-mips/local.h +++ b/include/asm-mips/local.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #include <linux/percpu.h> | 4 | #include <linux/percpu.h> |
| 5 | #include <linux/bitops.h> | 5 | #include <linux/bitops.h> |
| 6 | #include <asm/atomic.h> | 6 | #include <asm/atomic.h> |
| 7 | #include <asm/cmpxchg.h> | ||
| 7 | #include <asm/war.h> | 8 | #include <asm/war.h> |
| 8 | 9 | ||
| 9 | typedef struct | 10 | typedef struct |
| @@ -114,68 +115,6 @@ static __inline__ long local_sub_return(long i, local_t * l) | |||
| 114 | return result; | 115 | return result; |
| 115 | } | 116 | } |
| 116 | 117 | ||
| 117 | /* | ||
| 118 | * local_sub_if_positive - conditionally subtract integer from atomic variable | ||
| 119 | * @i: integer value to subtract | ||
| 120 | * @l: pointer of type local_t | ||
| 121 | * | ||
| 122 | * Atomically test @l and subtract @i if @l is greater or equal than @i. | ||
| 123 | * The function returns the old value of @l minus @i. | ||
| 124 | */ | ||
| 125 | static __inline__ long local_sub_if_positive(long i, local_t * l) | ||
| 126 | { | ||
| 127 | unsigned long result; | ||
| 128 | |||
| 129 | if (cpu_has_llsc && R10000_LLSC_WAR) { | ||
| 130 | unsigned long temp; | ||
| 131 | |||
| 132 | __asm__ __volatile__( | ||
| 133 | " .set mips3 \n" | ||
| 134 | "1:" __LL "%1, %2 # local_sub_if_positive\n" | ||
| 135 | " dsubu %0, %1, %3 \n" | ||
| 136 | " bltz %0, 1f \n" | ||
| 137 | __SC "%0, %2 \n" | ||
| 138 | " .set noreorder \n" | ||
| 139 | " beqzl %0, 1b \n" | ||
| 140 | " dsubu %0, %1, %3 \n" | ||
| 141 | " .set reorder \n" | ||
| 142 | "1: \n" | ||
| 143 | " .set mips0 \n" | ||
| 144 | : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) | ||
| 145 | : "Ir" (i), "m" (l->a.counter) | ||
| 146 | : "memory"); | ||
| 147 | } else if (cpu_has_llsc) { | ||
| 148 | unsigned long temp; | ||
| 149 | |||
| 150 | __asm__ __volatile__( | ||
| 151 | " .set mips3 \n" | ||
| 152 | "1:" __LL "%1, %2 # local_sub_if_positive\n" | ||
| 153 | " dsubu %0, %1, %3 \n" | ||
| 154 | " bltz %0, 1f \n" | ||
| 155 | __SC "%0, %2 \n" | ||
| 156 | " .set noreorder \n" | ||
| 157 | " beqz %0, 1b \n" | ||
| 158 | " dsubu %0, %1, %3 \n" | ||
| 159 | " .set reorder \n" | ||
| 160 | "1: \n" | ||
| 161 | " .set mips0 \n" | ||
| 162 | : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) | ||
| 163 | : "Ir" (i), "m" (l->a.counter) | ||
| 164 | : "memory"); | ||
| 165 | } else { | ||
| 166 | unsigned long flags; | ||
| 167 | |||
| 168 | local_irq_save(flags); | ||
| 169 | result = l->a.counter; | ||
| 170 | result -= i; | ||
| 171 | if (result >= 0) | ||
| 172 | l->a.counter = result; | ||
| 173 | local_irq_restore(flags); | ||
| 174 | } | ||
| 175 | |||
| 176 | return result; | ||
| 177 | } | ||
| 178 | |||
| 179 | #define local_cmpxchg(l, o, n) \ | 118 | #define local_cmpxchg(l, o, n) \ |
| 180 | ((long)cmpxchg_local(&((l)->a.counter), (o), (n))) | 119 | ((long)cmpxchg_local(&((l)->a.counter), (o), (n))) |
| 181 | #define local_xchg(l, n) (xchg_local(&((l)->a.counter),(n))) | 120 | #define local_xchg(l, n) (xchg_local(&((l)->a.counter),(n))) |
| @@ -234,12 +173,6 @@ static __inline__ long local_sub_if_positive(long i, local_t * l) | |||
| 234 | #define local_dec_and_test(l) (local_sub_return(1, (l)) == 0) | 173 | #define local_dec_and_test(l) (local_sub_return(1, (l)) == 0) |
| 235 | 174 | ||
| 236 | /* | 175 | /* |
| 237 | * local_dec_if_positive - decrement by 1 if old value positive | ||
| 238 | * @l: pointer of type local_t | ||
| 239 | */ | ||
| 240 | #define local_dec_if_positive(l) local_sub_if_positive(1, l) | ||
| 241 | |||
| 242 | /* | ||
| 243 | * local_add_negative - add and test if negative | 176 | * local_add_negative - add and test if negative |
| 244 | * @l: pointer of type local_t | 177 | * @l: pointer of type local_t |
| 245 | * @i: integer value to add | 178 | * @i: integer value to add |
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h index b92dd8c760da..e3301e54d559 100644 --- a/include/asm-mips/page.h +++ b/include/asm-mips/page.h | |||
| @@ -142,7 +142,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; | |||
| 142 | /* | 142 | /* |
| 143 | * __pa()/__va() should be used only during mem init. | 143 | * __pa()/__va() should be used only during mem init. |
| 144 | */ | 144 | */ |
| 145 | #if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64) | 145 | #ifdef CONFIG_64BIT |
| 146 | #define __pa(x) \ | 146 | #define __pa(x) \ |
| 147 | ({ \ | 147 | ({ \ |
| 148 | unsigned long __x = (unsigned long)(x); \ | 148 | unsigned long __x = (unsigned long)(x); \ |
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h index 357251f42518..480b574e2483 100644 --- a/include/asm-mips/system.h +++ b/include/asm-mips/system.h | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | #include <asm/addrspace.h> | 18 | #include <asm/addrspace.h> |
| 19 | #include <asm/barrier.h> | 19 | #include <asm/barrier.h> |
| 20 | #include <asm/cmpxchg.h> | ||
| 20 | #include <asm/cpu-features.h> | 21 | #include <asm/cpu-features.h> |
| 21 | #include <asm/dsp.h> | 22 | #include <asm/dsp.h> |
| 22 | #include <asm/war.h> | 23 | #include <asm/war.h> |
| @@ -194,266 +195,6 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz | |||
| 194 | 195 | ||
| 195 | #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) | 196 | #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) |
| 196 | 197 | ||
| 197 | #define __HAVE_ARCH_CMPXCHG 1 | ||
| 198 | |||
| 199 | static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old, | ||
| 200 | unsigned long new) | ||
| 201 | { | ||
| 202 | __u32 retval; | ||
| 203 | |||
| 204 | if (cpu_has_llsc && R10000_LLSC_WAR) { | ||
| 205 | __asm__ __volatile__( | ||
| 206 | " .set push \n" | ||
| 207 | " .set noat \n" | ||
| 208 | " .set mips3 \n" | ||
| 209 | "1: ll %0, %2 # __cmpxchg_u32 \n" | ||
| 210 | " bne %0, %z3, 2f \n" | ||
| 211 | " .set mips0 \n" | ||
| 212 | " move $1, %z4 \n" | ||
| 213 | " .set mips3 \n" | ||
| 214 | " sc $1, %1 \n" | ||
| 215 | " beqzl $1, 1b \n" | ||
| 216 | "2: \n" | ||
| 217 | " .set pop \n" | ||
| 218 | : "=&r" (retval), "=R" (*m) | ||
| 219 | : "R" (*m), "Jr" (old), "Jr" (new) | ||
| 220 | : "memory"); | ||
| 221 | } else if (cpu_has_llsc) { | ||
| 222 | __asm__ __volatile__( | ||
| 223 | " .set push \n" | ||
| 224 | " .set noat \n" | ||
| 225 | " .set mips3 \n" | ||
| 226 | "1: ll %0, %2 # __cmpxchg_u32 \n" | ||
| 227 | " bne %0, %z3, 2f \n" | ||
| 228 | " .set mips0 \n" | ||
| 229 | " move $1, %z4 \n" | ||
| 230 | " .set mips3 \n" | ||
| 231 | " sc $1, %1 \n" | ||
| 232 | " beqz $1, 3f \n" | ||
| 233 | "2: \n" | ||
| 234 | " .subsection 2 \n" | ||
| 235 | "3: b 1b \n" | ||
| 236 | " .previous \n" | ||
| 237 | " .set pop \n" | ||
| 238 | : "=&r" (retval), "=R" (*m) | ||
| 239 | : "R" (*m), "Jr" (old), "Jr" (new) | ||
| 240 | : "memory"); | ||
| 241 | } else { | ||
| 242 | unsigned long flags; | ||
| 243 | |||
| 244 | raw_local_irq_save(flags); | ||
| 245 | retval = *m; | ||
| 246 | if (retval == old) | ||
| 247 | *m = new; | ||
| 248 | raw_local_irq_restore(flags); /* implies memory barrier */ | ||
| 249 | } | ||
| 250 | |||
| 251 | smp_llsc_mb(); | ||
| 252 | |||
| 253 | return retval; | ||
| 254 | } | ||
| 255 | |||
| 256 | static inline unsigned long __cmpxchg_u32_local(volatile int * m, | ||
| 257 | unsigned long old, unsigned long new) | ||
| 258 | { | ||
| 259 | __u32 retval; | ||
| 260 | |||
| 261 | if (cpu_has_llsc && R10000_LLSC_WAR) { | ||
| 262 | __asm__ __volatile__( | ||
| 263 | " .set push \n" | ||
| 264 | " .set noat \n" | ||
| 265 | " .set mips3 \n" | ||
| 266 | "1: ll %0, %2 # __cmpxchg_u32 \n" | ||
| 267 | " bne %0, %z3, 2f \n" | ||
| 268 | " .set mips0 \n" | ||
| 269 | " move $1, %z4 \n" | ||
| 270 | " .set mips3 \n" | ||
| 271 | " sc $1, %1 \n" | ||
| 272 | " beqzl $1, 1b \n" | ||
| 273 | "2: \n" | ||
| 274 | " .set pop \n" | ||
| 275 | : "=&r" (retval), "=R" (*m) | ||
| 276 | : "R" (*m), "Jr" (old), "Jr" (new) | ||
| 277 | : "memory"); | ||
| 278 | } else if (cpu_has_llsc) { | ||
| 279 | __asm__ __volatile__( | ||
| 280 | " .set push \n" | ||
| 281 | " .set noat \n" | ||
| 282 | " .set mips3 \n" | ||
| 283 | "1: ll %0, %2 # __cmpxchg_u32 \n" | ||
| 284 | " bne %0, %z3, 2f \n" | ||
| 285 | " .set mips0 \n" | ||
| 286 | " move $1, %z4 \n" | ||
| 287 | " .set mips3 \n" | ||
| 288 | " sc $1, %1 \n" | ||
| 289 | " beqz $1, 1b \n" | ||
| 290 | "2: \n" | ||
| 291 | " .set pop \n" | ||
| 292 | : "=&r" (retval), "=R" (*m) | ||
| 293 | : "R" (*m), "Jr" (old), "Jr" (new) | ||
| 294 | : "memory"); | ||
| 295 | } else { | ||
| 296 | unsigned long flags; | ||
| 297 | |||
| 298 | local_irq_save(flags); | ||
| 299 | retval = *m; | ||
| 300 | if (retval == old) | ||
| 301 | *m = new; | ||
| 302 | local_irq_restore(flags); /* implies memory barrier */ | ||
| 303 | } | ||
| 304 | |||
| 305 | return retval; | ||
| 306 | } | ||
| 307 | |||
| 308 | #ifdef CONFIG_64BIT | ||
| 309 | static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old, | ||
| 310 | unsigned long new) | ||
| 311 | { | ||
| 312 | __u64 retval; | ||
| 313 | |||
| 314 | if (cpu_has_llsc && R10000_LLSC_WAR) { | ||
| 315 | __asm__ __volatile__( | ||
| 316 | " .set push \n" | ||
| 317 | " .set noat \n" | ||
| 318 | " .set mips3 \n" | ||
| 319 | "1: lld %0, %2 # __cmpxchg_u64 \n" | ||
| 320 | " bne %0, %z3, 2f \n" | ||
| 321 | " move $1, %z4 \n" | ||
| 322 | " scd $1, %1 \n" | ||
| 323 | " beqzl $1, 1b \n" | ||
| 324 | "2: \n" | ||
| 325 | " .set pop \n" | ||
| 326 | : "=&r" (retval), "=R" (*m) | ||
| 327 | : "R" (*m), "Jr" (old), "Jr" (new) | ||
| 328 | : "memory"); | ||
| 329 | } else if (cpu_has_llsc) { | ||
| 330 | __asm__ __volatile__( | ||
| 331 | " .set push \n" | ||
| 332 | " .set noat \n" | ||
| 333 | " .set mips3 \n" | ||
| 334 | "1: lld %0, %2 # __cmpxchg_u64 \n" | ||
| 335 | " bne %0, %z3, 2f \n" | ||
| 336 | " move $1, %z4 \n" | ||
| 337 | " scd $1, %1 \n" | ||
| 338 | " beqz $1, 3f \n" | ||
| 339 | "2: \n" | ||
| 340 | " .subsection 2 \n" | ||
| 341 | "3: b 1b \n" | ||
| 342 | " .previous \n" | ||
| 343 | " .set pop \n" | ||
| 344 | : "=&r" (retval), "=R" (*m) | ||
| 345 | : "R" (*m), "Jr" (old), "Jr" (new) | ||
| 346 | : "memory"); | ||
| 347 | } else { | ||
| 348 | unsigned long flags; | ||
| 349 | |||
| 350 | raw_local_irq_save(flags); | ||
| 351 | retval = *m; | ||
| 352 | if (retval == old) | ||
| 353 | *m = new; | ||
| 354 | raw_local_irq_restore(flags); /* implies memory barrier */ | ||
| 355 | } | ||
| 356 | |||
| 357 | smp_llsc_mb(); | ||
| 358 | |||
| 359 | return retval; | ||
| 360 | } | ||
| 361 | |||
| 362 | static inline unsigned long __cmpxchg_u64_local(volatile int * m, | ||
| 363 | unsigned long old, unsigned long new) | ||
| 364 | { | ||
| 365 | __u64 retval; | ||
| 366 | |||
| 367 | if (cpu_has_llsc && R10000_LLSC_WAR) { | ||
| 368 | __asm__ __volatile__( | ||
| 369 | " .set push \n" | ||
| 370 | " .set noat \n" | ||
| 371 | " .set mips3 \n" | ||
| 372 | "1: lld %0, %2 # __cmpxchg_u64 \n" | ||
| 373 | " bne %0, %z3, 2f \n" | ||
| 374 | " move $1, %z4 \n" | ||
| 375 | " scd $1, %1 \n" | ||
| 376 | " beqzl $1, 1b \n" | ||
| 377 | "2: \n" | ||
| 378 | " .set pop \n" | ||
| 379 | : "=&r" (retval), "=R" (*m) | ||
| 380 | : "R" (*m), "Jr" (old), "Jr" (new) | ||
| 381 | : "memory"); | ||
| 382 | } else if (cpu_has_llsc) { | ||
| 383 | __asm__ __volatile__( | ||
| 384 | " .set push \n" | ||
| 385 | " .set noat \n" | ||
| 386 | " .set mips3 \n" | ||
| 387 | "1: lld %0, %2 # __cmpxchg_u64 \n" | ||
| 388 | " bne %0, %z3, 2f \n" | ||
| 389 | " move $1, %z4 \n" | ||
| 390 | " scd $1, %1 \n" | ||
| 391 | " beqz $1, 1b \n" | ||
| 392 | "2: \n" | ||
| 393 | " .set pop \n" | ||
| 394 | : "=&r" (retval), "=R" (*m) | ||
| 395 | : "R" (*m), "Jr" (old), "Jr" (new) | ||
| 396 | : "memory"); | ||
| 397 | } else { | ||
| 398 | unsigned long flags; | ||
| 399 | |||
| 400 | local_irq_save(flags); | ||
| 401 | retval = *m; | ||
| 402 | if (retval == old) | ||
| 403 | *m = new; | ||
| 404 | local_irq_restore(flags); /* implies memory barrier */ | ||
| 405 | } | ||
| 406 | |||
| 407 | return retval; | ||
| 408 | } | ||
| 409 | |||
| 410 | #else | ||
| 411 | extern unsigned long __cmpxchg_u64_unsupported_on_32bit_kernels( | ||
| 412 | volatile int * m, unsigned long old, unsigned long new); | ||
| 413 | #define __cmpxchg_u64 __cmpxchg_u64_unsupported_on_32bit_kernels | ||
| 414 | extern unsigned long __cmpxchg_u64_local_unsupported_on_32bit_kernels( | ||
| 415 | volatile int * m, unsigned long old, unsigned long new); | ||
| 416 | #define __cmpxchg_u64_local __cmpxchg_u64_local_unsupported_on_32bit_kernels | ||
| 417 | #endif | ||
| 418 | |||
| 419 | /* This function doesn't exist, so you'll get a linker error | ||
| 420 | if something tries to do an invalid cmpxchg(). */ | ||
| 421 | extern void __cmpxchg_called_with_bad_pointer(void); | ||
| 422 | |||
| 423 | static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old, | ||
| 424 | unsigned long new, int size) | ||
| 425 | { | ||
| 426 | switch (size) { | ||
| 427 | case 4: | ||
| 428 | return __cmpxchg_u32(ptr, old, new); | ||
| 429 | case 8: | ||
| 430 | return __cmpxchg_u64(ptr, old, new); | ||
| 431 | } | ||
| 432 | __cmpxchg_called_with_bad_pointer(); | ||
| 433 | return old; | ||
| 434 | } | ||
| 435 | |||
| 436 | static inline unsigned long __cmpxchg_local(volatile void * ptr, | ||
| 437 | unsigned long old, unsigned long new, int size) | ||
| 438 | { | ||
| 439 | switch (size) { | ||
| 440 | case 4: | ||
| 441 | return __cmpxchg_u32_local(ptr, old, new); | ||
| 442 | case 8: | ||
| 443 | return __cmpxchg_u64_local(ptr, old, new); | ||
| 444 | } | ||
| 445 | __cmpxchg_called_with_bad_pointer(); | ||
| 446 | return old; | ||
| 447 | } | ||
| 448 | |||
| 449 | #define cmpxchg(ptr,old,new) \ | ||
| 450 | ((__typeof__(*(ptr)))__cmpxchg((ptr), \ | ||
| 451 | (unsigned long)(old), (unsigned long)(new),sizeof(*(ptr)))) | ||
| 452 | |||
| 453 | #define cmpxchg_local(ptr,old,new) \ | ||
| 454 | ((__typeof__(*(ptr)))__cmpxchg_local((ptr), \ | ||
| 455 | (unsigned long)(old), (unsigned long)(new),sizeof(*(ptr)))) | ||
| 456 | |||
| 457 | extern void set_handler (unsigned long offset, void *addr, unsigned long len); | 198 | extern void set_handler (unsigned long offset, void *addr, unsigned long len); |
| 458 | extern void set_uncached_handler (unsigned long offset, void *addr, unsigned long len); | 199 | extern void set_uncached_handler (unsigned long offset, void *addr, unsigned long len); |
| 459 | 200 | ||
diff --git a/include/asm-sh/flat.h b/include/asm-sh/flat.h index 0d5cc04ab005..dc4f5950dafa 100644 --- a/include/asm-sh/flat.h +++ b/include/asm-sh/flat.h | |||
| @@ -16,8 +16,9 @@ | |||
| 16 | #define flat_argvp_envp_on_stack() 0 | 16 | #define flat_argvp_envp_on_stack() 0 |
| 17 | #define flat_old_ram_flag(flags) (flags) | 17 | #define flat_old_ram_flag(flags) (flags) |
| 18 | #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) | 18 | #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) |
| 19 | #define flat_get_addr_from_rp(rp, relval, flags) get_unaligned(rp) | 19 | #define flat_get_addr_from_rp(rp, relval, flags, p) get_unaligned(rp) |
| 20 | #define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp) | 20 | #define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp) |
| 21 | #define flat_get_relocate_addr(rel) (rel) | 21 | #define flat_get_relocate_addr(rel) (rel) |
| 22 | #define flat_set_persistent(relval, p) 0 | ||
| 22 | 23 | ||
| 23 | #endif /* __ASM_SH_FLAT_H */ | 24 | #endif /* __ASM_SH_FLAT_H */ |
diff --git a/include/asm-v850/flat.h b/include/asm-v850/flat.h index 3888f59d6881..17f0ea566611 100644 --- a/include/asm-v850/flat.h +++ b/include/asm-v850/flat.h | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #define flat_stack_align(sp) /* nothing needed */ | 25 | #define flat_stack_align(sp) /* nothing needed */ |
| 26 | #define flat_argvp_envp_on_stack() 0 | 26 | #define flat_argvp_envp_on_stack() 0 |
| 27 | #define flat_old_ram_flag(flags) (flags) | 27 | #define flat_old_ram_flag(flags) (flags) |
| 28 | #define flat_set_persistent(relval, p) 0 | ||
| 28 | 29 | ||
| 29 | /* We store the type of relocation in the top 4 bits of the `relval.' */ | 30 | /* We store the type of relocation in the top 4 bits of the `relval.' */ |
| 30 | 31 | ||
| @@ -46,7 +47,8 @@ flat_get_relocate_addr (unsigned long relval) | |||
| 46 | For the v850, RP should always be half-word aligned. */ | 47 | For the v850, RP should always be half-word aligned. */ |
| 47 | static inline unsigned long flat_get_addr_from_rp (unsigned long *rp, | 48 | static inline unsigned long flat_get_addr_from_rp (unsigned long *rp, |
| 48 | unsigned long relval, | 49 | unsigned long relval, |
| 49 | unsigned long flags) | 50 | unsigned long flags, |
| 51 | unsigned long *persistent) | ||
| 50 | { | 52 | { |
| 51 | short *srp = (short *)rp; | 53 | short *srp = (short *)rp; |
| 52 | 54 | ||
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h index 19525175b91c..31f579b828f2 100644 --- a/include/asm-x86_64/processor.h +++ b/include/asm-x86_64/processor.h | |||
| @@ -371,7 +371,7 @@ static inline void sync_core(void) | |||
| 371 | #define ARCH_HAS_PREFETCH | 371 | #define ARCH_HAS_PREFETCH |
| 372 | static inline void prefetch(void *x) | 372 | static inline void prefetch(void *x) |
| 373 | { | 373 | { |
| 374 | asm volatile("prefetcht0 %0" :: "m" (*(unsigned long *)x)); | 374 | asm volatile("prefetcht0 (%0)" :: "r" (x)); |
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | #define ARCH_HAS_PREFETCHW 1 | 377 | #define ARCH_HAS_PREFETCHW 1 |
diff --git a/include/linux/sched.h b/include/linux/sched.h index a01ac6dd5f5e..313c6b6e774f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -113,7 +113,7 @@ extern unsigned long avenrun[]; /* Load averages */ | |||
| 113 | 113 | ||
| 114 | #define FSHIFT 11 /* nr of bits of precision */ | 114 | #define FSHIFT 11 /* nr of bits of precision */ |
| 115 | #define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */ | 115 | #define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */ |
| 116 | #define LOAD_FREQ (5*HZ) /* 5 sec intervals */ | 116 | #define LOAD_FREQ (5*HZ+1) /* 5 sec intervals */ |
| 117 | #define EXP_1 1884 /* 1/exp(5sec/1min) as fixed-point */ | 117 | #define EXP_1 1884 /* 1/exp(5sec/1min) as fixed-point */ |
| 118 | #define EXP_5 2014 /* 1/exp(5sec/5min) */ | 118 | #define EXP_5 2014 /* 1/exp(5sec/5min) */ |
| 119 | #define EXP_15 2037 /* 1/exp(5sec/15min) */ | 119 | #define EXP_15 2037 /* 1/exp(5sec/15min) */ |
diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 4ef4d22e5e43..b4af6bcb7b7a 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h | |||
| @@ -127,7 +127,7 @@ int sync_page_range(struct inode *inode, struct address_space *mapping, | |||
| 127 | loff_t pos, loff_t count); | 127 | loff_t pos, loff_t count); |
| 128 | int sync_page_range_nolock(struct inode *inode, struct address_space *mapping, | 128 | int sync_page_range_nolock(struct inode *inode, struct address_space *mapping, |
| 129 | loff_t pos, loff_t count); | 129 | loff_t pos, loff_t count); |
| 130 | void set_page_dirty_balance(struct page *page); | 130 | void set_page_dirty_balance(struct page *page, int page_mkwrite); |
| 131 | void writeback_set_ratelimit(void); | 131 | void writeback_set_ratelimit(void); |
| 132 | 132 | ||
| 133 | /* pdflush.c */ | 133 | /* pdflush.c */ |
diff --git a/include/net/rose.h b/include/net/rose.h index a4047d3cf5dd..e5bb084d8754 100644 --- a/include/net/rose.h +++ b/include/net/rose.h | |||
| @@ -188,7 +188,7 @@ extern void rose_kick(struct sock *); | |||
| 188 | extern void rose_enquiry_response(struct sock *); | 188 | extern void rose_enquiry_response(struct sock *); |
| 189 | 189 | ||
| 190 | /* rose_route.c */ | 190 | /* rose_route.c */ |
| 191 | extern struct rose_neigh rose_loopback_neigh; | 191 | extern struct rose_neigh *rose_loopback_neigh; |
| 192 | extern const struct file_operations rose_neigh_fops; | 192 | extern const struct file_operations rose_neigh_fops; |
| 193 | extern const struct file_operations rose_nodes_fops; | 193 | extern const struct file_operations rose_nodes_fops; |
| 194 | extern const struct file_operations rose_routes_fops; | 194 | extern const struct file_operations rose_routes_fops; |
diff --git a/include/net/tcp.h b/include/net/tcp.h index 185c7ecce4cc..54053de0bdd7 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
| @@ -1059,14 +1059,12 @@ struct tcp_md5sig_key { | |||
| 1059 | }; | 1059 | }; |
| 1060 | 1060 | ||
| 1061 | struct tcp4_md5sig_key { | 1061 | struct tcp4_md5sig_key { |
| 1062 | u8 *key; | 1062 | struct tcp_md5sig_key base; |
| 1063 | u16 keylen; | ||
| 1064 | __be32 addr; | 1063 | __be32 addr; |
| 1065 | }; | 1064 | }; |
| 1066 | 1065 | ||
| 1067 | struct tcp6_md5sig_key { | 1066 | struct tcp6_md5sig_key { |
| 1068 | u8 *key; | 1067 | struct tcp_md5sig_key base; |
| 1069 | u16 keylen; | ||
| 1070 | #if 0 | 1068 | #if 0 |
| 1071 | u32 scope_id; /* XXX */ | 1069 | u32 scope_id; /* XXX */ |
| 1072 | #endif | 1070 | #endif |
diff --git a/kernel/futex.c b/kernel/futex.c index e8935b195e88..fcc94e7b4086 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
| @@ -1943,9 +1943,10 @@ static inline int fetch_robust_entry(struct robust_list __user **entry, | |||
| 1943 | void exit_robust_list(struct task_struct *curr) | 1943 | void exit_robust_list(struct task_struct *curr) |
| 1944 | { | 1944 | { |
| 1945 | struct robust_list_head __user *head = curr->robust_list; | 1945 | struct robust_list_head __user *head = curr->robust_list; |
| 1946 | struct robust_list __user *entry, *pending; | 1946 | struct robust_list __user *entry, *next_entry, *pending; |
| 1947 | unsigned int limit = ROBUST_LIST_LIMIT, pi, pip; | 1947 | unsigned int limit = ROBUST_LIST_LIMIT, pi, next_pi, pip; |
| 1948 | unsigned long futex_offset; | 1948 | unsigned long futex_offset; |
| 1949 | int rc; | ||
| 1949 | 1950 | ||
| 1950 | /* | 1951 | /* |
| 1951 | * Fetch the list head (which was registered earlier, via | 1952 | * Fetch the list head (which was registered earlier, via |
| @@ -1965,12 +1966,14 @@ void exit_robust_list(struct task_struct *curr) | |||
| 1965 | if (fetch_robust_entry(&pending, &head->list_op_pending, &pip)) | 1966 | if (fetch_robust_entry(&pending, &head->list_op_pending, &pip)) |
| 1966 | return; | 1967 | return; |
| 1967 | 1968 | ||
| 1968 | if (pending) | 1969 | next_entry = NULL; /* avoid warning with gcc */ |
| 1969 | handle_futex_death((void __user *)pending + futex_offset, | ||
| 1970 | curr, pip); | ||
| 1971 | |||
| 1972 | while (entry != &head->list) { | 1970 | while (entry != &head->list) { |
| 1973 | /* | 1971 | /* |
| 1972 | * Fetch the next entry in the list before calling | ||
| 1973 | * handle_futex_death: | ||
| 1974 | */ | ||
| 1975 | rc = fetch_robust_entry(&next_entry, &entry->next, &next_pi); | ||
| 1976 | /* | ||
| 1974 | * A pending lock might already be on the list, so | 1977 | * A pending lock might already be on the list, so |
| 1975 | * don't process it twice: | 1978 | * don't process it twice: |
| 1976 | */ | 1979 | */ |
| @@ -1978,11 +1981,10 @@ void exit_robust_list(struct task_struct *curr) | |||
| 1978 | if (handle_futex_death((void __user *)entry + futex_offset, | 1981 | if (handle_futex_death((void __user *)entry + futex_offset, |
| 1979 | curr, pi)) | 1982 | curr, pi)) |
| 1980 | return; | 1983 | return; |
| 1981 | /* | 1984 | if (rc) |
| 1982 | * Fetch the next entry in the list: | ||
| 1983 | */ | ||
| 1984 | if (fetch_robust_entry(&entry, &entry->next, &pi)) | ||
| 1985 | return; | 1985 | return; |
| 1986 | entry = next_entry; | ||
| 1987 | pi = next_pi; | ||
| 1986 | /* | 1988 | /* |
| 1987 | * Avoid excessively long or circular lists: | 1989 | * Avoid excessively long or circular lists: |
| 1988 | */ | 1990 | */ |
| @@ -1991,6 +1993,10 @@ void exit_robust_list(struct task_struct *curr) | |||
| 1991 | 1993 | ||
| 1992 | cond_resched(); | 1994 | cond_resched(); |
| 1993 | } | 1995 | } |
| 1996 | |||
| 1997 | if (pending) | ||
| 1998 | handle_futex_death((void __user *)pending + futex_offset, | ||
| 1999 | curr, pip); | ||
| 1994 | } | 2000 | } |
| 1995 | 2001 | ||
| 1996 | long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, | 2002 | long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, |
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c index 7e52eb051f22..2c2e2954b713 100644 --- a/kernel/futex_compat.c +++ b/kernel/futex_compat.c | |||
| @@ -38,10 +38,11 @@ fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **entry, | |||
| 38 | void compat_exit_robust_list(struct task_struct *curr) | 38 | void compat_exit_robust_list(struct task_struct *curr) |
| 39 | { | 39 | { |
| 40 | struct compat_robust_list_head __user *head = curr->compat_robust_list; | 40 | struct compat_robust_list_head __user *head = curr->compat_robust_list; |
| 41 | struct robust_list __user *entry, *pending; | 41 | struct robust_list __user *entry, *next_entry, *pending; |
| 42 | unsigned int limit = ROBUST_LIST_LIMIT, pi, pip; | 42 | unsigned int limit = ROBUST_LIST_LIMIT, pi, next_pi, pip; |
| 43 | compat_uptr_t uentry, upending; | 43 | compat_uptr_t uentry, next_uentry, upending; |
| 44 | compat_long_t futex_offset; | 44 | compat_long_t futex_offset; |
| 45 | int rc; | ||
| 45 | 46 | ||
| 46 | /* | 47 | /* |
| 47 | * Fetch the list head (which was registered earlier, via | 48 | * Fetch the list head (which was registered earlier, via |
| @@ -61,11 +62,16 @@ void compat_exit_robust_list(struct task_struct *curr) | |||
| 61 | if (fetch_robust_entry(&upending, &pending, | 62 | if (fetch_robust_entry(&upending, &pending, |
| 62 | &head->list_op_pending, &pip)) | 63 | &head->list_op_pending, &pip)) |
| 63 | return; | 64 | return; |
| 64 | if (pending) | ||
| 65 | handle_futex_death((void __user *)pending + futex_offset, curr, pip); | ||
| 66 | 65 | ||
| 66 | next_entry = NULL; /* avoid warning with gcc */ | ||
| 67 | while (entry != (struct robust_list __user *) &head->list) { | 67 | while (entry != (struct robust_list __user *) &head->list) { |
| 68 | /* | 68 | /* |
| 69 | * Fetch the next entry in the list before calling | ||
| 70 | * handle_futex_death: | ||
| 71 | */ | ||
| 72 | rc = fetch_robust_entry(&next_uentry, &next_entry, | ||
| 73 | (compat_uptr_t __user *)&entry->next, &next_pi); | ||
| 74 | /* | ||
| 69 | * A pending lock might already be on the list, so | 75 | * A pending lock might already be on the list, so |
| 70 | * dont process it twice: | 76 | * dont process it twice: |
| 71 | */ | 77 | */ |
| @@ -74,12 +80,11 @@ void compat_exit_robust_list(struct task_struct *curr) | |||
| 74 | curr, pi)) | 80 | curr, pi)) |
| 75 | return; | 81 | return; |
| 76 | 82 | ||
| 77 | /* | 83 | if (rc) |
| 78 | * Fetch the next entry in the list: | ||
| 79 | */ | ||
| 80 | if (fetch_robust_entry(&uentry, &entry, | ||
| 81 | (compat_uptr_t __user *)&entry->next, &pi)) | ||
| 82 | return; | 84 | return; |
| 85 | uentry = next_uentry; | ||
| 86 | entry = next_entry; | ||
| 87 | pi = next_pi; | ||
| 83 | /* | 88 | /* |
| 84 | * Avoid excessively long or circular lists: | 89 | * Avoid excessively long or circular lists: |
| 85 | */ | 90 | */ |
| @@ -88,6 +93,9 @@ void compat_exit_robust_list(struct task_struct *curr) | |||
| 88 | 93 | ||
| 89 | cond_resched(); | 94 | cond_resched(); |
| 90 | } | 95 | } |
| 96 | if (pending) | ||
| 97 | handle_futex_death((void __user *)pending + futex_offset, | ||
| 98 | curr, pip); | ||
| 91 | } | 99 | } |
| 92 | 100 | ||
| 93 | asmlinkage long | 101 | asmlinkage long |
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index c9fbe8e73a45..67c67a87146e 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c | |||
| @@ -639,6 +639,16 @@ static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se) | |||
| 639 | 639 | ||
| 640 | se->block_start = 0; | 640 | se->block_start = 0; |
| 641 | se->sum_sleep_runtime += delta; | 641 | se->sum_sleep_runtime += delta; |
| 642 | |||
| 643 | /* | ||
| 644 | * Blocking time is in units of nanosecs, so shift by 20 to | ||
| 645 | * get a milliseconds-range estimation of the amount of | ||
| 646 | * time that the task spent sleeping: | ||
| 647 | */ | ||
| 648 | if (unlikely(prof_on == SLEEP_PROFILING)) { | ||
| 649 | profile_hits(SLEEP_PROFILING, (void *)get_wchan(tsk), | ||
| 650 | delta >> 20); | ||
| 651 | } | ||
| 642 | } | 652 | } |
| 643 | #endif | 653 | #endif |
| 644 | } | 654 | } |
diff --git a/kernel/signal.c b/kernel/signal.c index 9fb91a32edda..792952381092 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
| @@ -531,18 +531,18 @@ static int check_kill_permission(int sig, struct siginfo *info, | |||
| 531 | if (!valid_signal(sig)) | 531 | if (!valid_signal(sig)) |
| 532 | return error; | 532 | return error; |
| 533 | 533 | ||
| 534 | error = audit_signal_info(sig, t); /* Let audit system see the signal */ | 534 | if (info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) { |
| 535 | if (error) | 535 | error = audit_signal_info(sig, t); /* Let audit system see the signal */ |
| 536 | return error; | 536 | if (error) |
| 537 | 537 | return error; | |
| 538 | error = -EPERM; | 538 | error = -EPERM; |
| 539 | if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) | 539 | if (((sig != SIGCONT) || |
| 540 | && ((sig != SIGCONT) || | 540 | (process_session(current) != process_session(t))) |
| 541 | (process_session(current) != process_session(t))) | 541 | && (current->euid ^ t->suid) && (current->euid ^ t->uid) |
| 542 | && (current->euid ^ t->suid) && (current->euid ^ t->uid) | 542 | && (current->uid ^ t->suid) && (current->uid ^ t->uid) |
| 543 | && (current->uid ^ t->suid) && (current->uid ^ t->uid) | 543 | && !capable(CAP_KILL)) |
| 544 | && !capable(CAP_KILL)) | ||
| 545 | return error; | 544 | return error; |
| 545 | } | ||
| 546 | 546 | ||
| 547 | return security_task_kill(t, info, sig, 0); | 547 | return security_task_kill(t, info, sig, 0); |
| 548 | } | 548 | } |
diff --git a/kernel/sys.c b/kernel/sys.c index 1b33b05d346b..8ae2e636eb1b 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/getcpu.h> | 32 | #include <linux/getcpu.h> |
| 33 | #include <linux/task_io_accounting_ops.h> | 33 | #include <linux/task_io_accounting_ops.h> |
| 34 | #include <linux/seccomp.h> | 34 | #include <linux/seccomp.h> |
| 35 | #include <linux/cpu.h> | ||
| 35 | 36 | ||
| 36 | #include <linux/compat.h> | 37 | #include <linux/compat.h> |
| 37 | #include <linux/syscalls.h> | 38 | #include <linux/syscalls.h> |
| @@ -878,6 +879,7 @@ void kernel_power_off(void) | |||
| 878 | kernel_shutdown_prepare(SYSTEM_POWER_OFF); | 879 | kernel_shutdown_prepare(SYSTEM_POWER_OFF); |
| 879 | if (pm_power_off_prepare) | 880 | if (pm_power_off_prepare) |
| 880 | pm_power_off_prepare(); | 881 | pm_power_off_prepare(); |
| 882 | disable_nonboot_cpus(); | ||
| 881 | sysdev_shutdown(); | 883 | sysdev_shutdown(); |
| 882 | printk(KERN_EMERG "Power down.\n"); | 884 | printk(KERN_EMERG "Power down.\n"); |
| 883 | machine_power_off(); | 885 | machine_power_off(); |
diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c index 3c38fb5eae1b..c36bb7ed0301 100644 --- a/kernel/time/timer_stats.c +++ b/kernel/time/timer_stats.c | |||
| @@ -327,8 +327,9 @@ static int tstats_show(struct seq_file *m, void *v) | |||
| 327 | ms = 1; | 327 | ms = 1; |
| 328 | 328 | ||
| 329 | if (events && period.tv_sec) | 329 | if (events && period.tv_sec) |
| 330 | seq_printf(m, "%ld total events, %ld.%ld events/sec\n", events, | 330 | seq_printf(m, "%ld total events, %ld.%03ld events/sec\n", |
| 331 | events / period.tv_sec, events * 1000 / ms); | 331 | events, events * 1000 / ms, |
| 332 | (events * 1000000 / ms) % 1000); | ||
| 332 | else | 333 | else |
| 333 | seq_printf(m, "%ld total events\n", events); | 334 | seq_printf(m, "%ld total events\n", events); |
| 334 | 335 | ||
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 495863a500cd..cdc9b099e620 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
| @@ -294,6 +294,8 @@ config LOCK_STAT | |||
| 294 | help | 294 | help |
| 295 | This feature enables tracking lock contention points | 295 | This feature enables tracking lock contention points |
| 296 | 296 | ||
| 297 | For more details, see Documentation/lockstat.txt | ||
| 298 | |||
| 297 | config DEBUG_LOCKDEP | 299 | config DEBUG_LOCKDEP |
| 298 | bool "Lock dependency engine debugging" | 300 | bool "Lock dependency engine debugging" |
| 299 | depends on DEBUG_KERNEL && LOCKDEP | 301 | depends on DEBUG_KERNEL && LOCKDEP |
diff --git a/lib/Makefile b/lib/Makefile index 6b0ba8cf4e5f..4f3f3e256501 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | # Makefile for some libs needed in the kernel. | 2 | # Makefile for some libs needed in the kernel. |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | lib-y := ctype.o string.o vsprintf.o kasprintf.o cmdline.o \ | 5 | lib-y := ctype.o string.o vsprintf.o cmdline.o \ |
| 6 | rbtree.o radix-tree.o dump_stack.o \ | 6 | rbtree.o radix-tree.o dump_stack.o \ |
| 7 | idr.o int_sqrt.o bitmap.o extable.o prio_tree.o \ | 7 | idr.o int_sqrt.o bitmap.o extable.o prio_tree.o \ |
| 8 | sha1.o irq_regs.o reciprocal_div.o argv_split.o | 8 | sha1.o irq_regs.o reciprocal_div.o argv_split.o |
| @@ -13,7 +13,7 @@ lib-$(CONFIG_SMP) += cpumask.o | |||
| 13 | lib-y += kobject.o kref.o kobject_uevent.o klist.o | 13 | lib-y += kobject.o kref.o kobject_uevent.o klist.o |
| 14 | 14 | ||
| 15 | obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ | 15 | obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ |
| 16 | bust_spinlocks.o hexdump.o | 16 | bust_spinlocks.o hexdump.o kasprintf.o |
| 17 | 17 | ||
| 18 | ifeq ($(CONFIG_DEBUG_KOBJECT),y) | 18 | ifeq ($(CONFIG_DEBUG_KOBJECT),y) |
| 19 | CFLAGS_kobject.o += -DDEBUG | 19 | CFLAGS_kobject.o += -DDEBUG |
diff --git a/mm/Kconfig b/mm/Kconfig index e24d348083c3..a7609cbcb00d 100644 --- a/mm/Kconfig +++ b/mm/Kconfig | |||
| @@ -137,6 +137,7 @@ config SPLIT_PTLOCK_CPUS | |||
| 137 | int | 137 | int |
| 138 | default "4096" if ARM && !CPU_CACHE_VIPT | 138 | default "4096" if ARM && !CPU_CACHE_VIPT |
| 139 | default "4096" if PARISC && !PA20 | 139 | default "4096" if PARISC && !PA20 |
| 140 | default "4096" if XEN | ||
| 140 | default "4" | 141 | default "4" |
| 141 | 142 | ||
| 142 | # | 143 | # |
diff --git a/mm/filemap.c b/mm/filemap.c index 90b657b50f81..15c8413ee929 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
| @@ -1388,6 +1388,7 @@ retry_find: | |||
| 1388 | size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 1388 | size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
| 1389 | if (unlikely(vmf->pgoff >= size)) { | 1389 | if (unlikely(vmf->pgoff >= size)) { |
| 1390 | unlock_page(page); | 1390 | unlock_page(page); |
| 1391 | page_cache_release(page); | ||
| 1391 | goto outside_data_content; | 1392 | goto outside_data_content; |
| 1392 | } | 1393 | } |
| 1393 | 1394 | ||
diff --git a/mm/fremap.c b/mm/fremap.c index c395b1abf082..95bcb5641c72 100644 --- a/mm/fremap.c +++ b/mm/fremap.c | |||
| @@ -160,7 +160,7 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, | |||
| 160 | if (vma->vm_private_data && !(vma->vm_flags & VM_NONLINEAR)) | 160 | if (vma->vm_private_data && !(vma->vm_flags & VM_NONLINEAR)) |
| 161 | goto out; | 161 | goto out; |
| 162 | 162 | ||
| 163 | if (!vma->vm_flags & VM_CAN_NONLINEAR) | 163 | if (!(vma->vm_flags & VM_CAN_NONLINEAR)) |
| 164 | goto out; | 164 | goto out; |
| 165 | 165 | ||
| 166 | if (end <= start || start < vma->vm_start || end > vma->vm_end) | 166 | if (end <= start || start < vma->vm_start || end > vma->vm_end) |
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 84c795ee2d65..eab8c428cc93 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
| @@ -42,7 +42,7 @@ static void clear_huge_page(struct page *page, unsigned long addr) | |||
| 42 | might_sleep(); | 42 | might_sleep(); |
| 43 | for (i = 0; i < (HPAGE_SIZE/PAGE_SIZE); i++) { | 43 | for (i = 0; i < (HPAGE_SIZE/PAGE_SIZE); i++) { |
| 44 | cond_resched(); | 44 | cond_resched(); |
| 45 | clear_user_highpage(page + i, addr); | 45 | clear_user_highpage(page + i, addr + i * PAGE_SIZE); |
| 46 | } | 46 | } |
| 47 | } | 47 | } |
| 48 | 48 | ||
diff --git a/mm/memory.c b/mm/memory.c index ca8cac11bd2c..f82b359b2745 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
| @@ -1639,6 +1639,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 1639 | struct page *old_page, *new_page; | 1639 | struct page *old_page, *new_page; |
| 1640 | pte_t entry; | 1640 | pte_t entry; |
| 1641 | int reuse = 0, ret = 0; | 1641 | int reuse = 0, ret = 0; |
| 1642 | int page_mkwrite = 0; | ||
| 1642 | struct page *dirty_page = NULL; | 1643 | struct page *dirty_page = NULL; |
| 1643 | 1644 | ||
| 1644 | old_page = vm_normal_page(vma, address, orig_pte); | 1645 | old_page = vm_normal_page(vma, address, orig_pte); |
| @@ -1687,6 +1688,8 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 1687 | page_cache_release(old_page); | 1688 | page_cache_release(old_page); |
| 1688 | if (!pte_same(*page_table, orig_pte)) | 1689 | if (!pte_same(*page_table, orig_pte)) |
| 1689 | goto unlock; | 1690 | goto unlock; |
| 1691 | |||
| 1692 | page_mkwrite = 1; | ||
| 1690 | } | 1693 | } |
| 1691 | dirty_page = old_page; | 1694 | dirty_page = old_page; |
| 1692 | get_page(dirty_page); | 1695 | get_page(dirty_page); |
| @@ -1774,7 +1777,7 @@ unlock: | |||
| 1774 | * do_no_page is protected similarly. | 1777 | * do_no_page is protected similarly. |
| 1775 | */ | 1778 | */ |
| 1776 | wait_on_page_locked(dirty_page); | 1779 | wait_on_page_locked(dirty_page); |
| 1777 | set_page_dirty_balance(dirty_page); | 1780 | set_page_dirty_balance(dirty_page, page_mkwrite); |
| 1778 | put_page(dirty_page); | 1781 | put_page(dirty_page); |
| 1779 | } | 1782 | } |
| 1780 | return ret; | 1783 | return ret; |
| @@ -2307,13 +2310,14 @@ oom: | |||
| 2307 | * do not need to flush old virtual caches or the TLB. | 2310 | * do not need to flush old virtual caches or the TLB. |
| 2308 | * | 2311 | * |
| 2309 | * We enter with non-exclusive mmap_sem (to exclude vma changes, | 2312 | * We enter with non-exclusive mmap_sem (to exclude vma changes, |
| 2310 | * but allow concurrent faults), and pte mapped but not yet locked. | 2313 | * but allow concurrent faults), and pte neither mapped nor locked. |
| 2311 | * We return with mmap_sem still held, but pte unmapped and unlocked. | 2314 | * We return with mmap_sem still held, but pte unmapped and unlocked. |
| 2312 | */ | 2315 | */ |
| 2313 | static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | 2316 | static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, |
| 2314 | unsigned long address, pte_t *page_table, pmd_t *pmd, | 2317 | unsigned long address, pmd_t *pmd, |
| 2315 | pgoff_t pgoff, unsigned int flags, pte_t orig_pte) | 2318 | pgoff_t pgoff, unsigned int flags, pte_t orig_pte) |
| 2316 | { | 2319 | { |
| 2320 | pte_t *page_table; | ||
| 2317 | spinlock_t *ptl; | 2321 | spinlock_t *ptl; |
| 2318 | struct page *page; | 2322 | struct page *page; |
| 2319 | pte_t entry; | 2323 | pte_t entry; |
| @@ -2321,13 +2325,13 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2321 | struct page *dirty_page = NULL; | 2325 | struct page *dirty_page = NULL; |
| 2322 | struct vm_fault vmf; | 2326 | struct vm_fault vmf; |
| 2323 | int ret; | 2327 | int ret; |
| 2328 | int page_mkwrite = 0; | ||
| 2324 | 2329 | ||
| 2325 | vmf.virtual_address = (void __user *)(address & PAGE_MASK); | 2330 | vmf.virtual_address = (void __user *)(address & PAGE_MASK); |
| 2326 | vmf.pgoff = pgoff; | 2331 | vmf.pgoff = pgoff; |
| 2327 | vmf.flags = flags; | 2332 | vmf.flags = flags; |
| 2328 | vmf.page = NULL; | 2333 | vmf.page = NULL; |
| 2329 | 2334 | ||
| 2330 | pte_unmap(page_table); | ||
| 2331 | BUG_ON(vma->vm_flags & VM_PFNMAP); | 2335 | BUG_ON(vma->vm_flags & VM_PFNMAP); |
| 2332 | 2336 | ||
| 2333 | if (likely(vma->vm_ops->fault)) { | 2337 | if (likely(vma->vm_ops->fault)) { |
| @@ -2398,6 +2402,7 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2398 | anon = 1; /* no anon but release vmf.page */ | 2402 | anon = 1; /* no anon but release vmf.page */ |
| 2399 | goto out; | 2403 | goto out; |
| 2400 | } | 2404 | } |
| 2405 | page_mkwrite = 1; | ||
| 2401 | } | 2406 | } |
| 2402 | } | 2407 | } |
| 2403 | 2408 | ||
| @@ -2453,7 +2458,7 @@ out_unlocked: | |||
| 2453 | if (anon) | 2458 | if (anon) |
| 2454 | page_cache_release(vmf.page); | 2459 | page_cache_release(vmf.page); |
| 2455 | else if (dirty_page) { | 2460 | else if (dirty_page) { |
| 2456 | set_page_dirty_balance(dirty_page); | 2461 | set_page_dirty_balance(dirty_page, page_mkwrite); |
| 2457 | put_page(dirty_page); | 2462 | put_page(dirty_page); |
| 2458 | } | 2463 | } |
| 2459 | 2464 | ||
| @@ -2468,8 +2473,8 @@ static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2468 | - vma->vm_start) >> PAGE_CACHE_SHIFT) + vma->vm_pgoff; | 2473 | - vma->vm_start) >> PAGE_CACHE_SHIFT) + vma->vm_pgoff; |
| 2469 | unsigned int flags = (write_access ? FAULT_FLAG_WRITE : 0); | 2474 | unsigned int flags = (write_access ? FAULT_FLAG_WRITE : 0); |
| 2470 | 2475 | ||
| 2471 | return __do_fault(mm, vma, address, page_table, pmd, pgoff, | 2476 | pte_unmap(page_table); |
| 2472 | flags, orig_pte); | 2477 | return __do_fault(mm, vma, address, pmd, pgoff, flags, orig_pte); |
| 2473 | } | 2478 | } |
| 2474 | 2479 | ||
| 2475 | 2480 | ||
| @@ -2552,9 +2557,7 @@ static int do_nonlinear_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2552 | } | 2557 | } |
| 2553 | 2558 | ||
| 2554 | pgoff = pte_to_pgoff(orig_pte); | 2559 | pgoff = pte_to_pgoff(orig_pte); |
| 2555 | 2560 | return __do_fault(mm, vma, address, pmd, pgoff, flags, orig_pte); | |
| 2556 | return __do_fault(mm, vma, address, page_table, pmd, pgoff, | ||
| 2557 | flags, orig_pte); | ||
| 2558 | } | 2561 | } |
| 2559 | 2562 | ||
| 2560 | /* | 2563 | /* |
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 63512a9ed57e..44720363374c 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
| @@ -274,9 +274,9 @@ static void balance_dirty_pages(struct address_space *mapping) | |||
| 274 | pdflush_operation(background_writeout, 0); | 274 | pdflush_operation(background_writeout, 0); |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | void set_page_dirty_balance(struct page *page) | 277 | void set_page_dirty_balance(struct page *page, int page_mkwrite) |
| 278 | { | 278 | { |
| 279 | if (set_page_dirty(page)) { | 279 | if (set_page_dirty(page) || page_mkwrite) { |
| 280 | struct address_space *mapping = page_mapping(page); | 280 | struct address_space *mapping = page_mapping(page); |
| 281 | 281 | ||
| 282 | if (mapping) | 282 | if (mapping) |
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index f2de2e48b021..6284c99b456e 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c | |||
| @@ -366,6 +366,12 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, | |||
| 366 | frag = WLAN_GET_SEQ_FRAG(sc); | 366 | frag = WLAN_GET_SEQ_FRAG(sc); |
| 367 | hdrlen = ieee80211_get_hdrlen(fc); | 367 | hdrlen = ieee80211_get_hdrlen(fc); |
| 368 | 368 | ||
| 369 | if (skb->len < hdrlen) { | ||
| 370 | printk(KERN_INFO "%s: invalid SKB length %d\n", | ||
| 371 | dev->name, skb->len); | ||
| 372 | goto rx_dropped; | ||
| 373 | } | ||
| 374 | |||
| 369 | /* Put this code here so that we avoid duplicating it in all | 375 | /* Put this code here so that we avoid duplicating it in all |
| 370 | * Rx paths. - Jean II */ | 376 | * Rx paths. - Jean II */ |
| 371 | #ifdef CONFIG_WIRELESS_EXT | 377 | #ifdef CONFIG_WIRELESS_EXT |
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c index 442b9875f3fb..5742dc803b79 100644 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c | |||
| @@ -114,7 +114,7 @@ check_assoc_again: | |||
| 114 | sm->associnfo.associating = 1; | 114 | sm->associnfo.associating = 1; |
| 115 | /* queue lower level code to do work (if necessary) */ | 115 | /* queue lower level code to do work (if necessary) */ |
| 116 | schedule_delayed_work(&sm->associnfo.work, 0); | 116 | schedule_delayed_work(&sm->associnfo.work, 0); |
| 117 | out: | 117 | |
| 118 | mutex_unlock(&sm->associnfo.mutex); | 118 | mutex_unlock(&sm->associnfo.mutex); |
| 119 | 119 | ||
| 120 | return 0; | 120 | return 0; |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index bbad2cdb74b7..f893e90061eb 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -2420,6 +2420,9 @@ static int tcp_tso_acked(struct sock *sk, struct sk_buff *skb, | |||
| 2420 | __u32 dval = min(tp->fackets_out, packets_acked); | 2420 | __u32 dval = min(tp->fackets_out, packets_acked); |
| 2421 | tp->fackets_out -= dval; | 2421 | tp->fackets_out -= dval; |
| 2422 | } | 2422 | } |
| 2423 | /* hint's skb might be NULL but we don't need to care */ | ||
| 2424 | tp->fastpath_cnt_hint -= min_t(u32, packets_acked, | ||
| 2425 | tp->fastpath_cnt_hint); | ||
| 2423 | tp->packets_out -= packets_acked; | 2426 | tp->packets_out -= packets_acked; |
| 2424 | 2427 | ||
| 2425 | BUG_ON(tcp_skb_pcount(skb) == 0); | 2428 | BUG_ON(tcp_skb_pcount(skb) == 0); |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 9c94627c8c7e..e089a978e128 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
| @@ -833,8 +833,7 @@ static struct tcp_md5sig_key * | |||
| 833 | return NULL; | 833 | return NULL; |
| 834 | for (i = 0; i < tp->md5sig_info->entries4; i++) { | 834 | for (i = 0; i < tp->md5sig_info->entries4; i++) { |
| 835 | if (tp->md5sig_info->keys4[i].addr == addr) | 835 | if (tp->md5sig_info->keys4[i].addr == addr) |
| 836 | return (struct tcp_md5sig_key *) | 836 | return &tp->md5sig_info->keys4[i].base; |
| 837 | &tp->md5sig_info->keys4[i]; | ||
| 838 | } | 837 | } |
| 839 | return NULL; | 838 | return NULL; |
| 840 | } | 839 | } |
| @@ -865,9 +864,9 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, | |||
| 865 | key = (struct tcp4_md5sig_key *)tcp_v4_md5_do_lookup(sk, addr); | 864 | key = (struct tcp4_md5sig_key *)tcp_v4_md5_do_lookup(sk, addr); |
| 866 | if (key) { | 865 | if (key) { |
| 867 | /* Pre-existing entry - just update that one. */ | 866 | /* Pre-existing entry - just update that one. */ |
| 868 | kfree(key->key); | 867 | kfree(key->base.key); |
| 869 | key->key = newkey; | 868 | key->base.key = newkey; |
| 870 | key->keylen = newkeylen; | 869 | key->base.keylen = newkeylen; |
| 871 | } else { | 870 | } else { |
| 872 | struct tcp_md5sig_info *md5sig; | 871 | struct tcp_md5sig_info *md5sig; |
| 873 | 872 | ||
| @@ -906,9 +905,9 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, | |||
| 906 | md5sig->alloced4++; | 905 | md5sig->alloced4++; |
| 907 | } | 906 | } |
| 908 | md5sig->entries4++; | 907 | md5sig->entries4++; |
| 909 | md5sig->keys4[md5sig->entries4 - 1].addr = addr; | 908 | md5sig->keys4[md5sig->entries4 - 1].addr = addr; |
| 910 | md5sig->keys4[md5sig->entries4 - 1].key = newkey; | 909 | md5sig->keys4[md5sig->entries4 - 1].base.key = newkey; |
| 911 | md5sig->keys4[md5sig->entries4 - 1].keylen = newkeylen; | 910 | md5sig->keys4[md5sig->entries4 - 1].base.keylen = newkeylen; |
| 912 | } | 911 | } |
| 913 | return 0; | 912 | return 0; |
| 914 | } | 913 | } |
| @@ -930,7 +929,7 @@ int tcp_v4_md5_do_del(struct sock *sk, __be32 addr) | |||
| 930 | for (i = 0; i < tp->md5sig_info->entries4; i++) { | 929 | for (i = 0; i < tp->md5sig_info->entries4; i++) { |
| 931 | if (tp->md5sig_info->keys4[i].addr == addr) { | 930 | if (tp->md5sig_info->keys4[i].addr == addr) { |
| 932 | /* Free the key */ | 931 | /* Free the key */ |
| 933 | kfree(tp->md5sig_info->keys4[i].key); | 932 | kfree(tp->md5sig_info->keys4[i].base.key); |
| 934 | tp->md5sig_info->entries4--; | 933 | tp->md5sig_info->entries4--; |
| 935 | 934 | ||
| 936 | if (tp->md5sig_info->entries4 == 0) { | 935 | if (tp->md5sig_info->entries4 == 0) { |
| @@ -964,7 +963,7 @@ static void tcp_v4_clear_md5_list(struct sock *sk) | |||
| 964 | if (tp->md5sig_info->entries4) { | 963 | if (tp->md5sig_info->entries4) { |
| 965 | int i; | 964 | int i; |
| 966 | for (i = 0; i < tp->md5sig_info->entries4; i++) | 965 | for (i = 0; i < tp->md5sig_info->entries4; i++) |
| 967 | kfree(tp->md5sig_info->keys4[i].key); | 966 | kfree(tp->md5sig_info->keys4[i].base.key); |
| 968 | tp->md5sig_info->entries4 = 0; | 967 | tp->md5sig_info->entries4 = 0; |
| 969 | tcp_free_md5sig_pool(); | 968 | tcp_free_md5sig_pool(); |
| 970 | } | 969 | } |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 73a894a2152c..5b596659177c 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
| @@ -1268,9 +1268,10 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
| 1268 | 1268 | ||
| 1269 | if (ipv6_addr_equal(dest, target)) { | 1269 | if (ipv6_addr_equal(dest, target)) { |
| 1270 | on_link = 1; | 1270 | on_link = 1; |
| 1271 | } else if (!(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) { | 1271 | } else if (ipv6_addr_type(target) != |
| 1272 | (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) { | ||
| 1272 | ND_PRINTK2(KERN_WARNING | 1273 | ND_PRINTK2(KERN_WARNING |
| 1273 | "ICMPv6 Redirect: target address is not link-local.\n"); | 1274 | "ICMPv6 Redirect: target address is not link-local unicast.\n"); |
| 1274 | return; | 1275 | return; |
| 1275 | } | 1276 | } |
| 1276 | 1277 | ||
| @@ -1344,9 +1345,9 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
| 1344 | } | 1345 | } |
| 1345 | 1346 | ||
| 1346 | if (!ipv6_addr_equal(&ipv6_hdr(skb)->daddr, target) && | 1347 | if (!ipv6_addr_equal(&ipv6_hdr(skb)->daddr, target) && |
| 1347 | !(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) { | 1348 | ipv6_addr_type(target) != (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) { |
| 1348 | ND_PRINTK2(KERN_WARNING | 1349 | ND_PRINTK2(KERN_WARNING |
| 1349 | "ICMPv6 Redirect: target address is not link-local.\n"); | 1350 | "ICMPv6 Redirect: target address is not link-local unicast.\n"); |
| 1350 | return; | 1351 | return; |
| 1351 | } | 1352 | } |
| 1352 | 1353 | ||
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 0f7defb482e9..3e06799b37a6 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -539,7 +539,7 @@ static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, | |||
| 539 | 539 | ||
| 540 | for (i = 0; i < tp->md5sig_info->entries6; i++) { | 540 | for (i = 0; i < tp->md5sig_info->entries6; i++) { |
| 541 | if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0) | 541 | if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0) |
| 542 | return (struct tcp_md5sig_key *)&tp->md5sig_info->keys6[i]; | 542 | return &tp->md5sig_info->keys6[i].base; |
| 543 | } | 543 | } |
| 544 | return NULL; | 544 | return NULL; |
| 545 | } | 545 | } |
| @@ -567,9 +567,9 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, | |||
| 567 | key = (struct tcp6_md5sig_key*) tcp_v6_md5_do_lookup(sk, peer); | 567 | key = (struct tcp6_md5sig_key*) tcp_v6_md5_do_lookup(sk, peer); |
| 568 | if (key) { | 568 | if (key) { |
| 569 | /* modify existing entry - just update that one */ | 569 | /* modify existing entry - just update that one */ |
| 570 | kfree(key->key); | 570 | kfree(key->base.key); |
| 571 | key->key = newkey; | 571 | key->base.key = newkey; |
| 572 | key->keylen = newkeylen; | 572 | key->base.keylen = newkeylen; |
| 573 | } else { | 573 | } else { |
| 574 | /* reallocate new list if current one is full. */ | 574 | /* reallocate new list if current one is full. */ |
| 575 | if (!tp->md5sig_info) { | 575 | if (!tp->md5sig_info) { |
| @@ -603,8 +603,8 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, | |||
| 603 | 603 | ||
| 604 | ipv6_addr_copy(&tp->md5sig_info->keys6[tp->md5sig_info->entries6].addr, | 604 | ipv6_addr_copy(&tp->md5sig_info->keys6[tp->md5sig_info->entries6].addr, |
| 605 | peer); | 605 | peer); |
| 606 | tp->md5sig_info->keys6[tp->md5sig_info->entries6].key = newkey; | 606 | tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.key = newkey; |
| 607 | tp->md5sig_info->keys6[tp->md5sig_info->entries6].keylen = newkeylen; | 607 | tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.keylen = newkeylen; |
| 608 | 608 | ||
| 609 | tp->md5sig_info->entries6++; | 609 | tp->md5sig_info->entries6++; |
| 610 | } | 610 | } |
| @@ -626,7 +626,7 @@ static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer) | |||
| 626 | for (i = 0; i < tp->md5sig_info->entries6; i++) { | 626 | for (i = 0; i < tp->md5sig_info->entries6; i++) { |
| 627 | if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) { | 627 | if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) { |
| 628 | /* Free the key */ | 628 | /* Free the key */ |
| 629 | kfree(tp->md5sig_info->keys6[i].key); | 629 | kfree(tp->md5sig_info->keys6[i].base.key); |
| 630 | tp->md5sig_info->entries6--; | 630 | tp->md5sig_info->entries6--; |
| 631 | 631 | ||
| 632 | if (tp->md5sig_info->entries6 == 0) { | 632 | if (tp->md5sig_info->entries6 == 0) { |
| @@ -657,7 +657,7 @@ static void tcp_v6_clear_md5_list (struct sock *sk) | |||
| 657 | 657 | ||
| 658 | if (tp->md5sig_info->entries6) { | 658 | if (tp->md5sig_info->entries6) { |
| 659 | for (i = 0; i < tp->md5sig_info->entries6; i++) | 659 | for (i = 0; i < tp->md5sig_info->entries6; i++) |
| 660 | kfree(tp->md5sig_info->keys6[i].key); | 660 | kfree(tp->md5sig_info->keys6[i].base.key); |
| 661 | tp->md5sig_info->entries6 = 0; | 661 | tp->md5sig_info->entries6 = 0; |
| 662 | tcp_free_md5sig_pool(); | 662 | tcp_free_md5sig_pool(); |
| 663 | } | 663 | } |
| @@ -668,7 +668,7 @@ static void tcp_v6_clear_md5_list (struct sock *sk) | |||
| 668 | 668 | ||
| 669 | if (tp->md5sig_info->entries4) { | 669 | if (tp->md5sig_info->entries4) { |
| 670 | for (i = 0; i < tp->md5sig_info->entries4; i++) | 670 | for (i = 0; i < tp->md5sig_info->entries4; i++) |
| 671 | kfree(tp->md5sig_info->keys4[i].key); | 671 | kfree(tp->md5sig_info->keys4[i].base.key); |
| 672 | tp->md5sig_info->entries4 = 0; | 672 | tp->md5sig_info->entries4 = 0; |
| 673 | tcp_free_md5sig_pool(); | 673 | tcp_free_md5sig_pool(); |
| 674 | } | 674 | } |
diff --git a/net/rose/rose_loopback.c b/net/rose/rose_loopback.c index cd01642f0491..114df6eec8c3 100644 --- a/net/rose/rose_loopback.c +++ b/net/rose/rose_loopback.c | |||
| @@ -79,7 +79,7 @@ static void rose_loopback_timer(unsigned long param) | |||
| 79 | 79 | ||
| 80 | skb_reset_transport_header(skb); | 80 | skb_reset_transport_header(skb); |
| 81 | 81 | ||
| 82 | sk = rose_find_socket(lci_o, &rose_loopback_neigh); | 82 | sk = rose_find_socket(lci_o, rose_loopback_neigh); |
| 83 | if (sk) { | 83 | if (sk) { |
| 84 | if (rose_process_rx_frame(sk, skb) == 0) | 84 | if (rose_process_rx_frame(sk, skb) == 0) |
| 85 | kfree_skb(skb); | 85 | kfree_skb(skb); |
| @@ -88,7 +88,7 @@ static void rose_loopback_timer(unsigned long param) | |||
| 88 | 88 | ||
| 89 | if (frametype == ROSE_CALL_REQUEST) { | 89 | if (frametype == ROSE_CALL_REQUEST) { |
| 90 | if ((dev = rose_dev_get(dest)) != NULL) { | 90 | if ((dev = rose_dev_get(dest)) != NULL) { |
| 91 | if (rose_rx_call_request(skb, dev, &rose_loopback_neigh, lci_o) == 0) | 91 | if (rose_rx_call_request(skb, dev, rose_loopback_neigh, lci_o) == 0) |
| 92 | kfree_skb(skb); | 92 | kfree_skb(skb); |
| 93 | } else { | 93 | } else { |
| 94 | kfree_skb(skb); | 94 | kfree_skb(skb); |
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index bbcbad1da0d0..96f61a71b252 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c | |||
| @@ -45,7 +45,7 @@ static DEFINE_SPINLOCK(rose_neigh_list_lock); | |||
| 45 | static struct rose_route *rose_route_list; | 45 | static struct rose_route *rose_route_list; |
| 46 | static DEFINE_SPINLOCK(rose_route_list_lock); | 46 | static DEFINE_SPINLOCK(rose_route_list_lock); |
| 47 | 47 | ||
| 48 | struct rose_neigh rose_loopback_neigh; | 48 | struct rose_neigh *rose_loopback_neigh; |
| 49 | 49 | ||
| 50 | /* | 50 | /* |
| 51 | * Add a new route to a node, and in the process add the node and the | 51 | * Add a new route to a node, and in the process add the node and the |
| @@ -362,7 +362,12 @@ out: | |||
| 362 | */ | 362 | */ |
| 363 | void rose_add_loopback_neigh(void) | 363 | void rose_add_loopback_neigh(void) |
| 364 | { | 364 | { |
| 365 | struct rose_neigh *sn = &rose_loopback_neigh; | 365 | struct rose_neigh *sn; |
| 366 | |||
| 367 | rose_loopback_neigh = kmalloc(sizeof(struct rose_neigh), GFP_KERNEL); | ||
| 368 | if (!rose_loopback_neigh) | ||
| 369 | return; | ||
| 370 | sn = rose_loopback_neigh; | ||
| 366 | 371 | ||
| 367 | sn->callsign = null_ax25_address; | 372 | sn->callsign = null_ax25_address; |
| 368 | sn->digipeat = NULL; | 373 | sn->digipeat = NULL; |
| @@ -417,13 +422,13 @@ int rose_add_loopback_node(rose_address *address) | |||
| 417 | rose_node->mask = 10; | 422 | rose_node->mask = 10; |
| 418 | rose_node->count = 1; | 423 | rose_node->count = 1; |
| 419 | rose_node->loopback = 1; | 424 | rose_node->loopback = 1; |
| 420 | rose_node->neighbour[0] = &rose_loopback_neigh; | 425 | rose_node->neighbour[0] = rose_loopback_neigh; |
| 421 | 426 | ||
| 422 | /* Insert at the head of list. Address is always mask=10 */ | 427 | /* Insert at the head of list. Address is always mask=10 */ |
| 423 | rose_node->next = rose_node_list; | 428 | rose_node->next = rose_node_list; |
| 424 | rose_node_list = rose_node; | 429 | rose_node_list = rose_node; |
| 425 | 430 | ||
| 426 | rose_loopback_neigh.count++; | 431 | rose_loopback_neigh->count++; |
| 427 | 432 | ||
| 428 | out: | 433 | out: |
| 429 | spin_unlock_bh(&rose_node_list_lock); | 434 | spin_unlock_bh(&rose_node_list_lock); |
| @@ -454,7 +459,7 @@ void rose_del_loopback_node(rose_address *address) | |||
| 454 | 459 | ||
| 455 | rose_remove_node(rose_node); | 460 | rose_remove_node(rose_node); |
| 456 | 461 | ||
| 457 | rose_loopback_neigh.count--; | 462 | rose_loopback_neigh->count--; |
| 458 | 463 | ||
| 459 | out: | 464 | out: |
| 460 | spin_unlock_bh(&rose_node_list_lock); | 465 | spin_unlock_bh(&rose_node_list_lock); |
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 8dbe36912ecb..d4d5d2f271d2 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c | |||
| @@ -502,7 +502,7 @@ static int u32_set_parms(struct tcf_proto *tp, unsigned long base, | |||
| 502 | 502 | ||
| 503 | #ifdef CONFIG_NET_CLS_IND | 503 | #ifdef CONFIG_NET_CLS_IND |
| 504 | if (tb[TCA_U32_INDEV-1]) { | 504 | if (tb[TCA_U32_INDEV-1]) { |
| 505 | int err = tcf_change_indev(tp, n->indev, tb[TCA_U32_INDEV-1]); | 505 | err = tcf_change_indev(tp, n->indev, tb[TCA_U32_INDEV-1]); |
| 506 | if (err < 0) | 506 | if (err < 0) |
| 507 | goto errout; | 507 | goto errout; |
| 508 | } | 508 | } |
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 3a23e30bc79e..b542c875e154 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
| 20 | #include <linux/ipv6.h> | 20 | #include <linux/ipv6.h> |
| 21 | #include <linux/skbuff.h> | 21 | #include <linux/skbuff.h> |
| 22 | #include <linux/jhash.h> | ||
| 22 | #include <net/ip.h> | 23 | #include <net/ip.h> |
| 23 | #include <net/netlink.h> | 24 | #include <net/netlink.h> |
| 24 | #include <net/pkt_sched.h> | 25 | #include <net/pkt_sched.h> |
| @@ -95,7 +96,7 @@ struct sfq_sched_data | |||
| 95 | 96 | ||
| 96 | /* Variables */ | 97 | /* Variables */ |
| 97 | struct timer_list perturb_timer; | 98 | struct timer_list perturb_timer; |
| 98 | int perturbation; | 99 | u32 perturbation; |
| 99 | sfq_index tail; /* Index of current slot in round */ | 100 | sfq_index tail; /* Index of current slot in round */ |
| 100 | sfq_index max_depth; /* Maximal depth */ | 101 | sfq_index max_depth; /* Maximal depth */ |
| 101 | 102 | ||
| @@ -109,12 +110,7 @@ struct sfq_sched_data | |||
| 109 | 110 | ||
| 110 | static __inline__ unsigned sfq_fold_hash(struct sfq_sched_data *q, u32 h, u32 h1) | 111 | static __inline__ unsigned sfq_fold_hash(struct sfq_sched_data *q, u32 h, u32 h1) |
| 111 | { | 112 | { |
| 112 | int pert = q->perturbation; | 113 | return jhash_2words(h, h1, q->perturbation) & (SFQ_HASH_DIVISOR - 1); |
| 113 | |||
| 114 | /* Have we any rotation primitives? If not, WHY? */ | ||
| 115 | h ^= (h1<<pert) ^ (h1>>(0x1F - pert)); | ||
| 116 | h ^= h>>10; | ||
| 117 | return h & 0x3FF; | ||
| 118 | } | 114 | } |
| 119 | 115 | ||
| 120 | static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) | 116 | static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) |
| @@ -256,6 +252,13 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc* sch) | |||
| 256 | q->ht[hash] = x = q->dep[SFQ_DEPTH].next; | 252 | q->ht[hash] = x = q->dep[SFQ_DEPTH].next; |
| 257 | q->hash[x] = hash; | 253 | q->hash[x] = hash; |
| 258 | } | 254 | } |
| 255 | /* If selected queue has length q->limit, this means that | ||
| 256 | * all another queues are empty and that we do simple tail drop, | ||
| 257 | * i.e. drop _this_ packet. | ||
| 258 | */ | ||
| 259 | if (q->qs[x].qlen >= q->limit) | ||
| 260 | return qdisc_drop(skb, sch); | ||
| 261 | |||
| 259 | sch->qstats.backlog += skb->len; | 262 | sch->qstats.backlog += skb->len; |
| 260 | __skb_queue_tail(&q->qs[x], skb); | 263 | __skb_queue_tail(&q->qs[x], skb); |
| 261 | sfq_inc(q, x); | 264 | sfq_inc(q, x); |
| @@ -294,6 +297,19 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc* sch) | |||
| 294 | } | 297 | } |
| 295 | sch->qstats.backlog += skb->len; | 298 | sch->qstats.backlog += skb->len; |
| 296 | __skb_queue_head(&q->qs[x], skb); | 299 | __skb_queue_head(&q->qs[x], skb); |
| 300 | /* If selected queue has length q->limit+1, this means that | ||
| 301 | * all another queues are empty and we do simple tail drop. | ||
| 302 | * This packet is still requeued at head of queue, tail packet | ||
| 303 | * is dropped. | ||
| 304 | */ | ||
| 305 | if (q->qs[x].qlen > q->limit) { | ||
| 306 | skb = q->qs[x].prev; | ||
| 307 | __skb_unlink(skb, &q->qs[x]); | ||
| 308 | sch->qstats.drops++; | ||
| 309 | sch->qstats.backlog -= skb->len; | ||
| 310 | kfree_skb(skb); | ||
| 311 | return NET_XMIT_CN; | ||
| 312 | } | ||
| 297 | sfq_inc(q, x); | 313 | sfq_inc(q, x); |
| 298 | if (q->qs[x].qlen == 1) { /* The flow is new */ | 314 | if (q->qs[x].qlen == 1) { /* The flow is new */ |
| 299 | if (q->tail == SFQ_DEPTH) { /* It is the first flow */ | 315 | if (q->tail == SFQ_DEPTH) { /* It is the first flow */ |
| @@ -370,12 +386,10 @@ static void sfq_perturbation(unsigned long arg) | |||
| 370 | struct Qdisc *sch = (struct Qdisc*)arg; | 386 | struct Qdisc *sch = (struct Qdisc*)arg; |
| 371 | struct sfq_sched_data *q = qdisc_priv(sch); | 387 | struct sfq_sched_data *q = qdisc_priv(sch); |
| 372 | 388 | ||
| 373 | q->perturbation = net_random()&0x1F; | 389 | get_random_bytes(&q->perturbation, 4); |
| 374 | 390 | ||
| 375 | if (q->perturb_period) { | 391 | if (q->perturb_period) |
| 376 | q->perturb_timer.expires = jiffies + q->perturb_period; | 392 | mod_timer(&q->perturb_timer, jiffies + q->perturb_period); |
| 377 | add_timer(&q->perturb_timer); | ||
| 378 | } | ||
| 379 | } | 393 | } |
| 380 | 394 | ||
| 381 | static int sfq_change(struct Qdisc *sch, struct rtattr *opt) | 395 | static int sfq_change(struct Qdisc *sch, struct rtattr *opt) |
| @@ -391,7 +405,7 @@ static int sfq_change(struct Qdisc *sch, struct rtattr *opt) | |||
| 391 | q->quantum = ctl->quantum ? : psched_mtu(sch->dev); | 405 | q->quantum = ctl->quantum ? : psched_mtu(sch->dev); |
| 392 | q->perturb_period = ctl->perturb_period*HZ; | 406 | q->perturb_period = ctl->perturb_period*HZ; |
| 393 | if (ctl->limit) | 407 | if (ctl->limit) |
| 394 | q->limit = min_t(u32, ctl->limit, SFQ_DEPTH - 2); | 408 | q->limit = min_t(u32, ctl->limit, SFQ_DEPTH - 1); |
| 395 | 409 | ||
| 396 | qlen = sch->q.qlen; | 410 | qlen = sch->q.qlen; |
| 397 | while (sch->q.qlen > q->limit) | 411 | while (sch->q.qlen > q->limit) |
| @@ -400,8 +414,8 @@ static int sfq_change(struct Qdisc *sch, struct rtattr *opt) | |||
| 400 | 414 | ||
| 401 | del_timer(&q->perturb_timer); | 415 | del_timer(&q->perturb_timer); |
| 402 | if (q->perturb_period) { | 416 | if (q->perturb_period) { |
| 403 | q->perturb_timer.expires = jiffies + q->perturb_period; | 417 | mod_timer(&q->perturb_timer, jiffies + q->perturb_period); |
| 404 | add_timer(&q->perturb_timer); | 418 | get_random_bytes(&q->perturbation, 4); |
| 405 | } | 419 | } |
| 406 | sch_tree_unlock(sch); | 420 | sch_tree_unlock(sch); |
| 407 | return 0; | 421 | return 0; |
| @@ -423,12 +437,13 @@ static int sfq_init(struct Qdisc *sch, struct rtattr *opt) | |||
| 423 | q->dep[i+SFQ_DEPTH].next = i+SFQ_DEPTH; | 437 | q->dep[i+SFQ_DEPTH].next = i+SFQ_DEPTH; |
| 424 | q->dep[i+SFQ_DEPTH].prev = i+SFQ_DEPTH; | 438 | q->dep[i+SFQ_DEPTH].prev = i+SFQ_DEPTH; |
| 425 | } | 439 | } |
| 426 | q->limit = SFQ_DEPTH - 2; | 440 | q->limit = SFQ_DEPTH - 1; |
| 427 | q->max_depth = 0; | 441 | q->max_depth = 0; |
| 428 | q->tail = SFQ_DEPTH; | 442 | q->tail = SFQ_DEPTH; |
| 429 | if (opt == NULL) { | 443 | if (opt == NULL) { |
| 430 | q->quantum = psched_mtu(sch->dev); | 444 | q->quantum = psched_mtu(sch->dev); |
| 431 | q->perturb_period = 0; | 445 | q->perturb_period = 0; |
| 446 | get_random_bytes(&q->perturbation, 4); | ||
| 432 | } else { | 447 | } else { |
| 433 | int err = sfq_change(sch, opt); | 448 | int err = sfq_change(sch, opt); |
| 434 | if (err) | 449 | if (err) |
diff --git a/net/socket.c b/net/socket.c index 7d44453dfae1..b09eb9036a17 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -777,9 +777,6 @@ static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 777 | if (pos != 0) | 777 | if (pos != 0) |
| 778 | return -ESPIPE; | 778 | return -ESPIPE; |
| 779 | 779 | ||
| 780 | if (iocb->ki_left == 0) /* Match SYS5 behaviour */ | ||
| 781 | return 0; | ||
| 782 | |||
| 783 | x = alloc_sock_iocb(iocb, &siocb); | 780 | x = alloc_sock_iocb(iocb, &siocb); |
| 784 | if (!x) | 781 | if (!x) |
| 785 | return -ENOMEM; | 782 | return -ENOMEM; |
