diff options
178 files changed, 9153 insertions, 871 deletions
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index edef85ce1195..50f99eab0e1f 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX | |||
@@ -290,6 +290,8 @@ powerpc/ | |||
290 | - directory with info on using Linux with the PowerPC. | 290 | - directory with info on using Linux with the PowerPC. |
291 | preempt-locking.txt | 291 | preempt-locking.txt |
292 | - info on locking under a preemptive kernel. | 292 | - info on locking under a preemptive kernel. |
293 | printk-formats.txt | ||
294 | - how to get printk format specifiers right | ||
293 | prio_tree.txt | 295 | prio_tree.txt |
294 | - info on radix-priority-search-tree use for indexing vmas. | 296 | - info on radix-priority-search-tree use for indexing vmas. |
295 | ramdisk.txt | 297 | ramdisk.txt |
diff --git a/Documentation/ABI/testing/sysfs-c2port b/Documentation/ABI/testing/sysfs-c2port new file mode 100644 index 000000000000..716cffc457e9 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-c2port | |||
@@ -0,0 +1,88 @@ | |||
1 | What: /sys/class/c2port/ | ||
2 | Date: October 2008 | ||
3 | Contact: Rodolfo Giometti <giometti@linux.it> | ||
4 | Description: | ||
5 | The /sys/class/c2port/ directory will contain files and | ||
6 | directories that will provide a unified interface to | ||
7 | the C2 port interface. | ||
8 | |||
9 | What: /sys/class/c2port/c2portX | ||
10 | Date: October 2008 | ||
11 | Contact: Rodolfo Giometti <giometti@linux.it> | ||
12 | Description: | ||
13 | The /sys/class/c2port/c2portX/ directory is related to X-th | ||
14 | C2 port into the system. Each directory will contain files to | ||
15 | manage and control its C2 port. | ||
16 | |||
17 | What: /sys/class/c2port/c2portX/access | ||
18 | Date: October 2008 | ||
19 | Contact: Rodolfo Giometti <giometti@linux.it> | ||
20 | Description: | ||
21 | The /sys/class/c2port/c2portX/access file enable the access | ||
22 | to the C2 port from the system. No commands can be sent | ||
23 | till this entry is set to 0. | ||
24 | |||
25 | What: /sys/class/c2port/c2portX/dev_id | ||
26 | Date: October 2008 | ||
27 | Contact: Rodolfo Giometti <giometti@linux.it> | ||
28 | Description: | ||
29 | The /sys/class/c2port/c2portX/dev_id file show the device ID | ||
30 | of the connected micro. | ||
31 | |||
32 | What: /sys/class/c2port/c2portX/flash_access | ||
33 | Date: October 2008 | ||
34 | Contact: Rodolfo Giometti <giometti@linux.it> | ||
35 | Description: | ||
36 | The /sys/class/c2port/c2portX/flash_access file enable the | ||
37 | access to the on-board flash of the connected micro. | ||
38 | No commands can be sent till this entry is set to 0. | ||
39 | |||
40 | What: /sys/class/c2port/c2portX/flash_block_size | ||
41 | Date: October 2008 | ||
42 | Contact: Rodolfo Giometti <giometti@linux.it> | ||
43 | Description: | ||
44 | The /sys/class/c2port/c2portX/flash_block_size file show | ||
45 | the on-board flash block size of the connected micro. | ||
46 | |||
47 | What: /sys/class/c2port/c2portX/flash_blocks_num | ||
48 | Date: October 2008 | ||
49 | Contact: Rodolfo Giometti <giometti@linux.it> | ||
50 | Description: | ||
51 | The /sys/class/c2port/c2portX/flash_blocks_num file show | ||
52 | the on-board flash blocks number of the connected micro. | ||
53 | |||
54 | What: /sys/class/c2port/c2portX/flash_data | ||
55 | Date: October 2008 | ||
56 | Contact: Rodolfo Giometti <giometti@linux.it> | ||
57 | Description: | ||
58 | The /sys/class/c2port/c2portX/flash_data file export | ||
59 | the content of the on-board flash of the connected micro. | ||
60 | |||
61 | What: /sys/class/c2port/c2portX/flash_erase | ||
62 | Date: October 2008 | ||
63 | Contact: Rodolfo Giometti <giometti@linux.it> | ||
64 | Description: | ||
65 | The /sys/class/c2port/c2portX/flash_erase file execute | ||
66 | the "erase" command on the on-board flash of the connected | ||
67 | micro. | ||
68 | |||
69 | What: /sys/class/c2port/c2portX/flash_erase | ||
70 | Date: October 2008 | ||
71 | Contact: Rodolfo Giometti <giometti@linux.it> | ||
72 | Description: | ||
73 | The /sys/class/c2port/c2portX/flash_erase file show the | ||
74 | on-board flash size of the connected micro. | ||
75 | |||
76 | What: /sys/class/c2port/c2portX/reset | ||
77 | Date: October 2008 | ||
78 | Contact: Rodolfo Giometti <giometti@linux.it> | ||
79 | Description: | ||
80 | The /sys/class/c2port/c2portX/reset file execute a "reset" | ||
81 | command on the connected micro. | ||
82 | |||
83 | What: /sys/class/c2port/c2portX/rev_id | ||
84 | Date: October 2008 | ||
85 | Contact: Rodolfo Giometti <giometti@linux.it> | ||
86 | Description: | ||
87 | The /sys/class/c2port/c2portX/rev_id file show the revision ID | ||
88 | of the connected micro. | ||
diff --git a/Documentation/ABI/testing/sysfs-firmware-acpi b/Documentation/ABI/testing/sysfs-firmware-acpi index f27be7d1a49f..e8ffc70ffe12 100644 --- a/Documentation/ABI/testing/sysfs-firmware-acpi +++ b/Documentation/ABI/testing/sysfs-firmware-acpi | |||
@@ -89,7 +89,7 @@ Description: | |||
89 | 89 | ||
90 | error - an interrupt that can't be accounted for above. | 90 | error - an interrupt that can't be accounted for above. |
91 | 91 | ||
92 | invalid: it's either a wakeup GPE or a GPE/Fixed Event that | 92 | invalid: it's either a GPE or a Fixed Event that |
93 | doesn't have an event handler. | 93 | doesn't have an event handler. |
94 | 94 | ||
95 | disable: the GPE/Fixed Event is valid but disabled. | 95 | disable: the GPE/Fixed Event is valid but disabled. |
@@ -117,30 +117,30 @@ Description: | |||
117 | and other user space applications so that the machine won't shutdown | 117 | and other user space applications so that the machine won't shutdown |
118 | when pressing the power button. | 118 | when pressing the power button. |
119 | # cat ff_pwr_btn | 119 | # cat ff_pwr_btn |
120 | 0 | 120 | 0 enabled |
121 | # press the power button for 3 times; | 121 | # press the power button for 3 times; |
122 | # cat ff_pwr_btn | 122 | # cat ff_pwr_btn |
123 | 3 | 123 | 3 enabled |
124 | # echo disable > ff_pwr_btn | 124 | # echo disable > ff_pwr_btn |
125 | # cat ff_pwr_btn | 125 | # cat ff_pwr_btn |
126 | disable | 126 | 3 disabled |
127 | # press the power button for 3 times; | 127 | # press the power button for 3 times; |
128 | # cat ff_pwr_btn | 128 | # cat ff_pwr_btn |
129 | disable | 129 | 3 disabled |
130 | # echo enable > ff_pwr_btn | 130 | # echo enable > ff_pwr_btn |
131 | # cat ff_pwr_btn | 131 | # cat ff_pwr_btn |
132 | 4 | 132 | 4 enabled |
133 | /* | 133 | /* |
134 | * this is because the status bit is set even if the enable bit is cleared, | 134 | * this is because the status bit is set even if the enable bit is cleared, |
135 | * and it triggers an ACPI fixed event when the enable bit is set again | 135 | * and it triggers an ACPI fixed event when the enable bit is set again |
136 | */ | 136 | */ |
137 | # press the power button for 3 times; | 137 | # press the power button for 3 times; |
138 | # cat ff_pwr_btn | 138 | # cat ff_pwr_btn |
139 | 7 | 139 | 7 enabled |
140 | # echo disable > ff_pwr_btn | 140 | # echo disable > ff_pwr_btn |
141 | # press the power button for 3 times; | 141 | # press the power button for 3 times; |
142 | # echo clear > ff_pwr_btn /* clear the status bit */ | 142 | # echo clear > ff_pwr_btn /* clear the status bit */ |
143 | # echo disable > ff_pwr_btn | 143 | # echo disable > ff_pwr_btn |
144 | # cat ff_pwr_btn | 144 | # cat ff_pwr_btn |
145 | 7 | 145 | 7 enabled |
146 | 146 | ||
diff --git a/Documentation/acpi/debug.txt b/Documentation/acpi/debug.txt new file mode 100644 index 000000000000..65bf47c46b6d --- /dev/null +++ b/Documentation/acpi/debug.txt | |||
@@ -0,0 +1,148 @@ | |||
1 | ACPI Debug Output | ||
2 | |||
3 | |||
4 | The ACPI CA, the Linux ACPI core, and some ACPI drivers can generate debug | ||
5 | output. This document describes how to use this facility. | ||
6 | |||
7 | Compile-time configuration | ||
8 | -------------------------- | ||
9 | |||
10 | ACPI debug output is globally enabled by CONFIG_ACPI_DEBUG. If this config | ||
11 | option is turned off, the debug messages are not even built into the | ||
12 | kernel. | ||
13 | |||
14 | Boot- and run-time configuration | ||
15 | -------------------------------- | ||
16 | |||
17 | When CONFIG_ACPI_DEBUG=y, you can select the component and level of messages | ||
18 | you're interested in. At boot-time, use the acpi.debug_layer and | ||
19 | acpi.debug_level kernel command line options. After boot, you can use the | ||
20 | debug_layer and debug_level files in /sys/module/acpi/parameters/ to control | ||
21 | the debug messages. | ||
22 | |||
23 | debug_layer (component) | ||
24 | ----------------------- | ||
25 | |||
26 | The "debug_layer" is a mask that selects components of interest, e.g., a | ||
27 | specific driver or part of the ACPI interpreter. To build the debug_layer | ||
28 | bitmask, look for the "#define _COMPONENT" in an ACPI source file. | ||
29 | |||
30 | You can set the debug_layer mask at boot-time using the acpi.debug_layer | ||
31 | command line argument, and you can change it after boot by writing values | ||
32 | to /sys/module/acpi/parameters/debug_layer. | ||
33 | |||
34 | The possible components are defined in include/acpi/acoutput.h and | ||
35 | include/acpi/acpi_drivers.h. Reading /sys/module/acpi/parameters/debug_layer | ||
36 | shows the supported mask values, currently these: | ||
37 | |||
38 | ACPI_UTILITIES 0x00000001 | ||
39 | ACPI_HARDWARE 0x00000002 | ||
40 | ACPI_EVENTS 0x00000004 | ||
41 | ACPI_TABLES 0x00000008 | ||
42 | ACPI_NAMESPACE 0x00000010 | ||
43 | ACPI_PARSER 0x00000020 | ||
44 | ACPI_DISPATCHER 0x00000040 | ||
45 | ACPI_EXECUTER 0x00000080 | ||
46 | ACPI_RESOURCES 0x00000100 | ||
47 | ACPI_CA_DEBUGGER 0x00000200 | ||
48 | ACPI_OS_SERVICES 0x00000400 | ||
49 | ACPI_CA_DISASSEMBLER 0x00000800 | ||
50 | ACPI_COMPILER 0x00001000 | ||
51 | ACPI_TOOLS 0x00002000 | ||
52 | ACPI_BUS_COMPONENT 0x00010000 | ||
53 | ACPI_AC_COMPONENT 0x00020000 | ||
54 | ACPI_BATTERY_COMPONENT 0x00040000 | ||
55 | ACPI_BUTTON_COMPONENT 0x00080000 | ||
56 | ACPI_SBS_COMPONENT 0x00100000 | ||
57 | ACPI_FAN_COMPONENT 0x00200000 | ||
58 | ACPI_PCI_COMPONENT 0x00400000 | ||
59 | ACPI_POWER_COMPONENT 0x00800000 | ||
60 | ACPI_CONTAINER_COMPONENT 0x01000000 | ||
61 | ACPI_SYSTEM_COMPONENT 0x02000000 | ||
62 | ACPI_THERMAL_COMPONENT 0x04000000 | ||
63 | ACPI_MEMORY_DEVICE_COMPONENT 0x08000000 | ||
64 | ACPI_VIDEO_COMPONENT 0x10000000 | ||
65 | ACPI_PROCESSOR_COMPONENT 0x20000000 | ||
66 | |||
67 | debug_level | ||
68 | ----------- | ||
69 | |||
70 | The "debug_level" is a mask that selects different types of messages, e.g., | ||
71 | those related to initialization, method execution, informational messages, etc. | ||
72 | To build debug_level, look at the level specified in an ACPI_DEBUG_PRINT() | ||
73 | statement. | ||
74 | |||
75 | The ACPI interpreter uses several different levels, but the Linux | ||
76 | ACPI core and ACPI drivers generally only use ACPI_LV_INFO. | ||
77 | |||
78 | You can set the debug_level mask at boot-time using the acpi.debug_level | ||
79 | command line argument, and you can change it after boot by writing values | ||
80 | to /sys/module/acpi/parameters/debug_level. | ||
81 | |||
82 | The possible levels are defined in include/acpi/acoutput.h. Reading | ||
83 | /sys/module/acpi/parameters/debug_level shows the supported mask values, | ||
84 | currently these: | ||
85 | |||
86 | ACPI_LV_INIT 0x00000001 | ||
87 | ACPI_LV_DEBUG_OBJECT 0x00000002 | ||
88 | ACPI_LV_INFO 0x00000004 | ||
89 | ACPI_LV_INIT_NAMES 0x00000020 | ||
90 | ACPI_LV_PARSE 0x00000040 | ||
91 | ACPI_LV_LOAD 0x00000080 | ||
92 | ACPI_LV_DISPATCH 0x00000100 | ||
93 | ACPI_LV_EXEC 0x00000200 | ||
94 | ACPI_LV_NAMES 0x00000400 | ||
95 | ACPI_LV_OPREGION 0x00000800 | ||
96 | ACPI_LV_BFIELD 0x00001000 | ||
97 | ACPI_LV_TABLES 0x00002000 | ||
98 | ACPI_LV_VALUES 0x00004000 | ||
99 | ACPI_LV_OBJECTS 0x00008000 | ||
100 | ACPI_LV_RESOURCES 0x00010000 | ||
101 | ACPI_LV_USER_REQUESTS 0x00020000 | ||
102 | ACPI_LV_PACKAGE 0x00040000 | ||
103 | ACPI_LV_ALLOCATIONS 0x00100000 | ||
104 | ACPI_LV_FUNCTIONS 0x00200000 | ||
105 | ACPI_LV_OPTIMIZATIONS 0x00400000 | ||
106 | ACPI_LV_MUTEX 0x01000000 | ||
107 | ACPI_LV_THREADS 0x02000000 | ||
108 | ACPI_LV_IO 0x04000000 | ||
109 | ACPI_LV_INTERRUPTS 0x08000000 | ||
110 | ACPI_LV_AML_DISASSEMBLE 0x10000000 | ||
111 | ACPI_LV_VERBOSE_INFO 0x20000000 | ||
112 | ACPI_LV_FULL_TABLES 0x40000000 | ||
113 | ACPI_LV_EVENTS 0x80000000 | ||
114 | |||
115 | Examples | ||
116 | -------- | ||
117 | |||
118 | For example, drivers/acpi/bus.c contains this: | ||
119 | |||
120 | #define _COMPONENT ACPI_BUS_COMPONENT | ||
121 | ... | ||
122 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n")); | ||
123 | |||
124 | To turn on this message, set the ACPI_BUS_COMPONENT bit in acpi.debug_layer | ||
125 | and the ACPI_LV_INFO bit in acpi.debug_level. (The ACPI_DEBUG_PRINT | ||
126 | statement uses ACPI_DB_INFO, which is macro based on the ACPI_LV_INFO | ||
127 | definition.) | ||
128 | |||
129 | Enable all AML "Debug" output (stores to the Debug object while interpreting | ||
130 | AML) during boot: | ||
131 | |||
132 | acpi.debug_layer=0xffffffff acpi.debug_level=0x2 | ||
133 | |||
134 | Enable PCI and PCI interrupt routing debug messages: | ||
135 | |||
136 | acpi.debug_layer=0x400000 acpi.debug_level=0x4 | ||
137 | |||
138 | Enable all ACPI hardware-related messages: | ||
139 | |||
140 | acpi.debug_layer=0x2 acpi.debug_level=0xffffffff | ||
141 | |||
142 | Enable all ACPI_DB_INFO messages after boot: | ||
143 | |||
144 | # echo 0x4 > /sys/module/acpi/parameters/debug_level | ||
145 | |||
146 | Show all valid component values: | ||
147 | |||
148 | # cat /sys/module/acpi/parameters/debug_layer | ||
diff --git a/Documentation/c2port.txt b/Documentation/c2port.txt new file mode 100644 index 000000000000..d9bf93ea4398 --- /dev/null +++ b/Documentation/c2port.txt | |||
@@ -0,0 +1,90 @@ | |||
1 | C2 port support | ||
2 | --------------- | ||
3 | |||
4 | (C) Copyright 2007 Rodolfo Giometti <giometti@enneenne.com> | ||
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; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | |||
17 | |||
18 | Overview | ||
19 | -------- | ||
20 | |||
21 | This driver implements the support for Linux of Silicon Labs (Silabs) | ||
22 | C2 Interface used for in-system programming of micro controllers. | ||
23 | |||
24 | By using this driver you can reprogram the in-system flash without EC2 | ||
25 | or EC3 debug adapter. This solution is also useful in those systems | ||
26 | where the micro controller is connected via special GPIOs pins. | ||
27 | |||
28 | References | ||
29 | ---------- | ||
30 | |||
31 | The C2 Interface main references are at (http://www.silabs.com) | ||
32 | Silicon Laboratories site], see: | ||
33 | |||
34 | - AN127: FLASH Programming via the C2 Interface at | ||
35 | http://www.silabs.com/public/documents/tpub_doc/anote/Microcontrollers/Small_Form_Factor/en/an127.pdf, and | ||
36 | |||
37 | - C2 Specification at | ||
38 | http://www.silabs.com/public/documents/tpub_doc/spec/Microcontrollers/en/C2spec.pdf, | ||
39 | |||
40 | however it implements a two wire serial communication protocol (bit | ||
41 | banging) designed to enable in-system programming, debugging, and | ||
42 | boundary-scan testing on low pin-count Silicon Labs devices. Currently | ||
43 | this code supports only flash programming but extensions are easy to | ||
44 | add. | ||
45 | |||
46 | Using the driver | ||
47 | ---------------- | ||
48 | |||
49 | Once the driver is loaded you can use sysfs support to get C2port's | ||
50 | info or read/write in-system flash. | ||
51 | |||
52 | # ls /sys/class/c2port/c2port0/ | ||
53 | access flash_block_size flash_erase rev_id | ||
54 | dev_id flash_blocks_num flash_size subsystem/ | ||
55 | flash_access flash_data reset uevent | ||
56 | |||
57 | Initially the C2port access is disabled since you hardware may have | ||
58 | such lines multiplexed with other devices so, to get access to the | ||
59 | C2port, you need the command: | ||
60 | |||
61 | # echo 1 > /sys/class/c2port/c2port0/access | ||
62 | |||
63 | after that you should read the device ID and revision ID of the | ||
64 | connected micro controller: | ||
65 | |||
66 | # cat /sys/class/c2port/c2port0/dev_id | ||
67 | 8 | ||
68 | # cat /sys/class/c2port/c2port0/rev_id | ||
69 | 1 | ||
70 | |||
71 | However, for security reasons, the in-system flash access in not | ||
72 | enabled yet, to do so you need the command: | ||
73 | |||
74 | # echo 1 > /sys/class/c2port/c2port0/flash_access | ||
75 | |||
76 | After that you can read the whole flash: | ||
77 | |||
78 | # cat /sys/class/c2port/c2port0/flash_data > image | ||
79 | |||
80 | erase it: | ||
81 | |||
82 | # echo 1 > /sys/class/c2port/c2port0/flash_erase | ||
83 | |||
84 | and write it: | ||
85 | |||
86 | # cat image > /sys/class/c2port/c2port0/flash_data | ||
87 | |||
88 | after writing you have to reset the device to execute the new code: | ||
89 | |||
90 | # echo 1 > /sys/class/c2port/c2port0/reset | ||
diff --git a/Documentation/cgroups/freezer-subsystem.txt b/Documentation/cgroups/freezer-subsystem.txt index c50ab58b72eb..41f37fea1276 100644 --- a/Documentation/cgroups/freezer-subsystem.txt +++ b/Documentation/cgroups/freezer-subsystem.txt | |||
@@ -1,4 +1,4 @@ | |||
1 | The cgroup freezer is useful to batch job management system which start | 1 | The cgroup freezer is useful to batch job management system which start |
2 | and stop sets of tasks in order to schedule the resources of a machine | 2 | and stop sets of tasks in order to schedule the resources of a machine |
3 | according to the desires of a system administrator. This sort of program | 3 | according to the desires of a system administrator. This sort of program |
4 | is often used on HPC clusters to schedule access to the cluster as a | 4 | is often used on HPC clusters to schedule access to the cluster as a |
@@ -6,7 +6,7 @@ whole. The cgroup freezer uses cgroups to describe the set of tasks to | |||
6 | be started/stopped by the batch job management system. It also provides | 6 | be started/stopped by the batch job management system. It also provides |
7 | a means to start and stop the tasks composing the job. | 7 | a means to start and stop the tasks composing the job. |
8 | 8 | ||
9 | The cgroup freezer will also be useful for checkpointing running groups | 9 | The cgroup freezer will also be useful for checkpointing running groups |
10 | of tasks. The freezer allows the checkpoint code to obtain a consistent | 10 | of tasks. The freezer allows the checkpoint code to obtain a consistent |
11 | image of the tasks by attempting to force the tasks in a cgroup into a | 11 | image of the tasks by attempting to force the tasks in a cgroup into a |
12 | quiescent state. Once the tasks are quiescent another task can | 12 | quiescent state. Once the tasks are quiescent another task can |
@@ -16,7 +16,7 @@ recoverable error occur. This also allows the checkpointed tasks to be | |||
16 | migrated between nodes in a cluster by copying the gathered information | 16 | migrated between nodes in a cluster by copying the gathered information |
17 | to another node and restarting the tasks there. | 17 | to another node and restarting the tasks there. |
18 | 18 | ||
19 | Sequences of SIGSTOP and SIGCONT are not always sufficient for stopping | 19 | Sequences of SIGSTOP and SIGCONT are not always sufficient for stopping |
20 | and resuming tasks in userspace. Both of these signals are observable | 20 | and resuming tasks in userspace. Both of these signals are observable |
21 | from within the tasks we wish to freeze. While SIGSTOP cannot be caught, | 21 | from within the tasks we wish to freeze. While SIGSTOP cannot be caught, |
22 | blocked, or ignored it can be seen by waiting or ptracing parent tasks. | 22 | blocked, or ignored it can be seen by waiting or ptracing parent tasks. |
@@ -37,26 +37,29 @@ demonstrate this problem using nested bash shells: | |||
37 | 37 | ||
38 | <at this point 16990 exits and causes 16644 to exit too> | 38 | <at this point 16990 exits and causes 16644 to exit too> |
39 | 39 | ||
40 | This happens because bash can observe both signals and choose how it | 40 | This happens because bash can observe both signals and choose how it |
41 | responds to them. | 41 | responds to them. |
42 | 42 | ||
43 | Another example of a program which catches and responds to these | 43 | Another example of a program which catches and responds to these |
44 | signals is gdb. In fact any program designed to use ptrace is likely to | 44 | signals is gdb. In fact any program designed to use ptrace is likely to |
45 | have a problem with this method of stopping and resuming tasks. | 45 | have a problem with this method of stopping and resuming tasks. |
46 | 46 | ||
47 | In contrast, the cgroup freezer uses the kernel freezer code to | 47 | In contrast, the cgroup freezer uses the kernel freezer code to |
48 | prevent the freeze/unfreeze cycle from becoming visible to the tasks | 48 | prevent the freeze/unfreeze cycle from becoming visible to the tasks |
49 | being frozen. This allows the bash example above and gdb to run as | 49 | being frozen. This allows the bash example above and gdb to run as |
50 | expected. | 50 | expected. |
51 | 51 | ||
52 | The freezer subsystem in the container filesystem defines a file named | 52 | The freezer subsystem in the container filesystem defines a file named |
53 | freezer.state. Writing "FROZEN" to the state file will freeze all tasks in the | 53 | freezer.state. Writing "FROZEN" to the state file will freeze all tasks in the |
54 | cgroup. Subsequently writing "THAWED" will unfreeze the tasks in the cgroup. | 54 | cgroup. Subsequently writing "THAWED" will unfreeze the tasks in the cgroup. |
55 | Reading will return the current state. | 55 | Reading will return the current state. |
56 | 56 | ||
57 | Note freezer.state doesn't exist in root cgroup, which means root cgroup | ||
58 | is non-freezable. | ||
59 | |||
57 | * Examples of usage : | 60 | * Examples of usage : |
58 | 61 | ||
59 | # mkdir /containers/freezer | 62 | # mkdir /containers |
60 | # mount -t cgroup -ofreezer freezer /containers | 63 | # mount -t cgroup -ofreezer freezer /containers |
61 | # mkdir /containers/0 | 64 | # mkdir /containers/0 |
62 | # echo $some_pid > /containers/0/tasks | 65 | # echo $some_pid > /containers/0/tasks |
@@ -94,6 +97,6 @@ things happens: | |||
94 | the freezer.state file | 97 | the freezer.state file |
95 | 2) Userspace retries the freezing operation by writing "FROZEN" to | 98 | 2) Userspace retries the freezing operation by writing "FROZEN" to |
96 | the freezer.state file (writing "FREEZING" is not legal | 99 | the freezer.state file (writing "FREEZING" is not legal |
97 | and returns EIO) | 100 | and returns EINVAL) |
98 | 3) The tasks that blocked the cgroup from entering the "FROZEN" | 101 | 3) The tasks that blocked the cgroup from entering the "FROZEN" |
99 | state disappear from the cgroup's set of tasks. | 102 | state disappear from the cgroup's set of tasks. |
diff --git a/Documentation/filesystems/xip.txt b/Documentation/filesystems/xip.txt index 3cc4010521a0..0466ee569278 100644 --- a/Documentation/filesystems/xip.txt +++ b/Documentation/filesystems/xip.txt | |||
@@ -39,10 +39,11 @@ The block device operation is optional, these block devices support it as of | |||
39 | today: | 39 | today: |
40 | - dcssblk: s390 dcss block device driver | 40 | - dcssblk: s390 dcss block device driver |
41 | 41 | ||
42 | An address space operation named get_xip_page is used to retrieve reference | 42 | An address space operation named get_xip_mem is used to retrieve references |
43 | to a struct page. To address the target page, a reference to an address_space, | 43 | to a page frame number and a kernel address. To obtain these values a reference |
44 | and a sector number is provided. A 3rd argument indicates whether the | 44 | to an address_space is provided. This function assigns values to the kmem and |
45 | function should allocate blocks if needed. | 45 | pfn parameters. The third argument indicates whether the function should allocate |
46 | blocks if needed. | ||
46 | 47 | ||
47 | This address space operation is mutually exclusive with readpage&writepage that | 48 | This address space operation is mutually exclusive with readpage&writepage that |
48 | do page cache read/write operations. | 49 | do page cache read/write operations. |
diff --git a/Documentation/hwmon/adt7462 b/Documentation/hwmon/adt7462 new file mode 100644 index 000000000000..ec660b328275 --- /dev/null +++ b/Documentation/hwmon/adt7462 | |||
@@ -0,0 +1,67 @@ | |||
1 | Kernel driver adt7462 | ||
2 | ====================== | ||
3 | |||
4 | Supported chips: | ||
5 | * Analog Devices ADT7462 | ||
6 | Prefix: 'adt7462' | ||
7 | Addresses scanned: I2C 0x58, 0x5C | ||
8 | Datasheet: Publicly available at the Analog Devices website | ||
9 | |||
10 | Author: Darrick J. Wong | ||
11 | |||
12 | Description | ||
13 | ----------- | ||
14 | |||
15 | This driver implements support for the Analog Devices ADT7462 chip family. | ||
16 | |||
17 | This chip is a bit of a beast. It has 8 counters for measuring fan speed. It | ||
18 | can also measure 13 voltages or 4 temperatures, or various combinations of the | ||
19 | two. See the chip documentation for more details about the exact set of | ||
20 | configurations. This driver does not allow one to configure the chip; that is | ||
21 | left to the system designer. | ||
22 | |||
23 | A sophisticated control system for the PWM outputs is designed into the ADT7462 | ||
24 | that allows fan speed to be adjusted automatically based on any of the three | ||
25 | temperature sensors. Each PWM output is individually adjustable and | ||
26 | programmable. Once configured, the ADT7462 will adjust the PWM outputs in | ||
27 | response to the measured temperatures without further host intervention. This | ||
28 | feature can also be disabled for manual control of the PWM's. | ||
29 | |||
30 | Each of the measured inputs (voltage, temperature, fan speed) has | ||
31 | corresponding high/low limit values. The ADT7462 will signal an ALARM if | ||
32 | any measured value exceeds either limit. | ||
33 | |||
34 | The ADT7462 samples all inputs continuously. The driver will not read | ||
35 | the registers more often than once every other second. Further, | ||
36 | configuration data is only read once per minute. | ||
37 | |||
38 | Special Features | ||
39 | ---------------- | ||
40 | |||
41 | The ADT7462 have a 10-bit ADC and can therefore measure temperatures | ||
42 | with 0.25 degC resolution. | ||
43 | |||
44 | The Analog Devices datasheet is very detailed and describes a procedure for | ||
45 | determining an optimal configuration for the automatic PWM control. | ||
46 | |||
47 | The driver will report sensor labels when it is able to determine that | ||
48 | information from the configuration registers. | ||
49 | |||
50 | Configuration Notes | ||
51 | ------------------- | ||
52 | |||
53 | Besides standard interfaces driver adds the following: | ||
54 | |||
55 | * PWM Control | ||
56 | |||
57 | * pwm#_auto_point1_pwm and temp#_auto_point1_temp and | ||
58 | * pwm#_auto_point2_pwm and temp#_auto_point2_temp - | ||
59 | |||
60 | point1: Set the pwm speed at a lower temperature bound. | ||
61 | point2: Set the pwm speed at a higher temperature bound. | ||
62 | |||
63 | The ADT7462 will scale the pwm between the lower and higher pwm speed when | ||
64 | the temperature is between the two temperature boundaries. PWM values range | ||
65 | from 0 (off) to 255 (full speed). Fan speed will be set to maximum when the | ||
66 | temperature sensor associated with the PWM control exceeds temp#_max. | ||
67 | |||
diff --git a/Documentation/hwmon/lis3lv02d b/Documentation/hwmon/lis3lv02d new file mode 100644 index 000000000000..65dfb0c0fd67 --- /dev/null +++ b/Documentation/hwmon/lis3lv02d | |||
@@ -0,0 +1,49 @@ | |||
1 | Kernel driver lis3lv02d | ||
2 | ================== | ||
3 | |||
4 | Supported chips: | ||
5 | |||
6 | * STMicroelectronics LIS3LV02DL and LIS3LV02DQ | ||
7 | |||
8 | Author: | ||
9 | Yan Burman <burman.yan@gmail.com> | ||
10 | Eric Piel <eric.piel@tremplin-utc.net> | ||
11 | |||
12 | |||
13 | Description | ||
14 | ----------- | ||
15 | |||
16 | This driver provides support for the accelerometer found in various HP laptops | ||
17 | sporting the feature officially called "HP Mobile Data Protection System 3D" or | ||
18 | "HP 3D DriveGuard". It detect automatically laptops with this sensor. Known models | ||
19 | (for now the HP 2133, nc6420, nc2510, nc8510, nc84x0, nw9440 and nx9420) will | ||
20 | have their axis automatically oriented on standard way (eg: you can directly | ||
21 | play neverball). The accelerometer data is readable via | ||
22 | /sys/devices/platform/lis3lv02d. | ||
23 | |||
24 | Sysfs attributes under /sys/devices/platform/lis3lv02d/: | ||
25 | position - 3D position that the accelerometer reports. Format: "(x,y,z)" | ||
26 | calibrate - read: values (x, y, z) that are used as the base for input class device operation. | ||
27 | write: forces the base to be recalibrated with the current position. | ||
28 | rate - reports the sampling rate of the accelerometer device in HZ | ||
29 | |||
30 | This driver also provides an absolute input class device, allowing | ||
31 | the laptop to act as a pinball machine-esque joystick. | ||
32 | |||
33 | Axes orientation | ||
34 | ---------------- | ||
35 | |||
36 | For better compatibility between the various laptops. The values reported by | ||
37 | the accelerometer are converted into a "standard" organisation of the axes | ||
38 | (aka "can play neverball out of the box"): | ||
39 | * When the laptop is horizontal the position reported is about 0 for X and Y | ||
40 | and a positive value for Z | ||
41 | * If the left side is elevated, X increases (becomes positive) | ||
42 | * If the front side (where the touchpad is) is elevated, Y decreases (becomes negative) | ||
43 | * If the laptop is put upside-down, Z becomes negative | ||
44 | |||
45 | If your laptop model is not recognized (cf "dmesg"), you can send an email to the | ||
46 | authors to add it to the database. When reporting a new laptop, please include | ||
47 | the output of "dmidecode" plus the value of /sys/devices/platform/lis3lv02d/position | ||
48 | in these four cases. | ||
49 | |||
diff --git a/Documentation/ics932s401 b/Documentation/ics932s401 new file mode 100644 index 000000000000..07a739f406d8 --- /dev/null +++ b/Documentation/ics932s401 | |||
@@ -0,0 +1,31 @@ | |||
1 | Kernel driver ics932s401 | ||
2 | ====================== | ||
3 | |||
4 | Supported chips: | ||
5 | * IDT ICS932S401 | ||
6 | Prefix: 'ics932s401' | ||
7 | Addresses scanned: I2C 0x69 | ||
8 | Datasheet: Publically available at the IDT website | ||
9 | |||
10 | Author: Darrick J. Wong | ||
11 | |||
12 | Description | ||
13 | ----------- | ||
14 | |||
15 | This driver implements support for the IDT ICS932S401 chip family. | ||
16 | |||
17 | This chip has 4 clock outputs--a base clock for the CPU (which is likely | ||
18 | multiplied to get the real CPU clock), a system clock, a PCI clock, a USB | ||
19 | clock, and a reference clock. The driver reports selected and actual | ||
20 | frequency. If spread spectrum mode is enabled, the driver also reports by what | ||
21 | percent the clock signal is being spread, which should be between 0 and -0.5%. | ||
22 | All frequencies are reported in KHz. | ||
23 | |||
24 | The ICS932S401 monitors all inputs continuously. The driver will not read | ||
25 | the registers more often than once every other second. | ||
26 | |||
27 | Special Features | ||
28 | ---------------- | ||
29 | |||
30 | The clocks could be reprogrammed to increase system speed. I will not help you | ||
31 | do this, as you risk damaging your system! | ||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index c86c07459712..c600c4ffc657 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -198,59 +198,42 @@ and is between 256 and 4096 characters. It is defined in the file | |||
198 | that require a timer override, but don't have | 198 | that require a timer override, but don't have |
199 | HPET | 199 | HPET |
200 | 200 | ||
201 | acpi.debug_layer= [HW,ACPI] | 201 | acpi_backlight= [HW,ACPI] |
202 | acpi_backlight=vendor | ||
203 | acpi_backlight=video | ||
204 | If set to vendor, prefer vendor specific driver | ||
205 | (e.g. thinkpad_acpi, sony_acpi, etc.) instead | ||
206 | of the ACPI video.ko driver. | ||
207 | |||
208 | acpi_display_output= [HW,ACPI] | ||
209 | acpi_display_output=vendor | ||
210 | acpi_display_output=video | ||
211 | See above. | ||
212 | |||
213 | acpi.debug_layer= [HW,ACPI,ACPI_DEBUG] | ||
214 | acpi.debug_level= [HW,ACPI,ACPI_DEBUG] | ||
202 | Format: <int> | 215 | Format: <int> |
203 | Each bit of the <int> indicates an ACPI debug layer, | 216 | CONFIG_ACPI_DEBUG must be enabled to produce any ACPI |
204 | 1: enable, 0: disable. It is useful for boot time | 217 | debug output. Bits in debug_layer correspond to a |
205 | debugging. After system has booted up, it can be set | 218 | _COMPONENT in an ACPI source file, e.g., |
206 | via /sys/module/acpi/parameters/debug_layer. | 219 | #define _COMPONENT ACPI_PCI_COMPONENT |
207 | CONFIG_ACPI_DEBUG must be enabled for this to produce any output. | 220 | Bits in debug_level correspond to a level in |
208 | Available bits (add the numbers together) to enable debug output | 221 | ACPI_DEBUG_PRINT statements, e.g., |
209 | for specific parts of the ACPI subsystem: | 222 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, ... |
210 | 0x01 utilities 0x02 hardware 0x04 events 0x08 tables | 223 | See Documentation/acpi/debug.txt for more information |
211 | 0x10 namespace 0x20 parser 0x40 dispatcher | 224 | about debug layers and levels. |
212 | 0x80 executer 0x100 resources 0x200 acpica debugger | 225 | |
213 | 0x400 os services 0x800 acpica disassembler. | 226 | Enable AML "Debug" output, i.e., stores to the Debug |
214 | The number can be in decimal or prefixed with 0x in hex. | 227 | object while interpreting AML: |
215 | Warning: Many of these options can produce a lot of | 228 | acpi.debug_layer=0xffffffff acpi.debug_level=0x2 |
216 | output and make your system unusable. Be very careful. | 229 | Enable PCI/PCI interrupt routing info messages: |
217 | 230 | acpi.debug_layer=0x400000 acpi.debug_level=0x4 | |
218 | acpi.debug_level= [HW,ACPI] | 231 | Enable all messages related to ACPI hardware: |
219 | Format: <int> | 232 | acpi.debug_layer=0x2 acpi.debug_level=0xffffffff |
220 | Each bit of the <int> indicates an ACPI debug level, | 233 | |
221 | which corresponds to the level in an ACPI_DEBUG_PRINT | 234 | Some values produce so much output that the system is |
222 | statement. After system has booted up, this mask | 235 | unusable. The "log_buf_len" parameter may be useful |
223 | can be set via /sys/module/acpi/parameters/debug_level. | 236 | if you need to capture more output. |
224 | |||
225 | CONFIG_ACPI_DEBUG must be enabled for this to produce | ||
226 | any output. The number can be in decimal or prefixed | ||
227 | with 0x in hex. Some of these options produce so much | ||
228 | output that the system is unusable. | ||
229 | |||
230 | The following global components are defined by the | ||
231 | ACPI CA: | ||
232 | 0x01 error | ||
233 | 0x02 warn | ||
234 | 0x04 init | ||
235 | 0x08 debug object | ||
236 | 0x10 info | ||
237 | 0x20 init names | ||
238 | 0x40 parse | ||
239 | 0x80 load | ||
240 | 0x100 dispatch | ||
241 | 0x200 execute | ||
242 | 0x400 names | ||
243 | 0x800 operation region | ||
244 | 0x1000 bfield | ||
245 | 0x2000 tables | ||
246 | 0x4000 values | ||
247 | 0x8000 objects | ||
248 | 0x10000 resources | ||
249 | 0x20000 user requests | ||
250 | 0x40000 package | ||
251 | The number can be in decimal or prefixed with 0x in hex. | ||
252 | Warning: Many of these options can produce a lot of | ||
253 | output and make your system unusable. Be very careful. | ||
254 | 237 | ||
255 | acpi.power_nocheck= [HW,ACPI] | 238 | acpi.power_nocheck= [HW,ACPI] |
256 | Format: 1/0 enable/disable the check of power state. | 239 | Format: 1/0 enable/disable the check of power state. |
diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt new file mode 100644 index 000000000000..1b5a5ddbc3ef --- /dev/null +++ b/Documentation/printk-formats.txt | |||
@@ -0,0 +1,35 @@ | |||
1 | If variable is of Type, use printk format specifier: | ||
2 | --------------------------------------------------------- | ||
3 | int %d or %x | ||
4 | unsigned int %u or %x | ||
5 | long %ld or %lx | ||
6 | unsigned long %lu or %lx | ||
7 | long long %lld or %llx | ||
8 | unsigned long long %llu or %llx | ||
9 | size_t %zu or %zx | ||
10 | ssize_t %zd or %zx | ||
11 | |||
12 | Raw pointer value SHOULD be printed with %p. | ||
13 | |||
14 | u64 SHOULD be printed with %llu/%llx, (unsigned long long): | ||
15 | |||
16 | printk("%llu", (unsigned long long)u64_var); | ||
17 | |||
18 | s64 SHOULD be printed with %lld/%llx, (long long): | ||
19 | |||
20 | printk("%lld", (long long)s64_var); | ||
21 | |||
22 | If <type> is dependent on a config option for its size (e.g., sector_t, | ||
23 | blkcnt_t, phys_addr_t, resource_size_t) or is architecture-dependent | ||
24 | for its size (e.g., tcflag_t), use a format specifier of its largest | ||
25 | possible type and explicitly cast to it. Example: | ||
26 | |||
27 | printk("test: sector number/total blocks: %llu/%llu\n", | ||
28 | (unsigned long long)sector, (unsigned long long)blockcount); | ||
29 | |||
30 | Reminder: sizeof() result is of type size_t. | ||
31 | |||
32 | Thank you for your cooperation and attention. | ||
33 | |||
34 | |||
35 | By Randy Dunlap <rdunlap@xenotime.net> | ||
diff --git a/Documentation/w1/masters/omap-hdq b/Documentation/w1/masters/omap-hdq new file mode 100644 index 000000000000..ca722e09b6a1 --- /dev/null +++ b/Documentation/w1/masters/omap-hdq | |||
@@ -0,0 +1,46 @@ | |||
1 | Kernel driver for omap HDQ/1-wire module. | ||
2 | ======================================== | ||
3 | |||
4 | Supported chips: | ||
5 | ================ | ||
6 | HDQ/1-wire controller on the TI OMAP 2430/3430 platforms. | ||
7 | |||
8 | A useful link about HDQ basics: | ||
9 | =============================== | ||
10 | http://focus.ti.com/lit/an/slua408/slua408.pdf | ||
11 | |||
12 | Description: | ||
13 | ============ | ||
14 | The HDQ/1-Wire module of TI OMAP2430/3430 platforms implement the hardware | ||
15 | protocol of the master functions of the Benchmark HDQ and the Dallas | ||
16 | Semiconductor 1-Wire protocols. These protocols use a single wire for | ||
17 | communication between the master (HDQ/1-Wire controller) and the slave | ||
18 | (HDQ/1-Wire external compliant device). | ||
19 | |||
20 | A typical application of the HDQ/1-Wire module is the communication with battery | ||
21 | monitor (gas gauge) integrated circuits. | ||
22 | |||
23 | The controller supports operation in both HDQ and 1-wire mode. The essential | ||
24 | difference between the HDQ and 1-wire mode is how the slave device responds to | ||
25 | initialization pulse.In HDQ mode, the firmware does not require the host to | ||
26 | create an initialization pulse to the slave.However, the slave can be reset by | ||
27 | using an initialization pulse (also referred to as a break pulse).The slave | ||
28 | does not respond with a presence pulse as it does in the 1-Wire protocol. | ||
29 | |||
30 | Remarks: | ||
31 | ======== | ||
32 | The driver (drivers/w1/masters/omap_hdq.c) supports the HDQ mode of the | ||
33 | controller. In this mode, as we can not read the ID which obeys the W1 | ||
34 | spec(family:id:crc), a module parameter can be passed to the driver which will | ||
35 | be used to calculate the CRC and pass back an appropriate slave ID to the W1 | ||
36 | core. | ||
37 | |||
38 | By default the master driver and the BQ slave i/f | ||
39 | driver(drivers/w1/slaves/w1_bq27000.c) sets the ID to 1. | ||
40 | Please note to load both the modules with a different ID if required, but note | ||
41 | that the ID used should be same for both master and slave driver loading. | ||
42 | |||
43 | e.g: | ||
44 | insmod omap_hdq.ko W1_ID=2 | ||
45 | inamod w1_bq27000.ko F_ID=2 | ||
46 | |||
diff --git a/MAINTAINERS b/MAINTAINERS index 53e78c83cc7a..8e0777fae3ce 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -2216,6 +2216,13 @@ M: adaplas@gmail.com | |||
2216 | L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) | 2216 | L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) |
2217 | S: Maintained | 2217 | S: Maintained |
2218 | 2218 | ||
2219 | INTEL MENLOW THERMAL DRIVER | ||
2220 | P: Sujith Thomas | ||
2221 | M: sujith.thomas@intel.com | ||
2222 | L: linux-acpi@vger.kernel.org | ||
2223 | W: http://www.lesswatts.org/projects/acpi/ | ||
2224 | S: Supported | ||
2225 | |||
2219 | INTEL IA32 MICROCODE UPDATE SUPPORT | 2226 | INTEL IA32 MICROCODE UPDATE SUPPORT |
2220 | P: Tigran Aivazian | 2227 | P: Tigran Aivazian |
2221 | M: tigran@aivazian.fsnet.co.uk | 2228 | M: tigran@aivazian.fsnet.co.uk |
@@ -2696,6 +2703,11 @@ P: Arnaldo Carvalho de Melo | |||
2696 | M: acme@ghostprotocols.net | 2703 | M: acme@ghostprotocols.net |
2697 | S: Maintained | 2704 | S: Maintained |
2698 | 2705 | ||
2706 | LIS3LV02D ACCELEROMETER DRIVER | ||
2707 | P: Eric Piel | ||
2708 | M: eric.piel@tremplin-utc.net | ||
2709 | S: Maintained | ||
2710 | |||
2699 | LM83 HARDWARE MONITOR DRIVER | 2711 | LM83 HARDWARE MONITOR DRIVER |
2700 | P: Jean Delvare | 2712 | P: Jean Delvare |
2701 | M: khali@linux-fr.org | 2713 | M: khali@linux-fr.org |
@@ -3377,7 +3389,9 @@ S: Maintained | |||
3377 | 3389 | ||
3378 | PNP SUPPORT | 3390 | PNP SUPPORT |
3379 | P: Adam Belay | 3391 | P: Adam Belay |
3380 | M: ambx1@neo.rr.com | 3392 | M: abelay@mit.edu |
3393 | P: Bjorn Helgaas | ||
3394 | M: bjorn.helgaas@hp.com | ||
3381 | S: Maintained | 3395 | S: Maintained |
3382 | 3396 | ||
3383 | PNXxxxx I2C DRIVER | 3397 | PNXxxxx I2C DRIVER |
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index 1cb8602dd9d5..4ed149cbb32a 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h | |||
@@ -256,8 +256,17 @@ int dmabounce_sync_for_cpu(struct device *, dma_addr_t, unsigned long, | |||
256 | int dmabounce_sync_for_device(struct device *, dma_addr_t, unsigned long, | 256 | int dmabounce_sync_for_device(struct device *, dma_addr_t, unsigned long, |
257 | size_t, enum dma_data_direction); | 257 | size_t, enum dma_data_direction); |
258 | #else | 258 | #else |
259 | #define dmabounce_sync_for_cpu(dev,dma,off,sz,dir) (1) | 259 | static inline int dmabounce_sync_for_cpu(struct device *d, dma_addr_t addr, |
260 | #define dmabounce_sync_for_device(dev,dma,off,sz,dir) (1) | 260 | unsigned long offset, size_t size, enum dma_data_direction dir) |
261 | { | ||
262 | return 1; | ||
263 | } | ||
264 | |||
265 | static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr, | ||
266 | unsigned long offset, size_t size, enum dma_data_direction dir) | ||
267 | { | ||
268 | return 1; | ||
269 | } | ||
261 | 270 | ||
262 | 271 | ||
263 | /** | 272 | /** |
diff --git a/arch/arm/include/asm/hardware/iop3xx-adma.h b/arch/arm/include/asm/hardware/iop3xx-adma.h index 87bff09633aa..83e6ba338e2c 100644 --- a/arch/arm/include/asm/hardware/iop3xx-adma.h +++ b/arch/arm/include/asm/hardware/iop3xx-adma.h | |||
@@ -730,7 +730,8 @@ static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc, | |||
730 | { | 730 | { |
731 | /* hw_desc->next_desc is the same location for all channels */ | 731 | /* hw_desc->next_desc is the same location for all channels */ |
732 | union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, }; | 732 | union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, }; |
733 | BUG_ON(hw_desc.dma->next_desc); | 733 | |
734 | iop_paranoia(hw_desc.dma->next_desc); | ||
734 | hw_desc.dma->next_desc = next_desc_addr; | 735 | hw_desc.dma->next_desc = next_desc_addr; |
735 | } | 736 | } |
736 | 737 | ||
@@ -760,7 +761,7 @@ static inline int iop_desc_get_zero_result(struct iop_adma_desc_slot *desc) | |||
760 | struct iop3xx_desc_aau *hw_desc = desc->hw_desc; | 761 | struct iop3xx_desc_aau *hw_desc = desc->hw_desc; |
761 | struct iop3xx_aau_desc_ctrl desc_ctrl = hw_desc->desc_ctrl_field; | 762 | struct iop3xx_aau_desc_ctrl desc_ctrl = hw_desc->desc_ctrl_field; |
762 | 763 | ||
763 | BUG_ON(!(desc_ctrl.tx_complete && desc_ctrl.zero_result_en)); | 764 | iop_paranoia(!(desc_ctrl.tx_complete && desc_ctrl.zero_result_en)); |
764 | return desc_ctrl.zero_result_err; | 765 | return desc_ctrl.zero_result_err; |
765 | } | 766 | } |
766 | 767 | ||
diff --git a/arch/arm/include/asm/hardware/iop_adma.h b/arch/arm/include/asm/hardware/iop_adma.h index cb7e3611bcba..385c6e8cbbd2 100644 --- a/arch/arm/include/asm/hardware/iop_adma.h +++ b/arch/arm/include/asm/hardware/iop_adma.h | |||
@@ -23,6 +23,12 @@ | |||
23 | 23 | ||
24 | #define IOP_ADMA_SLOT_SIZE 32 | 24 | #define IOP_ADMA_SLOT_SIZE 32 |
25 | #define IOP_ADMA_THRESHOLD 4 | 25 | #define IOP_ADMA_THRESHOLD 4 |
26 | #ifdef DEBUG | ||
27 | #define IOP_PARANOIA 1 | ||
28 | #else | ||
29 | #define IOP_PARANOIA 0 | ||
30 | #endif | ||
31 | #define iop_paranoia(x) BUG_ON(IOP_PARANOIA && (x)) | ||
26 | 32 | ||
27 | /** | 33 | /** |
28 | * struct iop_adma_device - internal representation of an ADMA device | 34 | * struct iop_adma_device - internal representation of an ADMA device |
diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h index cb1139ac1943..39d949b63e80 100644 --- a/arch/arm/include/asm/mach/map.h +++ b/arch/arm/include/asm/mach/map.h | |||
@@ -19,12 +19,13 @@ struct map_desc { | |||
19 | }; | 19 | }; |
20 | 20 | ||
21 | /* types 0-3 are defined in asm/io.h */ | 21 | /* types 0-3 are defined in asm/io.h */ |
22 | #define MT_CACHECLEAN 4 | 22 | #define MT_UNCACHED 4 |
23 | #define MT_MINICLEAN 5 | 23 | #define MT_CACHECLEAN 5 |
24 | #define MT_LOW_VECTORS 6 | 24 | #define MT_MINICLEAN 6 |
25 | #define MT_HIGH_VECTORS 7 | 25 | #define MT_LOW_VECTORS 7 |
26 | #define MT_MEMORY 8 | 26 | #define MT_HIGH_VECTORS 8 |
27 | #define MT_ROM 9 | 27 | #define MT_MEMORY 9 |
28 | #define MT_ROM 10 | ||
28 | 29 | ||
29 | #ifdef CONFIG_MMU | 30 | #ifdef CONFIG_MMU |
30 | extern void iotable_init(struct map_desc *, int); | 31 | extern void iotable_init(struct map_desc *, int); |
diff --git a/arch/arm/mach-clps711x/include/mach/hardware.h b/arch/arm/mach-clps711x/include/mach/hardware.h index 4c3e101b96c9..b3ebe9e4871f 100644 --- a/arch/arm/mach-clps711x/include/mach/hardware.h +++ b/arch/arm/mach-clps711x/include/mach/hardware.h | |||
@@ -94,20 +94,6 @@ | |||
94 | #include <asm/hardware/ep7212.h> | 94 | #include <asm/hardware/ep7212.h> |
95 | #include <asm/hardware/cs89712.h> | 95 | #include <asm/hardware/cs89712.h> |
96 | 96 | ||
97 | /* dynamic ioremap() areas */ | ||
98 | #define FLASH_START 0x00000000 | ||
99 | #define FLASH_SIZE 0x800000 | ||
100 | #define FLASH_WIDTH 4 | ||
101 | |||
102 | #define SRAM_START 0x60000000 | ||
103 | #define SRAM_SIZE 0xc000 | ||
104 | #define SRAM_WIDTH 4 | ||
105 | |||
106 | #define BOOTROM_START 0x70000000 | ||
107 | #define BOOTROM_SIZE 0x80 | ||
108 | #define BOOTROM_WIDTH 4 | ||
109 | |||
110 | |||
111 | /* static cdb89712_map_io() areas */ | 97 | /* static cdb89712_map_io() areas */ |
112 | #define REGISTER_START 0x80000000 | 98 | #define REGISTER_START 0x80000000 |
113 | #define REGISTER_SIZE 0x4000 | 99 | #define REGISTER_SIZE 0x4000 |
@@ -198,14 +184,6 @@ | |||
198 | #define CEIVA_FLASH_SIZE 0x100000 | 184 | #define CEIVA_FLASH_SIZE 0x100000 |
199 | #define CEIVA_FLASH_WIDTH 2 | 185 | #define CEIVA_FLASH_WIDTH 2 |
200 | 186 | ||
201 | #define SRAM_START 0x60000000 | ||
202 | #define SRAM_SIZE 0xc000 | ||
203 | #define SRAM_WIDTH 4 | ||
204 | |||
205 | #define BOOTROM_START 0x70000000 | ||
206 | #define BOOTROM_SIZE 0x80 | ||
207 | #define BOOTROM_WIDTH 4 | ||
208 | |||
209 | /* | 187 | /* |
210 | * SED1355 LCD controller | 188 | * SED1355 LCD controller |
211 | */ | 189 | */ |
diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c index c3a33b8a5aac..7e247c04d41c 100644 --- a/arch/arm/mach-clps7500/core.c +++ b/arch/arm/mach-clps7500/core.c | |||
@@ -275,9 +275,9 @@ static struct map_desc cl7500_io_desc[] __initdata = { | |||
275 | .length = ISA_SIZE, | 275 | .length = ISA_SIZE, |
276 | .type = MT_DEVICE | 276 | .type = MT_DEVICE |
277 | }, { /* Flash */ | 277 | }, { /* Flash */ |
278 | .virtual = FLASH_BASE, | 278 | .virtual = CLPS7500_FLASH_BASE, |
279 | .pfn = __phys_to_pfn(FLASH_START), | 279 | .pfn = __phys_to_pfn(CLPS7500_FLASH_START), |
280 | .length = FLASH_SIZE, | 280 | .length = CLPS7500_FLASH_SIZE, |
281 | .type = MT_DEVICE | 281 | .type = MT_DEVICE |
282 | }, { /* LED */ | 282 | }, { /* LED */ |
283 | .virtual = LED_BASE, | 283 | .virtual = LED_BASE, |
diff --git a/arch/arm/mach-clps7500/include/mach/hardware.h b/arch/arm/mach-clps7500/include/mach/hardware.h index d66578a3371c..a6ad1d44badf 100644 --- a/arch/arm/mach-clps7500/include/mach/hardware.h +++ b/arch/arm/mach-clps7500/include/mach/hardware.h | |||
@@ -39,9 +39,9 @@ | |||
39 | #define ISA_SIZE 0x00010000 | 39 | #define ISA_SIZE 0x00010000 |
40 | #define ISA_BASE 0xe1000000 | 40 | #define ISA_BASE 0xe1000000 |
41 | 41 | ||
42 | #define FLASH_START 0x01000000 /* XXX */ | 42 | #define CLPS7500_FLASH_START 0x01000000 /* XXX */ |
43 | #define FLASH_SIZE 0x01000000 | 43 | #define CLPS7500_FLASH_SIZE 0x01000000 |
44 | #define FLASH_BASE 0xe2000000 | 44 | #define CLPS7500_FLASH_BASE 0xe2000000 |
45 | 45 | ||
46 | #define LED_START 0x0302B000 | 46 | #define LED_START 0x0302B000 |
47 | #define LED_SIZE 0x00001000 | 47 | #define LED_SIZE 0x00001000 |
diff --git a/arch/arm/mach-h720x/include/mach/boards.h b/arch/arm/mach-h720x/include/mach/boards.h index 079b279e1242..38b8e0d61fbf 100644 --- a/arch/arm/mach-h720x/include/mach/boards.h +++ b/arch/arm/mach-h720x/include/mach/boards.h | |||
@@ -19,9 +19,9 @@ | |||
19 | #ifdef CONFIG_ARCH_H7202 | 19 | #ifdef CONFIG_ARCH_H7202 |
20 | 20 | ||
21 | /* FLASH */ | 21 | /* FLASH */ |
22 | #define FLASH_VIRT 0xd0000000 | 22 | #define H720X_FLASH_VIRT 0xd0000000 |
23 | #define FLASH_PHYS 0x00000000 | 23 | #define H720X_FLASH_PHYS 0x00000000 |
24 | #define FLASH_SIZE 0x02000000 | 24 | #define H720X_FLASH_SIZE 0x02000000 |
25 | 25 | ||
26 | /* onboard LAN controller */ | 26 | /* onboard LAN controller */ |
27 | # define ETH0_PHYS 0x08000000 | 27 | # define ETH0_PHYS 0x08000000 |
diff --git a/arch/arm/mach-integrator/include/mach/platform.h b/arch/arm/mach-integrator/include/mach/platform.h index 028b87839c0f..e00a2624f269 100644 --- a/arch/arm/mach-integrator/include/mach/platform.h +++ b/arch/arm/mach-integrator/include/mach/platform.h | |||
@@ -408,27 +408,10 @@ | |||
408 | #define uHAL_MEMORY_SIZE INTEGRATOR_SSRAM_SIZE | 408 | #define uHAL_MEMORY_SIZE INTEGRATOR_SSRAM_SIZE |
409 | 409 | ||
410 | /* | 410 | /* |
411 | * Application Flash | ||
412 | * | ||
413 | */ | ||
414 | #define FLASH_BASE INTEGRATOR_FLASH_BASE | ||
415 | #define FLASH_SIZE INTEGRATOR_FLASH_SIZE | ||
416 | #define FLASH_END (FLASH_BASE + FLASH_SIZE - 1) | ||
417 | #define FLASH_BLOCK_SIZE SZ_128K | ||
418 | |||
419 | /* | ||
420 | * Boot Flash | ||
421 | * | ||
422 | */ | ||
423 | #define EPROM_BASE INTEGRATOR_BOOT_ROM_HI | ||
424 | #define EPROM_SIZE INTEGRATOR_BOOT_ROM_SIZE | ||
425 | #define EPROM_END (EPROM_BASE + EPROM_SIZE - 1) | ||
426 | |||
427 | /* | ||
428 | * Clean base - dummy | 411 | * Clean base - dummy |
429 | * | 412 | * |
430 | */ | 413 | */ |
431 | #define CLEAN_BASE EPROM_BASE | 414 | #define CLEAN_BASE INTEGRATOR_BOOT_ROM_HI |
432 | 415 | ||
433 | /* | 416 | /* |
434 | * Timer definitions | 417 | * Timer definitions |
diff --git a/arch/arm/mach-iop13xx/include/mach/adma.h b/arch/arm/mach-iop13xx/include/mach/adma.h index 60019c8e6465..5722e86f2174 100644 --- a/arch/arm/mach-iop13xx/include/mach/adma.h +++ b/arch/arm/mach-iop13xx/include/mach/adma.h | |||
@@ -404,7 +404,8 @@ static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc, | |||
404 | u32 next_desc_addr) | 404 | u32 next_desc_addr) |
405 | { | 405 | { |
406 | struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc; | 406 | struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc; |
407 | BUG_ON(hw_desc->next_desc); | 407 | |
408 | iop_paranoia(hw_desc->next_desc); | ||
408 | hw_desc->next_desc = next_desc_addr; | 409 | hw_desc->next_desc = next_desc_addr; |
409 | } | 410 | } |
410 | 411 | ||
diff --git a/arch/arm/mach-realview/clock.c b/arch/arm/mach-realview/clock.c index 3e706c57833a..3347c4236a60 100644 --- a/arch/arm/mach-realview/clock.c +++ b/arch/arm/mach-realview/clock.c | |||
@@ -104,7 +104,7 @@ static struct clk uart_clk = { | |||
104 | 104 | ||
105 | static struct clk mmci_clk = { | 105 | static struct clk mmci_clk = { |
106 | .name = "MCLK", | 106 | .name = "MCLK", |
107 | .rate = 33000000, | 107 | .rate = 24000000, |
108 | }; | 108 | }; |
109 | 109 | ||
110 | int clk_register(struct clk *clk) | 110 | int clk_register(struct clk *clk) |
diff --git a/arch/arm/mach-realview/include/mach/platform.h b/arch/arm/mach-realview/include/mach/platform.h index 4034b54950c2..793a3a332712 100644 --- a/arch/arm/mach-realview/include/mach/platform.h +++ b/arch/arm/mach-realview/include/mach/platform.h | |||
@@ -239,27 +239,10 @@ | |||
239 | #define REALVIEW_DECODE_OFFSET 0xC /* Fitted logic modules */ | 239 | #define REALVIEW_DECODE_OFFSET 0xC /* Fitted logic modules */ |
240 | 240 | ||
241 | /* | 241 | /* |
242 | * Application Flash | ||
243 | * | ||
244 | */ | ||
245 | #define FLASH_BASE REALVIEW_FLASH_BASE | ||
246 | #define FLASH_SIZE REALVIEW_FLASH_SIZE | ||
247 | #define FLASH_END (FLASH_BASE + FLASH_SIZE - 1) | ||
248 | #define FLASH_BLOCK_SIZE SZ_128K | ||
249 | |||
250 | /* | ||
251 | * Boot Flash | ||
252 | * | ||
253 | */ | ||
254 | #define EPROM_BASE REALVIEW_BOOT_ROM_HI | ||
255 | #define EPROM_SIZE REALVIEW_BOOT_ROM_SIZE | ||
256 | #define EPROM_END (EPROM_BASE + EPROM_SIZE - 1) | ||
257 | |||
258 | /* | ||
259 | * Clean base - dummy | 242 | * Clean base - dummy |
260 | * | 243 | * |
261 | */ | 244 | */ |
262 | #define CLEAN_BASE EPROM_BASE | 245 | #define CLEAN_BASE REALVIEW_BOOT_ROM_HI |
263 | 246 | ||
264 | /* | 247 | /* |
265 | * System controller bit assignment | 248 | * System controller bit assignment |
diff --git a/arch/arm/mach-versatile/clock.c b/arch/arm/mach-versatile/clock.c index 9336508ec0b2..58937f1fb38c 100644 --- a/arch/arm/mach-versatile/clock.c +++ b/arch/arm/mach-versatile/clock.c | |||
@@ -105,7 +105,7 @@ static struct clk uart_clk = { | |||
105 | 105 | ||
106 | static struct clk mmci_clk = { | 106 | static struct clk mmci_clk = { |
107 | .name = "MCLK", | 107 | .name = "MCLK", |
108 | .rate = 33000000, | 108 | .rate = 24000000, |
109 | }; | 109 | }; |
110 | 110 | ||
111 | int clk_register(struct clk *clk) | 111 | int clk_register(struct clk *clk) |
diff --git a/arch/arm/mach-versatile/include/mach/platform.h b/arch/arm/mach-versatile/include/mach/platform.h index 27cbe6a3f220..f91ba930ca8a 100644 --- a/arch/arm/mach-versatile/include/mach/platform.h +++ b/arch/arm/mach-versatile/include/mach/platform.h | |||
@@ -436,28 +436,12 @@ | |||
436 | #define SIC_INTMASK_PCI1 (1 << SIC_INT_PCI1) | 436 | #define SIC_INTMASK_PCI1 (1 << SIC_INT_PCI1) |
437 | #define SIC_INTMASK_PCI2 (1 << SIC_INT_PCI2) | 437 | #define SIC_INTMASK_PCI2 (1 << SIC_INT_PCI2) |
438 | #define SIC_INTMASK_PCI3 (1 << SIC_INT_PCI3) | 438 | #define SIC_INTMASK_PCI3 (1 << SIC_INT_PCI3) |
439 | /* | ||
440 | * Application Flash | ||
441 | * | ||
442 | */ | ||
443 | #define FLASH_BASE VERSATILE_FLASH_BASE | ||
444 | #define FLASH_SIZE VERSATILE_FLASH_SIZE | ||
445 | #define FLASH_END (FLASH_BASE + FLASH_SIZE - 1) | ||
446 | #define FLASH_BLOCK_SIZE SZ_128K | ||
447 | |||
448 | /* | ||
449 | * Boot Flash | ||
450 | * | ||
451 | */ | ||
452 | #define EPROM_BASE VERSATILE_BOOT_ROM_HI | ||
453 | #define EPROM_SIZE VERSATILE_BOOT_ROM_SIZE | ||
454 | #define EPROM_END (EPROM_BASE + EPROM_SIZE - 1) | ||
455 | 439 | ||
456 | /* | 440 | /* |
457 | * Clean base - dummy | 441 | * Clean base - dummy |
458 | * | 442 | * |
459 | */ | 443 | */ |
460 | #define CLEAN_BASE EPROM_BASE | 444 | #define CLEAN_BASE VERSATILE_BOOT_ROM_HI |
461 | 445 | ||
462 | /* | 446 | /* |
463 | * System controller bit assignment | 447 | * System controller bit assignment |
diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c index 13cdae8b0d44..80cd207cbaea 100644 --- a/arch/arm/mm/cache-feroceon-l2.c +++ b/arch/arm/mm/cache-feroceon-l2.c | |||
@@ -150,7 +150,7 @@ static void feroceon_l2_inv_range(unsigned long start, unsigned long end) | |||
150 | /* | 150 | /* |
151 | * Clean and invalidate partial last cache line. | 151 | * Clean and invalidate partial last cache line. |
152 | */ | 152 | */ |
153 | if (end & (CACHE_LINE_SIZE - 1)) { | 153 | if (start < end && end & (CACHE_LINE_SIZE - 1)) { |
154 | l2_clean_inv_pa(end & ~(CACHE_LINE_SIZE - 1)); | 154 | l2_clean_inv_pa(end & ~(CACHE_LINE_SIZE - 1)); |
155 | end &= ~(CACHE_LINE_SIZE - 1); | 155 | end &= ~(CACHE_LINE_SIZE - 1); |
156 | } | 156 | } |
@@ -158,7 +158,7 @@ static void feroceon_l2_inv_range(unsigned long start, unsigned long end) | |||
158 | /* | 158 | /* |
159 | * Invalidate all full cache lines between 'start' and 'end'. | 159 | * Invalidate all full cache lines between 'start' and 'end'. |
160 | */ | 160 | */ |
161 | while (start != end) { | 161 | while (start < end) { |
162 | unsigned long range_end = calc_range_end(start, end); | 162 | unsigned long range_end = calc_range_end(start, end); |
163 | l2_inv_pa_range(start, range_end - CACHE_LINE_SIZE); | 163 | l2_inv_pa_range(start, range_end - CACHE_LINE_SIZE); |
164 | start = range_end; | 164 | start = range_end; |
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index e63db11f16a8..7f36c825718d 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
@@ -208,6 +208,12 @@ static struct mem_type mem_types[] = { | |||
208 | .prot_sect = PROT_SECT_DEVICE, | 208 | .prot_sect = PROT_SECT_DEVICE, |
209 | .domain = DOMAIN_IO, | 209 | .domain = DOMAIN_IO, |
210 | }, | 210 | }, |
211 | [MT_UNCACHED] = { | ||
212 | .prot_pte = PROT_PTE_DEVICE, | ||
213 | .prot_l1 = PMD_TYPE_TABLE, | ||
214 | .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN, | ||
215 | .domain = DOMAIN_IO, | ||
216 | }, | ||
211 | [MT_CACHECLEAN] = { | 217 | [MT_CACHECLEAN] = { |
212 | .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN, | 218 | .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN, |
213 | .domain = DOMAIN_KERNEL, | 219 | .domain = DOMAIN_KERNEL, |
diff --git a/arch/arm/plat-iop/setup.c b/arch/arm/plat-iop/setup.c index 4689db638e95..9e573e78176a 100644 --- a/arch/arm/plat-iop/setup.c +++ b/arch/arm/plat-iop/setup.c | |||
@@ -16,14 +16,15 @@ | |||
16 | #include <asm/hardware/iop3xx.h> | 16 | #include <asm/hardware/iop3xx.h> |
17 | 17 | ||
18 | /* | 18 | /* |
19 | * Standard IO mapping for all IOP3xx based systems | 19 | * Standard IO mapping for all IOP3xx based systems. Note that |
20 | * the IOP3xx OCCDR must be mapped uncached and unbuffered. | ||
20 | */ | 21 | */ |
21 | static struct map_desc iop3xx_std_desc[] __initdata = { | 22 | static struct map_desc iop3xx_std_desc[] __initdata = { |
22 | { /* mem mapped registers */ | 23 | { /* mem mapped registers */ |
23 | .virtual = IOP3XX_PERIPHERAL_VIRT_BASE, | 24 | .virtual = IOP3XX_PERIPHERAL_VIRT_BASE, |
24 | .pfn = __phys_to_pfn(IOP3XX_PERIPHERAL_PHYS_BASE), | 25 | .pfn = __phys_to_pfn(IOP3XX_PERIPHERAL_PHYS_BASE), |
25 | .length = IOP3XX_PERIPHERAL_SIZE, | 26 | .length = IOP3XX_PERIPHERAL_SIZE, |
26 | .type = MT_DEVICE, | 27 | .type = MT_UNCACHED, |
27 | }, { /* PCI IO space */ | 28 | }, { /* PCI IO space */ |
28 | .virtual = IOP3XX_PCI_LOWER_IO_VA, | 29 | .virtual = IOP3XX_PCI_LOWER_IO_VA, |
29 | .pfn = __phys_to_pfn(IOP3XX_PCI_LOWER_IO_PA), | 30 | .pfn = __phys_to_pfn(IOP3XX_PCI_LOWER_IO_PA), |
diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig index 8e99fed6b3fd..f833a0b4188d 100644 --- a/arch/ia64/kvm/Kconfig +++ b/arch/ia64/kvm/Kconfig | |||
@@ -20,6 +20,8 @@ if VIRTUALIZATION | |||
20 | config KVM | 20 | config KVM |
21 | tristate "Kernel-based Virtual Machine (KVM) support" | 21 | tristate "Kernel-based Virtual Machine (KVM) support" |
22 | depends on HAVE_KVM && EXPERIMENTAL | 22 | depends on HAVE_KVM && EXPERIMENTAL |
23 | # for device assignment: | ||
24 | depends on PCI | ||
23 | select PREEMPT_NOTIFIERS | 25 | select PREEMPT_NOTIFIERS |
24 | select ANON_INODES | 26 | select ANON_INODES |
25 | ---help--- | 27 | ---help--- |
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index 3caac477de9e..af1464f7a6ad 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c | |||
@@ -673,16 +673,16 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
673 | 673 | ||
674 | vcpu_load(vcpu); | 674 | vcpu_load(vcpu); |
675 | 675 | ||
676 | if (vcpu->sigset_active) | ||
677 | sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved); | ||
678 | |||
676 | if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_UNINITIALIZED)) { | 679 | if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_UNINITIALIZED)) { |
677 | kvm_vcpu_block(vcpu); | 680 | kvm_vcpu_block(vcpu); |
678 | clear_bit(KVM_REQ_UNHALT, &vcpu->requests); | 681 | clear_bit(KVM_REQ_UNHALT, &vcpu->requests); |
679 | vcpu_put(vcpu); | 682 | r = -EAGAIN; |
680 | return -EAGAIN; | 683 | goto out; |
681 | } | 684 | } |
682 | 685 | ||
683 | if (vcpu->sigset_active) | ||
684 | sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved); | ||
685 | |||
686 | if (vcpu->mmio_needed) { | 686 | if (vcpu->mmio_needed) { |
687 | memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8); | 687 | memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8); |
688 | kvm_set_mmio_data(vcpu); | 688 | kvm_set_mmio_data(vcpu); |
@@ -690,7 +690,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
690 | vcpu->mmio_needed = 0; | 690 | vcpu->mmio_needed = 0; |
691 | } | 691 | } |
692 | r = __vcpu_run(vcpu, kvm_run); | 692 | r = __vcpu_run(vcpu, kvm_run); |
693 | 693 | out: | |
694 | if (vcpu->sigset_active) | 694 | if (vcpu->sigset_active) |
695 | sigprocmask(SIG_SETMASK, &sigsaved, NULL); | 695 | sigprocmask(SIG_SETMASK, &sigsaved, NULL); |
696 | 696 | ||
diff --git a/arch/ia64/kvm/vcpu.h b/arch/ia64/kvm/vcpu.h index 341e3fee280c..e9b2a4e121c0 100644 --- a/arch/ia64/kvm/vcpu.h +++ b/arch/ia64/kvm/vcpu.h | |||
@@ -384,6 +384,10 @@ static inline u64 __gpfn_is_io(u64 gpfn) | |||
384 | #define MODE_IND(psr) \ | 384 | #define MODE_IND(psr) \ |
385 | (((psr).it << 2) + ((psr).dt << 1) + (psr).rt) | 385 | (((psr).it << 2) + ((psr).dt << 1) + (psr).rt) |
386 | 386 | ||
387 | #ifndef CONFIG_SMP | ||
388 | #define _vmm_raw_spin_lock(x) do {}while(0) | ||
389 | #define _vmm_raw_spin_unlock(x) do {}while(0) | ||
390 | #else | ||
387 | #define _vmm_raw_spin_lock(x) \ | 391 | #define _vmm_raw_spin_lock(x) \ |
388 | do { \ | 392 | do { \ |
389 | __u32 *ia64_spinlock_ptr = (__u32 *) (x); \ | 393 | __u32 *ia64_spinlock_ptr = (__u32 *) (x); \ |
@@ -403,6 +407,7 @@ static inline u64 __gpfn_is_io(u64 gpfn) | |||
403 | do { barrier(); \ | 407 | do { barrier(); \ |
404 | ((spinlock_t *)x)->raw_lock.lock = 0; } \ | 408 | ((spinlock_t *)x)->raw_lock.lock = 0; } \ |
405 | while (0) | 409 | while (0) |
410 | #endif | ||
406 | 411 | ||
407 | void vmm_spin_lock(spinlock_t *lock); | 412 | void vmm_spin_lock(spinlock_t *lock); |
408 | void vmm_spin_unlock(spinlock_t *lock); | 413 | void vmm_spin_unlock(spinlock_t *lock); |
diff --git a/arch/mn10300/Kconfig.debug b/arch/mn10300/Kconfig.debug index 524e33819f32..ff80e86b9bd2 100644 --- a/arch/mn10300/Kconfig.debug +++ b/arch/mn10300/Kconfig.debug | |||
@@ -15,6 +15,15 @@ config DEBUG_DECOMPRESS_KERNEL | |||
15 | decompressing Linux seeing "Uncompressing Linux... " and | 15 | decompressing Linux seeing "Uncompressing Linux... " and |
16 | "Ok, booting the kernel.\n" on console. | 16 | "Ok, booting the kernel.\n" on console. |
17 | 17 | ||
18 | config TEST_MISALIGNMENT_HANDLER | ||
19 | bool "Run tests on the misalignment handler" | ||
20 | depends on DEBUG_KERNEL | ||
21 | default n | ||
22 | help | ||
23 | If you say Y here the kernel will execute a list of misaligned memory | ||
24 | accesses to make sure the misalignment handler deals them with | ||
25 | correctly. If it does not, the kernel will throw a BUG. | ||
26 | |||
18 | config KPROBES | 27 | config KPROBES |
19 | bool "Kprobes" | 28 | bool "Kprobes" |
20 | depends on DEBUG_KERNEL | 29 | depends on DEBUG_KERNEL |
diff --git a/arch/mn10300/mm/misalignment.c b/arch/mn10300/mm/misalignment.c index 32aa89dc3848..94c4a4358065 100644 --- a/arch/mn10300/mm/misalignment.c +++ b/arch/mn10300/mm/misalignment.c | |||
@@ -37,26 +37,22 @@ | |||
37 | #include <asm/asm-offsets.h> | 37 | #include <asm/asm-offsets.h> |
38 | 38 | ||
39 | #if 0 | 39 | #if 0 |
40 | #define kdebug(FMT, ...) printk(KERN_DEBUG FMT, ##__VA_ARGS__) | 40 | #define kdebug(FMT, ...) printk(KERN_DEBUG "MISALIGN: "FMT"\n", ##__VA_ARGS__) |
41 | #else | 41 | #else |
42 | #define kdebug(FMT, ...) do {} while (0) | 42 | #define kdebug(FMT, ...) do {} while (0) |
43 | #endif | 43 | #endif |
44 | 44 | ||
45 | static int misalignment_addr(unsigned long *registers, unsigned params, | 45 | static int misalignment_addr(unsigned long *registers, unsigned long sp, |
46 | unsigned opcode, unsigned disp, | 46 | unsigned params, unsigned opcode, |
47 | void **_address, unsigned long **_postinc); | 47 | unsigned long disp, |
48 | void **_address, unsigned long **_postinc, | ||
49 | unsigned long *_inc); | ||
48 | 50 | ||
49 | static int misalignment_reg(unsigned long *registers, unsigned params, | 51 | static int misalignment_reg(unsigned long *registers, unsigned params, |
50 | unsigned opcode, unsigned disp, | 52 | unsigned opcode, unsigned long disp, |
51 | unsigned long **_register); | 53 | unsigned long **_register); |
52 | 54 | ||
53 | static inline unsigned int_log2(unsigned x) | 55 | static void misalignment_MOV_Lcc(struct pt_regs *regs, uint32_t opcode); |
54 | { | ||
55 | unsigned y; | ||
56 | asm("bsch %1,%0" : "=r"(y) : "r"(x), "0"(0)); | ||
57 | return y; | ||
58 | } | ||
59 | #define log2(x) int_log2(x) | ||
60 | 56 | ||
61 | static const unsigned Dreg_index[] = { | 57 | static const unsigned Dreg_index[] = { |
62 | REG_D0 >> 2, REG_D1 >> 2, REG_D2 >> 2, REG_D3 >> 2 | 58 | REG_D0 >> 2, REG_D1 >> 2, REG_D2 >> 2, REG_D3 >> 2 |
@@ -86,9 +82,10 @@ enum format_id { | |||
86 | FMT_D7, | 82 | FMT_D7, |
87 | FMT_D8, | 83 | FMT_D8, |
88 | FMT_D9, | 84 | FMT_D9, |
85 | FMT_D10, | ||
89 | }; | 86 | }; |
90 | 87 | ||
91 | struct { | 88 | static const struct { |
92 | u_int8_t opsz, dispsz; | 89 | u_int8_t opsz, dispsz; |
93 | } format_tbl[16] = { | 90 | } format_tbl[16] = { |
94 | [FMT_S0] = { 8, 0 }, | 91 | [FMT_S0] = { 8, 0 }, |
@@ -103,6 +100,7 @@ struct { | |||
103 | [FMT_D7] = { 24, 8 }, | 100 | [FMT_D7] = { 24, 8 }, |
104 | [FMT_D8] = { 24, 24 }, | 101 | [FMT_D8] = { 24, 24 }, |
105 | [FMT_D9] = { 24, 32 }, | 102 | [FMT_D9] = { 24, 32 }, |
103 | [FMT_D10] = { 32, 0 }, | ||
106 | }; | 104 | }; |
107 | 105 | ||
108 | enum value_id { | 106 | enum value_id { |
@@ -128,9 +126,14 @@ enum value_id { | |||
128 | SD24, /* 24-bit signed displacement */ | 126 | SD24, /* 24-bit signed displacement */ |
129 | SIMM4_2, /* 4-bit signed displacement in opcode bits 4-7 */ | 127 | SIMM4_2, /* 4-bit signed displacement in opcode bits 4-7 */ |
130 | SIMM8, /* 8-bit signed immediate */ | 128 | SIMM8, /* 8-bit signed immediate */ |
129 | IMM8, /* 8-bit unsigned immediate */ | ||
130 | IMM16, /* 16-bit unsigned immediate */ | ||
131 | IMM24, /* 24-bit unsigned immediate */ | 131 | IMM24, /* 24-bit unsigned immediate */ |
132 | IMM32, /* 32-bit unsigned immediate */ | 132 | IMM32, /* 32-bit unsigned immediate */ |
133 | IMM32_HIGH8, /* 32-bit unsigned immediate, high 8-bits in opcode */ | 133 | IMM32_HIGH8, /* 32-bit unsigned immediate, LSB in opcode */ |
134 | |||
135 | IMM32_MEM, /* 32-bit unsigned displacement */ | ||
136 | IMM32_HIGH8_MEM, /* 32-bit unsigned displacement, LSB in opcode */ | ||
134 | 137 | ||
135 | DN0 = DM0, | 138 | DN0 = DM0, |
136 | DN1 = DM1, | 139 | DN1 = DM1, |
@@ -149,7 +152,7 @@ enum value_id { | |||
149 | }; | 152 | }; |
150 | 153 | ||
151 | struct mn10300_opcode { | 154 | struct mn10300_opcode { |
152 | const char *name; | 155 | const char name[8]; |
153 | u_int32_t opcode; | 156 | u_int32_t opcode; |
154 | u_int32_t opmask; | 157 | u_int32_t opmask; |
155 | unsigned exclusion; | 158 | unsigned exclusion; |
@@ -185,6 +188,10 @@ struct mn10300_opcode { | |||
185 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 188 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
186 | */ | 189 | */ |
187 | static const struct mn10300_opcode mn10300_opcodes[] = { | 190 | static const struct mn10300_opcode mn10300_opcodes[] = { |
191 | { "mov", 0x4200, 0xf300, 0, FMT_S1, 0, {DM1, MEM2(IMM8, SP)}}, | ||
192 | { "mov", 0x4300, 0xf300, 0, FMT_S1, 0, {AM1, MEM2(IMM8, SP)}}, | ||
193 | { "mov", 0x5800, 0xfc00, 0, FMT_S1, 0, {MEM2(IMM8, SP), DN0}}, | ||
194 | { "mov", 0x5c00, 0xfc00, 0, FMT_S1, 0, {MEM2(IMM8, SP), AN0}}, | ||
188 | { "mov", 0x60, 0xf0, 0, FMT_S0, 0, {DM1, MEM(AN0)}}, | 195 | { "mov", 0x60, 0xf0, 0, FMT_S0, 0, {DM1, MEM(AN0)}}, |
189 | { "mov", 0x70, 0xf0, 0, FMT_S0, 0, {MEM(AM0), DN1}}, | 196 | { "mov", 0x70, 0xf0, 0, FMT_S0, 0, {MEM(AM0), DN1}}, |
190 | { "mov", 0xf000, 0xfff0, 0, FMT_D0, 0, {MEM(AM0), AN1}}, | 197 | { "mov", 0xf000, 0xfff0, 0, FMT_D0, 0, {MEM(AM0), AN1}}, |
@@ -197,8 +204,6 @@ static const struct mn10300_opcode mn10300_opcodes[] = { | |||
197 | { "mov", 0xf81000, 0xfff000, 0, FMT_D1, 0, {DM1, MEM2(SD8, AN0)}}, | 204 | { "mov", 0xf81000, 0xfff000, 0, FMT_D1, 0, {DM1, MEM2(SD8, AN0)}}, |
198 | { "mov", 0xf82000, 0xfff000, 0, FMT_D1, 0, {MEM2(SD8,AM0), AN1}}, | 205 | { "mov", 0xf82000, 0xfff000, 0, FMT_D1, 0, {MEM2(SD8,AM0), AN1}}, |
199 | { "mov", 0xf83000, 0xfff000, 0, FMT_D1, 0, {AM1, MEM2(SD8, AN0)}}, | 206 | { "mov", 0xf83000, 0xfff000, 0, FMT_D1, 0, {AM1, MEM2(SD8, AN0)}}, |
200 | { "mov", 0xf8f000, 0xfffc00, 0, FMT_D1, AM33, {MEM2(SD8, AM0), SP}}, | ||
201 | { "mov", 0xf8f400, 0xfffc00, 0, FMT_D1, AM33, {SP, MEM2(SD8, AN0)}}, | ||
202 | { "mov", 0xf90a00, 0xffff00, 0, FMT_D6, AM33, {MEM(RM0), RN2}}, | 207 | { "mov", 0xf90a00, 0xffff00, 0, FMT_D6, AM33, {MEM(RM0), RN2}}, |
203 | { "mov", 0xf91a00, 0xffff00, 0, FMT_D6, AM33, {RM2, MEM(RN0)}}, | 208 | { "mov", 0xf91a00, 0xffff00, 0, FMT_D6, AM33, {RM2, MEM(RN0)}}, |
204 | { "mov", 0xf96a00, 0xffff00, 0x12, FMT_D6, AM33, {MEMINC(RM0), RN2}}, | 209 | { "mov", 0xf96a00, 0xffff00, 0x12, FMT_D6, AM33, {MEMINC(RM0), RN2}}, |
@@ -207,24 +212,46 @@ static const struct mn10300_opcode mn10300_opcodes[] = { | |||
207 | { "mov", 0xfa100000, 0xfff00000, 0, FMT_D2, 0, {DM1, MEM2(SD16, AN0)}}, | 212 | { "mov", 0xfa100000, 0xfff00000, 0, FMT_D2, 0, {DM1, MEM2(SD16, AN0)}}, |
208 | { "mov", 0xfa200000, 0xfff00000, 0, FMT_D2, 0, {MEM2(SD16, AM0), AN1}}, | 213 | { "mov", 0xfa200000, 0xfff00000, 0, FMT_D2, 0, {MEM2(SD16, AM0), AN1}}, |
209 | { "mov", 0xfa300000, 0xfff00000, 0, FMT_D2, 0, {AM1, MEM2(SD16, AN0)}}, | 214 | { "mov", 0xfa300000, 0xfff00000, 0, FMT_D2, 0, {AM1, MEM2(SD16, AN0)}}, |
215 | { "mov", 0xfa900000, 0xfff30000, 0, FMT_D2, 0, {AM1, MEM2(IMM16, SP)}}, | ||
216 | { "mov", 0xfa910000, 0xfff30000, 0, FMT_D2, 0, {DM1, MEM2(IMM16, SP)}}, | ||
217 | { "mov", 0xfab00000, 0xfffc0000, 0, FMT_D2, 0, {MEM2(IMM16, SP), AN0}}, | ||
218 | { "mov", 0xfab40000, 0xfffc0000, 0, FMT_D2, 0, {MEM2(IMM16, SP), DN0}}, | ||
210 | { "mov", 0xfb0a0000, 0xffff0000, 0, FMT_D7, AM33, {MEM2(SD8, RM0), RN2}}, | 219 | { "mov", 0xfb0a0000, 0xffff0000, 0, FMT_D7, AM33, {MEM2(SD8, RM0), RN2}}, |
211 | { "mov", 0xfb1a0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEM2(SD8, RN0)}}, | 220 | { "mov", 0xfb1a0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEM2(SD8, RN0)}}, |
212 | { "mov", 0xfb6a0000, 0xffff0000, 0x22, FMT_D7, AM33, {MEMINC2 (RM0, SIMM8), RN2}}, | 221 | { "mov", 0xfb6a0000, 0xffff0000, 0x22, FMT_D7, AM33, {MEMINC2 (RM0, SIMM8), RN2}}, |
213 | { "mov", 0xfb7a0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEMINC2 (RN0, SIMM8)}}, | 222 | { "mov", 0xfb7a0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEMINC2 (RN0, SIMM8)}}, |
223 | { "mov", 0xfb8a0000, 0xffff0f00, 0, FMT_D7, AM33, {MEM2(IMM8, SP), RN2}}, | ||
214 | { "mov", 0xfb8e0000, 0xffff000f, 0, FMT_D7, AM33, {MEM2(RI, RM0), RD2}}, | 224 | { "mov", 0xfb8e0000, 0xffff000f, 0, FMT_D7, AM33, {MEM2(RI, RM0), RD2}}, |
225 | { "mov", 0xfb9a0000, 0xffff0f00, 0, FMT_D7, AM33, {RM2, MEM2(IMM8, SP)}}, | ||
215 | { "mov", 0xfb9e0000, 0xffff000f, 0, FMT_D7, AM33, {RD2, MEM2(RI, RN0)}}, | 226 | { "mov", 0xfb9e0000, 0xffff000f, 0, FMT_D7, AM33, {RD2, MEM2(RI, RN0)}}, |
216 | { "mov", 0xfc000000, 0xfff00000, 0, FMT_D4, 0, {MEM2(IMM32,AM0), DN1}}, | 227 | { "mov", 0xfc000000, 0xfff00000, 0, FMT_D4, 0, {MEM2(IMM32,AM0), DN1}}, |
217 | { "mov", 0xfc100000, 0xfff00000, 0, FMT_D4, 0, {DM1, MEM2(IMM32,AN0)}}, | 228 | { "mov", 0xfc100000, 0xfff00000, 0, FMT_D4, 0, {DM1, MEM2(IMM32,AN0)}}, |
218 | { "mov", 0xfc200000, 0xfff00000, 0, FMT_D4, 0, {MEM2(IMM32,AM0), AN1}}, | 229 | { "mov", 0xfc200000, 0xfff00000, 0, FMT_D4, 0, {MEM2(IMM32,AM0), AN1}}, |
219 | { "mov", 0xfc300000, 0xfff00000, 0, FMT_D4, 0, {AM1, MEM2(IMM32,AN0)}}, | 230 | { "mov", 0xfc300000, 0xfff00000, 0, FMT_D4, 0, {AM1, MEM2(IMM32,AN0)}}, |
231 | { "mov", 0xfc800000, 0xfff30000, 0, FMT_D4, 0, {AM1, MEM(IMM32_MEM)}}, | ||
232 | { "mov", 0xfc810000, 0xfff30000, 0, FMT_D4, 0, {DM1, MEM(IMM32_MEM)}}, | ||
233 | { "mov", 0xfc900000, 0xfff30000, 0, FMT_D4, 0, {AM1, MEM2(IMM32, SP)}}, | ||
234 | { "mov", 0xfc910000, 0xfff30000, 0, FMT_D4, 0, {DM1, MEM2(IMM32, SP)}}, | ||
235 | { "mov", 0xfca00000, 0xfffc0000, 0, FMT_D4, 0, {MEM(IMM32_MEM), AN0}}, | ||
236 | { "mov", 0xfca40000, 0xfffc0000, 0, FMT_D4, 0, {MEM(IMM32_MEM), DN0}}, | ||
237 | { "mov", 0xfcb00000, 0xfffc0000, 0, FMT_D4, 0, {MEM2(IMM32, SP), AN0}}, | ||
238 | { "mov", 0xfcb40000, 0xfffc0000, 0, FMT_D4, 0, {MEM2(IMM32, SP), DN0}}, | ||
220 | { "mov", 0xfd0a0000, 0xffff0000, 0, FMT_D8, AM33, {MEM2(SD24, RM0), RN2}}, | 239 | { "mov", 0xfd0a0000, 0xffff0000, 0, FMT_D8, AM33, {MEM2(SD24, RM0), RN2}}, |
221 | { "mov", 0xfd1a0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEM2(SD24, RN0)}}, | 240 | { "mov", 0xfd1a0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEM2(SD24, RN0)}}, |
222 | { "mov", 0xfd6a0000, 0xffff0000, 0x22, FMT_D8, AM33, {MEMINC2 (RM0, IMM24), RN2}}, | 241 | { "mov", 0xfd6a0000, 0xffff0000, 0x22, FMT_D8, AM33, {MEMINC2 (RM0, IMM24), RN2}}, |
223 | { "mov", 0xfd7a0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEMINC2 (RN0, IMM24)}}, | 242 | { "mov", 0xfd7a0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEMINC2 (RN0, IMM24)}}, |
243 | { "mov", 0xfd8a0000, 0xffff0f00, 0, FMT_D8, AM33, {MEM2(IMM24, SP), RN2}}, | ||
244 | { "mov", 0xfd9a0000, 0xffff0f00, 0, FMT_D8, AM33, {RM2, MEM2(IMM24, SP)}}, | ||
224 | { "mov", 0xfe0a0000, 0xffff0000, 0, FMT_D9, AM33, {MEM2(IMM32_HIGH8,RM0), RN2}}, | 245 | { "mov", 0xfe0a0000, 0xffff0000, 0, FMT_D9, AM33, {MEM2(IMM32_HIGH8,RM0), RN2}}, |
246 | { "mov", 0xfe0a0000, 0xffff0000, 0, FMT_D9, AM33, {MEM2(IMM32_HIGH8,RM0), RN2}}, | ||
247 | { "mov", 0xfe0e0000, 0xffff0f00, 0, FMT_D9, AM33, {MEM(IMM32_HIGH8_MEM), RN2}}, | ||
248 | { "mov", 0xfe1a0000, 0xffff0000, 0, FMT_D9, AM33, {RM2, MEM2(IMM32_HIGH8, RN0)}}, | ||
225 | { "mov", 0xfe1a0000, 0xffff0000, 0, FMT_D9, AM33, {RM2, MEM2(IMM32_HIGH8, RN0)}}, | 249 | { "mov", 0xfe1a0000, 0xffff0000, 0, FMT_D9, AM33, {RM2, MEM2(IMM32_HIGH8, RN0)}}, |
250 | { "mov", 0xfe1e0000, 0xffff0f00, 0, FMT_D9, AM33, {RM2, MEM(IMM32_HIGH8_MEM)}}, | ||
226 | { "mov", 0xfe6a0000, 0xffff0000, 0x22, FMT_D9, AM33, {MEMINC2 (RM0, IMM32_HIGH8), RN2}}, | 251 | { "mov", 0xfe6a0000, 0xffff0000, 0x22, FMT_D9, AM33, {MEMINC2 (RM0, IMM32_HIGH8), RN2}}, |
227 | { "mov", 0xfe7a0000, 0xffff0000, 0, FMT_D9, AM33, {RN2, MEMINC2 (RM0, IMM32_HIGH8)}}, | 252 | { "mov", 0xfe7a0000, 0xffff0000, 0, FMT_D9, AM33, {RN2, MEMINC2 (RM0, IMM32_HIGH8)}}, |
253 | { "mov", 0xfe8a0000, 0xffff0f00, 0, FMT_D9, AM33, {MEM2(IMM32_HIGH8, SP), RN2}}, | ||
254 | { "mov", 0xfe9a0000, 0xffff0f00, 0, FMT_D9, AM33, {RM2, MEM2(IMM32_HIGH8, SP)}}, | ||
228 | 255 | ||
229 | { "movhu", 0xf060, 0xfff0, 0, FMT_D0, 0, {MEM(AM0), DN1}}, | 256 | { "movhu", 0xf060, 0xfff0, 0, FMT_D0, 0, {MEM(AM0), DN1}}, |
230 | { "movhu", 0xf070, 0xfff0, 0, FMT_D0, 0, {DM1, MEM(AN0)}}, | 257 | { "movhu", 0xf070, 0xfff0, 0, FMT_D0, 0, {DM1, MEM(AN0)}}, |
@@ -232,29 +259,58 @@ static const struct mn10300_opcode mn10300_opcodes[] = { | |||
232 | { "movhu", 0xf4c0, 0xffc0, 0, FMT_D0, 0, {DM2, MEM2(DI, AN0)}}, | 259 | { "movhu", 0xf4c0, 0xffc0, 0, FMT_D0, 0, {DM2, MEM2(DI, AN0)}}, |
233 | { "movhu", 0xf86000, 0xfff000, 0, FMT_D1, 0, {MEM2(SD8, AM0), DN1}}, | 260 | { "movhu", 0xf86000, 0xfff000, 0, FMT_D1, 0, {MEM2(SD8, AM0), DN1}}, |
234 | { "movhu", 0xf87000, 0xfff000, 0, FMT_D1, 0, {DM1, MEM2(SD8, AN0)}}, | 261 | { "movhu", 0xf87000, 0xfff000, 0, FMT_D1, 0, {DM1, MEM2(SD8, AN0)}}, |
262 | { "movhu", 0xf89300, 0xfff300, 0, FMT_D1, 0, {DM1, MEM2(IMM8, SP)}}, | ||
263 | { "movhu", 0xf8bc00, 0xfffc00, 0, FMT_D1, 0, {MEM2(IMM8, SP), DN0}}, | ||
235 | { "movhu", 0xf94a00, 0xffff00, 0, FMT_D6, AM33, {MEM(RM0), RN2}}, | 264 | { "movhu", 0xf94a00, 0xffff00, 0, FMT_D6, AM33, {MEM(RM0), RN2}}, |
236 | { "movhu", 0xf95a00, 0xffff00, 0, FMT_D6, AM33, {RM2, MEM(RN0)}}, | 265 | { "movhu", 0xf95a00, 0xffff00, 0, FMT_D6, AM33, {RM2, MEM(RN0)}}, |
237 | { "movhu", 0xf9ea00, 0xffff00, 0x12, FMT_D6, AM33, {MEMINC(RM0), RN2}}, | 266 | { "movhu", 0xf9ea00, 0xffff00, 0x12, FMT_D6, AM33, {MEMINC(RM0), RN2}}, |
238 | { "movhu", 0xf9fa00, 0xffff00, 0, FMT_D6, AM33, {RM2, MEMINC(RN0)}}, | 267 | { "movhu", 0xf9fa00, 0xffff00, 0, FMT_D6, AM33, {RM2, MEMINC(RN0)}}, |
239 | { "movhu", 0xfa600000, 0xfff00000, 0, FMT_D2, 0, {MEM2(SD16, AM0), DN1}}, | 268 | { "movhu", 0xfa600000, 0xfff00000, 0, FMT_D2, 0, {MEM2(SD16, AM0), DN1}}, |
240 | { "movhu", 0xfa700000, 0xfff00000, 0, FMT_D2, 0, {DM1, MEM2(SD16, AN0)}}, | 269 | { "movhu", 0xfa700000, 0xfff00000, 0, FMT_D2, 0, {DM1, MEM2(SD16, AN0)}}, |
270 | { "movhu", 0xfa930000, 0xfff30000, 0, FMT_D2, 0, {DM1, MEM2(IMM16, SP)}}, | ||
271 | { "movhu", 0xfabc0000, 0xfffc0000, 0, FMT_D2, 0, {MEM2(IMM16, SP), DN0}}, | ||
241 | { "movhu", 0xfb4a0000, 0xffff0000, 0, FMT_D7, AM33, {MEM2(SD8, RM0), RN2}}, | 272 | { "movhu", 0xfb4a0000, 0xffff0000, 0, FMT_D7, AM33, {MEM2(SD8, RM0), RN2}}, |
242 | { "movhu", 0xfb5a0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEM2(SD8, RN0)}}, | 273 | { "movhu", 0xfb5a0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEM2(SD8, RN0)}}, |
274 | { "movhu", 0xfbca0000, 0xffff0f00, 0, FMT_D7, AM33, {MEM2(IMM8, SP), RN2}}, | ||
243 | { "movhu", 0xfbce0000, 0xffff000f, 0, FMT_D7, AM33, {MEM2(RI, RM0), RD2}}, | 275 | { "movhu", 0xfbce0000, 0xffff000f, 0, FMT_D7, AM33, {MEM2(RI, RM0), RD2}}, |
276 | { "movhu", 0xfbda0000, 0xffff0f00, 0, FMT_D7, AM33, {RM2, MEM2(IMM8, SP)}}, | ||
244 | { "movhu", 0xfbde0000, 0xffff000f, 0, FMT_D7, AM33, {RD2, MEM2(RI, RN0)}}, | 277 | { "movhu", 0xfbde0000, 0xffff000f, 0, FMT_D7, AM33, {RD2, MEM2(RI, RN0)}}, |
245 | { "movhu", 0xfbea0000, 0xffff0000, 0x22, FMT_D7, AM33, {MEMINC2 (RM0, SIMM8), RN2}}, | 278 | { "movhu", 0xfbea0000, 0xffff0000, 0x22, FMT_D7, AM33, {MEMINC2 (RM0, SIMM8), RN2}}, |
246 | { "movhu", 0xfbfa0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEMINC2 (RN0, SIMM8)}}, | 279 | { "movhu", 0xfbfa0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEMINC2 (RN0, SIMM8)}}, |
247 | { "movhu", 0xfc600000, 0xfff00000, 0, FMT_D4, 0, {MEM2(IMM32,AM0), DN1}}, | 280 | { "movhu", 0xfc600000, 0xfff00000, 0, FMT_D4, 0, {MEM2(IMM32,AM0), DN1}}, |
248 | { "movhu", 0xfc700000, 0xfff00000, 0, FMT_D4, 0, {DM1, MEM2(IMM32,AN0)}}, | 281 | { "movhu", 0xfc700000, 0xfff00000, 0, FMT_D4, 0, {DM1, MEM2(IMM32,AN0)}}, |
282 | { "movhu", 0xfc830000, 0xfff30000, 0, FMT_D4, 0, {DM1, MEM(IMM32_MEM)}}, | ||
283 | { "movhu", 0xfc930000, 0xfff30000, 0, FMT_D4, 0, {DM1, MEM2(IMM32, SP)}}, | ||
284 | { "movhu", 0xfcac0000, 0xfffc0000, 0, FMT_D4, 0, {MEM(IMM32_MEM), DN0}}, | ||
285 | { "movhu", 0xfcbc0000, 0xfffc0000, 0, FMT_D4, 0, {MEM2(IMM32, SP), DN0}}, | ||
249 | { "movhu", 0xfd4a0000, 0xffff0000, 0, FMT_D8, AM33, {MEM2(SD24, RM0), RN2}}, | 286 | { "movhu", 0xfd4a0000, 0xffff0000, 0, FMT_D8, AM33, {MEM2(SD24, RM0), RN2}}, |
250 | { "movhu", 0xfd5a0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEM2(SD24, RN0)}}, | 287 | { "movhu", 0xfd5a0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEM2(SD24, RN0)}}, |
288 | { "movhu", 0xfdca0000, 0xffff0f00, 0, FMT_D8, AM33, {MEM2(IMM24, SP), RN2}}, | ||
289 | { "movhu", 0xfdda0000, 0xffff0f00, 0, FMT_D8, AM33, {RM2, MEM2(IMM24, SP)}}, | ||
251 | { "movhu", 0xfdea0000, 0xffff0000, 0x22, FMT_D8, AM33, {MEMINC2 (RM0, IMM24), RN2}}, | 290 | { "movhu", 0xfdea0000, 0xffff0000, 0x22, FMT_D8, AM33, {MEMINC2 (RM0, IMM24), RN2}}, |
252 | { "movhu", 0xfdfa0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEMINC2 (RN0, IMM24)}}, | 291 | { "movhu", 0xfdfa0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEMINC2 (RN0, IMM24)}}, |
253 | { "movhu", 0xfe4a0000, 0xffff0000, 0, FMT_D9, AM33, {MEM2(IMM32_HIGH8,RM0), RN2}}, | 292 | { "movhu", 0xfe4a0000, 0xffff0000, 0, FMT_D9, AM33, {MEM2(IMM32_HIGH8,RM0), RN2}}, |
293 | { "movhu", 0xfe4e0000, 0xffff0f00, 0, FMT_D9, AM33, {MEM(IMM32_HIGH8_MEM), RN2}}, | ||
254 | { "movhu", 0xfe5a0000, 0xffff0000, 0, FMT_D9, AM33, {RM2, MEM2(IMM32_HIGH8, RN0)}}, | 294 | { "movhu", 0xfe5a0000, 0xffff0000, 0, FMT_D9, AM33, {RM2, MEM2(IMM32_HIGH8, RN0)}}, |
295 | { "movhu", 0xfe5e0000, 0xffff0f00, 0, FMT_D9, AM33, {RM2, MEM(IMM32_HIGH8_MEM)}}, | ||
296 | { "movhu", 0xfeca0000, 0xffff0f00, 0, FMT_D9, AM33, {MEM2(IMM32_HIGH8, SP), RN2}}, | ||
297 | { "movhu", 0xfeda0000, 0xffff0f00, 0, FMT_D9, AM33, {RM2, MEM2(IMM32_HIGH8, SP)}}, | ||
255 | { "movhu", 0xfeea0000, 0xffff0000, 0x22, FMT_D9, AM33, {MEMINC2 (RM0, IMM32_HIGH8), RN2}}, | 298 | { "movhu", 0xfeea0000, 0xffff0000, 0x22, FMT_D9, AM33, {MEMINC2 (RM0, IMM32_HIGH8), RN2}}, |
256 | { "movhu", 0xfefa0000, 0xffff0000, 0, FMT_D9, AM33, {RN2, MEMINC2 (RM0, IMM32_HIGH8)}}, | 299 | { "movhu", 0xfefa0000, 0xffff0000, 0, FMT_D9, AM33, {RN2, MEMINC2 (RM0, IMM32_HIGH8)}}, |
257 | { 0, 0, 0, 0, 0, 0, {0}}, | 300 | |
301 | { "mov_llt", 0xf7e00000, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}}, | ||
302 | { "mov_lgt", 0xf7e00001, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}}, | ||
303 | { "mov_lge", 0xf7e00002, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}}, | ||
304 | { "mov_lle", 0xf7e00003, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}}, | ||
305 | { "mov_lcs", 0xf7e00004, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}}, | ||
306 | { "mov_lhi", 0xf7e00005, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}}, | ||
307 | { "mov_lcc", 0xf7e00006, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}}, | ||
308 | { "mov_lls", 0xf7e00007, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}}, | ||
309 | { "mov_leq", 0xf7e00008, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}}, | ||
310 | { "mov_lne", 0xf7e00009, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}}, | ||
311 | { "mov_lra", 0xf7e0000a, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}}, | ||
312 | |||
313 | { "", 0, 0, 0, 0, 0, {0}}, | ||
258 | }; | 314 | }; |
259 | 315 | ||
260 | /* | 316 | /* |
@@ -265,18 +321,21 @@ asmlinkage void misalignment(struct pt_regs *regs, enum exception_code code) | |||
265 | const struct exception_table_entry *fixup; | 321 | const struct exception_table_entry *fixup; |
266 | const struct mn10300_opcode *pop; | 322 | const struct mn10300_opcode *pop; |
267 | unsigned long *registers = (unsigned long *) regs; | 323 | unsigned long *registers = (unsigned long *) regs; |
268 | unsigned long data, *store, *postinc; | 324 | unsigned long data, *store, *postinc, disp, inc, sp; |
269 | mm_segment_t seg; | 325 | mm_segment_t seg; |
270 | siginfo_t info; | 326 | siginfo_t info; |
271 | uint32_t opcode, disp, noc, xo, xm; | 327 | uint32_t opcode, noc, xo, xm; |
272 | uint8_t *pc, byte; | 328 | uint8_t *pc, byte, datasz; |
273 | void *address; | 329 | void *address; |
274 | unsigned tmp, npop; | 330 | unsigned tmp, npop, dispsz, loop; |
331 | |||
332 | /* we don't fix up userspace misalignment faults */ | ||
333 | if (user_mode(regs)) | ||
334 | goto bus_error; | ||
275 | 335 | ||
276 | kdebug("MISALIGN at %lx\n", regs->pc); | 336 | sp = (unsigned long) regs + sizeof(*regs); |
277 | 337 | ||
278 | if (in_interrupt()) | 338 | kdebug("==>misalignment({pc=%lx,sp=%lx})", regs->pc, sp); |
279 | die("Misalignment trap in interrupt context", regs, code); | ||
280 | 339 | ||
281 | if (regs->epsw & EPSW_IE) | 340 | if (regs->epsw & EPSW_IE) |
282 | asm volatile("or %0,epsw" : : "i"(EPSW_IE)); | 341 | asm volatile("or %0,epsw" : : "i"(EPSW_IE)); |
@@ -294,8 +353,8 @@ asmlinkage void misalignment(struct pt_regs *regs, enum exception_code code) | |||
294 | opcode = byte; | 353 | opcode = byte; |
295 | noc = 8; | 354 | noc = 8; |
296 | 355 | ||
297 | for (pop = mn10300_opcodes; pop->name; pop++) { | 356 | for (pop = mn10300_opcodes; pop->name[0]; pop++) { |
298 | npop = log2(pop->opcode | pop->opmask); | 357 | npop = ilog2(pop->opcode | pop->opmask); |
299 | if (npop <= 0 || npop > 31) | 358 | if (npop <= 0 || npop > 31) |
300 | continue; | 359 | continue; |
301 | npop = (npop + 8) & ~7; | 360 | npop = (npop + 8) & ~7; |
@@ -328,15 +387,15 @@ asmlinkage void misalignment(struct pt_regs *regs, enum exception_code code) | |||
328 | } | 387 | } |
329 | 388 | ||
330 | /* didn't manage to find a fixup */ | 389 | /* didn't manage to find a fixup */ |
331 | if (!user_mode(regs)) | 390 | printk(KERN_CRIT "MISALIGN: %lx: unsupported instruction %x\n", |
332 | printk(KERN_CRIT "MISALIGN: %lx: unsupported instruction %x\n", | 391 | regs->pc, opcode); |
333 | regs->pc, opcode); | ||
334 | 392 | ||
335 | failed: | 393 | failed: |
336 | set_fs(seg); | 394 | set_fs(seg); |
337 | if (die_if_no_fixup("misalignment error", regs, code)) | 395 | if (die_if_no_fixup("misalignment error", regs, code)) |
338 | return; | 396 | return; |
339 | 397 | ||
398 | bus_error: | ||
340 | info.si_signo = SIGBUS; | 399 | info.si_signo = SIGBUS; |
341 | info.si_errno = 0; | 400 | info.si_errno = 0; |
342 | info.si_code = BUS_ADRALN; | 401 | info.si_code = BUS_ADRALN; |
@@ -346,31 +405,27 @@ failed: | |||
346 | 405 | ||
347 | /* error reading opcodes */ | 406 | /* error reading opcodes */ |
348 | fetch_error: | 407 | fetch_error: |
349 | if (!user_mode(regs)) | 408 | printk(KERN_CRIT |
350 | printk(KERN_CRIT | 409 | "MISALIGN: %p: fault whilst reading instruction data\n", |
351 | "MISALIGN: %p: fault whilst reading instruction data\n", | 410 | pc); |
352 | pc); | ||
353 | goto failed; | 411 | goto failed; |
354 | 412 | ||
355 | bad_addr_mode: | 413 | bad_addr_mode: |
356 | if (!user_mode(regs)) | 414 | printk(KERN_CRIT |
357 | printk(KERN_CRIT | 415 | "MISALIGN: %lx: unsupported addressing mode %x\n", |
358 | "MISALIGN: %lx: unsupported addressing mode %x\n", | 416 | regs->pc, opcode); |
359 | regs->pc, opcode); | ||
360 | goto failed; | 417 | goto failed; |
361 | 418 | ||
362 | bad_reg_mode: | 419 | bad_reg_mode: |
363 | if (!user_mode(regs)) | 420 | printk(KERN_CRIT |
364 | printk(KERN_CRIT | 421 | "MISALIGN: %lx: unsupported register mode %x\n", |
365 | "MISALIGN: %lx: unsupported register mode %x\n", | 422 | regs->pc, opcode); |
366 | regs->pc, opcode); | ||
367 | goto failed; | 423 | goto failed; |
368 | 424 | ||
369 | unsupported_instruction: | 425 | unsupported_instruction: |
370 | if (!user_mode(regs)) | 426 | printk(KERN_CRIT |
371 | printk(KERN_CRIT | 427 | "MISALIGN: %lx: unsupported instruction %x (%s)\n", |
372 | "MISALIGN: %lx: unsupported instruction %x (%s)\n", | 428 | regs->pc, opcode, pop->name); |
373 | regs->pc, opcode, pop->name); | ||
374 | goto failed; | 429 | goto failed; |
375 | 430 | ||
376 | transfer_failed: | 431 | transfer_failed: |
@@ -391,7 +446,7 @@ transfer_failed: | |||
391 | 446 | ||
392 | /* we matched the opcode */ | 447 | /* we matched the opcode */ |
393 | found_opcode: | 448 | found_opcode: |
394 | kdebug("MISALIGN: %lx: %x==%x { %x, %x }\n", | 449 | kdebug("%lx: %x==%x { %x, %x }", |
395 | regs->pc, opcode, pop->opcode, pop->params[0], pop->params[1]); | 450 | regs->pc, opcode, pop->opcode, pop->params[0], pop->params[1]); |
396 | 451 | ||
397 | tmp = format_tbl[pop->format].opsz; | 452 | tmp = format_tbl[pop->format].opsz; |
@@ -406,106 +461,108 @@ found_opcode: | |||
406 | 461 | ||
407 | /* grab the extra displacement (note it's LSB first) */ | 462 | /* grab the extra displacement (note it's LSB first) */ |
408 | disp = 0; | 463 | disp = 0; |
409 | tmp = format_tbl[pop->format].dispsz >> 3; | 464 | dispsz = format_tbl[pop->format].dispsz; |
410 | while (tmp > 0) { | 465 | for (loop = 0; loop < dispsz; loop += 8) { |
411 | tmp--; | ||
412 | disp <<= 8; | ||
413 | |||
414 | pc++; | 466 | pc++; |
415 | if (__get_user(byte, pc) != 0) | 467 | if (__get_user(byte, pc) != 0) |
416 | goto fetch_error; | 468 | goto fetch_error; |
417 | disp |= byte; | 469 | disp |= byte << loop; |
470 | kdebug("{%p} disp[%02x]=%02x", pc, loop, byte); | ||
418 | } | 471 | } |
419 | 472 | ||
473 | kdebug("disp=%lx", disp); | ||
474 | |||
420 | set_fs(KERNEL_XDS); | 475 | set_fs(KERNEL_XDS); |
421 | if (fixup || regs->epsw & EPSW_nSL) | 476 | if (fixup) |
422 | set_fs(seg); | 477 | set_fs(seg); |
423 | 478 | ||
424 | tmp = (pop->params[0] ^ pop->params[1]) & 0x80000000; | 479 | tmp = (pop->params[0] ^ pop->params[1]) & 0x80000000; |
425 | if (!tmp) { | 480 | if (!tmp) { |
426 | if (!user_mode(regs)) | 481 | printk(KERN_CRIT |
427 | printk(KERN_CRIT | 482 | "MISALIGN: %lx: insn not move to/from memory %x\n", |
428 | "MISALIGN: %lx:" | 483 | regs->pc, opcode); |
429 | " insn not move to/from memory %x\n", | ||
430 | regs->pc, opcode); | ||
431 | goto failed; | 484 | goto failed; |
432 | } | 485 | } |
433 | 486 | ||
487 | /* determine the data transfer size of the move */ | ||
488 | if (pop->name[3] == 0 || /* "mov" */ | ||
489 | pop->name[4] == 'l') /* mov_lcc */ | ||
490 | inc = datasz = 4; | ||
491 | else if (pop->name[3] == 'h') /* movhu */ | ||
492 | inc = datasz = 2; | ||
493 | else | ||
494 | goto unsupported_instruction; | ||
495 | |||
434 | if (pop->params[0] & 0x80000000) { | 496 | if (pop->params[0] & 0x80000000) { |
435 | /* move memory to register */ | 497 | /* move memory to register */ |
436 | if (!misalignment_addr(registers, pop->params[0], opcode, disp, | 498 | if (!misalignment_addr(registers, sp, |
437 | &address, &postinc)) | 499 | pop->params[0], opcode, disp, |
500 | &address, &postinc, &inc)) | ||
438 | goto bad_addr_mode; | 501 | goto bad_addr_mode; |
439 | 502 | ||
440 | if (!misalignment_reg(registers, pop->params[1], opcode, disp, | 503 | if (!misalignment_reg(registers, pop->params[1], opcode, disp, |
441 | &store)) | 504 | &store)) |
442 | goto bad_reg_mode; | 505 | goto bad_reg_mode; |
443 | 506 | ||
444 | if (strcmp(pop->name, "mov") == 0) { | 507 | kdebug("mov%u (%p),DARn", datasz, address); |
445 | kdebug("FIXUP: mov (%p),DARn\n", address); | 508 | if (copy_from_user(&data, (void *) address, datasz) != 0) |
446 | if (copy_from_user(&data, (void *) address, 4) != 0) | 509 | goto transfer_failed; |
447 | goto transfer_failed; | 510 | if (pop->params[0] & 0x1000000) { |
448 | if (pop->params[0] & 0x1000000) | 511 | kdebug("inc=%lx", inc); |
449 | *postinc += 4; | 512 | *postinc += inc; |
450 | } else if (strcmp(pop->name, "movhu") == 0) { | ||
451 | kdebug("FIXUP: movhu (%p),DARn\n", address); | ||
452 | data = 0; | ||
453 | if (copy_from_user(&data, (void *) address, 2) != 0) | ||
454 | goto transfer_failed; | ||
455 | if (pop->params[0] & 0x1000000) | ||
456 | *postinc += 2; | ||
457 | } else { | ||
458 | goto unsupported_instruction; | ||
459 | } | 513 | } |
460 | 514 | ||
461 | *store = data; | 515 | *store = data; |
516 | kdebug("loaded %lx", data); | ||
462 | } else { | 517 | } else { |
463 | /* move register to memory */ | 518 | /* move register to memory */ |
464 | if (!misalignment_reg(registers, pop->params[0], opcode, disp, | 519 | if (!misalignment_reg(registers, pop->params[0], opcode, disp, |
465 | &store)) | 520 | &store)) |
466 | goto bad_reg_mode; | 521 | goto bad_reg_mode; |
467 | 522 | ||
468 | if (!misalignment_addr(registers, pop->params[1], opcode, disp, | 523 | if (!misalignment_addr(registers, sp, |
469 | &address, &postinc)) | 524 | pop->params[1], opcode, disp, |
525 | &address, &postinc, &inc)) | ||
470 | goto bad_addr_mode; | 526 | goto bad_addr_mode; |
471 | 527 | ||
472 | data = *store; | 528 | data = *store; |
473 | 529 | ||
474 | if (strcmp(pop->name, "mov") == 0) { | 530 | kdebug("mov%u %lx,(%p)", datasz, data, address); |
475 | kdebug("FIXUP: mov %lx,(%p)\n", data, address); | 531 | if (copy_to_user((void *) address, &data, datasz) != 0) |
476 | if (copy_to_user((void *) address, &data, 4) != 0) | 532 | goto transfer_failed; |
477 | goto transfer_failed; | 533 | if (pop->params[1] & 0x1000000) |
478 | if (pop->params[1] & 0x1000000) | 534 | *postinc += inc; |
479 | *postinc += 4; | ||
480 | } else if (strcmp(pop->name, "movhu") == 0) { | ||
481 | kdebug("FIXUP: movhu %hx,(%p)\n", | ||
482 | (uint16_t) data, address); | ||
483 | if (copy_to_user((void *) address, &data, 2) != 0) | ||
484 | goto transfer_failed; | ||
485 | if (pop->params[1] & 0x1000000) | ||
486 | *postinc += 2; | ||
487 | } else { | ||
488 | goto unsupported_instruction; | ||
489 | } | ||
490 | } | 535 | } |
491 | 536 | ||
492 | tmp = format_tbl[pop->format].opsz + format_tbl[pop->format].dispsz; | 537 | tmp = format_tbl[pop->format].opsz + format_tbl[pop->format].dispsz; |
493 | regs->pc += tmp >> 3; | 538 | regs->pc += tmp >> 3; |
494 | 539 | ||
540 | /* handle MOV_Lcc, which are currently the only FMT_D10 insns that | ||
541 | * access memory */ | ||
542 | if (pop->format == FMT_D10) | ||
543 | misalignment_MOV_Lcc(regs, opcode); | ||
544 | |||
495 | set_fs(seg); | 545 | set_fs(seg); |
496 | return; | ||
497 | } | 546 | } |
498 | 547 | ||
499 | /* | 548 | /* |
500 | * determine the address that was being accessed | 549 | * determine the address that was being accessed |
501 | */ | 550 | */ |
502 | static int misalignment_addr(unsigned long *registers, unsigned params, | 551 | static int misalignment_addr(unsigned long *registers, unsigned long sp, |
503 | unsigned opcode, unsigned disp, | 552 | unsigned params, unsigned opcode, |
504 | void **_address, unsigned long **_postinc) | 553 | unsigned long disp, |
554 | void **_address, unsigned long **_postinc, | ||
555 | unsigned long *_inc) | ||
505 | { | 556 | { |
506 | unsigned long *postinc = NULL, address = 0, tmp; | 557 | unsigned long *postinc = NULL, address = 0, tmp; |
507 | 558 | ||
508 | params &= 0x7fffffff; | 559 | if (!(params & 0x1000000)) { |
560 | kdebug("noinc"); | ||
561 | *_inc = 0; | ||
562 | _inc = NULL; | ||
563 | } | ||
564 | |||
565 | params &= 0x00ffffff; | ||
509 | 566 | ||
510 | do { | 567 | do { |
511 | switch (params & 0xff) { | 568 | switch (params & 0xff) { |
@@ -514,11 +571,11 @@ static int misalignment_addr(unsigned long *registers, unsigned params, | |||
514 | address += *postinc; | 571 | address += *postinc; |
515 | break; | 572 | break; |
516 | case DM1: | 573 | case DM1: |
517 | postinc = ®isters[Dreg_index[opcode >> 2 & 0x0c]]; | 574 | postinc = ®isters[Dreg_index[opcode >> 2 & 0x03]]; |
518 | address += *postinc; | 575 | address += *postinc; |
519 | break; | 576 | break; |
520 | case DM2: | 577 | case DM2: |
521 | postinc = ®isters[Dreg_index[opcode >> 4 & 0x30]]; | 578 | postinc = ®isters[Dreg_index[opcode >> 4 & 0x03]]; |
522 | address += *postinc; | 579 | address += *postinc; |
523 | break; | 580 | break; |
524 | case AM0: | 581 | case AM0: |
@@ -526,11 +583,11 @@ static int misalignment_addr(unsigned long *registers, unsigned params, | |||
526 | address += *postinc; | 583 | address += *postinc; |
527 | break; | 584 | break; |
528 | case AM1: | 585 | case AM1: |
529 | postinc = ®isters[Areg_index[opcode >> 2 & 0x0c]]; | 586 | postinc = ®isters[Areg_index[opcode >> 2 & 0x03]]; |
530 | address += *postinc; | 587 | address += *postinc; |
531 | break; | 588 | break; |
532 | case AM2: | 589 | case AM2: |
533 | postinc = ®isters[Areg_index[opcode >> 4 & 0x30]]; | 590 | postinc = ®isters[Areg_index[opcode >> 4 & 0x03]]; |
534 | address += *postinc; | 591 | address += *postinc; |
535 | break; | 592 | break; |
536 | case RM0: | 593 | case RM0: |
@@ -561,33 +618,53 @@ static int misalignment_addr(unsigned long *registers, unsigned params, | |||
561 | postinc = ®isters[Rreg_index[disp >> 4 & 0x0f]]; | 618 | postinc = ®isters[Rreg_index[disp >> 4 & 0x0f]]; |
562 | address += *postinc; | 619 | address += *postinc; |
563 | break; | 620 | break; |
621 | case SP: | ||
622 | address += sp; | ||
623 | break; | ||
564 | 624 | ||
625 | /* displacements are either to be added to the address | ||
626 | * before use, or, in the case of post-inc addressing, | ||
627 | * to be added into the base register after use */ | ||
565 | case SD8: | 628 | case SD8: |
566 | case SIMM8: | 629 | case SIMM8: |
567 | address += (int32_t) (int8_t) (disp & 0xff); | 630 | disp = (long) (int8_t) (disp & 0xff); |
568 | break; | 631 | goto displace_or_inc; |
569 | case SD16: | 632 | case SD16: |
570 | address += (int32_t) (int16_t) (disp & 0xffff); | 633 | disp = (long) (int16_t) (disp & 0xffff); |
571 | break; | 634 | goto displace_or_inc; |
572 | case SD24: | 635 | case SD24: |
573 | tmp = disp << 8; | 636 | tmp = disp << 8; |
574 | asm("asr 8,%0" : "=r"(tmp) : "0"(tmp)); | 637 | asm("asr 8,%0" : "=r"(tmp) : "0"(tmp)); |
575 | address += tmp; | 638 | disp = (long) tmp; |
576 | break; | 639 | goto displace_or_inc; |
577 | case SIMM4_2: | 640 | case SIMM4_2: |
578 | tmp = opcode >> 4 & 0x0f; | 641 | tmp = opcode >> 4 & 0x0f; |
579 | tmp <<= 28; | 642 | tmp <<= 28; |
580 | asm("asr 28,%0" : "=r"(tmp) : "0"(tmp)); | 643 | asm("asr 28,%0" : "=r"(tmp) : "0"(tmp)); |
581 | address += tmp; | 644 | disp = (long) tmp; |
582 | break; | 645 | goto displace_or_inc; |
646 | case IMM8: | ||
647 | disp &= 0x000000ff; | ||
648 | goto displace_or_inc; | ||
649 | case IMM16: | ||
650 | disp &= 0x0000ffff; | ||
651 | goto displace_or_inc; | ||
583 | case IMM24: | 652 | case IMM24: |
584 | address += disp & 0x00ffffff; | 653 | disp &= 0x00ffffff; |
585 | break; | 654 | goto displace_or_inc; |
586 | case IMM32: | 655 | case IMM32: |
656 | case IMM32_MEM: | ||
587 | case IMM32_HIGH8: | 657 | case IMM32_HIGH8: |
588 | address += disp; | 658 | case IMM32_HIGH8_MEM: |
659 | displace_or_inc: | ||
660 | kdebug("%s %lx", _inc ? "incr" : "disp", disp); | ||
661 | if (!_inc) | ||
662 | address += disp; | ||
663 | else | ||
664 | *_inc = disp; | ||
589 | break; | 665 | break; |
590 | default: | 666 | default: |
667 | BUG(); | ||
591 | return 0; | 668 | return 0; |
592 | } | 669 | } |
593 | } while ((params >>= 8)); | 670 | } while ((params >>= 8)); |
@@ -601,7 +678,7 @@ static int misalignment_addr(unsigned long *registers, unsigned params, | |||
601 | * determine the register that is acting as source/dest | 678 | * determine the register that is acting as source/dest |
602 | */ | 679 | */ |
603 | static int misalignment_reg(unsigned long *registers, unsigned params, | 680 | static int misalignment_reg(unsigned long *registers, unsigned params, |
604 | unsigned opcode, unsigned disp, | 681 | unsigned opcode, unsigned long disp, |
605 | unsigned long **_register) | 682 | unsigned long **_register) |
606 | { | 683 | { |
607 | params &= 0x7fffffff; | 684 | params &= 0x7fffffff; |
@@ -654,8 +731,239 @@ static int misalignment_reg(unsigned long *registers, unsigned params, | |||
654 | break; | 731 | break; |
655 | 732 | ||
656 | default: | 733 | default: |
734 | BUG(); | ||
657 | return 0; | 735 | return 0; |
658 | } | 736 | } |
659 | 737 | ||
660 | return 1; | 738 | return 1; |
661 | } | 739 | } |
740 | |||
741 | /* | ||
742 | * handle the conditional loop part of the move-and-loop instructions | ||
743 | */ | ||
744 | static void misalignment_MOV_Lcc(struct pt_regs *regs, uint32_t opcode) | ||
745 | { | ||
746 | unsigned long epsw = regs->epsw; | ||
747 | unsigned long NxorV; | ||
748 | |||
749 | kdebug("MOV_Lcc %x [flags=%lx]", opcode, epsw & 0xf); | ||
750 | |||
751 | /* calculate N^V and shift onto the same bit position as Z */ | ||
752 | NxorV = ((epsw >> 3) ^ epsw >> 1) & 1; | ||
753 | |||
754 | switch (opcode & 0xf) { | ||
755 | case 0x0: /* MOV_LLT: N^V */ | ||
756 | if (NxorV) | ||
757 | goto take_the_loop; | ||
758 | return; | ||
759 | case 0x1: /* MOV_LGT: ~(Z or (N^V))*/ | ||
760 | if (!((epsw & EPSW_FLAG_Z) | NxorV)) | ||
761 | goto take_the_loop; | ||
762 | return; | ||
763 | case 0x2: /* MOV_LGE: ~(N^V) */ | ||
764 | if (!NxorV) | ||
765 | goto take_the_loop; | ||
766 | return; | ||
767 | case 0x3: /* MOV_LLE: Z or (N^V) */ | ||
768 | if ((epsw & EPSW_FLAG_Z) | NxorV) | ||
769 | goto take_the_loop; | ||
770 | return; | ||
771 | |||
772 | case 0x4: /* MOV_LCS: C */ | ||
773 | if (epsw & EPSW_FLAG_C) | ||
774 | goto take_the_loop; | ||
775 | return; | ||
776 | case 0x5: /* MOV_LHI: ~(C or Z) */ | ||
777 | if (!(epsw & (EPSW_FLAG_C | EPSW_FLAG_Z))) | ||
778 | goto take_the_loop; | ||
779 | return; | ||
780 | case 0x6: /* MOV_LCC: ~C */ | ||
781 | if (!(epsw & EPSW_FLAG_C)) | ||
782 | goto take_the_loop; | ||
783 | return; | ||
784 | case 0x7: /* MOV_LLS: C or Z */ | ||
785 | if (epsw & (EPSW_FLAG_C | EPSW_FLAG_Z)) | ||
786 | goto take_the_loop; | ||
787 | return; | ||
788 | |||
789 | case 0x8: /* MOV_LEQ: Z */ | ||
790 | if (epsw & EPSW_FLAG_Z) | ||
791 | goto take_the_loop; | ||
792 | return; | ||
793 | case 0x9: /* MOV_LNE: ~Z */ | ||
794 | if (!(epsw & EPSW_FLAG_Z)) | ||
795 | goto take_the_loop; | ||
796 | return; | ||
797 | case 0xa: /* MOV_LRA: always */ | ||
798 | goto take_the_loop; | ||
799 | |||
800 | default: | ||
801 | BUG(); | ||
802 | } | ||
803 | |||
804 | take_the_loop: | ||
805 | /* wind the PC back to just after the SETLB insn */ | ||
806 | kdebug("loop LAR=%lx", regs->lar); | ||
807 | regs->pc = regs->lar - 4; | ||
808 | } | ||
809 | |||
810 | /* | ||
811 | * misalignment handler tests | ||
812 | */ | ||
813 | #ifdef CONFIG_TEST_MISALIGNMENT_HANDLER | ||
814 | static u8 __initdata testbuf[512] __attribute__((aligned(16))) = { | ||
815 | [257] = 0x11, | ||
816 | [258] = 0x22, | ||
817 | [259] = 0x33, | ||
818 | [260] = 0x44, | ||
819 | }; | ||
820 | |||
821 | #define ASSERTCMP(X, OP, Y) \ | ||
822 | do { \ | ||
823 | if (unlikely(!((X) OP (Y)))) { \ | ||
824 | printk(KERN_ERR "\n"); \ | ||
825 | printk(KERN_ERR "MISALIGN: Assertion failed at line %u\n", \ | ||
826 | __LINE__); \ | ||
827 | printk(KERN_ERR "0x%lx " #OP " 0x%lx is false\n", \ | ||
828 | (unsigned long)(X), (unsigned long)(Y)); \ | ||
829 | BUG(); \ | ||
830 | } \ | ||
831 | } while(0) | ||
832 | |||
833 | static int __init test_misalignment(void) | ||
834 | { | ||
835 | register void *r asm("e0"); | ||
836 | register u32 y asm("e1"); | ||
837 | void *p = testbuf, *q; | ||
838 | u32 tmp, tmp2, x; | ||
839 | |||
840 | printk(KERN_NOTICE "==>test_misalignment() [testbuf=%p]\n", p); | ||
841 | p++; | ||
842 | |||
843 | printk(KERN_NOTICE "___ MOV (Am),Dn ___\n"); | ||
844 | q = p + 256; | ||
845 | asm volatile("mov (%0),%1" : "+a"(q), "=d"(x)); | ||
846 | ASSERTCMP(q, ==, p + 256); | ||
847 | ASSERTCMP(x, ==, 0x44332211); | ||
848 | |||
849 | printk(KERN_NOTICE "___ MOV (256,Am),Dn ___\n"); | ||
850 | q = p; | ||
851 | asm volatile("mov (256,%0),%1" : "+a"(q), "=d"(x)); | ||
852 | ASSERTCMP(q, ==, p); | ||
853 | ASSERTCMP(x, ==, 0x44332211); | ||
854 | |||
855 | printk(KERN_NOTICE "___ MOV (Di,Am),Dn ___\n"); | ||
856 | tmp = 256; | ||
857 | q = p; | ||
858 | asm volatile("mov (%2,%0),%1" : "+a"(q), "=d"(x), "+d"(tmp)); | ||
859 | ASSERTCMP(q, ==, p); | ||
860 | ASSERTCMP(x, ==, 0x44332211); | ||
861 | ASSERTCMP(tmp, ==, 256); | ||
862 | |||
863 | printk(KERN_NOTICE "___ MOV (256,Rm),Rn ___\n"); | ||
864 | r = p; | ||
865 | asm volatile("mov (256,%0),%1" : "+r"(r), "=r"(y)); | ||
866 | ASSERTCMP(r, ==, p); | ||
867 | ASSERTCMP(y, ==, 0x44332211); | ||
868 | |||
869 | printk(KERN_NOTICE "___ MOV (Rm+),Rn ___\n"); | ||
870 | r = p + 256; | ||
871 | asm volatile("mov (%0+),%1" : "+r"(r), "=r"(y)); | ||
872 | ASSERTCMP(r, ==, p + 256 + 4); | ||
873 | ASSERTCMP(y, ==, 0x44332211); | ||
874 | |||
875 | printk(KERN_NOTICE "___ MOV (Rm+,8),Rn ___\n"); | ||
876 | r = p + 256; | ||
877 | asm volatile("mov (%0+,8),%1" : "+r"(r), "=r"(y)); | ||
878 | ASSERTCMP(r, ==, p + 256 + 8); | ||
879 | ASSERTCMP(y, ==, 0x44332211); | ||
880 | |||
881 | printk(KERN_NOTICE "___ MOV (7,SP),Rn ___\n"); | ||
882 | asm volatile( | ||
883 | "add -16,sp \n" | ||
884 | "mov +0x11,%0 \n" | ||
885 | "movbu %0,(7,sp) \n" | ||
886 | "mov +0x22,%0 \n" | ||
887 | "movbu %0,(8,sp) \n" | ||
888 | "mov +0x33,%0 \n" | ||
889 | "movbu %0,(9,sp) \n" | ||
890 | "mov +0x44,%0 \n" | ||
891 | "movbu %0,(10,sp) \n" | ||
892 | "mov (7,sp),%1 \n" | ||
893 | "add +16,sp \n" | ||
894 | : "+a"(q), "=d"(x)); | ||
895 | ASSERTCMP(x, ==, 0x44332211); | ||
896 | |||
897 | printk(KERN_NOTICE "___ MOV (259,SP),Rn ___\n"); | ||
898 | asm volatile( | ||
899 | "add -264,sp \n" | ||
900 | "mov +0x11,%0 \n" | ||
901 | "movbu %0,(259,sp) \n" | ||
902 | "mov +0x22,%0 \n" | ||
903 | "movbu %0,(260,sp) \n" | ||
904 | "mov +0x33,%0 \n" | ||
905 | "movbu %0,(261,sp) \n" | ||
906 | "mov +0x55,%0 \n" | ||
907 | "movbu %0,(262,sp) \n" | ||
908 | "mov (259,sp),%1 \n" | ||
909 | "add +264,sp \n" | ||
910 | : "+d"(tmp), "=d"(x)); | ||
911 | ASSERTCMP(x, ==, 0x55332211); | ||
912 | |||
913 | printk(KERN_NOTICE "___ MOV (260,SP),Rn ___\n"); | ||
914 | asm volatile( | ||
915 | "add -264,sp \n" | ||
916 | "mov +0x11,%0 \n" | ||
917 | "movbu %0,(260,sp) \n" | ||
918 | "mov +0x22,%0 \n" | ||
919 | "movbu %0,(261,sp) \n" | ||
920 | "mov +0x33,%0 \n" | ||
921 | "movbu %0,(262,sp) \n" | ||
922 | "mov +0x55,%0 \n" | ||
923 | "movbu %0,(263,sp) \n" | ||
924 | "mov (260,sp),%1 \n" | ||
925 | "add +264,sp \n" | ||
926 | : "+d"(tmp), "=d"(x)); | ||
927 | ASSERTCMP(x, ==, 0x55332211); | ||
928 | |||
929 | |||
930 | printk(KERN_NOTICE "___ MOV_LNE ___\n"); | ||
931 | tmp = 1; | ||
932 | tmp2 = 2; | ||
933 | q = p + 256; | ||
934 | asm volatile( | ||
935 | "setlb \n" | ||
936 | "mov %2,%3 \n" | ||
937 | "mov %1,%2 \n" | ||
938 | "cmp +0,%1 \n" | ||
939 | "mov_lne (%0+,4),%1" | ||
940 | : "+r"(q), "+d"(tmp), "+d"(tmp2), "=d"(x) | ||
941 | : | ||
942 | : "cc"); | ||
943 | ASSERTCMP(q, ==, p + 256 + 12); | ||
944 | ASSERTCMP(x, ==, 0x44332211); | ||
945 | |||
946 | printk(KERN_NOTICE "___ MOV in SETLB ___\n"); | ||
947 | tmp = 1; | ||
948 | tmp2 = 2; | ||
949 | q = p + 256; | ||
950 | asm volatile( | ||
951 | "setlb \n" | ||
952 | "mov %1,%3 \n" | ||
953 | "mov (%0+),%1 \n" | ||
954 | "cmp +0,%1 \n" | ||
955 | "lne " | ||
956 | : "+a"(q), "+d"(tmp), "+d"(tmp2), "=d"(x) | ||
957 | : | ||
958 | : "cc"); | ||
959 | |||
960 | ASSERTCMP(q, ==, p + 256 + 8); | ||
961 | ASSERTCMP(x, ==, 0x44332211); | ||
962 | |||
963 | printk(KERN_NOTICE "<==test_misalignment()\n"); | ||
964 | return 0; | ||
965 | } | ||
966 | |||
967 | arch_initcall(test_misalignment); | ||
968 | |||
969 | #endif /* CONFIG_TEST_MISALIGNMENT_HANDLER */ | ||
diff --git a/arch/parisc/include/asm/smp.h b/arch/parisc/include/asm/smp.h index 398cdbaf4e54..409e698f4361 100644 --- a/arch/parisc/include/asm/smp.h +++ b/arch/parisc/include/asm/smp.h | |||
@@ -44,8 +44,6 @@ extern void arch_send_call_function_ipi(cpumask_t mask); | |||
44 | 44 | ||
45 | #define PROC_CHANGE_PENALTY 15 /* Schedule penalty */ | 45 | #define PROC_CHANGE_PENALTY 15 /* Schedule penalty */ |
46 | 46 | ||
47 | extern unsigned long cpu_present_mask; | ||
48 | |||
49 | #define raw_smp_processor_id() (current_thread_info()->cpu) | 47 | #define raw_smp_processor_id() (current_thread_info()->cpu) |
50 | 48 | ||
51 | #else /* CONFIG_SMP */ | 49 | #else /* CONFIG_SMP */ |
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 8d676d8ecde9..9830681446ad 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h | |||
@@ -113,7 +113,6 @@ static inline void acpi_disable_pci(void) | |||
113 | acpi_pci_disabled = 1; | 113 | acpi_pci_disabled = 1; |
114 | acpi_noirq_set(); | 114 | acpi_noirq_set(); |
115 | } | 115 | } |
116 | extern int acpi_irq_balance_set(char *str); | ||
117 | 116 | ||
118 | /* routines for saving/restoring kernel state */ | 117 | /* routines for saving/restoring kernel state */ |
119 | extern int acpi_save_state_mem(void); | 118 | extern int acpi_save_state_mem(void); |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 8c1f76abae9e..4c51a2f8fd31 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -1343,7 +1343,6 @@ static void __init acpi_process_madt(void) | |||
1343 | error = acpi_parse_madt_ioapic_entries(); | 1343 | error = acpi_parse_madt_ioapic_entries(); |
1344 | if (!error) { | 1344 | if (!error) { |
1345 | acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; | 1345 | acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; |
1346 | acpi_irq_balance_set(NULL); | ||
1347 | acpi_ioapic = 1; | 1346 | acpi_ioapic = 1; |
1348 | 1347 | ||
1349 | smp_found_config = 1; | 1348 | smp_found_config = 1; |
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c index 774ac4991568..1c9cc431ea4f 100644 --- a/arch/x86/kernel/kvmclock.c +++ b/arch/x86/kernel/kvmclock.c | |||
@@ -128,7 +128,7 @@ static int kvm_register_clock(char *txt) | |||
128 | } | 128 | } |
129 | 129 | ||
130 | #ifdef CONFIG_X86_LOCAL_APIC | 130 | #ifdef CONFIG_X86_LOCAL_APIC |
131 | static void kvm_setup_secondary_clock(void) | 131 | static void __devinit kvm_setup_secondary_clock(void) |
132 | { | 132 | { |
133 | /* | 133 | /* |
134 | * Now that the first cpu already had this clocksource initialized, | 134 | * Now that the first cpu already had this clocksource initialized, |
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index ce3251ce5504..b81125f0bdee 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig | |||
@@ -20,6 +20,8 @@ if VIRTUALIZATION | |||
20 | config KVM | 20 | config KVM |
21 | tristate "Kernel-based Virtual Machine (KVM) support" | 21 | tristate "Kernel-based Virtual Machine (KVM) support" |
22 | depends on HAVE_KVM | 22 | depends on HAVE_KVM |
23 | # for device assignment: | ||
24 | depends on PCI | ||
23 | select PREEMPT_NOTIFIERS | 25 | select PREEMPT_NOTIFIERS |
24 | select MMU_NOTIFIER | 26 | select MMU_NOTIFIER |
25 | select ANON_INODES | 27 | select ANON_INODES |
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c index 8772dc946823..59ebd37ad79e 100644 --- a/arch/x86/kvm/i8254.c +++ b/arch/x86/kvm/i8254.c | |||
@@ -548,8 +548,10 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm) | |||
548 | mutex_lock(&kvm->lock); | 548 | mutex_lock(&kvm->lock); |
549 | pit->irq_source_id = kvm_request_irq_source_id(kvm); | 549 | pit->irq_source_id = kvm_request_irq_source_id(kvm); |
550 | mutex_unlock(&kvm->lock); | 550 | mutex_unlock(&kvm->lock); |
551 | if (pit->irq_source_id < 0) | 551 | if (pit->irq_source_id < 0) { |
552 | kfree(pit); | ||
552 | return NULL; | 553 | return NULL; |
554 | } | ||
553 | 555 | ||
554 | mutex_init(&pit->pit_state.lock); | 556 | mutex_init(&pit->pit_state.lock); |
555 | mutex_lock(&pit->pit_state.lock); | 557 | mutex_lock(&pit->pit_state.lock); |
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 2a5e64881d9b..f1983d9477cd 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
@@ -314,7 +314,7 @@ static int mmu_topup_memory_caches(struct kvm_vcpu *vcpu) | |||
314 | if (r) | 314 | if (r) |
315 | goto out; | 315 | goto out; |
316 | r = mmu_topup_memory_cache(&vcpu->arch.mmu_rmap_desc_cache, | 316 | r = mmu_topup_memory_cache(&vcpu->arch.mmu_rmap_desc_cache, |
317 | rmap_desc_cache, 1); | 317 | rmap_desc_cache, 4); |
318 | if (r) | 318 | if (r) |
319 | goto out; | 319 | goto out; |
320 | r = mmu_topup_memory_cache_page(&vcpu->arch.mmu_page_cache, 8); | 320 | r = mmu_topup_memory_cache_page(&vcpu->arch.mmu_page_cache, 8); |
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 2643b430d83a..d06b4dc0e2ea 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -3564,7 +3564,8 @@ static int __init vmx_init(void) | |||
3564 | bypass_guest_pf = 0; | 3564 | bypass_guest_pf = 0; |
3565 | kvm_mmu_set_base_ptes(VMX_EPT_READABLE_MASK | | 3565 | kvm_mmu_set_base_ptes(VMX_EPT_READABLE_MASK | |
3566 | VMX_EPT_WRITABLE_MASK | | 3566 | VMX_EPT_WRITABLE_MASK | |
3567 | VMX_EPT_DEFAULT_MT << VMX_EPT_MT_EPTE_SHIFT); | 3567 | VMX_EPT_DEFAULT_MT << VMX_EPT_MT_EPTE_SHIFT | |
3568 | VMX_EPT_IGMT_BIT); | ||
3568 | kvm_mmu_set_mask_ptes(0ull, 0ull, 0ull, 0ull, | 3569 | kvm_mmu_set_mask_ptes(0ull, 0ull, 0ull, 0ull, |
3569 | VMX_EPT_EXECUTABLE_MASK); | 3570 | VMX_EPT_EXECUTABLE_MASK); |
3570 | kvm_enable_tdp(); | 3571 | kvm_enable_tdp(); |
diff --git a/arch/x86/kvm/vmx.h b/arch/x86/kvm/vmx.h index 3e010d21fdd7..ec5edc339da6 100644 --- a/arch/x86/kvm/vmx.h +++ b/arch/x86/kvm/vmx.h | |||
@@ -352,6 +352,7 @@ enum vmcs_field { | |||
352 | #define VMX_EPT_READABLE_MASK 0x1ull | 352 | #define VMX_EPT_READABLE_MASK 0x1ull |
353 | #define VMX_EPT_WRITABLE_MASK 0x2ull | 353 | #define VMX_EPT_WRITABLE_MASK 0x2ull |
354 | #define VMX_EPT_EXECUTABLE_MASK 0x4ull | 354 | #define VMX_EPT_EXECUTABLE_MASK 0x4ull |
355 | #define VMX_EPT_IGMT_BIT (1ull << 6) | ||
355 | 356 | ||
356 | #define VMX_EPT_IDENTITY_PAGETABLE_ADDR 0xfffbc000ul | 357 | #define VMX_EPT_IDENTITY_PAGETABLE_ADDR 0xfffbc000ul |
357 | 358 | ||
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index f4f632917509..b0243fd55ac0 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -312,9 +312,13 @@ config ACPI_DEBUG | |||
312 | bool "Debug Statements" | 312 | bool "Debug Statements" |
313 | default n | 313 | default n |
314 | help | 314 | help |
315 | The ACPI driver can optionally report errors with a great deal | 315 | The ACPI subsystem can produce debug output. Saying Y enables this |
316 | of verbosity. Saying Y enables these statements. This will increase | 316 | output and increases the kernel size by around 50K. |
317 | your kernel size by around 50K. | 317 | |
318 | Use the acpi.debug_layer and acpi.debug_level kernel command-line | ||
319 | parameters documented in Documentation/acpi/debug.txt and | ||
320 | Documentation/kernel-parameters.txt to control the type and | ||
321 | amount of debug output. | ||
318 | 322 | ||
319 | config ACPI_DEBUG_FUNC_TRACE | 323 | config ACPI_DEBUG_FUNC_TRACE |
320 | bool "Additionally enable ACPI function tracing" | 324 | bool "Additionally enable ACPI function tracing" |
@@ -324,14 +328,6 @@ config ACPI_DEBUG_FUNC_TRACE | |||
324 | ACPI Debug Statements slow down ACPI processing. Function trace | 328 | ACPI Debug Statements slow down ACPI processing. Function trace |
325 | is about half of the penalty and is rarely useful. | 329 | is about half of the penalty and is rarely useful. |
326 | 330 | ||
327 | config ACPI_EC | ||
328 | bool | ||
329 | default y | ||
330 | help | ||
331 | This driver is required on some systems for the proper operation of | ||
332 | the battery and thermal drivers. If you are compiling for a | ||
333 | mobile system, say Y. | ||
334 | |||
335 | config ACPI_PCI_SLOT | 331 | config ACPI_PCI_SLOT |
336 | tristate "PCI slot detection driver" | 332 | tristate "PCI slot detection driver" |
337 | default n | 333 | default n |
@@ -341,10 +337,6 @@ config ACPI_PCI_SLOT | |||
341 | help you correlate PCI bus addresses with the physical geography | 337 | help you correlate PCI bus addresses with the physical geography |
342 | of your slots. If you are unsure, say N. | 338 | of your slots. If you are unsure, say N. |
343 | 339 | ||
344 | config ACPI_POWER | ||
345 | bool | ||
346 | default y | ||
347 | |||
348 | config ACPI_SYSTEM | 340 | config ACPI_SYSTEM |
349 | bool | 341 | bool |
350 | default y | 342 | default y |
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index d91c027ece8f..3c0c93300f12 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile | |||
@@ -39,19 +39,23 @@ obj-y += sleep/ | |||
39 | obj-y += bus.o glue.o | 39 | obj-y += bus.o glue.o |
40 | obj-y += scan.o | 40 | obj-y += scan.o |
41 | # Keep EC driver first. Initialization of others depend on it. | 41 | # Keep EC driver first. Initialization of others depend on it. |
42 | obj-$(CONFIG_ACPI_EC) += ec.o | 42 | obj-y += ec.o |
43 | obj-$(CONFIG_ACPI_AC) += ac.o | 43 | obj-$(CONFIG_ACPI_AC) += ac.o |
44 | obj-$(CONFIG_ACPI_BATTERY) += battery.o | 44 | obj-$(CONFIG_ACPI_BATTERY) += battery.o |
45 | obj-$(CONFIG_ACPI_BUTTON) += button.o | 45 | obj-$(CONFIG_ACPI_BUTTON) += button.o |
46 | obj-$(CONFIG_ACPI_FAN) += fan.o | 46 | obj-$(CONFIG_ACPI_FAN) += fan.o |
47 | obj-$(CONFIG_ACPI_DOCK) += dock.o | 47 | obj-$(CONFIG_ACPI_DOCK) += dock.o |
48 | obj-$(CONFIG_ACPI_VIDEO) += video.o | 48 | obj-$(CONFIG_ACPI_VIDEO) += video.o |
49 | ifdef CONFIG_ACPI_VIDEO | ||
50 | obj-y += video_detect.o | ||
51 | endif | ||
52 | |||
49 | obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o | 53 | obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o |
50 | obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o | 54 | obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o |
51 | obj-$(CONFIG_ACPI_PROCESSOR) += processor.o | 55 | obj-$(CONFIG_ACPI_PROCESSOR) += processor.o |
52 | obj-$(CONFIG_ACPI_CONTAINER) += container.o | 56 | obj-$(CONFIG_ACPI_CONTAINER) += container.o |
53 | obj-$(CONFIG_ACPI_THERMAL) += thermal.o | 57 | obj-$(CONFIG_ACPI_THERMAL) += thermal.o |
54 | obj-$(CONFIG_ACPI_POWER) += power.o | 58 | obj-y += power.o |
55 | obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o | 59 | obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o |
56 | obj-$(CONFIG_ACPI_DEBUG) += debug.o | 60 | obj-$(CONFIG_ACPI_DEBUG) += debug.o |
57 | obj-$(CONFIG_ACPI_NUMA) += numa.o | 61 | obj-$(CONFIG_ACPI_NUMA) += numa.o |
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index d72a1b6c8a94..9b917dac7732 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <acpi/acpi_bus.h> | 37 | #include <acpi/acpi_bus.h> |
38 | #include <acpi/acpi_drivers.h> | 38 | #include <acpi/acpi_drivers.h> |
39 | 39 | ||
40 | #define ACPI_AC_COMPONENT 0x00020000 | ||
41 | #define ACPI_AC_CLASS "ac_adapter" | 40 | #define ACPI_AC_CLASS "ac_adapter" |
42 | #define ACPI_AC_DEVICE_NAME "AC Adapter" | 41 | #define ACPI_AC_DEVICE_NAME "AC Adapter" |
43 | #define ACPI_AC_FILE_STATE "state" | 42 | #define ACPI_AC_FILE_STATE "state" |
@@ -242,7 +241,7 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data) | |||
242 | acpi_ac_get_state(ac); | 241 | acpi_ac_get_state(ac); |
243 | acpi_bus_generate_proc_event(device, event, (u32) ac->state); | 242 | acpi_bus_generate_proc_event(device, event, (u32) ac->state); |
244 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 243 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
245 | device->dev.bus_id, event, | 244 | dev_name(&device->dev), event, |
246 | (u32) ac->state); | 245 | (u32) ac->state); |
247 | #ifdef CONFIG_ACPI_SYSFS_POWER | 246 | #ifdef CONFIG_ACPI_SYSFS_POWER |
248 | kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); | 247 | kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); |
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 71d21c51c45f..63a17b55b39b 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/memory_hotplug.h> | 32 | #include <linux/memory_hotplug.h> |
33 | #include <acpi/acpi_drivers.h> | 33 | #include <acpi/acpi_drivers.h> |
34 | 34 | ||
35 | #define ACPI_MEMORY_DEVICE_COMPONENT 0x08000000UL | ||
36 | #define ACPI_MEMORY_DEVICE_CLASS "memory" | 35 | #define ACPI_MEMORY_DEVICE_CLASS "memory" |
37 | #define ACPI_MEMORY_DEVICE_HID "PNP0C80" | 36 | #define ACPI_MEMORY_DEVICE_HID "PNP0C80" |
38 | #define ACPI_MEMORY_DEVICE_NAME "Hotplug Mem Device" | 37 | #define ACPI_MEMORY_DEVICE_NAME "Hotplug Mem Device" |
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index b2133e89ad9a..1423b0c0cd2e 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
@@ -46,7 +46,6 @@ | |||
46 | 46 | ||
47 | #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF | 47 | #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF |
48 | 48 | ||
49 | #define ACPI_BATTERY_COMPONENT 0x00040000 | ||
50 | #define ACPI_BATTERY_CLASS "battery" | 49 | #define ACPI_BATTERY_CLASS "battery" |
51 | #define ACPI_BATTERY_DEVICE_NAME "Battery" | 50 | #define ACPI_BATTERY_DEVICE_NAME "Battery" |
52 | #define ACPI_BATTERY_NOTIFY_STATUS 0x80 | 51 | #define ACPI_BATTERY_NOTIFY_STATUS 0x80 |
@@ -782,7 +781,7 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) | |||
782 | acpi_bus_generate_proc_event(device, event, | 781 | acpi_bus_generate_proc_event(device, event, |
783 | acpi_battery_present(battery)); | 782 | acpi_battery_present(battery)); |
784 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 783 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
785 | device->dev.bus_id, event, | 784 | dev_name(&device->dev), event, |
786 | acpi_battery_present(battery)); | 785 | acpi_battery_present(battery)); |
787 | #ifdef CONFIG_ACPI_SYSFS_POWER | 786 | #ifdef CONFIG_ACPI_SYSFS_POWER |
788 | /* acpi_batter_update could remove power_supply object */ | 787 | /* acpi_batter_update could remove power_supply object */ |
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index c797c6473f31..7edf6d913c13 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -688,6 +688,14 @@ void __init acpi_early_init(void) | |||
688 | if (acpi_disabled) | 688 | if (acpi_disabled) |
689 | return; | 689 | return; |
690 | 690 | ||
691 | /* | ||
692 | * ACPI CA initializes acpi_dbg_level to non-zero, which means | ||
693 | * we get debug output merely by turning on CONFIG_ACPI_DEBUG. | ||
694 | * Turn it off so we don't get output unless the user specifies | ||
695 | * acpi.debug_level. | ||
696 | */ | ||
697 | acpi_dbg_level = 0; | ||
698 | |||
691 | printk(KERN_INFO PREFIX "Core revision %08x\n", ACPI_CA_VERSION); | 699 | printk(KERN_INFO PREFIX "Core revision %08x\n", ACPI_CA_VERSION); |
692 | 700 | ||
693 | /* enable workarounds, unless strict ACPI spec. compliance */ | 701 | /* enable workarounds, unless strict ACPI spec. compliance */ |
@@ -774,7 +782,7 @@ static int __init acpi_bus_init(void) | |||
774 | "Unable to initialize ACPI OS objects\n"); | 782 | "Unable to initialize ACPI OS objects\n"); |
775 | goto error1; | 783 | goto error1; |
776 | } | 784 | } |
777 | #ifdef CONFIG_ACPI_EC | 785 | |
778 | /* | 786 | /* |
779 | * ACPI 2.0 requires the EC driver to be loaded and work before | 787 | * ACPI 2.0 requires the EC driver to be loaded and work before |
780 | * the EC device is found in the namespace (i.e. before acpi_initialize_objects() | 788 | * the EC device is found in the namespace (i.e. before acpi_initialize_objects() |
@@ -785,7 +793,6 @@ static int __init acpi_bus_init(void) | |||
785 | */ | 793 | */ |
786 | status = acpi_ec_ecdt_probe(); | 794 | status = acpi_ec_ecdt_probe(); |
787 | /* Ignore result. Not having an ECDT is not fatal. */ | 795 | /* Ignore result. Not having an ECDT is not fatal. */ |
788 | #endif | ||
789 | 796 | ||
790 | status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); | 797 | status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); |
791 | if (ACPI_FAILURE(status)) { | 798 | if (ACPI_FAILURE(status)) { |
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index cb046c3fc3f2..171fd914f435 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <acpi/acpi_bus.h> | 33 | #include <acpi/acpi_bus.h> |
34 | #include <acpi/acpi_drivers.h> | 34 | #include <acpi/acpi_drivers.h> |
35 | 35 | ||
36 | #define ACPI_BUTTON_COMPONENT 0x00080000 | ||
37 | #define ACPI_BUTTON_CLASS "button" | 36 | #define ACPI_BUTTON_CLASS "button" |
38 | #define ACPI_BUTTON_FILE_INFO "info" | 37 | #define ACPI_BUTTON_FILE_INFO "info" |
39 | #define ACPI_BUTTON_FILE_STATE "state" | 38 | #define ACPI_BUTTON_FILE_STATE "state" |
@@ -479,7 +478,7 @@ static int acpi_button_add(struct acpi_device *device) | |||
479 | device->wakeup.gpe_number, | 478 | device->wakeup.gpe_number, |
480 | ACPI_GPE_TYPE_WAKE_RUN); | 479 | ACPI_GPE_TYPE_WAKE_RUN); |
481 | acpi_enable_gpe(device->wakeup.gpe_device, | 480 | acpi_enable_gpe(device->wakeup.gpe_device, |
482 | device->wakeup.gpe_number, ACPI_NOT_ISR); | 481 | device->wakeup.gpe_number); |
483 | device->wakeup.state.enabled = 1; | 482 | device->wakeup.state.enabled = 1; |
484 | } | 483 | } |
485 | 484 | ||
diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c index 4441e84b28a9..307963bd1043 100644 --- a/drivers/acpi/cm_sbs.c +++ b/drivers/acpi/cm_sbs.c | |||
@@ -34,7 +34,6 @@ | |||
34 | ACPI_MODULE_NAME("cm_sbs"); | 34 | ACPI_MODULE_NAME("cm_sbs"); |
35 | #define ACPI_AC_CLASS "ac_adapter" | 35 | #define ACPI_AC_CLASS "ac_adapter" |
36 | #define ACPI_BATTERY_CLASS "battery" | 36 | #define ACPI_BATTERY_CLASS "battery" |
37 | #define ACPI_SBS_COMPONENT 0x00080000 | ||
38 | #define _COMPONENT ACPI_SBS_COMPONENT | 37 | #define _COMPONENT ACPI_SBS_COMPONENT |
39 | static struct proc_dir_entry *acpi_ac_dir; | 38 | static struct proc_dir_entry *acpi_ac_dir; |
40 | static struct proc_dir_entry *acpi_battery_dir; | 39 | static struct proc_dir_entry *acpi_battery_dir; |
@@ -105,9 +104,3 @@ void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir_param) | |||
105 | return; | 104 | return; |
106 | } | 105 | } |
107 | EXPORT_SYMBOL(acpi_unlock_battery_dir); | 106 | EXPORT_SYMBOL(acpi_unlock_battery_dir); |
108 | |||
109 | static int __init acpi_cm_sbs_init(void) | ||
110 | { | ||
111 | return 0; | ||
112 | } | ||
113 | subsys_initcall(acpi_cm_sbs_init); | ||
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 134818b265a9..17020c12623c 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #define INSTALL_NOTIFY_HANDLER 1 | 41 | #define INSTALL_NOTIFY_HANDLER 1 |
42 | #define UNINSTALL_NOTIFY_HANDLER 2 | 42 | #define UNINSTALL_NOTIFY_HANDLER 2 |
43 | 43 | ||
44 | #define ACPI_CONTAINER_COMPONENT 0x01000000 | ||
45 | #define _COMPONENT ACPI_CONTAINER_COMPONENT | 44 | #define _COMPONENT ACPI_CONTAINER_COMPONENT |
46 | ACPI_MODULE_NAME("container"); | 45 | ACPI_MODULE_NAME("container"); |
47 | 46 | ||
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index abf36b4b1d1d..c48396892008 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c | |||
@@ -44,6 +44,21 @@ static const struct acpi_dlayer acpi_debug_layers[] = { | |||
44 | ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER), | 44 | ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER), |
45 | ACPI_DEBUG_INIT(ACPI_COMPILER), | 45 | ACPI_DEBUG_INIT(ACPI_COMPILER), |
46 | ACPI_DEBUG_INIT(ACPI_TOOLS), | 46 | ACPI_DEBUG_INIT(ACPI_TOOLS), |
47 | |||
48 | ACPI_DEBUG_INIT(ACPI_BUS_COMPONENT), | ||
49 | ACPI_DEBUG_INIT(ACPI_AC_COMPONENT), | ||
50 | ACPI_DEBUG_INIT(ACPI_BATTERY_COMPONENT), | ||
51 | ACPI_DEBUG_INIT(ACPI_BUTTON_COMPONENT), | ||
52 | ACPI_DEBUG_INIT(ACPI_SBS_COMPONENT), | ||
53 | ACPI_DEBUG_INIT(ACPI_FAN_COMPONENT), | ||
54 | ACPI_DEBUG_INIT(ACPI_PCI_COMPONENT), | ||
55 | ACPI_DEBUG_INIT(ACPI_POWER_COMPONENT), | ||
56 | ACPI_DEBUG_INIT(ACPI_CONTAINER_COMPONENT), | ||
57 | ACPI_DEBUG_INIT(ACPI_SYSTEM_COMPONENT), | ||
58 | ACPI_DEBUG_INIT(ACPI_THERMAL_COMPONENT), | ||
59 | ACPI_DEBUG_INIT(ACPI_MEMORY_DEVICE_COMPONENT), | ||
60 | ACPI_DEBUG_INIT(ACPI_VIDEO_COMPONENT), | ||
61 | ACPI_DEBUG_INIT(ACPI_PROCESSOR_COMPONENT), | ||
47 | }; | 62 | }; |
48 | 63 | ||
49 | static const struct acpi_dlevel acpi_debug_levels[] = { | 64 | static const struct acpi_dlevel acpi_debug_levels[] = { |
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index ef42316f89f5..cf41f9fc24a7 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -70,7 +70,7 @@ enum ec_command { | |||
70 | #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ | 70 | #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ |
71 | #define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */ | 71 | #define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */ |
72 | 72 | ||
73 | #define ACPI_EC_STORM_THRESHOLD 20 /* number of false interrupts | 73 | #define ACPI_EC_STORM_THRESHOLD 8 /* number of false interrupts |
74 | per one transaction */ | 74 | per one transaction */ |
75 | 75 | ||
76 | enum { | 76 | enum { |
@@ -100,8 +100,11 @@ struct transaction { | |||
100 | u8 *rdata; | 100 | u8 *rdata; |
101 | unsigned short irq_count; | 101 | unsigned short irq_count; |
102 | u8 command; | 102 | u8 command; |
103 | u8 wi; | ||
104 | u8 ri; | ||
103 | u8 wlen; | 105 | u8 wlen; |
104 | u8 rlen; | 106 | u8 rlen; |
107 | bool done; | ||
105 | }; | 108 | }; |
106 | 109 | ||
107 | static struct acpi_ec { | 110 | static struct acpi_ec { |
@@ -178,34 +181,45 @@ static int ec_transaction_done(struct acpi_ec *ec) | |||
178 | unsigned long flags; | 181 | unsigned long flags; |
179 | int ret = 0; | 182 | int ret = 0; |
180 | spin_lock_irqsave(&ec->curr_lock, flags); | 183 | spin_lock_irqsave(&ec->curr_lock, flags); |
181 | if (!ec->curr || (!ec->curr->wlen && !ec->curr->rlen)) | 184 | if (!ec->curr || ec->curr->done) |
182 | ret = 1; | 185 | ret = 1; |
183 | spin_unlock_irqrestore(&ec->curr_lock, flags); | 186 | spin_unlock_irqrestore(&ec->curr_lock, flags); |
184 | return ret; | 187 | return ret; |
185 | } | 188 | } |
186 | 189 | ||
190 | static void start_transaction(struct acpi_ec *ec) | ||
191 | { | ||
192 | ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0; | ||
193 | ec->curr->done = false; | ||
194 | acpi_ec_write_cmd(ec, ec->curr->command); | ||
195 | } | ||
196 | |||
187 | static void gpe_transaction(struct acpi_ec *ec, u8 status) | 197 | static void gpe_transaction(struct acpi_ec *ec, u8 status) |
188 | { | 198 | { |
189 | unsigned long flags; | 199 | unsigned long flags; |
190 | spin_lock_irqsave(&ec->curr_lock, flags); | 200 | spin_lock_irqsave(&ec->curr_lock, flags); |
191 | if (!ec->curr) | 201 | if (!ec->curr) |
192 | goto unlock; | 202 | goto unlock; |
193 | if (ec->curr->wlen > 0) { | 203 | if (ec->curr->wlen > ec->curr->wi) { |
194 | if ((status & ACPI_EC_FLAG_IBF) == 0) { | 204 | if ((status & ACPI_EC_FLAG_IBF) == 0) |
195 | acpi_ec_write_data(ec, *(ec->curr->wdata++)); | 205 | acpi_ec_write_data(ec, |
196 | --ec->curr->wlen; | 206 | ec->curr->wdata[ec->curr->wi++]); |
197 | } else | 207 | else |
198 | /* false interrupt, state didn't change */ | 208 | goto err; |
199 | ++ec->curr->irq_count; | 209 | } else if (ec->curr->rlen > ec->curr->ri) { |
200 | |||
201 | } else if (ec->curr->rlen > 0) { | ||
202 | if ((status & ACPI_EC_FLAG_OBF) == 1) { | 210 | if ((status & ACPI_EC_FLAG_OBF) == 1) { |
203 | *(ec->curr->rdata++) = acpi_ec_read_data(ec); | 211 | ec->curr->rdata[ec->curr->ri++] = acpi_ec_read_data(ec); |
204 | --ec->curr->rlen; | 212 | if (ec->curr->rlen == ec->curr->ri) |
213 | ec->curr->done = true; | ||
205 | } else | 214 | } else |
206 | /* false interrupt, state didn't change */ | 215 | goto err; |
207 | ++ec->curr->irq_count; | 216 | } else if (ec->curr->wlen == ec->curr->wi && |
208 | } | 217 | (status & ACPI_EC_FLAG_IBF) == 0) |
218 | ec->curr->done = true; | ||
219 | goto unlock; | ||
220 | err: | ||
221 | /* false interrupt, state didn't change */ | ||
222 | ++ec->curr->irq_count; | ||
209 | unlock: | 223 | unlock: |
210 | spin_unlock_irqrestore(&ec->curr_lock, flags); | 224 | spin_unlock_irqrestore(&ec->curr_lock, flags); |
211 | } | 225 | } |
@@ -215,6 +229,15 @@ static int acpi_ec_wait(struct acpi_ec *ec) | |||
215 | if (wait_event_timeout(ec->wait, ec_transaction_done(ec), | 229 | if (wait_event_timeout(ec->wait, ec_transaction_done(ec), |
216 | msecs_to_jiffies(ACPI_EC_DELAY))) | 230 | msecs_to_jiffies(ACPI_EC_DELAY))) |
217 | return 0; | 231 | return 0; |
232 | /* try restart command if we get any false interrupts */ | ||
233 | if (ec->curr->irq_count && | ||
234 | (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) { | ||
235 | pr_debug(PREFIX "controller reset, restart transaction\n"); | ||
236 | start_transaction(ec); | ||
237 | if (wait_event_timeout(ec->wait, ec_transaction_done(ec), | ||
238 | msecs_to_jiffies(ACPI_EC_DELAY))) | ||
239 | return 0; | ||
240 | } | ||
218 | /* missing GPEs, switch back to poll mode */ | 241 | /* missing GPEs, switch back to poll mode */ |
219 | if (printk_ratelimit()) | 242 | if (printk_ratelimit()) |
220 | pr_info(PREFIX "missing confirmations, " | 243 | pr_info(PREFIX "missing confirmations, " |
@@ -239,10 +262,10 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state) | |||
239 | static int ec_poll(struct acpi_ec *ec) | 262 | static int ec_poll(struct acpi_ec *ec) |
240 | { | 263 | { |
241 | unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); | 264 | unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); |
242 | msleep(1); | 265 | udelay(ACPI_EC_UDELAY); |
243 | while (time_before(jiffies, delay)) { | 266 | while (time_before(jiffies, delay)) { |
244 | gpe_transaction(ec, acpi_ec_read_status(ec)); | 267 | gpe_transaction(ec, acpi_ec_read_status(ec)); |
245 | msleep(1); | 268 | udelay(ACPI_EC_UDELAY); |
246 | if (ec_transaction_done(ec)) | 269 | if (ec_transaction_done(ec)) |
247 | return 0; | 270 | return 0; |
248 | } | 271 | } |
@@ -259,14 +282,13 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | |||
259 | /* disable GPE during transaction if storm is detected */ | 282 | /* disable GPE during transaction if storm is detected */ |
260 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { | 283 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { |
261 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); | 284 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); |
262 | acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | 285 | acpi_disable_gpe(NULL, ec->gpe); |
263 | } | 286 | } |
264 | /* start transaction */ | 287 | /* start transaction */ |
265 | spin_lock_irqsave(&ec->curr_lock, tmp); | 288 | spin_lock_irqsave(&ec->curr_lock, tmp); |
266 | /* following two actions should be kept atomic */ | 289 | /* following two actions should be kept atomic */ |
267 | t->irq_count = 0; | ||
268 | ec->curr = t; | 290 | ec->curr = t; |
269 | acpi_ec_write_cmd(ec, ec->curr->command); | 291 | start_transaction(ec); |
270 | if (ec->curr->command == ACPI_EC_COMMAND_QUERY) | 292 | if (ec->curr->command == ACPI_EC_COMMAND_QUERY) |
271 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); | 293 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); |
272 | spin_unlock_irqrestore(&ec->curr_lock, tmp); | 294 | spin_unlock_irqrestore(&ec->curr_lock, tmp); |
@@ -283,10 +305,11 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | |||
283 | /* check if we received SCI during transaction */ | 305 | /* check if we received SCI during transaction */ |
284 | ec_check_sci(ec, acpi_ec_read_status(ec)); | 306 | ec_check_sci(ec, acpi_ec_read_status(ec)); |
285 | /* it is safe to enable GPE outside of transaction */ | 307 | /* it is safe to enable GPE outside of transaction */ |
286 | acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | 308 | acpi_enable_gpe(NULL, ec->gpe); |
287 | } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && | 309 | } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && |
288 | t->irq_count > ACPI_EC_STORM_THRESHOLD) { | 310 | t->irq_count > ACPI_EC_STORM_THRESHOLD) { |
289 | pr_debug(PREFIX "GPE storm detected\n"); | 311 | pr_info(PREFIX "GPE storm detected, " |
312 | "transactions will use polling mode\n"); | ||
290 | set_bit(EC_FLAGS_GPE_STORM, &ec->flags); | 313 | set_bit(EC_FLAGS_GPE_STORM, &ec->flags); |
291 | } | 314 | } |
292 | return ret; | 315 | return ret; |
@@ -558,17 +581,26 @@ static u32 acpi_ec_gpe_handler(void *data) | |||
558 | pr_debug(PREFIX "~~~> interrupt\n"); | 581 | pr_debug(PREFIX "~~~> interrupt\n"); |
559 | status = acpi_ec_read_status(ec); | 582 | status = acpi_ec_read_status(ec); |
560 | 583 | ||
561 | gpe_transaction(ec, status); | 584 | if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) { |
562 | if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0) | 585 | gpe_transaction(ec, status); |
563 | wake_up(&ec->wait); | 586 | if (ec_transaction_done(ec) && |
587 | (status & ACPI_EC_FLAG_IBF) == 0) | ||
588 | wake_up(&ec->wait); | ||
589 | } | ||
564 | 590 | ||
565 | ec_check_sci(ec, status); | 591 | ec_check_sci(ec, status); |
566 | if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && | 592 | if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && |
567 | !test_bit(EC_FLAGS_NO_GPE, &ec->flags)) { | 593 | !test_bit(EC_FLAGS_NO_GPE, &ec->flags)) { |
568 | /* this is non-query, must be confirmation */ | 594 | /* this is non-query, must be confirmation */ |
569 | if (printk_ratelimit()) | 595 | if (!test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { |
570 | pr_info(PREFIX "non-query interrupt received," | 596 | if (printk_ratelimit()) |
597 | pr_info(PREFIX "non-query interrupt received," | ||
598 | " switching to interrupt mode\n"); | ||
599 | } else { | ||
600 | /* hush, STORM switches the mode every transaction */ | ||
601 | pr_debug(PREFIX "non-query interrupt received," | ||
571 | " switching to interrupt mode\n"); | 602 | " switching to interrupt mode\n"); |
603 | } | ||
572 | set_bit(EC_FLAGS_GPE_MODE, &ec->flags); | 604 | set_bit(EC_FLAGS_GPE_MODE, &ec->flags); |
573 | } | 605 | } |
574 | return ACPI_INTERRUPT_HANDLED; | 606 | return ACPI_INTERRUPT_HANDLED; |
@@ -736,7 +768,7 @@ static acpi_status | |||
736 | ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) | 768 | ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) |
737 | { | 769 | { |
738 | acpi_status status; | 770 | acpi_status status; |
739 | unsigned long long tmp; | 771 | unsigned long long tmp = 0; |
740 | 772 | ||
741 | struct acpi_ec *ec = context; | 773 | struct acpi_ec *ec = context; |
742 | status = acpi_walk_resources(handle, METHOD_NAME__CRS, | 774 | status = acpi_walk_resources(handle, METHOD_NAME__CRS, |
@@ -751,6 +783,7 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) | |||
751 | return status; | 783 | return status; |
752 | ec->gpe = tmp; | 784 | ec->gpe = tmp; |
753 | /* Use the global lock for all EC transactions? */ | 785 | /* Use the global lock for all EC transactions? */ |
786 | tmp = 0; | ||
754 | acpi_evaluate_integer(handle, "_GLK", NULL, &tmp); | 787 | acpi_evaluate_integer(handle, "_GLK", NULL, &tmp); |
755 | ec->global_lock = tmp; | 788 | ec->global_lock = tmp; |
756 | ec->handle = handle; | 789 | ec->handle = handle; |
@@ -868,7 +901,7 @@ static int ec_install_handlers(struct acpi_ec *ec) | |||
868 | if (ACPI_FAILURE(status)) | 901 | if (ACPI_FAILURE(status)) |
869 | return -ENODEV; | 902 | return -ENODEV; |
870 | acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); | 903 | acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); |
871 | acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | 904 | acpi_enable_gpe(NULL, ec->gpe); |
872 | status = acpi_install_address_space_handler(ec->handle, | 905 | status = acpi_install_address_space_handler(ec->handle, |
873 | ACPI_ADR_SPACE_EC, | 906 | ACPI_ADR_SPACE_EC, |
874 | &acpi_ec_space_handler, | 907 | &acpi_ec_space_handler, |
@@ -1007,7 +1040,7 @@ static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state) | |||
1007 | /* Stop using GPE */ | 1040 | /* Stop using GPE */ |
1008 | set_bit(EC_FLAGS_NO_GPE, &ec->flags); | 1041 | set_bit(EC_FLAGS_NO_GPE, &ec->flags); |
1009 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); | 1042 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); |
1010 | acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | 1043 | acpi_disable_gpe(NULL, ec->gpe); |
1011 | return 0; | 1044 | return 0; |
1012 | } | 1045 | } |
1013 | 1046 | ||
@@ -1016,7 +1049,7 @@ static int acpi_ec_resume(struct acpi_device *device) | |||
1016 | struct acpi_ec *ec = acpi_driver_data(device); | 1049 | struct acpi_ec *ec = acpi_driver_data(device); |
1017 | /* Enable use of GPE back */ | 1050 | /* Enable use of GPE back */ |
1018 | clear_bit(EC_FLAGS_NO_GPE, &ec->flags); | 1051 | clear_bit(EC_FLAGS_NO_GPE, &ec->flags); |
1019 | acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | 1052 | acpi_enable_gpe(NULL, ec->gpe); |
1020 | return 0; | 1053 | return 0; |
1021 | } | 1054 | } |
1022 | 1055 | ||
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index c5e53aae86f7..f45c74fe745e 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c | |||
@@ -289,8 +289,6 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) | |||
289 | */ | 289 | */ |
290 | status = acpi_hw_low_disable_gpe(gpe_event_info); | 290 | status = acpi_hw_low_disable_gpe(gpe_event_info); |
291 | return_ACPI_STATUS(status); | 291 | return_ACPI_STATUS(status); |
292 | |||
293 | return_ACPI_STATUS(AE_OK); | ||
294 | } | 292 | } |
295 | 293 | ||
296 | /******************************************************************************* | 294 | /******************************************************************************* |
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c index 73bfd6bf962f..41554f736b68 100644 --- a/drivers/acpi/events/evxfevnt.c +++ b/drivers/acpi/events/evxfevnt.c | |||
@@ -248,21 +248,15 @@ ACPI_EXPORT_SYMBOL(acpi_set_gpe_type) | |||
248 | * DESCRIPTION: Enable an ACPI event (general purpose) | 248 | * DESCRIPTION: Enable an ACPI event (general purpose) |
249 | * | 249 | * |
250 | ******************************************************************************/ | 250 | ******************************************************************************/ |
251 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) | 251 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) |
252 | { | 252 | { |
253 | acpi_status status = AE_OK; | 253 | acpi_status status = AE_OK; |
254 | acpi_cpu_flags flags; | ||
254 | struct acpi_gpe_event_info *gpe_event_info; | 255 | struct acpi_gpe_event_info *gpe_event_info; |
255 | 256 | ||
256 | ACPI_FUNCTION_TRACE(acpi_enable_gpe); | 257 | ACPI_FUNCTION_TRACE(acpi_enable_gpe); |
257 | 258 | ||
258 | /* Use semaphore lock if not executing at interrupt level */ | 259 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
259 | |||
260 | if (flags & ACPI_NOT_ISR) { | ||
261 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
262 | if (ACPI_FAILURE(status)) { | ||
263 | return_ACPI_STATUS(status); | ||
264 | } | ||
265 | } | ||
266 | 260 | ||
267 | /* Ensure that we have a valid GPE number */ | 261 | /* Ensure that we have a valid GPE number */ |
268 | 262 | ||
@@ -277,9 +271,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) | |||
277 | status = acpi_ev_enable_gpe(gpe_event_info, TRUE); | 271 | status = acpi_ev_enable_gpe(gpe_event_info, TRUE); |
278 | 272 | ||
279 | unlock_and_exit: | 273 | unlock_and_exit: |
280 | if (flags & ACPI_NOT_ISR) { | 274 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); |
281 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
282 | } | ||
283 | return_ACPI_STATUS(status); | 275 | return_ACPI_STATUS(status); |
284 | } | 276 | } |
285 | 277 | ||
@@ -299,22 +291,15 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe) | |||
299 | * DESCRIPTION: Disable an ACPI event (general purpose) | 291 | * DESCRIPTION: Disable an ACPI event (general purpose) |
300 | * | 292 | * |
301 | ******************************************************************************/ | 293 | ******************************************************************************/ |
302 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) | 294 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) |
303 | { | 295 | { |
304 | acpi_status status = AE_OK; | 296 | acpi_status status = AE_OK; |
297 | acpi_cpu_flags flags; | ||
305 | struct acpi_gpe_event_info *gpe_event_info; | 298 | struct acpi_gpe_event_info *gpe_event_info; |
306 | 299 | ||
307 | ACPI_FUNCTION_TRACE(acpi_disable_gpe); | 300 | ACPI_FUNCTION_TRACE(acpi_disable_gpe); |
308 | 301 | ||
309 | /* Use semaphore lock if not executing at interrupt level */ | 302 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
310 | |||
311 | if (flags & ACPI_NOT_ISR) { | ||
312 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
313 | if (ACPI_FAILURE(status)) { | ||
314 | return_ACPI_STATUS(status); | ||
315 | } | ||
316 | } | ||
317 | |||
318 | /* Ensure that we have a valid GPE number */ | 303 | /* Ensure that we have a valid GPE number */ |
319 | 304 | ||
320 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | 305 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); |
@@ -325,10 +310,8 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) | |||
325 | 310 | ||
326 | status = acpi_ev_disable_gpe(gpe_event_info); | 311 | status = acpi_ev_disable_gpe(gpe_event_info); |
327 | 312 | ||
328 | unlock_and_exit: | 313 | unlock_and_exit: |
329 | if (flags & ACPI_NOT_ISR) { | 314 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); |
330 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
331 | } | ||
332 | return_ACPI_STATUS(status); | 315 | return_ACPI_STATUS(status); |
333 | } | 316 | } |
334 | 317 | ||
@@ -521,6 +504,9 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) | |||
521 | if (value) | 504 | if (value) |
522 | *event_status |= ACPI_EVENT_FLAG_SET; | 505 | *event_status |= ACPI_EVENT_FLAG_SET; |
523 | 506 | ||
507 | if (acpi_gbl_fixed_event_handlers[event].handler) | ||
508 | *event_status |= ACPI_EVENT_FLAG_HANDLE; | ||
509 | |||
524 | return_ACPI_STATUS(status); | 510 | return_ACPI_STATUS(status); |
525 | } | 511 | } |
526 | 512 | ||
@@ -571,6 +557,9 @@ acpi_get_gpe_status(acpi_handle gpe_device, | |||
571 | 557 | ||
572 | status = acpi_hw_get_gpe_status(gpe_event_info, event_status); | 558 | status = acpi_hw_get_gpe_status(gpe_event_info, event_status); |
573 | 559 | ||
560 | if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) | ||
561 | *event_status |= ACPI_EVENT_FLAG_HANDLE; | ||
562 | |||
574 | unlock_and_exit: | 563 | unlock_and_exit: |
575 | if (flags & ACPI_NOT_ISR) { | 564 | if (flags & ACPI_NOT_ISR) { |
576 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | 565 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); |
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 60d54d1f6b19..eaaee1660bdf 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <acpi/acpi_bus.h> | 34 | #include <acpi/acpi_bus.h> |
35 | #include <acpi/acpi_drivers.h> | 35 | #include <acpi/acpi_drivers.h> |
36 | 36 | ||
37 | #define ACPI_FAN_COMPONENT 0x00200000 | ||
38 | #define ACPI_FAN_CLASS "fan" | 37 | #define ACPI_FAN_CLASS "fan" |
39 | #define ACPI_FAN_FILE_STATE "state" | 38 | #define ACPI_FAN_FILE_STATE "state" |
40 | 39 | ||
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 24649ada08df..adec3d15810a 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
@@ -140,6 +140,46 @@ struct device *acpi_get_physical_device(acpi_handle handle) | |||
140 | 140 | ||
141 | EXPORT_SYMBOL(acpi_get_physical_device); | 141 | EXPORT_SYMBOL(acpi_get_physical_device); |
142 | 142 | ||
143 | /* ToDo: When a PCI bridge is found, return the PCI device behind the bridge | ||
144 | * This should work in general, but did not on a Lenovo T61 for the | ||
145 | * graphics card. But this must be fixed when the PCI device is | ||
146 | * bound and the kernel device struct is attached to the acpi device | ||
147 | * Note: A success call will increase reference count by one | ||
148 | * Do call put_device(dev) on the returned device then | ||
149 | */ | ||
150 | struct device *acpi_get_physical_pci_device(acpi_handle handle) | ||
151 | { | ||
152 | struct device *dev; | ||
153 | long long device_id; | ||
154 | acpi_status status; | ||
155 | |||
156 | status = | ||
157 | acpi_evaluate_integer(handle, "_ADR", NULL, &device_id); | ||
158 | |||
159 | if (ACPI_FAILURE(status)) | ||
160 | return NULL; | ||
161 | |||
162 | /* We need to attempt to determine whether the _ADR refers to a | ||
163 | PCI device or not. There's no terribly good way to do this, | ||
164 | so the best we can hope for is to assume that there'll never | ||
165 | be a device in the host bridge */ | ||
166 | if (device_id >= 0x10000) { | ||
167 | /* It looks like a PCI device. Does it exist? */ | ||
168 | dev = acpi_get_physical_device(handle); | ||
169 | } else { | ||
170 | /* It doesn't look like a PCI device. Does its parent | ||
171 | exist? */ | ||
172 | acpi_handle phandle; | ||
173 | if (acpi_get_parent(handle, &phandle)) | ||
174 | return NULL; | ||
175 | dev = acpi_get_physical_device(phandle); | ||
176 | } | ||
177 | if (!dev) | ||
178 | return NULL; | ||
179 | return dev; | ||
180 | } | ||
181 | EXPORT_SYMBOL(acpi_get_physical_pci_device); | ||
182 | |||
143 | static int acpi_bind_one(struct device *dev, acpi_handle handle) | 183 | static int acpi_bind_one(struct device *dev, acpi_handle handle) |
144 | { | 184 | { |
145 | struct acpi_device *acpi_dev; | 185 | struct acpi_device *acpi_dev; |
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index fcfdef7b4fdd..e52ad91ce2dc 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c | |||
@@ -531,7 +531,7 @@ int __init acpi_irq_penalty_init(void) | |||
531 | return 0; | 531 | return 0; |
532 | } | 532 | } |
533 | 533 | ||
534 | static int acpi_irq_balance; /* 0: static, 1: balance */ | 534 | static int acpi_irq_balance = -1; /* 0: static, 1: balance */ |
535 | 535 | ||
536 | static int acpi_pci_link_allocate(struct acpi_pci_link *link) | 536 | static int acpi_pci_link_allocate(struct acpi_pci_link *link) |
537 | { | 537 | { |
@@ -950,10 +950,17 @@ device_initcall(irqrouter_init_sysfs); | |||
950 | 950 | ||
951 | static int __init acpi_pci_link_init(void) | 951 | static int __init acpi_pci_link_init(void) |
952 | { | 952 | { |
953 | |||
954 | if (acpi_noirq) | 953 | if (acpi_noirq) |
955 | return 0; | 954 | return 0; |
956 | 955 | ||
956 | if (acpi_irq_balance == -1) { | ||
957 | /* no command line switch: enable balancing in IOAPIC mode */ | ||
958 | if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) | ||
959 | acpi_irq_balance = 1; | ||
960 | else | ||
961 | acpi_irq_balance = 0; | ||
962 | } | ||
963 | |||
957 | acpi_link.count = 0; | 964 | acpi_link.count = 0; |
958 | INIT_LIST_HEAD(&acpi_link.entries); | 965 | INIT_LIST_HEAD(&acpi_link.entries); |
959 | 966 | ||
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 1b8f67d21d53..642554b1b60c 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -376,15 +376,9 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) | |||
376 | 376 | ||
377 | static int __init acpi_pci_root_init(void) | 377 | static int __init acpi_pci_root_init(void) |
378 | { | 378 | { |
379 | |||
380 | if (acpi_pci_disabled) | 379 | if (acpi_pci_disabled) |
381 | return 0; | 380 | return 0; |
382 | 381 | ||
383 | /* DEBUG: | ||
384 | acpi_dbg_layer = ACPI_PCI_COMPONENT; | ||
385 | acpi_dbg_level = 0xFFFFFFFF; | ||
386 | */ | ||
387 | |||
388 | if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0) | 382 | if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0) |
389 | return -ENODEV; | 383 | return -ENODEV; |
390 | 384 | ||
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index a1718e56103b..bb7d50dd2818 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
@@ -44,9 +44,8 @@ | |||
44 | #include <acpi/acpi_bus.h> | 44 | #include <acpi/acpi_bus.h> |
45 | #include <acpi/acpi_drivers.h> | 45 | #include <acpi/acpi_drivers.h> |
46 | 46 | ||
47 | #define _COMPONENT ACPI_POWER_COMPONENT | 47 | #define _COMPONENT ACPI_POWER_COMPONENT |
48 | ACPI_MODULE_NAME("power"); | 48 | ACPI_MODULE_NAME("power"); |
49 | #define ACPI_POWER_COMPONENT 0x00800000 | ||
50 | #define ACPI_POWER_CLASS "power_resource" | 49 | #define ACPI_POWER_CLASS "power_resource" |
51 | #define ACPI_POWER_DEVICE_NAME "Power Resource" | 50 | #define ACPI_POWER_DEVICE_NAME "Power Resource" |
52 | #define ACPI_POWER_FILE_INFO "info" | 51 | #define ACPI_POWER_FILE_INFO "info" |
@@ -153,7 +152,8 @@ static int acpi_power_get_state(acpi_handle handle, int *state) | |||
153 | ACPI_POWER_RESOURCE_STATE_OFF; | 152 | ACPI_POWER_RESOURCE_STATE_OFF; |
154 | 153 | ||
155 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", | 154 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", |
156 | acpi_ut_get_node_name(handle), state ? "on" : "off")); | 155 | acpi_ut_get_node_name(handle), |
156 | *state ? "on" : "off")); | ||
157 | 157 | ||
158 | return 0; | 158 | return 0; |
159 | } | 159 | } |
@@ -516,11 +516,6 @@ int acpi_power_transition(struct acpi_device *device, int state) | |||
516 | cl = &device->power.states[device->power.state].resources; | 516 | cl = &device->power.states[device->power.state].resources; |
517 | tl = &device->power.states[state].resources; | 517 | tl = &device->power.states[state].resources; |
518 | 518 | ||
519 | if (!cl->count && !tl->count) { | ||
520 | result = -ENODEV; | ||
521 | goto end; | ||
522 | } | ||
523 | |||
524 | /* TBD: Resources must be ordered. */ | 519 | /* TBD: Resources must be ordered. */ |
525 | 520 | ||
526 | /* | 521 | /* |
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 24a362f8034c..34948362f41d 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
@@ -59,7 +59,6 @@ | |||
59 | #include <acpi/acpi_drivers.h> | 59 | #include <acpi/acpi_drivers.h> |
60 | #include <acpi/processor.h> | 60 | #include <acpi/processor.h> |
61 | 61 | ||
62 | #define ACPI_PROCESSOR_COMPONENT 0x01000000 | ||
63 | #define ACPI_PROCESSOR_CLASS "processor" | 62 | #define ACPI_PROCESSOR_CLASS "processor" |
64 | #define ACPI_PROCESSOR_DEVICE_NAME "Processor" | 63 | #define ACPI_PROCESSOR_DEVICE_NAME "Processor" |
65 | #define ACPI_PROCESSOR_FILE_INFO "info" | 64 | #define ACPI_PROCESSOR_FILE_INFO "info" |
@@ -89,6 +88,7 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr); | |||
89 | 88 | ||
90 | 89 | ||
91 | static const struct acpi_device_id processor_device_ids[] = { | 90 | static const struct acpi_device_id processor_device_ids[] = { |
91 | {ACPI_PROCESSOR_OBJECT_HID, 0}, | ||
92 | {ACPI_PROCESSOR_HID, 0}, | 92 | {ACPI_PROCESSOR_HID, 0}, |
93 | {"", 0}, | 93 | {"", 0}, |
94 | }; | 94 | }; |
@@ -409,7 +409,7 @@ static int acpi_processor_remove_fs(struct acpi_device *device) | |||
409 | /* Use the acpiid in MADT to map cpus in case of SMP */ | 409 | /* Use the acpiid in MADT to map cpus in case of SMP */ |
410 | 410 | ||
411 | #ifndef CONFIG_SMP | 411 | #ifndef CONFIG_SMP |
412 | static int get_cpu_id(acpi_handle handle, u32 acpi_id) {return -1;} | 412 | static int get_cpu_id(acpi_handle handle, int type, u32 acpi_id) { return -1; } |
413 | #else | 413 | #else |
414 | 414 | ||
415 | static struct acpi_table_madt *madt; | 415 | static struct acpi_table_madt *madt; |
@@ -428,27 +428,35 @@ static int map_lapic_id(struct acpi_subtable_header *entry, | |||
428 | } | 428 | } |
429 | 429 | ||
430 | static int map_lsapic_id(struct acpi_subtable_header *entry, | 430 | static int map_lsapic_id(struct acpi_subtable_header *entry, |
431 | u32 acpi_id, int *apic_id) | 431 | int device_declaration, u32 acpi_id, int *apic_id) |
432 | { | 432 | { |
433 | struct acpi_madt_local_sapic *lsapic = | 433 | struct acpi_madt_local_sapic *lsapic = |
434 | (struct acpi_madt_local_sapic *)entry; | 434 | (struct acpi_madt_local_sapic *)entry; |
435 | u32 tmp = (lsapic->id << 8) | lsapic->eid; | ||
436 | |||
435 | /* Only check enabled APICs*/ | 437 | /* Only check enabled APICs*/ |
436 | if (lsapic->lapic_flags & ACPI_MADT_ENABLED) { | 438 | if (!(lsapic->lapic_flags & ACPI_MADT_ENABLED)) |
437 | /* First check against id */ | 439 | return 0; |
438 | if (lsapic->processor_id == acpi_id) { | 440 | |
439 | *apic_id = (lsapic->id << 8) | lsapic->eid; | 441 | /* Device statement declaration type */ |
440 | return 1; | 442 | if (device_declaration) { |
441 | /* Check against optional uid */ | 443 | if (entry->length < 16) |
442 | } else if (entry->length >= 16 && | 444 | printk(KERN_ERR PREFIX |
443 | lsapic->uid == acpi_id) { | 445 | "Invalid LSAPIC with Device type processor (SAPIC ID %#x)\n", |
444 | *apic_id = lsapic->uid; | 446 | tmp); |
445 | return 1; | 447 | else if (lsapic->uid == acpi_id) |
446 | } | 448 | goto found; |
447 | } | 449 | /* Processor statement declaration type */ |
450 | } else if (lsapic->processor_id == acpi_id) | ||
451 | goto found; | ||
452 | |||
448 | return 0; | 453 | return 0; |
454 | found: | ||
455 | *apic_id = tmp; | ||
456 | return 1; | ||
449 | } | 457 | } |
450 | 458 | ||
451 | static int map_madt_entry(u32 acpi_id) | 459 | static int map_madt_entry(int type, u32 acpi_id) |
452 | { | 460 | { |
453 | unsigned long madt_end, entry; | 461 | unsigned long madt_end, entry; |
454 | int apic_id = -1; | 462 | int apic_id = -1; |
@@ -469,7 +477,7 @@ static int map_madt_entry(u32 acpi_id) | |||
469 | if (map_lapic_id(header, acpi_id, &apic_id)) | 477 | if (map_lapic_id(header, acpi_id, &apic_id)) |
470 | break; | 478 | break; |
471 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { | 479 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { |
472 | if (map_lsapic_id(header, acpi_id, &apic_id)) | 480 | if (map_lsapic_id(header, type, acpi_id, &apic_id)) |
473 | break; | 481 | break; |
474 | } | 482 | } |
475 | entry += header->length; | 483 | entry += header->length; |
@@ -477,7 +485,7 @@ static int map_madt_entry(u32 acpi_id) | |||
477 | return apic_id; | 485 | return apic_id; |
478 | } | 486 | } |
479 | 487 | ||
480 | static int map_mat_entry(acpi_handle handle, u32 acpi_id) | 488 | static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id) |
481 | { | 489 | { |
482 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 490 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
483 | union acpi_object *obj; | 491 | union acpi_object *obj; |
@@ -500,7 +508,7 @@ static int map_mat_entry(acpi_handle handle, u32 acpi_id) | |||
500 | if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) { | 508 | if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) { |
501 | map_lapic_id(header, acpi_id, &apic_id); | 509 | map_lapic_id(header, acpi_id, &apic_id); |
502 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { | 510 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { |
503 | map_lsapic_id(header, acpi_id, &apic_id); | 511 | map_lsapic_id(header, type, acpi_id, &apic_id); |
504 | } | 512 | } |
505 | 513 | ||
506 | exit: | 514 | exit: |
@@ -509,14 +517,14 @@ exit: | |||
509 | return apic_id; | 517 | return apic_id; |
510 | } | 518 | } |
511 | 519 | ||
512 | static int get_cpu_id(acpi_handle handle, u32 acpi_id) | 520 | static int get_cpu_id(acpi_handle handle, int type, u32 acpi_id) |
513 | { | 521 | { |
514 | int i; | 522 | int i; |
515 | int apic_id = -1; | 523 | int apic_id = -1; |
516 | 524 | ||
517 | apic_id = map_mat_entry(handle, acpi_id); | 525 | apic_id = map_mat_entry(handle, type, acpi_id); |
518 | if (apic_id == -1) | 526 | if (apic_id == -1) |
519 | apic_id = map_madt_entry(acpi_id); | 527 | apic_id = map_madt_entry(type, acpi_id); |
520 | if (apic_id == -1) | 528 | if (apic_id == -1) |
521 | return apic_id; | 529 | return apic_id; |
522 | 530 | ||
@@ -532,15 +540,16 @@ static int get_cpu_id(acpi_handle handle, u32 acpi_id) | |||
532 | Driver Interface | 540 | Driver Interface |
533 | -------------------------------------------------------------------------- */ | 541 | -------------------------------------------------------------------------- */ |
534 | 542 | ||
535 | static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) | 543 | static int acpi_processor_get_info(struct acpi_device *device) |
536 | { | 544 | { |
537 | acpi_status status = 0; | 545 | acpi_status status = 0; |
538 | union acpi_object object = { 0 }; | 546 | union acpi_object object = { 0 }; |
539 | struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; | 547 | struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; |
540 | int cpu_index; | 548 | struct acpi_processor *pr; |
549 | int cpu_index, device_declaration = 0; | ||
541 | static int cpu0_initialized; | 550 | static int cpu0_initialized; |
542 | 551 | ||
543 | 552 | pr = acpi_driver_data(device); | |
544 | if (!pr) | 553 | if (!pr) |
545 | return -EINVAL; | 554 | return -EINVAL; |
546 | 555 | ||
@@ -561,22 +570,23 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) | |||
561 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 570 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
562 | "No bus mastering arbitration control\n")); | 571 | "No bus mastering arbitration control\n")); |
563 | 572 | ||
564 | /* Check if it is a Device with HID and UID */ | 573 | if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_HID)) { |
565 | if (has_uid) { | 574 | /* |
575 | * Declared with "Device" statement; match _UID. | ||
576 | * Note that we don't handle string _UIDs yet. | ||
577 | */ | ||
566 | unsigned long long value; | 578 | unsigned long long value; |
567 | status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, | 579 | status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, |
568 | NULL, &value); | 580 | NULL, &value); |
569 | if (ACPI_FAILURE(status)) { | 581 | if (ACPI_FAILURE(status)) { |
570 | printk(KERN_ERR PREFIX "Evaluating processor _UID\n"); | 582 | printk(KERN_ERR PREFIX |
583 | "Evaluating processor _UID [%#x]\n", status); | ||
571 | return -ENODEV; | 584 | return -ENODEV; |
572 | } | 585 | } |
586 | device_declaration = 1; | ||
573 | pr->acpi_id = value; | 587 | pr->acpi_id = value; |
574 | } else { | 588 | } else { |
575 | /* | 589 | /* Declared with "Processor" statement; match ProcessorID */ |
576 | * Evalute the processor object. Note that it is common on SMP to | ||
577 | * have the first (boot) processor with a valid PBLK address while | ||
578 | * all others have a NULL address. | ||
579 | */ | ||
580 | status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); | 590 | status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); |
581 | if (ACPI_FAILURE(status)) { | 591 | if (ACPI_FAILURE(status)) { |
582 | printk(KERN_ERR PREFIX "Evaluating processor object\n"); | 592 | printk(KERN_ERR PREFIX "Evaluating processor object\n"); |
@@ -584,12 +594,13 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) | |||
584 | } | 594 | } |
585 | 595 | ||
586 | /* | 596 | /* |
587 | * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. | 597 | * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. |
588 | * >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c | 598 | * >>> 'acpi_get_processor_id(acpi_id, &id)' in |
589 | */ | 599 | * arch/xxx/acpi.c |
600 | */ | ||
590 | pr->acpi_id = object.processor.proc_id; | 601 | pr->acpi_id = object.processor.proc_id; |
591 | } | 602 | } |
592 | cpu_index = get_cpu_id(pr->handle, pr->acpi_id); | 603 | cpu_index = get_cpu_id(pr->handle, device_declaration, pr->acpi_id); |
593 | 604 | ||
594 | /* Handle UP system running SMP kernel, with no LAPIC in MADT */ | 605 | /* Handle UP system running SMP kernel, with no LAPIC in MADT */ |
595 | if (!cpu0_initialized && (cpu_index == -1) && | 606 | if (!cpu0_initialized && (cpu_index == -1) && |
@@ -661,7 +672,7 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) | |||
661 | 672 | ||
662 | pr = acpi_driver_data(device); | 673 | pr = acpi_driver_data(device); |
663 | 674 | ||
664 | result = acpi_processor_get_info(pr, device->flags.unique_id); | 675 | result = acpi_processor_get_info(device); |
665 | if (result) { | 676 | if (result) { |
666 | /* Processor is physically not present */ | 677 | /* Processor is physically not present */ |
667 | return 0; | 678 | return 0; |
@@ -761,20 +772,20 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) | |||
761 | acpi_bus_generate_proc_event(device, event, | 772 | acpi_bus_generate_proc_event(device, event, |
762 | pr->performance_platform_limit); | 773 | pr->performance_platform_limit); |
763 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 774 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
764 | device->dev.bus_id, event, | 775 | dev_name(&device->dev), event, |
765 | pr->performance_platform_limit); | 776 | pr->performance_platform_limit); |
766 | break; | 777 | break; |
767 | case ACPI_PROCESSOR_NOTIFY_POWER: | 778 | case ACPI_PROCESSOR_NOTIFY_POWER: |
768 | acpi_processor_cst_has_changed(pr); | 779 | acpi_processor_cst_has_changed(pr); |
769 | acpi_bus_generate_proc_event(device, event, 0); | 780 | acpi_bus_generate_proc_event(device, event, 0); |
770 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 781 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
771 | device->dev.bus_id, event, 0); | 782 | dev_name(&device->dev), event, 0); |
772 | break; | 783 | break; |
773 | case ACPI_PROCESSOR_NOTIFY_THROTTLING: | 784 | case ACPI_PROCESSOR_NOTIFY_THROTTLING: |
774 | acpi_processor_tstate_has_changed(pr); | 785 | acpi_processor_tstate_has_changed(pr); |
775 | acpi_bus_generate_proc_event(device, event, 0); | 786 | acpi_bus_generate_proc_event(device, event, 0); |
776 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 787 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
777 | device->dev.bus_id, event, 0); | 788 | dev_name(&device->dev), event, 0); |
778 | default: | 789 | default: |
779 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 790 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
780 | "Unsupported event [0x%x]\n", event)); | 791 | "Unsupported event [0x%x]\n", event)); |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 81b40ed5379e..5f8d746a9b81 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -59,7 +59,6 @@ | |||
59 | #include <acpi/processor.h> | 59 | #include <acpi/processor.h> |
60 | #include <asm/processor.h> | 60 | #include <asm/processor.h> |
61 | 61 | ||
62 | #define ACPI_PROCESSOR_COMPONENT 0x01000000 | ||
63 | #define ACPI_PROCESSOR_CLASS "processor" | 62 | #define ACPI_PROCESSOR_CLASS "processor" |
64 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 63 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
65 | ACPI_MODULE_NAME("processor_idle"); | 64 | ACPI_MODULE_NAME("processor_idle"); |
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index dbcf260ea93f..0d7b772bef50 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
@@ -44,9 +44,9 @@ | |||
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | #include <acpi/acpi_bus.h> | 46 | #include <acpi/acpi_bus.h> |
47 | #include <acpi/acpi_drivers.h> | ||
47 | #include <acpi/processor.h> | 48 | #include <acpi/processor.h> |
48 | 49 | ||
49 | #define ACPI_PROCESSOR_COMPONENT 0x01000000 | ||
50 | #define ACPI_PROCESSOR_CLASS "processor" | 50 | #define ACPI_PROCESSOR_CLASS "processor" |
51 | #define ACPI_PROCESSOR_FILE_PERFORMANCE "performance" | 51 | #define ACPI_PROCESSOR_FILE_PERFORMANCE "performance" |
52 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 52 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index ef34b18f95ca..b1eb376fae45 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <acpi/processor.h> | 40 | #include <acpi/processor.h> |
41 | #include <acpi/acpi_drivers.h> | 41 | #include <acpi/acpi_drivers.h> |
42 | 42 | ||
43 | #define ACPI_PROCESSOR_COMPONENT 0x01000000 | ||
44 | #define ACPI_PROCESSOR_CLASS "processor" | 43 | #define ACPI_PROCESSOR_CLASS "processor" |
45 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 44 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
46 | ACPI_MODULE_NAME("processor_thermal"); | 45 | ACPI_MODULE_NAME("processor_thermal"); |
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 3da2df93d924..a0c38c94a8a0 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c | |||
@@ -38,9 +38,9 @@ | |||
38 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
39 | 39 | ||
40 | #include <acpi/acpi_bus.h> | 40 | #include <acpi/acpi_bus.h> |
41 | #include <acpi/acpi_drivers.h> | ||
41 | #include <acpi/processor.h> | 42 | #include <acpi/processor.h> |
42 | 43 | ||
43 | #define ACPI_PROCESSOR_COMPONENT 0x01000000 | ||
44 | #define ACPI_PROCESSOR_CLASS "processor" | 44 | #define ACPI_PROCESSOR_CLASS "processor" |
45 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 45 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
46 | ACPI_MODULE_NAME("processor_throttling"); | 46 | ACPI_MODULE_NAME("processor_throttling"); |
diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c index 755baf2ca70a..a6b662c00b67 100644 --- a/drivers/acpi/reboot.c +++ b/drivers/acpi/reboot.c | |||
@@ -15,28 +15,9 @@ void acpi_reboot(void) | |||
15 | 15 | ||
16 | rr = &acpi_gbl_FADT.reset_register; | 16 | rr = &acpi_gbl_FADT.reset_register; |
17 | 17 | ||
18 | /* | 18 | /* Is the reset register supported? */ |
19 | * Is the ACPI reset register supported? | 19 | if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) || |
20 | * | 20 | rr->bit_width != 8 || rr->bit_offset != 0) |
21 | * According to ACPI 3.0, FADT.flags.RESET_REG_SUP indicates | ||
22 | * whether the ACPI reset mechanism is supported. | ||
23 | * | ||
24 | * However, some boxes have this bit clear, yet a valid | ||
25 | * ACPI_RESET_REG & RESET_VALUE, and ACPI reboot is the only | ||
26 | * mechanism that works for them after S3. | ||
27 | * | ||
28 | * This suggests that other operating systems may not be checking | ||
29 | * the RESET_REG_SUP bit, and are using other means to decide | ||
30 | * whether to use the ACPI reboot mechanism or not. | ||
31 | * | ||
32 | * So when acpi reboot is requested, | ||
33 | * only the reset_register is checked. If the following | ||
34 | * conditions are met, it indicates that the reset register is supported. | ||
35 | * a. reset_register is not zero | ||
36 | * b. the access width is eight | ||
37 | * c. the bit_offset is zero | ||
38 | */ | ||
39 | if (!(rr->address) || rr->bit_width != 8 || rr->bit_offset != 0) | ||
40 | return; | 21 | return; |
41 | 22 | ||
42 | reset_value = acpi_gbl_FADT.reset_value; | 23 | reset_value = acpi_gbl_FADT.reset_value; |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a9dda8e0f9f9..bd5253ee5c85 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -109,8 +109,7 @@ static int acpi_bus_hot_remove_device(void *context) | |||
109 | return 0; | 109 | return 0; |
110 | 110 | ||
111 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 111 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
112 | "Hot-removing device %s...\n", device->dev.bus_id)); | 112 | "Hot-removing device %s...\n", dev_name(&device->dev))); |
113 | |||
114 | 113 | ||
115 | if (acpi_bus_trim(device, 1)) { | 114 | if (acpi_bus_trim(device, 1)) { |
116 | printk(KERN_ERR PREFIX | 115 | printk(KERN_ERR PREFIX |
@@ -460,7 +459,7 @@ static int acpi_device_register(struct acpi_device *device, | |||
460 | acpi_device_bus_id->instance_no = 0; | 459 | acpi_device_bus_id->instance_no = 0; |
461 | list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list); | 460 | list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list); |
462 | } | 461 | } |
463 | sprintf(device->dev.bus_id, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no); | 462 | dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no); |
464 | 463 | ||
465 | if (device->parent) { | 464 | if (device->parent) { |
466 | list_add_tail(&device->node, &device->parent->children); | 465 | list_add_tail(&device->node, &device->parent->children); |
@@ -484,7 +483,8 @@ static int acpi_device_register(struct acpi_device *device, | |||
484 | 483 | ||
485 | result = acpi_device_setup_files(device); | 484 | result = acpi_device_setup_files(device); |
486 | if(result) | 485 | if(result) |
487 | printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n", device->dev.bus_id); | 486 | printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n", |
487 | dev_name(&device->dev)); | ||
488 | 488 | ||
489 | device->removal_type = ACPI_BUS_REMOVAL_NORMAL; | 489 | device->removal_type = ACPI_BUS_REMOVAL_NORMAL; |
490 | return 0; | 490 | return 0; |
@@ -919,36 +919,6 @@ static void acpi_device_get_busid(struct acpi_device *device, | |||
919 | } | 919 | } |
920 | } | 920 | } |
921 | 921 | ||
922 | static int | ||
923 | acpi_video_bus_match(struct acpi_device *device) | ||
924 | { | ||
925 | acpi_handle h_dummy; | ||
926 | |||
927 | if (!device) | ||
928 | return -EINVAL; | ||
929 | |||
930 | /* Since there is no HID, CID for ACPI Video drivers, we have | ||
931 | * to check well known required nodes for each feature we support. | ||
932 | */ | ||
933 | |||
934 | /* Does this device able to support video switching ? */ | ||
935 | if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) && | ||
936 | ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy))) | ||
937 | return 0; | ||
938 | |||
939 | /* Does this device able to retrieve a video ROM ? */ | ||
940 | if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy))) | ||
941 | return 0; | ||
942 | |||
943 | /* Does this device able to configure which video head to be POSTed ? */ | ||
944 | if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) && | ||
945 | ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) && | ||
946 | ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy))) | ||
947 | return 0; | ||
948 | |||
949 | return -ENODEV; | ||
950 | } | ||
951 | |||
952 | /* | 922 | /* |
953 | * acpi_bay_match - see if a device is an ejectable driver bay | 923 | * acpi_bay_match - see if a device is an ejectable driver bay |
954 | * | 924 | * |
@@ -1031,7 +1001,7 @@ static void acpi_device_set_id(struct acpi_device *device, | |||
1031 | will get autoloaded and the device might still match | 1001 | will get autoloaded and the device might still match |
1032 | against another driver. | 1002 | against another driver. |
1033 | */ | 1003 | */ |
1034 | if (ACPI_SUCCESS(acpi_video_bus_match(device))) | 1004 | if (acpi_is_video_device(device)) |
1035 | cid_add = ACPI_VIDEO_HID; | 1005 | cid_add = ACPI_VIDEO_HID; |
1036 | else if (ACPI_SUCCESS(acpi_bay_match(device))) | 1006 | else if (ACPI_SUCCESS(acpi_bay_match(device))) |
1037 | cid_add = ACPI_BAY_HID; | 1007 | cid_add = ACPI_BAY_HID; |
@@ -1043,7 +1013,7 @@ static void acpi_device_set_id(struct acpi_device *device, | |||
1043 | hid = ACPI_POWER_HID; | 1013 | hid = ACPI_POWER_HID; |
1044 | break; | 1014 | break; |
1045 | case ACPI_BUS_TYPE_PROCESSOR: | 1015 | case ACPI_BUS_TYPE_PROCESSOR: |
1046 | hid = ACPI_PROCESSOR_HID; | 1016 | hid = ACPI_PROCESSOR_OBJECT_HID; |
1047 | break; | 1017 | break; |
1048 | case ACPI_BUS_TYPE_SYSTEM: | 1018 | case ACPI_BUS_TYPE_SYSTEM: |
1049 | hid = ACPI_SYSTEM_HID; | 1019 | hid = ACPI_SYSTEM_HID; |
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index 631ee2ee2ca0..64e591ba86f2 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c | |||
@@ -366,8 +366,8 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) | |||
366 | dev->wakeup.state.enabled ? "enabled" : "disabled"); | 366 | dev->wakeup.state.enabled ? "enabled" : "disabled"); |
367 | if (ldev) | 367 | if (ldev) |
368 | seq_printf(seq, "%s:%s", | 368 | seq_printf(seq, "%s:%s", |
369 | ldev->bus ? ldev->bus->name : "no-bus", | 369 | dev_name(ldev) ? ldev->bus->name : "no-bus", |
370 | ldev->bus_id); | 370 | dev_name(ldev)); |
371 | seq_printf(seq, "\n"); | 371 | seq_printf(seq, "\n"); |
372 | put_device(ldev); | 372 | put_device(ldev); |
373 | 373 | ||
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c index 38655eb132dc..dea4c23df764 100644 --- a/drivers/acpi/sleep/wakeup.c +++ b/drivers/acpi/sleep/wakeup.c | |||
@@ -88,7 +88,7 @@ void acpi_enable_wakeup_device(u8 sleep_state) | |||
88 | spin_unlock(&acpi_device_lock); | 88 | spin_unlock(&acpi_device_lock); |
89 | if (!dev->wakeup.flags.run_wake) | 89 | if (!dev->wakeup.flags.run_wake) |
90 | acpi_enable_gpe(dev->wakeup.gpe_device, | 90 | acpi_enable_gpe(dev->wakeup.gpe_device, |
91 | dev->wakeup.gpe_number, ACPI_ISR); | 91 | dev->wakeup.gpe_number); |
92 | spin_lock(&acpi_device_lock); | 92 | spin_lock(&acpi_device_lock); |
93 | } | 93 | } |
94 | spin_unlock(&acpi_device_lock); | 94 | spin_unlock(&acpi_device_lock); |
@@ -122,7 +122,7 @@ void acpi_disable_wakeup_device(u8 sleep_state) | |||
122 | ACPI_GPE_TYPE_WAKE_RUN); | 122 | ACPI_GPE_TYPE_WAKE_RUN); |
123 | /* Re-enable it, since set_gpe_type will disable it */ | 123 | /* Re-enable it, since set_gpe_type will disable it */ |
124 | acpi_enable_gpe(dev->wakeup.gpe_device, | 124 | acpi_enable_gpe(dev->wakeup.gpe_device, |
125 | dev->wakeup.gpe_number, ACPI_NOT_ISR); | 125 | dev->wakeup.gpe_number); |
126 | spin_lock(&acpi_device_lock); | 126 | spin_lock(&acpi_device_lock); |
127 | } | 127 | } |
128 | continue; | 128 | continue; |
@@ -133,7 +133,7 @@ void acpi_disable_wakeup_device(u8 sleep_state) | |||
133 | /* Never disable run-wake GPE */ | 133 | /* Never disable run-wake GPE */ |
134 | if (!dev->wakeup.flags.run_wake) { | 134 | if (!dev->wakeup.flags.run_wake) { |
135 | acpi_disable_gpe(dev->wakeup.gpe_device, | 135 | acpi_disable_gpe(dev->wakeup.gpe_device, |
136 | dev->wakeup.gpe_number, ACPI_NOT_ISR); | 136 | dev->wakeup.gpe_number); |
137 | acpi_clear_gpe(dev->wakeup.gpe_device, | 137 | acpi_clear_gpe(dev->wakeup.gpe_device, |
138 | dev->wakeup.gpe_number, ACPI_NOT_ISR); | 138 | dev->wakeup.gpe_number, ACPI_NOT_ISR); |
139 | } | 139 | } |
@@ -162,7 +162,7 @@ static int __init acpi_wakeup_device_init(void) | |||
162 | dev->wakeup.gpe_number, | 162 | dev->wakeup.gpe_number, |
163 | ACPI_GPE_TYPE_WAKE_RUN); | 163 | ACPI_GPE_TYPE_WAKE_RUN); |
164 | acpi_enable_gpe(dev->wakeup.gpe_device, | 164 | acpi_enable_gpe(dev->wakeup.gpe_device, |
165 | dev->wakeup.gpe_number, ACPI_NOT_ISR); | 165 | dev->wakeup.gpe_number); |
166 | dev->wakeup.state.enabled = 1; | 166 | dev->wakeup.state.enabled = 1; |
167 | spin_lock(&acpi_device_lock); | 167 | spin_lock(&acpi_device_lock); |
168 | } | 168 | } |
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 1d74171b7940..6e4107f82403 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c | |||
@@ -78,9 +78,15 @@ static ssize_t acpi_table_show(struct kobject *kobj, | |||
78 | container_of(bin_attr, struct acpi_table_attr, attr); | 78 | container_of(bin_attr, struct acpi_table_attr, attr); |
79 | struct acpi_table_header *table_header = NULL; | 79 | struct acpi_table_header *table_header = NULL; |
80 | acpi_status status; | 80 | acpi_status status; |
81 | char name[ACPI_NAME_SIZE]; | ||
82 | |||
83 | if (strncmp(table_attr->name, "NULL", 4)) | ||
84 | memcpy(name, table_attr->name, ACPI_NAME_SIZE); | ||
85 | else | ||
86 | memcpy(name, "\0\0\0\0", 4); | ||
81 | 87 | ||
82 | status = | 88 | status = |
83 | acpi_get_table(table_attr->name, table_attr->instance, | 89 | acpi_get_table(name, table_attr->instance, |
84 | &table_header); | 90 | &table_header); |
85 | if (ACPI_FAILURE(status)) | 91 | if (ACPI_FAILURE(status)) |
86 | return -ENODEV; | 92 | return -ENODEV; |
@@ -95,21 +101,24 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr, | |||
95 | struct acpi_table_header *header = NULL; | 101 | struct acpi_table_header *header = NULL; |
96 | struct acpi_table_attr *attr = NULL; | 102 | struct acpi_table_attr *attr = NULL; |
97 | 103 | ||
98 | memcpy(table_attr->name, table_header->signature, ACPI_NAME_SIZE); | 104 | if (table_header->signature[0] != '\0') |
105 | memcpy(table_attr->name, table_header->signature, | ||
106 | ACPI_NAME_SIZE); | ||
107 | else | ||
108 | memcpy(table_attr->name, "NULL", 4); | ||
99 | 109 | ||
100 | list_for_each_entry(attr, &acpi_table_attr_list, node) { | 110 | list_for_each_entry(attr, &acpi_table_attr_list, node) { |
101 | if (!memcmp(table_header->signature, attr->name, | 111 | if (!memcmp(table_attr->name, attr->name, ACPI_NAME_SIZE)) |
102 | ACPI_NAME_SIZE)) | ||
103 | if (table_attr->instance < attr->instance) | 112 | if (table_attr->instance < attr->instance) |
104 | table_attr->instance = attr->instance; | 113 | table_attr->instance = attr->instance; |
105 | } | 114 | } |
106 | table_attr->instance++; | 115 | table_attr->instance++; |
107 | 116 | ||
108 | if (table_attr->instance > 1 || (table_attr->instance == 1 && | 117 | if (table_attr->instance > 1 || (table_attr->instance == 1 && |
109 | !acpi_get_table(table_header-> | 118 | !acpi_get_table |
110 | signature, 2, | 119 | (table_header->signature, 2, &header))) |
111 | &header))) | 120 | sprintf(table_attr->name + ACPI_NAME_SIZE, "%d", |
112 | sprintf(table_attr->name + 4, "%d", table_attr->instance); | 121 | table_attr->instance); |
113 | 122 | ||
114 | table_attr->attr.size = 0; | 123 | table_attr->attr.size = 0; |
115 | table_attr->attr.read = acpi_table_show; | 124 | table_attr->attr.read = acpi_table_show; |
@@ -167,7 +176,6 @@ static int acpi_system_sysfs_init(void) | |||
167 | #define COUNT_ERROR 2 /* other */ | 176 | #define COUNT_ERROR 2 /* other */ |
168 | #define NUM_COUNTERS_EXTRA 3 | 177 | #define NUM_COUNTERS_EXTRA 3 |
169 | 178 | ||
170 | #define ACPI_EVENT_VALID 0x01 | ||
171 | struct event_counter { | 179 | struct event_counter { |
172 | u32 count; | 180 | u32 count; |
173 | u32 flags; | 181 | u32 flags; |
@@ -312,12 +320,6 @@ static int get_status(u32 index, acpi_event_status *status, acpi_handle *handle) | |||
312 | } else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS)) | 320 | } else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS)) |
313 | result = acpi_get_event_status(index - num_gpes, status); | 321 | result = acpi_get_event_status(index - num_gpes, status); |
314 | 322 | ||
315 | /* | ||
316 | * sleep/power button GPE/Fixed Event is enabled after acpi_system_init, | ||
317 | * check the status at runtime and mark it as valid once it's enabled | ||
318 | */ | ||
319 | if (!result && (*status & ACPI_EVENT_FLAG_ENABLED)) | ||
320 | all_counters[index].flags |= ACPI_EVENT_VALID; | ||
321 | end: | 323 | end: |
322 | return result; | 324 | return result; |
323 | } | 325 | } |
@@ -346,12 +348,14 @@ static ssize_t counter_show(struct kobject *kobj, | |||
346 | if (result) | 348 | if (result) |
347 | goto end; | 349 | goto end; |
348 | 350 | ||
349 | if (!(all_counters[index].flags & ACPI_EVENT_VALID)) | 351 | if (!(status & ACPI_EVENT_FLAG_HANDLE)) |
350 | size += sprintf(buf + size, " invalid"); | 352 | size += sprintf(buf + size, " invalid"); |
351 | else if (status & ACPI_EVENT_FLAG_ENABLED) | 353 | else if (status & ACPI_EVENT_FLAG_ENABLED) |
352 | size += sprintf(buf + size, " enable"); | 354 | size += sprintf(buf + size, " enabled"); |
355 | else if (status & ACPI_EVENT_FLAG_WAKE_ENABLED) | ||
356 | size += sprintf(buf + size, " wake_enabled"); | ||
353 | else | 357 | else |
354 | size += sprintf(buf + size, " disable"); | 358 | size += sprintf(buf + size, " disabled"); |
355 | 359 | ||
356 | end: | 360 | end: |
357 | size += sprintf(buf + size, "\n"); | 361 | size += sprintf(buf + size, "\n"); |
@@ -385,7 +389,7 @@ static ssize_t counter_set(struct kobject *kobj, | |||
385 | if (result) | 389 | if (result) |
386 | goto end; | 390 | goto end; |
387 | 391 | ||
388 | if (!(all_counters[index].flags & ACPI_EVENT_VALID)) { | 392 | if (!(status & ACPI_EVENT_FLAG_HANDLE)) { |
389 | printk(KERN_WARNING PREFIX | 393 | printk(KERN_WARNING PREFIX |
390 | "Can not change Invalid GPE/Fixed Event status\n"); | 394 | "Can not change Invalid GPE/Fixed Event status\n"); |
391 | return -EINVAL; | 395 | return -EINVAL; |
@@ -394,10 +398,10 @@ static ssize_t counter_set(struct kobject *kobj, | |||
394 | if (index < num_gpes) { | 398 | if (index < num_gpes) { |
395 | if (!strcmp(buf, "disable\n") && | 399 | if (!strcmp(buf, "disable\n") && |
396 | (status & ACPI_EVENT_FLAG_ENABLED)) | 400 | (status & ACPI_EVENT_FLAG_ENABLED)) |
397 | result = acpi_disable_gpe(handle, index, ACPI_NOT_ISR); | 401 | result = acpi_disable_gpe(handle, index); |
398 | else if (!strcmp(buf, "enable\n") && | 402 | else if (!strcmp(buf, "enable\n") && |
399 | !(status & ACPI_EVENT_FLAG_ENABLED)) | 403 | !(status & ACPI_EVENT_FLAG_ENABLED)) |
400 | result = acpi_enable_gpe(handle, index, ACPI_NOT_ISR); | 404 | result = acpi_enable_gpe(handle, index); |
401 | else if (!strcmp(buf, "clear\n") && | 405 | else if (!strcmp(buf, "clear\n") && |
402 | (status & ACPI_EVENT_FLAG_SET)) | 406 | (status & ACPI_EVENT_FLAG_SET)) |
403 | result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR); | 407 | result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR); |
diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c index 2c7885e7ffba..2817158fb6a1 100644 --- a/drivers/acpi/tables/tbfadt.c +++ b/drivers/acpi/tables/tbfadt.c | |||
@@ -304,7 +304,7 @@ static void acpi_tb_convert_fadt(void) | |||
304 | * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at | 304 | * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at |
305 | * offset 45, 55, 95, and the word located at offset 109, 110. | 305 | * offset 45, 55, 95, and the word located at offset 109, 110. |
306 | */ | 306 | */ |
307 | if (acpi_gbl_FADT.header.revision < 3) { | 307 | if (acpi_gbl_FADT.header.revision < FADT2_REVISION_ID) { |
308 | acpi_gbl_FADT.preferred_profile = 0; | 308 | acpi_gbl_FADT.preferred_profile = 0; |
309 | acpi_gbl_FADT.pstate_control = 0; | 309 | acpi_gbl_FADT.pstate_control = 0; |
310 | acpi_gbl_FADT.cst_control = 0; | 310 | acpi_gbl_FADT.cst_control = 0; |
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index ad6cae938f0b..073ff09218a9 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c | |||
@@ -47,7 +47,6 @@ | |||
47 | #include <acpi/acpi_bus.h> | 47 | #include <acpi/acpi_bus.h> |
48 | #include <acpi/acpi_drivers.h> | 48 | #include <acpi/acpi_drivers.h> |
49 | 49 | ||
50 | #define ACPI_THERMAL_COMPONENT 0x04000000 | ||
51 | #define ACPI_THERMAL_CLASS "thermal_zone" | 50 | #define ACPI_THERMAL_CLASS "thermal_zone" |
52 | #define ACPI_THERMAL_DEVICE_NAME "Thermal Zone" | 51 | #define ACPI_THERMAL_DEVICE_NAME "Thermal Zone" |
53 | #define ACPI_THERMAL_FILE_STATE "state" | 52 | #define ACPI_THERMAL_FILE_STATE "state" |
@@ -576,7 +575,7 @@ static int acpi_thermal_critical(struct acpi_thermal *tz) | |||
576 | acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL, | 575 | acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL, |
577 | tz->trips.critical.flags.enabled); | 576 | tz->trips.critical.flags.enabled); |
578 | acpi_bus_generate_netlink_event(tz->device->pnp.device_class, | 577 | acpi_bus_generate_netlink_event(tz->device->pnp.device_class, |
579 | tz->device->dev.bus_id, | 578 | dev_name(&tz->device->dev), |
580 | ACPI_THERMAL_NOTIFY_CRITICAL, | 579 | ACPI_THERMAL_NOTIFY_CRITICAL, |
581 | tz->trips.critical.flags.enabled); | 580 | tz->trips.critical.flags.enabled); |
582 | 581 | ||
@@ -605,7 +604,7 @@ static int acpi_thermal_hot(struct acpi_thermal *tz) | |||
605 | acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_HOT, | 604 | acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_HOT, |
606 | tz->trips.hot.flags.enabled); | 605 | tz->trips.hot.flags.enabled); |
607 | acpi_bus_generate_netlink_event(tz->device->pnp.device_class, | 606 | acpi_bus_generate_netlink_event(tz->device->pnp.device_class, |
608 | tz->device->dev.bus_id, | 607 | dev_name(&tz->device->dev), |
609 | ACPI_THERMAL_NOTIFY_HOT, | 608 | ACPI_THERMAL_NOTIFY_HOT, |
610 | tz->trips.hot.flags.enabled); | 609 | tz->trips.hot.flags.enabled); |
611 | 610 | ||
@@ -1592,14 +1591,14 @@ static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data) | |||
1592 | acpi_thermal_check(tz); | 1591 | acpi_thermal_check(tz); |
1593 | acpi_bus_generate_proc_event(device, event, 0); | 1592 | acpi_bus_generate_proc_event(device, event, 0); |
1594 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 1593 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
1595 | device->dev.bus_id, event, 0); | 1594 | dev_name(&device->dev), event, 0); |
1596 | break; | 1595 | break; |
1597 | case ACPI_THERMAL_NOTIFY_DEVICES: | 1596 | case ACPI_THERMAL_NOTIFY_DEVICES: |
1598 | acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES); | 1597 | acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES); |
1599 | acpi_thermal_check(tz); | 1598 | acpi_thermal_check(tz); |
1600 | acpi_bus_generate_proc_event(device, event, 0); | 1599 | acpi_bus_generate_proc_event(device, event, 0); |
1601 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 1600 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
1602 | device->dev.bus_id, event, 0); | 1601 | dev_name(&device->dev), event, 0); |
1603 | break; | 1602 | break; |
1604 | default: | 1603 | default: |
1605 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 1604 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index a29b0ccac65a..baa441929720 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <acpi/acpi_bus.h> | 41 | #include <acpi/acpi_bus.h> |
42 | #include <acpi/acpi_drivers.h> | 42 | #include <acpi/acpi_drivers.h> |
43 | 43 | ||
44 | #define ACPI_VIDEO_COMPONENT 0x08000000 | ||
45 | #define ACPI_VIDEO_CLASS "video" | 44 | #define ACPI_VIDEO_CLASS "video" |
46 | #define ACPI_VIDEO_BUS_NAME "Video Bus" | 45 | #define ACPI_VIDEO_BUS_NAME "Video Bus" |
47 | #define ACPI_VIDEO_DEVICE_NAME "Video Device" | 46 | #define ACPI_VIDEO_DEVICE_NAME "Video Device" |
@@ -739,7 +738,8 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
739 | device->cap._DSS = 1; | 738 | device->cap._DSS = 1; |
740 | } | 739 | } |
741 | 740 | ||
742 | max_level = acpi_video_init_brightness(device); | 741 | if (acpi_video_backlight_support()) |
742 | max_level = acpi_video_init_brightness(device); | ||
743 | 743 | ||
744 | if (device->cap._BCL && device->cap._BCM && max_level > 0) { | 744 | if (device->cap._BCL && device->cap._BCM && max_level > 0) { |
745 | int result; | 745 | int result; |
@@ -785,18 +785,21 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
785 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | 785 | printk(KERN_ERR PREFIX "Create sysfs link\n"); |
786 | 786 | ||
787 | } | 787 | } |
788 | if (device->cap._DCS && device->cap._DSS){ | 788 | |
789 | static int count = 0; | 789 | if (acpi_video_display_switch_support()) { |
790 | char *name; | 790 | |
791 | name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); | 791 | if (device->cap._DCS && device->cap._DSS) { |
792 | if (!name) | 792 | static int count; |
793 | return; | 793 | char *name; |
794 | sprintf(name, "acpi_video%d", count++); | 794 | name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); |
795 | device->output_dev = video_output_register(name, | 795 | if (!name) |
796 | NULL, device, &acpi_output_properties); | 796 | return; |
797 | kfree(name); | 797 | sprintf(name, "acpi_video%d", count++); |
798 | device->output_dev = video_output_register(name, | ||
799 | NULL, device, &acpi_output_properties); | ||
800 | kfree(name); | ||
801 | } | ||
798 | } | 802 | } |
799 | return; | ||
800 | } | 803 | } |
801 | 804 | ||
802 | /* | 805 | /* |
@@ -842,11 +845,16 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video) | |||
842 | static int acpi_video_bus_check(struct acpi_video_bus *video) | 845 | static int acpi_video_bus_check(struct acpi_video_bus *video) |
843 | { | 846 | { |
844 | acpi_status status = -ENOENT; | 847 | acpi_status status = -ENOENT; |
845 | 848 | struct device *dev; | |
846 | 849 | ||
847 | if (!video) | 850 | if (!video) |
848 | return -EINVAL; | 851 | return -EINVAL; |
849 | 852 | ||
853 | dev = acpi_get_physical_pci_device(video->device->handle); | ||
854 | if (!dev) | ||
855 | return -ENODEV; | ||
856 | put_device(dev); | ||
857 | |||
850 | /* Since there is no HID, CID and so on for VGA driver, we have | 858 | /* Since there is no HID, CID and so on for VGA driver, we have |
851 | * to check well known required nodes. | 859 | * to check well known required nodes. |
852 | */ | 860 | */ |
@@ -2094,12 +2102,6 @@ static int __init acpi_video_init(void) | |||
2094 | { | 2102 | { |
2095 | int result = 0; | 2103 | int result = 0; |
2096 | 2104 | ||
2097 | |||
2098 | /* | ||
2099 | acpi_dbg_level = 0xFFFFFFFF; | ||
2100 | acpi_dbg_layer = 0x08000000; | ||
2101 | */ | ||
2102 | |||
2103 | acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); | 2105 | acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); |
2104 | if (!acpi_video_dir) | 2106 | if (!acpi_video_dir) |
2105 | return -ENODEV; | 2107 | return -ENODEV; |
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c new file mode 100644 index 000000000000..f022eb6f5637 --- /dev/null +++ b/drivers/acpi/video_detect.c | |||
@@ -0,0 +1,267 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 SuSE Linux Products GmbH | ||
3 | * Thomas Renninger <trenn@suse.de> | ||
4 | * | ||
5 | * May be copied or modified under the terms of the GNU General Public License | ||
6 | * | ||
7 | * video_detect.c: | ||
8 | * Provides acpi_is_video_device() for early scanning of ACPI devices in scan.c | ||
9 | * There a Linux specific (Spec does not provide a HID for video devices) is | ||
10 | * assinged | ||
11 | * | ||
12 | * After PCI devices are glued with ACPI devices | ||
13 | * acpi_get_physical_pci_device() can be called to identify ACPI graphics | ||
14 | * devices for which a real graphics card is plugged in | ||
15 | * | ||
16 | * Now acpi_video_get_capabilities() can be called to check which | ||
17 | * capabilities the graphics cards plugged in support. The check for general | ||
18 | * video capabilities will be triggered by the first caller of | ||
19 | * acpi_video_get_capabilities(NULL); which will happen when the first | ||
20 | * backlight (or display output) switching supporting driver calls: | ||
21 | * acpi_video_backlight_support(); | ||
22 | * | ||
23 | * Depending on whether ACPI graphics extensions (cmp. ACPI spec Appendix B) | ||
24 | * are available, video.ko should be used to handle the device. | ||
25 | * | ||
26 | * Otherwise vendor specific drivers like thinkpad_acpi, asus_acpi, | ||
27 | * sony_acpi,... can take care about backlight brightness and display output | ||
28 | * switching. | ||
29 | * | ||
30 | * If CONFIG_ACPI_VIDEO is neither set as "compiled in" (y) nor as a module (m) | ||
31 | * this file will not be compiled, acpi_video_get_capabilities() and | ||
32 | * acpi_video_backlight_support() will always return 0 and vendor specific | ||
33 | * drivers always can handle backlight. | ||
34 | * | ||
35 | */ | ||
36 | |||
37 | #include <linux/acpi.h> | ||
38 | #include <linux/dmi.h> | ||
39 | |||
40 | ACPI_MODULE_NAME("video"); | ||
41 | #define _COMPONENT ACPI_VIDEO_COMPONENT | ||
42 | |||
43 | static long acpi_video_support; | ||
44 | static bool acpi_video_caps_checked; | ||
45 | |||
46 | static acpi_status | ||
47 | acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context, | ||
48 | void **retyurn_value) | ||
49 | { | ||
50 | long *cap = context; | ||
51 | acpi_handle h_dummy; | ||
52 | |||
53 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_BCM", &h_dummy)) && | ||
54 | ACPI_SUCCESS(acpi_get_handle(handle, "_BCL", &h_dummy))) { | ||
55 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight " | ||
56 | "support\n")); | ||
57 | *cap |= ACPI_VIDEO_BACKLIGHT; | ||
58 | /* We have backlight support, no need to scan further */ | ||
59 | return AE_CTRL_TERMINATE; | ||
60 | } | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | /* Returns true if the device is a video device which can be handled by | ||
65 | * video.ko. | ||
66 | * The device will get a Linux specific CID added in scan.c to | ||
67 | * identify the device as an ACPI graphics device | ||
68 | * Be aware that the graphics device may not be physically present | ||
69 | * Use acpi_video_get_capabilities() to detect general ACPI video | ||
70 | * capabilities of present cards | ||
71 | */ | ||
72 | long acpi_is_video_device(struct acpi_device *device) | ||
73 | { | ||
74 | acpi_handle h_dummy; | ||
75 | long video_caps = 0; | ||
76 | |||
77 | if (!device) | ||
78 | return 0; | ||
79 | |||
80 | /* Does this device able to support video switching ? */ | ||
81 | if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) && | ||
82 | ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy))) | ||
83 | video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING; | ||
84 | |||
85 | /* Does this device able to retrieve a video ROM ? */ | ||
86 | if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy))) | ||
87 | video_caps |= ACPI_VIDEO_ROM_AVAILABLE; | ||
88 | |||
89 | /* Does this device able to configure which video head to be POSTed ? */ | ||
90 | if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) && | ||
91 | ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) && | ||
92 | ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy))) | ||
93 | video_caps |= ACPI_VIDEO_DEVICE_POSTING; | ||
94 | |||
95 | /* Only check for backlight functionality if one of the above hit. */ | ||
96 | if (video_caps) | ||
97 | acpi_walk_namespace(ACPI_TYPE_DEVICE, device->handle, | ||
98 | ACPI_UINT32_MAX, acpi_backlight_cap_match, | ||
99 | &video_caps, NULL); | ||
100 | |||
101 | return video_caps; | ||
102 | } | ||
103 | EXPORT_SYMBOL(acpi_is_video_device); | ||
104 | |||
105 | static acpi_status | ||
106 | find_video(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
107 | { | ||
108 | long *cap = context; | ||
109 | struct device *dev; | ||
110 | struct acpi_device *acpi_dev; | ||
111 | |||
112 | const struct acpi_device_id video_ids[] = { | ||
113 | {ACPI_VIDEO_HID, 0}, | ||
114 | {"", 0}, | ||
115 | }; | ||
116 | if (acpi_bus_get_device(handle, &acpi_dev)) | ||
117 | return AE_OK; | ||
118 | |||
119 | if (!acpi_match_device_ids(acpi_dev, video_ids)) { | ||
120 | dev = acpi_get_physical_pci_device(handle); | ||
121 | if (!dev) | ||
122 | return AE_OK; | ||
123 | put_device(dev); | ||
124 | *cap |= acpi_is_video_device(acpi_dev); | ||
125 | } | ||
126 | return AE_OK; | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | * Returns the video capabilities of a specific ACPI graphics device | ||
131 | * | ||
132 | * if NULL is passed as argument all ACPI devices are enumerated and | ||
133 | * all graphics capabilities of physically present devices are | ||
134 | * summerized and returned. This is cached and done only once. | ||
135 | */ | ||
136 | long acpi_video_get_capabilities(acpi_handle graphics_handle) | ||
137 | { | ||
138 | long caps = 0; | ||
139 | struct acpi_device *tmp_dev; | ||
140 | acpi_status status; | ||
141 | |||
142 | if (acpi_video_caps_checked && graphics_handle == NULL) | ||
143 | return acpi_video_support; | ||
144 | |||
145 | if (!graphics_handle) { | ||
146 | /* Only do the global walk through all graphics devices once */ | ||
147 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
148 | ACPI_UINT32_MAX, find_video, | ||
149 | &caps, NULL); | ||
150 | /* There might be boot param flags set already... */ | ||
151 | acpi_video_support |= caps; | ||
152 | acpi_video_caps_checked = 1; | ||
153 | /* Add blacklists here. Be careful to use the right *DMI* bits | ||
154 | * to still be able to override logic via boot params, e.g.: | ||
155 | * | ||
156 | * if (dmi_name_in_vendors("XY")) { | ||
157 | * acpi_video_support |= | ||
158 | * ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR; | ||
159 | * acpi_video_support |= | ||
160 | * ACPI_VIDEO_BACKLIGHT_DMI_VENDOR; | ||
161 | *} | ||
162 | */ | ||
163 | } else { | ||
164 | status = acpi_bus_get_device(graphics_handle, &tmp_dev); | ||
165 | if (ACPI_FAILURE(status)) { | ||
166 | ACPI_EXCEPTION((AE_INFO, status, "Invalid device")); | ||
167 | return 0; | ||
168 | } | ||
169 | acpi_walk_namespace(ACPI_TYPE_DEVICE, graphics_handle, | ||
170 | ACPI_UINT32_MAX, find_video, | ||
171 | &caps, NULL); | ||
172 | } | ||
173 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "We have 0x%lX video support %s %s\n", | ||
174 | graphics_handle ? caps : acpi_video_support, | ||
175 | graphics_handle ? "on device " : "in general", | ||
176 | graphics_handle ? acpi_device_bid(tmp_dev) : "")); | ||
177 | return caps; | ||
178 | } | ||
179 | EXPORT_SYMBOL(acpi_video_get_capabilities); | ||
180 | |||
181 | /* Returns true if video.ko can do backlight switching */ | ||
182 | int acpi_video_backlight_support(void) | ||
183 | { | ||
184 | /* | ||
185 | * We must check whether the ACPI graphics device is physically plugged | ||
186 | * in. Therefore this must be called after binding PCI and ACPI devices | ||
187 | */ | ||
188 | if (!acpi_video_caps_checked) | ||
189 | acpi_video_get_capabilities(NULL); | ||
190 | |||
191 | /* First check for boot param -> highest prio */ | ||
192 | if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR) | ||
193 | return 0; | ||
194 | else if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO) | ||
195 | return 1; | ||
196 | |||
197 | /* Then check for DMI blacklist -> second highest prio */ | ||
198 | if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_DMI_VENDOR) | ||
199 | return 0; | ||
200 | else if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_DMI_VIDEO) | ||
201 | return 1; | ||
202 | |||
203 | /* Then go the default way */ | ||
204 | return acpi_video_support & ACPI_VIDEO_BACKLIGHT; | ||
205 | } | ||
206 | EXPORT_SYMBOL(acpi_video_backlight_support); | ||
207 | |||
208 | /* | ||
209 | * Returns true if video.ko can do display output switching. | ||
210 | * This does not work well/at all with binary graphics drivers | ||
211 | * which disable system io ranges and do it on their own. | ||
212 | */ | ||
213 | int acpi_video_display_switch_support(void) | ||
214 | { | ||
215 | if (!acpi_video_caps_checked) | ||
216 | acpi_video_get_capabilities(NULL); | ||
217 | |||
218 | if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR) | ||
219 | return 0; | ||
220 | else if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO) | ||
221 | return 1; | ||
222 | |||
223 | if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR) | ||
224 | return 0; | ||
225 | else if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO) | ||
226 | return 1; | ||
227 | |||
228 | return acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING; | ||
229 | } | ||
230 | EXPORT_SYMBOL(acpi_video_display_switch_support); | ||
231 | |||
232 | /* | ||
233 | * Use acpi_display_output=vendor/video or acpi_backlight=vendor/video | ||
234 | * To force that backlight or display output switching is processed by vendor | ||
235 | * specific acpi drivers or video.ko driver. | ||
236 | */ | ||
237 | int __init acpi_backlight(char *str) | ||
238 | { | ||
239 | if (str == NULL || *str == '\0') | ||
240 | return 1; | ||
241 | else { | ||
242 | if (!strcmp("vendor", str)) | ||
243 | acpi_video_support |= | ||
244 | ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR; | ||
245 | if (!strcmp("video", str)) | ||
246 | acpi_video_support |= | ||
247 | ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO; | ||
248 | } | ||
249 | return 1; | ||
250 | } | ||
251 | __setup("acpi_backlight=", acpi_backlight); | ||
252 | |||
253 | int __init acpi_display_output(char *str) | ||
254 | { | ||
255 | if (str == NULL || *str == '\0') | ||
256 | return 1; | ||
257 | else { | ||
258 | if (!strcmp("vendor", str)) | ||
259 | acpi_video_support |= | ||
260 | ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR; | ||
261 | if (!strcmp("video", str)) | ||
262 | acpi_video_support |= | ||
263 | ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO; | ||
264 | } | ||
265 | return 1; | ||
266 | } | ||
267 | __setup("acpi_display_output=", acpi_display_output); | ||
diff --git a/drivers/acpi/wmi.c b/drivers/acpi/wmi.c index 47cd7baf9b1b..8a8b377712c9 100644 --- a/drivers/acpi/wmi.c +++ b/drivers/acpi/wmi.c | |||
@@ -660,7 +660,7 @@ static void acpi_wmi_notify(acpi_handle handle, u32 event, void *data) | |||
660 | wblock->handler(event, wblock->handler_data); | 660 | wblock->handler(event, wblock->handler_data); |
661 | 661 | ||
662 | acpi_bus_generate_netlink_event( | 662 | acpi_bus_generate_netlink_event( |
663 | device->pnp.device_class, device->dev.bus_id, | 663 | device->pnp.device_class, dev_name(&device->dev), |
664 | event, 0); | 664 | event, 0); |
665 | break; | 665 | break; |
666 | } | 666 | } |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 8a59aaa21be5..7a88dfd4427b 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -422,9 +422,11 @@ struct ipmi_smi { | |||
422 | /** | 422 | /** |
423 | * The driver model view of the IPMI messaging driver. | 423 | * The driver model view of the IPMI messaging driver. |
424 | */ | 424 | */ |
425 | static struct device_driver ipmidriver = { | 425 | static struct platform_driver ipmidriver = { |
426 | .name = "ipmi", | 426 | .driver = { |
427 | .bus = &platform_bus_type | 427 | .name = "ipmi", |
428 | .bus = &platform_bus_type | ||
429 | } | ||
428 | }; | 430 | }; |
429 | static DEFINE_MUTEX(ipmidriver_mutex); | 431 | static DEFINE_MUTEX(ipmidriver_mutex); |
430 | 432 | ||
@@ -2384,9 +2386,9 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, | |||
2384 | * representing the interfaced BMC already | 2386 | * representing the interfaced BMC already |
2385 | */ | 2387 | */ |
2386 | if (bmc->guid_set) | 2388 | if (bmc->guid_set) |
2387 | old_bmc = ipmi_find_bmc_guid(&ipmidriver, bmc->guid); | 2389 | old_bmc = ipmi_find_bmc_guid(&ipmidriver.driver, bmc->guid); |
2388 | else | 2390 | else |
2389 | old_bmc = ipmi_find_bmc_prod_dev_id(&ipmidriver, | 2391 | old_bmc = ipmi_find_bmc_prod_dev_id(&ipmidriver.driver, |
2390 | bmc->id.product_id, | 2392 | bmc->id.product_id, |
2391 | bmc->id.device_id); | 2393 | bmc->id.device_id); |
2392 | 2394 | ||
@@ -2416,7 +2418,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, | |||
2416 | snprintf(name, sizeof(name), | 2418 | snprintf(name, sizeof(name), |
2417 | "ipmi_bmc.%4.4x", bmc->id.product_id); | 2419 | "ipmi_bmc.%4.4x", bmc->id.product_id); |
2418 | 2420 | ||
2419 | while (ipmi_find_bmc_prod_dev_id(&ipmidriver, | 2421 | while (ipmi_find_bmc_prod_dev_id(&ipmidriver.driver, |
2420 | bmc->id.product_id, | 2422 | bmc->id.product_id, |
2421 | bmc->id.device_id)) { | 2423 | bmc->id.device_id)) { |
2422 | if (!warn_printed) { | 2424 | if (!warn_printed) { |
@@ -2446,7 +2448,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, | |||
2446 | " Unable to allocate platform device\n"); | 2448 | " Unable to allocate platform device\n"); |
2447 | return -ENOMEM; | 2449 | return -ENOMEM; |
2448 | } | 2450 | } |
2449 | bmc->dev->dev.driver = &ipmidriver; | 2451 | bmc->dev->dev.driver = &ipmidriver.driver; |
2450 | dev_set_drvdata(&bmc->dev->dev, bmc); | 2452 | dev_set_drvdata(&bmc->dev->dev, bmc); |
2451 | kref_init(&bmc->refcount); | 2453 | kref_init(&bmc->refcount); |
2452 | 2454 | ||
@@ -4247,7 +4249,7 @@ static int ipmi_init_msghandler(void) | |||
4247 | if (initialized) | 4249 | if (initialized) |
4248 | return 0; | 4250 | return 0; |
4249 | 4251 | ||
4250 | rv = driver_register(&ipmidriver); | 4252 | rv = driver_register(&ipmidriver.driver); |
4251 | if (rv) { | 4253 | if (rv) { |
4252 | printk(KERN_ERR PFX "Could not register IPMI driver\n"); | 4254 | printk(KERN_ERR PFX "Could not register IPMI driver\n"); |
4253 | return rv; | 4255 | return rv; |
@@ -4308,7 +4310,7 @@ static __exit void cleanup_ipmi(void) | |||
4308 | remove_proc_entry(proc_ipmi_root->name, NULL); | 4310 | remove_proc_entry(proc_ipmi_root->name, NULL); |
4309 | #endif /* CONFIG_PROC_FS */ | 4311 | #endif /* CONFIG_PROC_FS */ |
4310 | 4312 | ||
4311 | driver_unregister(&ipmidriver); | 4313 | driver_unregister(&ipmidriver.driver); |
4312 | 4314 | ||
4313 | initialized = 0; | 4315 | initialized = 0; |
4314 | 4316 | ||
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 3123bf57ad91..3000135f2ead 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -114,9 +114,11 @@ static char *si_to_str[] = { "kcs", "smic", "bt" }; | |||
114 | 114 | ||
115 | #define DEVICE_NAME "ipmi_si" | 115 | #define DEVICE_NAME "ipmi_si" |
116 | 116 | ||
117 | static struct device_driver ipmi_driver = { | 117 | static struct platform_driver ipmi_driver = { |
118 | .name = DEVICE_NAME, | 118 | .driver = { |
119 | .bus = &platform_bus_type | 119 | .name = DEVICE_NAME, |
120 | .bus = &platform_bus_type | ||
121 | } | ||
120 | }; | 122 | }; |
121 | 123 | ||
122 | 124 | ||
@@ -2868,7 +2870,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2868 | goto out_err; | 2870 | goto out_err; |
2869 | } | 2871 | } |
2870 | new_smi->dev = &new_smi->pdev->dev; | 2872 | new_smi->dev = &new_smi->pdev->dev; |
2871 | new_smi->dev->driver = &ipmi_driver; | 2873 | new_smi->dev->driver = &ipmi_driver.driver; |
2872 | 2874 | ||
2873 | rv = platform_device_add(new_smi->pdev); | 2875 | rv = platform_device_add(new_smi->pdev); |
2874 | if (rv) { | 2876 | if (rv) { |
@@ -2983,7 +2985,7 @@ static __devinit int init_ipmi_si(void) | |||
2983 | initialized = 1; | 2985 | initialized = 1; |
2984 | 2986 | ||
2985 | /* Register the device drivers. */ | 2987 | /* Register the device drivers. */ |
2986 | rv = driver_register(&ipmi_driver); | 2988 | rv = driver_register(&ipmi_driver.driver); |
2987 | if (rv) { | 2989 | if (rv) { |
2988 | printk(KERN_ERR | 2990 | printk(KERN_ERR |
2989 | "init_ipmi_si: Unable to register driver: %d\n", | 2991 | "init_ipmi_si: Unable to register driver: %d\n", |
@@ -3052,7 +3054,7 @@ static __devinit int init_ipmi_si(void) | |||
3052 | #ifdef CONFIG_PPC_OF | 3054 | #ifdef CONFIG_PPC_OF |
3053 | of_unregister_platform_driver(&ipmi_of_platform_driver); | 3055 | of_unregister_platform_driver(&ipmi_of_platform_driver); |
3054 | #endif | 3056 | #endif |
3055 | driver_unregister(&ipmi_driver); | 3057 | driver_unregister(&ipmi_driver.driver); |
3056 | printk(KERN_WARNING | 3058 | printk(KERN_WARNING |
3057 | "ipmi_si: Unable to find any System Interface(s)\n"); | 3059 | "ipmi_si: Unable to find any System Interface(s)\n"); |
3058 | return -ENODEV; | 3060 | return -ENODEV; |
@@ -3151,7 +3153,7 @@ static __exit void cleanup_ipmi_si(void) | |||
3151 | cleanup_one_si(e); | 3153 | cleanup_one_si(e); |
3152 | mutex_unlock(&smi_infos_lock); | 3154 | mutex_unlock(&smi_infos_lock); |
3153 | 3155 | ||
3154 | driver_unregister(&ipmi_driver); | 3156 | driver_unregister(&ipmi_driver.driver); |
3155 | } | 3157 | } |
3156 | module_exit(cleanup_ipmi_si); | 3158 | module_exit(cleanup_ipmi_si); |
3157 | 3159 | ||
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 2457b07dabd6..f4374437a033 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c | |||
@@ -523,7 +523,7 @@ static int acpi_driver_registered; | |||
523 | 523 | ||
524 | static int sonypi_ec_write(u8 addr, u8 value) | 524 | static int sonypi_ec_write(u8 addr, u8 value) |
525 | { | 525 | { |
526 | #ifdef CONFIG_ACPI_EC | 526 | #ifdef CONFIG_ACPI |
527 | if (SONYPI_ACPI_ACTIVE) | 527 | if (SONYPI_ACPI_ACTIVE) |
528 | return ec_write(addr, value); | 528 | return ec_write(addr, value); |
529 | #endif | 529 | #endif |
@@ -539,7 +539,7 @@ static int sonypi_ec_write(u8 addr, u8 value) | |||
539 | 539 | ||
540 | static int sonypi_ec_read(u8 addr, u8 *value) | 540 | static int sonypi_ec_read(u8 addr, u8 *value) |
541 | { | 541 | { |
542 | #ifdef CONFIG_ACPI_EC | 542 | #ifdef CONFIG_ACPI |
543 | if (SONYPI_ACPI_ACTIVE) | 543 | if (SONYPI_ACPI_ACTIVE) |
544 | return ec_read(addr, value); | 544 | return ec_read(addr, value); |
545 | #endif | 545 | #endif |
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index dc003a3a787d..5317e08221ec 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c | |||
@@ -399,8 +399,8 @@ int dma_async_device_register(struct dma_device *device) | |||
399 | chan->chan_id = chancnt++; | 399 | chan->chan_id = chancnt++; |
400 | chan->dev.class = &dma_devclass; | 400 | chan->dev.class = &dma_devclass; |
401 | chan->dev.parent = device->dev; | 401 | chan->dev.parent = device->dev; |
402 | snprintf(chan->dev.bus_id, BUS_ID_SIZE, "dma%dchan%d", | 402 | dev_set_name(&chan->dev, "dma%dchan%d", |
403 | device->dev_id, chan->chan_id); | 403 | device->dev_id, chan->chan_id); |
404 | 404 | ||
405 | rc = device_register(&chan->dev); | 405 | rc = device_register(&chan->dev); |
406 | if (rc) { | 406 | if (rc) { |
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index d1e381e35a9e..ed9636bfb54a 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c | |||
@@ -20,11 +20,11 @@ static unsigned int test_buf_size = 16384; | |||
20 | module_param(test_buf_size, uint, S_IRUGO); | 20 | module_param(test_buf_size, uint, S_IRUGO); |
21 | MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer"); | 21 | MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer"); |
22 | 22 | ||
23 | static char test_channel[BUS_ID_SIZE]; | 23 | static char test_channel[20]; |
24 | module_param_string(channel, test_channel, sizeof(test_channel), S_IRUGO); | 24 | module_param_string(channel, test_channel, sizeof(test_channel), S_IRUGO); |
25 | MODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)"); | 25 | MODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)"); |
26 | 26 | ||
27 | static char test_device[BUS_ID_SIZE]; | 27 | static char test_device[20]; |
28 | module_param_string(device, test_device, sizeof(test_device), S_IRUGO); | 28 | module_param_string(device, test_device, sizeof(test_device), S_IRUGO); |
29 | MODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)"); | 29 | MODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)"); |
30 | 30 | ||
@@ -80,14 +80,14 @@ static bool dmatest_match_channel(struct dma_chan *chan) | |||
80 | { | 80 | { |
81 | if (test_channel[0] == '\0') | 81 | if (test_channel[0] == '\0') |
82 | return true; | 82 | return true; |
83 | return strcmp(chan->dev.bus_id, test_channel) == 0; | 83 | return strcmp(dev_name(&chan->dev), test_channel) == 0; |
84 | } | 84 | } |
85 | 85 | ||
86 | static bool dmatest_match_device(struct dma_device *device) | 86 | static bool dmatest_match_device(struct dma_device *device) |
87 | { | 87 | { |
88 | if (test_device[0] == '\0') | 88 | if (test_device[0] == '\0') |
89 | return true; | 89 | return true; |
90 | return strcmp(device->dev->bus_id, test_device) == 0; | 90 | return strcmp(dev_name(device->dev), test_device) == 0; |
91 | } | 91 | } |
92 | 92 | ||
93 | static unsigned long dmatest_random(void) | 93 | static unsigned long dmatest_random(void) |
@@ -332,7 +332,7 @@ static enum dma_state_client dmatest_add_channel(struct dma_chan *chan) | |||
332 | 332 | ||
333 | dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL); | 333 | dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL); |
334 | if (!dtc) { | 334 | if (!dtc) { |
335 | pr_warning("dmatest: No memory for %s\n", chan->dev.bus_id); | 335 | pr_warning("dmatest: No memory for %s\n", dev_name(&chan->dev)); |
336 | return DMA_NAK; | 336 | return DMA_NAK; |
337 | } | 337 | } |
338 | 338 | ||
@@ -343,16 +343,16 @@ static enum dma_state_client dmatest_add_channel(struct dma_chan *chan) | |||
343 | thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL); | 343 | thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL); |
344 | if (!thread) { | 344 | if (!thread) { |
345 | pr_warning("dmatest: No memory for %s-test%u\n", | 345 | pr_warning("dmatest: No memory for %s-test%u\n", |
346 | chan->dev.bus_id, i); | 346 | dev_name(&chan->dev), i); |
347 | break; | 347 | break; |
348 | } | 348 | } |
349 | thread->chan = dtc->chan; | 349 | thread->chan = dtc->chan; |
350 | smp_wmb(); | 350 | smp_wmb(); |
351 | thread->task = kthread_run(dmatest_func, thread, "%s-test%u", | 351 | thread->task = kthread_run(dmatest_func, thread, "%s-test%u", |
352 | chan->dev.bus_id, i); | 352 | dev_name(&chan->dev), i); |
353 | if (IS_ERR(thread->task)) { | 353 | if (IS_ERR(thread->task)) { |
354 | pr_warning("dmatest: Failed to run thread %s-test%u\n", | 354 | pr_warning("dmatest: Failed to run thread %s-test%u\n", |
355 | chan->dev.bus_id, i); | 355 | dev_name(&chan->dev), i); |
356 | kfree(thread); | 356 | kfree(thread); |
357 | break; | 357 | break; |
358 | } | 358 | } |
@@ -362,7 +362,7 @@ static enum dma_state_client dmatest_add_channel(struct dma_chan *chan) | |||
362 | list_add_tail(&thread->node, &dtc->threads); | 362 | list_add_tail(&thread->node, &dtc->threads); |
363 | } | 363 | } |
364 | 364 | ||
365 | pr_info("dmatest: Started %u threads using %s\n", i, chan->dev.bus_id); | 365 | pr_info("dmatest: Started %u threads using %s\n", i, dev_name(&chan->dev)); |
366 | 366 | ||
367 | list_add_tail(&dtc->node, &dmatest_channels); | 367 | list_add_tail(&dtc->node, &dmatest_channels); |
368 | nr_channels++; | 368 | nr_channels++; |
@@ -379,7 +379,7 @@ static enum dma_state_client dmatest_remove_channel(struct dma_chan *chan) | |||
379 | list_del(&dtc->node); | 379 | list_del(&dtc->node); |
380 | dmatest_cleanup_channel(dtc); | 380 | dmatest_cleanup_channel(dtc); |
381 | pr_debug("dmatest: lost channel %s\n", | 381 | pr_debug("dmatest: lost channel %s\n", |
382 | chan->dev.bus_id); | 382 | dev_name(&chan->dev)); |
383 | return DMA_ACK; | 383 | return DMA_ACK; |
384 | } | 384 | } |
385 | } | 385 | } |
@@ -418,7 +418,7 @@ dmatest_event(struct dma_client *client, struct dma_chan *chan, | |||
418 | 418 | ||
419 | default: | 419 | default: |
420 | pr_info("dmatest: Unhandled event %u (%s)\n", | 420 | pr_info("dmatest: Unhandled event %u (%s)\n", |
421 | state, chan->dev.bus_id); | 421 | state, dev_name(&chan->dev)); |
422 | break; | 422 | break; |
423 | } | 423 | } |
424 | 424 | ||
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index 71fba82462cb..c7a9306d951d 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c | |||
@@ -411,6 +411,7 @@ iop_adma_tx_submit(struct dma_async_tx_descriptor *tx) | |||
411 | int slot_cnt; | 411 | int slot_cnt; |
412 | int slots_per_op; | 412 | int slots_per_op; |
413 | dma_cookie_t cookie; | 413 | dma_cookie_t cookie; |
414 | dma_addr_t next_dma; | ||
414 | 415 | ||
415 | grp_start = sw_desc->group_head; | 416 | grp_start = sw_desc->group_head; |
416 | slot_cnt = grp_start->slot_cnt; | 417 | slot_cnt = grp_start->slot_cnt; |
@@ -425,12 +426,12 @@ iop_adma_tx_submit(struct dma_async_tx_descriptor *tx) | |||
425 | &old_chain_tail->chain_node); | 426 | &old_chain_tail->chain_node); |
426 | 427 | ||
427 | /* fix up the hardware chain */ | 428 | /* fix up the hardware chain */ |
428 | iop_desc_set_next_desc(old_chain_tail, grp_start->async_tx.phys); | 429 | next_dma = grp_start->async_tx.phys; |
430 | iop_desc_set_next_desc(old_chain_tail, next_dma); | ||
431 | BUG_ON(iop_desc_get_next_desc(old_chain_tail) != next_dma); /* flush */ | ||
429 | 432 | ||
430 | /* 1/ don't add pre-chained descriptors | 433 | /* check for pre-chained descriptors */ |
431 | * 2/ dummy read to flush next_desc write | 434 | iop_paranoia(iop_desc_get_next_desc(sw_desc)); |
432 | */ | ||
433 | BUG_ON(iop_desc_get_next_desc(sw_desc)); | ||
434 | 435 | ||
435 | /* increment the pending count by the number of slots | 436 | /* increment the pending count by the number of slots |
436 | * memcpy operations have a 1:1 (slot:operation) relation | 437 | * memcpy operations have a 1:1 (slot:operation) relation |
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index f0d9b415db50..d335086f4a26 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c | |||
@@ -1381,6 +1381,7 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) | |||
1381 | if (mci == NULL) | 1381 | if (mci == NULL) |
1382 | return -ENOMEM; | 1382 | return -ENOMEM; |
1383 | 1383 | ||
1384 | kobject_get(&mci->edac_mci_kobj); | ||
1384 | debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); | 1385 | debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); |
1385 | 1386 | ||
1386 | mci->dev = &pdev->dev; /* record ptr to the generic device */ | 1387 | mci->dev = &pdev->dev; /* record ptr to the generic device */ |
@@ -1453,6 +1454,7 @@ fail1: | |||
1453 | i5000_put_devices(mci); | 1454 | i5000_put_devices(mci); |
1454 | 1455 | ||
1455 | fail0: | 1456 | fail0: |
1457 | kobject_put(&mci->edac_mci_kobj); | ||
1456 | edac_mc_free(mci); | 1458 | edac_mc_free(mci); |
1457 | return -ENODEV; | 1459 | return -ENODEV; |
1458 | } | 1460 | } |
@@ -1498,7 +1500,7 @@ static void __devexit i5000_remove_one(struct pci_dev *pdev) | |||
1498 | 1500 | ||
1499 | /* retrieve references to resources, and free those resources */ | 1501 | /* retrieve references to resources, and free those resources */ |
1500 | i5000_put_devices(mci); | 1502 | i5000_put_devices(mci); |
1501 | 1503 | kobject_put(&mci->edac_mci_kobj); | |
1502 | edac_mc_free(mci); | 1504 | edac_mc_free(mci); |
1503 | } | 1505 | } |
1504 | 1506 | ||
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 7f2ee27fe76b..48f49d93d249 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -65,6 +65,14 @@ config GPIO_SYSFS | |||
65 | 65 | ||
66 | # put expanders in the right section, in alphabetical order | 66 | # put expanders in the right section, in alphabetical order |
67 | 67 | ||
68 | comment "Memory mapped GPIO expanders:" | ||
69 | |||
70 | config GPIO_XILINX | ||
71 | bool "Xilinx GPIO support" | ||
72 | depends on PPC_OF | ||
73 | help | ||
74 | Say yes here to support the Xilinx FPGA GPIO device | ||
75 | |||
68 | comment "I2C GPIO expanders:" | 76 | comment "I2C GPIO expanders:" |
69 | 77 | ||
70 | config GPIO_MAX732X | 78 | config GPIO_MAX732X |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 6aafdeb9ad03..49ac64e515e6 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -10,4 +10,5 @@ obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o | |||
10 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o | 10 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o |
11 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o | 11 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o |
12 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o | 12 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o |
13 | obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o | ||
13 | obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o | 14 | obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o |
diff --git a/drivers/gpio/xilinx_gpio.c b/drivers/gpio/xilinx_gpio.c new file mode 100644 index 000000000000..3c1177abebd3 --- /dev/null +++ b/drivers/gpio/xilinx_gpio.c | |||
@@ -0,0 +1,235 @@ | |||
1 | /* | ||
2 | * Xilinx gpio driver | ||
3 | * | ||
4 | * Copyright 2008 Xilinx, Inc. | ||
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 version 2 | ||
8 | * as published by the Free Software Foundation. | ||
9 | * | ||
10 | * You should have received a copy of the GNU General Public License | ||
11 | * along with this program; if not, write to the Free Software | ||
12 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
13 | */ | ||
14 | |||
15 | #include <linux/init.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/of_device.h> | ||
18 | #include <linux/of_platform.h> | ||
19 | #include <linux/of_gpio.h> | ||
20 | #include <linux/io.h> | ||
21 | #include <linux/gpio.h> | ||
22 | |||
23 | /* Register Offset Definitions */ | ||
24 | #define XGPIO_DATA_OFFSET (0x0) /* Data register */ | ||
25 | #define XGPIO_TRI_OFFSET (0x4) /* I/O direction register */ | ||
26 | |||
27 | struct xgpio_instance { | ||
28 | struct of_mm_gpio_chip mmchip; | ||
29 | u32 gpio_state; /* GPIO state shadow register */ | ||
30 | u32 gpio_dir; /* GPIO direction shadow register */ | ||
31 | spinlock_t gpio_lock; /* Lock used for synchronization */ | ||
32 | }; | ||
33 | |||
34 | /** | ||
35 | * xgpio_get - Read the specified signal of the GPIO device. | ||
36 | * @gc: Pointer to gpio_chip device structure. | ||
37 | * @gpio: GPIO signal number. | ||
38 | * | ||
39 | * This function reads the specified signal of the GPIO device. It returns 0 if | ||
40 | * the signal clear, 1 if signal is set or negative value on error. | ||
41 | */ | ||
42 | static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) | ||
43 | { | ||
44 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
45 | |||
46 | return (in_be32(mm_gc->regs + XGPIO_DATA_OFFSET) >> gpio) & 1; | ||
47 | } | ||
48 | |||
49 | /** | ||
50 | * xgpio_set - Write the specified signal of the GPIO device. | ||
51 | * @gc: Pointer to gpio_chip device structure. | ||
52 | * @gpio: GPIO signal number. | ||
53 | * @val: Value to be written to specified signal. | ||
54 | * | ||
55 | * This function writes the specified value in to the specified signal of the | ||
56 | * GPIO device. | ||
57 | */ | ||
58 | static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | ||
59 | { | ||
60 | unsigned long flags; | ||
61 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
62 | struct xgpio_instance *chip = | ||
63 | container_of(mm_gc, struct xgpio_instance, mmchip); | ||
64 | |||
65 | spin_lock_irqsave(&chip->gpio_lock, flags); | ||
66 | |||
67 | /* Write to GPIO signal and set its direction to output */ | ||
68 | if (val) | ||
69 | chip->gpio_state |= 1 << gpio; | ||
70 | else | ||
71 | chip->gpio_state &= ~(1 << gpio); | ||
72 | out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); | ||
73 | |||
74 | spin_unlock_irqrestore(&chip->gpio_lock, flags); | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * xgpio_dir_in - Set the direction of the specified GPIO signal as input. | ||
79 | * @gc: Pointer to gpio_chip device structure. | ||
80 | * @gpio: GPIO signal number. | ||
81 | * | ||
82 | * This function sets the direction of specified GPIO signal as input. | ||
83 | * It returns 0 if direction of GPIO signals is set as input otherwise it | ||
84 | * returns negative error value. | ||
85 | */ | ||
86 | static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) | ||
87 | { | ||
88 | unsigned long flags; | ||
89 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
90 | struct xgpio_instance *chip = | ||
91 | container_of(mm_gc, struct xgpio_instance, mmchip); | ||
92 | |||
93 | spin_lock_irqsave(&chip->gpio_lock, flags); | ||
94 | |||
95 | /* Set the GPIO bit in shadow register and set direction as input */ | ||
96 | chip->gpio_dir |= (1 << gpio); | ||
97 | out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); | ||
98 | |||
99 | spin_unlock_irqrestore(&chip->gpio_lock, flags); | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | /** | ||
105 | * xgpio_dir_out - Set the direction of the specified GPIO signal as output. | ||
106 | * @gc: Pointer to gpio_chip device structure. | ||
107 | * @gpio: GPIO signal number. | ||
108 | * @val: Value to be written to specified signal. | ||
109 | * | ||
110 | * This function sets the direction of specified GPIO signal as output. If all | ||
111 | * GPIO signals of GPIO chip is configured as input then it returns | ||
112 | * error otherwise it returns 0. | ||
113 | */ | ||
114 | static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | ||
115 | { | ||
116 | unsigned long flags; | ||
117 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
118 | struct xgpio_instance *chip = | ||
119 | container_of(mm_gc, struct xgpio_instance, mmchip); | ||
120 | |||
121 | spin_lock_irqsave(&chip->gpio_lock, flags); | ||
122 | |||
123 | /* Write state of GPIO signal */ | ||
124 | if (val) | ||
125 | chip->gpio_state |= 1 << gpio; | ||
126 | else | ||
127 | chip->gpio_state &= ~(1 << gpio); | ||
128 | out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); | ||
129 | |||
130 | /* Clear the GPIO bit in shadow register and set direction as output */ | ||
131 | chip->gpio_dir &= (~(1 << gpio)); | ||
132 | out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); | ||
133 | |||
134 | spin_unlock_irqrestore(&chip->gpio_lock, flags); | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * xgpio_save_regs - Set initial values of GPIO pins | ||
141 | * @mm_gc: pointer to memory mapped GPIO chip structure | ||
142 | */ | ||
143 | static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc) | ||
144 | { | ||
145 | struct xgpio_instance *chip = | ||
146 | container_of(mm_gc, struct xgpio_instance, mmchip); | ||
147 | |||
148 | out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); | ||
149 | out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * xgpio_of_probe - Probe method for the GPIO device. | ||
154 | * @np: pointer to device tree node | ||
155 | * | ||
156 | * This function probes the GPIO device in the device tree. It initializes the | ||
157 | * driver data structure. It returns 0, if the driver is bound to the GPIO | ||
158 | * device, or a negative value if there is an error. | ||
159 | */ | ||
160 | static int __devinit xgpio_of_probe(struct device_node *np) | ||
161 | { | ||
162 | struct xgpio_instance *chip; | ||
163 | struct of_gpio_chip *ofchip; | ||
164 | int status = 0; | ||
165 | const u32 *tree_info; | ||
166 | |||
167 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
168 | if (!chip) | ||
169 | return -ENOMEM; | ||
170 | ofchip = &chip->mmchip.of_gc; | ||
171 | |||
172 | /* Update GPIO state shadow register with default value */ | ||
173 | tree_info = of_get_property(np, "xlnx,dout-default", NULL); | ||
174 | if (tree_info) | ||
175 | chip->gpio_state = *tree_info; | ||
176 | |||
177 | /* Update GPIO direction shadow register with default value */ | ||
178 | chip->gpio_dir = 0xFFFFFFFF; /* By default, all pins are inputs */ | ||
179 | tree_info = of_get_property(np, "xlnx,tri-default", NULL); | ||
180 | if (tree_info) | ||
181 | chip->gpio_dir = *tree_info; | ||
182 | |||
183 | /* Check device node and parent device node for device width */ | ||
184 | ofchip->gc.ngpio = 32; /* By default assume full GPIO controller */ | ||
185 | tree_info = of_get_property(np, "xlnx,gpio-width", NULL); | ||
186 | if (!tree_info) | ||
187 | tree_info = of_get_property(np->parent, | ||
188 | "xlnx,gpio-width", NULL); | ||
189 | if (tree_info) | ||
190 | ofchip->gc.ngpio = *tree_info; | ||
191 | |||
192 | spin_lock_init(&chip->gpio_lock); | ||
193 | |||
194 | ofchip->gpio_cells = 2; | ||
195 | ofchip->gc.direction_input = xgpio_dir_in; | ||
196 | ofchip->gc.direction_output = xgpio_dir_out; | ||
197 | ofchip->gc.get = xgpio_get; | ||
198 | ofchip->gc.set = xgpio_set; | ||
199 | |||
200 | chip->mmchip.save_regs = xgpio_save_regs; | ||
201 | |||
202 | /* Call the OF gpio helper to setup and register the GPIO device */ | ||
203 | status = of_mm_gpiochip_add(np, &chip->mmchip); | ||
204 | if (status) { | ||
205 | kfree(chip); | ||
206 | pr_err("%s: error in probe function with status %d\n", | ||
207 | np->full_name, status); | ||
208 | return status; | ||
209 | } | ||
210 | pr_info("XGpio: %s: registered\n", np->full_name); | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static struct of_device_id xgpio_of_match[] __devinitdata = { | ||
215 | { .compatible = "xlnx,xps-gpio-1.00.a", }, | ||
216 | { /* end of list */ }, | ||
217 | }; | ||
218 | |||
219 | static int __init xgpio_init(void) | ||
220 | { | ||
221 | struct device_node *np; | ||
222 | |||
223 | for_each_matching_node(np, xgpio_of_match) | ||
224 | xgpio_of_probe(np); | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | /* Make sure we get initialized before anyone else tries to use us */ | ||
230 | subsys_initcall(xgpio_init); | ||
231 | /* No exit call at the moment as we cannot unregister of GPIO chips */ | ||
232 | |||
233 | MODULE_AUTHOR("Xilinx, Inc."); | ||
234 | MODULE_DESCRIPTION("Xilinx GPIO driver"); | ||
235 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 6de1e0ffd391..c709e821f04b 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -159,6 +159,16 @@ config SENSORS_ADM9240 | |||
159 | This driver can also be built as a module. If so, the module | 159 | This driver can also be built as a module. If so, the module |
160 | will be called adm9240. | 160 | will be called adm9240. |
161 | 161 | ||
162 | config SENSORS_ADT7462 | ||
163 | tristate "Analog Devices ADT7462" | ||
164 | depends on I2C && EXPERIMENTAL | ||
165 | help | ||
166 | If you say yes here you get support for the Analog Devices | ||
167 | ADT7462 temperature monitoring chips. | ||
168 | |||
169 | This driver can also be built as a module. If so, the module | ||
170 | will be called adt7462. | ||
171 | |||
162 | config SENSORS_ADT7470 | 172 | config SENSORS_ADT7470 |
163 | tristate "Analog Devices ADT7470" | 173 | tristate "Analog Devices ADT7470" |
164 | depends on I2C && EXPERIMENTAL | 174 | depends on I2C && EXPERIMENTAL |
@@ -825,6 +835,25 @@ config SENSORS_HDAPS | |||
825 | Say Y here if you have an applicable laptop and want to experience | 835 | Say Y here if you have an applicable laptop and want to experience |
826 | the awesome power of hdaps. | 836 | the awesome power of hdaps. |
827 | 837 | ||
838 | config SENSORS_LIS3LV02D | ||
839 | tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer" | ||
840 | depends on ACPI && INPUT | ||
841 | default n | ||
842 | help | ||
843 | This driver provides support for the LIS3LV02Dx accelerometer. In | ||
844 | particular, it can be found in a number of HP laptops, which have the | ||
845 | "Mobile Data Protection System 3D" or "3D DriveGuard" feature. On such | ||
846 | systems the driver should load automatically (via ACPI). The | ||
847 | accelerometer might also be found in other systems, connected via SPI | ||
848 | or I2C. The accelerometer data is readable via | ||
849 | /sys/devices/platform/lis3lv02d. | ||
850 | |||
851 | This driver also provides an absolute input class device, allowing | ||
852 | the laptop to act as a pinball machine-esque joystick. | ||
853 | |||
854 | This driver can also be built as a module. If so, the module | ||
855 | will be called lis3lv02d. | ||
856 | |||
828 | config SENSORS_APPLESMC | 857 | config SENSORS_APPLESMC |
829 | tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)" | 858 | tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)" |
830 | depends on INPUT && X86 | 859 | depends on INPUT && X86 |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 042d5a78622e..58fc5be5355d 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -25,6 +25,7 @@ obj-$(CONFIG_SENSORS_ADM1029) += adm1029.o | |||
25 | obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o | 25 | obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o |
26 | obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o | 26 | obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o |
27 | obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o | 27 | obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o |
28 | obj-$(CONFIG_SENSORS_ADT7462) += adt7462.o | ||
28 | obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o | 29 | obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o |
29 | obj-$(CONFIG_SENSORS_ADT7473) += adt7473.o | 30 | obj-$(CONFIG_SENSORS_ADT7473) += adt7473.o |
30 | obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o | 31 | obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o |
@@ -48,6 +49,7 @@ obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o | |||
48 | obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o | 49 | obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o |
49 | obj-$(CONFIG_SENSORS_IT87) += it87.o | 50 | obj-$(CONFIG_SENSORS_IT87) += it87.o |
50 | obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o | 51 | obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o |
52 | obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o | ||
51 | obj-$(CONFIG_SENSORS_LM63) += lm63.o | 53 | obj-$(CONFIG_SENSORS_LM63) += lm63.o |
52 | obj-$(CONFIG_SENSORS_LM70) += lm70.o | 54 | obj-$(CONFIG_SENSORS_LM70) += lm70.o |
53 | obj-$(CONFIG_SENSORS_LM75) += lm75.o | 55 | obj-$(CONFIG_SENSORS_LM75) += lm75.o |
diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c new file mode 100644 index 000000000000..66107b4dc12a --- /dev/null +++ b/drivers/hwmon/adt7462.c | |||
@@ -0,0 +1,2002 @@ | |||
1 | /* | ||
2 | * A hwmon driver for the Analog Devices ADT7462 | ||
3 | * Copyright (C) 2008 IBM | ||
4 | * | ||
5 | * Author: Darrick J. Wong <djwong@us.ibm.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/jiffies.h> | ||
24 | #include <linux/i2c.h> | ||
25 | #include <linux/hwmon.h> | ||
26 | #include <linux/hwmon-sysfs.h> | ||
27 | #include <linux/err.h> | ||
28 | #include <linux/mutex.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/log2.h> | ||
31 | |||
32 | /* Addresses to scan */ | ||
33 | static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END }; | ||
34 | |||
35 | /* Insmod parameters */ | ||
36 | I2C_CLIENT_INSMOD_1(adt7462); | ||
37 | |||
38 | /* ADT7462 registers */ | ||
39 | #define ADT7462_REG_DEVICE 0x3D | ||
40 | #define ADT7462_REG_VENDOR 0x3E | ||
41 | #define ADT7462_REG_REVISION 0x3F | ||
42 | |||
43 | #define ADT7462_REG_MIN_TEMP_BASE_ADDR 0x44 | ||
44 | #define ADT7462_REG_MIN_TEMP_MAX_ADDR 0x47 | ||
45 | #define ADT7462_REG_MAX_TEMP_BASE_ADDR 0x48 | ||
46 | #define ADT7462_REG_MAX_TEMP_MAX_ADDR 0x4B | ||
47 | #define ADT7462_REG_TEMP_BASE_ADDR 0x88 | ||
48 | #define ADT7462_REG_TEMP_MAX_ADDR 0x8F | ||
49 | |||
50 | #define ADT7462_REG_FAN_BASE_ADDR 0x98 | ||
51 | #define ADT7462_REG_FAN_MAX_ADDR 0x9F | ||
52 | #define ADT7462_REG_FAN2_BASE_ADDR 0xA2 | ||
53 | #define ADT7462_REG_FAN2_MAX_ADDR 0xA9 | ||
54 | #define ADT7462_REG_FAN_ENABLE 0x07 | ||
55 | #define ADT7462_REG_FAN_MIN_BASE_ADDR 0x78 | ||
56 | #define ADT7462_REG_FAN_MIN_MAX_ADDR 0x7F | ||
57 | |||
58 | #define ADT7462_REG_CFG2 0x02 | ||
59 | #define ADT7462_FSPD_MASK 0x20 | ||
60 | |||
61 | #define ADT7462_REG_PWM_BASE_ADDR 0xAA | ||
62 | #define ADT7462_REG_PWM_MAX_ADDR 0xAD | ||
63 | #define ADT7462_REG_PWM_MIN_BASE_ADDR 0x28 | ||
64 | #define ADT7462_REG_PWM_MIN_MAX_ADDR 0x2B | ||
65 | #define ADT7462_REG_PWM_MAX 0x2C | ||
66 | #define ADT7462_REG_PWM_TEMP_MIN_BASE_ADDR 0x5C | ||
67 | #define ADT7462_REG_PWM_TEMP_MIN_MAX_ADDR 0x5F | ||
68 | #define ADT7462_REG_PWM_TEMP_RANGE_BASE_ADDR 0x60 | ||
69 | #define ADT7462_REG_PWM_TEMP_RANGE_MAX_ADDR 0x63 | ||
70 | #define ADT7462_PWM_HYST_MASK 0x0F | ||
71 | #define ADT7462_PWM_RANGE_MASK 0xF0 | ||
72 | #define ADT7462_PWM_RANGE_SHIFT 4 | ||
73 | #define ADT7462_REG_PWM_CFG_BASE_ADDR 0x21 | ||
74 | #define ADT7462_REG_PWM_CFG_MAX_ADDR 0x24 | ||
75 | #define ADT7462_PWM_CHANNEL_MASK 0xE0 | ||
76 | #define ADT7462_PWM_CHANNEL_SHIFT 5 | ||
77 | |||
78 | #define ADT7462_REG_PIN_CFG_BASE_ADDR 0x10 | ||
79 | #define ADT7462_REG_PIN_CFG_MAX_ADDR 0x13 | ||
80 | #define ADT7462_PIN7_INPUT 0x01 /* cfg0 */ | ||
81 | #define ADT7462_DIODE3_INPUT 0x20 | ||
82 | #define ADT7462_DIODE1_INPUT 0x40 | ||
83 | #define ADT7462_VID_INPUT 0x80 | ||
84 | #define ADT7462_PIN22_INPUT 0x04 /* cfg1 */ | ||
85 | #define ADT7462_PIN21_INPUT 0x08 | ||
86 | #define ADT7462_PIN19_INPUT 0x10 | ||
87 | #define ADT7462_PIN15_INPUT 0x20 | ||
88 | #define ADT7462_PIN13_INPUT 0x40 | ||
89 | #define ADT7462_PIN8_INPUT 0x80 | ||
90 | #define ADT7462_PIN23_MASK 0x03 | ||
91 | #define ADT7462_PIN23_SHIFT 0 | ||
92 | #define ADT7462_PIN26_MASK 0x0C /* cfg2 */ | ||
93 | #define ADT7462_PIN26_SHIFT 2 | ||
94 | #define ADT7462_PIN25_MASK 0x30 | ||
95 | #define ADT7462_PIN25_SHIFT 4 | ||
96 | #define ADT7462_PIN24_MASK 0xC0 | ||
97 | #define ADT7462_PIN24_SHIFT 6 | ||
98 | #define ADT7462_PIN26_VOLT_INPUT 0x08 | ||
99 | #define ADT7462_PIN25_VOLT_INPUT 0x20 | ||
100 | #define ADT7462_PIN28_SHIFT 6 /* cfg3 */ | ||
101 | #define ADT7462_PIN28_VOLT 0x5 | ||
102 | |||
103 | #define ADT7462_REG_ALARM1 0xB8 | ||
104 | #define ADT7462_LT_ALARM 0x02 | ||
105 | #define ADT7462_R1T_ALARM 0x04 | ||
106 | #define ADT7462_R2T_ALARM 0x08 | ||
107 | #define ADT7462_R3T_ALARM 0x10 | ||
108 | #define ADT7462_REG_ALARM2 0xBB | ||
109 | #define ADT7462_V0_ALARM 0x01 | ||
110 | #define ADT7462_V1_ALARM 0x02 | ||
111 | #define ADT7462_V2_ALARM 0x04 | ||
112 | #define ADT7462_V3_ALARM 0x08 | ||
113 | #define ADT7462_V4_ALARM 0x10 | ||
114 | #define ADT7462_V5_ALARM 0x20 | ||
115 | #define ADT7462_V6_ALARM 0x40 | ||
116 | #define ADT7462_V7_ALARM 0x80 | ||
117 | #define ADT7462_REG_ALARM3 0xBC | ||
118 | #define ADT7462_V8_ALARM 0x08 | ||
119 | #define ADT7462_V9_ALARM 0x10 | ||
120 | #define ADT7462_V10_ALARM 0x20 | ||
121 | #define ADT7462_V11_ALARM 0x40 | ||
122 | #define ADT7462_V12_ALARM 0x80 | ||
123 | #define ADT7462_REG_ALARM4 0xBD | ||
124 | #define ADT7462_F0_ALARM 0x01 | ||
125 | #define ADT7462_F1_ALARM 0x02 | ||
126 | #define ADT7462_F2_ALARM 0x04 | ||
127 | #define ADT7462_F3_ALARM 0x08 | ||
128 | #define ADT7462_F4_ALARM 0x10 | ||
129 | #define ADT7462_F5_ALARM 0x20 | ||
130 | #define ADT7462_F6_ALARM 0x40 | ||
131 | #define ADT7462_F7_ALARM 0x80 | ||
132 | #define ADT7462_ALARM1 0x0000 | ||
133 | #define ADT7462_ALARM2 0x0100 | ||
134 | #define ADT7462_ALARM3 0x0200 | ||
135 | #define ADT7462_ALARM4 0x0300 | ||
136 | #define ADT7462_ALARM_REG_SHIFT 8 | ||
137 | #define ADT7462_ALARM_FLAG_MASK 0x0F | ||
138 | |||
139 | #define ADT7462_TEMP_COUNT 4 | ||
140 | #define ADT7462_TEMP_REG(x) (ADT7462_REG_TEMP_BASE_ADDR + (x * 2)) | ||
141 | #define ADT7462_TEMP_MIN_REG(x) (ADT7462_REG_MIN_TEMP_BASE_ADDR + (x)) | ||
142 | #define ADT7462_TEMP_MAX_REG(x) (ADT7462_REG_MAX_TEMP_BASE_ADDR + (x)) | ||
143 | #define TEMP_FRAC_OFFSET 6 | ||
144 | |||
145 | #define ADT7462_FAN_COUNT 8 | ||
146 | #define ADT7462_REG_FAN_MIN(x) (ADT7462_REG_FAN_MIN_BASE_ADDR + (x)) | ||
147 | |||
148 | #define ADT7462_PWM_COUNT 4 | ||
149 | #define ADT7462_REG_PWM(x) (ADT7462_REG_PWM_BASE_ADDR + (x)) | ||
150 | #define ADT7462_REG_PWM_MIN(x) (ADT7462_REG_PWM_MIN_BASE_ADDR + (x)) | ||
151 | #define ADT7462_REG_PWM_TMIN(x) \ | ||
152 | (ADT7462_REG_PWM_TEMP_MIN_BASE_ADDR + (x)) | ||
153 | #define ADT7462_REG_PWM_TRANGE(x) \ | ||
154 | (ADT7462_REG_PWM_TEMP_RANGE_BASE_ADDR + (x)) | ||
155 | |||
156 | #define ADT7462_PIN_CFG_REG_COUNT 4 | ||
157 | #define ADT7462_REG_PIN_CFG(x) (ADT7462_REG_PIN_CFG_BASE_ADDR + (x)) | ||
158 | #define ADT7462_REG_PWM_CFG(x) (ADT7462_REG_PWM_CFG_BASE_ADDR + (x)) | ||
159 | |||
160 | #define ADT7462_ALARM_REG_COUNT 4 | ||
161 | |||
162 | /* | ||
163 | * The chip can measure 13 different voltage sources: | ||
164 | * | ||
165 | * 1. +12V1 (pin 7) | ||
166 | * 2. Vccp1/+2.5V/+1.8V/+1.5V (pin 23) | ||
167 | * 3. +12V3 (pin 22) | ||
168 | * 4. +5V (pin 21) | ||
169 | * 5. +1.25V/+0.9V (pin 19) | ||
170 | * 6. +2.5V/+1.8V (pin 15) | ||
171 | * 7. +3.3v (pin 13) | ||
172 | * 8. +12V2 (pin 8) | ||
173 | * 9. Vbatt/FSB_Vtt (pin 26) | ||
174 | * A. +3.3V/+1.2V1 (pin 25) | ||
175 | * B. Vccp2/+2.5V/+1.8V/+1.5V (pin 24) | ||
176 | * C. +1.5V ICH (only if BOTH pin 28/29 are set to +1.5V) | ||
177 | * D. +1.5V 3GPIO (only if BOTH pin 28/29 are set to +1.5V) | ||
178 | * | ||
179 | * Each of these 13 has a factor to convert raw to voltage. Even better, | ||
180 | * the pins can be connected to other sensors (tach/gpio/hot/etc), which | ||
181 | * makes the bookkeeping tricky. | ||
182 | * | ||
183 | * Some, but not all, of these voltages have low/high limits. | ||
184 | */ | ||
185 | #define ADT7462_VOLT_COUNT 12 | ||
186 | |||
187 | #define ADT7462_VENDOR 0x41 | ||
188 | #define ADT7462_DEVICE 0x62 | ||
189 | /* datasheet only mentions a revision 4 */ | ||
190 | #define ADT7462_REVISION 0x04 | ||
191 | |||
192 | /* How often do we reread sensors values? (In jiffies) */ | ||
193 | #define SENSOR_REFRESH_INTERVAL (2 * HZ) | ||
194 | |||
195 | /* How often do we reread sensor limit values? (In jiffies) */ | ||
196 | #define LIMIT_REFRESH_INTERVAL (60 * HZ) | ||
197 | |||
198 | /* datasheet says to divide this number by the fan reading to get fan rpm */ | ||
199 | #define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x)) | ||
200 | #define FAN_RPM_TO_PERIOD FAN_PERIOD_TO_RPM | ||
201 | #define FAN_PERIOD_INVALID 65535 | ||
202 | #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) | ||
203 | |||
204 | #define MASK_AND_SHIFT(value, prefix) \ | ||
205 | (((value) & prefix##_MASK) >> prefix##_SHIFT) | ||
206 | |||
207 | #define ROUND_DIV(x, divisor) (((x) + ((divisor) / 2)) / (divisor)) | ||
208 | |||
209 | struct adt7462_data { | ||
210 | struct device *hwmon_dev; | ||
211 | struct attribute_group attrs; | ||
212 | struct mutex lock; | ||
213 | char sensors_valid; | ||
214 | char limits_valid; | ||
215 | unsigned long sensors_last_updated; /* In jiffies */ | ||
216 | unsigned long limits_last_updated; /* In jiffies */ | ||
217 | |||
218 | u8 temp[ADT7462_TEMP_COUNT]; | ||
219 | /* bits 6-7 are quarter pieces of temp */ | ||
220 | u8 temp_frac[ADT7462_TEMP_COUNT]; | ||
221 | u8 temp_min[ADT7462_TEMP_COUNT]; | ||
222 | u8 temp_max[ADT7462_TEMP_COUNT]; | ||
223 | u16 fan[ADT7462_FAN_COUNT]; | ||
224 | u8 fan_enabled; | ||
225 | u8 fan_min[ADT7462_FAN_COUNT]; | ||
226 | u8 cfg2; | ||
227 | u8 pwm[ADT7462_PWM_COUNT]; | ||
228 | u8 pin_cfg[ADT7462_PIN_CFG_REG_COUNT]; | ||
229 | u8 voltages[ADT7462_VOLT_COUNT]; | ||
230 | u8 volt_max[ADT7462_VOLT_COUNT]; | ||
231 | u8 volt_min[ADT7462_VOLT_COUNT]; | ||
232 | u8 pwm_min[ADT7462_PWM_COUNT]; | ||
233 | u8 pwm_tmin[ADT7462_PWM_COUNT]; | ||
234 | u8 pwm_trange[ADT7462_PWM_COUNT]; | ||
235 | u8 pwm_max; /* only one per chip */ | ||
236 | u8 pwm_cfg[ADT7462_PWM_COUNT]; | ||
237 | u8 alarms[ADT7462_ALARM_REG_COUNT]; | ||
238 | }; | ||
239 | |||
240 | static int adt7462_probe(struct i2c_client *client, | ||
241 | const struct i2c_device_id *id); | ||
242 | static int adt7462_detect(struct i2c_client *client, int kind, | ||
243 | struct i2c_board_info *info); | ||
244 | static int adt7462_remove(struct i2c_client *client); | ||
245 | |||
246 | static const struct i2c_device_id adt7462_id[] = { | ||
247 | { "adt7462", adt7462 }, | ||
248 | { } | ||
249 | }; | ||
250 | MODULE_DEVICE_TABLE(i2c, adt7462_id); | ||
251 | |||
252 | static struct i2c_driver adt7462_driver = { | ||
253 | .class = I2C_CLASS_HWMON, | ||
254 | .driver = { | ||
255 | .name = "adt7462", | ||
256 | }, | ||
257 | .probe = adt7462_probe, | ||
258 | .remove = adt7462_remove, | ||
259 | .id_table = adt7462_id, | ||
260 | .detect = adt7462_detect, | ||
261 | .address_data = &addr_data, | ||
262 | }; | ||
263 | |||
264 | /* | ||
265 | * 16-bit registers on the ADT7462 are low-byte first. The data sheet says | ||
266 | * that the low byte must be read before the high byte. | ||
267 | */ | ||
268 | static inline int adt7462_read_word_data(struct i2c_client *client, u8 reg) | ||
269 | { | ||
270 | u16 foo; | ||
271 | foo = i2c_smbus_read_byte_data(client, reg); | ||
272 | foo |= ((u16)i2c_smbus_read_byte_data(client, reg + 1) << 8); | ||
273 | return foo; | ||
274 | } | ||
275 | |||
276 | /* For some reason these registers are not contiguous. */ | ||
277 | static int ADT7462_REG_FAN(int fan) | ||
278 | { | ||
279 | if (fan < 4) | ||
280 | return ADT7462_REG_FAN_BASE_ADDR + (2 * fan); | ||
281 | return ADT7462_REG_FAN2_BASE_ADDR + (2 * (fan - 4)); | ||
282 | } | ||
283 | |||
284 | /* Voltage registers are scattered everywhere */ | ||
285 | static int ADT7462_REG_VOLT_MAX(struct adt7462_data *data, int which) | ||
286 | { | ||
287 | switch (which) { | ||
288 | case 0: | ||
289 | if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) | ||
290 | return 0x7C; | ||
291 | break; | ||
292 | case 1: | ||
293 | return 0x69; | ||
294 | case 2: | ||
295 | if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) | ||
296 | return 0x7F; | ||
297 | break; | ||
298 | case 3: | ||
299 | if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) | ||
300 | return 0x7E; | ||
301 | break; | ||
302 | case 4: | ||
303 | if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) | ||
304 | return 0x4B; | ||
305 | break; | ||
306 | case 5: | ||
307 | if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) | ||
308 | return 0x49; | ||
309 | break; | ||
310 | case 6: | ||
311 | if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) | ||
312 | return 0x68; | ||
313 | break; | ||
314 | case 7: | ||
315 | if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) | ||
316 | return 0x7D; | ||
317 | break; | ||
318 | case 8: | ||
319 | if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT)) | ||
320 | return 0x6C; | ||
321 | break; | ||
322 | case 9: | ||
323 | if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT)) | ||
324 | return 0x6B; | ||
325 | break; | ||
326 | case 10: | ||
327 | return 0x6A; | ||
328 | case 11: | ||
329 | if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == | ||
330 | ADT7462_PIN28_VOLT && | ||
331 | !(data->pin_cfg[0] & ADT7462_VID_INPUT)) | ||
332 | return 0x50; | ||
333 | break; | ||
334 | case 12: | ||
335 | if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == | ||
336 | ADT7462_PIN28_VOLT && | ||
337 | !(data->pin_cfg[0] & ADT7462_VID_INPUT)) | ||
338 | return 0x4C; | ||
339 | break; | ||
340 | } | ||
341 | return -ENODEV; | ||
342 | } | ||
343 | |||
344 | static int ADT7462_REG_VOLT_MIN(struct adt7462_data *data, int which) | ||
345 | { | ||
346 | switch (which) { | ||
347 | case 0: | ||
348 | if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) | ||
349 | return 0x6D; | ||
350 | break; | ||
351 | case 1: | ||
352 | return 0x72; | ||
353 | case 2: | ||
354 | if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) | ||
355 | return 0x6F; | ||
356 | break; | ||
357 | case 3: | ||
358 | if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) | ||
359 | return 0x71; | ||
360 | break; | ||
361 | case 4: | ||
362 | if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) | ||
363 | return 0x47; | ||
364 | break; | ||
365 | case 5: | ||
366 | if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) | ||
367 | return 0x45; | ||
368 | break; | ||
369 | case 6: | ||
370 | if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) | ||
371 | return 0x70; | ||
372 | break; | ||
373 | case 7: | ||
374 | if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) | ||
375 | return 0x6E; | ||
376 | break; | ||
377 | case 8: | ||
378 | if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT)) | ||
379 | return 0x75; | ||
380 | break; | ||
381 | case 9: | ||
382 | if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT)) | ||
383 | return 0x74; | ||
384 | break; | ||
385 | case 10: | ||
386 | return 0x73; | ||
387 | case 11: | ||
388 | if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == | ||
389 | ADT7462_PIN28_VOLT && | ||
390 | !(data->pin_cfg[0] & ADT7462_VID_INPUT)) | ||
391 | return 0x76; | ||
392 | break; | ||
393 | case 12: | ||
394 | if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == | ||
395 | ADT7462_PIN28_VOLT && | ||
396 | !(data->pin_cfg[0] & ADT7462_VID_INPUT)) | ||
397 | return 0x77; | ||
398 | break; | ||
399 | } | ||
400 | return -ENODEV; | ||
401 | } | ||
402 | |||
403 | static int ADT7462_REG_VOLT(struct adt7462_data *data, int which) | ||
404 | { | ||
405 | switch (which) { | ||
406 | case 0: | ||
407 | if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) | ||
408 | return 0xA3; | ||
409 | break; | ||
410 | case 1: | ||
411 | return 0x90; | ||
412 | case 2: | ||
413 | if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) | ||
414 | return 0xA9; | ||
415 | break; | ||
416 | case 3: | ||
417 | if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) | ||
418 | return 0xA7; | ||
419 | break; | ||
420 | case 4: | ||
421 | if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) | ||
422 | return 0x8F; | ||
423 | break; | ||
424 | case 5: | ||
425 | if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) | ||
426 | return 0x8B; | ||
427 | break; | ||
428 | case 6: | ||
429 | if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) | ||
430 | return 0x96; | ||
431 | break; | ||
432 | case 7: | ||
433 | if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) | ||
434 | return 0xA5; | ||
435 | break; | ||
436 | case 8: | ||
437 | if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT)) | ||
438 | return 0x93; | ||
439 | break; | ||
440 | case 9: | ||
441 | if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT)) | ||
442 | return 0x92; | ||
443 | break; | ||
444 | case 10: | ||
445 | return 0x91; | ||
446 | case 11: | ||
447 | if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == | ||
448 | ADT7462_PIN28_VOLT && | ||
449 | !(data->pin_cfg[0] & ADT7462_VID_INPUT)) | ||
450 | return 0x94; | ||
451 | break; | ||
452 | case 12: | ||
453 | if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == | ||
454 | ADT7462_PIN28_VOLT && | ||
455 | !(data->pin_cfg[0] & ADT7462_VID_INPUT)) | ||
456 | return 0x95; | ||
457 | break; | ||
458 | } | ||
459 | return -ENODEV; | ||
460 | } | ||
461 | |||
462 | /* Provide labels for sysfs */ | ||
463 | static const char *voltage_label(struct adt7462_data *data, int which) | ||
464 | { | ||
465 | switch (which) { | ||
466 | case 0: | ||
467 | if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) | ||
468 | return "+12V1"; | ||
469 | break; | ||
470 | case 1: | ||
471 | switch (MASK_AND_SHIFT(data->pin_cfg[1], ADT7462_PIN23)) { | ||
472 | case 0: | ||
473 | return "Vccp1"; | ||
474 | case 1: | ||
475 | return "+2.5V"; | ||
476 | case 2: | ||
477 | return "+1.8V"; | ||
478 | case 3: | ||
479 | return "+1.5V"; | ||
480 | } | ||
481 | case 2: | ||
482 | if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) | ||
483 | return "+12V3"; | ||
484 | break; | ||
485 | case 3: | ||
486 | if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) | ||
487 | return "+5V"; | ||
488 | break; | ||
489 | case 4: | ||
490 | if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) { | ||
491 | if (data->pin_cfg[1] & ADT7462_PIN19_INPUT) | ||
492 | return "+0.9V"; | ||
493 | return "+1.25V"; | ||
494 | } | ||
495 | break; | ||
496 | case 5: | ||
497 | if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) { | ||
498 | if (data->pin_cfg[1] & ADT7462_PIN19_INPUT) | ||
499 | return "+1.8V"; | ||
500 | return "+2.5V"; | ||
501 | } | ||
502 | break; | ||
503 | case 6: | ||
504 | if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) | ||
505 | return "+3.3V"; | ||
506 | break; | ||
507 | case 7: | ||
508 | if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) | ||
509 | return "+12V2"; | ||
510 | break; | ||
511 | case 8: | ||
512 | switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN26)) { | ||
513 | case 0: | ||
514 | return "Vbatt"; | ||
515 | case 1: | ||
516 | return "FSB_Vtt"; | ||
517 | } | ||
518 | break; | ||
519 | case 9: | ||
520 | switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN25)) { | ||
521 | case 0: | ||
522 | return "+3.3V"; | ||
523 | case 1: | ||
524 | return "+1.2V1"; | ||
525 | } | ||
526 | break; | ||
527 | case 10: | ||
528 | switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN24)) { | ||
529 | case 0: | ||
530 | return "Vccp2"; | ||
531 | case 1: | ||
532 | return "+2.5V"; | ||
533 | case 2: | ||
534 | return "+1.8V"; | ||
535 | case 3: | ||
536 | return "+1.5"; | ||
537 | } | ||
538 | case 11: | ||
539 | if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == | ||
540 | ADT7462_PIN28_VOLT && | ||
541 | !(data->pin_cfg[0] & ADT7462_VID_INPUT)) | ||
542 | return "+1.5V ICH"; | ||
543 | break; | ||
544 | case 12: | ||
545 | if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == | ||
546 | ADT7462_PIN28_VOLT && | ||
547 | !(data->pin_cfg[0] & ADT7462_VID_INPUT)) | ||
548 | return "+1.5V 3GPIO"; | ||
549 | break; | ||
550 | } | ||
551 | return "N/A"; | ||
552 | } | ||
553 | |||
554 | /* Multipliers are actually in uV, not mV. */ | ||
555 | static int voltage_multiplier(struct adt7462_data *data, int which) | ||
556 | { | ||
557 | switch (which) { | ||
558 | case 0: | ||
559 | if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) | ||
560 | return 62500; | ||
561 | break; | ||
562 | case 1: | ||
563 | switch (MASK_AND_SHIFT(data->pin_cfg[1], ADT7462_PIN23)) { | ||
564 | case 0: | ||
565 | if (data->pin_cfg[0] & ADT7462_VID_INPUT) | ||
566 | return 12500; | ||
567 | return 6250; | ||
568 | case 1: | ||
569 | return 13000; | ||
570 | case 2: | ||
571 | return 9400; | ||
572 | case 3: | ||
573 | return 7800; | ||
574 | } | ||
575 | case 2: | ||
576 | if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) | ||
577 | return 62500; | ||
578 | break; | ||
579 | case 3: | ||
580 | if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) | ||
581 | return 26000; | ||
582 | break; | ||
583 | case 4: | ||
584 | if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) { | ||
585 | if (data->pin_cfg[1] & ADT7462_PIN19_INPUT) | ||
586 | return 4690; | ||
587 | return 6500; | ||
588 | } | ||
589 | break; | ||
590 | case 5: | ||
591 | if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) { | ||
592 | if (data->pin_cfg[1] & ADT7462_PIN15_INPUT) | ||
593 | return 9400; | ||
594 | return 13000; | ||
595 | } | ||
596 | break; | ||
597 | case 6: | ||
598 | if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) | ||
599 | return 17200; | ||
600 | break; | ||
601 | case 7: | ||
602 | if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) | ||
603 | return 62500; | ||
604 | break; | ||
605 | case 8: | ||
606 | switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN26)) { | ||
607 | case 0: | ||
608 | return 15600; | ||
609 | case 1: | ||
610 | return 6250; | ||
611 | } | ||
612 | break; | ||
613 | case 9: | ||
614 | switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN25)) { | ||
615 | case 0: | ||
616 | return 17200; | ||
617 | case 1: | ||
618 | return 6250; | ||
619 | } | ||
620 | break; | ||
621 | case 10: | ||
622 | switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN24)) { | ||
623 | case 0: | ||
624 | return 6250; | ||
625 | case 1: | ||
626 | return 13000; | ||
627 | case 2: | ||
628 | return 9400; | ||
629 | case 3: | ||
630 | return 7800; | ||
631 | } | ||
632 | case 11: | ||
633 | case 12: | ||
634 | if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == | ||
635 | ADT7462_PIN28_VOLT && | ||
636 | !(data->pin_cfg[0] & ADT7462_VID_INPUT)) | ||
637 | return 7800; | ||
638 | } | ||
639 | return 0; | ||
640 | } | ||
641 | |||
642 | static int temp_enabled(struct adt7462_data *data, int which) | ||
643 | { | ||
644 | switch (which) { | ||
645 | case 0: | ||
646 | case 2: | ||
647 | return 1; | ||
648 | case 1: | ||
649 | if (data->pin_cfg[0] & ADT7462_DIODE1_INPUT) | ||
650 | return 1; | ||
651 | break; | ||
652 | case 3: | ||
653 | if (data->pin_cfg[0] & ADT7462_DIODE3_INPUT) | ||
654 | return 1; | ||
655 | break; | ||
656 | } | ||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | static const char *temp_label(struct adt7462_data *data, int which) | ||
661 | { | ||
662 | switch (which) { | ||
663 | case 0: | ||
664 | return "local"; | ||
665 | case 1: | ||
666 | if (data->pin_cfg[0] & ADT7462_DIODE1_INPUT) | ||
667 | return "remote1"; | ||
668 | break; | ||
669 | case 2: | ||
670 | return "remote2"; | ||
671 | case 3: | ||
672 | if (data->pin_cfg[0] & ADT7462_DIODE3_INPUT) | ||
673 | return "remote3"; | ||
674 | break; | ||
675 | } | ||
676 | return "N/A"; | ||
677 | } | ||
678 | |||
679 | /* Map Trange register values to mC */ | ||
680 | #define NUM_TRANGE_VALUES 16 | ||
681 | static const int trange_values[NUM_TRANGE_VALUES] = { | ||
682 | 2000, | ||
683 | 2500, | ||
684 | 3300, | ||
685 | 4000, | ||
686 | 5000, | ||
687 | 6700, | ||
688 | 8000, | ||
689 | 10000, | ||
690 | 13300, | ||
691 | 16000, | ||
692 | 20000, | ||
693 | 26700, | ||
694 | 32000, | ||
695 | 40000, | ||
696 | 53300, | ||
697 | 80000 | ||
698 | }; | ||
699 | |||
700 | static int find_trange_value(int trange) | ||
701 | { | ||
702 | int i; | ||
703 | |||
704 | for (i = 0; i < NUM_TRANGE_VALUES; i++) | ||
705 | if (trange_values[i] == trange) | ||
706 | return i; | ||
707 | |||
708 | return -ENODEV; | ||
709 | } | ||
710 | |||
711 | static struct adt7462_data *adt7462_update_device(struct device *dev) | ||
712 | { | ||
713 | struct i2c_client *client = to_i2c_client(dev); | ||
714 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
715 | unsigned long local_jiffies = jiffies; | ||
716 | int i; | ||
717 | |||
718 | mutex_lock(&data->lock); | ||
719 | if (time_before(local_jiffies, data->sensors_last_updated + | ||
720 | SENSOR_REFRESH_INTERVAL) | ||
721 | && data->sensors_valid) | ||
722 | goto no_sensor_update; | ||
723 | |||
724 | for (i = 0; i < ADT7462_TEMP_COUNT; i++) { | ||
725 | /* | ||
726 | * Reading the fractional register locks the integral | ||
727 | * register until both have been read. | ||
728 | */ | ||
729 | data->temp_frac[i] = i2c_smbus_read_byte_data(client, | ||
730 | ADT7462_TEMP_REG(i)); | ||
731 | data->temp[i] = i2c_smbus_read_byte_data(client, | ||
732 | ADT7462_TEMP_REG(i) + 1); | ||
733 | } | ||
734 | |||
735 | for (i = 0; i < ADT7462_FAN_COUNT; i++) | ||
736 | data->fan[i] = adt7462_read_word_data(client, | ||
737 | ADT7462_REG_FAN(i)); | ||
738 | |||
739 | data->fan_enabled = i2c_smbus_read_byte_data(client, | ||
740 | ADT7462_REG_FAN_ENABLE); | ||
741 | |||
742 | for (i = 0; i < ADT7462_PWM_COUNT; i++) | ||
743 | data->pwm[i] = i2c_smbus_read_byte_data(client, | ||
744 | ADT7462_REG_PWM(i)); | ||
745 | |||
746 | for (i = 0; i < ADT7462_PIN_CFG_REG_COUNT; i++) | ||
747 | data->pin_cfg[i] = i2c_smbus_read_byte_data(client, | ||
748 | ADT7462_REG_PIN_CFG(i)); | ||
749 | |||
750 | for (i = 0; i < ADT7462_VOLT_COUNT; i++) { | ||
751 | int reg = ADT7462_REG_VOLT(data, i); | ||
752 | if (!reg) | ||
753 | data->voltages[i] = 0; | ||
754 | else | ||
755 | data->voltages[i] = i2c_smbus_read_byte_data(client, | ||
756 | reg); | ||
757 | } | ||
758 | |||
759 | data->alarms[0] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM1); | ||
760 | data->alarms[1] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM2); | ||
761 | data->alarms[2] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM3); | ||
762 | data->alarms[3] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM4); | ||
763 | |||
764 | data->sensors_last_updated = local_jiffies; | ||
765 | data->sensors_valid = 1; | ||
766 | |||
767 | no_sensor_update: | ||
768 | if (time_before(local_jiffies, data->limits_last_updated + | ||
769 | LIMIT_REFRESH_INTERVAL) | ||
770 | && data->limits_valid) | ||
771 | goto out; | ||
772 | |||
773 | for (i = 0; i < ADT7462_TEMP_COUNT; i++) { | ||
774 | data->temp_min[i] = i2c_smbus_read_byte_data(client, | ||
775 | ADT7462_TEMP_MIN_REG(i)); | ||
776 | data->temp_max[i] = i2c_smbus_read_byte_data(client, | ||
777 | ADT7462_TEMP_MAX_REG(i)); | ||
778 | } | ||
779 | |||
780 | for (i = 0; i < ADT7462_FAN_COUNT; i++) | ||
781 | data->fan_min[i] = i2c_smbus_read_byte_data(client, | ||
782 | ADT7462_REG_FAN_MIN(i)); | ||
783 | |||
784 | for (i = 0; i < ADT7462_VOLT_COUNT; i++) { | ||
785 | int reg = ADT7462_REG_VOLT_MAX(data, i); | ||
786 | data->volt_max[i] = | ||
787 | (reg ? i2c_smbus_read_byte_data(client, reg) : 0); | ||
788 | |||
789 | reg = ADT7462_REG_VOLT_MIN(data, i); | ||
790 | data->volt_min[i] = | ||
791 | (reg ? i2c_smbus_read_byte_data(client, reg) : 0); | ||
792 | } | ||
793 | |||
794 | for (i = 0; i < ADT7462_PWM_COUNT; i++) { | ||
795 | data->pwm_min[i] = i2c_smbus_read_byte_data(client, | ||
796 | ADT7462_REG_PWM_MIN(i)); | ||
797 | data->pwm_tmin[i] = i2c_smbus_read_byte_data(client, | ||
798 | ADT7462_REG_PWM_TMIN(i)); | ||
799 | data->pwm_trange[i] = i2c_smbus_read_byte_data(client, | ||
800 | ADT7462_REG_PWM_TRANGE(i)); | ||
801 | data->pwm_cfg[i] = i2c_smbus_read_byte_data(client, | ||
802 | ADT7462_REG_PWM_CFG(i)); | ||
803 | } | ||
804 | |||
805 | data->pwm_max = i2c_smbus_read_byte_data(client, ADT7462_REG_PWM_MAX); | ||
806 | |||
807 | data->cfg2 = i2c_smbus_read_byte_data(client, ADT7462_REG_CFG2); | ||
808 | |||
809 | data->limits_last_updated = local_jiffies; | ||
810 | data->limits_valid = 1; | ||
811 | |||
812 | out: | ||
813 | mutex_unlock(&data->lock); | ||
814 | return data; | ||
815 | } | ||
816 | |||
817 | static ssize_t show_temp_min(struct device *dev, | ||
818 | struct device_attribute *devattr, | ||
819 | char *buf) | ||
820 | { | ||
821 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
822 | struct adt7462_data *data = adt7462_update_device(dev); | ||
823 | |||
824 | if (!temp_enabled(data, attr->index)) | ||
825 | return sprintf(buf, "0\n"); | ||
826 | |||
827 | return sprintf(buf, "%d\n", 1000 * (data->temp_min[attr->index] - 64)); | ||
828 | } | ||
829 | |||
830 | static ssize_t set_temp_min(struct device *dev, | ||
831 | struct device_attribute *devattr, | ||
832 | const char *buf, | ||
833 | size_t count) | ||
834 | { | ||
835 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
836 | struct i2c_client *client = to_i2c_client(dev); | ||
837 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
838 | long temp; | ||
839 | |||
840 | if (strict_strtol(buf, 10, &temp) || !temp_enabled(data, attr->index)) | ||
841 | return -EINVAL; | ||
842 | |||
843 | temp = ROUND_DIV(temp, 1000) + 64; | ||
844 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
845 | |||
846 | mutex_lock(&data->lock); | ||
847 | data->temp_min[attr->index] = temp; | ||
848 | i2c_smbus_write_byte_data(client, ADT7462_TEMP_MIN_REG(attr->index), | ||
849 | temp); | ||
850 | mutex_unlock(&data->lock); | ||
851 | |||
852 | return count; | ||
853 | } | ||
854 | |||
855 | static ssize_t show_temp_max(struct device *dev, | ||
856 | struct device_attribute *devattr, | ||
857 | char *buf) | ||
858 | { | ||
859 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
860 | struct adt7462_data *data = adt7462_update_device(dev); | ||
861 | |||
862 | if (!temp_enabled(data, attr->index)) | ||
863 | return sprintf(buf, "0\n"); | ||
864 | |||
865 | return sprintf(buf, "%d\n", 1000 * (data->temp_max[attr->index] - 64)); | ||
866 | } | ||
867 | |||
868 | static ssize_t set_temp_max(struct device *dev, | ||
869 | struct device_attribute *devattr, | ||
870 | const char *buf, | ||
871 | size_t count) | ||
872 | { | ||
873 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
874 | struct i2c_client *client = to_i2c_client(dev); | ||
875 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
876 | long temp; | ||
877 | |||
878 | if (strict_strtol(buf, 10, &temp) || !temp_enabled(data, attr->index)) | ||
879 | return -EINVAL; | ||
880 | |||
881 | temp = ROUND_DIV(temp, 1000) + 64; | ||
882 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
883 | |||
884 | mutex_lock(&data->lock); | ||
885 | data->temp_max[attr->index] = temp; | ||
886 | i2c_smbus_write_byte_data(client, ADT7462_TEMP_MAX_REG(attr->index), | ||
887 | temp); | ||
888 | mutex_unlock(&data->lock); | ||
889 | |||
890 | return count; | ||
891 | } | ||
892 | |||
893 | static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, | ||
894 | char *buf) | ||
895 | { | ||
896 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
897 | struct adt7462_data *data = adt7462_update_device(dev); | ||
898 | u8 frac = data->temp_frac[attr->index] >> TEMP_FRAC_OFFSET; | ||
899 | |||
900 | if (!temp_enabled(data, attr->index)) | ||
901 | return sprintf(buf, "0\n"); | ||
902 | |||
903 | return sprintf(buf, "%d\n", 1000 * (data->temp[attr->index] - 64) + | ||
904 | 250 * frac); | ||
905 | } | ||
906 | |||
907 | static ssize_t show_temp_label(struct device *dev, | ||
908 | struct device_attribute *devattr, | ||
909 | char *buf) | ||
910 | { | ||
911 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
912 | struct adt7462_data *data = adt7462_update_device(dev); | ||
913 | |||
914 | return sprintf(buf, "%s\n", temp_label(data, attr->index)); | ||
915 | } | ||
916 | |||
917 | static ssize_t show_volt_max(struct device *dev, | ||
918 | struct device_attribute *devattr, | ||
919 | char *buf) | ||
920 | { | ||
921 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
922 | struct adt7462_data *data = adt7462_update_device(dev); | ||
923 | int x = voltage_multiplier(data, attr->index); | ||
924 | |||
925 | x *= data->volt_max[attr->index]; | ||
926 | x /= 1000; /* convert from uV to mV */ | ||
927 | |||
928 | return sprintf(buf, "%d\n", x); | ||
929 | } | ||
930 | |||
931 | static ssize_t set_volt_max(struct device *dev, | ||
932 | struct device_attribute *devattr, | ||
933 | const char *buf, | ||
934 | size_t count) | ||
935 | { | ||
936 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
937 | struct i2c_client *client = to_i2c_client(dev); | ||
938 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
939 | int x = voltage_multiplier(data, attr->index); | ||
940 | long temp; | ||
941 | |||
942 | if (strict_strtol(buf, 10, &temp) || !x) | ||
943 | return -EINVAL; | ||
944 | |||
945 | temp *= 1000; /* convert mV to uV */ | ||
946 | temp = ROUND_DIV(temp, x); | ||
947 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
948 | |||
949 | mutex_lock(&data->lock); | ||
950 | data->volt_max[attr->index] = temp; | ||
951 | i2c_smbus_write_byte_data(client, | ||
952 | ADT7462_REG_VOLT_MAX(data, attr->index), | ||
953 | temp); | ||
954 | mutex_unlock(&data->lock); | ||
955 | |||
956 | return count; | ||
957 | } | ||
958 | |||
959 | static ssize_t show_volt_min(struct device *dev, | ||
960 | struct device_attribute *devattr, | ||
961 | char *buf) | ||
962 | { | ||
963 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
964 | struct adt7462_data *data = adt7462_update_device(dev); | ||
965 | int x = voltage_multiplier(data, attr->index); | ||
966 | |||
967 | x *= data->volt_min[attr->index]; | ||
968 | x /= 1000; /* convert from uV to mV */ | ||
969 | |||
970 | return sprintf(buf, "%d\n", x); | ||
971 | } | ||
972 | |||
973 | static ssize_t set_volt_min(struct device *dev, | ||
974 | struct device_attribute *devattr, | ||
975 | const char *buf, | ||
976 | size_t count) | ||
977 | { | ||
978 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
979 | struct i2c_client *client = to_i2c_client(dev); | ||
980 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
981 | int x = voltage_multiplier(data, attr->index); | ||
982 | long temp; | ||
983 | |||
984 | if (strict_strtol(buf, 10, &temp) || !x) | ||
985 | return -EINVAL; | ||
986 | |||
987 | temp *= 1000; /* convert mV to uV */ | ||
988 | temp = ROUND_DIV(temp, x); | ||
989 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
990 | |||
991 | mutex_lock(&data->lock); | ||
992 | data->volt_min[attr->index] = temp; | ||
993 | i2c_smbus_write_byte_data(client, | ||
994 | ADT7462_REG_VOLT_MIN(data, attr->index), | ||
995 | temp); | ||
996 | mutex_unlock(&data->lock); | ||
997 | |||
998 | return count; | ||
999 | } | ||
1000 | |||
1001 | static ssize_t show_voltage(struct device *dev, | ||
1002 | struct device_attribute *devattr, | ||
1003 | char *buf) | ||
1004 | { | ||
1005 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1006 | struct adt7462_data *data = adt7462_update_device(dev); | ||
1007 | int x = voltage_multiplier(data, attr->index); | ||
1008 | |||
1009 | x *= data->voltages[attr->index]; | ||
1010 | x /= 1000; /* convert from uV to mV */ | ||
1011 | |||
1012 | return sprintf(buf, "%d\n", x); | ||
1013 | } | ||
1014 | |||
1015 | static ssize_t show_voltage_label(struct device *dev, | ||
1016 | struct device_attribute *devattr, | ||
1017 | char *buf) | ||
1018 | { | ||
1019 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1020 | struct adt7462_data *data = adt7462_update_device(dev); | ||
1021 | |||
1022 | return sprintf(buf, "%s\n", voltage_label(data, attr->index)); | ||
1023 | } | ||
1024 | |||
1025 | static ssize_t show_alarm(struct device *dev, | ||
1026 | struct device_attribute *devattr, | ||
1027 | char *buf) | ||
1028 | { | ||
1029 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1030 | struct adt7462_data *data = adt7462_update_device(dev); | ||
1031 | int reg = attr->index >> ADT7462_ALARM_REG_SHIFT; | ||
1032 | int mask = attr->index & ADT7462_ALARM_FLAG_MASK; | ||
1033 | |||
1034 | if (data->alarms[reg] & mask) | ||
1035 | return sprintf(buf, "1\n"); | ||
1036 | else | ||
1037 | return sprintf(buf, "0\n"); | ||
1038 | } | ||
1039 | |||
1040 | static int fan_enabled(struct adt7462_data *data, int fan) | ||
1041 | { | ||
1042 | return data->fan_enabled & (1 << fan); | ||
1043 | } | ||
1044 | |||
1045 | static ssize_t show_fan_min(struct device *dev, | ||
1046 | struct device_attribute *devattr, | ||
1047 | char *buf) | ||
1048 | { | ||
1049 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1050 | struct adt7462_data *data = adt7462_update_device(dev); | ||
1051 | u16 temp; | ||
1052 | |||
1053 | /* Only the MSB of the min fan period is stored... */ | ||
1054 | temp = data->fan_min[attr->index]; | ||
1055 | temp <<= 8; | ||
1056 | |||
1057 | if (!fan_enabled(data, attr->index) || | ||
1058 | !FAN_DATA_VALID(temp)) | ||
1059 | return sprintf(buf, "0\n"); | ||
1060 | |||
1061 | return sprintf(buf, "%d\n", FAN_PERIOD_TO_RPM(temp)); | ||
1062 | } | ||
1063 | |||
1064 | static ssize_t set_fan_min(struct device *dev, | ||
1065 | struct device_attribute *devattr, | ||
1066 | const char *buf, size_t count) | ||
1067 | { | ||
1068 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1069 | struct i2c_client *client = to_i2c_client(dev); | ||
1070 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
1071 | long temp; | ||
1072 | |||
1073 | if (strict_strtol(buf, 10, &temp) || !temp || | ||
1074 | !fan_enabled(data, attr->index)) | ||
1075 | return -EINVAL; | ||
1076 | |||
1077 | temp = FAN_RPM_TO_PERIOD(temp); | ||
1078 | temp >>= 8; | ||
1079 | temp = SENSORS_LIMIT(temp, 1, 255); | ||
1080 | |||
1081 | mutex_lock(&data->lock); | ||
1082 | data->fan_min[attr->index] = temp; | ||
1083 | i2c_smbus_write_byte_data(client, ADT7462_REG_FAN_MIN(attr->index), | ||
1084 | temp); | ||
1085 | mutex_unlock(&data->lock); | ||
1086 | |||
1087 | return count; | ||
1088 | } | ||
1089 | |||
1090 | static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, | ||
1091 | char *buf) | ||
1092 | { | ||
1093 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1094 | struct adt7462_data *data = adt7462_update_device(dev); | ||
1095 | |||
1096 | if (!fan_enabled(data, attr->index) || | ||
1097 | !FAN_DATA_VALID(data->fan[attr->index])) | ||
1098 | return sprintf(buf, "0\n"); | ||
1099 | |||
1100 | return sprintf(buf, "%d\n", | ||
1101 | FAN_PERIOD_TO_RPM(data->fan[attr->index])); | ||
1102 | } | ||
1103 | |||
1104 | static ssize_t show_force_pwm_max(struct device *dev, | ||
1105 | struct device_attribute *devattr, | ||
1106 | char *buf) | ||
1107 | { | ||
1108 | struct adt7462_data *data = adt7462_update_device(dev); | ||
1109 | return sprintf(buf, "%d\n", (data->cfg2 & ADT7462_FSPD_MASK ? 1 : 0)); | ||
1110 | } | ||
1111 | |||
1112 | static ssize_t set_force_pwm_max(struct device *dev, | ||
1113 | struct device_attribute *devattr, | ||
1114 | const char *buf, | ||
1115 | size_t count) | ||
1116 | { | ||
1117 | struct i2c_client *client = to_i2c_client(dev); | ||
1118 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
1119 | long temp; | ||
1120 | u8 reg; | ||
1121 | |||
1122 | if (strict_strtol(buf, 10, &temp)) | ||
1123 | return -EINVAL; | ||
1124 | |||
1125 | mutex_lock(&data->lock); | ||
1126 | reg = i2c_smbus_read_byte_data(client, ADT7462_REG_CFG2); | ||
1127 | if (temp) | ||
1128 | reg |= ADT7462_FSPD_MASK; | ||
1129 | else | ||
1130 | reg &= ~ADT7462_FSPD_MASK; | ||
1131 | data->cfg2 = reg; | ||
1132 | i2c_smbus_write_byte_data(client, ADT7462_REG_CFG2, reg); | ||
1133 | mutex_unlock(&data->lock); | ||
1134 | |||
1135 | return count; | ||
1136 | } | ||
1137 | |||
1138 | static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, | ||
1139 | char *buf) | ||
1140 | { | ||
1141 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1142 | struct adt7462_data *data = adt7462_update_device(dev); | ||
1143 | return sprintf(buf, "%d\n", data->pwm[attr->index]); | ||
1144 | } | ||
1145 | |||
1146 | static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, | ||
1147 | const char *buf, size_t count) | ||
1148 | { | ||
1149 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1150 | struct i2c_client *client = to_i2c_client(dev); | ||
1151 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
1152 | long temp; | ||
1153 | |||
1154 | if (strict_strtol(buf, 10, &temp)) | ||
1155 | return -EINVAL; | ||
1156 | |||
1157 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
1158 | |||
1159 | mutex_lock(&data->lock); | ||
1160 | data->pwm[attr->index] = temp; | ||
1161 | i2c_smbus_write_byte_data(client, ADT7462_REG_PWM(attr->index), temp); | ||
1162 | mutex_unlock(&data->lock); | ||
1163 | |||
1164 | return count; | ||
1165 | } | ||
1166 | |||
1167 | static ssize_t show_pwm_max(struct device *dev, | ||
1168 | struct device_attribute *devattr, | ||
1169 | char *buf) | ||
1170 | { | ||
1171 | struct adt7462_data *data = adt7462_update_device(dev); | ||
1172 | return sprintf(buf, "%d\n", data->pwm_max); | ||
1173 | } | ||
1174 | |||
1175 | static ssize_t set_pwm_max(struct device *dev, | ||
1176 | struct device_attribute *devattr, | ||
1177 | const char *buf, | ||
1178 | size_t count) | ||
1179 | { | ||
1180 | struct i2c_client *client = to_i2c_client(dev); | ||
1181 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
1182 | long temp; | ||
1183 | |||
1184 | if (strict_strtol(buf, 10, &temp)) | ||
1185 | return -EINVAL; | ||
1186 | |||
1187 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
1188 | |||
1189 | mutex_lock(&data->lock); | ||
1190 | data->pwm_max = temp; | ||
1191 | i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_MAX, temp); | ||
1192 | mutex_unlock(&data->lock); | ||
1193 | |||
1194 | return count; | ||
1195 | } | ||
1196 | |||
1197 | static ssize_t show_pwm_min(struct device *dev, | ||
1198 | struct device_attribute *devattr, | ||
1199 | char *buf) | ||
1200 | { | ||
1201 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1202 | struct adt7462_data *data = adt7462_update_device(dev); | ||
1203 | return sprintf(buf, "%d\n", data->pwm_min[attr->index]); | ||
1204 | } | ||
1205 | |||
1206 | static ssize_t set_pwm_min(struct device *dev, | ||
1207 | struct device_attribute *devattr, | ||
1208 | const char *buf, | ||
1209 | size_t count) | ||
1210 | { | ||
1211 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1212 | struct i2c_client *client = to_i2c_client(dev); | ||
1213 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
1214 | long temp; | ||
1215 | |||
1216 | if (strict_strtol(buf, 10, &temp)) | ||
1217 | return -EINVAL; | ||
1218 | |||
1219 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
1220 | |||
1221 | mutex_lock(&data->lock); | ||
1222 | data->pwm_min[attr->index] = temp; | ||
1223 | i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_MIN(attr->index), | ||
1224 | temp); | ||
1225 | mutex_unlock(&data->lock); | ||
1226 | |||
1227 | return count; | ||
1228 | } | ||
1229 | |||
1230 | static ssize_t show_pwm_hyst(struct device *dev, | ||
1231 | struct device_attribute *devattr, | ||
1232 | char *buf) | ||
1233 | { | ||
1234 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1235 | struct adt7462_data *data = adt7462_update_device(dev); | ||
1236 | return sprintf(buf, "%d\n", 1000 * | ||
1237 | (data->pwm_trange[attr->index] & ADT7462_PWM_HYST_MASK)); | ||
1238 | } | ||
1239 | |||
1240 | static ssize_t set_pwm_hyst(struct device *dev, | ||
1241 | struct device_attribute *devattr, | ||
1242 | const char *buf, | ||
1243 | size_t count) | ||
1244 | { | ||
1245 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1246 | struct i2c_client *client = to_i2c_client(dev); | ||
1247 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
1248 | long temp; | ||
1249 | |||
1250 | if (strict_strtol(buf, 10, &temp)) | ||
1251 | return -EINVAL; | ||
1252 | |||
1253 | temp = ROUND_DIV(temp, 1000); | ||
1254 | temp = SENSORS_LIMIT(temp, 0, 15); | ||
1255 | |||
1256 | /* package things up */ | ||
1257 | temp &= ADT7462_PWM_HYST_MASK; | ||
1258 | temp |= data->pwm_trange[attr->index] & ADT7462_PWM_RANGE_MASK; | ||
1259 | |||
1260 | mutex_lock(&data->lock); | ||
1261 | data->pwm_trange[attr->index] = temp; | ||
1262 | i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TRANGE(attr->index), | ||
1263 | temp); | ||
1264 | mutex_unlock(&data->lock); | ||
1265 | |||
1266 | return count; | ||
1267 | } | ||
1268 | |||
1269 | static ssize_t show_pwm_tmax(struct device *dev, | ||
1270 | struct device_attribute *devattr, | ||
1271 | char *buf) | ||
1272 | { | ||
1273 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1274 | struct adt7462_data *data = adt7462_update_device(dev); | ||
1275 | |||
1276 | /* tmax = tmin + trange */ | ||
1277 | int trange = trange_values[data->pwm_trange[attr->index] >> | ||
1278 | ADT7462_PWM_RANGE_SHIFT]; | ||
1279 | int tmin = (data->pwm_tmin[attr->index] - 64) * 1000; | ||
1280 | |||
1281 | return sprintf(buf, "%d\n", tmin + trange); | ||
1282 | } | ||
1283 | |||
1284 | static ssize_t set_pwm_tmax(struct device *dev, | ||
1285 | struct device_attribute *devattr, | ||
1286 | const char *buf, | ||
1287 | size_t count) | ||
1288 | { | ||
1289 | int temp; | ||
1290 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1291 | struct i2c_client *client = to_i2c_client(dev); | ||
1292 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
1293 | int tmin, trange_value; | ||
1294 | long trange; | ||
1295 | |||
1296 | if (strict_strtol(buf, 10, &trange)) | ||
1297 | return -EINVAL; | ||
1298 | |||
1299 | /* trange = tmax - tmin */ | ||
1300 | tmin = (data->pwm_tmin[attr->index] - 64) * 1000; | ||
1301 | trange_value = find_trange_value(trange - tmin); | ||
1302 | |||
1303 | if (trange_value < 0) | ||
1304 | return -EINVAL; | ||
1305 | |||
1306 | temp = trange_value << ADT7462_PWM_RANGE_SHIFT; | ||
1307 | temp |= data->pwm_trange[attr->index] & ADT7462_PWM_HYST_MASK; | ||
1308 | |||
1309 | mutex_lock(&data->lock); | ||
1310 | data->pwm_trange[attr->index] = temp; | ||
1311 | i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TRANGE(attr->index), | ||
1312 | temp); | ||
1313 | mutex_unlock(&data->lock); | ||
1314 | |||
1315 | return count; | ||
1316 | } | ||
1317 | |||
1318 | static ssize_t show_pwm_tmin(struct device *dev, | ||
1319 | struct device_attribute *devattr, | ||
1320 | char *buf) | ||
1321 | { | ||
1322 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1323 | struct adt7462_data *data = adt7462_update_device(dev); | ||
1324 | return sprintf(buf, "%d\n", 1000 * (data->pwm_tmin[attr->index] - 64)); | ||
1325 | } | ||
1326 | |||
1327 | static ssize_t set_pwm_tmin(struct device *dev, | ||
1328 | struct device_attribute *devattr, | ||
1329 | const char *buf, | ||
1330 | size_t count) | ||
1331 | { | ||
1332 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1333 | struct i2c_client *client = to_i2c_client(dev); | ||
1334 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
1335 | long temp; | ||
1336 | |||
1337 | if (strict_strtol(buf, 10, &temp)) | ||
1338 | return -EINVAL; | ||
1339 | |||
1340 | temp = ROUND_DIV(temp, 1000) + 64; | ||
1341 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
1342 | |||
1343 | mutex_lock(&data->lock); | ||
1344 | data->pwm_tmin[attr->index] = temp; | ||
1345 | i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TMIN(attr->index), | ||
1346 | temp); | ||
1347 | mutex_unlock(&data->lock); | ||
1348 | |||
1349 | return count; | ||
1350 | } | ||
1351 | |||
1352 | static ssize_t show_pwm_auto(struct device *dev, | ||
1353 | struct device_attribute *devattr, | ||
1354 | char *buf) | ||
1355 | { | ||
1356 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1357 | struct adt7462_data *data = adt7462_update_device(dev); | ||
1358 | int cfg = data->pwm_cfg[attr->index] >> ADT7462_PWM_CHANNEL_SHIFT; | ||
1359 | |||
1360 | switch (cfg) { | ||
1361 | case 4: /* off */ | ||
1362 | return sprintf(buf, "0\n"); | ||
1363 | case 7: /* manual */ | ||
1364 | return sprintf(buf, "1\n"); | ||
1365 | default: /* automatic */ | ||
1366 | return sprintf(buf, "2\n"); | ||
1367 | } | ||
1368 | } | ||
1369 | |||
1370 | static void set_pwm_channel(struct i2c_client *client, | ||
1371 | struct adt7462_data *data, | ||
1372 | int which, | ||
1373 | int value) | ||
1374 | { | ||
1375 | int temp = data->pwm_cfg[which] & ~ADT7462_PWM_CHANNEL_MASK; | ||
1376 | temp |= value << ADT7462_PWM_CHANNEL_SHIFT; | ||
1377 | |||
1378 | mutex_lock(&data->lock); | ||
1379 | data->pwm_cfg[which] = temp; | ||
1380 | i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_CFG(which), temp); | ||
1381 | mutex_unlock(&data->lock); | ||
1382 | } | ||
1383 | |||
1384 | static ssize_t set_pwm_auto(struct device *dev, | ||
1385 | struct device_attribute *devattr, | ||
1386 | const char *buf, | ||
1387 | size_t count) | ||
1388 | { | ||
1389 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1390 | struct i2c_client *client = to_i2c_client(dev); | ||
1391 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
1392 | long temp; | ||
1393 | |||
1394 | if (strict_strtol(buf, 10, &temp)) | ||
1395 | return -EINVAL; | ||
1396 | |||
1397 | switch (temp) { | ||
1398 | case 0: /* off */ | ||
1399 | set_pwm_channel(client, data, attr->index, 4); | ||
1400 | return count; | ||
1401 | case 1: /* manual */ | ||
1402 | set_pwm_channel(client, data, attr->index, 7); | ||
1403 | return count; | ||
1404 | default: | ||
1405 | return -EINVAL; | ||
1406 | } | ||
1407 | } | ||
1408 | |||
1409 | static ssize_t show_pwm_auto_temp(struct device *dev, | ||
1410 | struct device_attribute *devattr, | ||
1411 | char *buf) | ||
1412 | { | ||
1413 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1414 | struct adt7462_data *data = adt7462_update_device(dev); | ||
1415 | int channel = data->pwm_cfg[attr->index] >> ADT7462_PWM_CHANNEL_SHIFT; | ||
1416 | |||
1417 | switch (channel) { | ||
1418 | case 0: /* temp[1234] only */ | ||
1419 | case 1: | ||
1420 | case 2: | ||
1421 | case 3: | ||
1422 | return sprintf(buf, "%d\n", (1 << channel)); | ||
1423 | case 5: /* temp1 & temp4 */ | ||
1424 | return sprintf(buf, "9\n"); | ||
1425 | case 6: | ||
1426 | return sprintf(buf, "15\n"); | ||
1427 | default: | ||
1428 | return sprintf(buf, "0\n"); | ||
1429 | } | ||
1430 | } | ||
1431 | |||
1432 | static int cvt_auto_temp(int input) | ||
1433 | { | ||
1434 | if (input == 0xF) | ||
1435 | return 6; | ||
1436 | if (input == 0x9) | ||
1437 | return 5; | ||
1438 | if (input < 1 || !is_power_of_2(input)) | ||
1439 | return -EINVAL; | ||
1440 | return ilog2(input); | ||
1441 | } | ||
1442 | |||
1443 | static ssize_t set_pwm_auto_temp(struct device *dev, | ||
1444 | struct device_attribute *devattr, | ||
1445 | const char *buf, | ||
1446 | size_t count) | ||
1447 | { | ||
1448 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
1449 | struct i2c_client *client = to_i2c_client(dev); | ||
1450 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
1451 | long temp; | ||
1452 | |||
1453 | if (strict_strtol(buf, 10, &temp)) | ||
1454 | return -EINVAL; | ||
1455 | |||
1456 | temp = cvt_auto_temp(temp); | ||
1457 | if (temp < 0) | ||
1458 | return temp; | ||
1459 | |||
1460 | set_pwm_channel(client, data, attr->index, temp); | ||
1461 | |||
1462 | return count; | ||
1463 | } | ||
1464 | |||
1465 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, | ||
1466 | set_temp_max, 0); | ||
1467 | static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, | ||
1468 | set_temp_max, 1); | ||
1469 | static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_max, | ||
1470 | set_temp_max, 2); | ||
1471 | static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp_max, | ||
1472 | set_temp_max, 3); | ||
1473 | |||
1474 | static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min, | ||
1475 | set_temp_min, 0); | ||
1476 | static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min, | ||
1477 | set_temp_min, 1); | ||
1478 | static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_temp_min, | ||
1479 | set_temp_min, 2); | ||
1480 | static SENSOR_DEVICE_ATTR(temp4_min, S_IWUSR | S_IRUGO, show_temp_min, | ||
1481 | set_temp_min, 3); | ||
1482 | |||
1483 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); | ||
1484 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); | ||
1485 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); | ||
1486 | static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); | ||
1487 | |||
1488 | static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0); | ||
1489 | static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1); | ||
1490 | static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2); | ||
1491 | static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3); | ||
1492 | |||
1493 | static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, | ||
1494 | ADT7462_ALARM1 | ADT7462_LT_ALARM); | ||
1495 | static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, | ||
1496 | ADT7462_ALARM1 | ADT7462_R1T_ALARM); | ||
1497 | static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, | ||
1498 | ADT7462_ALARM1 | ADT7462_R2T_ALARM); | ||
1499 | static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL, | ||
1500 | ADT7462_ALARM1 | ADT7462_R3T_ALARM); | ||
1501 | |||
1502 | static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
1503 | set_volt_max, 0); | ||
1504 | static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
1505 | set_volt_max, 1); | ||
1506 | static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
1507 | set_volt_max, 2); | ||
1508 | static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
1509 | set_volt_max, 3); | ||
1510 | static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
1511 | set_volt_max, 4); | ||
1512 | static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
1513 | set_volt_max, 5); | ||
1514 | static SENSOR_DEVICE_ATTR(in7_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
1515 | set_volt_max, 6); | ||
1516 | static SENSOR_DEVICE_ATTR(in8_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
1517 | set_volt_max, 7); | ||
1518 | static SENSOR_DEVICE_ATTR(in9_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
1519 | set_volt_max, 8); | ||
1520 | static SENSOR_DEVICE_ATTR(in10_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
1521 | set_volt_max, 9); | ||
1522 | static SENSOR_DEVICE_ATTR(in11_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
1523 | set_volt_max, 10); | ||
1524 | static SENSOR_DEVICE_ATTR(in12_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
1525 | set_volt_max, 11); | ||
1526 | static SENSOR_DEVICE_ATTR(in13_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
1527 | set_volt_max, 12); | ||
1528 | |||
1529 | static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
1530 | set_volt_min, 0); | ||
1531 | static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
1532 | set_volt_min, 1); | ||
1533 | static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
1534 | set_volt_min, 2); | ||
1535 | static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
1536 | set_volt_min, 3); | ||
1537 | static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
1538 | set_volt_min, 4); | ||
1539 | static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
1540 | set_volt_min, 5); | ||
1541 | static SENSOR_DEVICE_ATTR(in7_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
1542 | set_volt_min, 6); | ||
1543 | static SENSOR_DEVICE_ATTR(in8_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
1544 | set_volt_min, 7); | ||
1545 | static SENSOR_DEVICE_ATTR(in9_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
1546 | set_volt_min, 8); | ||
1547 | static SENSOR_DEVICE_ATTR(in10_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
1548 | set_volt_min, 9); | ||
1549 | static SENSOR_DEVICE_ATTR(in11_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
1550 | set_volt_min, 10); | ||
1551 | static SENSOR_DEVICE_ATTR(in12_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
1552 | set_volt_min, 11); | ||
1553 | static SENSOR_DEVICE_ATTR(in13_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
1554 | set_volt_min, 12); | ||
1555 | |||
1556 | static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 0); | ||
1557 | static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 1); | ||
1558 | static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_voltage, NULL, 2); | ||
1559 | static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_voltage, NULL, 3); | ||
1560 | static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 4); | ||
1561 | static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 5); | ||
1562 | static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 6); | ||
1563 | static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_voltage, NULL, 7); | ||
1564 | static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_voltage, NULL, 8); | ||
1565 | static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_voltage, NULL, 9); | ||
1566 | static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_voltage, NULL, 10); | ||
1567 | static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_voltage, NULL, 11); | ||
1568 | static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, show_voltage, NULL, 12); | ||
1569 | |||
1570 | static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_voltage_label, NULL, 0); | ||
1571 | static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_voltage_label, NULL, 1); | ||
1572 | static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_voltage_label, NULL, 2); | ||
1573 | static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, show_voltage_label, NULL, 3); | ||
1574 | static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, show_voltage_label, NULL, 4); | ||
1575 | static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, show_voltage_label, NULL, 5); | ||
1576 | static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_voltage_label, NULL, 6); | ||
1577 | static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_voltage_label, NULL, 7); | ||
1578 | static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_voltage_label, NULL, 8); | ||
1579 | static SENSOR_DEVICE_ATTR(in10_label, S_IRUGO, show_voltage_label, NULL, 9); | ||
1580 | static SENSOR_DEVICE_ATTR(in11_label, S_IRUGO, show_voltage_label, NULL, 10); | ||
1581 | static SENSOR_DEVICE_ATTR(in12_label, S_IRUGO, show_voltage_label, NULL, 11); | ||
1582 | static SENSOR_DEVICE_ATTR(in13_label, S_IRUGO, show_voltage_label, NULL, 12); | ||
1583 | |||
1584 | static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, | ||
1585 | ADT7462_ALARM2 | ADT7462_V0_ALARM); | ||
1586 | static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, | ||
1587 | ADT7462_ALARM2 | ADT7462_V7_ALARM); | ||
1588 | static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, | ||
1589 | ADT7462_ALARM2 | ADT7462_V2_ALARM); | ||
1590 | static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, | ||
1591 | ADT7462_ALARM2 | ADT7462_V6_ALARM); | ||
1592 | static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, | ||
1593 | ADT7462_ALARM2 | ADT7462_V5_ALARM); | ||
1594 | static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, | ||
1595 | ADT7462_ALARM2 | ADT7462_V4_ALARM); | ||
1596 | static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, | ||
1597 | ADT7462_ALARM2 | ADT7462_V3_ALARM); | ||
1598 | static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, | ||
1599 | ADT7462_ALARM2 | ADT7462_V1_ALARM); | ||
1600 | static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, | ||
1601 | ADT7462_ALARM3 | ADT7462_V10_ALARM); | ||
1602 | static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, | ||
1603 | ADT7462_ALARM3 | ADT7462_V9_ALARM); | ||
1604 | static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, | ||
1605 | ADT7462_ALARM3 | ADT7462_V8_ALARM); | ||
1606 | static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, | ||
1607 | ADT7462_ALARM3 | ADT7462_V11_ALARM); | ||
1608 | static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, | ||
1609 | ADT7462_ALARM3 | ADT7462_V12_ALARM); | ||
1610 | |||
1611 | static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
1612 | set_fan_min, 0); | ||
1613 | static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
1614 | set_fan_min, 1); | ||
1615 | static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
1616 | set_fan_min, 2); | ||
1617 | static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
1618 | set_fan_min, 3); | ||
1619 | static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
1620 | set_fan_min, 4); | ||
1621 | static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
1622 | set_fan_min, 5); | ||
1623 | static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
1624 | set_fan_min, 6); | ||
1625 | static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
1626 | set_fan_min, 7); | ||
1627 | |||
1628 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); | ||
1629 | static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); | ||
1630 | static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); | ||
1631 | static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); | ||
1632 | static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4); | ||
1633 | static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 5); | ||
1634 | static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 6); | ||
1635 | static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan, NULL, 7); | ||
1636 | |||
1637 | static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, | ||
1638 | ADT7462_ALARM4 | ADT7462_F0_ALARM); | ||
1639 | static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, | ||
1640 | ADT7462_ALARM4 | ADT7462_F1_ALARM); | ||
1641 | static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, | ||
1642 | ADT7462_ALARM4 | ADT7462_F2_ALARM); | ||
1643 | static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, | ||
1644 | ADT7462_ALARM4 | ADT7462_F3_ALARM); | ||
1645 | static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, | ||
1646 | ADT7462_ALARM4 | ADT7462_F4_ALARM); | ||
1647 | static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, | ||
1648 | ADT7462_ALARM4 | ADT7462_F5_ALARM); | ||
1649 | static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_alarm, NULL, | ||
1650 | ADT7462_ALARM4 | ADT7462_F6_ALARM); | ||
1651 | static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_alarm, NULL, | ||
1652 | ADT7462_ALARM4 | ADT7462_F7_ALARM); | ||
1653 | |||
1654 | static SENSOR_DEVICE_ATTR(force_pwm_max, S_IWUSR | S_IRUGO, | ||
1655 | show_force_pwm_max, set_force_pwm_max, 0); | ||
1656 | |||
1657 | static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); | ||
1658 | static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); | ||
1659 | static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); | ||
1660 | static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3); | ||
1661 | |||
1662 | static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO, | ||
1663 | show_pwm_min, set_pwm_min, 0); | ||
1664 | static SENSOR_DEVICE_ATTR(pwm2_auto_point1_pwm, S_IWUSR | S_IRUGO, | ||
1665 | show_pwm_min, set_pwm_min, 1); | ||
1666 | static SENSOR_DEVICE_ATTR(pwm3_auto_point1_pwm, S_IWUSR | S_IRUGO, | ||
1667 | show_pwm_min, set_pwm_min, 2); | ||
1668 | static SENSOR_DEVICE_ATTR(pwm4_auto_point1_pwm, S_IWUSR | S_IRUGO, | ||
1669 | show_pwm_min, set_pwm_min, 3); | ||
1670 | |||
1671 | static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO, | ||
1672 | show_pwm_max, set_pwm_max, 0); | ||
1673 | static SENSOR_DEVICE_ATTR(pwm2_auto_point2_pwm, S_IWUSR | S_IRUGO, | ||
1674 | show_pwm_max, set_pwm_max, 1); | ||
1675 | static SENSOR_DEVICE_ATTR(pwm3_auto_point2_pwm, S_IWUSR | S_IRUGO, | ||
1676 | show_pwm_max, set_pwm_max, 2); | ||
1677 | static SENSOR_DEVICE_ATTR(pwm4_auto_point2_pwm, S_IWUSR | S_IRUGO, | ||
1678 | show_pwm_max, set_pwm_max, 3); | ||
1679 | |||
1680 | static SENSOR_DEVICE_ATTR(temp1_auto_point1_hyst, S_IWUSR | S_IRUGO, | ||
1681 | show_pwm_hyst, set_pwm_hyst, 0); | ||
1682 | static SENSOR_DEVICE_ATTR(temp2_auto_point1_hyst, S_IWUSR | S_IRUGO, | ||
1683 | show_pwm_hyst, set_pwm_hyst, 1); | ||
1684 | static SENSOR_DEVICE_ATTR(temp3_auto_point1_hyst, S_IWUSR | S_IRUGO, | ||
1685 | show_pwm_hyst, set_pwm_hyst, 2); | ||
1686 | static SENSOR_DEVICE_ATTR(temp4_auto_point1_hyst, S_IWUSR | S_IRUGO, | ||
1687 | show_pwm_hyst, set_pwm_hyst, 3); | ||
1688 | |||
1689 | static SENSOR_DEVICE_ATTR(temp1_auto_point2_hyst, S_IWUSR | S_IRUGO, | ||
1690 | show_pwm_hyst, set_pwm_hyst, 0); | ||
1691 | static SENSOR_DEVICE_ATTR(temp2_auto_point2_hyst, S_IWUSR | S_IRUGO, | ||
1692 | show_pwm_hyst, set_pwm_hyst, 1); | ||
1693 | static SENSOR_DEVICE_ATTR(temp3_auto_point2_hyst, S_IWUSR | S_IRUGO, | ||
1694 | show_pwm_hyst, set_pwm_hyst, 2); | ||
1695 | static SENSOR_DEVICE_ATTR(temp4_auto_point2_hyst, S_IWUSR | S_IRUGO, | ||
1696 | show_pwm_hyst, set_pwm_hyst, 3); | ||
1697 | |||
1698 | static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp, S_IWUSR | S_IRUGO, | ||
1699 | show_pwm_tmin, set_pwm_tmin, 0); | ||
1700 | static SENSOR_DEVICE_ATTR(temp2_auto_point1_temp, S_IWUSR | S_IRUGO, | ||
1701 | show_pwm_tmin, set_pwm_tmin, 1); | ||
1702 | static SENSOR_DEVICE_ATTR(temp3_auto_point1_temp, S_IWUSR | S_IRUGO, | ||
1703 | show_pwm_tmin, set_pwm_tmin, 2); | ||
1704 | static SENSOR_DEVICE_ATTR(temp4_auto_point1_temp, S_IWUSR | S_IRUGO, | ||
1705 | show_pwm_tmin, set_pwm_tmin, 3); | ||
1706 | |||
1707 | static SENSOR_DEVICE_ATTR(temp1_auto_point2_temp, S_IWUSR | S_IRUGO, | ||
1708 | show_pwm_tmax, set_pwm_tmax, 0); | ||
1709 | static SENSOR_DEVICE_ATTR(temp2_auto_point2_temp, S_IWUSR | S_IRUGO, | ||
1710 | show_pwm_tmax, set_pwm_tmax, 1); | ||
1711 | static SENSOR_DEVICE_ATTR(temp3_auto_point2_temp, S_IWUSR | S_IRUGO, | ||
1712 | show_pwm_tmax, set_pwm_tmax, 2); | ||
1713 | static SENSOR_DEVICE_ATTR(temp4_auto_point2_temp, S_IWUSR | S_IRUGO, | ||
1714 | show_pwm_tmax, set_pwm_tmax, 3); | ||
1715 | |||
1716 | static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_auto, | ||
1717 | set_pwm_auto, 0); | ||
1718 | static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_auto, | ||
1719 | set_pwm_auto, 1); | ||
1720 | static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_auto, | ||
1721 | set_pwm_auto, 2); | ||
1722 | static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_auto, | ||
1723 | set_pwm_auto, 3); | ||
1724 | |||
1725 | static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IWUSR | S_IRUGO, | ||
1726 | show_pwm_auto_temp, set_pwm_auto_temp, 0); | ||
1727 | static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IWUSR | S_IRUGO, | ||
1728 | show_pwm_auto_temp, set_pwm_auto_temp, 1); | ||
1729 | static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IWUSR | S_IRUGO, | ||
1730 | show_pwm_auto_temp, set_pwm_auto_temp, 2); | ||
1731 | static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IWUSR | S_IRUGO, | ||
1732 | show_pwm_auto_temp, set_pwm_auto_temp, 3); | ||
1733 | |||
1734 | static struct attribute *adt7462_attr[] = | ||
1735 | { | ||
1736 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
1737 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
1738 | &sensor_dev_attr_temp3_max.dev_attr.attr, | ||
1739 | &sensor_dev_attr_temp4_max.dev_attr.attr, | ||
1740 | |||
1741 | &sensor_dev_attr_temp1_min.dev_attr.attr, | ||
1742 | &sensor_dev_attr_temp2_min.dev_attr.attr, | ||
1743 | &sensor_dev_attr_temp3_min.dev_attr.attr, | ||
1744 | &sensor_dev_attr_temp4_min.dev_attr.attr, | ||
1745 | |||
1746 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
1747 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
1748 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
1749 | &sensor_dev_attr_temp4_input.dev_attr.attr, | ||
1750 | |||
1751 | &sensor_dev_attr_temp1_label.dev_attr.attr, | ||
1752 | &sensor_dev_attr_temp2_label.dev_attr.attr, | ||
1753 | &sensor_dev_attr_temp3_label.dev_attr.attr, | ||
1754 | &sensor_dev_attr_temp4_label.dev_attr.attr, | ||
1755 | |||
1756 | &sensor_dev_attr_temp1_alarm.dev_attr.attr, | ||
1757 | &sensor_dev_attr_temp2_alarm.dev_attr.attr, | ||
1758 | &sensor_dev_attr_temp3_alarm.dev_attr.attr, | ||
1759 | &sensor_dev_attr_temp4_alarm.dev_attr.attr, | ||
1760 | |||
1761 | &sensor_dev_attr_in1_max.dev_attr.attr, | ||
1762 | &sensor_dev_attr_in2_max.dev_attr.attr, | ||
1763 | &sensor_dev_attr_in3_max.dev_attr.attr, | ||
1764 | &sensor_dev_attr_in4_max.dev_attr.attr, | ||
1765 | &sensor_dev_attr_in5_max.dev_attr.attr, | ||
1766 | &sensor_dev_attr_in6_max.dev_attr.attr, | ||
1767 | &sensor_dev_attr_in7_max.dev_attr.attr, | ||
1768 | &sensor_dev_attr_in8_max.dev_attr.attr, | ||
1769 | &sensor_dev_attr_in9_max.dev_attr.attr, | ||
1770 | &sensor_dev_attr_in10_max.dev_attr.attr, | ||
1771 | &sensor_dev_attr_in11_max.dev_attr.attr, | ||
1772 | &sensor_dev_attr_in12_max.dev_attr.attr, | ||
1773 | &sensor_dev_attr_in13_max.dev_attr.attr, | ||
1774 | |||
1775 | &sensor_dev_attr_in1_min.dev_attr.attr, | ||
1776 | &sensor_dev_attr_in2_min.dev_attr.attr, | ||
1777 | &sensor_dev_attr_in3_min.dev_attr.attr, | ||
1778 | &sensor_dev_attr_in4_min.dev_attr.attr, | ||
1779 | &sensor_dev_attr_in5_min.dev_attr.attr, | ||
1780 | &sensor_dev_attr_in6_min.dev_attr.attr, | ||
1781 | &sensor_dev_attr_in7_min.dev_attr.attr, | ||
1782 | &sensor_dev_attr_in8_min.dev_attr.attr, | ||
1783 | &sensor_dev_attr_in9_min.dev_attr.attr, | ||
1784 | &sensor_dev_attr_in10_min.dev_attr.attr, | ||
1785 | &sensor_dev_attr_in11_min.dev_attr.attr, | ||
1786 | &sensor_dev_attr_in12_min.dev_attr.attr, | ||
1787 | &sensor_dev_attr_in13_min.dev_attr.attr, | ||
1788 | |||
1789 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
1790 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
1791 | &sensor_dev_attr_in3_input.dev_attr.attr, | ||
1792 | &sensor_dev_attr_in4_input.dev_attr.attr, | ||
1793 | &sensor_dev_attr_in5_input.dev_attr.attr, | ||
1794 | &sensor_dev_attr_in6_input.dev_attr.attr, | ||
1795 | &sensor_dev_attr_in7_input.dev_attr.attr, | ||
1796 | &sensor_dev_attr_in8_input.dev_attr.attr, | ||
1797 | &sensor_dev_attr_in9_input.dev_attr.attr, | ||
1798 | &sensor_dev_attr_in10_input.dev_attr.attr, | ||
1799 | &sensor_dev_attr_in11_input.dev_attr.attr, | ||
1800 | &sensor_dev_attr_in12_input.dev_attr.attr, | ||
1801 | &sensor_dev_attr_in13_input.dev_attr.attr, | ||
1802 | |||
1803 | &sensor_dev_attr_in1_label.dev_attr.attr, | ||
1804 | &sensor_dev_attr_in2_label.dev_attr.attr, | ||
1805 | &sensor_dev_attr_in3_label.dev_attr.attr, | ||
1806 | &sensor_dev_attr_in4_label.dev_attr.attr, | ||
1807 | &sensor_dev_attr_in5_label.dev_attr.attr, | ||
1808 | &sensor_dev_attr_in6_label.dev_attr.attr, | ||
1809 | &sensor_dev_attr_in7_label.dev_attr.attr, | ||
1810 | &sensor_dev_attr_in8_label.dev_attr.attr, | ||
1811 | &sensor_dev_attr_in9_label.dev_attr.attr, | ||
1812 | &sensor_dev_attr_in10_label.dev_attr.attr, | ||
1813 | &sensor_dev_attr_in11_label.dev_attr.attr, | ||
1814 | &sensor_dev_attr_in12_label.dev_attr.attr, | ||
1815 | &sensor_dev_attr_in13_label.dev_attr.attr, | ||
1816 | |||
1817 | &sensor_dev_attr_in1_alarm.dev_attr.attr, | ||
1818 | &sensor_dev_attr_in2_alarm.dev_attr.attr, | ||
1819 | &sensor_dev_attr_in3_alarm.dev_attr.attr, | ||
1820 | &sensor_dev_attr_in4_alarm.dev_attr.attr, | ||
1821 | &sensor_dev_attr_in5_alarm.dev_attr.attr, | ||
1822 | &sensor_dev_attr_in6_alarm.dev_attr.attr, | ||
1823 | &sensor_dev_attr_in7_alarm.dev_attr.attr, | ||
1824 | &sensor_dev_attr_in8_alarm.dev_attr.attr, | ||
1825 | &sensor_dev_attr_in9_alarm.dev_attr.attr, | ||
1826 | &sensor_dev_attr_in10_alarm.dev_attr.attr, | ||
1827 | &sensor_dev_attr_in11_alarm.dev_attr.attr, | ||
1828 | &sensor_dev_attr_in12_alarm.dev_attr.attr, | ||
1829 | &sensor_dev_attr_in13_alarm.dev_attr.attr, | ||
1830 | |||
1831 | &sensor_dev_attr_fan1_min.dev_attr.attr, | ||
1832 | &sensor_dev_attr_fan2_min.dev_attr.attr, | ||
1833 | &sensor_dev_attr_fan3_min.dev_attr.attr, | ||
1834 | &sensor_dev_attr_fan4_min.dev_attr.attr, | ||
1835 | &sensor_dev_attr_fan5_min.dev_attr.attr, | ||
1836 | &sensor_dev_attr_fan6_min.dev_attr.attr, | ||
1837 | &sensor_dev_attr_fan7_min.dev_attr.attr, | ||
1838 | &sensor_dev_attr_fan8_min.dev_attr.attr, | ||
1839 | |||
1840 | &sensor_dev_attr_fan1_input.dev_attr.attr, | ||
1841 | &sensor_dev_attr_fan2_input.dev_attr.attr, | ||
1842 | &sensor_dev_attr_fan3_input.dev_attr.attr, | ||
1843 | &sensor_dev_attr_fan4_input.dev_attr.attr, | ||
1844 | &sensor_dev_attr_fan5_input.dev_attr.attr, | ||
1845 | &sensor_dev_attr_fan6_input.dev_attr.attr, | ||
1846 | &sensor_dev_attr_fan7_input.dev_attr.attr, | ||
1847 | &sensor_dev_attr_fan8_input.dev_attr.attr, | ||
1848 | |||
1849 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, | ||
1850 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, | ||
1851 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, | ||
1852 | &sensor_dev_attr_fan4_alarm.dev_attr.attr, | ||
1853 | &sensor_dev_attr_fan5_alarm.dev_attr.attr, | ||
1854 | &sensor_dev_attr_fan6_alarm.dev_attr.attr, | ||
1855 | &sensor_dev_attr_fan7_alarm.dev_attr.attr, | ||
1856 | &sensor_dev_attr_fan8_alarm.dev_attr.attr, | ||
1857 | |||
1858 | &sensor_dev_attr_force_pwm_max.dev_attr.attr, | ||
1859 | &sensor_dev_attr_pwm1.dev_attr.attr, | ||
1860 | &sensor_dev_attr_pwm2.dev_attr.attr, | ||
1861 | &sensor_dev_attr_pwm3.dev_attr.attr, | ||
1862 | &sensor_dev_attr_pwm4.dev_attr.attr, | ||
1863 | |||
1864 | &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, | ||
1865 | &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, | ||
1866 | &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, | ||
1867 | &sensor_dev_attr_pwm4_auto_point1_pwm.dev_attr.attr, | ||
1868 | |||
1869 | &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, | ||
1870 | &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, | ||
1871 | &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, | ||
1872 | &sensor_dev_attr_pwm4_auto_point2_pwm.dev_attr.attr, | ||
1873 | |||
1874 | &sensor_dev_attr_temp1_auto_point1_hyst.dev_attr.attr, | ||
1875 | &sensor_dev_attr_temp2_auto_point1_hyst.dev_attr.attr, | ||
1876 | &sensor_dev_attr_temp3_auto_point1_hyst.dev_attr.attr, | ||
1877 | &sensor_dev_attr_temp4_auto_point1_hyst.dev_attr.attr, | ||
1878 | |||
1879 | &sensor_dev_attr_temp1_auto_point2_hyst.dev_attr.attr, | ||
1880 | &sensor_dev_attr_temp2_auto_point2_hyst.dev_attr.attr, | ||
1881 | &sensor_dev_attr_temp3_auto_point2_hyst.dev_attr.attr, | ||
1882 | &sensor_dev_attr_temp4_auto_point2_hyst.dev_attr.attr, | ||
1883 | |||
1884 | &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, | ||
1885 | &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr, | ||
1886 | &sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr, | ||
1887 | &sensor_dev_attr_temp4_auto_point1_temp.dev_attr.attr, | ||
1888 | |||
1889 | &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr, | ||
1890 | &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr, | ||
1891 | &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr, | ||
1892 | &sensor_dev_attr_temp4_auto_point2_temp.dev_attr.attr, | ||
1893 | |||
1894 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, | ||
1895 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, | ||
1896 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, | ||
1897 | &sensor_dev_attr_pwm4_enable.dev_attr.attr, | ||
1898 | |||
1899 | &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, | ||
1900 | &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr, | ||
1901 | &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, | ||
1902 | &sensor_dev_attr_pwm4_auto_channels_temp.dev_attr.attr, | ||
1903 | NULL | ||
1904 | }; | ||
1905 | |||
1906 | /* Return 0 if detection is successful, -ENODEV otherwise */ | ||
1907 | static int adt7462_detect(struct i2c_client *client, int kind, | ||
1908 | struct i2c_board_info *info) | ||
1909 | { | ||
1910 | struct i2c_adapter *adapter = client->adapter; | ||
1911 | |||
1912 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
1913 | return -ENODEV; | ||
1914 | |||
1915 | if (kind <= 0) { | ||
1916 | int vendor, device, revision; | ||
1917 | |||
1918 | vendor = i2c_smbus_read_byte_data(client, ADT7462_REG_VENDOR); | ||
1919 | if (vendor != ADT7462_VENDOR) | ||
1920 | return -ENODEV; | ||
1921 | |||
1922 | device = i2c_smbus_read_byte_data(client, ADT7462_REG_DEVICE); | ||
1923 | if (device != ADT7462_DEVICE) | ||
1924 | return -ENODEV; | ||
1925 | |||
1926 | revision = i2c_smbus_read_byte_data(client, | ||
1927 | ADT7462_REG_REVISION); | ||
1928 | if (revision != ADT7462_REVISION) | ||
1929 | return -ENODEV; | ||
1930 | } else | ||
1931 | dev_dbg(&adapter->dev, "detection forced\n"); | ||
1932 | |||
1933 | strlcpy(info->type, "adt7462", I2C_NAME_SIZE); | ||
1934 | |||
1935 | return 0; | ||
1936 | } | ||
1937 | |||
1938 | static int adt7462_probe(struct i2c_client *client, | ||
1939 | const struct i2c_device_id *id) | ||
1940 | { | ||
1941 | struct adt7462_data *data; | ||
1942 | int err; | ||
1943 | |||
1944 | data = kzalloc(sizeof(struct adt7462_data), GFP_KERNEL); | ||
1945 | if (!data) { | ||
1946 | err = -ENOMEM; | ||
1947 | goto exit; | ||
1948 | } | ||
1949 | |||
1950 | i2c_set_clientdata(client, data); | ||
1951 | mutex_init(&data->lock); | ||
1952 | |||
1953 | dev_info(&client->dev, "%s chip found\n", client->name); | ||
1954 | |||
1955 | /* Register sysfs hooks */ | ||
1956 | data->attrs.attrs = adt7462_attr; | ||
1957 | err = sysfs_create_group(&client->dev.kobj, &data->attrs); | ||
1958 | if (err) | ||
1959 | goto exit_free; | ||
1960 | |||
1961 | data->hwmon_dev = hwmon_device_register(&client->dev); | ||
1962 | if (IS_ERR(data->hwmon_dev)) { | ||
1963 | err = PTR_ERR(data->hwmon_dev); | ||
1964 | goto exit_remove; | ||
1965 | } | ||
1966 | |||
1967 | return 0; | ||
1968 | |||
1969 | exit_remove: | ||
1970 | sysfs_remove_group(&client->dev.kobj, &data->attrs); | ||
1971 | exit_free: | ||
1972 | kfree(data); | ||
1973 | exit: | ||
1974 | return err; | ||
1975 | } | ||
1976 | |||
1977 | static int adt7462_remove(struct i2c_client *client) | ||
1978 | { | ||
1979 | struct adt7462_data *data = i2c_get_clientdata(client); | ||
1980 | |||
1981 | hwmon_device_unregister(data->hwmon_dev); | ||
1982 | sysfs_remove_group(&client->dev.kobj, &data->attrs); | ||
1983 | kfree(data); | ||
1984 | return 0; | ||
1985 | } | ||
1986 | |||
1987 | static int __init adt7462_init(void) | ||
1988 | { | ||
1989 | return i2c_add_driver(&adt7462_driver); | ||
1990 | } | ||
1991 | |||
1992 | static void __exit adt7462_exit(void) | ||
1993 | { | ||
1994 | i2c_del_driver(&adt7462_driver); | ||
1995 | } | ||
1996 | |||
1997 | MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>"); | ||
1998 | MODULE_DESCRIPTION("ADT7462 driver"); | ||
1999 | MODULE_LICENSE("GPL"); | ||
2000 | |||
2001 | module_init(adt7462_init); | ||
2002 | module_exit(adt7462_exit); | ||
diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c index d368d8f845e1..1311a595147e 100644 --- a/drivers/hwmon/adt7470.c +++ b/drivers/hwmon/adt7470.c | |||
@@ -137,6 +137,8 @@ I2C_CLIENT_INSMOD_1(adt7470); | |||
137 | #define FAN_PERIOD_INVALID 65535 | 137 | #define FAN_PERIOD_INVALID 65535 |
138 | #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) | 138 | #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) |
139 | 139 | ||
140 | #define ROUND_DIV(x, divisor) (((x) + ((divisor) / 2)) / (divisor)) | ||
141 | |||
140 | struct adt7470_data { | 142 | struct adt7470_data { |
141 | struct device *hwmon_dev; | 143 | struct device *hwmon_dev; |
142 | struct attribute_group attrs; | 144 | struct attribute_group attrs; |
@@ -353,7 +355,13 @@ static ssize_t set_temp_min(struct device *dev, | |||
353 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 355 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
354 | struct i2c_client *client = to_i2c_client(dev); | 356 | struct i2c_client *client = to_i2c_client(dev); |
355 | struct adt7470_data *data = i2c_get_clientdata(client); | 357 | struct adt7470_data *data = i2c_get_clientdata(client); |
356 | int temp = simple_strtol(buf, NULL, 10) / 1000; | 358 | long temp; |
359 | |||
360 | if (strict_strtol(buf, 10, &temp)) | ||
361 | return -EINVAL; | ||
362 | |||
363 | temp = ROUND_DIV(temp, 1000); | ||
364 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
357 | 365 | ||
358 | mutex_lock(&data->lock); | 366 | mutex_lock(&data->lock); |
359 | data->temp_min[attr->index] = temp; | 367 | data->temp_min[attr->index] = temp; |
@@ -381,7 +389,13 @@ static ssize_t set_temp_max(struct device *dev, | |||
381 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 389 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
382 | struct i2c_client *client = to_i2c_client(dev); | 390 | struct i2c_client *client = to_i2c_client(dev); |
383 | struct adt7470_data *data = i2c_get_clientdata(client); | 391 | struct adt7470_data *data = i2c_get_clientdata(client); |
384 | int temp = simple_strtol(buf, NULL, 10) / 1000; | 392 | long temp; |
393 | |||
394 | if (strict_strtol(buf, 10, &temp)) | ||
395 | return -EINVAL; | ||
396 | |||
397 | temp = ROUND_DIV(temp, 1000); | ||
398 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
385 | 399 | ||
386 | mutex_lock(&data->lock); | 400 | mutex_lock(&data->lock); |
387 | data->temp_max[attr->index] = temp; | 401 | data->temp_max[attr->index] = temp; |
@@ -430,11 +444,13 @@ static ssize_t set_fan_max(struct device *dev, | |||
430 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 444 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
431 | struct i2c_client *client = to_i2c_client(dev); | 445 | struct i2c_client *client = to_i2c_client(dev); |
432 | struct adt7470_data *data = i2c_get_clientdata(client); | 446 | struct adt7470_data *data = i2c_get_clientdata(client); |
433 | int temp = simple_strtol(buf, NULL, 10); | 447 | long temp; |
434 | 448 | ||
435 | if (!temp) | 449 | if (strict_strtol(buf, 10, &temp) || !temp) |
436 | return -EINVAL; | 450 | return -EINVAL; |
451 | |||
437 | temp = FAN_RPM_TO_PERIOD(temp); | 452 | temp = FAN_RPM_TO_PERIOD(temp); |
453 | temp = SENSORS_LIMIT(temp, 1, 65534); | ||
438 | 454 | ||
439 | mutex_lock(&data->lock); | 455 | mutex_lock(&data->lock); |
440 | data->fan_max[attr->index] = temp; | 456 | data->fan_max[attr->index] = temp; |
@@ -465,11 +481,13 @@ static ssize_t set_fan_min(struct device *dev, | |||
465 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 481 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
466 | struct i2c_client *client = to_i2c_client(dev); | 482 | struct i2c_client *client = to_i2c_client(dev); |
467 | struct adt7470_data *data = i2c_get_clientdata(client); | 483 | struct adt7470_data *data = i2c_get_clientdata(client); |
468 | int temp = simple_strtol(buf, NULL, 10); | 484 | long temp; |
469 | 485 | ||
470 | if (!temp) | 486 | if (strict_strtol(buf, 10, &temp) || !temp) |
471 | return -EINVAL; | 487 | return -EINVAL; |
488 | |||
472 | temp = FAN_RPM_TO_PERIOD(temp); | 489 | temp = FAN_RPM_TO_PERIOD(temp); |
490 | temp = SENSORS_LIMIT(temp, 1, 65534); | ||
473 | 491 | ||
474 | mutex_lock(&data->lock); | 492 | mutex_lock(&data->lock); |
475 | data->fan_min[attr->index] = temp; | 493 | data->fan_min[attr->index] = temp; |
@@ -507,9 +525,12 @@ static ssize_t set_force_pwm_max(struct device *dev, | |||
507 | { | 525 | { |
508 | struct i2c_client *client = to_i2c_client(dev); | 526 | struct i2c_client *client = to_i2c_client(dev); |
509 | struct adt7470_data *data = i2c_get_clientdata(client); | 527 | struct adt7470_data *data = i2c_get_clientdata(client); |
510 | int temp = simple_strtol(buf, NULL, 10); | 528 | long temp; |
511 | u8 reg; | 529 | u8 reg; |
512 | 530 | ||
531 | if (strict_strtol(buf, 10, &temp)) | ||
532 | return -EINVAL; | ||
533 | |||
513 | mutex_lock(&data->lock); | 534 | mutex_lock(&data->lock); |
514 | data->force_pwm_max = temp; | 535 | data->force_pwm_max = temp; |
515 | reg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG); | 536 | reg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG); |
@@ -537,7 +558,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, | |||
537 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 558 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
538 | struct i2c_client *client = to_i2c_client(dev); | 559 | struct i2c_client *client = to_i2c_client(dev); |
539 | struct adt7470_data *data = i2c_get_clientdata(client); | 560 | struct adt7470_data *data = i2c_get_clientdata(client); |
540 | int temp = simple_strtol(buf, NULL, 10); | 561 | long temp; |
562 | |||
563 | if (strict_strtol(buf, 10, &temp)) | ||
564 | return -EINVAL; | ||
565 | |||
566 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
541 | 567 | ||
542 | mutex_lock(&data->lock); | 568 | mutex_lock(&data->lock); |
543 | data->pwm[attr->index] = temp; | 569 | data->pwm[attr->index] = temp; |
@@ -564,7 +590,12 @@ static ssize_t set_pwm_max(struct device *dev, | |||
564 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 590 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
565 | struct i2c_client *client = to_i2c_client(dev); | 591 | struct i2c_client *client = to_i2c_client(dev); |
566 | struct adt7470_data *data = i2c_get_clientdata(client); | 592 | struct adt7470_data *data = i2c_get_clientdata(client); |
567 | int temp = simple_strtol(buf, NULL, 10); | 593 | long temp; |
594 | |||
595 | if (strict_strtol(buf, 10, &temp)) | ||
596 | return -EINVAL; | ||
597 | |||
598 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
568 | 599 | ||
569 | mutex_lock(&data->lock); | 600 | mutex_lock(&data->lock); |
570 | data->pwm_max[attr->index] = temp; | 601 | data->pwm_max[attr->index] = temp; |
@@ -592,7 +623,12 @@ static ssize_t set_pwm_min(struct device *dev, | |||
592 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 623 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
593 | struct i2c_client *client = to_i2c_client(dev); | 624 | struct i2c_client *client = to_i2c_client(dev); |
594 | struct adt7470_data *data = i2c_get_clientdata(client); | 625 | struct adt7470_data *data = i2c_get_clientdata(client); |
595 | int temp = simple_strtol(buf, NULL, 10); | 626 | long temp; |
627 | |||
628 | if (strict_strtol(buf, 10, &temp)) | ||
629 | return -EINVAL; | ||
630 | |||
631 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
596 | 632 | ||
597 | mutex_lock(&data->lock); | 633 | mutex_lock(&data->lock); |
598 | data->pwm_min[attr->index] = temp; | 634 | data->pwm_min[attr->index] = temp; |
@@ -630,7 +666,13 @@ static ssize_t set_pwm_tmin(struct device *dev, | |||
630 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 666 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
631 | struct i2c_client *client = to_i2c_client(dev); | 667 | struct i2c_client *client = to_i2c_client(dev); |
632 | struct adt7470_data *data = i2c_get_clientdata(client); | 668 | struct adt7470_data *data = i2c_get_clientdata(client); |
633 | int temp = simple_strtol(buf, NULL, 10) / 1000; | 669 | long temp; |
670 | |||
671 | if (strict_strtol(buf, 10, &temp)) | ||
672 | return -EINVAL; | ||
673 | |||
674 | temp = ROUND_DIV(temp, 1000); | ||
675 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
634 | 676 | ||
635 | mutex_lock(&data->lock); | 677 | mutex_lock(&data->lock); |
636 | data->pwm_tmin[attr->index] = temp; | 678 | data->pwm_tmin[attr->index] = temp; |
@@ -658,11 +700,14 @@ static ssize_t set_pwm_auto(struct device *dev, | |||
658 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 700 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
659 | struct i2c_client *client = to_i2c_client(dev); | 701 | struct i2c_client *client = to_i2c_client(dev); |
660 | struct adt7470_data *data = i2c_get_clientdata(client); | 702 | struct adt7470_data *data = i2c_get_clientdata(client); |
661 | int temp = simple_strtol(buf, NULL, 10); | ||
662 | int pwm_auto_reg = ADT7470_REG_PWM_CFG(attr->index); | 703 | int pwm_auto_reg = ADT7470_REG_PWM_CFG(attr->index); |
663 | int pwm_auto_reg_mask; | 704 | int pwm_auto_reg_mask; |
705 | long temp; | ||
664 | u8 reg; | 706 | u8 reg; |
665 | 707 | ||
708 | if (strict_strtol(buf, 10, &temp)) | ||
709 | return -EINVAL; | ||
710 | |||
666 | if (attr->index % 2) | 711 | if (attr->index % 2) |
667 | pwm_auto_reg_mask = ADT7470_PWM2_AUTO_MASK; | 712 | pwm_auto_reg_mask = ADT7470_PWM2_AUTO_MASK; |
668 | else | 713 | else |
@@ -716,10 +761,14 @@ static ssize_t set_pwm_auto_temp(struct device *dev, | |||
716 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 761 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
717 | struct i2c_client *client = to_i2c_client(dev); | 762 | struct i2c_client *client = to_i2c_client(dev); |
718 | struct adt7470_data *data = i2c_get_clientdata(client); | 763 | struct adt7470_data *data = i2c_get_clientdata(client); |
719 | int temp = cvt_auto_temp(simple_strtol(buf, NULL, 10)); | ||
720 | int pwm_auto_reg = ADT7470_REG_PWM_AUTO_TEMP(attr->index); | 764 | int pwm_auto_reg = ADT7470_REG_PWM_AUTO_TEMP(attr->index); |
765 | long temp; | ||
721 | u8 reg; | 766 | u8 reg; |
722 | 767 | ||
768 | if (strict_strtol(buf, 10, &temp)) | ||
769 | return -EINVAL; | ||
770 | |||
771 | temp = cvt_auto_temp(temp); | ||
723 | if (temp < 0) | 772 | if (temp < 0) |
724 | return temp; | 773 | return temp; |
725 | 774 | ||
diff --git a/drivers/hwmon/adt7473.c b/drivers/hwmon/adt7473.c index b9a8ea30c99c..18aa30866a6c 100644 --- a/drivers/hwmon/adt7473.c +++ b/drivers/hwmon/adt7473.c | |||
@@ -129,6 +129,8 @@ I2C_CLIENT_INSMOD_1(adt7473); | |||
129 | #define FAN_PERIOD_INVALID 65535 | 129 | #define FAN_PERIOD_INVALID 65535 |
130 | #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) | 130 | #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) |
131 | 131 | ||
132 | #define ROUND_DIV(x, divisor) (((x) + ((divisor) / 2)) / (divisor)) | ||
133 | |||
132 | struct adt7473_data { | 134 | struct adt7473_data { |
133 | struct device *hwmon_dev; | 135 | struct device *hwmon_dev; |
134 | struct attribute_group attrs; | 136 | struct attribute_group attrs; |
@@ -357,7 +359,12 @@ static ssize_t set_volt_min(struct device *dev, | |||
357 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 359 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
358 | struct i2c_client *client = to_i2c_client(dev); | 360 | struct i2c_client *client = to_i2c_client(dev); |
359 | struct adt7473_data *data = i2c_get_clientdata(client); | 361 | struct adt7473_data *data = i2c_get_clientdata(client); |
360 | int volt = encode_volt(attr->index, simple_strtol(buf, NULL, 10)); | 362 | long volt; |
363 | |||
364 | if (strict_strtol(buf, 10, &volt)) | ||
365 | return -EINVAL; | ||
366 | |||
367 | volt = encode_volt(attr->index, volt); | ||
361 | 368 | ||
362 | mutex_lock(&data->lock); | 369 | mutex_lock(&data->lock); |
363 | data->volt_min[attr->index] = volt; | 370 | data->volt_min[attr->index] = volt; |
@@ -386,7 +393,12 @@ static ssize_t set_volt_max(struct device *dev, | |||
386 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 393 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
387 | struct i2c_client *client = to_i2c_client(dev); | 394 | struct i2c_client *client = to_i2c_client(dev); |
388 | struct adt7473_data *data = i2c_get_clientdata(client); | 395 | struct adt7473_data *data = i2c_get_clientdata(client); |
389 | int volt = encode_volt(attr->index, simple_strtol(buf, NULL, 10)); | 396 | long volt; |
397 | |||
398 | if (strict_strtol(buf, 10, &volt)) | ||
399 | return -EINVAL; | ||
400 | |||
401 | volt = encode_volt(attr->index, volt); | ||
390 | 402 | ||
391 | mutex_lock(&data->lock); | 403 | mutex_lock(&data->lock); |
392 | data->volt_max[attr->index] = volt; | 404 | data->volt_max[attr->index] = volt; |
@@ -419,7 +431,8 @@ static int decode_temp(u8 twos_complement, u8 raw) | |||
419 | 431 | ||
420 | static u8 encode_temp(u8 twos_complement, int cooked) | 432 | static u8 encode_temp(u8 twos_complement, int cooked) |
421 | { | 433 | { |
422 | return twos_complement ? cooked & 0xFF : cooked + 64; | 434 | u8 ret = twos_complement ? cooked & 0xFF : cooked + 64; |
435 | return SENSORS_LIMIT(ret, 0, 255); | ||
423 | } | 436 | } |
424 | 437 | ||
425 | static ssize_t show_temp_min(struct device *dev, | 438 | static ssize_t show_temp_min(struct device *dev, |
@@ -441,7 +454,12 @@ static ssize_t set_temp_min(struct device *dev, | |||
441 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 454 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
442 | struct i2c_client *client = to_i2c_client(dev); | 455 | struct i2c_client *client = to_i2c_client(dev); |
443 | struct adt7473_data *data = i2c_get_clientdata(client); | 456 | struct adt7473_data *data = i2c_get_clientdata(client); |
444 | int temp = simple_strtol(buf, NULL, 10) / 1000; | 457 | long temp; |
458 | |||
459 | if (strict_strtol(buf, 10, &temp)) | ||
460 | return -EINVAL; | ||
461 | |||
462 | temp = ROUND_DIV(temp, 1000); | ||
445 | temp = encode_temp(data->temp_twos_complement, temp); | 463 | temp = encode_temp(data->temp_twos_complement, temp); |
446 | 464 | ||
447 | mutex_lock(&data->lock); | 465 | mutex_lock(&data->lock); |
@@ -472,7 +490,12 @@ static ssize_t set_temp_max(struct device *dev, | |||
472 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 490 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
473 | struct i2c_client *client = to_i2c_client(dev); | 491 | struct i2c_client *client = to_i2c_client(dev); |
474 | struct adt7473_data *data = i2c_get_clientdata(client); | 492 | struct adt7473_data *data = i2c_get_clientdata(client); |
475 | int temp = simple_strtol(buf, NULL, 10) / 1000; | 493 | long temp; |
494 | |||
495 | if (strict_strtol(buf, 10, &temp)) | ||
496 | return -EINVAL; | ||
497 | |||
498 | temp = ROUND_DIV(temp, 1000); | ||
476 | temp = encode_temp(data->temp_twos_complement, temp); | 499 | temp = encode_temp(data->temp_twos_complement, temp); |
477 | 500 | ||
478 | mutex_lock(&data->lock); | 501 | mutex_lock(&data->lock); |
@@ -515,11 +538,13 @@ static ssize_t set_fan_min(struct device *dev, | |||
515 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 538 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
516 | struct i2c_client *client = to_i2c_client(dev); | 539 | struct i2c_client *client = to_i2c_client(dev); |
517 | struct adt7473_data *data = i2c_get_clientdata(client); | 540 | struct adt7473_data *data = i2c_get_clientdata(client); |
518 | int temp = simple_strtol(buf, NULL, 10); | 541 | long temp; |
519 | 542 | ||
520 | if (!temp) | 543 | if (strict_strtol(buf, 10, &temp) || !temp) |
521 | return -EINVAL; | 544 | return -EINVAL; |
545 | |||
522 | temp = FAN_RPM_TO_PERIOD(temp); | 546 | temp = FAN_RPM_TO_PERIOD(temp); |
547 | temp = SENSORS_LIMIT(temp, 1, 65534); | ||
523 | 548 | ||
524 | mutex_lock(&data->lock); | 549 | mutex_lock(&data->lock); |
525 | data->fan_min[attr->index] = temp; | 550 | data->fan_min[attr->index] = temp; |
@@ -558,7 +583,10 @@ static ssize_t set_max_duty_at_crit(struct device *dev, | |||
558 | u8 reg; | 583 | u8 reg; |
559 | struct i2c_client *client = to_i2c_client(dev); | 584 | struct i2c_client *client = to_i2c_client(dev); |
560 | struct adt7473_data *data = i2c_get_clientdata(client); | 585 | struct adt7473_data *data = i2c_get_clientdata(client); |
561 | int temp = simple_strtol(buf, NULL, 10); | 586 | long temp; |
587 | |||
588 | if (strict_strtol(buf, 10, &temp)) | ||
589 | return -EINVAL; | ||
562 | 590 | ||
563 | mutex_lock(&data->lock); | 591 | mutex_lock(&data->lock); |
564 | data->max_duty_at_overheat = !!temp; | 592 | data->max_duty_at_overheat = !!temp; |
@@ -587,7 +615,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, | |||
587 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 615 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
588 | struct i2c_client *client = to_i2c_client(dev); | 616 | struct i2c_client *client = to_i2c_client(dev); |
589 | struct adt7473_data *data = i2c_get_clientdata(client); | 617 | struct adt7473_data *data = i2c_get_clientdata(client); |
590 | int temp = simple_strtol(buf, NULL, 10); | 618 | long temp; |
619 | |||
620 | if (strict_strtol(buf, 10, &temp)) | ||
621 | return -EINVAL; | ||
622 | |||
623 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
591 | 624 | ||
592 | mutex_lock(&data->lock); | 625 | mutex_lock(&data->lock); |
593 | data->pwm[attr->index] = temp; | 626 | data->pwm[attr->index] = temp; |
@@ -614,7 +647,12 @@ static ssize_t set_pwm_max(struct device *dev, | |||
614 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 647 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
615 | struct i2c_client *client = to_i2c_client(dev); | 648 | struct i2c_client *client = to_i2c_client(dev); |
616 | struct adt7473_data *data = i2c_get_clientdata(client); | 649 | struct adt7473_data *data = i2c_get_clientdata(client); |
617 | int temp = simple_strtol(buf, NULL, 10); | 650 | long temp; |
651 | |||
652 | if (strict_strtol(buf, 10, &temp)) | ||
653 | return -EINVAL; | ||
654 | |||
655 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
618 | 656 | ||
619 | mutex_lock(&data->lock); | 657 | mutex_lock(&data->lock); |
620 | data->pwm_max[attr->index] = temp; | 658 | data->pwm_max[attr->index] = temp; |
@@ -642,7 +680,12 @@ static ssize_t set_pwm_min(struct device *dev, | |||
642 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 680 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
643 | struct i2c_client *client = to_i2c_client(dev); | 681 | struct i2c_client *client = to_i2c_client(dev); |
644 | struct adt7473_data *data = i2c_get_clientdata(client); | 682 | struct adt7473_data *data = i2c_get_clientdata(client); |
645 | int temp = simple_strtol(buf, NULL, 10); | 683 | long temp; |
684 | |||
685 | if (strict_strtol(buf, 10, &temp)) | ||
686 | return -EINVAL; | ||
687 | |||
688 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
646 | 689 | ||
647 | mutex_lock(&data->lock); | 690 | mutex_lock(&data->lock); |
648 | data->pwm_min[attr->index] = temp; | 691 | data->pwm_min[attr->index] = temp; |
@@ -672,7 +715,12 @@ static ssize_t set_temp_tmax(struct device *dev, | |||
672 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 715 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
673 | struct i2c_client *client = to_i2c_client(dev); | 716 | struct i2c_client *client = to_i2c_client(dev); |
674 | struct adt7473_data *data = i2c_get_clientdata(client); | 717 | struct adt7473_data *data = i2c_get_clientdata(client); |
675 | int temp = simple_strtol(buf, NULL, 10) / 1000; | 718 | long temp; |
719 | |||
720 | if (strict_strtol(buf, 10, &temp)) | ||
721 | return -EINVAL; | ||
722 | |||
723 | temp = ROUND_DIV(temp, 1000); | ||
676 | temp = encode_temp(data->temp_twos_complement, temp); | 724 | temp = encode_temp(data->temp_twos_complement, temp); |
677 | 725 | ||
678 | mutex_lock(&data->lock); | 726 | mutex_lock(&data->lock); |
@@ -703,7 +751,12 @@ static ssize_t set_temp_tmin(struct device *dev, | |||
703 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 751 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
704 | struct i2c_client *client = to_i2c_client(dev); | 752 | struct i2c_client *client = to_i2c_client(dev); |
705 | struct adt7473_data *data = i2c_get_clientdata(client); | 753 | struct adt7473_data *data = i2c_get_clientdata(client); |
706 | int temp = simple_strtol(buf, NULL, 10) / 1000; | 754 | long temp; |
755 | |||
756 | if (strict_strtol(buf, 10, &temp)) | ||
757 | return -EINVAL; | ||
758 | |||
759 | temp = ROUND_DIV(temp, 1000); | ||
707 | temp = encode_temp(data->temp_twos_complement, temp); | 760 | temp = encode_temp(data->temp_twos_complement, temp); |
708 | 761 | ||
709 | mutex_lock(&data->lock); | 762 | mutex_lock(&data->lock); |
@@ -741,7 +794,10 @@ static ssize_t set_pwm_enable(struct device *dev, | |||
741 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 794 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
742 | struct i2c_client *client = to_i2c_client(dev); | 795 | struct i2c_client *client = to_i2c_client(dev); |
743 | struct adt7473_data *data = i2c_get_clientdata(client); | 796 | struct adt7473_data *data = i2c_get_clientdata(client); |
744 | int temp = simple_strtol(buf, NULL, 10); | 797 | long temp; |
798 | |||
799 | if (strict_strtol(buf, 10, &temp)) | ||
800 | return -EINVAL; | ||
745 | 801 | ||
746 | switch (temp) { | 802 | switch (temp) { |
747 | case 0: | 803 | case 0: |
@@ -805,7 +861,10 @@ static ssize_t set_pwm_auto_temp(struct device *dev, | |||
805 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 861 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
806 | struct i2c_client *client = to_i2c_client(dev); | 862 | struct i2c_client *client = to_i2c_client(dev); |
807 | struct adt7473_data *data = i2c_get_clientdata(client); | 863 | struct adt7473_data *data = i2c_get_clientdata(client); |
808 | int temp = simple_strtol(buf, NULL, 10); | 864 | long temp; |
865 | |||
866 | if (strict_strtol(buf, 10, &temp)) | ||
867 | return -EINVAL; | ||
809 | 868 | ||
810 | switch (temp) { | 869 | switch (temp) { |
811 | case 1: | 870 | case 1: |
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index be3285912cb7..488e45cd43d7 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c | |||
@@ -1280,7 +1280,7 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = { | |||
1280 | { .accelerometer = 0, .light = 0, .temperature_set = 4 }, | 1280 | { .accelerometer = 0, .light = 0, .temperature_set = 4 }, |
1281 | /* iMac: temperature set 5 */ | 1281 | /* iMac: temperature set 5 */ |
1282 | { .accelerometer = 0, .light = 0, .temperature_set = 5 }, | 1282 | { .accelerometer = 0, .light = 0, .temperature_set = 5 }, |
1283 | /* MacBook3: accelerometer and temperature set 6 */ | 1283 | /* MacBook3, MacBook4: accelerometer and temperature set 6 */ |
1284 | { .accelerometer = 1, .light = 0, .temperature_set = 6 }, | 1284 | { .accelerometer = 1, .light = 0, .temperature_set = 6 }, |
1285 | /* MacBook Air: accelerometer, backlight and temperature set 7 */ | 1285 | /* MacBook Air: accelerometer, backlight and temperature set 7 */ |
1286 | { .accelerometer = 1, .light = 1, .temperature_set = 7 }, | 1286 | { .accelerometer = 1, .light = 1, .temperature_set = 7 }, |
@@ -1329,6 +1329,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { | |||
1329 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), | 1329 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), |
1330 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBook3") }, | 1330 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBook3") }, |
1331 | &applesmc_dmi_data[6]}, | 1331 | &applesmc_dmi_data[6]}, |
1332 | { applesmc_dmi_match, "Apple MacBook 4", { | ||
1333 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | ||
1334 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4") }, | ||
1335 | &applesmc_dmi_data[6]}, | ||
1332 | { applesmc_dmi_match, "Apple MacBook 5", { | 1336 | { applesmc_dmi_match, "Apple MacBook 5", { |
1333 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | 1337 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), |
1334 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5") }, | 1338 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5") }, |
diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c index 7b0ed5dea399..fe74609a7feb 100644 --- a/drivers/hwmon/ibmaem.c +++ b/drivers/hwmon/ibmaem.c | |||
@@ -88,9 +88,11 @@ | |||
88 | static DEFINE_IDR(aem_idr); | 88 | static DEFINE_IDR(aem_idr); |
89 | static DEFINE_SPINLOCK(aem_idr_lock); | 89 | static DEFINE_SPINLOCK(aem_idr_lock); |
90 | 90 | ||
91 | static struct device_driver aem_driver = { | 91 | static struct platform_driver aem_driver = { |
92 | .name = DRVNAME, | 92 | .driver = { |
93 | .bus = &platform_bus_type, | 93 | .name = DRVNAME, |
94 | .bus = &platform_bus_type, | ||
95 | } | ||
94 | }; | 96 | }; |
95 | 97 | ||
96 | struct aem_ipmi_data { | 98 | struct aem_ipmi_data { |
@@ -583,7 +585,7 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle) | |||
583 | data->pdev = platform_device_alloc(DRVNAME, data->id); | 585 | data->pdev = platform_device_alloc(DRVNAME, data->id); |
584 | if (!data->pdev) | 586 | if (!data->pdev) |
585 | goto dev_err; | 587 | goto dev_err; |
586 | data->pdev->dev.driver = &aem_driver; | 588 | data->pdev->dev.driver = &aem_driver.driver; |
587 | 589 | ||
588 | res = platform_device_add(data->pdev); | 590 | res = platform_device_add(data->pdev); |
589 | if (res) | 591 | if (res) |
@@ -716,7 +718,7 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe, | |||
716 | data->pdev = platform_device_alloc(DRVNAME, data->id); | 718 | data->pdev = platform_device_alloc(DRVNAME, data->id); |
717 | if (!data->pdev) | 719 | if (!data->pdev) |
718 | goto dev_err; | 720 | goto dev_err; |
719 | data->pdev->dev.driver = &aem_driver; | 721 | data->pdev->dev.driver = &aem_driver.driver; |
720 | 722 | ||
721 | res = platform_device_add(data->pdev); | 723 | res = platform_device_add(data->pdev); |
722 | if (res) | 724 | if (res) |
@@ -1085,7 +1087,7 @@ static int __init aem_init(void) | |||
1085 | { | 1087 | { |
1086 | int res; | 1088 | int res; |
1087 | 1089 | ||
1088 | res = driver_register(&aem_driver); | 1090 | res = driver_register(&aem_driver.driver); |
1089 | if (res) { | 1091 | if (res) { |
1090 | printk(KERN_ERR "Can't register aem driver\n"); | 1092 | printk(KERN_ERR "Can't register aem driver\n"); |
1091 | return res; | 1093 | return res; |
@@ -1097,7 +1099,7 @@ static int __init aem_init(void) | |||
1097 | return 0; | 1099 | return 0; |
1098 | 1100 | ||
1099 | ipmi_reg_err: | 1101 | ipmi_reg_err: |
1100 | driver_unregister(&aem_driver); | 1102 | driver_unregister(&aem_driver.driver); |
1101 | return res; | 1103 | return res; |
1102 | 1104 | ||
1103 | } | 1105 | } |
@@ -1107,7 +1109,7 @@ static void __exit aem_exit(void) | |||
1107 | struct aem_data *p1, *next1; | 1109 | struct aem_data *p1, *next1; |
1108 | 1110 | ||
1109 | ipmi_smi_watcher_unregister(&driver_data.bmc_events); | 1111 | ipmi_smi_watcher_unregister(&driver_data.bmc_events); |
1110 | driver_unregister(&aem_driver); | 1112 | driver_unregister(&aem_driver.driver); |
1111 | list_for_each_entry_safe(p1, next1, &driver_data.aem_devices, list) | 1113 | list_for_each_entry_safe(p1, next1, &driver_data.aem_devices, list) |
1112 | aem_delete(p1); | 1114 | aem_delete(p1); |
1113 | } | 1115 | } |
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c new file mode 100644 index 000000000000..752b5c44df9c --- /dev/null +++ b/drivers/hwmon/lis3lv02d.c | |||
@@ -0,0 +1,582 @@ | |||
1 | /* | ||
2 | * lis3lv02d.c - ST LIS3LV02DL accelerometer driver | ||
3 | * | ||
4 | * Copyright (C) 2007-2008 Yan Burman | ||
5 | * Copyright (C) 2008 Eric Piel | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/dmi.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/types.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/input.h> | ||
30 | #include <linux/kthread.h> | ||
31 | #include <linux/semaphore.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/wait.h> | ||
34 | #include <linux/poll.h> | ||
35 | #include <linux/freezer.h> | ||
36 | #include <linux/version.h> | ||
37 | #include <linux/uaccess.h> | ||
38 | #include <acpi/acpi_drivers.h> | ||
39 | #include <asm/atomic.h> | ||
40 | #include "lis3lv02d.h" | ||
41 | |||
42 | #define DRIVER_NAME "lis3lv02d" | ||
43 | #define ACPI_MDPS_CLASS "accelerometer" | ||
44 | |||
45 | /* joystick device poll interval in milliseconds */ | ||
46 | #define MDPS_POLL_INTERVAL 50 | ||
47 | /* | ||
48 | * The sensor can also generate interrupts (DRDY) but it's pretty pointless | ||
49 | * because their are generated even if the data do not change. So it's better | ||
50 | * to keep the interrupt for the free-fall event. The values are updated at | ||
51 | * 40Hz (at the lowest frequency), but as it can be pretty time consuming on | ||
52 | * some low processor, we poll the sensor only at 20Hz... enough for the | ||
53 | * joystick. | ||
54 | */ | ||
55 | |||
56 | /* Maximum value our axis may get for the input device (signed 12 bits) */ | ||
57 | #define MDPS_MAX_VAL 2048 | ||
58 | |||
59 | struct axis_conversion { | ||
60 | s8 x; | ||
61 | s8 y; | ||
62 | s8 z; | ||
63 | }; | ||
64 | |||
65 | struct acpi_lis3lv02d { | ||
66 | struct acpi_device *device; /* The ACPI device */ | ||
67 | struct input_dev *idev; /* input device */ | ||
68 | struct task_struct *kthread; /* kthread for input */ | ||
69 | struct mutex lock; | ||
70 | struct platform_device *pdev; /* platform device */ | ||
71 | atomic_t count; /* interrupt count after last read */ | ||
72 | int xcalib; /* calibrated null value for x */ | ||
73 | int ycalib; /* calibrated null value for y */ | ||
74 | int zcalib; /* calibrated null value for z */ | ||
75 | unsigned char is_on; /* whether the device is on or off */ | ||
76 | unsigned char usage; /* usage counter */ | ||
77 | struct axis_conversion ac; /* hw -> logical axis */ | ||
78 | }; | ||
79 | |||
80 | static struct acpi_lis3lv02d adev; | ||
81 | |||
82 | static int lis3lv02d_remove_fs(void); | ||
83 | static int lis3lv02d_add_fs(struct acpi_device *device); | ||
84 | |||
85 | /* For automatic insertion of the module */ | ||
86 | static struct acpi_device_id lis3lv02d_device_ids[] = { | ||
87 | {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */ | ||
88 | {"", 0}, | ||
89 | }; | ||
90 | MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids); | ||
91 | |||
92 | /** | ||
93 | * lis3lv02d_acpi_init - ACPI _INI method: initialize the device. | ||
94 | * @handle: the handle of the device | ||
95 | * | ||
96 | * Returns AE_OK on success. | ||
97 | */ | ||
98 | static inline acpi_status lis3lv02d_acpi_init(acpi_handle handle) | ||
99 | { | ||
100 | return acpi_evaluate_object(handle, METHOD_NAME__INI, NULL, NULL); | ||
101 | } | ||
102 | |||
103 | /** | ||
104 | * lis3lv02d_acpi_read - ACPI ALRD method: read a register | ||
105 | * @handle: the handle of the device | ||
106 | * @reg: the register to read | ||
107 | * @ret: result of the operation | ||
108 | * | ||
109 | * Returns AE_OK on success. | ||
110 | */ | ||
111 | static acpi_status lis3lv02d_acpi_read(acpi_handle handle, int reg, u8 *ret) | ||
112 | { | ||
113 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | ||
114 | struct acpi_object_list args = { 1, &arg0 }; | ||
115 | unsigned long long lret; | ||
116 | acpi_status status; | ||
117 | |||
118 | arg0.integer.value = reg; | ||
119 | |||
120 | status = acpi_evaluate_integer(handle, "ALRD", &args, &lret); | ||
121 | *ret = lret; | ||
122 | return status; | ||
123 | } | ||
124 | |||
125 | /** | ||
126 | * lis3lv02d_acpi_write - ACPI ALWR method: write to a register | ||
127 | * @handle: the handle of the device | ||
128 | * @reg: the register to write to | ||
129 | * @val: the value to write | ||
130 | * | ||
131 | * Returns AE_OK on success. | ||
132 | */ | ||
133 | static acpi_status lis3lv02d_acpi_write(acpi_handle handle, int reg, u8 val) | ||
134 | { | ||
135 | unsigned long long ret; /* Not used when writting */ | ||
136 | union acpi_object in_obj[2]; | ||
137 | struct acpi_object_list args = { 2, in_obj }; | ||
138 | |||
139 | in_obj[0].type = ACPI_TYPE_INTEGER; | ||
140 | in_obj[0].integer.value = reg; | ||
141 | in_obj[1].type = ACPI_TYPE_INTEGER; | ||
142 | in_obj[1].integer.value = val; | ||
143 | |||
144 | return acpi_evaluate_integer(handle, "ALWR", &args, &ret); | ||
145 | } | ||
146 | |||
147 | static s16 lis3lv02d_read_16(acpi_handle handle, int reg) | ||
148 | { | ||
149 | u8 lo, hi; | ||
150 | |||
151 | lis3lv02d_acpi_read(handle, reg, &lo); | ||
152 | lis3lv02d_acpi_read(handle, reg + 1, &hi); | ||
153 | /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */ | ||
154 | return (s16)((hi << 8) | lo); | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * lis3lv02d_get_axis - For the given axis, give the value converted | ||
159 | * @axis: 1,2,3 - can also be negative | ||
160 | * @hw_values: raw values returned by the hardware | ||
161 | * | ||
162 | * Returns the converted value. | ||
163 | */ | ||
164 | static inline int lis3lv02d_get_axis(s8 axis, int hw_values[3]) | ||
165 | { | ||
166 | if (axis > 0) | ||
167 | return hw_values[axis - 1]; | ||
168 | else | ||
169 | return -hw_values[-axis - 1]; | ||
170 | } | ||
171 | |||
172 | /** | ||
173 | * lis3lv02d_get_xyz - Get X, Y and Z axis values from the accelerometer | ||
174 | * @handle: the handle to the device | ||
175 | * @x: where to store the X axis value | ||
176 | * @y: where to store the Y axis value | ||
177 | * @z: where to store the Z axis value | ||
178 | * | ||
179 | * Note that 40Hz input device can eat up about 10% CPU at 800MHZ | ||
180 | */ | ||
181 | static void lis3lv02d_get_xyz(acpi_handle handle, int *x, int *y, int *z) | ||
182 | { | ||
183 | int position[3]; | ||
184 | |||
185 | position[0] = lis3lv02d_read_16(handle, OUTX_L); | ||
186 | position[1] = lis3lv02d_read_16(handle, OUTY_L); | ||
187 | position[2] = lis3lv02d_read_16(handle, OUTZ_L); | ||
188 | |||
189 | *x = lis3lv02d_get_axis(adev.ac.x, position); | ||
190 | *y = lis3lv02d_get_axis(adev.ac.y, position); | ||
191 | *z = lis3lv02d_get_axis(adev.ac.z, position); | ||
192 | } | ||
193 | |||
194 | static inline void lis3lv02d_poweroff(acpi_handle handle) | ||
195 | { | ||
196 | adev.is_on = 0; | ||
197 | /* disable X,Y,Z axis and power down */ | ||
198 | lis3lv02d_acpi_write(handle, CTRL_REG1, 0x00); | ||
199 | } | ||
200 | |||
201 | static void lis3lv02d_poweron(acpi_handle handle) | ||
202 | { | ||
203 | u8 val; | ||
204 | |||
205 | adev.is_on = 1; | ||
206 | lis3lv02d_acpi_init(handle); | ||
207 | lis3lv02d_acpi_write(handle, FF_WU_CFG, 0); | ||
208 | /* | ||
209 | * BDU: LSB and MSB values are not updated until both have been read. | ||
210 | * So the value read will always be correct. | ||
211 | * IEN: Interrupt for free-fall and DD, not for data-ready. | ||
212 | */ | ||
213 | lis3lv02d_acpi_read(handle, CTRL_REG2, &val); | ||
214 | val |= CTRL2_BDU | CTRL2_IEN; | ||
215 | lis3lv02d_acpi_write(handle, CTRL_REG2, val); | ||
216 | } | ||
217 | |||
218 | #ifdef CONFIG_PM | ||
219 | static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state) | ||
220 | { | ||
221 | /* make sure the device is off when we suspend */ | ||
222 | lis3lv02d_poweroff(device->handle); | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static int lis3lv02d_resume(struct acpi_device *device) | ||
227 | { | ||
228 | /* put back the device in the right state (ACPI might turn it on) */ | ||
229 | mutex_lock(&adev.lock); | ||
230 | if (adev.usage > 0) | ||
231 | lis3lv02d_poweron(device->handle); | ||
232 | else | ||
233 | lis3lv02d_poweroff(device->handle); | ||
234 | mutex_unlock(&adev.lock); | ||
235 | return 0; | ||
236 | } | ||
237 | #else | ||
238 | #define lis3lv02d_suspend NULL | ||
239 | #define lis3lv02d_resume NULL | ||
240 | #endif | ||
241 | |||
242 | |||
243 | /* | ||
244 | * To be called before starting to use the device. It makes sure that the | ||
245 | * device will always be on until a call to lis3lv02d_decrease_use(). Not to be | ||
246 | * used from interrupt context. | ||
247 | */ | ||
248 | static void lis3lv02d_increase_use(struct acpi_lis3lv02d *dev) | ||
249 | { | ||
250 | mutex_lock(&dev->lock); | ||
251 | dev->usage++; | ||
252 | if (dev->usage == 1) { | ||
253 | if (!dev->is_on) | ||
254 | lis3lv02d_poweron(dev->device->handle); | ||
255 | } | ||
256 | mutex_unlock(&dev->lock); | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * To be called whenever a usage of the device is stopped. | ||
261 | * It will make sure to turn off the device when there is not usage. | ||
262 | */ | ||
263 | static void lis3lv02d_decrease_use(struct acpi_lis3lv02d *dev) | ||
264 | { | ||
265 | mutex_lock(&dev->lock); | ||
266 | dev->usage--; | ||
267 | if (dev->usage == 0) | ||
268 | lis3lv02d_poweroff(dev->device->handle); | ||
269 | mutex_unlock(&dev->lock); | ||
270 | } | ||
271 | |||
272 | /** | ||
273 | * lis3lv02d_joystick_kthread - Kthread polling function | ||
274 | * @data: unused - here to conform to threadfn prototype | ||
275 | */ | ||
276 | static int lis3lv02d_joystick_kthread(void *data) | ||
277 | { | ||
278 | int x, y, z; | ||
279 | |||
280 | while (!kthread_should_stop()) { | ||
281 | lis3lv02d_get_xyz(adev.device->handle, &x, &y, &z); | ||
282 | input_report_abs(adev.idev, ABS_X, x - adev.xcalib); | ||
283 | input_report_abs(adev.idev, ABS_Y, y - adev.ycalib); | ||
284 | input_report_abs(adev.idev, ABS_Z, z - adev.zcalib); | ||
285 | |||
286 | input_sync(adev.idev); | ||
287 | |||
288 | try_to_freeze(); | ||
289 | msleep_interruptible(MDPS_POLL_INTERVAL); | ||
290 | } | ||
291 | |||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | static int lis3lv02d_joystick_open(struct input_dev *input) | ||
296 | { | ||
297 | lis3lv02d_increase_use(&adev); | ||
298 | adev.kthread = kthread_run(lis3lv02d_joystick_kthread, NULL, "klis3lv02d"); | ||
299 | if (IS_ERR(adev.kthread)) { | ||
300 | lis3lv02d_decrease_use(&adev); | ||
301 | return PTR_ERR(adev.kthread); | ||
302 | } | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static void lis3lv02d_joystick_close(struct input_dev *input) | ||
308 | { | ||
309 | kthread_stop(adev.kthread); | ||
310 | lis3lv02d_decrease_use(&adev); | ||
311 | } | ||
312 | |||
313 | |||
314 | static inline void lis3lv02d_calibrate_joystick(void) | ||
315 | { | ||
316 | lis3lv02d_get_xyz(adev.device->handle, &adev.xcalib, &adev.ycalib, &adev.zcalib); | ||
317 | } | ||
318 | |||
319 | static int lis3lv02d_joystick_enable(void) | ||
320 | { | ||
321 | int err; | ||
322 | |||
323 | if (adev.idev) | ||
324 | return -EINVAL; | ||
325 | |||
326 | adev.idev = input_allocate_device(); | ||
327 | if (!adev.idev) | ||
328 | return -ENOMEM; | ||
329 | |||
330 | lis3lv02d_calibrate_joystick(); | ||
331 | |||
332 | adev.idev->name = "ST LIS3LV02DL Accelerometer"; | ||
333 | adev.idev->phys = DRIVER_NAME "/input0"; | ||
334 | adev.idev->id.bustype = BUS_HOST; | ||
335 | adev.idev->id.vendor = 0; | ||
336 | adev.idev->dev.parent = &adev.pdev->dev; | ||
337 | adev.idev->open = lis3lv02d_joystick_open; | ||
338 | adev.idev->close = lis3lv02d_joystick_close; | ||
339 | |||
340 | set_bit(EV_ABS, adev.idev->evbit); | ||
341 | input_set_abs_params(adev.idev, ABS_X, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3); | ||
342 | input_set_abs_params(adev.idev, ABS_Y, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3); | ||
343 | input_set_abs_params(adev.idev, ABS_Z, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3); | ||
344 | |||
345 | err = input_register_device(adev.idev); | ||
346 | if (err) { | ||
347 | input_free_device(adev.idev); | ||
348 | adev.idev = NULL; | ||
349 | } | ||
350 | |||
351 | return err; | ||
352 | } | ||
353 | |||
354 | static void lis3lv02d_joystick_disable(void) | ||
355 | { | ||
356 | if (!adev.idev) | ||
357 | return; | ||
358 | |||
359 | input_unregister_device(adev.idev); | ||
360 | adev.idev = NULL; | ||
361 | } | ||
362 | |||
363 | |||
364 | /* | ||
365 | * Initialise the accelerometer and the various subsystems. | ||
366 | * Should be rather independant of the bus system. | ||
367 | */ | ||
368 | static int lis3lv02d_init_device(struct acpi_lis3lv02d *dev) | ||
369 | { | ||
370 | mutex_init(&dev->lock); | ||
371 | lis3lv02d_add_fs(dev->device); | ||
372 | lis3lv02d_increase_use(dev); | ||
373 | |||
374 | if (lis3lv02d_joystick_enable()) | ||
375 | printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n"); | ||
376 | |||
377 | lis3lv02d_decrease_use(dev); | ||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi) | ||
382 | { | ||
383 | adev.ac = *((struct axis_conversion *)dmi->driver_data); | ||
384 | printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident); | ||
385 | |||
386 | return 1; | ||
387 | } | ||
388 | |||
389 | /* Represents, for each axis seen by userspace, the corresponding hw axis (+1). | ||
390 | * If the value is negative, the opposite of the hw value is used. */ | ||
391 | static struct axis_conversion lis3lv02d_axis_normal = {1, 2, 3}; | ||
392 | static struct axis_conversion lis3lv02d_axis_y_inverted = {1, -2, 3}; | ||
393 | static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3}; | ||
394 | static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3}; | ||
395 | static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3}; | ||
396 | static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3}; | ||
397 | |||
398 | #define AXIS_DMI_MATCH(_ident, _name, _axis) { \ | ||
399 | .ident = _ident, \ | ||
400 | .callback = lis3lv02d_dmi_matched, \ | ||
401 | .matches = { \ | ||
402 | DMI_MATCH(DMI_PRODUCT_NAME, _name) \ | ||
403 | }, \ | ||
404 | .driver_data = &lis3lv02d_axis_##_axis \ | ||
405 | } | ||
406 | static struct dmi_system_id lis3lv02d_dmi_ids[] = { | ||
407 | /* product names are truncated to match all kinds of a same model */ | ||
408 | AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted), | ||
409 | AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted), | ||
410 | AXIS_DMI_MATCH("NX9420", "HP Compaq nx9420", x_inverted), | ||
411 | AXIS_DMI_MATCH("NW9440", "HP Compaq nw9440", x_inverted), | ||
412 | AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted), | ||
413 | AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted), | ||
414 | AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left), | ||
415 | { NULL, } | ||
416 | /* Laptop models without axis info (yet): | ||
417 | * "NC651xx" "HP Compaq 651" | ||
418 | * "NC671xx" "HP Compaq 671" | ||
419 | * "NC6910" "HP Compaq 6910" | ||
420 | * HP Compaq 8710x Notebook PC / Mobile Workstation | ||
421 | * "NC2400" "HP Compaq nc2400" | ||
422 | * "NX74x0" "HP Compaq nx74" | ||
423 | * "NX6325" "HP Compaq nx6325" | ||
424 | * "NC4400" "HP Compaq nc4400" | ||
425 | */ | ||
426 | }; | ||
427 | |||
428 | static int lis3lv02d_add(struct acpi_device *device) | ||
429 | { | ||
430 | u8 val; | ||
431 | |||
432 | if (!device) | ||
433 | return -EINVAL; | ||
434 | |||
435 | adev.device = device; | ||
436 | strcpy(acpi_device_name(device), DRIVER_NAME); | ||
437 | strcpy(acpi_device_class(device), ACPI_MDPS_CLASS); | ||
438 | device->driver_data = &adev; | ||
439 | |||
440 | lis3lv02d_acpi_read(device->handle, WHO_AM_I, &val); | ||
441 | if ((val != LIS3LV02DL_ID) && (val != LIS302DL_ID)) { | ||
442 | printk(KERN_ERR DRIVER_NAME | ||
443 | ": Accelerometer chip not LIS3LV02D{L,Q}\n"); | ||
444 | } | ||
445 | |||
446 | /* If possible use a "standard" axes order */ | ||
447 | if (dmi_check_system(lis3lv02d_dmi_ids) == 0) { | ||
448 | printk(KERN_INFO DRIVER_NAME ": laptop model unknown, " | ||
449 | "using default axes configuration\n"); | ||
450 | adev.ac = lis3lv02d_axis_normal; | ||
451 | } | ||
452 | |||
453 | return lis3lv02d_init_device(&adev); | ||
454 | } | ||
455 | |||
456 | static int lis3lv02d_remove(struct acpi_device *device, int type) | ||
457 | { | ||
458 | if (!device) | ||
459 | return -EINVAL; | ||
460 | |||
461 | lis3lv02d_joystick_disable(); | ||
462 | lis3lv02d_poweroff(device->handle); | ||
463 | |||
464 | return lis3lv02d_remove_fs(); | ||
465 | } | ||
466 | |||
467 | |||
468 | /* Sysfs stuff */ | ||
469 | static ssize_t lis3lv02d_position_show(struct device *dev, | ||
470 | struct device_attribute *attr, char *buf) | ||
471 | { | ||
472 | int x, y, z; | ||
473 | |||
474 | lis3lv02d_increase_use(&adev); | ||
475 | lis3lv02d_get_xyz(adev.device->handle, &x, &y, &z); | ||
476 | lis3lv02d_decrease_use(&adev); | ||
477 | return sprintf(buf, "(%d,%d,%d)\n", x, y, z); | ||
478 | } | ||
479 | |||
480 | static ssize_t lis3lv02d_calibrate_show(struct device *dev, | ||
481 | struct device_attribute *attr, char *buf) | ||
482 | { | ||
483 | return sprintf(buf, "(%d,%d,%d)\n", adev.xcalib, adev.ycalib, adev.zcalib); | ||
484 | } | ||
485 | |||
486 | static ssize_t lis3lv02d_calibrate_store(struct device *dev, | ||
487 | struct device_attribute *attr, | ||
488 | const char *buf, size_t count) | ||
489 | { | ||
490 | lis3lv02d_increase_use(&adev); | ||
491 | lis3lv02d_calibrate_joystick(); | ||
492 | lis3lv02d_decrease_use(&adev); | ||
493 | return count; | ||
494 | } | ||
495 | |||
496 | /* conversion btw sampling rate and the register values */ | ||
497 | static int lis3lv02dl_df_val[4] = {40, 160, 640, 2560}; | ||
498 | static ssize_t lis3lv02d_rate_show(struct device *dev, | ||
499 | struct device_attribute *attr, char *buf) | ||
500 | { | ||
501 | u8 ctrl; | ||
502 | int val; | ||
503 | |||
504 | lis3lv02d_increase_use(&adev); | ||
505 | lis3lv02d_acpi_read(adev.device->handle, CTRL_REG1, &ctrl); | ||
506 | lis3lv02d_decrease_use(&adev); | ||
507 | val = (ctrl & (CTRL1_DF0 | CTRL1_DF1)) >> 4; | ||
508 | return sprintf(buf, "%d\n", lis3lv02dl_df_val[val]); | ||
509 | } | ||
510 | |||
511 | static DEVICE_ATTR(position, S_IRUGO, lis3lv02d_position_show, NULL); | ||
512 | static DEVICE_ATTR(calibrate, S_IRUGO|S_IWUSR, lis3lv02d_calibrate_show, | ||
513 | lis3lv02d_calibrate_store); | ||
514 | static DEVICE_ATTR(rate, S_IRUGO, lis3lv02d_rate_show, NULL); | ||
515 | |||
516 | static struct attribute *lis3lv02d_attributes[] = { | ||
517 | &dev_attr_position.attr, | ||
518 | &dev_attr_calibrate.attr, | ||
519 | &dev_attr_rate.attr, | ||
520 | NULL | ||
521 | }; | ||
522 | |||
523 | static struct attribute_group lis3lv02d_attribute_group = { | ||
524 | .attrs = lis3lv02d_attributes | ||
525 | }; | ||
526 | |||
527 | static int lis3lv02d_add_fs(struct acpi_device *device) | ||
528 | { | ||
529 | adev.pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); | ||
530 | if (IS_ERR(adev.pdev)) | ||
531 | return PTR_ERR(adev.pdev); | ||
532 | |||
533 | return sysfs_create_group(&adev.pdev->dev.kobj, &lis3lv02d_attribute_group); | ||
534 | } | ||
535 | |||
536 | static int lis3lv02d_remove_fs(void) | ||
537 | { | ||
538 | sysfs_remove_group(&adev.pdev->dev.kobj, &lis3lv02d_attribute_group); | ||
539 | platform_device_unregister(adev.pdev); | ||
540 | return 0; | ||
541 | } | ||
542 | |||
543 | /* For the HP MDPS aka 3D Driveguard */ | ||
544 | static struct acpi_driver lis3lv02d_driver = { | ||
545 | .name = DRIVER_NAME, | ||
546 | .class = ACPI_MDPS_CLASS, | ||
547 | .ids = lis3lv02d_device_ids, | ||
548 | .ops = { | ||
549 | .add = lis3lv02d_add, | ||
550 | .remove = lis3lv02d_remove, | ||
551 | .suspend = lis3lv02d_suspend, | ||
552 | .resume = lis3lv02d_resume, | ||
553 | } | ||
554 | }; | ||
555 | |||
556 | static int __init lis3lv02d_init_module(void) | ||
557 | { | ||
558 | int ret; | ||
559 | |||
560 | if (acpi_disabled) | ||
561 | return -ENODEV; | ||
562 | |||
563 | ret = acpi_bus_register_driver(&lis3lv02d_driver); | ||
564 | if (ret < 0) | ||
565 | return ret; | ||
566 | |||
567 | printk(KERN_INFO DRIVER_NAME " driver loaded.\n"); | ||
568 | |||
569 | return 0; | ||
570 | } | ||
571 | |||
572 | static void __exit lis3lv02d_exit_module(void) | ||
573 | { | ||
574 | acpi_bus_unregister_driver(&lis3lv02d_driver); | ||
575 | } | ||
576 | |||
577 | MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver"); | ||
578 | MODULE_AUTHOR("Yan Burman and Eric Piel"); | ||
579 | MODULE_LICENSE("GPL"); | ||
580 | |||
581 | module_init(lis3lv02d_init_module); | ||
582 | module_exit(lis3lv02d_exit_module); | ||
diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h new file mode 100644 index 000000000000..330cfc60e948 --- /dev/null +++ b/drivers/hwmon/lis3lv02d.h | |||
@@ -0,0 +1,149 @@ | |||
1 | /* | ||
2 | * lis3lv02d.h - ST LIS3LV02DL accelerometer driver | ||
3 | * | ||
4 | * Copyright (C) 2007-2008 Yan Burman | ||
5 | * Copyright (C) 2008 Eric Piel | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | /* | ||
23 | * The actual chip is STMicroelectronics LIS3LV02DL or LIS3LV02DQ that seems to | ||
24 | * be connected via SPI. There exists also several similar chips (such as LIS302DL or | ||
25 | * LIS3L02DQ) but not in the HP laptops and they have slightly different registers. | ||
26 | * They can also be connected via I²C. | ||
27 | */ | ||
28 | |||
29 | #define LIS3LV02DL_ID 0x3A /* Also the LIS3LV02DQ */ | ||
30 | #define LIS302DL_ID 0x3B /* Also the LIS202DL! */ | ||
31 | |||
32 | enum lis3lv02d_reg { | ||
33 | WHO_AM_I = 0x0F, | ||
34 | OFFSET_X = 0x16, | ||
35 | OFFSET_Y = 0x17, | ||
36 | OFFSET_Z = 0x18, | ||
37 | GAIN_X = 0x19, | ||
38 | GAIN_Y = 0x1A, | ||
39 | GAIN_Z = 0x1B, | ||
40 | CTRL_REG1 = 0x20, | ||
41 | CTRL_REG2 = 0x21, | ||
42 | CTRL_REG3 = 0x22, | ||
43 | HP_FILTER_RESET = 0x23, | ||
44 | STATUS_REG = 0x27, | ||
45 | OUTX_L = 0x28, | ||
46 | OUTX_H = 0x29, | ||
47 | OUTY_L = 0x2A, | ||
48 | OUTY_H = 0x2B, | ||
49 | OUTZ_L = 0x2C, | ||
50 | OUTZ_H = 0x2D, | ||
51 | FF_WU_CFG = 0x30, | ||
52 | FF_WU_SRC = 0x31, | ||
53 | FF_WU_ACK = 0x32, | ||
54 | FF_WU_THS_L = 0x34, | ||
55 | FF_WU_THS_H = 0x35, | ||
56 | FF_WU_DURATION = 0x36, | ||
57 | DD_CFG = 0x38, | ||
58 | DD_SRC = 0x39, | ||
59 | DD_ACK = 0x3A, | ||
60 | DD_THSI_L = 0x3C, | ||
61 | DD_THSI_H = 0x3D, | ||
62 | DD_THSE_L = 0x3E, | ||
63 | DD_THSE_H = 0x3F, | ||
64 | }; | ||
65 | |||
66 | enum lis3lv02d_ctrl1 { | ||
67 | CTRL1_Xen = 0x01, | ||
68 | CTRL1_Yen = 0x02, | ||
69 | CTRL1_Zen = 0x04, | ||
70 | CTRL1_ST = 0x08, | ||
71 | CTRL1_DF0 = 0x10, | ||
72 | CTRL1_DF1 = 0x20, | ||
73 | CTRL1_PD0 = 0x40, | ||
74 | CTRL1_PD1 = 0x80, | ||
75 | }; | ||
76 | enum lis3lv02d_ctrl2 { | ||
77 | CTRL2_DAS = 0x01, | ||
78 | CTRL2_SIM = 0x02, | ||
79 | CTRL2_DRDY = 0x04, | ||
80 | CTRL2_IEN = 0x08, | ||
81 | CTRL2_BOOT = 0x10, | ||
82 | CTRL2_BLE = 0x20, | ||
83 | CTRL2_BDU = 0x40, /* Block Data Update */ | ||
84 | CTRL2_FS = 0x80, /* Full Scale selection */ | ||
85 | }; | ||
86 | |||
87 | |||
88 | enum lis3lv02d_ctrl3 { | ||
89 | CTRL3_CFS0 = 0x01, | ||
90 | CTRL3_CFS1 = 0x02, | ||
91 | CTRL3_FDS = 0x10, | ||
92 | CTRL3_HPFF = 0x20, | ||
93 | CTRL3_HPDD = 0x40, | ||
94 | CTRL3_ECK = 0x80, | ||
95 | }; | ||
96 | |||
97 | enum lis3lv02d_status_reg { | ||
98 | STATUS_XDA = 0x01, | ||
99 | STATUS_YDA = 0x02, | ||
100 | STATUS_ZDA = 0x04, | ||
101 | STATUS_XYZDA = 0x08, | ||
102 | STATUS_XOR = 0x10, | ||
103 | STATUS_YOR = 0x20, | ||
104 | STATUS_ZOR = 0x40, | ||
105 | STATUS_XYZOR = 0x80, | ||
106 | }; | ||
107 | |||
108 | enum lis3lv02d_ff_wu_cfg { | ||
109 | FF_WU_CFG_XLIE = 0x01, | ||
110 | FF_WU_CFG_XHIE = 0x02, | ||
111 | FF_WU_CFG_YLIE = 0x04, | ||
112 | FF_WU_CFG_YHIE = 0x08, | ||
113 | FF_WU_CFG_ZLIE = 0x10, | ||
114 | FF_WU_CFG_ZHIE = 0x20, | ||
115 | FF_WU_CFG_LIR = 0x40, | ||
116 | FF_WU_CFG_AOI = 0x80, | ||
117 | }; | ||
118 | |||
119 | enum lis3lv02d_ff_wu_src { | ||
120 | FF_WU_SRC_XL = 0x01, | ||
121 | FF_WU_SRC_XH = 0x02, | ||
122 | FF_WU_SRC_YL = 0x04, | ||
123 | FF_WU_SRC_YH = 0x08, | ||
124 | FF_WU_SRC_ZL = 0x10, | ||
125 | FF_WU_SRC_ZH = 0x20, | ||
126 | FF_WU_SRC_IA = 0x40, | ||
127 | }; | ||
128 | |||
129 | enum lis3lv02d_dd_cfg { | ||
130 | DD_CFG_XLIE = 0x01, | ||
131 | DD_CFG_XHIE = 0x02, | ||
132 | DD_CFG_YLIE = 0x04, | ||
133 | DD_CFG_YHIE = 0x08, | ||
134 | DD_CFG_ZLIE = 0x10, | ||
135 | DD_CFG_ZHIE = 0x20, | ||
136 | DD_CFG_LIR = 0x40, | ||
137 | DD_CFG_IEND = 0x80, | ||
138 | }; | ||
139 | |||
140 | enum lis3lv02d_dd_src { | ||
141 | DD_SRC_XL = 0x01, | ||
142 | DD_SRC_XH = 0x02, | ||
143 | DD_SRC_YL = 0x04, | ||
144 | DD_SRC_YH = 0x08, | ||
145 | DD_SRC_ZL = 0x10, | ||
146 | DD_SRC_ZH = 0x20, | ||
147 | DD_SRC_IA = 0x40, | ||
148 | }; | ||
149 | |||
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 3ff0285396fa..cfc1ee90f5a3 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c | |||
@@ -39,7 +39,8 @@ | |||
39 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; | 39 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; |
40 | 40 | ||
41 | /* Insmod parameters */ | 41 | /* Insmod parameters */ |
42 | I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102); | 42 | I2C_CLIENT_INSMOD_7(lm85b, lm85c, adm1027, adt7463, adt7468, emc6d100, |
43 | emc6d102); | ||
43 | 44 | ||
44 | /* The LM85 registers */ | 45 | /* The LM85 registers */ |
45 | 46 | ||
@@ -59,6 +60,12 @@ I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102); | |||
59 | 60 | ||
60 | #define LM85_REG_COMPANY 0x3e | 61 | #define LM85_REG_COMPANY 0x3e |
61 | #define LM85_REG_VERSTEP 0x3f | 62 | #define LM85_REG_VERSTEP 0x3f |
63 | |||
64 | #define ADT7468_REG_CFG5 0x7c | ||
65 | #define ADT7468_OFF64 0x01 | ||
66 | #define IS_ADT7468_OFF64(data) \ | ||
67 | ((data)->type == adt7468 && !((data)->cfg5 & ADT7468_OFF64)) | ||
68 | |||
62 | /* These are the recognized values for the above regs */ | 69 | /* These are the recognized values for the above regs */ |
63 | #define LM85_COMPANY_NATIONAL 0x01 | 70 | #define LM85_COMPANY_NATIONAL 0x01 |
64 | #define LM85_COMPANY_ANALOG_DEV 0x41 | 71 | #define LM85_COMPANY_ANALOG_DEV 0x41 |
@@ -70,6 +77,8 @@ I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102); | |||
70 | #define LM85_VERSTEP_ADM1027 0x60 | 77 | #define LM85_VERSTEP_ADM1027 0x60 |
71 | #define LM85_VERSTEP_ADT7463 0x62 | 78 | #define LM85_VERSTEP_ADT7463 0x62 |
72 | #define LM85_VERSTEP_ADT7463C 0x6A | 79 | #define LM85_VERSTEP_ADT7463C 0x6A |
80 | #define LM85_VERSTEP_ADT7468_1 0x71 | ||
81 | #define LM85_VERSTEP_ADT7468_2 0x72 | ||
73 | #define LM85_VERSTEP_EMC6D100_A0 0x60 | 82 | #define LM85_VERSTEP_EMC6D100_A0 0x60 |
74 | #define LM85_VERSTEP_EMC6D100_A1 0x61 | 83 | #define LM85_VERSTEP_EMC6D100_A1 0x61 |
75 | #define LM85_VERSTEP_EMC6D102 0x65 | 84 | #define LM85_VERSTEP_EMC6D102 0x65 |
@@ -306,6 +315,7 @@ struct lm85_data { | |||
306 | u8 vid; /* Register value */ | 315 | u8 vid; /* Register value */ |
307 | u8 vrm; /* VRM version */ | 316 | u8 vrm; /* VRM version */ |
308 | u32 alarms; /* Register encoding, combined */ | 317 | u32 alarms; /* Register encoding, combined */ |
318 | u8 cfg5; /* Config Register 5 on ADT7468 */ | ||
309 | struct lm85_autofan autofan[3]; | 319 | struct lm85_autofan autofan[3]; |
310 | struct lm85_zone zone[3]; | 320 | struct lm85_zone zone[3]; |
311 | }; | 321 | }; |
@@ -685,6 +695,9 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, | |||
685 | struct lm85_data *data = i2c_get_clientdata(client); | 695 | struct lm85_data *data = i2c_get_clientdata(client); |
686 | long val = simple_strtol(buf, NULL, 10); | 696 | long val = simple_strtol(buf, NULL, 10); |
687 | 697 | ||
698 | if (IS_ADT7468_OFF64(data)) | ||
699 | val += 64; | ||
700 | |||
688 | mutex_lock(&data->update_lock); | 701 | mutex_lock(&data->update_lock); |
689 | data->temp_min[nr] = TEMP_TO_REG(val); | 702 | data->temp_min[nr] = TEMP_TO_REG(val); |
690 | lm85_write_value(client, LM85_REG_TEMP_MIN(nr), data->temp_min[nr]); | 703 | lm85_write_value(client, LM85_REG_TEMP_MIN(nr), data->temp_min[nr]); |
@@ -708,6 +721,9 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, | |||
708 | struct lm85_data *data = i2c_get_clientdata(client); | 721 | struct lm85_data *data = i2c_get_clientdata(client); |
709 | long val = simple_strtol(buf, NULL, 10); | 722 | long val = simple_strtol(buf, NULL, 10); |
710 | 723 | ||
724 | if (IS_ADT7468_OFF64(data)) | ||
725 | val += 64; | ||
726 | |||
711 | mutex_lock(&data->update_lock); | 727 | mutex_lock(&data->update_lock); |
712 | data->temp_max[nr] = TEMP_TO_REG(val); | 728 | data->temp_max[nr] = TEMP_TO_REG(val); |
713 | lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]); | 729 | lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]); |
@@ -1163,6 +1179,10 @@ static int lm85_detect(struct i2c_client *client, int kind, | |||
1163 | case LM85_VERSTEP_ADT7463C: | 1179 | case LM85_VERSTEP_ADT7463C: |
1164 | kind = adt7463; | 1180 | kind = adt7463; |
1165 | break; | 1181 | break; |
1182 | case LM85_VERSTEP_ADT7468_1: | ||
1183 | case LM85_VERSTEP_ADT7468_2: | ||
1184 | kind = adt7468; | ||
1185 | break; | ||
1166 | } | 1186 | } |
1167 | } else if (company == LM85_COMPANY_SMSC) { | 1187 | } else if (company == LM85_COMPANY_SMSC) { |
1168 | switch (verstep) { | 1188 | switch (verstep) { |
@@ -1195,6 +1215,9 @@ static int lm85_detect(struct i2c_client *client, int kind, | |||
1195 | case adt7463: | 1215 | case adt7463: |
1196 | type_name = "adt7463"; | 1216 | type_name = "adt7463"; |
1197 | break; | 1217 | break; |
1218 | case adt7468: | ||
1219 | type_name = "adt7468"; | ||
1220 | break; | ||
1198 | case emc6d100: | 1221 | case emc6d100: |
1199 | type_name = "emc6d100"; | 1222 | type_name = "emc6d100"; |
1200 | break; | 1223 | break; |
@@ -1246,10 +1269,11 @@ static int lm85_probe(struct i2c_client *client, | |||
1246 | if (err) | 1269 | if (err) |
1247 | goto err_kfree; | 1270 | goto err_kfree; |
1248 | 1271 | ||
1249 | /* The ADT7463 has an optional VRM 10 mode where pin 21 is used | 1272 | /* The ADT7463/68 have an optional VRM 10 mode where pin 21 is used |
1250 | as a sixth digital VID input rather than an analog input. */ | 1273 | as a sixth digital VID input rather than an analog input. */ |
1251 | data->vid = lm85_read_value(client, LM85_REG_VID); | 1274 | data->vid = lm85_read_value(client, LM85_REG_VID); |
1252 | if (!(data->type == adt7463 && (data->vid & 0x80))) | 1275 | if (!((data->type == adt7463 || data->type == adt7468) && |
1276 | (data->vid & 0x80))) | ||
1253 | if ((err = sysfs_create_group(&client->dev.kobj, | 1277 | if ((err = sysfs_create_group(&client->dev.kobj, |
1254 | &lm85_group_in4))) | 1278 | &lm85_group_in4))) |
1255 | goto err_remove_files; | 1279 | goto err_remove_files; |
@@ -1357,7 +1381,8 @@ static struct lm85_data *lm85_update_device(struct device *dev) | |||
1357 | * There are 2 additional resolution bits per channel and we | 1381 | * There are 2 additional resolution bits per channel and we |
1358 | * have room for 4, so we shift them to the left. | 1382 | * have room for 4, so we shift them to the left. |
1359 | */ | 1383 | */ |
1360 | if (data->type == adm1027 || data->type == adt7463) { | 1384 | if (data->type == adm1027 || data->type == adt7463 || |
1385 | data->type == adt7468) { | ||
1361 | int ext1 = lm85_read_value(client, | 1386 | int ext1 = lm85_read_value(client, |
1362 | ADM1027_REG_EXTEND_ADC1); | 1387 | ADM1027_REG_EXTEND_ADC1); |
1363 | int ext2 = lm85_read_value(client, | 1388 | int ext2 = lm85_read_value(client, |
@@ -1382,16 +1407,23 @@ static struct lm85_data *lm85_update_device(struct device *dev) | |||
1382 | lm85_read_value(client, LM85_REG_FAN(i)); | 1407 | lm85_read_value(client, LM85_REG_FAN(i)); |
1383 | } | 1408 | } |
1384 | 1409 | ||
1385 | if (!(data->type == adt7463 && (data->vid & 0x80))) { | 1410 | if (!((data->type == adt7463 || data->type == adt7468) && |
1411 | (data->vid & 0x80))) { | ||
1386 | data->in[4] = lm85_read_value(client, | 1412 | data->in[4] = lm85_read_value(client, |
1387 | LM85_REG_IN(4)); | 1413 | LM85_REG_IN(4)); |
1388 | } | 1414 | } |
1389 | 1415 | ||
1416 | if (data->type == adt7468) | ||
1417 | data->cfg5 = lm85_read_value(client, ADT7468_REG_CFG5); | ||
1418 | |||
1390 | for (i = 0; i <= 2; ++i) { | 1419 | for (i = 0; i <= 2; ++i) { |
1391 | data->temp[i] = | 1420 | data->temp[i] = |
1392 | lm85_read_value(client, LM85_REG_TEMP(i)); | 1421 | lm85_read_value(client, LM85_REG_TEMP(i)); |
1393 | data->pwm[i] = | 1422 | data->pwm[i] = |
1394 | lm85_read_value(client, LM85_REG_PWM(i)); | 1423 | lm85_read_value(client, LM85_REG_PWM(i)); |
1424 | |||
1425 | if (IS_ADT7468_OFF64(data)) | ||
1426 | data->temp[i] -= 64; | ||
1395 | } | 1427 | } |
1396 | 1428 | ||
1397 | data->alarms = lm85_read_value(client, LM85_REG_ALARM1); | 1429 | data->alarms = lm85_read_value(client, LM85_REG_ALARM1); |
@@ -1446,7 +1478,8 @@ static struct lm85_data *lm85_update_device(struct device *dev) | |||
1446 | lm85_read_value(client, LM85_REG_FAN_MIN(i)); | 1478 | lm85_read_value(client, LM85_REG_FAN_MIN(i)); |
1447 | } | 1479 | } |
1448 | 1480 | ||
1449 | if (!(data->type == adt7463 && (data->vid & 0x80))) { | 1481 | if (!((data->type == adt7463 || data->type == adt7468) && |
1482 | (data->vid & 0x80))) { | ||
1450 | data->in_min[4] = lm85_read_value(client, | 1483 | data->in_min[4] = lm85_read_value(client, |
1451 | LM85_REG_IN_MIN(4)); | 1484 | LM85_REG_IN_MIN(4)); |
1452 | data->in_max[4] = lm85_read_value(client, | 1485 | data->in_max[4] = lm85_read_value(client, |
@@ -1481,6 +1514,13 @@ static struct lm85_data *lm85_update_device(struct device *dev) | |||
1481 | lm85_read_value(client, LM85_REG_AFAN_LIMIT(i)); | 1514 | lm85_read_value(client, LM85_REG_AFAN_LIMIT(i)); |
1482 | data->zone[i].critical = | 1515 | data->zone[i].critical = |
1483 | lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i)); | 1516 | lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i)); |
1517 | |||
1518 | if (IS_ADT7468_OFF64(data)) { | ||
1519 | data->temp_min[i] -= 64; | ||
1520 | data->temp_max[i] -= 64; | ||
1521 | data->zone[i].limit -= 64; | ||
1522 | data->zone[i].critical -= 64; | ||
1523 | } | ||
1484 | } | 1524 | } |
1485 | 1525 | ||
1486 | i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1); | 1526 | i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1); |
diff --git a/drivers/idle/Kconfig b/drivers/idle/Kconfig index 108264de0ac9..f15e90a453d1 100644 --- a/drivers/idle/Kconfig +++ b/drivers/idle/Kconfig | |||
@@ -1,5 +1,6 @@ | |||
1 | 1 | ||
2 | menu "Memory power savings" | 2 | menu "Memory power savings" |
3 | depends on X86_64 | ||
3 | 4 | ||
4 | config I7300_IDLE_IOAT_CHANNEL | 5 | config I7300_IDLE_IOAT_CHANNEL |
5 | bool | 6 | bool |
@@ -7,7 +8,7 @@ config I7300_IDLE_IOAT_CHANNEL | |||
7 | config I7300_IDLE | 8 | config I7300_IDLE |
8 | tristate "Intel chipset idle memory power saving driver" | 9 | tristate "Intel chipset idle memory power saving driver" |
9 | select I7300_IDLE_IOAT_CHANNEL | 10 | select I7300_IDLE_IOAT_CHANNEL |
10 | depends on X86_64 && EXPERIMENTAL | 11 | depends on EXPERIMENTAL |
11 | help | 12 | help |
12 | Enable memory power savings when idle with certain Intel server | 13 | Enable memory power savings when idle with certain Intel server |
13 | chipsets. The chipset must have I/O AT support, such as the | 14 | chipsets. The chipset must have I/O AT support, such as the |
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c index ecff98043589..160ef482712d 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_provider.c +++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c | |||
@@ -1102,9 +1102,7 @@ static u64 fw_vers_string_to_u64(struct iwch_dev *iwch_dev) | |||
1102 | char *cp, *next; | 1102 | char *cp, *next; |
1103 | unsigned fw_maj, fw_min, fw_mic; | 1103 | unsigned fw_maj, fw_min, fw_mic; |
1104 | 1104 | ||
1105 | rtnl_lock(); | ||
1106 | lldev->ethtool_ops->get_drvinfo(lldev, &info); | 1105 | lldev->ethtool_ops->get_drvinfo(lldev, &info); |
1107 | rtnl_unlock(); | ||
1108 | 1106 | ||
1109 | next = info.fw_version + 1; | 1107 | next = info.fw_version + 1; |
1110 | cp = strsep(&next, "."); | 1108 | cp = strsep(&next, "."); |
@@ -1192,9 +1190,7 @@ static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr, ch | |||
1192 | struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev; | 1190 | struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev; |
1193 | 1191 | ||
1194 | PDBG("%s dev 0x%p\n", __func__, dev); | 1192 | PDBG("%s dev 0x%p\n", __func__, dev); |
1195 | rtnl_lock(); | ||
1196 | lldev->ethtool_ops->get_drvinfo(lldev, &info); | 1193 | lldev->ethtool_ops->get_drvinfo(lldev, &info); |
1197 | rtnl_unlock(); | ||
1198 | return sprintf(buf, "%s\n", info.fw_version); | 1194 | return sprintf(buf, "%s\n", info.fw_version); |
1199 | } | 1195 | } |
1200 | 1196 | ||
@@ -1207,9 +1203,7 @@ static ssize_t show_hca(struct device *dev, struct device_attribute *attr, | |||
1207 | struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev; | 1203 | struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev; |
1208 | 1204 | ||
1209 | PDBG("%s dev 0x%p\n", __func__, dev); | 1205 | PDBG("%s dev 0x%p\n", __func__, dev); |
1210 | rtnl_lock(); | ||
1211 | lldev->ethtool_ops->get_drvinfo(lldev, &info); | 1206 | lldev->ethtool_ops->get_drvinfo(lldev, &info); |
1212 | rtnl_unlock(); | ||
1213 | return sprintf(buf, "%s\n", info.driver); | 1207 | return sprintf(buf, "%s\n", info.driver); |
1214 | } | 1208 | } |
1215 | 1209 | ||
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c index 3e4585c2318a..19661b2f0406 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_qp.c +++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c | |||
@@ -745,7 +745,6 @@ int iwch_post_zb_read(struct iwch_qp *qhp) | |||
745 | wqe->read.rdmaop = T3_READ_REQ; | 745 | wqe->read.rdmaop = T3_READ_REQ; |
746 | wqe->read.reserved[0] = 0; | 746 | wqe->read.reserved[0] = 0; |
747 | wqe->read.reserved[1] = 0; | 747 | wqe->read.reserved[1] = 0; |
748 | wqe->read.reserved[2] = 0; | ||
749 | wqe->read.rem_stag = cpu_to_be32(1); | 748 | wqe->read.rem_stag = cpu_to_be32(1); |
750 | wqe->read.rem_to = cpu_to_be64(1); | 749 | wqe->read.rem_to = cpu_to_be64(1); |
751 | wqe->read.local_stag = cpu_to_be32(1); | 750 | wqe->read.local_stag = cpu_to_be32(1); |
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c index cb55be04442c..757035ea246f 100644 --- a/drivers/infiniband/hw/ehca/ehca_irq.c +++ b/drivers/infiniband/hw/ehca/ehca_irq.c | |||
@@ -359,36 +359,48 @@ static void notify_port_conf_change(struct ehca_shca *shca, int port_num) | |||
359 | *old_attr = new_attr; | 359 | *old_attr = new_attr; |
360 | } | 360 | } |
361 | 361 | ||
362 | /* replay modify_qp for sqps -- return 0 if all is well, 1 if AQP1 destroyed */ | ||
363 | static int replay_modify_qp(struct ehca_sport *sport) | ||
364 | { | ||
365 | int aqp1_destroyed; | ||
366 | unsigned long flags; | ||
367 | |||
368 | spin_lock_irqsave(&sport->mod_sqp_lock, flags); | ||
369 | |||
370 | aqp1_destroyed = !sport->ibqp_sqp[IB_QPT_GSI]; | ||
371 | |||
372 | if (sport->ibqp_sqp[IB_QPT_SMI]) | ||
373 | ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]); | ||
374 | if (!aqp1_destroyed) | ||
375 | ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]); | ||
376 | |||
377 | spin_unlock_irqrestore(&sport->mod_sqp_lock, flags); | ||
378 | |||
379 | return aqp1_destroyed; | ||
380 | } | ||
381 | |||
362 | static void parse_ec(struct ehca_shca *shca, u64 eqe) | 382 | static void parse_ec(struct ehca_shca *shca, u64 eqe) |
363 | { | 383 | { |
364 | u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe); | 384 | u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe); |
365 | u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe); | 385 | u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe); |
366 | u8 spec_event; | 386 | u8 spec_event; |
367 | struct ehca_sport *sport = &shca->sport[port - 1]; | 387 | struct ehca_sport *sport = &shca->sport[port - 1]; |
368 | unsigned long flags; | ||
369 | 388 | ||
370 | switch (ec) { | 389 | switch (ec) { |
371 | case 0x30: /* port availability change */ | 390 | case 0x30: /* port availability change */ |
372 | if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) { | 391 | if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) { |
373 | int suppress_event; | 392 | /* only replay modify_qp calls in autodetect mode; |
374 | /* replay modify_qp for sqps */ | 393 | * if AQP1 was destroyed, the port is already down |
375 | spin_lock_irqsave(&sport->mod_sqp_lock, flags); | 394 | * again and we can drop the event. |
376 | suppress_event = !sport->ibqp_sqp[IB_QPT_GSI]; | 395 | */ |
377 | if (sport->ibqp_sqp[IB_QPT_SMI]) | 396 | if (ehca_nr_ports < 0) |
378 | ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]); | 397 | if (replay_modify_qp(sport)) |
379 | if (!suppress_event) | 398 | break; |
380 | ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]); | ||
381 | spin_unlock_irqrestore(&sport->mod_sqp_lock, flags); | ||
382 | |||
383 | /* AQP1 was destroyed, ignore this event */ | ||
384 | if (suppress_event) | ||
385 | break; | ||
386 | 399 | ||
387 | sport->port_state = IB_PORT_ACTIVE; | 400 | sport->port_state = IB_PORT_ACTIVE; |
388 | dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE, | 401 | dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE, |
389 | "is active"); | 402 | "is active"); |
390 | ehca_query_sma_attr(shca, port, | 403 | ehca_query_sma_attr(shca, port, &sport->saved_attr); |
391 | &sport->saved_attr); | ||
392 | } else { | 404 | } else { |
393 | sport->port_state = IB_PORT_DOWN; | 405 | sport->port_state = IB_PORT_DOWN; |
394 | dispatch_port_event(shca, port, IB_EVENT_PORT_ERR, | 406 | dispatch_port_event(shca, port, IB_EVENT_PORT_ERR, |
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c index 4d54b9f64567..9e05ee2db39b 100644 --- a/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/drivers/infiniband/hw/ehca/ehca_qp.c | |||
@@ -860,6 +860,11 @@ static struct ehca_qp *internal_create_qp( | |||
860 | if (qp_type == IB_QPT_GSI) { | 860 | if (qp_type == IB_QPT_GSI) { |
861 | h_ret = ehca_define_sqp(shca, my_qp, init_attr); | 861 | h_ret = ehca_define_sqp(shca, my_qp, init_attr); |
862 | if (h_ret != H_SUCCESS) { | 862 | if (h_ret != H_SUCCESS) { |
863 | kfree(my_qp->mod_qp_parm); | ||
864 | my_qp->mod_qp_parm = NULL; | ||
865 | /* the QP pointer is no longer valid */ | ||
866 | shca->sport[init_attr->port_num - 1].ibqp_sqp[qp_type] = | ||
867 | NULL; | ||
863 | ret = ehca2ib_return_code(h_ret); | 868 | ret = ehca2ib_return_code(h_ret); |
864 | goto create_qp_exit6; | 869 | goto create_qp_exit6; |
865 | } | 870 | } |
diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c index fc0f6d9e6030..2296832f94da 100644 --- a/drivers/infiniband/hw/ipath/ipath_ruc.c +++ b/drivers/infiniband/hw/ipath/ipath_ruc.c | |||
@@ -156,7 +156,7 @@ bail: | |||
156 | /** | 156 | /** |
157 | * ipath_get_rwqe - copy the next RWQE into the QP's RWQE | 157 | * ipath_get_rwqe - copy the next RWQE into the QP's RWQE |
158 | * @qp: the QP | 158 | * @qp: the QP |
159 | * @wr_id_only: update wr_id only, not SGEs | 159 | * @wr_id_only: update qp->r_wr_id only, not qp->r_sge |
160 | * | 160 | * |
161 | * Return 0 if no RWQE is available, otherwise return 1. | 161 | * Return 0 if no RWQE is available, otherwise return 1. |
162 | * | 162 | * |
@@ -173,8 +173,6 @@ int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only) | |||
173 | u32 tail; | 173 | u32 tail; |
174 | int ret; | 174 | int ret; |
175 | 175 | ||
176 | qp->r_sge.sg_list = qp->r_sg_list; | ||
177 | |||
178 | if (qp->ibqp.srq) { | 176 | if (qp->ibqp.srq) { |
179 | srq = to_isrq(qp->ibqp.srq); | 177 | srq = to_isrq(qp->ibqp.srq); |
180 | handler = srq->ibsrq.event_handler; | 178 | handler = srq->ibsrq.event_handler; |
@@ -206,8 +204,10 @@ int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only) | |||
206 | wqe = get_rwqe_ptr(rq, tail); | 204 | wqe = get_rwqe_ptr(rq, tail); |
207 | if (++tail >= rq->size) | 205 | if (++tail >= rq->size) |
208 | tail = 0; | 206 | tail = 0; |
209 | } while (!wr_id_only && !ipath_init_sge(qp, wqe, &qp->r_len, | 207 | if (wr_id_only) |
210 | &qp->r_sge)); | 208 | break; |
209 | qp->r_sge.sg_list = qp->r_sg_list; | ||
210 | } while (!ipath_init_sge(qp, wqe, &qp->r_len, &qp->r_sge)); | ||
211 | qp->r_wr_id = wqe->wr_id; | 211 | qp->r_wr_id = wqe->wr_id; |
212 | wq->tail = tail; | 212 | wq->tail = tail; |
213 | 213 | ||
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c index 87f5c5a87b98..8e4d26d56a95 100644 --- a/drivers/infiniband/hw/mlx4/mr.c +++ b/drivers/infiniband/hw/mlx4/mr.c | |||
@@ -205,6 +205,7 @@ struct ib_mr *mlx4_ib_alloc_fast_reg_mr(struct ib_pd *pd, | |||
205 | goto err_mr; | 205 | goto err_mr; |
206 | 206 | ||
207 | mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key; | 207 | mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key; |
208 | mr->umem = NULL; | ||
208 | 209 | ||
209 | return &mr->ibmr; | 210 | return &mr->ibmr; |
210 | 211 | ||
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c index a2b04d62b1a4..aa1dc41f04c8 100644 --- a/drivers/infiniband/hw/nes/nes.c +++ b/drivers/infiniband/hw/nes/nes.c | |||
@@ -95,6 +95,10 @@ unsigned int wqm_quanta = 0x10000; | |||
95 | module_param(wqm_quanta, int, 0644); | 95 | module_param(wqm_quanta, int, 0644); |
96 | MODULE_PARM_DESC(wqm_quanta, "WQM quanta"); | 96 | MODULE_PARM_DESC(wqm_quanta, "WQM quanta"); |
97 | 97 | ||
98 | static unsigned int limit_maxrdreqsz; | ||
99 | module_param(limit_maxrdreqsz, bool, 0644); | ||
100 | MODULE_PARM_DESC(limit_maxrdreqsz, "Limit max read request size to 256 Bytes"); | ||
101 | |||
98 | LIST_HEAD(nes_adapter_list); | 102 | LIST_HEAD(nes_adapter_list); |
99 | static LIST_HEAD(nes_dev_list); | 103 | static LIST_HEAD(nes_dev_list); |
100 | 104 | ||
@@ -588,6 +592,18 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i | |||
588 | nesdev->nesadapter->port_count; | 592 | nesdev->nesadapter->port_count; |
589 | } | 593 | } |
590 | 594 | ||
595 | if ((limit_maxrdreqsz || | ||
596 | ((nesdev->nesadapter->phy_type[0] == NES_PHY_TYPE_GLADIUS) && | ||
597 | (hw_rev == NE020_REV1))) && | ||
598 | (pcie_get_readrq(pcidev) > 256)) { | ||
599 | if (pcie_set_readrq(pcidev, 256)) | ||
600 | printk(KERN_ERR PFX "Unable to set max read request" | ||
601 | " to 256 bytes\n"); | ||
602 | else | ||
603 | nes_debug(NES_DBG_INIT, "Max read request size set" | ||
604 | " to 256 bytes\n"); | ||
605 | } | ||
606 | |||
591 | tasklet_init(&nesdev->dpc_tasklet, nes_dpc, (unsigned long)nesdev); | 607 | tasklet_init(&nesdev->dpc_tasklet, nes_dpc, (unsigned long)nesdev); |
592 | 608 | ||
593 | /* bring up the Control QP */ | 609 | /* bring up the Control QP */ |
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h index 610b9d859597..bc0b4de04450 100644 --- a/drivers/infiniband/hw/nes/nes_hw.h +++ b/drivers/infiniband/hw/nes/nes_hw.h | |||
@@ -40,6 +40,7 @@ | |||
40 | #define NES_PHY_TYPE_ARGUS 4 | 40 | #define NES_PHY_TYPE_ARGUS 4 |
41 | #define NES_PHY_TYPE_PUMA_1G 5 | 41 | #define NES_PHY_TYPE_PUMA_1G 5 |
42 | #define NES_PHY_TYPE_PUMA_10G 6 | 42 | #define NES_PHY_TYPE_PUMA_10G 6 |
43 | #define NES_PHY_TYPE_GLADIUS 7 | ||
43 | 44 | ||
44 | #define NES_MULTICAST_PF_MAX 8 | 45 | #define NES_MULTICAST_PF_MAX 8 |
45 | 46 | ||
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 932e56fcf774..d36c9a0bf1bb 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c | |||
@@ -220,14 +220,14 @@ static int nes_bind_mw(struct ib_qp *ibqp, struct ib_mw *ibmw, | |||
220 | if (nesqp->ibqp_state > IB_QPS_RTS) | 220 | if (nesqp->ibqp_state > IB_QPS_RTS) |
221 | return -EINVAL; | 221 | return -EINVAL; |
222 | 222 | ||
223 | spin_lock_irqsave(&nesqp->lock, flags); | 223 | spin_lock_irqsave(&nesqp->lock, flags); |
224 | 224 | ||
225 | head = nesqp->hwqp.sq_head; | 225 | head = nesqp->hwqp.sq_head; |
226 | qsize = nesqp->hwqp.sq_tail; | 226 | qsize = nesqp->hwqp.sq_tail; |
227 | 227 | ||
228 | /* Check for SQ overflow */ | 228 | /* Check for SQ overflow */ |
229 | if (((head + (2 * qsize) - nesqp->hwqp.sq_tail) % qsize) == (qsize - 1)) { | 229 | if (((head + (2 * qsize) - nesqp->hwqp.sq_tail) % qsize) == (qsize - 1)) { |
230 | spin_unlock_irqrestore(&nesqp->lock, flags); | 230 | spin_unlock_irqrestore(&nesqp->lock, flags); |
231 | return -EINVAL; | 231 | return -EINVAL; |
232 | } | 232 | } |
233 | 233 | ||
@@ -269,7 +269,7 @@ static int nes_bind_mw(struct ib_qp *ibqp, struct ib_mw *ibmw, | |||
269 | nes_write32(nesdev->regs+NES_WQE_ALLOC, | 269 | nes_write32(nesdev->regs+NES_WQE_ALLOC, |
270 | (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id); | 270 | (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id); |
271 | 271 | ||
272 | spin_unlock_irqrestore(&nesqp->lock, flags); | 272 | spin_unlock_irqrestore(&nesqp->lock, flags); |
273 | 273 | ||
274 | return 0; | 274 | return 0; |
275 | } | 275 | } |
@@ -349,7 +349,7 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, | |||
349 | if (nesfmr->nesmr.pbls_used > nesadapter->free_4kpbl) { | 349 | if (nesfmr->nesmr.pbls_used > nesadapter->free_4kpbl) { |
350 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | 350 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); |
351 | ret = -ENOMEM; | 351 | ret = -ENOMEM; |
352 | goto failed_vpbl_alloc; | 352 | goto failed_vpbl_avail; |
353 | } else { | 353 | } else { |
354 | nesadapter->free_4kpbl -= nesfmr->nesmr.pbls_used; | 354 | nesadapter->free_4kpbl -= nesfmr->nesmr.pbls_used; |
355 | } | 355 | } |
@@ -357,7 +357,7 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, | |||
357 | if (nesfmr->nesmr.pbls_used > nesadapter->free_256pbl) { | 357 | if (nesfmr->nesmr.pbls_used > nesadapter->free_256pbl) { |
358 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | 358 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); |
359 | ret = -ENOMEM; | 359 | ret = -ENOMEM; |
360 | goto failed_vpbl_alloc; | 360 | goto failed_vpbl_avail; |
361 | } else { | 361 | } else { |
362 | nesadapter->free_256pbl -= nesfmr->nesmr.pbls_used; | 362 | nesadapter->free_256pbl -= nesfmr->nesmr.pbls_used; |
363 | } | 363 | } |
@@ -391,14 +391,14 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, | |||
391 | goto failed_vpbl_alloc; | 391 | goto failed_vpbl_alloc; |
392 | } | 392 | } |
393 | 393 | ||
394 | nesfmr->root_vpbl.leaf_vpbl = kzalloc(sizeof(*nesfmr->root_vpbl.leaf_vpbl)*1024, GFP_KERNEL); | 394 | nesfmr->leaf_pbl_cnt = nesfmr->nesmr.pbls_used-1; |
395 | nesfmr->root_vpbl.leaf_vpbl = kzalloc(sizeof(*nesfmr->root_vpbl.leaf_vpbl)*1024, GFP_ATOMIC); | ||
395 | if (!nesfmr->root_vpbl.leaf_vpbl) { | 396 | if (!nesfmr->root_vpbl.leaf_vpbl) { |
396 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | 397 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); |
397 | ret = -ENOMEM; | 398 | ret = -ENOMEM; |
398 | goto failed_leaf_vpbl_alloc; | 399 | goto failed_leaf_vpbl_alloc; |
399 | } | 400 | } |
400 | 401 | ||
401 | nesfmr->leaf_pbl_cnt = nesfmr->nesmr.pbls_used-1; | ||
402 | nes_debug(NES_DBG_MR, "two level pbl, root_vpbl.pbl_vbase=%p" | 402 | nes_debug(NES_DBG_MR, "two level pbl, root_vpbl.pbl_vbase=%p" |
403 | " leaf_pbl_cnt=%d root_vpbl.leaf_vpbl=%p\n", | 403 | " leaf_pbl_cnt=%d root_vpbl.leaf_vpbl=%p\n", |
404 | nesfmr->root_vpbl.pbl_vbase, nesfmr->leaf_pbl_cnt, nesfmr->root_vpbl.leaf_vpbl); | 404 | nesfmr->root_vpbl.pbl_vbase, nesfmr->leaf_pbl_cnt, nesfmr->root_vpbl.leaf_vpbl); |
@@ -519,6 +519,16 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, | |||
519 | nesfmr->root_vpbl.pbl_pbase); | 519 | nesfmr->root_vpbl.pbl_pbase); |
520 | 520 | ||
521 | failed_vpbl_alloc: | 521 | failed_vpbl_alloc: |
522 | if (nesfmr->nesmr.pbls_used != 0) { | ||
523 | spin_lock_irqsave(&nesadapter->pbl_lock, flags); | ||
524 | if (nesfmr->nesmr.pbl_4k) | ||
525 | nesadapter->free_4kpbl += nesfmr->nesmr.pbls_used; | ||
526 | else | ||
527 | nesadapter->free_256pbl += nesfmr->nesmr.pbls_used; | ||
528 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | ||
529 | } | ||
530 | |||
531 | failed_vpbl_avail: | ||
522 | kfree(nesfmr); | 532 | kfree(nesfmr); |
523 | 533 | ||
524 | failed_fmr_alloc: | 534 | failed_fmr_alloc: |
@@ -534,18 +544,14 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, | |||
534 | */ | 544 | */ |
535 | static int nes_dealloc_fmr(struct ib_fmr *ibfmr) | 545 | static int nes_dealloc_fmr(struct ib_fmr *ibfmr) |
536 | { | 546 | { |
547 | unsigned long flags; | ||
537 | struct nes_mr *nesmr = to_nesmr_from_ibfmr(ibfmr); | 548 | struct nes_mr *nesmr = to_nesmr_from_ibfmr(ibfmr); |
538 | struct nes_fmr *nesfmr = to_nesfmr(nesmr); | 549 | struct nes_fmr *nesfmr = to_nesfmr(nesmr); |
539 | struct nes_vnic *nesvnic = to_nesvnic(ibfmr->device); | 550 | struct nes_vnic *nesvnic = to_nesvnic(ibfmr->device); |
540 | struct nes_device *nesdev = nesvnic->nesdev; | 551 | struct nes_device *nesdev = nesvnic->nesdev; |
541 | struct nes_mr temp_nesmr = *nesmr; | 552 | struct nes_adapter *nesadapter = nesdev->nesadapter; |
542 | int i = 0; | 553 | int i = 0; |
543 | 554 | ||
544 | temp_nesmr.ibmw.device = ibfmr->device; | ||
545 | temp_nesmr.ibmw.pd = ibfmr->pd; | ||
546 | temp_nesmr.ibmw.rkey = ibfmr->rkey; | ||
547 | temp_nesmr.ibmw.uobject = NULL; | ||
548 | |||
549 | /* free the resources */ | 555 | /* free the resources */ |
550 | if (nesfmr->leaf_pbl_cnt == 0) { | 556 | if (nesfmr->leaf_pbl_cnt == 0) { |
551 | /* single PBL case */ | 557 | /* single PBL case */ |
@@ -561,8 +567,24 @@ static int nes_dealloc_fmr(struct ib_fmr *ibfmr) | |||
561 | pci_free_consistent(nesdev->pcidev, 8192, nesfmr->root_vpbl.pbl_vbase, | 567 | pci_free_consistent(nesdev->pcidev, 8192, nesfmr->root_vpbl.pbl_vbase, |
562 | nesfmr->root_vpbl.pbl_pbase); | 568 | nesfmr->root_vpbl.pbl_pbase); |
563 | } | 569 | } |
570 | nesmr->ibmw.device = ibfmr->device; | ||
571 | nesmr->ibmw.pd = ibfmr->pd; | ||
572 | nesmr->ibmw.rkey = ibfmr->rkey; | ||
573 | nesmr->ibmw.uobject = NULL; | ||
564 | 574 | ||
565 | return nes_dealloc_mw(&temp_nesmr.ibmw); | 575 | if (nesfmr->nesmr.pbls_used != 0) { |
576 | spin_lock_irqsave(&nesadapter->pbl_lock, flags); | ||
577 | if (nesfmr->nesmr.pbl_4k) { | ||
578 | nesadapter->free_4kpbl += nesfmr->nesmr.pbls_used; | ||
579 | WARN_ON(nesadapter->free_4kpbl > nesadapter->max_4kpbl); | ||
580 | } else { | ||
581 | nesadapter->free_256pbl += nesfmr->nesmr.pbls_used; | ||
582 | WARN_ON(nesadapter->free_256pbl > nesadapter->max_256pbl); | ||
583 | } | ||
584 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | ||
585 | } | ||
586 | |||
587 | return nes_dealloc_mw(&nesmr->ibmw); | ||
566 | } | 588 | } |
567 | 589 | ||
568 | 590 | ||
@@ -1595,7 +1617,7 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries, | |||
1595 | nes_ucontext->mcrqf = req.mcrqf; | 1617 | nes_ucontext->mcrqf = req.mcrqf; |
1596 | if (nes_ucontext->mcrqf) { | 1618 | if (nes_ucontext->mcrqf) { |
1597 | if (nes_ucontext->mcrqf & 0x80000000) | 1619 | if (nes_ucontext->mcrqf & 0x80000000) |
1598 | nescq->hw_cq.cq_number = nesvnic->nic.qp_id + 12 + (nes_ucontext->mcrqf & 0xf) - 1; | 1620 | nescq->hw_cq.cq_number = nesvnic->nic.qp_id + 28 + 2 * ((nes_ucontext->mcrqf & 0xf) - 1); |
1599 | else if (nes_ucontext->mcrqf & 0x40000000) | 1621 | else if (nes_ucontext->mcrqf & 0x40000000) |
1600 | nescq->hw_cq.cq_number = nes_ucontext->mcrqf & 0xffff; | 1622 | nescq->hw_cq.cq_number = nes_ucontext->mcrqf & 0xffff; |
1601 | else | 1623 | else |
@@ -3212,7 +3234,7 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, | |||
3212 | if (nesqp->ibqp_state > IB_QPS_RTS) | 3234 | if (nesqp->ibqp_state > IB_QPS_RTS) |
3213 | return -EINVAL; | 3235 | return -EINVAL; |
3214 | 3236 | ||
3215 | spin_lock_irqsave(&nesqp->lock, flags); | 3237 | spin_lock_irqsave(&nesqp->lock, flags); |
3216 | 3238 | ||
3217 | head = nesqp->hwqp.sq_head; | 3239 | head = nesqp->hwqp.sq_head; |
3218 | 3240 | ||
@@ -3337,7 +3359,7 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, | |||
3337 | (counter << 24) | 0x00800000 | nesqp->hwqp.qp_id); | 3359 | (counter << 24) | 0x00800000 | nesqp->hwqp.qp_id); |
3338 | } | 3360 | } |
3339 | 3361 | ||
3340 | spin_unlock_irqrestore(&nesqp->lock, flags); | 3362 | spin_unlock_irqrestore(&nesqp->lock, flags); |
3341 | 3363 | ||
3342 | if (err) | 3364 | if (err) |
3343 | *bad_wr = ib_wr; | 3365 | *bad_wr = ib_wr; |
@@ -3368,7 +3390,7 @@ static int nes_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr, | |||
3368 | if (nesqp->ibqp_state > IB_QPS_RTS) | 3390 | if (nesqp->ibqp_state > IB_QPS_RTS) |
3369 | return -EINVAL; | 3391 | return -EINVAL; |
3370 | 3392 | ||
3371 | spin_lock_irqsave(&nesqp->lock, flags); | 3393 | spin_lock_irqsave(&nesqp->lock, flags); |
3372 | 3394 | ||
3373 | head = nesqp->hwqp.rq_head; | 3395 | head = nesqp->hwqp.rq_head; |
3374 | 3396 | ||
@@ -3421,7 +3443,7 @@ static int nes_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr, | |||
3421 | nes_write32(nesdev->regs+NES_WQE_ALLOC, (counter<<24) | nesqp->hwqp.qp_id); | 3443 | nes_write32(nesdev->regs+NES_WQE_ALLOC, (counter<<24) | nesqp->hwqp.qp_id); |
3422 | } | 3444 | } |
3423 | 3445 | ||
3424 | spin_unlock_irqrestore(&nesqp->lock, flags); | 3446 | spin_unlock_irqrestore(&nesqp->lock, flags); |
3425 | 3447 | ||
3426 | if (err) | 3448 | if (err) |
3427 | *bad_wr = ib_wr; | 3449 | *bad_wr = ib_wr; |
@@ -3453,7 +3475,7 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) | |||
3453 | 3475 | ||
3454 | nes_debug(NES_DBG_CQ, "\n"); | 3476 | nes_debug(NES_DBG_CQ, "\n"); |
3455 | 3477 | ||
3456 | spin_lock_irqsave(&nescq->lock, flags); | 3478 | spin_lock_irqsave(&nescq->lock, flags); |
3457 | 3479 | ||
3458 | head = nescq->hw_cq.cq_head; | 3480 | head = nescq->hw_cq.cq_head; |
3459 | cq_size = nescq->hw_cq.cq_size; | 3481 | cq_size = nescq->hw_cq.cq_size; |
@@ -3562,7 +3584,7 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) | |||
3562 | nes_debug(NES_DBG_CQ, "Reporting %u completions for CQ%u.\n", | 3584 | nes_debug(NES_DBG_CQ, "Reporting %u completions for CQ%u.\n", |
3563 | cqe_count, nescq->hw_cq.cq_number); | 3585 | cqe_count, nescq->hw_cq.cq_number); |
3564 | 3586 | ||
3565 | spin_unlock_irqrestore(&nescq->lock, flags); | 3587 | spin_unlock_irqrestore(&nescq->lock, flags); |
3566 | 3588 | ||
3567 | return cqe_count; | 3589 | return cqe_count; |
3568 | } | 3590 | } |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index fddded7900d1..85257f6b9576 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -106,12 +106,13 @@ int ipoib_open(struct net_device *dev) | |||
106 | 106 | ||
107 | ipoib_dbg(priv, "bringing up interface\n"); | 107 | ipoib_dbg(priv, "bringing up interface\n"); |
108 | 108 | ||
109 | napi_enable(&priv->napi); | ||
110 | set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); | 109 | set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); |
111 | 110 | ||
112 | if (ipoib_pkey_dev_delay_open(dev)) | 111 | if (ipoib_pkey_dev_delay_open(dev)) |
113 | return 0; | 112 | return 0; |
114 | 113 | ||
114 | napi_enable(&priv->napi); | ||
115 | |||
115 | if (ipoib_ib_dev_open(dev)) { | 116 | if (ipoib_ib_dev_open(dev)) { |
116 | napi_disable(&priv->napi); | 117 | napi_disable(&priv->napi); |
117 | return -EINVAL; | 118 | return -EINVAL; |
@@ -546,6 +547,7 @@ static int path_rec_start(struct net_device *dev, | |||
546 | if (path->query_id < 0) { | 547 | if (path->query_id < 0) { |
547 | ipoib_warn(priv, "ib_sa_path_rec_get failed: %d\n", path->query_id); | 548 | ipoib_warn(priv, "ib_sa_path_rec_get failed: %d\n", path->query_id); |
548 | path->query = NULL; | 549 | path->query = NULL; |
550 | complete(&path->done); | ||
549 | return path->query_id; | 551 | return path->query_id; |
550 | } | 552 | } |
551 | 553 | ||
@@ -662,7 +664,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, | |||
662 | skb_push(skb, sizeof *phdr); | 664 | skb_push(skb, sizeof *phdr); |
663 | __skb_queue_tail(&path->queue, skb); | 665 | __skb_queue_tail(&path->queue, skb); |
664 | 666 | ||
665 | if (path_rec_start(dev, path)) { | 667 | if (!path->query && path_rec_start(dev, path)) { |
666 | spin_unlock_irqrestore(&priv->lock, flags); | 668 | spin_unlock_irqrestore(&priv->lock, flags); |
667 | path_free(dev, path); | 669 | path_free(dev, path); |
668 | return; | 670 | return; |
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 9494400e8fd0..fee7304102af 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
@@ -227,10 +227,20 @@ config HP_WMI | |||
227 | To compile this driver as a module, choose M here: the module will | 227 | To compile this driver as a module, choose M here: the module will |
228 | be called hp-wmi. | 228 | be called hp-wmi. |
229 | 229 | ||
230 | config ICS932S401 | ||
231 | tristate "Integrated Circuits ICS932S401" | ||
232 | depends on I2C && EXPERIMENTAL | ||
233 | help | ||
234 | If you say yes here you get support for the Integrated Circuits | ||
235 | ICS932S401 clock control chips. | ||
236 | |||
237 | This driver can also be built as a module. If so, the module | ||
238 | will be called ics932s401. | ||
239 | |||
230 | config MSI_LAPTOP | 240 | config MSI_LAPTOP |
231 | tristate "MSI Laptop Extras" | 241 | tristate "MSI Laptop Extras" |
232 | depends on X86 | 242 | depends on X86 |
233 | depends on ACPI_EC | 243 | depends on ACPI |
234 | depends on BACKLIGHT_CLASS_DEVICE | 244 | depends on BACKLIGHT_CLASS_DEVICE |
235 | ---help--- | 245 | ---help--- |
236 | This is a driver for laptops built by MSI (MICRO-STAR | 246 | This is a driver for laptops built by MSI (MICRO-STAR |
@@ -260,7 +270,7 @@ config PANASONIC_LAPTOP | |||
260 | config COMPAL_LAPTOP | 270 | config COMPAL_LAPTOP |
261 | tristate "Compal Laptop Extras" | 271 | tristate "Compal Laptop Extras" |
262 | depends on X86 | 272 | depends on X86 |
263 | depends on ACPI_EC | 273 | depends on ACPI |
264 | depends on BACKLIGHT_CLASS_DEVICE | 274 | depends on BACKLIGHT_CLASS_DEVICE |
265 | ---help--- | 275 | ---help--- |
266 | This is a driver for laptops built by Compal: | 276 | This is a driver for laptops built by Compal: |
@@ -488,4 +498,6 @@ config SGI_GRU_DEBUG | |||
488 | This option enables addition debugging code for the SGI GRU driver. If | 498 | This option enables addition debugging code for the SGI GRU driver. If |
489 | you are unsure, say N. | 499 | you are unsure, say N. |
490 | 500 | ||
501 | source "drivers/misc/c2port/Kconfig" | ||
502 | |||
491 | endif # MISC_DEVICES | 503 | endif # MISC_DEVICES |
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 909e2468cdc9..817f7f5ab3bd 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
@@ -14,6 +14,7 @@ obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o | |||
14 | obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o | 14 | obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o |
15 | obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o | 15 | obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o |
16 | obj-$(CONFIG_HP_WMI) += hp-wmi.o | 16 | obj-$(CONFIG_HP_WMI) += hp-wmi.o |
17 | obj-$(CONFIG_ICS932S401) += ics932s401.o | ||
17 | obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o | 18 | obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o |
18 | obj-$(CONFIG_LKDTM) += lkdtm.o | 19 | obj-$(CONFIG_LKDTM) += lkdtm.o |
19 | obj-$(CONFIG_TIFM_CORE) += tifm_core.o | 20 | obj-$(CONFIG_TIFM_CORE) += tifm_core.o |
@@ -31,3 +32,4 @@ obj-$(CONFIG_KGDB_TESTS) += kgdbts.o | |||
31 | obj-$(CONFIG_SGI_XP) += sgi-xp/ | 32 | obj-$(CONFIG_SGI_XP) += sgi-xp/ |
32 | obj-$(CONFIG_SGI_GRU) += sgi-gru/ | 33 | obj-$(CONFIG_SGI_GRU) += sgi-gru/ |
33 | obj-$(CONFIG_HP_ILO) += hpilo.o | 34 | obj-$(CONFIG_HP_ILO) += hpilo.o |
35 | obj-$(CONFIG_C2PORT) += c2port/ | ||
diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c index 0532a2de2ce4..94c9f911824e 100644 --- a/drivers/misc/acer-wmi.c +++ b/drivers/misc/acer-wmi.c | |||
@@ -1297,6 +1297,12 @@ static int __init acer_wmi_init(void) | |||
1297 | 1297 | ||
1298 | set_quirks(); | 1298 | set_quirks(); |
1299 | 1299 | ||
1300 | if (!acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) { | ||
1301 | interface->capability &= ~ACER_CAP_BRIGHTNESS; | ||
1302 | printk(ACER_INFO "Brightness must be controlled by " | ||
1303 | "generic video driver\n"); | ||
1304 | } | ||
1305 | |||
1300 | if (platform_driver_register(&acer_platform_driver)) { | 1306 | if (platform_driver_register(&acer_platform_driver)) { |
1301 | printk(ACER_ERR "Unable to register platform driver.\n"); | 1307 | printk(ACER_ERR "Unable to register platform driver.\n"); |
1302 | goto error_platform_register; | 1308 | goto error_platform_register; |
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c index a9d5228724a6..8fb8b3591048 100644 --- a/drivers/misc/asus-laptop.c +++ b/drivers/misc/asus-laptop.c | |||
@@ -1208,9 +1208,13 @@ static int __init asus_laptop_init(void) | |||
1208 | 1208 | ||
1209 | dev = acpi_get_physical_device(hotk->device->handle); | 1209 | dev = acpi_get_physical_device(hotk->device->handle); |
1210 | 1210 | ||
1211 | result = asus_backlight_init(dev); | 1211 | if (!acpi_video_backlight_support()) { |
1212 | if (result) | 1212 | result = asus_backlight_init(dev); |
1213 | goto fail_backlight; | 1213 | if (result) |
1214 | goto fail_backlight; | ||
1215 | } else | ||
1216 | printk(ASUS_INFO "Brightness ignored, must be controlled by " | ||
1217 | "ACPI video driver\n"); | ||
1214 | 1218 | ||
1215 | result = asus_led_init(dev); | 1219 | result = asus_led_init(dev); |
1216 | if (result) | 1220 | if (result) |
diff --git a/drivers/misc/c2port/Kconfig b/drivers/misc/c2port/Kconfig new file mode 100644 index 000000000000..e46af9a5810d --- /dev/null +++ b/drivers/misc/c2port/Kconfig | |||
@@ -0,0 +1,35 @@ | |||
1 | # | ||
2 | # C2 port devices | ||
3 | # | ||
4 | |||
5 | menuconfig C2PORT | ||
6 | tristate "Silicon Labs C2 port support (EXPERIMENTAL)" | ||
7 | depends on EXPERIMENTAL | ||
8 | default no | ||
9 | help | ||
10 | This option enables support for Silicon Labs C2 port used to | ||
11 | program Silicon micro controller chips (and other 8051 compatible). | ||
12 | |||
13 | If your board have no such micro controllers you don't need this | ||
14 | interface at all. | ||
15 | |||
16 | To compile this driver as a module, choose M here: the module will | ||
17 | be called c2port_core. Note that you also need a client module | ||
18 | usually called c2port-*. | ||
19 | |||
20 | If you are not sure, say N here. | ||
21 | |||
22 | if C2PORT | ||
23 | |||
24 | config C2PORT_DURAMAR_2150 | ||
25 | tristate "C2 port support for Eurotech's Duramar 2150 (EXPERIMENTAL)" | ||
26 | depends on X86 && C2PORT | ||
27 | default no | ||
28 | help | ||
29 | This option enables C2 support for the Eurotech's Duramar 2150 | ||
30 | on board micro controller. | ||
31 | |||
32 | To compile this driver as a module, choose M here: the module will | ||
33 | be called c2port-duramar2150. | ||
34 | |||
35 | endif # C2PORT | ||
diff --git a/drivers/misc/c2port/Makefile b/drivers/misc/c2port/Makefile new file mode 100644 index 000000000000..3b2cf43d60f5 --- /dev/null +++ b/drivers/misc/c2port/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | obj-$(CONFIG_C2PORT) += core.o | ||
2 | |||
3 | obj-$(CONFIG_C2PORT_DURAMAR_2150) += c2port-duramar2150.o | ||
diff --git a/drivers/misc/c2port/c2port-duramar2150.c b/drivers/misc/c2port/c2port-duramar2150.c new file mode 100644 index 000000000000..338dcc121507 --- /dev/null +++ b/drivers/misc/c2port/c2port-duramar2150.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * Silicon Labs C2 port Linux support for Eurotech Duramar 2150 | ||
3 | * | ||
4 | * Copyright (c) 2008 Rodolfo Giometti <giometti@linux.it> | ||
5 | * Copyright (c) 2008 Eurotech S.p.A. <info@eurotech.it> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License version 2 as published by | ||
9 | * the Free Software Foundation | ||
10 | */ | ||
11 | |||
12 | #include <linux/errno.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/c2port.h> | ||
19 | |||
20 | #define DATA_PORT 0x325 | ||
21 | #define DIR_PORT 0x326 | ||
22 | #define C2D (1 << 0) | ||
23 | #define C2CK (1 << 1) | ||
24 | |||
25 | static DEFINE_MUTEX(update_lock); | ||
26 | |||
27 | /* | ||
28 | * C2 port operations | ||
29 | */ | ||
30 | |||
31 | static void duramar2150_c2port_access(struct c2port_device *dev, int status) | ||
32 | { | ||
33 | u8 v; | ||
34 | |||
35 | mutex_lock(&update_lock); | ||
36 | |||
37 | v = inb(DIR_PORT); | ||
38 | |||
39 | /* 0 = input, 1 = output */ | ||
40 | if (status) | ||
41 | outb(v | (C2D | C2CK), DIR_PORT); | ||
42 | else | ||
43 | /* When access is "off" is important that both lines are set | ||
44 | * as inputs or hi-impedence */ | ||
45 | outb(v & ~(C2D | C2CK), DIR_PORT); | ||
46 | |||
47 | mutex_unlock(&update_lock); | ||
48 | } | ||
49 | |||
50 | static void duramar2150_c2port_c2d_dir(struct c2port_device *dev, int dir) | ||
51 | { | ||
52 | u8 v; | ||
53 | |||
54 | mutex_lock(&update_lock); | ||
55 | |||
56 | v = inb(DIR_PORT); | ||
57 | |||
58 | if (dir) | ||
59 | outb(v & ~C2D, DIR_PORT); | ||
60 | else | ||
61 | outb(v | C2D, DIR_PORT); | ||
62 | |||
63 | mutex_unlock(&update_lock); | ||
64 | } | ||
65 | |||
66 | static int duramar2150_c2port_c2d_get(struct c2port_device *dev) | ||
67 | { | ||
68 | return inb(DATA_PORT) & C2D; | ||
69 | } | ||
70 | |||
71 | static void duramar2150_c2port_c2d_set(struct c2port_device *dev, int status) | ||
72 | { | ||
73 | u8 v; | ||
74 | |||
75 | mutex_lock(&update_lock); | ||
76 | |||
77 | v = inb(DATA_PORT); | ||
78 | |||
79 | if (status) | ||
80 | outb(v | C2D, DATA_PORT); | ||
81 | else | ||
82 | outb(v & ~C2D, DATA_PORT); | ||
83 | |||
84 | mutex_unlock(&update_lock); | ||
85 | } | ||
86 | |||
87 | static void duramar2150_c2port_c2ck_set(struct c2port_device *dev, int status) | ||
88 | { | ||
89 | u8 v; | ||
90 | |||
91 | mutex_lock(&update_lock); | ||
92 | |||
93 | v = inb(DATA_PORT); | ||
94 | |||
95 | if (status) | ||
96 | outb(v | C2CK, DATA_PORT); | ||
97 | else | ||
98 | outb(v & ~C2CK, DATA_PORT); | ||
99 | |||
100 | mutex_unlock(&update_lock); | ||
101 | } | ||
102 | |||
103 | static struct c2port_ops duramar2150_c2port_ops = { | ||
104 | .block_size = 512, /* bytes */ | ||
105 | .blocks_num = 30, /* total flash size: 15360 bytes */ | ||
106 | |||
107 | .access = duramar2150_c2port_access, | ||
108 | .c2d_dir = duramar2150_c2port_c2d_dir, | ||
109 | .c2d_get = duramar2150_c2port_c2d_get, | ||
110 | .c2d_set = duramar2150_c2port_c2d_set, | ||
111 | .c2ck_set = duramar2150_c2port_c2ck_set, | ||
112 | }; | ||
113 | |||
114 | static struct c2port_device *duramar2150_c2port_dev; | ||
115 | |||
116 | /* | ||
117 | * Module stuff | ||
118 | */ | ||
119 | |||
120 | static int __init duramar2150_c2port_init(void) | ||
121 | { | ||
122 | struct resource *res; | ||
123 | int ret = 0; | ||
124 | |||
125 | res = request_region(0x325, 2, "c2port"); | ||
126 | if (!res) | ||
127 | return -EBUSY; | ||
128 | |||
129 | duramar2150_c2port_dev = c2port_device_register("uc", | ||
130 | &duramar2150_c2port_ops, NULL); | ||
131 | if (!duramar2150_c2port_dev) { | ||
132 | ret = -ENODEV; | ||
133 | goto free_region; | ||
134 | } | ||
135 | |||
136 | return 0; | ||
137 | |||
138 | free_region: | ||
139 | release_region(0x325, 2); | ||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | static void __exit duramar2150_c2port_exit(void) | ||
144 | { | ||
145 | /* Setup the GPIOs as input by default (access = 0) */ | ||
146 | duramar2150_c2port_access(duramar2150_c2port_dev, 0); | ||
147 | |||
148 | c2port_device_unregister(duramar2150_c2port_dev); | ||
149 | |||
150 | release_region(0x325, 2); | ||
151 | } | ||
152 | |||
153 | module_init(duramar2150_c2port_init); | ||
154 | module_exit(duramar2150_c2port_exit); | ||
155 | |||
156 | MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); | ||
157 | MODULE_DESCRIPTION("Silicon Labs C2 port Linux support for Duramar 2150"); | ||
158 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c new file mode 100644 index 000000000000..976b35d1d035 --- /dev/null +++ b/drivers/misc/c2port/core.c | |||
@@ -0,0 +1,1002 @@ | |||
1 | /* | ||
2 | * Silicon Labs C2 port core Linux support | ||
3 | * | ||
4 | * Copyright (c) 2007 Rodolfo Giometti <giometti@linux.it> | ||
5 | * Copyright (c) 2007 Eurotech S.p.A. <info@eurotech.it> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License version 2 as published by | ||
9 | * the Free Software Foundation | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/ctype.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/idr.h> | ||
21 | |||
22 | #include <linux/c2port.h> | ||
23 | |||
24 | #define DRIVER_NAME "c2port" | ||
25 | #define DRIVER_VERSION "0.51.0" | ||
26 | |||
27 | static DEFINE_SPINLOCK(c2port_idr_lock); | ||
28 | static DEFINE_IDR(c2port_idr); | ||
29 | |||
30 | /* | ||
31 | * Local variables | ||
32 | */ | ||
33 | |||
34 | static struct class *c2port_class; | ||
35 | |||
36 | /* | ||
37 | * C2 registers & commands defines | ||
38 | */ | ||
39 | |||
40 | /* C2 registers */ | ||
41 | #define C2PORT_DEVICEID 0x00 | ||
42 | #define C2PORT_REVID 0x01 | ||
43 | #define C2PORT_FPCTL 0x02 | ||
44 | #define C2PORT_FPDAT 0xB4 | ||
45 | |||
46 | /* C2 interface commands */ | ||
47 | #define C2PORT_GET_VERSION 0x01 | ||
48 | #define C2PORT_DEVICE_ERASE 0x03 | ||
49 | #define C2PORT_BLOCK_READ 0x06 | ||
50 | #define C2PORT_BLOCK_WRITE 0x07 | ||
51 | #define C2PORT_PAGE_ERASE 0x08 | ||
52 | |||
53 | /* C2 status return codes */ | ||
54 | #define C2PORT_INVALID_COMMAND 0x00 | ||
55 | #define C2PORT_COMMAND_FAILED 0x02 | ||
56 | #define C2PORT_COMMAND_OK 0x0d | ||
57 | |||
58 | /* | ||
59 | * C2 port low level signal managements | ||
60 | */ | ||
61 | |||
62 | static void c2port_reset(struct c2port_device *dev) | ||
63 | { | ||
64 | struct c2port_ops *ops = dev->ops; | ||
65 | |||
66 | /* To reset the device we have to keep clock line low for at least | ||
67 | * 20us. | ||
68 | */ | ||
69 | local_irq_disable(); | ||
70 | ops->c2ck_set(dev, 0); | ||
71 | udelay(25); | ||
72 | ops->c2ck_set(dev, 1); | ||
73 | local_irq_enable(); | ||
74 | |||
75 | udelay(1); | ||
76 | } | ||
77 | |||
78 | static void c2port_strobe_ck(struct c2port_device *dev) | ||
79 | { | ||
80 | struct c2port_ops *ops = dev->ops; | ||
81 | |||
82 | /* During hi-low-hi transition we disable local IRQs to avoid | ||
83 | * interructions since C2 port specification says that it must be | ||
84 | * shorter than 5us, otherwise the microcontroller may consider | ||
85 | * it as a reset signal! | ||
86 | */ | ||
87 | local_irq_disable(); | ||
88 | ops->c2ck_set(dev, 0); | ||
89 | udelay(1); | ||
90 | ops->c2ck_set(dev, 1); | ||
91 | local_irq_enable(); | ||
92 | |||
93 | udelay(1); | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * C2 port basic functions | ||
98 | */ | ||
99 | |||
100 | static void c2port_write_ar(struct c2port_device *dev, u8 addr) | ||
101 | { | ||
102 | struct c2port_ops *ops = dev->ops; | ||
103 | int i; | ||
104 | |||
105 | /* START field */ | ||
106 | c2port_strobe_ck(dev); | ||
107 | |||
108 | /* INS field (11b, LSB first) */ | ||
109 | ops->c2d_dir(dev, 0); | ||
110 | ops->c2d_set(dev, 1); | ||
111 | c2port_strobe_ck(dev); | ||
112 | ops->c2d_set(dev, 1); | ||
113 | c2port_strobe_ck(dev); | ||
114 | |||
115 | /* ADDRESS field */ | ||
116 | for (i = 0; i < 8; i++) { | ||
117 | ops->c2d_set(dev, addr & 0x01); | ||
118 | c2port_strobe_ck(dev); | ||
119 | |||
120 | addr >>= 1; | ||
121 | } | ||
122 | |||
123 | /* STOP field */ | ||
124 | ops->c2d_dir(dev, 1); | ||
125 | c2port_strobe_ck(dev); | ||
126 | } | ||
127 | |||
128 | static int c2port_read_ar(struct c2port_device *dev, u8 *addr) | ||
129 | { | ||
130 | struct c2port_ops *ops = dev->ops; | ||
131 | int i; | ||
132 | |||
133 | /* START field */ | ||
134 | c2port_strobe_ck(dev); | ||
135 | |||
136 | /* INS field (10b, LSB first) */ | ||
137 | ops->c2d_dir(dev, 0); | ||
138 | ops->c2d_set(dev, 0); | ||
139 | c2port_strobe_ck(dev); | ||
140 | ops->c2d_set(dev, 1); | ||
141 | c2port_strobe_ck(dev); | ||
142 | |||
143 | /* ADDRESS field */ | ||
144 | ops->c2d_dir(dev, 1); | ||
145 | *addr = 0; | ||
146 | for (i = 0; i < 8; i++) { | ||
147 | *addr >>= 1; /* shift in 8-bit ADDRESS field LSB first */ | ||
148 | |||
149 | c2port_strobe_ck(dev); | ||
150 | if (ops->c2d_get(dev)) | ||
151 | *addr |= 0x80; | ||
152 | } | ||
153 | |||
154 | /* STOP field */ | ||
155 | c2port_strobe_ck(dev); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static int c2port_write_dr(struct c2port_device *dev, u8 data) | ||
161 | { | ||
162 | struct c2port_ops *ops = dev->ops; | ||
163 | int timeout, i; | ||
164 | |||
165 | /* START field */ | ||
166 | c2port_strobe_ck(dev); | ||
167 | |||
168 | /* INS field (01b, LSB first) */ | ||
169 | ops->c2d_dir(dev, 0); | ||
170 | ops->c2d_set(dev, 1); | ||
171 | c2port_strobe_ck(dev); | ||
172 | ops->c2d_set(dev, 0); | ||
173 | c2port_strobe_ck(dev); | ||
174 | |||
175 | /* LENGTH field (00b, LSB first -> 1 byte) */ | ||
176 | ops->c2d_set(dev, 0); | ||
177 | c2port_strobe_ck(dev); | ||
178 | ops->c2d_set(dev, 0); | ||
179 | c2port_strobe_ck(dev); | ||
180 | |||
181 | /* DATA field */ | ||
182 | for (i = 0; i < 8; i++) { | ||
183 | ops->c2d_set(dev, data & 0x01); | ||
184 | c2port_strobe_ck(dev); | ||
185 | |||
186 | data >>= 1; | ||
187 | } | ||
188 | |||
189 | /* WAIT field */ | ||
190 | ops->c2d_dir(dev, 1); | ||
191 | timeout = 20; | ||
192 | do { | ||
193 | c2port_strobe_ck(dev); | ||
194 | if (ops->c2d_get(dev)) | ||
195 | break; | ||
196 | |||
197 | udelay(1); | ||
198 | } while (--timeout > 0); | ||
199 | if (timeout == 0) | ||
200 | return -EIO; | ||
201 | |||
202 | /* STOP field */ | ||
203 | c2port_strobe_ck(dev); | ||
204 | |||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | static int c2port_read_dr(struct c2port_device *dev, u8 *data) | ||
209 | { | ||
210 | struct c2port_ops *ops = dev->ops; | ||
211 | int timeout, i; | ||
212 | |||
213 | /* START field */ | ||
214 | c2port_strobe_ck(dev); | ||
215 | |||
216 | /* INS field (00b, LSB first) */ | ||
217 | ops->c2d_dir(dev, 0); | ||
218 | ops->c2d_set(dev, 0); | ||
219 | c2port_strobe_ck(dev); | ||
220 | ops->c2d_set(dev, 0); | ||
221 | c2port_strobe_ck(dev); | ||
222 | |||
223 | /* LENGTH field (00b, LSB first -> 1 byte) */ | ||
224 | ops->c2d_set(dev, 0); | ||
225 | c2port_strobe_ck(dev); | ||
226 | ops->c2d_set(dev, 0); | ||
227 | c2port_strobe_ck(dev); | ||
228 | |||
229 | /* WAIT field */ | ||
230 | ops->c2d_dir(dev, 1); | ||
231 | timeout = 20; | ||
232 | do { | ||
233 | c2port_strobe_ck(dev); | ||
234 | if (ops->c2d_get(dev)) | ||
235 | break; | ||
236 | |||
237 | udelay(1); | ||
238 | } while (--timeout > 0); | ||
239 | if (timeout == 0) | ||
240 | return -EIO; | ||
241 | |||
242 | /* DATA field */ | ||
243 | *data = 0; | ||
244 | for (i = 0; i < 8; i++) { | ||
245 | *data >>= 1; /* shift in 8-bit DATA field LSB first */ | ||
246 | |||
247 | c2port_strobe_ck(dev); | ||
248 | if (ops->c2d_get(dev)) | ||
249 | *data |= 0x80; | ||
250 | } | ||
251 | |||
252 | /* STOP field */ | ||
253 | c2port_strobe_ck(dev); | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static int c2port_poll_in_busy(struct c2port_device *dev) | ||
259 | { | ||
260 | u8 addr; | ||
261 | int ret, timeout = 20; | ||
262 | |||
263 | do { | ||
264 | ret = (c2port_read_ar(dev, &addr)); | ||
265 | if (ret < 0) | ||
266 | return -EIO; | ||
267 | |||
268 | if (!(addr & 0x02)) | ||
269 | break; | ||
270 | |||
271 | udelay(1); | ||
272 | } while (--timeout > 0); | ||
273 | if (timeout == 0) | ||
274 | return -EIO; | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static int c2port_poll_out_ready(struct c2port_device *dev) | ||
280 | { | ||
281 | u8 addr; | ||
282 | int ret, timeout = 10000; /* erase flash needs long time... */ | ||
283 | |||
284 | do { | ||
285 | ret = (c2port_read_ar(dev, &addr)); | ||
286 | if (ret < 0) | ||
287 | return -EIO; | ||
288 | |||
289 | if (addr & 0x01) | ||
290 | break; | ||
291 | |||
292 | udelay(1); | ||
293 | } while (--timeout > 0); | ||
294 | if (timeout == 0) | ||
295 | return -EIO; | ||
296 | |||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | /* | ||
301 | * sysfs methods | ||
302 | */ | ||
303 | |||
304 | static ssize_t c2port_show_name(struct device *dev, | ||
305 | struct device_attribute *attr, char *buf) | ||
306 | { | ||
307 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
308 | |||
309 | return sprintf(buf, "%s\n", c2dev->name); | ||
310 | } | ||
311 | |||
312 | static ssize_t c2port_show_flash_blocks_num(struct device *dev, | ||
313 | struct device_attribute *attr, char *buf) | ||
314 | { | ||
315 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
316 | struct c2port_ops *ops = c2dev->ops; | ||
317 | |||
318 | return sprintf(buf, "%d\n", ops->blocks_num); | ||
319 | } | ||
320 | |||
321 | static ssize_t c2port_show_flash_block_size(struct device *dev, | ||
322 | struct device_attribute *attr, char *buf) | ||
323 | { | ||
324 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
325 | struct c2port_ops *ops = c2dev->ops; | ||
326 | |||
327 | return sprintf(buf, "%d\n", ops->block_size); | ||
328 | } | ||
329 | |||
330 | static ssize_t c2port_show_flash_size(struct device *dev, | ||
331 | struct device_attribute *attr, char *buf) | ||
332 | { | ||
333 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
334 | struct c2port_ops *ops = c2dev->ops; | ||
335 | |||
336 | return sprintf(buf, "%d\n", ops->blocks_num * ops->block_size); | ||
337 | } | ||
338 | |||
339 | static ssize_t c2port_show_access(struct device *dev, | ||
340 | struct device_attribute *attr, char *buf) | ||
341 | { | ||
342 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
343 | |||
344 | return sprintf(buf, "%d\n", c2dev->access); | ||
345 | } | ||
346 | |||
347 | static ssize_t c2port_store_access(struct device *dev, | ||
348 | struct device_attribute *attr, | ||
349 | const char *buf, size_t count) | ||
350 | { | ||
351 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
352 | struct c2port_ops *ops = c2dev->ops; | ||
353 | int status, ret; | ||
354 | |||
355 | ret = sscanf(buf, "%d", &status); | ||
356 | if (ret != 1) | ||
357 | return -EINVAL; | ||
358 | |||
359 | mutex_lock(&c2dev->mutex); | ||
360 | |||
361 | c2dev->access = !!status; | ||
362 | |||
363 | /* If access is "on" clock should be HIGH _before_ setting the line | ||
364 | * as output and data line should be set as INPUT anyway */ | ||
365 | if (c2dev->access) | ||
366 | ops->c2ck_set(c2dev, 1); | ||
367 | ops->access(c2dev, c2dev->access); | ||
368 | if (c2dev->access) | ||
369 | ops->c2d_dir(c2dev, 1); | ||
370 | |||
371 | mutex_unlock(&c2dev->mutex); | ||
372 | |||
373 | return count; | ||
374 | } | ||
375 | |||
376 | static ssize_t c2port_store_reset(struct device *dev, | ||
377 | struct device_attribute *attr, | ||
378 | const char *buf, size_t count) | ||
379 | { | ||
380 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
381 | |||
382 | /* Check the device access status */ | ||
383 | if (!c2dev->access) | ||
384 | return -EBUSY; | ||
385 | |||
386 | mutex_lock(&c2dev->mutex); | ||
387 | |||
388 | c2port_reset(c2dev); | ||
389 | c2dev->flash_access = 0; | ||
390 | |||
391 | mutex_unlock(&c2dev->mutex); | ||
392 | |||
393 | return count; | ||
394 | } | ||
395 | |||
396 | static ssize_t __c2port_show_dev_id(struct c2port_device *dev, char *buf) | ||
397 | { | ||
398 | u8 data; | ||
399 | int ret; | ||
400 | |||
401 | /* Select DEVICEID register for C2 data register accesses */ | ||
402 | c2port_write_ar(dev, C2PORT_DEVICEID); | ||
403 | |||
404 | /* Read and return the device ID register */ | ||
405 | ret = c2port_read_dr(dev, &data); | ||
406 | if (ret < 0) | ||
407 | return ret; | ||
408 | |||
409 | return sprintf(buf, "%d\n", data); | ||
410 | } | ||
411 | |||
412 | static ssize_t c2port_show_dev_id(struct device *dev, | ||
413 | struct device_attribute *attr, char *buf) | ||
414 | { | ||
415 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
416 | ssize_t ret; | ||
417 | |||
418 | /* Check the device access status */ | ||
419 | if (!c2dev->access) | ||
420 | return -EBUSY; | ||
421 | |||
422 | mutex_lock(&c2dev->mutex); | ||
423 | ret = __c2port_show_dev_id(c2dev, buf); | ||
424 | mutex_unlock(&c2dev->mutex); | ||
425 | |||
426 | if (ret < 0) | ||
427 | dev_err(dev, "cannot read from %s\n", c2dev->name); | ||
428 | |||
429 | return ret; | ||
430 | } | ||
431 | |||
432 | static ssize_t __c2port_show_rev_id(struct c2port_device *dev, char *buf) | ||
433 | { | ||
434 | u8 data; | ||
435 | int ret; | ||
436 | |||
437 | /* Select REVID register for C2 data register accesses */ | ||
438 | c2port_write_ar(dev, C2PORT_REVID); | ||
439 | |||
440 | /* Read and return the revision ID register */ | ||
441 | ret = c2port_read_dr(dev, &data); | ||
442 | if (ret < 0) | ||
443 | return ret; | ||
444 | |||
445 | return sprintf(buf, "%d\n", data); | ||
446 | } | ||
447 | |||
448 | static ssize_t c2port_show_rev_id(struct device *dev, | ||
449 | struct device_attribute *attr, char *buf) | ||
450 | { | ||
451 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
452 | ssize_t ret; | ||
453 | |||
454 | /* Check the device access status */ | ||
455 | if (!c2dev->access) | ||
456 | return -EBUSY; | ||
457 | |||
458 | mutex_lock(&c2dev->mutex); | ||
459 | ret = __c2port_show_rev_id(c2dev, buf); | ||
460 | mutex_unlock(&c2dev->mutex); | ||
461 | |||
462 | if (ret < 0) | ||
463 | dev_err(c2dev->dev, "cannot read from %s\n", c2dev->name); | ||
464 | |||
465 | return ret; | ||
466 | } | ||
467 | |||
468 | static ssize_t c2port_show_flash_access(struct device *dev, | ||
469 | struct device_attribute *attr, char *buf) | ||
470 | { | ||
471 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
472 | |||
473 | return sprintf(buf, "%d\n", c2dev->flash_access); | ||
474 | } | ||
475 | |||
476 | static ssize_t __c2port_store_flash_access(struct c2port_device *dev, | ||
477 | int status) | ||
478 | { | ||
479 | int ret; | ||
480 | |||
481 | /* Check the device access status */ | ||
482 | if (!dev->access) | ||
483 | return -EBUSY; | ||
484 | |||
485 | dev->flash_access = !!status; | ||
486 | |||
487 | /* If flash_access is off we have nothing to do... */ | ||
488 | if (dev->flash_access == 0) | ||
489 | return 0; | ||
490 | |||
491 | /* Target the C2 flash programming control register for C2 data | ||
492 | * register access */ | ||
493 | c2port_write_ar(dev, C2PORT_FPCTL); | ||
494 | |||
495 | /* Write the first keycode to enable C2 Flash programming */ | ||
496 | ret = c2port_write_dr(dev, 0x02); | ||
497 | if (ret < 0) | ||
498 | return ret; | ||
499 | |||
500 | /* Write the second keycode to enable C2 Flash programming */ | ||
501 | ret = c2port_write_dr(dev, 0x01); | ||
502 | if (ret < 0) | ||
503 | return ret; | ||
504 | |||
505 | /* Delay for at least 20ms to ensure the target is ready for | ||
506 | * C2 flash programming */ | ||
507 | mdelay(25); | ||
508 | |||
509 | return 0; | ||
510 | } | ||
511 | |||
512 | static ssize_t c2port_store_flash_access(struct device *dev, | ||
513 | struct device_attribute *attr, | ||
514 | const char *buf, size_t count) | ||
515 | { | ||
516 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
517 | int status; | ||
518 | ssize_t ret; | ||
519 | |||
520 | ret = sscanf(buf, "%d", &status); | ||
521 | if (ret != 1) | ||
522 | return -EINVAL; | ||
523 | |||
524 | mutex_lock(&c2dev->mutex); | ||
525 | ret = __c2port_store_flash_access(c2dev, status); | ||
526 | mutex_unlock(&c2dev->mutex); | ||
527 | |||
528 | if (ret < 0) { | ||
529 | dev_err(c2dev->dev, "cannot enable %s flash programming\n", | ||
530 | c2dev->name); | ||
531 | return ret; | ||
532 | } | ||
533 | |||
534 | return count; | ||
535 | } | ||
536 | |||
537 | static ssize_t __c2port_write_flash_erase(struct c2port_device *dev) | ||
538 | { | ||
539 | u8 status; | ||
540 | int ret; | ||
541 | |||
542 | /* Target the C2 flash programming data register for C2 data register | ||
543 | * access. | ||
544 | */ | ||
545 | c2port_write_ar(dev, C2PORT_FPDAT); | ||
546 | |||
547 | /* Send device erase command */ | ||
548 | c2port_write_dr(dev, C2PORT_DEVICE_ERASE); | ||
549 | |||
550 | /* Wait for input acknowledge */ | ||
551 | ret = c2port_poll_in_busy(dev); | ||
552 | if (ret < 0) | ||
553 | return ret; | ||
554 | |||
555 | /* Should check status before starting FLASH access sequence */ | ||
556 | |||
557 | /* Wait for status information */ | ||
558 | ret = c2port_poll_out_ready(dev); | ||
559 | if (ret < 0) | ||
560 | return ret; | ||
561 | |||
562 | /* Read flash programming interface status */ | ||
563 | ret = c2port_read_dr(dev, &status); | ||
564 | if (ret < 0) | ||
565 | return ret; | ||
566 | if (status != C2PORT_COMMAND_OK) | ||
567 | return -EBUSY; | ||
568 | |||
569 | /* Send a three-byte arming sequence to enable the device erase. | ||
570 | * If the sequence is not received correctly, the command will be | ||
571 | * ignored. | ||
572 | * Sequence is: 0xde, 0xad, 0xa5. | ||
573 | */ | ||
574 | c2port_write_dr(dev, 0xde); | ||
575 | ret = c2port_poll_in_busy(dev); | ||
576 | if (ret < 0) | ||
577 | return ret; | ||
578 | c2port_write_dr(dev, 0xad); | ||
579 | ret = c2port_poll_in_busy(dev); | ||
580 | if (ret < 0) | ||
581 | return ret; | ||
582 | c2port_write_dr(dev, 0xa5); | ||
583 | ret = c2port_poll_in_busy(dev); | ||
584 | if (ret < 0) | ||
585 | return ret; | ||
586 | |||
587 | ret = c2port_poll_out_ready(dev); | ||
588 | if (ret < 0) | ||
589 | return ret; | ||
590 | |||
591 | return 0; | ||
592 | } | ||
593 | |||
594 | static ssize_t c2port_store_flash_erase(struct device *dev, | ||
595 | struct device_attribute *attr, | ||
596 | const char *buf, size_t count) | ||
597 | { | ||
598 | struct c2port_device *c2dev = dev_get_drvdata(dev); | ||
599 | int ret; | ||
600 | |||
601 | /* Check the device and flash access status */ | ||
602 | if (!c2dev->access || !c2dev->flash_access) | ||
603 | return -EBUSY; | ||
604 | |||
605 | mutex_lock(&c2dev->mutex); | ||
606 | ret = __c2port_write_flash_erase(c2dev); | ||
607 | mutex_unlock(&c2dev->mutex); | ||
608 | |||
609 | if (ret < 0) { | ||
610 | dev_err(c2dev->dev, "cannot erase %s flash\n", c2dev->name); | ||
611 | return ret; | ||
612 | } | ||
613 | |||
614 | return count; | ||
615 | } | ||
616 | |||
617 | static ssize_t __c2port_read_flash_data(struct c2port_device *dev, | ||
618 | char *buffer, loff_t offset, size_t count) | ||
619 | { | ||
620 | struct c2port_ops *ops = dev->ops; | ||
621 | u8 status, nread = 128; | ||
622 | int i, ret; | ||
623 | |||
624 | /* Check for flash end */ | ||
625 | if (offset >= ops->block_size * ops->blocks_num) | ||
626 | return 0; | ||
627 | |||
628 | if (ops->block_size * ops->blocks_num - offset < nread) | ||
629 | nread = ops->block_size * ops->blocks_num - offset; | ||
630 | if (count < nread) | ||
631 | nread = count; | ||
632 | if (nread == 0) | ||
633 | return nread; | ||
634 | |||
635 | /* Target the C2 flash programming data register for C2 data register | ||
636 | * access */ | ||
637 | c2port_write_ar(dev, C2PORT_FPDAT); | ||
638 | |||
639 | /* Send flash block read command */ | ||
640 | c2port_write_dr(dev, C2PORT_BLOCK_READ); | ||
641 | |||
642 | /* Wait for input acknowledge */ | ||
643 | ret = c2port_poll_in_busy(dev); | ||
644 | if (ret < 0) | ||
645 | return ret; | ||
646 | |||
647 | /* Should check status before starting FLASH access sequence */ | ||
648 | |||
649 | /* Wait for status information */ | ||
650 | ret = c2port_poll_out_ready(dev); | ||
651 | if (ret < 0) | ||
652 | return ret; | ||
653 | |||
654 | /* Read flash programming interface status */ | ||
655 | ret = c2port_read_dr(dev, &status); | ||
656 | if (ret < 0) | ||
657 | return ret; | ||
658 | if (status != C2PORT_COMMAND_OK) | ||
659 | return -EBUSY; | ||
660 | |||
661 | /* Send address high byte */ | ||
662 | c2port_write_dr(dev, offset >> 8); | ||
663 | ret = c2port_poll_in_busy(dev); | ||
664 | if (ret < 0) | ||
665 | return ret; | ||
666 | |||
667 | /* Send address low byte */ | ||
668 | c2port_write_dr(dev, offset & 0x00ff); | ||
669 | ret = c2port_poll_in_busy(dev); | ||
670 | if (ret < 0) | ||
671 | return ret; | ||
672 | |||
673 | /* Send address block size */ | ||
674 | c2port_write_dr(dev, nread); | ||
675 | ret = c2port_poll_in_busy(dev); | ||
676 | if (ret < 0) | ||
677 | return ret; | ||
678 | |||
679 | /* Should check status before reading FLASH block */ | ||
680 | |||
681 | /* Wait for status information */ | ||
682 | ret = c2port_poll_out_ready(dev); | ||
683 | if (ret < 0) | ||
684 | return ret; | ||
685 | |||
686 | /* Read flash programming interface status */ | ||
687 | ret = c2port_read_dr(dev, &status); | ||
688 | if (ret < 0) | ||
689 | return ret; | ||
690 | if (status != C2PORT_COMMAND_OK) | ||
691 | return -EBUSY; | ||
692 | |||
693 | /* Read flash block */ | ||
694 | for (i = 0; i < nread; i++) { | ||
695 | ret = c2port_poll_out_ready(dev); | ||
696 | if (ret < 0) | ||
697 | return ret; | ||
698 | |||
699 | ret = c2port_read_dr(dev, buffer+i); | ||
700 | if (ret < 0) | ||
701 | return ret; | ||
702 | } | ||
703 | |||
704 | return nread; | ||
705 | } | ||
706 | |||
707 | static ssize_t c2port_read_flash_data(struct kobject *kobj, | ||
708 | struct bin_attribute *attr, | ||
709 | char *buffer, loff_t offset, size_t count) | ||
710 | { | ||
711 | struct c2port_device *c2dev = | ||
712 | dev_get_drvdata(container_of(kobj, | ||
713 | struct device, kobj)); | ||
714 | ssize_t ret; | ||
715 | |||
716 | /* Check the device and flash access status */ | ||
717 | if (!c2dev->access || !c2dev->flash_access) | ||
718 | return -EBUSY; | ||
719 | |||
720 | mutex_lock(&c2dev->mutex); | ||
721 | ret = __c2port_read_flash_data(c2dev, buffer, offset, count); | ||
722 | mutex_unlock(&c2dev->mutex); | ||
723 | |||
724 | if (ret < 0) | ||
725 | dev_err(c2dev->dev, "cannot read %s flash\n", c2dev->name); | ||
726 | |||
727 | return ret; | ||
728 | } | ||
729 | |||
730 | static ssize_t __c2port_write_flash_data(struct c2port_device *dev, | ||
731 | char *buffer, loff_t offset, size_t count) | ||
732 | { | ||
733 | struct c2port_ops *ops = dev->ops; | ||
734 | u8 status, nwrite = 128; | ||
735 | int i, ret; | ||
736 | |||
737 | if (nwrite > count) | ||
738 | nwrite = count; | ||
739 | if (ops->block_size * ops->blocks_num - offset < nwrite) | ||
740 | nwrite = ops->block_size * ops->blocks_num - offset; | ||
741 | |||
742 | /* Check for flash end */ | ||
743 | if (offset >= ops->block_size * ops->blocks_num) | ||
744 | return -EINVAL; | ||
745 | |||
746 | /* Target the C2 flash programming data register for C2 data register | ||
747 | * access */ | ||
748 | c2port_write_ar(dev, C2PORT_FPDAT); | ||
749 | |||
750 | /* Send flash block write command */ | ||
751 | c2port_write_dr(dev, C2PORT_BLOCK_WRITE); | ||
752 | |||
753 | /* Wait for input acknowledge */ | ||
754 | ret = c2port_poll_in_busy(dev); | ||
755 | if (ret < 0) | ||
756 | return ret; | ||
757 | |||
758 | /* Should check status before starting FLASH access sequence */ | ||
759 | |||
760 | /* Wait for status information */ | ||
761 | ret = c2port_poll_out_ready(dev); | ||
762 | if (ret < 0) | ||
763 | return ret; | ||
764 | |||
765 | /* Read flash programming interface status */ | ||
766 | ret = c2port_read_dr(dev, &status); | ||
767 | if (ret < 0) | ||
768 | return ret; | ||
769 | if (status != C2PORT_COMMAND_OK) | ||
770 | return -EBUSY; | ||
771 | |||
772 | /* Send address high byte */ | ||
773 | c2port_write_dr(dev, offset >> 8); | ||
774 | ret = c2port_poll_in_busy(dev); | ||
775 | if (ret < 0) | ||
776 | return ret; | ||
777 | |||
778 | /* Send address low byte */ | ||
779 | c2port_write_dr(dev, offset & 0x00ff); | ||
780 | ret = c2port_poll_in_busy(dev); | ||
781 | if (ret < 0) | ||
782 | return ret; | ||
783 | |||
784 | /* Send address block size */ | ||
785 | c2port_write_dr(dev, nwrite); | ||
786 | ret = c2port_poll_in_busy(dev); | ||
787 | if (ret < 0) | ||
788 | return ret; | ||
789 | |||
790 | /* Should check status before writing FLASH block */ | ||
791 | |||
792 | /* Wait for status information */ | ||
793 | ret = c2port_poll_out_ready(dev); | ||
794 | if (ret < 0) | ||
795 | return ret; | ||
796 | |||
797 | /* Read flash programming interface status */ | ||
798 | ret = c2port_read_dr(dev, &status); | ||
799 | if (ret < 0) | ||
800 | return ret; | ||
801 | if (status != C2PORT_COMMAND_OK) | ||
802 | return -EBUSY; | ||
803 | |||
804 | /* Write flash block */ | ||
805 | for (i = 0; i < nwrite; i++) { | ||
806 | ret = c2port_write_dr(dev, *(buffer+i)); | ||
807 | if (ret < 0) | ||
808 | return ret; | ||
809 | |||
810 | ret = c2port_poll_in_busy(dev); | ||
811 | if (ret < 0) | ||
812 | return ret; | ||
813 | |||
814 | } | ||
815 | |||
816 | /* Wait for last flash write to complete */ | ||
817 | ret = c2port_poll_out_ready(dev); | ||
818 | if (ret < 0) | ||
819 | return ret; | ||
820 | |||
821 | return nwrite; | ||
822 | } | ||
823 | |||
824 | static ssize_t c2port_write_flash_data(struct kobject *kobj, | ||
825 | struct bin_attribute *attr, | ||
826 | char *buffer, loff_t offset, size_t count) | ||
827 | { | ||
828 | struct c2port_device *c2dev = | ||
829 | dev_get_drvdata(container_of(kobj, | ||
830 | struct device, kobj)); | ||
831 | int ret; | ||
832 | |||
833 | /* Check the device access status */ | ||
834 | if (!c2dev->access || !c2dev->flash_access) | ||
835 | return -EBUSY; | ||
836 | |||
837 | mutex_lock(&c2dev->mutex); | ||
838 | ret = __c2port_write_flash_data(c2dev, buffer, offset, count); | ||
839 | mutex_unlock(&c2dev->mutex); | ||
840 | |||
841 | if (ret < 0) | ||
842 | dev_err(c2dev->dev, "cannot write %s flash\n", c2dev->name); | ||
843 | |||
844 | return ret; | ||
845 | } | ||
846 | |||
847 | /* | ||
848 | * Class attributes | ||
849 | */ | ||
850 | |||
851 | static struct device_attribute c2port_attrs[] = { | ||
852 | __ATTR(name, 0444, c2port_show_name, NULL), | ||
853 | __ATTR(flash_blocks_num, 0444, c2port_show_flash_blocks_num, NULL), | ||
854 | __ATTR(flash_block_size, 0444, c2port_show_flash_block_size, NULL), | ||
855 | __ATTR(flash_size, 0444, c2port_show_flash_size, NULL), | ||
856 | __ATTR(access, 0644, c2port_show_access, c2port_store_access), | ||
857 | __ATTR(reset, 0200, NULL, c2port_store_reset), | ||
858 | __ATTR(dev_id, 0444, c2port_show_dev_id, NULL), | ||
859 | __ATTR(rev_id, 0444, c2port_show_rev_id, NULL), | ||
860 | |||
861 | __ATTR(flash_access, 0644, c2port_show_flash_access, | ||
862 | c2port_store_flash_access), | ||
863 | __ATTR(flash_erase, 0200, NULL, c2port_store_flash_erase), | ||
864 | __ATTR_NULL, | ||
865 | }; | ||
866 | |||
867 | static struct bin_attribute c2port_bin_attrs = { | ||
868 | .attr = { | ||
869 | .name = "flash_data", | ||
870 | .mode = 0644 | ||
871 | }, | ||
872 | .read = c2port_read_flash_data, | ||
873 | .write = c2port_write_flash_data, | ||
874 | /* .size is computed at run-time */ | ||
875 | }; | ||
876 | |||
877 | /* | ||
878 | * Exported functions | ||
879 | */ | ||
880 | |||
881 | struct c2port_device *c2port_device_register(char *name, | ||
882 | struct c2port_ops *ops, void *devdata) | ||
883 | { | ||
884 | struct c2port_device *c2dev; | ||
885 | int id, ret; | ||
886 | |||
887 | if (unlikely(!ops) || unlikely(!ops->access) || \ | ||
888 | unlikely(!ops->c2d_dir) || unlikely(!ops->c2ck_set) || \ | ||
889 | unlikely(!ops->c2d_get) || unlikely(!ops->c2d_set)) | ||
890 | return ERR_PTR(-EINVAL); | ||
891 | |||
892 | c2dev = kmalloc(sizeof(struct c2port_device), GFP_KERNEL); | ||
893 | if (unlikely(!c2dev)) | ||
894 | return ERR_PTR(-ENOMEM); | ||
895 | |||
896 | ret = idr_pre_get(&c2port_idr, GFP_KERNEL); | ||
897 | if (!ret) { | ||
898 | ret = -ENOMEM; | ||
899 | goto error_idr_get_new; | ||
900 | } | ||
901 | |||
902 | spin_lock_irq(&c2port_idr_lock); | ||
903 | ret = idr_get_new(&c2port_idr, c2dev, &id); | ||
904 | spin_unlock_irq(&c2port_idr_lock); | ||
905 | |||
906 | if (ret < 0) | ||
907 | goto error_idr_get_new; | ||
908 | c2dev->id = id; | ||
909 | |||
910 | c2dev->dev = device_create(c2port_class, NULL, 0, c2dev, | ||
911 | "c2port%d", id); | ||
912 | if (unlikely(!c2dev->dev)) { | ||
913 | ret = -ENOMEM; | ||
914 | goto error_device_create; | ||
915 | } | ||
916 | dev_set_drvdata(c2dev->dev, c2dev); | ||
917 | |||
918 | strncpy(c2dev->name, name, C2PORT_NAME_LEN); | ||
919 | c2dev->ops = ops; | ||
920 | mutex_init(&c2dev->mutex); | ||
921 | |||
922 | /* Create binary file */ | ||
923 | c2port_bin_attrs.size = ops->blocks_num * ops->block_size; | ||
924 | ret = device_create_bin_file(c2dev->dev, &c2port_bin_attrs); | ||
925 | if (unlikely(ret)) | ||
926 | goto error_device_create_bin_file; | ||
927 | |||
928 | /* By default C2 port access is off */ | ||
929 | c2dev->access = c2dev->flash_access = 0; | ||
930 | ops->access(c2dev, 0); | ||
931 | |||
932 | dev_info(c2dev->dev, "C2 port %s added\n", name); | ||
933 | dev_info(c2dev->dev, "%s flash has %d blocks x %d bytes " | ||
934 | "(%d bytes total)\n", | ||
935 | name, ops->blocks_num, ops->block_size, | ||
936 | ops->blocks_num * ops->block_size); | ||
937 | |||
938 | return c2dev; | ||
939 | |||
940 | error_device_create_bin_file: | ||
941 | device_destroy(c2port_class, 0); | ||
942 | |||
943 | error_device_create: | ||
944 | spin_lock_irq(&c2port_idr_lock); | ||
945 | idr_remove(&c2port_idr, id); | ||
946 | spin_unlock_irq(&c2port_idr_lock); | ||
947 | |||
948 | error_idr_get_new: | ||
949 | kfree(c2dev); | ||
950 | |||
951 | return ERR_PTR(ret); | ||
952 | } | ||
953 | EXPORT_SYMBOL(c2port_device_register); | ||
954 | |||
955 | void c2port_device_unregister(struct c2port_device *c2dev) | ||
956 | { | ||
957 | if (!c2dev) | ||
958 | return; | ||
959 | |||
960 | dev_info(c2dev->dev, "C2 port %s removed\n", c2dev->name); | ||
961 | |||
962 | device_remove_bin_file(c2dev->dev, &c2port_bin_attrs); | ||
963 | spin_lock_irq(&c2port_idr_lock); | ||
964 | idr_remove(&c2port_idr, c2dev->id); | ||
965 | spin_unlock_irq(&c2port_idr_lock); | ||
966 | |||
967 | device_destroy(c2port_class, c2dev->id); | ||
968 | |||
969 | kfree(c2dev); | ||
970 | } | ||
971 | EXPORT_SYMBOL(c2port_device_unregister); | ||
972 | |||
973 | /* | ||
974 | * Module stuff | ||
975 | */ | ||
976 | |||
977 | static int __init c2port_init(void) | ||
978 | { | ||
979 | printk(KERN_INFO "Silicon Labs C2 port support v. " DRIVER_VERSION | ||
980 | " - (C) 2007 Rodolfo Giometti\n"); | ||
981 | |||
982 | c2port_class = class_create(THIS_MODULE, "c2port"); | ||
983 | if (!c2port_class) { | ||
984 | printk(KERN_ERR "c2port: failed to allocate class\n"); | ||
985 | return -ENOMEM; | ||
986 | } | ||
987 | c2port_class->dev_attrs = c2port_attrs; | ||
988 | |||
989 | return 0; | ||
990 | } | ||
991 | |||
992 | static void __exit c2port_exit(void) | ||
993 | { | ||
994 | class_destroy(c2port_class); | ||
995 | } | ||
996 | |||
997 | module_init(c2port_init); | ||
998 | module_exit(c2port_exit); | ||
999 | |||
1000 | MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); | ||
1001 | MODULE_DESCRIPTION("Silicon Labs C2 port support v. " DRIVER_VERSION); | ||
1002 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/misc/compal-laptop.c b/drivers/misc/compal-laptop.c index 344b790a6253..11003bba10d3 100644 --- a/drivers/misc/compal-laptop.c +++ b/drivers/misc/compal-laptop.c | |||
@@ -326,12 +326,14 @@ static int __init compal_init(void) | |||
326 | 326 | ||
327 | /* Register backlight stuff */ | 327 | /* Register backlight stuff */ |
328 | 328 | ||
329 | compalbl_device = backlight_device_register("compal-laptop", NULL, NULL, | 329 | if (!acpi_video_backlight_support()) { |
330 | &compalbl_ops); | 330 | compalbl_device = backlight_device_register("compal-laptop", NULL, NULL, |
331 | if (IS_ERR(compalbl_device)) | 331 | &compalbl_ops); |
332 | return PTR_ERR(compalbl_device); | 332 | if (IS_ERR(compalbl_device)) |
333 | return PTR_ERR(compalbl_device); | ||
333 | 334 | ||
334 | compalbl_device->props.max_brightness = COMPAL_LCD_LEVEL_MAX-1; | 335 | compalbl_device->props.max_brightness = COMPAL_LCD_LEVEL_MAX-1; |
336 | } | ||
335 | 337 | ||
336 | ret = platform_driver_register(&compal_driver); | 338 | ret = platform_driver_register(&compal_driver); |
337 | if (ret) | 339 | if (ret) |
diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c index 9ef98b2d5039..02fe2b8b8939 100644 --- a/drivers/misc/eeepc-laptop.c +++ b/drivers/misc/eeepc-laptop.c | |||
@@ -825,9 +825,15 @@ static int __init eeepc_laptop_init(void) | |||
825 | return -ENODEV; | 825 | return -ENODEV; |
826 | } | 826 | } |
827 | dev = acpi_get_physical_device(ehotk->device->handle); | 827 | dev = acpi_get_physical_device(ehotk->device->handle); |
828 | result = eeepc_backlight_init(dev); | 828 | |
829 | if (result) | 829 | if (!acpi_video_backlight_support()) { |
830 | goto fail_backlight; | 830 | result = eeepc_backlight_init(dev); |
831 | if (result) | ||
832 | goto fail_backlight; | ||
833 | } else | ||
834 | printk(EEEPC_INFO "Backlight controlled by ACPI video " | ||
835 | "driver\n"); | ||
836 | |||
831 | result = eeepc_hwmon_init(dev); | 837 | result = eeepc_hwmon_init(dev); |
832 | if (result) | 838 | if (result) |
833 | goto fail_hwmon; | 839 | goto fail_hwmon; |
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c index d2cf0bfe3163..a7dd3e9fb79d 100644 --- a/drivers/misc/fujitsu-laptop.c +++ b/drivers/misc/fujitsu-laptop.c | |||
@@ -464,6 +464,14 @@ static int dmi_check_cb_s6410(const struct dmi_system_id *id) | |||
464 | return 0; | 464 | return 0; |
465 | } | 465 | } |
466 | 466 | ||
467 | static int dmi_check_cb_s6420(const struct dmi_system_id *id) | ||
468 | { | ||
469 | dmi_check_cb_common(id); | ||
470 | fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ | ||
471 | fujitsu->keycode2 = KEY_HELP; /* "Mobility Center" */ | ||
472 | return 0; | ||
473 | } | ||
474 | |||
467 | static int dmi_check_cb_p8010(const struct dmi_system_id *id) | 475 | static int dmi_check_cb_p8010(const struct dmi_system_id *id) |
468 | { | 476 | { |
469 | dmi_check_cb_common(id); | 477 | dmi_check_cb_common(id); |
@@ -473,7 +481,7 @@ static int dmi_check_cb_p8010(const struct dmi_system_id *id) | |||
473 | return 0; | 481 | return 0; |
474 | } | 482 | } |
475 | 483 | ||
476 | static struct dmi_system_id __initdata fujitsu_dmi_table[] = { | 484 | static struct dmi_system_id fujitsu_dmi_table[] = { |
477 | { | 485 | { |
478 | .ident = "Fujitsu Siemens S6410", | 486 | .ident = "Fujitsu Siemens S6410", |
479 | .matches = { | 487 | .matches = { |
@@ -482,6 +490,13 @@ static struct dmi_system_id __initdata fujitsu_dmi_table[] = { | |||
482 | }, | 490 | }, |
483 | .callback = dmi_check_cb_s6410}, | 491 | .callback = dmi_check_cb_s6410}, |
484 | { | 492 | { |
493 | .ident = "Fujitsu Siemens S6420", | ||
494 | .matches = { | ||
495 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
496 | DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6420"), | ||
497 | }, | ||
498 | .callback = dmi_check_cb_s6420}, | ||
499 | { | ||
485 | .ident = "Fujitsu LifeBook P8010", | 500 | .ident = "Fujitsu LifeBook P8010", |
486 | .matches = { | 501 | .matches = { |
487 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | 502 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), |
@@ -990,16 +1005,16 @@ static int __init fujitsu_init(void) | |||
990 | 1005 | ||
991 | /* Register backlight stuff */ | 1006 | /* Register backlight stuff */ |
992 | 1007 | ||
993 | fujitsu->bl_device = | 1008 | if (!acpi_video_backlight_support()) { |
994 | backlight_device_register("fujitsu-laptop", NULL, NULL, | 1009 | fujitsu->bl_device = |
995 | &fujitsubl_ops); | 1010 | backlight_device_register("fujitsu-laptop", NULL, NULL, |
996 | if (IS_ERR(fujitsu->bl_device)) | 1011 | &fujitsubl_ops); |
997 | return PTR_ERR(fujitsu->bl_device); | 1012 | if (IS_ERR(fujitsu->bl_device)) |
998 | 1013 | return PTR_ERR(fujitsu->bl_device); | |
999 | max_brightness = fujitsu->max_brightness; | 1014 | max_brightness = fujitsu->max_brightness; |
1000 | 1015 | fujitsu->bl_device->props.max_brightness = max_brightness - 1; | |
1001 | fujitsu->bl_device->props.max_brightness = max_brightness - 1; | 1016 | fujitsu->bl_device->props.brightness = fujitsu->brightness_level; |
1002 | fujitsu->bl_device->props.brightness = fujitsu->brightness_level; | 1017 | } |
1003 | 1018 | ||
1004 | ret = platform_driver_register(&fujitsupf_driver); | 1019 | ret = platform_driver_register(&fujitsupf_driver); |
1005 | if (ret) | 1020 | if (ret) |
@@ -1035,7 +1050,8 @@ fail_hotkey: | |||
1035 | 1050 | ||
1036 | fail_backlight: | 1051 | fail_backlight: |
1037 | 1052 | ||
1038 | backlight_device_unregister(fujitsu->bl_device); | 1053 | if (fujitsu->bl_device) |
1054 | backlight_device_unregister(fujitsu->bl_device); | ||
1039 | 1055 | ||
1040 | fail_platform_device2: | 1056 | fail_platform_device2: |
1041 | 1057 | ||
@@ -1062,7 +1078,8 @@ static void __exit fujitsu_cleanup(void) | |||
1062 | &fujitsupf_attribute_group); | 1078 | &fujitsupf_attribute_group); |
1063 | platform_device_unregister(fujitsu->pf_device); | 1079 | platform_device_unregister(fujitsu->pf_device); |
1064 | platform_driver_unregister(&fujitsupf_driver); | 1080 | platform_driver_unregister(&fujitsupf_driver); |
1065 | backlight_device_unregister(fujitsu->bl_device); | 1081 | if (fujitsu->bl_device) |
1082 | backlight_device_unregister(fujitsu->bl_device); | ||
1066 | 1083 | ||
1067 | acpi_bus_unregister_driver(&acpi_fujitsu_driver); | 1084 | acpi_bus_unregister_driver(&acpi_fujitsu_driver); |
1068 | 1085 | ||
diff --git a/drivers/misc/ics932s401.c b/drivers/misc/ics932s401.c new file mode 100644 index 000000000000..6e43ab4231ae --- /dev/null +++ b/drivers/misc/ics932s401.c | |||
@@ -0,0 +1,515 @@ | |||
1 | /* | ||
2 | * A driver for the Integrated Circuits ICS932S401 | ||
3 | * Copyright (C) 2008 IBM | ||
4 | * | ||
5 | * Author: Darrick J. Wong <djwong@us.ibm.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/jiffies.h> | ||
24 | #include <linux/i2c.h> | ||
25 | #include <linux/err.h> | ||
26 | #include <linux/mutex.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/log2.h> | ||
29 | |||
30 | /* Addresses to scan */ | ||
31 | static const unsigned short normal_i2c[] = { 0x69, I2C_CLIENT_END }; | ||
32 | |||
33 | /* Insmod parameters */ | ||
34 | I2C_CLIENT_INSMOD_1(ics932s401); | ||
35 | |||
36 | /* ICS932S401 registers */ | ||
37 | #define ICS932S401_REG_CFG2 0x01 | ||
38 | #define ICS932S401_CFG1_SPREAD 0x01 | ||
39 | #define ICS932S401_REG_CFG7 0x06 | ||
40 | #define ICS932S401_FS_MASK 0x07 | ||
41 | #define ICS932S401_REG_VENDOR_REV 0x07 | ||
42 | #define ICS932S401_VENDOR 1 | ||
43 | #define ICS932S401_VENDOR_MASK 0x0F | ||
44 | #define ICS932S401_REV 4 | ||
45 | #define ICS932S401_REV_SHIFT 4 | ||
46 | #define ICS932S401_REG_DEVICE 0x09 | ||
47 | #define ICS932S401_DEVICE 11 | ||
48 | #define ICS932S401_REG_CTRL 0x0A | ||
49 | #define ICS932S401_MN_ENABLED 0x80 | ||
50 | #define ICS932S401_CPU_ALT 0x04 | ||
51 | #define ICS932S401_SRC_ALT 0x08 | ||
52 | #define ICS932S401_REG_CPU_M_CTRL 0x0B | ||
53 | #define ICS932S401_M_MASK 0x3F | ||
54 | #define ICS932S401_REG_CPU_N_CTRL 0x0C | ||
55 | #define ICS932S401_REG_CPU_SPREAD1 0x0D | ||
56 | #define ICS932S401_REG_CPU_SPREAD2 0x0E | ||
57 | #define ICS932S401_SPREAD_MASK 0x7FFF | ||
58 | #define ICS932S401_REG_SRC_M_CTRL 0x0F | ||
59 | #define ICS932S401_REG_SRC_N_CTRL 0x10 | ||
60 | #define ICS932S401_REG_SRC_SPREAD1 0x11 | ||
61 | #define ICS932S401_REG_SRC_SPREAD2 0x12 | ||
62 | #define ICS932S401_REG_CPU_DIVISOR 0x13 | ||
63 | #define ICS932S401_CPU_DIVISOR_SHIFT 4 | ||
64 | #define ICS932S401_REG_PCISRC_DIVISOR 0x14 | ||
65 | #define ICS932S401_SRC_DIVISOR_MASK 0x0F | ||
66 | #define ICS932S401_PCI_DIVISOR_SHIFT 4 | ||
67 | |||
68 | /* Base clock is 14.318MHz */ | ||
69 | #define BASE_CLOCK 14318 | ||
70 | |||
71 | #define NUM_REGS 21 | ||
72 | #define NUM_MIRRORED_REGS 15 | ||
73 | |||
74 | static int regs_to_copy[NUM_MIRRORED_REGS] = { | ||
75 | ICS932S401_REG_CFG2, | ||
76 | ICS932S401_REG_CFG7, | ||
77 | ICS932S401_REG_VENDOR_REV, | ||
78 | ICS932S401_REG_DEVICE, | ||
79 | ICS932S401_REG_CTRL, | ||
80 | ICS932S401_REG_CPU_M_CTRL, | ||
81 | ICS932S401_REG_CPU_N_CTRL, | ||
82 | ICS932S401_REG_CPU_SPREAD1, | ||
83 | ICS932S401_REG_CPU_SPREAD2, | ||
84 | ICS932S401_REG_SRC_M_CTRL, | ||
85 | ICS932S401_REG_SRC_N_CTRL, | ||
86 | ICS932S401_REG_SRC_SPREAD1, | ||
87 | ICS932S401_REG_SRC_SPREAD2, | ||
88 | ICS932S401_REG_CPU_DIVISOR, | ||
89 | ICS932S401_REG_PCISRC_DIVISOR, | ||
90 | }; | ||
91 | |||
92 | /* How often do we reread sensors values? (In jiffies) */ | ||
93 | #define SENSOR_REFRESH_INTERVAL (2 * HZ) | ||
94 | |||
95 | /* How often do we reread sensor limit values? (In jiffies) */ | ||
96 | #define LIMIT_REFRESH_INTERVAL (60 * HZ) | ||
97 | |||
98 | struct ics932s401_data { | ||
99 | struct attribute_group attrs; | ||
100 | struct mutex lock; | ||
101 | char sensors_valid; | ||
102 | unsigned long sensors_last_updated; /* In jiffies */ | ||
103 | |||
104 | u8 regs[NUM_REGS]; | ||
105 | }; | ||
106 | |||
107 | static int ics932s401_probe(struct i2c_client *client, | ||
108 | const struct i2c_device_id *id); | ||
109 | static int ics932s401_detect(struct i2c_client *client, int kind, | ||
110 | struct i2c_board_info *info); | ||
111 | static int ics932s401_remove(struct i2c_client *client); | ||
112 | |||
113 | static const struct i2c_device_id ics932s401_id[] = { | ||
114 | { "ics932s401", ics932s401 }, | ||
115 | { } | ||
116 | }; | ||
117 | MODULE_DEVICE_TABLE(i2c, ics932s401_id); | ||
118 | |||
119 | static struct i2c_driver ics932s401_driver = { | ||
120 | .class = I2C_CLASS_HWMON, | ||
121 | .driver = { | ||
122 | .name = "ics932s401", | ||
123 | }, | ||
124 | .probe = ics932s401_probe, | ||
125 | .remove = ics932s401_remove, | ||
126 | .id_table = ics932s401_id, | ||
127 | .detect = ics932s401_detect, | ||
128 | .address_data = &addr_data, | ||
129 | }; | ||
130 | |||
131 | static struct ics932s401_data *ics932s401_update_device(struct device *dev) | ||
132 | { | ||
133 | struct i2c_client *client = to_i2c_client(dev); | ||
134 | struct ics932s401_data *data = i2c_get_clientdata(client); | ||
135 | unsigned long local_jiffies = jiffies; | ||
136 | int i, temp; | ||
137 | |||
138 | mutex_lock(&data->lock); | ||
139 | if (time_before(local_jiffies, data->sensors_last_updated + | ||
140 | SENSOR_REFRESH_INTERVAL) | ||
141 | && data->sensors_valid) | ||
142 | goto out; | ||
143 | |||
144 | /* | ||
145 | * Each register must be read as a word and then right shifted 8 bits. | ||
146 | * Not really sure why this is; setting the "byte count programming" | ||
147 | * register to 1 does not fix this problem. | ||
148 | */ | ||
149 | for (i = 0; i < NUM_MIRRORED_REGS; i++) { | ||
150 | temp = i2c_smbus_read_word_data(client, regs_to_copy[i]); | ||
151 | data->regs[regs_to_copy[i]] = temp >> 8; | ||
152 | } | ||
153 | |||
154 | data->sensors_last_updated = local_jiffies; | ||
155 | data->sensors_valid = 1; | ||
156 | |||
157 | out: | ||
158 | mutex_unlock(&data->lock); | ||
159 | return data; | ||
160 | } | ||
161 | |||
162 | static ssize_t show_spread_enabled(struct device *dev, | ||
163 | struct device_attribute *devattr, | ||
164 | char *buf) | ||
165 | { | ||
166 | struct ics932s401_data *data = ics932s401_update_device(dev); | ||
167 | |||
168 | if (data->regs[ICS932S401_REG_CFG2] & ICS932S401_CFG1_SPREAD) | ||
169 | return sprintf(buf, "1\n"); | ||
170 | |||
171 | return sprintf(buf, "0\n"); | ||
172 | } | ||
173 | |||
174 | /* bit to cpu khz map */ | ||
175 | static const int fs_speeds[] = { | ||
176 | 266666, | ||
177 | 133333, | ||
178 | 200000, | ||
179 | 166666, | ||
180 | 333333, | ||
181 | 100000, | ||
182 | 400000, | ||
183 | 0, | ||
184 | }; | ||
185 | |||
186 | /* clock divisor map */ | ||
187 | static const int divisors[] = {2, 3, 5, 15, 4, 6, 10, 30, 8, 12, 20, 60, 16, | ||
188 | 24, 40, 120}; | ||
189 | |||
190 | /* Calculate CPU frequency from the M/N registers. */ | ||
191 | static int calculate_cpu_freq(struct ics932s401_data *data) | ||
192 | { | ||
193 | int m, n, freq; | ||
194 | |||
195 | m = data->regs[ICS932S401_REG_CPU_M_CTRL] & ICS932S401_M_MASK; | ||
196 | n = data->regs[ICS932S401_REG_CPU_N_CTRL]; | ||
197 | |||
198 | /* Pull in bits 8 & 9 from the M register */ | ||
199 | n |= ((int)data->regs[ICS932S401_REG_CPU_M_CTRL] & 0x80) << 1; | ||
200 | n |= ((int)data->regs[ICS932S401_REG_CPU_M_CTRL] & 0x40) << 3; | ||
201 | |||
202 | freq = BASE_CLOCK * (n + 8) / (m + 2); | ||
203 | freq /= divisors[data->regs[ICS932S401_REG_CPU_DIVISOR] >> | ||
204 | ICS932S401_CPU_DIVISOR_SHIFT]; | ||
205 | |||
206 | return freq; | ||
207 | } | ||
208 | |||
209 | static ssize_t show_cpu_clock(struct device *dev, | ||
210 | struct device_attribute *devattr, | ||
211 | char *buf) | ||
212 | { | ||
213 | struct ics932s401_data *data = ics932s401_update_device(dev); | ||
214 | |||
215 | return sprintf(buf, "%d\n", calculate_cpu_freq(data)); | ||
216 | } | ||
217 | |||
218 | static ssize_t show_cpu_clock_sel(struct device *dev, | ||
219 | struct device_attribute *devattr, | ||
220 | char *buf) | ||
221 | { | ||
222 | struct ics932s401_data *data = ics932s401_update_device(dev); | ||
223 | int freq; | ||
224 | |||
225 | if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_MN_ENABLED) | ||
226 | freq = calculate_cpu_freq(data); | ||
227 | else { | ||
228 | /* Freq is neatly wrapped up for us */ | ||
229 | int fid = data->regs[ICS932S401_REG_CFG7] & ICS932S401_FS_MASK; | ||
230 | freq = fs_speeds[fid]; | ||
231 | if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_CPU_ALT) { | ||
232 | switch (freq) { | ||
233 | case 166666: | ||
234 | freq = 160000; | ||
235 | break; | ||
236 | case 333333: | ||
237 | freq = 320000; | ||
238 | break; | ||
239 | } | ||
240 | } | ||
241 | } | ||
242 | |||
243 | return sprintf(buf, "%d\n", freq); | ||
244 | } | ||
245 | |||
246 | /* Calculate SRC frequency from the M/N registers. */ | ||
247 | static int calculate_src_freq(struct ics932s401_data *data) | ||
248 | { | ||
249 | int m, n, freq; | ||
250 | |||
251 | m = data->regs[ICS932S401_REG_SRC_M_CTRL] & ICS932S401_M_MASK; | ||
252 | n = data->regs[ICS932S401_REG_SRC_N_CTRL]; | ||
253 | |||
254 | /* Pull in bits 8 & 9 from the M register */ | ||
255 | n |= ((int)data->regs[ICS932S401_REG_SRC_M_CTRL] & 0x80) << 1; | ||
256 | n |= ((int)data->regs[ICS932S401_REG_SRC_M_CTRL] & 0x40) << 3; | ||
257 | |||
258 | freq = BASE_CLOCK * (n + 8) / (m + 2); | ||
259 | freq /= divisors[data->regs[ICS932S401_REG_PCISRC_DIVISOR] & | ||
260 | ICS932S401_SRC_DIVISOR_MASK]; | ||
261 | |||
262 | return freq; | ||
263 | } | ||
264 | |||
265 | static ssize_t show_src_clock(struct device *dev, | ||
266 | struct device_attribute *devattr, | ||
267 | char *buf) | ||
268 | { | ||
269 | struct ics932s401_data *data = ics932s401_update_device(dev); | ||
270 | |||
271 | return sprintf(buf, "%d\n", calculate_src_freq(data)); | ||
272 | } | ||
273 | |||
274 | static ssize_t show_src_clock_sel(struct device *dev, | ||
275 | struct device_attribute *devattr, | ||
276 | char *buf) | ||
277 | { | ||
278 | struct ics932s401_data *data = ics932s401_update_device(dev); | ||
279 | int freq; | ||
280 | |||
281 | if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_MN_ENABLED) | ||
282 | freq = calculate_src_freq(data); | ||
283 | else | ||
284 | /* Freq is neatly wrapped up for us */ | ||
285 | if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_CPU_ALT && | ||
286 | data->regs[ICS932S401_REG_CTRL] & ICS932S401_SRC_ALT) | ||
287 | freq = 96000; | ||
288 | else | ||
289 | freq = 100000; | ||
290 | |||
291 | return sprintf(buf, "%d\n", freq); | ||
292 | } | ||
293 | |||
294 | /* Calculate PCI frequency from the SRC M/N registers. */ | ||
295 | static int calculate_pci_freq(struct ics932s401_data *data) | ||
296 | { | ||
297 | int m, n, freq; | ||
298 | |||
299 | m = data->regs[ICS932S401_REG_SRC_M_CTRL] & ICS932S401_M_MASK; | ||
300 | n = data->regs[ICS932S401_REG_SRC_N_CTRL]; | ||
301 | |||
302 | /* Pull in bits 8 & 9 from the M register */ | ||
303 | n |= ((int)data->regs[ICS932S401_REG_SRC_M_CTRL] & 0x80) << 1; | ||
304 | n |= ((int)data->regs[ICS932S401_REG_SRC_M_CTRL] & 0x40) << 3; | ||
305 | |||
306 | freq = BASE_CLOCK * (n + 8) / (m + 2); | ||
307 | freq /= divisors[data->regs[ICS932S401_REG_PCISRC_DIVISOR] >> | ||
308 | ICS932S401_PCI_DIVISOR_SHIFT]; | ||
309 | |||
310 | return freq; | ||
311 | } | ||
312 | |||
313 | static ssize_t show_pci_clock(struct device *dev, | ||
314 | struct device_attribute *devattr, | ||
315 | char *buf) | ||
316 | { | ||
317 | struct ics932s401_data *data = ics932s401_update_device(dev); | ||
318 | |||
319 | return sprintf(buf, "%d\n", calculate_pci_freq(data)); | ||
320 | } | ||
321 | |||
322 | static ssize_t show_pci_clock_sel(struct device *dev, | ||
323 | struct device_attribute *devattr, | ||
324 | char *buf) | ||
325 | { | ||
326 | struct ics932s401_data *data = ics932s401_update_device(dev); | ||
327 | int freq; | ||
328 | |||
329 | if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_MN_ENABLED) | ||
330 | freq = calculate_pci_freq(data); | ||
331 | else | ||
332 | freq = 33333; | ||
333 | |||
334 | return sprintf(buf, "%d\n", freq); | ||
335 | } | ||
336 | |||
337 | static ssize_t show_value(struct device *dev, | ||
338 | struct device_attribute *devattr, | ||
339 | char *buf); | ||
340 | |||
341 | static ssize_t show_spread(struct device *dev, | ||
342 | struct device_attribute *devattr, | ||
343 | char *buf); | ||
344 | |||
345 | static DEVICE_ATTR(spread_enabled, S_IRUGO, show_spread_enabled, NULL); | ||
346 | static DEVICE_ATTR(cpu_clock_selection, S_IRUGO, show_cpu_clock_sel, NULL); | ||
347 | static DEVICE_ATTR(cpu_clock, S_IRUGO, show_cpu_clock, NULL); | ||
348 | static DEVICE_ATTR(src_clock_selection, S_IRUGO, show_src_clock_sel, NULL); | ||
349 | static DEVICE_ATTR(src_clock, S_IRUGO, show_src_clock, NULL); | ||
350 | static DEVICE_ATTR(pci_clock_selection, S_IRUGO, show_pci_clock_sel, NULL); | ||
351 | static DEVICE_ATTR(pci_clock, S_IRUGO, show_pci_clock, NULL); | ||
352 | static DEVICE_ATTR(usb_clock, S_IRUGO, show_value, NULL); | ||
353 | static DEVICE_ATTR(ref_clock, S_IRUGO, show_value, NULL); | ||
354 | static DEVICE_ATTR(cpu_spread, S_IRUGO, show_spread, NULL); | ||
355 | static DEVICE_ATTR(src_spread, S_IRUGO, show_spread, NULL); | ||
356 | |||
357 | static struct attribute *ics932s401_attr[] = | ||
358 | { | ||
359 | &dev_attr_spread_enabled.attr, | ||
360 | &dev_attr_cpu_clock_selection.attr, | ||
361 | &dev_attr_cpu_clock.attr, | ||
362 | &dev_attr_src_clock_selection.attr, | ||
363 | &dev_attr_src_clock.attr, | ||
364 | &dev_attr_pci_clock_selection.attr, | ||
365 | &dev_attr_pci_clock.attr, | ||
366 | &dev_attr_usb_clock.attr, | ||
367 | &dev_attr_ref_clock.attr, | ||
368 | &dev_attr_cpu_spread.attr, | ||
369 | &dev_attr_src_spread.attr, | ||
370 | NULL | ||
371 | }; | ||
372 | |||
373 | static ssize_t show_value(struct device *dev, | ||
374 | struct device_attribute *devattr, | ||
375 | char *buf) | ||
376 | { | ||
377 | int x; | ||
378 | |||
379 | if (devattr == &dev_attr_usb_clock) | ||
380 | x = 48000; | ||
381 | else if (devattr == &dev_attr_ref_clock) | ||
382 | x = BASE_CLOCK; | ||
383 | else | ||
384 | BUG(); | ||
385 | |||
386 | return sprintf(buf, "%d\n", x); | ||
387 | } | ||
388 | |||
389 | static ssize_t show_spread(struct device *dev, | ||
390 | struct device_attribute *devattr, | ||
391 | char *buf) | ||
392 | { | ||
393 | struct ics932s401_data *data = ics932s401_update_device(dev); | ||
394 | int reg; | ||
395 | unsigned long val; | ||
396 | |||
397 | if (!(data->regs[ICS932S401_REG_CFG2] & ICS932S401_CFG1_SPREAD)) | ||
398 | return sprintf(buf, "0%%\n"); | ||
399 | |||
400 | if (devattr == &dev_attr_src_spread) | ||
401 | reg = ICS932S401_REG_SRC_SPREAD1; | ||
402 | else if (devattr == &dev_attr_cpu_spread) | ||
403 | reg = ICS932S401_REG_CPU_SPREAD1; | ||
404 | else | ||
405 | BUG(); | ||
406 | |||
407 | val = data->regs[reg] | (data->regs[reg + 1] << 8); | ||
408 | val &= ICS932S401_SPREAD_MASK; | ||
409 | |||
410 | /* Scale 0..2^14 to -0.5. */ | ||
411 | val = 500000 * val / 16384; | ||
412 | return sprintf(buf, "-0.%lu%%\n", val); | ||
413 | } | ||
414 | |||
415 | /* Return 0 if detection is successful, -ENODEV otherwise */ | ||
416 | static int ics932s401_detect(struct i2c_client *client, int kind, | ||
417 | struct i2c_board_info *info) | ||
418 | { | ||
419 | struct i2c_adapter *adapter = client->adapter; | ||
420 | |||
421 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
422 | return -ENODEV; | ||
423 | |||
424 | if (kind <= 0) { | ||
425 | int vendor, device, revision; | ||
426 | |||
427 | vendor = i2c_smbus_read_word_data(client, | ||
428 | ICS932S401_REG_VENDOR_REV); | ||
429 | vendor >>= 8; | ||
430 | revision = vendor >> ICS932S401_REV_SHIFT; | ||
431 | vendor &= ICS932S401_VENDOR_MASK; | ||
432 | if (vendor != ICS932S401_VENDOR) | ||
433 | return -ENODEV; | ||
434 | |||
435 | device = i2c_smbus_read_word_data(client, | ||
436 | ICS932S401_REG_DEVICE); | ||
437 | device >>= 8; | ||
438 | if (device != ICS932S401_DEVICE) | ||
439 | return -ENODEV; | ||
440 | |||
441 | if (revision != ICS932S401_REV) | ||
442 | dev_info(&adapter->dev, "Unknown revision %d\n", | ||
443 | revision); | ||
444 | } else | ||
445 | dev_dbg(&adapter->dev, "detection forced\n"); | ||
446 | |||
447 | strlcpy(info->type, "ics932s401", I2C_NAME_SIZE); | ||
448 | |||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | static int ics932s401_probe(struct i2c_client *client, | ||
453 | const struct i2c_device_id *id) | ||
454 | { | ||
455 | struct ics932s401_data *data; | ||
456 | int err; | ||
457 | |||
458 | data = kzalloc(sizeof(struct ics932s401_data), GFP_KERNEL); | ||
459 | if (!data) { | ||
460 | err = -ENOMEM; | ||
461 | goto exit; | ||
462 | } | ||
463 | |||
464 | i2c_set_clientdata(client, data); | ||
465 | mutex_init(&data->lock); | ||
466 | |||
467 | dev_info(&client->dev, "%s chip found\n", client->name); | ||
468 | |||
469 | /* Register sysfs hooks */ | ||
470 | data->attrs.attrs = ics932s401_attr; | ||
471 | err = sysfs_create_group(&client->dev.kobj, &data->attrs); | ||
472 | if (err) | ||
473 | goto exit_free; | ||
474 | |||
475 | return 0; | ||
476 | |||
477 | exit_free: | ||
478 | kfree(data); | ||
479 | exit: | ||
480 | return err; | ||
481 | } | ||
482 | |||
483 | static int ics932s401_remove(struct i2c_client *client) | ||
484 | { | ||
485 | struct ics932s401_data *data = i2c_get_clientdata(client); | ||
486 | |||
487 | sysfs_remove_group(&client->dev.kobj, &data->attrs); | ||
488 | kfree(data); | ||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | static int __init ics932s401_init(void) | ||
493 | { | ||
494 | return i2c_add_driver(&ics932s401_driver); | ||
495 | } | ||
496 | |||
497 | static void __exit ics932s401_exit(void) | ||
498 | { | ||
499 | i2c_del_driver(&ics932s401_driver); | ||
500 | } | ||
501 | |||
502 | MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>"); | ||
503 | MODULE_DESCRIPTION("ICS932S401 driver"); | ||
504 | MODULE_LICENSE("GPL"); | ||
505 | |||
506 | module_init(ics932s401_init); | ||
507 | module_exit(ics932s401_exit); | ||
508 | |||
509 | /* IBM IntelliStation Z30 */ | ||
510 | MODULE_ALIAS("dmi:bvnIBM:*:rn9228:*"); | ||
511 | MODULE_ALIAS("dmi:bvnIBM:*:rn9232:*"); | ||
512 | |||
513 | /* IBM x3650/x3550 */ | ||
514 | MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3650*"); | ||
515 | MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3550*"); | ||
diff --git a/drivers/misc/intel_menlow.c b/drivers/misc/intel_menlow.c index e00a2756e97e..27b7662955bb 100644 --- a/drivers/misc/intel_menlow.c +++ b/drivers/misc/intel_menlow.c | |||
@@ -52,6 +52,11 @@ MODULE_LICENSE("GPL"); | |||
52 | #define MEMORY_ARG_CUR_BANDWIDTH 1 | 52 | #define MEMORY_ARG_CUR_BANDWIDTH 1 |
53 | #define MEMORY_ARG_MAX_BANDWIDTH 0 | 53 | #define MEMORY_ARG_MAX_BANDWIDTH 0 |
54 | 54 | ||
55 | /* | ||
56 | * GTHS returning 'n' would mean that [0,n-1] states are supported | ||
57 | * In that case max_cstate would be n-1 | ||
58 | * GTHS returning '0' would mean that no bandwidth control states are supported | ||
59 | */ | ||
55 | static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev, | 60 | static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev, |
56 | unsigned long *max_state) | 61 | unsigned long *max_state) |
57 | { | 62 | { |
@@ -71,6 +76,9 @@ static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev, | |||
71 | if (ACPI_FAILURE(status)) | 76 | if (ACPI_FAILURE(status)) |
72 | return -EFAULT; | 77 | return -EFAULT; |
73 | 78 | ||
79 | if (!value) | ||
80 | return -EINVAL; | ||
81 | |||
74 | *max_state = value - 1; | 82 | *max_state = value - 1; |
75 | return 0; | 83 | return 0; |
76 | } | 84 | } |
@@ -121,7 +129,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev, | |||
121 | if (memory_get_int_max_bandwidth(cdev, &max_state)) | 129 | if (memory_get_int_max_bandwidth(cdev, &max_state)) |
122 | return -EFAULT; | 130 | return -EFAULT; |
123 | 131 | ||
124 | if (max_state < 0 || state > max_state) | 132 | if (state > max_state) |
125 | return -EINVAL; | 133 | return -EINVAL; |
126 | 134 | ||
127 | arg_list.count = 1; | 135 | arg_list.count = 1; |
diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c index de898c6938f3..759763d18e4c 100644 --- a/drivers/misc/msi-laptop.c +++ b/drivers/misc/msi-laptop.c | |||
@@ -347,12 +347,16 @@ static int __init msi_init(void) | |||
347 | 347 | ||
348 | /* Register backlight stuff */ | 348 | /* Register backlight stuff */ |
349 | 349 | ||
350 | msibl_device = backlight_device_register("msi-laptop-bl", NULL, NULL, | 350 | if (acpi_video_backlight_support()) { |
351 | &msibl_ops); | 351 | printk(KERN_INFO "MSI: Brightness ignored, must be controlled " |
352 | if (IS_ERR(msibl_device)) | 352 | "by ACPI video driver\n"); |
353 | return PTR_ERR(msibl_device); | 353 | } else { |
354 | 354 | msibl_device = backlight_device_register("msi-laptop-bl", NULL, | |
355 | msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1; | 355 | NULL, &msibl_ops); |
356 | if (IS_ERR(msibl_device)) | ||
357 | return PTR_ERR(msibl_device); | ||
358 | msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1; | ||
359 | } | ||
356 | 360 | ||
357 | ret = platform_driver_register(&msipf_driver); | 361 | ret = platform_driver_register(&msipf_driver); |
358 | if (ret) | 362 | if (ret) |
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index 06f07e19dc70..7bcb81002dcf 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c | |||
@@ -1038,7 +1038,11 @@ static int sony_nc_add(struct acpi_device *device) | |||
1038 | goto outinput; | 1038 | goto outinput; |
1039 | } | 1039 | } |
1040 | 1040 | ||
1041 | if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", &handle))) { | 1041 | if (!acpi_video_backlight_support()) { |
1042 | printk(KERN_INFO DRV_PFX "Sony: Brightness ignored, must be " | ||
1043 | "controlled by ACPI video driver\n"); | ||
1044 | } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", | ||
1045 | &handle))) { | ||
1042 | sony_backlight_device = backlight_device_register("sony", NULL, | 1046 | sony_backlight_device = backlight_device_register("sony", NULL, |
1043 | NULL, | 1047 | NULL, |
1044 | &sony_backlight_ops); | 1048 | &sony_backlight_ops); |
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 4db1cf9078d9..7a4a26b0edd2 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
@@ -4932,16 +4932,25 @@ static int __init brightness_init(struct ibm_init_struct *iibm) | |||
4932 | */ | 4932 | */ |
4933 | b = tpacpi_check_std_acpi_brightness_support(); | 4933 | b = tpacpi_check_std_acpi_brightness_support(); |
4934 | if (b > 0) { | 4934 | if (b > 0) { |
4935 | if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { | 4935 | |
4936 | printk(TPACPI_NOTICE | 4936 | if (acpi_video_backlight_support()) { |
4937 | "Lenovo BIOS switched to ACPI backlight " | 4937 | if (brightness_enable > 1) { |
4938 | "control mode\n"); | 4938 | printk(TPACPI_NOTICE |
4939 | } | 4939 | "Standard ACPI backlight interface " |
4940 | if (brightness_enable > 1) { | 4940 | "available, not loading native one.\n"); |
4941 | printk(TPACPI_NOTICE | 4941 | return 1; |
4942 | "standard ACPI backlight interface " | 4942 | } else if (brightness_enable == 1) { |
4943 | "available, not loading native one...\n"); | 4943 | printk(TPACPI_NOTICE |
4944 | return 1; | 4944 | "Backlight control force enabled, even if standard " |
4945 | "ACPI backlight interface is available\n"); | ||
4946 | } | ||
4947 | } else { | ||
4948 | if (brightness_enable > 1) { | ||
4949 | printk(TPACPI_NOTICE | ||
4950 | "Standard ACPI backlight interface not " | ||
4951 | "available, thinkpad_acpi native " | ||
4952 | "brightness control enabled\n"); | ||
4953 | } | ||
4945 | } | 4954 | } |
4946 | } | 4955 | } |
4947 | 4956 | ||
diff --git a/drivers/mtd/maps/cdb89712.c b/drivers/mtd/maps/cdb89712.c index e5059aa3c724..8d92d8db9a98 100644 --- a/drivers/mtd/maps/cdb89712.c +++ b/drivers/mtd/maps/cdb89712.c | |||
@@ -14,7 +14,18 @@ | |||
14 | #include <linux/mtd/map.h> | 14 | #include <linux/mtd/map.h> |
15 | #include <linux/mtd/partitions.h> | 15 | #include <linux/mtd/partitions.h> |
16 | 16 | ||
17 | 17 | /* dynamic ioremap() areas */ | |
18 | #define FLASH_START 0x00000000 | ||
19 | #define FLASH_SIZE 0x800000 | ||
20 | #define FLASH_WIDTH 4 | ||
21 | |||
22 | #define SRAM_START 0x60000000 | ||
23 | #define SRAM_SIZE 0xc000 | ||
24 | #define SRAM_WIDTH 4 | ||
25 | |||
26 | #define BOOTROM_START 0x70000000 | ||
27 | #define BOOTROM_SIZE 0x80 | ||
28 | #define BOOTROM_WIDTH 4 | ||
18 | 29 | ||
19 | 30 | ||
20 | static struct mtd_info *flash_mtd; | 31 | static struct mtd_info *flash_mtd; |
diff --git a/drivers/mtd/maps/h720x-flash.c b/drivers/mtd/maps/h720x-flash.c index 35fef655ccc4..3b959fad1c4e 100644 --- a/drivers/mtd/maps/h720x-flash.c +++ b/drivers/mtd/maps/h720x-flash.c | |||
@@ -24,8 +24,8 @@ static struct mtd_info *mymtd; | |||
24 | static struct map_info h720x_map = { | 24 | static struct map_info h720x_map = { |
25 | .name = "H720X", | 25 | .name = "H720X", |
26 | .bankwidth = 4, | 26 | .bankwidth = 4, |
27 | .size = FLASH_SIZE, | 27 | .size = H720X_FLASH_SIZE, |
28 | .phys = FLASH_PHYS, | 28 | .phys = H720X_FLASH_PHYS, |
29 | }; | 29 | }; |
30 | 30 | ||
31 | static struct mtd_partition h720x_partitions[] = { | 31 | static struct mtd_partition h720x_partitions[] = { |
@@ -70,7 +70,7 @@ int __init h720x_mtd_init(void) | |||
70 | 70 | ||
71 | char *part_type = NULL; | 71 | char *part_type = NULL; |
72 | 72 | ||
73 | h720x_map.virt = ioremap(FLASH_PHYS, FLASH_SIZE); | 73 | h720x_map.virt = ioremap(h720x_map.phys, h720x_map.size); |
74 | 74 | ||
75 | if (!h720x_map.virt) { | 75 | if (!h720x_map.virt) { |
76 | printk(KERN_ERR "H720x-MTD: ioremap failed\n"); | 76 | printk(KERN_ERR "H720x-MTD: ioremap failed\n"); |
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 430d430bce29..d07e3f148951 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
@@ -7204,10 +7204,13 @@ static void | |||
7204 | poll_bnx2(struct net_device *dev) | 7204 | poll_bnx2(struct net_device *dev) |
7205 | { | 7205 | { |
7206 | struct bnx2 *bp = netdev_priv(dev); | 7206 | struct bnx2 *bp = netdev_priv(dev); |
7207 | int i; | ||
7207 | 7208 | ||
7208 | disable_irq(bp->pdev->irq); | 7209 | for (i = 0; i < bp->irq_nvecs; i++) { |
7209 | bnx2_interrupt(bp->pdev->irq, dev); | 7210 | disable_irq(bp->irq_tbl[i].vector); |
7210 | enable_irq(bp->pdev->irq); | 7211 | bnx2_interrupt(bp->irq_tbl[i].vector, &bp->bnx2_napi[i]); |
7212 | enable_irq(bp->irq_tbl[i].vector); | ||
7213 | } | ||
7211 | } | 7214 | } |
7212 | #endif | 7215 | #endif |
7213 | 7216 | ||
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 1ace41a13ac3..2c341f83d327 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c | |||
@@ -1307,8 +1307,10 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) | |||
1307 | u32 fw_vers = 0; | 1307 | u32 fw_vers = 0; |
1308 | u32 tp_vers = 0; | 1308 | u32 tp_vers = 0; |
1309 | 1309 | ||
1310 | spin_lock(&adapter->stats_lock); | ||
1310 | t3_get_fw_version(adapter, &fw_vers); | 1311 | t3_get_fw_version(adapter, &fw_vers); |
1311 | t3_get_tp_version(adapter, &tp_vers); | 1312 | t3_get_tp_version(adapter, &tp_vers); |
1313 | spin_unlock(&adapter->stats_lock); | ||
1312 | 1314 | ||
1313 | strcpy(info->driver, DRV_NAME); | 1315 | strcpy(info->driver, DRV_NAME); |
1314 | strcpy(info->version, DRV_VERSION); | 1316 | strcpy(info->version, DRV_VERSION); |
@@ -2699,7 +2701,7 @@ static void set_nqsets(struct adapter *adap) | |||
2699 | int hwports = adap->params.nports; | 2701 | int hwports = adap->params.nports; |
2700 | int nqsets = SGE_QSETS; | 2702 | int nqsets = SGE_QSETS; |
2701 | 2703 | ||
2702 | if (adap->params.rev > 0) { | 2704 | if (adap->params.rev > 0 && adap->flags & USING_MSIX) { |
2703 | if (hwports == 2 && | 2705 | if (hwports == 2 && |
2704 | (hwports * nqsets > SGE_QSETS || | 2706 | (hwports * nqsets > SGE_QSETS || |
2705 | num_cpus >= nqsets / hwports)) | 2707 | num_cpus >= nqsets / hwports)) |
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index 968f64be3743..9a0898b0dbce 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c | |||
@@ -572,7 +572,7 @@ struct t3_vpd { | |||
572 | u32 pad; /* for multiple-of-4 sizing and alignment */ | 572 | u32 pad; /* for multiple-of-4 sizing and alignment */ |
573 | }; | 573 | }; |
574 | 574 | ||
575 | #define EEPROM_MAX_POLL 4 | 575 | #define EEPROM_MAX_POLL 40 |
576 | #define EEPROM_STAT_ADDR 0x4000 | 576 | #define EEPROM_STAT_ADDR 0x4000 |
577 | #define VPD_BASE 0xc00 | 577 | #define VPD_BASE 0xc00 |
578 | 578 | ||
@@ -3690,6 +3690,12 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, | |||
3690 | ; | 3690 | ; |
3691 | 3691 | ||
3692 | pti = &port_types[adapter->params.vpd.port_type[j]]; | 3692 | pti = &port_types[adapter->params.vpd.port_type[j]]; |
3693 | if (!pti->phy_prep) { | ||
3694 | CH_ALERT(adapter, "Invalid port type index %d\n", | ||
3695 | adapter->params.vpd.port_type[j]); | ||
3696 | return -EINVAL; | ||
3697 | } | ||
3698 | |||
3693 | ret = pti->phy_prep(&p->phy, adapter, ai->phy_base_addr + j, | 3699 | ret = pti->phy_prep(&p->phy, adapter, ai->phy_base_addr + j, |
3694 | ai->mdio_ops); | 3700 | ai->mdio_ops); |
3695 | if (ret) | 3701 | if (ret) |
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h index fa431fad0eec..56a2e213fe62 100644 --- a/drivers/net/mlx4/mlx4.h +++ b/drivers/net/mlx4/mlx4.h | |||
@@ -87,6 +87,9 @@ enum { | |||
87 | 87 | ||
88 | #ifdef CONFIG_MLX4_DEBUG | 88 | #ifdef CONFIG_MLX4_DEBUG |
89 | extern int mlx4_debug_level; | 89 | extern int mlx4_debug_level; |
90 | #else /* CONFIG_MLX4_DEBUG */ | ||
91 | #define mlx4_debug_level (0) | ||
92 | #endif /* CONFIG_MLX4_DEBUG */ | ||
90 | 93 | ||
91 | #define mlx4_dbg(mdev, format, arg...) \ | 94 | #define mlx4_dbg(mdev, format, arg...) \ |
92 | do { \ | 95 | do { \ |
@@ -94,12 +97,6 @@ extern int mlx4_debug_level; | |||
94 | dev_printk(KERN_DEBUG, &mdev->pdev->dev, format, ## arg); \ | 97 | dev_printk(KERN_DEBUG, &mdev->pdev->dev, format, ## arg); \ |
95 | } while (0) | 98 | } while (0) |
96 | 99 | ||
97 | #else /* CONFIG_MLX4_DEBUG */ | ||
98 | |||
99 | #define mlx4_dbg(mdev, format, arg...) do { (void) mdev; } while (0) | ||
100 | |||
101 | #endif /* CONFIG_MLX4_DEBUG */ | ||
102 | |||
103 | #define mlx4_err(mdev, format, arg...) \ | 100 | #define mlx4_err(mdev, format, arg...) \ |
104 | dev_err(&mdev->pdev->dev, format, ## arg) | 101 | dev_err(&mdev->pdev->dev, format, ## arg) |
105 | #define mlx4_info(mdev, format, arg...) \ | 102 | #define mlx4_info(mdev, format, arg...) \ |
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index a5f428bcc0eb..b37867097308 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
@@ -75,7 +75,7 @@ | |||
75 | #include "myri10ge_mcp.h" | 75 | #include "myri10ge_mcp.h" |
76 | #include "myri10ge_mcp_gen_header.h" | 76 | #include "myri10ge_mcp_gen_header.h" |
77 | 77 | ||
78 | #define MYRI10GE_VERSION_STR "1.4.3-1.375" | 78 | #define MYRI10GE_VERSION_STR "1.4.3-1.378" |
79 | 79 | ||
80 | MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); | 80 | MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); |
81 | MODULE_AUTHOR("Maintainer: help@myri.com"); | 81 | MODULE_AUTHOR("Maintainer: help@myri.com"); |
@@ -1393,6 +1393,7 @@ myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index) | |||
1393 | if (tx->req == tx->done) { | 1393 | if (tx->req == tx->done) { |
1394 | tx->queue_active = 0; | 1394 | tx->queue_active = 0; |
1395 | put_be32(htonl(1), tx->send_stop); | 1395 | put_be32(htonl(1), tx->send_stop); |
1396 | mb(); | ||
1396 | mmiowb(); | 1397 | mmiowb(); |
1397 | } | 1398 | } |
1398 | __netif_tx_unlock(dev_queue); | 1399 | __netif_tx_unlock(dev_queue); |
@@ -2865,6 +2866,7 @@ again: | |||
2865 | if ((mgp->dev->real_num_tx_queues > 1) && tx->queue_active == 0) { | 2866 | if ((mgp->dev->real_num_tx_queues > 1) && tx->queue_active == 0) { |
2866 | tx->queue_active = 1; | 2867 | tx->queue_active = 1; |
2867 | put_be32(htonl(1), tx->send_go); | 2868 | put_be32(htonl(1), tx->send_go); |
2869 | mb(); | ||
2868 | mmiowb(); | 2870 | mmiowb(); |
2869 | } | 2871 | } |
2870 | tx->pkt_start++; | 2872 | tx->pkt_start++; |
diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 9acb5d70a3ae..d8463b1c3df3 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c | |||
@@ -51,8 +51,7 @@ MODULE_VERSION(DRV_MODULE_VERSION); | |||
51 | #ifndef readq | 51 | #ifndef readq |
52 | static u64 readq(void __iomem *reg) | 52 | static u64 readq(void __iomem *reg) |
53 | { | 53 | { |
54 | return (((u64)readl(reg + 0x4UL) << 32) | | 54 | return ((u64) readl(reg)) | (((u64) readl(reg + 4UL)) << 32); |
55 | (u64)readl(reg)); | ||
56 | } | 55 | } |
57 | 56 | ||
58 | static void writeq(u64 val, void __iomem *reg) | 57 | static void writeq(u64 val, void __iomem *reg) |
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 5051554ff05b..1f26ab0e7986 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c | |||
@@ -2050,7 +2050,9 @@ err_out: | |||
2050 | */ | 2050 | */ |
2051 | static int smc911x_drv_probe(struct platform_device *pdev) | 2051 | static int smc911x_drv_probe(struct platform_device *pdev) |
2052 | { | 2052 | { |
2053 | #ifdef SMC_DYNAMIC_BUS_CONFIG | ||
2053 | struct smc911x_platdata *pd = pdev->dev.platform_data; | 2054 | struct smc911x_platdata *pd = pdev->dev.platform_data; |
2055 | #endif | ||
2054 | struct net_device *ndev; | 2056 | struct net_device *ndev; |
2055 | struct resource *res; | 2057 | struct resource *res; |
2056 | struct smc911x_local *lp; | 2058 | struct smc911x_local *lp; |
@@ -2182,9 +2184,9 @@ static int smc911x_drv_resume(struct platform_device *dev) | |||
2182 | 2184 | ||
2183 | if (netif_running(ndev)) { | 2185 | if (netif_running(ndev)) { |
2184 | smc911x_reset(ndev); | 2186 | smc911x_reset(ndev); |
2185 | smc911x_enable(ndev); | ||
2186 | if (lp->phy_type != 0) | 2187 | if (lp->phy_type != 0) |
2187 | smc911x_phy_configure(&lp->phy_configure); | 2188 | smc911x_phy_configure(&lp->phy_configure); |
2189 | smc911x_enable(ndev); | ||
2188 | netif_device_attach(ndev); | 2190 | netif_device_attach(ndev); |
2189 | } | 2191 | } |
2190 | } | 2192 | } |
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h index ffdf4876121b..a68f97c39359 100644 --- a/drivers/net/wireless/hostap/hostap_wlan.h +++ b/drivers/net/wireless/hostap/hostap_wlan.h | |||
@@ -918,9 +918,12 @@ struct hostap_interface { | |||
918 | 918 | ||
919 | /* | 919 | /* |
920 | * TX meta data - stored in skb->cb buffer, so this must not be increased over | 920 | * TX meta data - stored in skb->cb buffer, so this must not be increased over |
921 | * the 40-byte limit | 921 | * the 48-byte limit. |
922 | * THE PADDING THIS STARTS WITH IS A HORRIBLE HACK THAT SHOULD NOT LIVE | ||
923 | * TO SEE THE DAY. | ||
922 | */ | 924 | */ |
923 | struct hostap_skb_tx_data { | 925 | struct hostap_skb_tx_data { |
926 | unsigned int __padding_for_default_qdiscs; | ||
924 | u32 magic; /* HOSTAP_SKB_TX_DATA_MAGIC */ | 927 | u32 magic; /* HOSTAP_SKB_TX_DATA_MAGIC */ |
925 | u8 rate; /* transmit rate */ | 928 | u8 rate; /* transmit rate */ |
926 | #define HOSTAP_TX_FLAGS_WDS BIT(0) | 929 | #define HOSTAP_TX_FLAGS_WDS BIT(0) |
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 431e3c78bf27..69eb0132593b 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c | |||
@@ -48,6 +48,9 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { | |||
48 | {USB_DEVICE(0x03f0, 0xca02), .driver_info = DEVICE_RTL8187}, | 48 | {USB_DEVICE(0x03f0, 0xca02), .driver_info = DEVICE_RTL8187}, |
49 | /* Sitecom */ | 49 | /* Sitecom */ |
50 | {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, | 50 | {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, |
51 | {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B}, | ||
52 | /* Abocom */ | ||
53 | {USB_DEVICE(0x13d1, 0xabe6), .driver_info = DEVICE_RTL8187}, | ||
51 | {} | 54 | {} |
52 | }; | 55 | }; |
53 | 56 | ||
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 8abbb2020af9..123092d8a984 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -277,6 +277,14 @@ config RTC_DRV_FM3130 | |||
277 | This driver can also be built as a module. If so the module | 277 | This driver can also be built as a module. If so the module |
278 | will be called rtc-fm3130. | 278 | will be called rtc-fm3130. |
279 | 279 | ||
280 | config RTC_DRV_RX8581 | ||
281 | tristate "Epson RX-8581" | ||
282 | help | ||
283 | If you say yes here you will get support for the Epson RX-8581. | ||
284 | |||
285 | This driver can also be built as a module. If so the module | ||
286 | will be called rtc-rx8581. | ||
287 | |||
280 | endif # I2C | 288 | endif # I2C |
281 | 289 | ||
282 | comment "SPI RTC drivers" | 290 | comment "SPI RTC drivers" |
@@ -302,6 +310,17 @@ config RTC_DRV_DS1305 | |||
302 | This driver can also be built as a module. If so, the module | 310 | This driver can also be built as a module. If so, the module |
303 | will be called rtc-ds1305. | 311 | will be called rtc-ds1305. |
304 | 312 | ||
313 | config RTC_DRV_DS1390 | ||
314 | tristate "Dallas/Maxim DS1390/93/94" | ||
315 | help | ||
316 | If you say yes here you get support for the DS1390/93/94 chips. | ||
317 | |||
318 | This driver only supports the RTC feature, and not other chip | ||
319 | features such as alarms and trickle charging. | ||
320 | |||
321 | This driver can also be built as a module. If so, the module | ||
322 | will be called rtc-ds1390. | ||
323 | |||
305 | config RTC_DRV_MAX6902 | 324 | config RTC_DRV_MAX6902 |
306 | tristate "Maxim MAX6902" | 325 | tristate "Maxim MAX6902" |
307 | help | 326 | help |
@@ -468,6 +487,16 @@ config RTC_DRV_V3020 | |||
468 | This driver can also be built as a module. If so, the module | 487 | This driver can also be built as a module. If so, the module |
469 | will be called rtc-v3020. | 488 | will be called rtc-v3020. |
470 | 489 | ||
490 | config RTC_DRV_WM8350 | ||
491 | tristate "Wolfson Microelectronics WM8350 RTC" | ||
492 | depends on MFD_WM8350 | ||
493 | help | ||
494 | If you say yes here you will get support for the RTC subsystem | ||
495 | of the Wolfson Microelectronics WM8350. | ||
496 | |||
497 | This driver can also be built as a module. If so, the module | ||
498 | will be called "rtc-wm8350". | ||
499 | |||
471 | comment "on-CPU RTC drivers" | 500 | comment "on-CPU RTC drivers" |
472 | 501 | ||
473 | config RTC_DRV_OMAP | 502 | config RTC_DRV_OMAP |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index e9e8474cc8fe..6e79c912bf9e 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -28,6 +28,7 @@ obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o | |||
28 | obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o | 28 | obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o |
29 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o | 29 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o |
30 | obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o | 30 | obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o |
31 | obj-$(CONFIG_RTC_DRV_DS1390) += rtc-ds1390.o | ||
31 | obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o | 32 | obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o |
32 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o | 33 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o |
33 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o | 34 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o |
@@ -57,6 +58,7 @@ obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o | |||
57 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o | 58 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o |
58 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o | 59 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o |
59 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o | 60 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o |
61 | obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o | ||
60 | obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o | 62 | obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o |
61 | obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o | 63 | obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o |
62 | obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o | 64 | obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o |
@@ -66,4 +68,5 @@ obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o | |||
66 | obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl4030.o | 68 | obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl4030.o |
67 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o | 69 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o |
68 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o | 70 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o |
71 | obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o | ||
69 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o | 72 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o |
diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c new file mode 100644 index 000000000000..599e976bf014 --- /dev/null +++ b/drivers/rtc/rtc-ds1390.c | |||
@@ -0,0 +1,220 @@ | |||
1 | /* | ||
2 | * rtc-ds1390.c -- driver for DS1390/93/94 | ||
3 | * | ||
4 | * Copyright (C) 2008 Mercury IMC Ltd | ||
5 | * Written by Mark Jackson <mpfj@mimc.co.uk> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * NOTE : Currently this driver only supports the bare minimum for read | ||
12 | * and write the RTC. The extra features provided by the chip family | ||
13 | * (alarms, trickle charger, different control registers) are unavailable. | ||
14 | */ | ||
15 | |||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/rtc.h> | ||
18 | #include <linux/spi/spi.h> | ||
19 | #include <linux/bcd.h> | ||
20 | |||
21 | #define DS1390_REG_100THS 0x00 | ||
22 | #define DS1390_REG_SECONDS 0x01 | ||
23 | #define DS1390_REG_MINUTES 0x02 | ||
24 | #define DS1390_REG_HOURS 0x03 | ||
25 | #define DS1390_REG_DAY 0x04 | ||
26 | #define DS1390_REG_DATE 0x05 | ||
27 | #define DS1390_REG_MONTH_CENT 0x06 | ||
28 | #define DS1390_REG_YEAR 0x07 | ||
29 | |||
30 | #define DS1390_REG_ALARM_100THS 0x08 | ||
31 | #define DS1390_REG_ALARM_SECONDS 0x09 | ||
32 | #define DS1390_REG_ALARM_MINUTES 0x0A | ||
33 | #define DS1390_REG_ALARM_HOURS 0x0B | ||
34 | #define DS1390_REG_ALARM_DAY_DATE 0x0C | ||
35 | |||
36 | #define DS1390_REG_CONTROL 0x0D | ||
37 | #define DS1390_REG_STATUS 0x0E | ||
38 | #define DS1390_REG_TRICKLE 0x0F | ||
39 | |||
40 | struct ds1390 { | ||
41 | struct rtc_device *rtc; | ||
42 | u8 txrx_buf[9]; /* cmd + 8 registers */ | ||
43 | }; | ||
44 | |||
45 | static void ds1390_set_reg(struct device *dev, unsigned char address, | ||
46 | unsigned char data) | ||
47 | { | ||
48 | struct spi_device *spi = to_spi_device(dev); | ||
49 | struct ds1390 *chip = dev_get_drvdata(dev); | ||
50 | |||
51 | /* Set MSB to indicate write */ | ||
52 | chip->txrx_buf[0] = address | 0x80; | ||
53 | chip->txrx_buf[1] = data; | ||
54 | |||
55 | /* do the i/o */ | ||
56 | spi_write_then_read(spi, chip->txrx_buf, 2, NULL, 0); | ||
57 | } | ||
58 | |||
59 | static int ds1390_get_reg(struct device *dev, unsigned char address, | ||
60 | unsigned char *data) | ||
61 | { | ||
62 | struct spi_device *spi = to_spi_device(dev); | ||
63 | struct ds1390 *chip = dev_get_drvdata(dev); | ||
64 | int status; | ||
65 | |||
66 | if (!data) | ||
67 | return -EINVAL; | ||
68 | |||
69 | /* Clear MSB to indicate read */ | ||
70 | chip->txrx_buf[0] = address & 0x7f; | ||
71 | /* do the i/o */ | ||
72 | status = spi_write_then_read(spi, chip->txrx_buf, 1, chip->txrx_buf, 1); | ||
73 | if (status != 0) | ||
74 | return status; | ||
75 | |||
76 | *data = chip->txrx_buf[1]; | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static int ds1390_get_datetime(struct device *dev, struct rtc_time *dt) | ||
82 | { | ||
83 | struct spi_device *spi = to_spi_device(dev); | ||
84 | struct ds1390 *chip = dev_get_drvdata(dev); | ||
85 | int status; | ||
86 | |||
87 | /* build the message */ | ||
88 | chip->txrx_buf[0] = DS1390_REG_SECONDS; | ||
89 | |||
90 | /* do the i/o */ | ||
91 | status = spi_write_then_read(spi, chip->txrx_buf, 1, chip->txrx_buf, 8); | ||
92 | if (status != 0) | ||
93 | return status; | ||
94 | |||
95 | /* The chip sends data in this order: | ||
96 | * Seconds, Minutes, Hours, Day, Date, Month / Century, Year */ | ||
97 | dt->tm_sec = bcd2bin(chip->txrx_buf[0]); | ||
98 | dt->tm_min = bcd2bin(chip->txrx_buf[1]); | ||
99 | dt->tm_hour = bcd2bin(chip->txrx_buf[2]); | ||
100 | dt->tm_wday = bcd2bin(chip->txrx_buf[3]); | ||
101 | dt->tm_mday = bcd2bin(chip->txrx_buf[4]); | ||
102 | /* mask off century bit */ | ||
103 | dt->tm_mon = bcd2bin(chip->txrx_buf[5] & 0x7f) - 1; | ||
104 | /* adjust for century bit */ | ||
105 | dt->tm_year = bcd2bin(chip->txrx_buf[6]) + ((chip->txrx_buf[5] & 0x80) ? 100 : 0); | ||
106 | |||
107 | return rtc_valid_tm(dt); | ||
108 | } | ||
109 | |||
110 | static int ds1390_set_datetime(struct device *dev, struct rtc_time *dt) | ||
111 | { | ||
112 | struct spi_device *spi = to_spi_device(dev); | ||
113 | struct ds1390 *chip = dev_get_drvdata(dev); | ||
114 | |||
115 | /* build the message */ | ||
116 | chip->txrx_buf[0] = DS1390_REG_SECONDS | 0x80; | ||
117 | chip->txrx_buf[1] = bin2bcd(dt->tm_sec); | ||
118 | chip->txrx_buf[2] = bin2bcd(dt->tm_min); | ||
119 | chip->txrx_buf[3] = bin2bcd(dt->tm_hour); | ||
120 | chip->txrx_buf[4] = bin2bcd(dt->tm_wday); | ||
121 | chip->txrx_buf[5] = bin2bcd(dt->tm_mday); | ||
122 | chip->txrx_buf[6] = bin2bcd(dt->tm_mon + 1) | | ||
123 | ((dt->tm_year > 99) ? 0x80 : 0x00); | ||
124 | chip->txrx_buf[7] = bin2bcd(dt->tm_year % 100); | ||
125 | |||
126 | /* do the i/o */ | ||
127 | return spi_write_then_read(spi, chip->txrx_buf, 8, NULL, 0); | ||
128 | } | ||
129 | |||
130 | static int ds1390_read_time(struct device *dev, struct rtc_time *tm) | ||
131 | { | ||
132 | return ds1390_get_datetime(dev, tm); | ||
133 | } | ||
134 | |||
135 | static int ds1390_set_time(struct device *dev, struct rtc_time *tm) | ||
136 | { | ||
137 | return ds1390_set_datetime(dev, tm); | ||
138 | } | ||
139 | |||
140 | static const struct rtc_class_ops ds1390_rtc_ops = { | ||
141 | .read_time = ds1390_read_time, | ||
142 | .set_time = ds1390_set_time, | ||
143 | }; | ||
144 | |||
145 | static int __devinit ds1390_probe(struct spi_device *spi) | ||
146 | { | ||
147 | struct rtc_device *rtc; | ||
148 | unsigned char tmp; | ||
149 | struct ds1390 *chip; | ||
150 | int res; | ||
151 | |||
152 | printk(KERN_DEBUG "DS1390 SPI RTC driver\n"); | ||
153 | |||
154 | rtc = rtc_device_register("ds1390", | ||
155 | &spi->dev, &ds1390_rtc_ops, THIS_MODULE); | ||
156 | if (IS_ERR(rtc)) { | ||
157 | printk(KERN_ALERT "RTC : unable to register device\n"); | ||
158 | return PTR_ERR(rtc); | ||
159 | } | ||
160 | |||
161 | spi->mode = SPI_MODE_3; | ||
162 | spi->bits_per_word = 8; | ||
163 | spi_setup(spi); | ||
164 | |||
165 | chip = kzalloc(sizeof *chip, GFP_KERNEL); | ||
166 | if (!chip) { | ||
167 | printk(KERN_ALERT "RTC : unable to allocate device memory\n"); | ||
168 | rtc_device_unregister(rtc); | ||
169 | return -ENOMEM; | ||
170 | } | ||
171 | chip->rtc = rtc; | ||
172 | dev_set_drvdata(&spi->dev, chip); | ||
173 | |||
174 | res = ds1390_get_reg(&spi->dev, DS1390_REG_SECONDS, &tmp); | ||
175 | if (res) { | ||
176 | printk(KERN_ALERT "RTC : unable to read device\n"); | ||
177 | rtc_device_unregister(rtc); | ||
178 | return res; | ||
179 | } | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int __devexit ds1390_remove(struct spi_device *spi) | ||
185 | { | ||
186 | struct ds1390 *chip = platform_get_drvdata(spi); | ||
187 | struct rtc_device *rtc = chip->rtc; | ||
188 | |||
189 | if (rtc) | ||
190 | rtc_device_unregister(rtc); | ||
191 | |||
192 | kfree(chip); | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static struct spi_driver ds1390_driver = { | ||
198 | .driver = { | ||
199 | .name = "rtc-ds1390", | ||
200 | .owner = THIS_MODULE, | ||
201 | }, | ||
202 | .probe = ds1390_probe, | ||
203 | .remove = __devexit_p(ds1390_remove), | ||
204 | }; | ||
205 | |||
206 | static __init int ds1390_init(void) | ||
207 | { | ||
208 | return spi_register_driver(&ds1390_driver); | ||
209 | } | ||
210 | module_init(ds1390_init); | ||
211 | |||
212 | static __exit void ds1390_exit(void) | ||
213 | { | ||
214 | spi_unregister_driver(&ds1390_driver); | ||
215 | } | ||
216 | module_exit(ds1390_exit); | ||
217 | |||
218 | MODULE_DESCRIPTION("DS1390/93/94 SPI RTC driver"); | ||
219 | MODULE_AUTHOR("Mark Jackson <mpfj@mimc.co.uk>"); | ||
220 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c new file mode 100644 index 000000000000..c9522f3bc21c --- /dev/null +++ b/drivers/rtc/rtc-rx8581.c | |||
@@ -0,0 +1,281 @@ | |||
1 | /* | ||
2 | * An I2C driver for the Epson RX8581 RTC | ||
3 | * | ||
4 | * Author: Martyn Welch <martyn.welch@gefanuc.com> | ||
5 | * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * Based on: rtc-pcf8563.c (An I2C driver for the Philips PCF8563 RTC) | ||
12 | * Copyright 2005-06 Tower Technologies | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/bcd.h> | ||
18 | #include <linux/rtc.h> | ||
19 | #include <linux/log2.h> | ||
20 | |||
21 | #define DRV_VERSION "0.1" | ||
22 | |||
23 | #define RX8581_REG_SC 0x00 /* Second in BCD */ | ||
24 | #define RX8581_REG_MN 0x01 /* Minute in BCD */ | ||
25 | #define RX8581_REG_HR 0x02 /* Hour in BCD */ | ||
26 | #define RX8581_REG_DW 0x03 /* Day of Week */ | ||
27 | #define RX8581_REG_DM 0x04 /* Day of Month in BCD */ | ||
28 | #define RX8581_REG_MO 0x05 /* Month in BCD */ | ||
29 | #define RX8581_REG_YR 0x06 /* Year in BCD */ | ||
30 | #define RX8581_REG_RAM 0x07 /* RAM */ | ||
31 | #define RX8581_REG_AMN 0x08 /* Alarm Min in BCD*/ | ||
32 | #define RX8581_REG_AHR 0x09 /* Alarm Hour in BCD */ | ||
33 | #define RX8581_REG_ADM 0x0A | ||
34 | #define RX8581_REG_ADW 0x0A | ||
35 | #define RX8581_REG_TMR0 0x0B | ||
36 | #define RX8581_REG_TMR1 0x0C | ||
37 | #define RX8581_REG_EXT 0x0D /* Extension Register */ | ||
38 | #define RX8581_REG_FLAG 0x0E /* Flag Register */ | ||
39 | #define RX8581_REG_CTRL 0x0F /* Control Register */ | ||
40 | |||
41 | |||
42 | /* Flag Register bit definitions */ | ||
43 | #define RX8581_FLAG_UF 0x20 /* Update */ | ||
44 | #define RX8581_FLAG_TF 0x10 /* Timer */ | ||
45 | #define RX8581_FLAG_AF 0x08 /* Alarm */ | ||
46 | #define RX8581_FLAG_VLF 0x02 /* Voltage Low */ | ||
47 | |||
48 | /* Control Register bit definitions */ | ||
49 | #define RX8581_CTRL_UIE 0x20 /* Update Interrupt Enable */ | ||
50 | #define RX8581_CTRL_TIE 0x10 /* Timer Interrupt Enable */ | ||
51 | #define RX8581_CTRL_AIE 0x08 /* Alarm Interrupt Enable */ | ||
52 | #define RX8581_CTRL_STOP 0x02 /* STOP bit */ | ||
53 | #define RX8581_CTRL_RESET 0x01 /* RESET bit */ | ||
54 | |||
55 | static struct i2c_driver rx8581_driver; | ||
56 | |||
57 | /* | ||
58 | * In the routines that deal directly with the rx8581 hardware, we use | ||
59 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. | ||
60 | */ | ||
61 | static int rx8581_get_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
62 | { | ||
63 | unsigned char date[7]; | ||
64 | int data, err; | ||
65 | |||
66 | /* First we ensure that the "update flag" is not set, we read the | ||
67 | * time and date then re-read the "update flag". If the update flag | ||
68 | * has been set, we know that the time has changed during the read so | ||
69 | * we repeat the whole process again. | ||
70 | */ | ||
71 | data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG); | ||
72 | if (data < 0) { | ||
73 | dev_err(&client->dev, "Unable to read device flags\n"); | ||
74 | return -EIO; | ||
75 | } | ||
76 | |||
77 | do { | ||
78 | /* If update flag set, clear it */ | ||
79 | if (data & RX8581_FLAG_UF) { | ||
80 | err = i2c_smbus_write_byte_data(client, | ||
81 | RX8581_REG_FLAG, (data & ~RX8581_FLAG_UF)); | ||
82 | if (err != 0) { | ||
83 | dev_err(&client->dev, "Unable to write device " | ||
84 | "flags\n"); | ||
85 | return -EIO; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | /* Now read time and date */ | ||
90 | err = i2c_smbus_read_i2c_block_data(client, RX8581_REG_SC, | ||
91 | 7, date); | ||
92 | if (err < 0) { | ||
93 | dev_err(&client->dev, "Unable to read date\n"); | ||
94 | return -EIO; | ||
95 | } | ||
96 | |||
97 | /* Check flag register */ | ||
98 | data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG); | ||
99 | if (data < 0) { | ||
100 | dev_err(&client->dev, "Unable to read device flags\n"); | ||
101 | return -EIO; | ||
102 | } | ||
103 | } while (data & RX8581_FLAG_UF); | ||
104 | |||
105 | if (data & RX8581_FLAG_VLF) | ||
106 | dev_info(&client->dev, | ||
107 | "low voltage detected, date/time is not reliable.\n"); | ||
108 | |||
109 | dev_dbg(&client->dev, | ||
110 | "%s: raw data is sec=%02x, min=%02x, hr=%02x, " | ||
111 | "wday=%02x, mday=%02x, mon=%02x, year=%02x\n", | ||
112 | __func__, | ||
113 | date[0], date[1], date[2], date[3], date[4], date[5], date[6]); | ||
114 | |||
115 | tm->tm_sec = bcd2bin(date[RX8581_REG_SC] & 0x7F); | ||
116 | tm->tm_min = bcd2bin(date[RX8581_REG_MN] & 0x7F); | ||
117 | tm->tm_hour = bcd2bin(date[RX8581_REG_HR] & 0x3F); /* rtc hr 0-23 */ | ||
118 | tm->tm_wday = ilog2(date[RX8581_REG_DW] & 0x7F); | ||
119 | tm->tm_mday = bcd2bin(date[RX8581_REG_DM] & 0x3F); | ||
120 | tm->tm_mon = bcd2bin(date[RX8581_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ | ||
121 | tm->tm_year = bcd2bin(date[RX8581_REG_YR]); | ||
122 | if (tm->tm_year < 70) | ||
123 | tm->tm_year += 100; /* assume we are in 1970...2069 */ | ||
124 | |||
125 | |||
126 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " | ||
127 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
128 | __func__, | ||
129 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
130 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
131 | |||
132 | err = rtc_valid_tm(tm); | ||
133 | if (err < 0) | ||
134 | dev_err(&client->dev, "retrieved date/time is not valid.\n"); | ||
135 | |||
136 | return err; | ||
137 | } | ||
138 | |||
139 | static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
140 | { | ||
141 | int data, err; | ||
142 | unsigned char buf[7]; | ||
143 | |||
144 | dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " | ||
145 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
146 | __func__, | ||
147 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
148 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
149 | |||
150 | /* hours, minutes and seconds */ | ||
151 | buf[RX8581_REG_SC] = bin2bcd(tm->tm_sec); | ||
152 | buf[RX8581_REG_MN] = bin2bcd(tm->tm_min); | ||
153 | buf[RX8581_REG_HR] = bin2bcd(tm->tm_hour); | ||
154 | |||
155 | buf[RX8581_REG_DM] = bin2bcd(tm->tm_mday); | ||
156 | |||
157 | /* month, 1 - 12 */ | ||
158 | buf[RX8581_REG_MO] = bin2bcd(tm->tm_mon + 1); | ||
159 | |||
160 | /* year and century */ | ||
161 | buf[RX8581_REG_YR] = bin2bcd(tm->tm_year % 100); | ||
162 | buf[RX8581_REG_DW] = (0x1 << tm->tm_wday); | ||
163 | |||
164 | /* Stop the clock */ | ||
165 | data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL); | ||
166 | if (data < 0) { | ||
167 | dev_err(&client->dev, "Unable to read control register\n"); | ||
168 | return -EIO; | ||
169 | } | ||
170 | |||
171 | err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, | ||
172 | (data | RX8581_CTRL_STOP)); | ||
173 | if (err < 0) { | ||
174 | dev_err(&client->dev, "Unable to write control register\n"); | ||
175 | return -EIO; | ||
176 | } | ||
177 | |||
178 | /* write register's data */ | ||
179 | err = i2c_smbus_write_i2c_block_data(client, RX8581_REG_SC, 7, buf); | ||
180 | if (err < 0) { | ||
181 | dev_err(&client->dev, "Unable to write to date registers\n"); | ||
182 | return -EIO; | ||
183 | } | ||
184 | |||
185 | /* Restart the clock */ | ||
186 | data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL); | ||
187 | if (data < 0) { | ||
188 | dev_err(&client->dev, "Unable to read control register\n"); | ||
189 | return -EIO; | ||
190 | } | ||
191 | |||
192 | err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, | ||
193 | (data | ~(RX8581_CTRL_STOP))); | ||
194 | if (err != 0) { | ||
195 | dev_err(&client->dev, "Unable to write control register\n"); | ||
196 | return -EIO; | ||
197 | } | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
203 | { | ||
204 | return rx8581_get_datetime(to_i2c_client(dev), tm); | ||
205 | } | ||
206 | |||
207 | static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
208 | { | ||
209 | return rx8581_set_datetime(to_i2c_client(dev), tm); | ||
210 | } | ||
211 | |||
212 | static const struct rtc_class_ops rx8581_rtc_ops = { | ||
213 | .read_time = rx8581_rtc_read_time, | ||
214 | .set_time = rx8581_rtc_set_time, | ||
215 | }; | ||
216 | |||
217 | static int __devinit rx8581_probe(struct i2c_client *client, | ||
218 | const struct i2c_device_id *id) | ||
219 | { | ||
220 | struct rtc_device *rtc; | ||
221 | |||
222 | dev_dbg(&client->dev, "%s\n", __func__); | ||
223 | |||
224 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | ||
225 | return -ENODEV; | ||
226 | |||
227 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | ||
228 | |||
229 | rtc = rtc_device_register(rx8581_driver.driver.name, | ||
230 | &client->dev, &rx8581_rtc_ops, THIS_MODULE); | ||
231 | |||
232 | if (IS_ERR(rtc)) | ||
233 | return PTR_ERR(rtc); | ||
234 | |||
235 | i2c_set_clientdata(client, rtc); | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | static int __devexit rx8581_remove(struct i2c_client *client) | ||
241 | { | ||
242 | struct rtc_device *rtc = i2c_get_clientdata(client); | ||
243 | |||
244 | rtc_device_unregister(rtc); | ||
245 | |||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static const struct i2c_device_id rx8581_id[] = { | ||
250 | { "rx8581", 0 }, | ||
251 | { } | ||
252 | }; | ||
253 | MODULE_DEVICE_TABLE(i2c, rx8581_id); | ||
254 | |||
255 | static struct i2c_driver rx8581_driver = { | ||
256 | .driver = { | ||
257 | .name = "rtc-rx8581", | ||
258 | .owner = THIS_MODULE, | ||
259 | }, | ||
260 | .probe = rx8581_probe, | ||
261 | .remove = __devexit_p(rx8581_remove), | ||
262 | .id_table = rx8581_id, | ||
263 | }; | ||
264 | |||
265 | static int __init rx8581_init(void) | ||
266 | { | ||
267 | return i2c_add_driver(&rx8581_driver); | ||
268 | } | ||
269 | |||
270 | static void __exit rx8581_exit(void) | ||
271 | { | ||
272 | i2c_del_driver(&rx8581_driver); | ||
273 | } | ||
274 | |||
275 | MODULE_AUTHOR("Martyn Welch <martyn.welch@gefanuc.com>"); | ||
276 | MODULE_DESCRIPTION("Epson RX-8581 RTC driver"); | ||
277 | MODULE_LICENSE("GPL"); | ||
278 | MODULE_VERSION(DRV_VERSION); | ||
279 | |||
280 | module_init(rx8581_init); | ||
281 | module_exit(rx8581_exit); | ||
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c new file mode 100644 index 000000000000..5c5e3aa91385 --- /dev/null +++ b/drivers/rtc/rtc-wm8350.c | |||
@@ -0,0 +1,514 @@ | |||
1 | /* | ||
2 | * Real Time Clock driver for Wolfson Microelectronics WM8350 | ||
3 | * | ||
4 | * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC. | ||
5 | * | ||
6 | * Author: Liam Girdwood | ||
7 | * linux@wolfsonmicro.com | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/time.h> | ||
19 | #include <linux/rtc.h> | ||
20 | #include <linux/bcd.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/ioctl.h> | ||
23 | #include <linux/completion.h> | ||
24 | #include <linux/mfd/wm8350/rtc.h> | ||
25 | #include <linux/mfd/wm8350/core.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | |||
29 | #define WM8350_SET_ALM_RETRIES 5 | ||
30 | #define WM8350_SET_TIME_RETRIES 5 | ||
31 | #define WM8350_GET_TIME_RETRIES 5 | ||
32 | |||
33 | #define to_wm8350_from_rtc_dev(d) container_of(d, struct wm8350, rtc.pdev.dev) | ||
34 | |||
35 | /* | ||
36 | * Read current time and date in RTC | ||
37 | */ | ||
38 | static int wm8350_rtc_readtime(struct device *dev, struct rtc_time *tm) | ||
39 | { | ||
40 | struct wm8350 *wm8350 = dev_get_drvdata(dev); | ||
41 | u16 time1[4], time2[4]; | ||
42 | int retries = WM8350_GET_TIME_RETRIES, ret; | ||
43 | |||
44 | /* | ||
45 | * Read the time twice and compare. | ||
46 | * If time1 == time2, then time is valid else retry. | ||
47 | */ | ||
48 | do { | ||
49 | ret = wm8350_block_read(wm8350, WM8350_RTC_SECONDS_MINUTES, | ||
50 | 4, time1); | ||
51 | if (ret < 0) | ||
52 | return ret; | ||
53 | ret = wm8350_block_read(wm8350, WM8350_RTC_SECONDS_MINUTES, | ||
54 | 4, time2); | ||
55 | if (ret < 0) | ||
56 | return ret; | ||
57 | |||
58 | if (memcmp(time1, time2, sizeof(time1)) == 0) { | ||
59 | tm->tm_sec = time1[0] & WM8350_RTC_SECS_MASK; | ||
60 | |||
61 | tm->tm_min = (time1[0] & WM8350_RTC_MINS_MASK) | ||
62 | >> WM8350_RTC_MINS_SHIFT; | ||
63 | |||
64 | tm->tm_hour = time1[1] & WM8350_RTC_HRS_MASK; | ||
65 | |||
66 | tm->tm_wday = ((time1[1] >> WM8350_RTC_DAY_SHIFT) | ||
67 | & 0x7) - 1; | ||
68 | |||
69 | tm->tm_mon = ((time1[2] & WM8350_RTC_MTH_MASK) | ||
70 | >> WM8350_RTC_MTH_SHIFT) - 1; | ||
71 | |||
72 | tm->tm_mday = (time1[2] & WM8350_RTC_DATE_MASK); | ||
73 | |||
74 | tm->tm_year = ((time1[3] & WM8350_RTC_YHUNDREDS_MASK) | ||
75 | >> WM8350_RTC_YHUNDREDS_SHIFT) * 100; | ||
76 | tm->tm_year += time1[3] & WM8350_RTC_YUNITS_MASK; | ||
77 | |||
78 | tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, | ||
79 | tm->tm_year); | ||
80 | tm->tm_year -= 1900; | ||
81 | |||
82 | dev_dbg(dev, "Read (%d left): %04x %04x %04x %04x\n", | ||
83 | retries, | ||
84 | time1[0], time1[1], time1[2], time1[3]); | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | } while (retries--); | ||
89 | |||
90 | dev_err(dev, "timed out reading RTC time\n"); | ||
91 | return -EIO; | ||
92 | } | ||
93 | |||
94 | /* | ||
95 | * Set current time and date in RTC | ||
96 | */ | ||
97 | static int wm8350_rtc_settime(struct device *dev, struct rtc_time *tm) | ||
98 | { | ||
99 | struct wm8350 *wm8350 = dev_get_drvdata(dev); | ||
100 | u16 time[4]; | ||
101 | u16 rtc_ctrl; | ||
102 | int ret, retries = WM8350_SET_TIME_RETRIES; | ||
103 | |||
104 | time[0] = tm->tm_sec; | ||
105 | time[0] |= tm->tm_min << WM8350_RTC_MINS_SHIFT; | ||
106 | time[1] = tm->tm_hour; | ||
107 | time[1] |= (tm->tm_wday + 1) << WM8350_RTC_DAY_SHIFT; | ||
108 | time[2] = tm->tm_mday; | ||
109 | time[2] |= (tm->tm_mon + 1) << WM8350_RTC_MTH_SHIFT; | ||
110 | time[3] = ((tm->tm_year + 1900) / 100) << WM8350_RTC_YHUNDREDS_SHIFT; | ||
111 | time[3] |= (tm->tm_year + 1900) % 100; | ||
112 | |||
113 | dev_dbg(dev, "Setting: %04x %04x %04x %04x\n", | ||
114 | time[0], time[1], time[2], time[3]); | ||
115 | |||
116 | /* Set RTC_SET to stop the clock */ | ||
117 | ret = wm8350_set_bits(wm8350, WM8350_RTC_TIME_CONTROL, WM8350_RTC_SET); | ||
118 | if (ret < 0) | ||
119 | return ret; | ||
120 | |||
121 | /* Wait until confirmation of stopping */ | ||
122 | do { | ||
123 | rtc_ctrl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); | ||
124 | schedule_timeout_uninterruptible(msecs_to_jiffies(1)); | ||
125 | } while (retries-- && !(rtc_ctrl & WM8350_RTC_STS)); | ||
126 | |||
127 | if (!retries) { | ||
128 | dev_err(dev, "timed out on set confirmation\n"); | ||
129 | return -EIO; | ||
130 | } | ||
131 | |||
132 | /* Write time to RTC */ | ||
133 | ret = wm8350_block_write(wm8350, WM8350_RTC_SECONDS_MINUTES, 4, time); | ||
134 | if (ret < 0) | ||
135 | return ret; | ||
136 | |||
137 | /* Clear RTC_SET to start the clock */ | ||
138 | ret = wm8350_clear_bits(wm8350, WM8350_RTC_TIME_CONTROL, | ||
139 | WM8350_RTC_SET); | ||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | /* | ||
144 | * Read alarm time and date in RTC | ||
145 | */ | ||
146 | static int wm8350_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
147 | { | ||
148 | struct wm8350 *wm8350 = dev_get_drvdata(dev); | ||
149 | struct rtc_time *tm = &alrm->time; | ||
150 | u16 time[4]; | ||
151 | int ret; | ||
152 | |||
153 | ret = wm8350_block_read(wm8350, WM8350_ALARM_SECONDS_MINUTES, 4, time); | ||
154 | if (ret < 0) | ||
155 | return ret; | ||
156 | |||
157 | tm->tm_sec = time[0] & WM8350_RTC_ALMSECS_MASK; | ||
158 | if (tm->tm_sec == WM8350_RTC_ALMSECS_MASK) | ||
159 | tm->tm_sec = -1; | ||
160 | |||
161 | tm->tm_min = time[0] & WM8350_RTC_ALMMINS_MASK; | ||
162 | if (tm->tm_min == WM8350_RTC_ALMMINS_MASK) | ||
163 | tm->tm_min = -1; | ||
164 | else | ||
165 | tm->tm_min >>= WM8350_RTC_ALMMINS_SHIFT; | ||
166 | |||
167 | tm->tm_hour = time[1] & WM8350_RTC_ALMHRS_MASK; | ||
168 | if (tm->tm_hour == WM8350_RTC_ALMHRS_MASK) | ||
169 | tm->tm_hour = -1; | ||
170 | |||
171 | tm->tm_wday = ((time[1] >> WM8350_RTC_ALMDAY_SHIFT) & 0x7) - 1; | ||
172 | if (tm->tm_wday > 7) | ||
173 | tm->tm_wday = -1; | ||
174 | |||
175 | tm->tm_mon = time[2] & WM8350_RTC_ALMMTH_MASK; | ||
176 | if (tm->tm_mon == WM8350_RTC_ALMMTH_MASK) | ||
177 | tm->tm_mon = -1; | ||
178 | else | ||
179 | tm->tm_mon = (tm->tm_mon >> WM8350_RTC_ALMMTH_SHIFT) - 1; | ||
180 | |||
181 | tm->tm_mday = (time[2] & WM8350_RTC_ALMDATE_MASK); | ||
182 | if (tm->tm_mday == WM8350_RTC_ALMDATE_MASK) | ||
183 | tm->tm_mday = -1; | ||
184 | |||
185 | tm->tm_year = -1; | ||
186 | |||
187 | alrm->enabled = !(time[3] & WM8350_RTC_ALMSTS); | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static int wm8350_rtc_stop_alarm(struct wm8350 *wm8350) | ||
193 | { | ||
194 | int retries = WM8350_SET_ALM_RETRIES; | ||
195 | u16 rtc_ctrl; | ||
196 | int ret; | ||
197 | |||
198 | /* Set RTC_SET to stop the clock */ | ||
199 | ret = wm8350_set_bits(wm8350, WM8350_RTC_TIME_CONTROL, | ||
200 | WM8350_RTC_ALMSET); | ||
201 | if (ret < 0) | ||
202 | return ret; | ||
203 | |||
204 | /* Wait until confirmation of stopping */ | ||
205 | do { | ||
206 | rtc_ctrl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); | ||
207 | schedule_timeout_uninterruptible(msecs_to_jiffies(1)); | ||
208 | } while (retries-- && !(rtc_ctrl & WM8350_RTC_ALMSTS)); | ||
209 | |||
210 | if (!(rtc_ctrl & WM8350_RTC_ALMSTS)) | ||
211 | return -ETIMEDOUT; | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int wm8350_rtc_start_alarm(struct wm8350 *wm8350) | ||
217 | { | ||
218 | int ret; | ||
219 | int retries = WM8350_SET_ALM_RETRIES; | ||
220 | u16 rtc_ctrl; | ||
221 | |||
222 | ret = wm8350_clear_bits(wm8350, WM8350_RTC_TIME_CONTROL, | ||
223 | WM8350_RTC_ALMSET); | ||
224 | if (ret < 0) | ||
225 | return ret; | ||
226 | |||
227 | /* Wait until confirmation */ | ||
228 | do { | ||
229 | rtc_ctrl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); | ||
230 | schedule_timeout_uninterruptible(msecs_to_jiffies(1)); | ||
231 | } while (retries-- && rtc_ctrl & WM8350_RTC_ALMSTS); | ||
232 | |||
233 | if (rtc_ctrl & WM8350_RTC_ALMSTS) | ||
234 | return -ETIMEDOUT; | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static int wm8350_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
240 | { | ||
241 | struct wm8350 *wm8350 = dev_get_drvdata(dev); | ||
242 | struct rtc_time *tm = &alrm->time; | ||
243 | u16 time[3]; | ||
244 | int ret; | ||
245 | |||
246 | memset(time, 0, sizeof(time)); | ||
247 | |||
248 | if (tm->tm_sec != -1) | ||
249 | time[0] |= tm->tm_sec; | ||
250 | else | ||
251 | time[0] |= WM8350_RTC_ALMSECS_MASK; | ||
252 | |||
253 | if (tm->tm_min != -1) | ||
254 | time[0] |= tm->tm_min << WM8350_RTC_ALMMINS_SHIFT; | ||
255 | else | ||
256 | time[0] |= WM8350_RTC_ALMMINS_MASK; | ||
257 | |||
258 | if (tm->tm_hour != -1) | ||
259 | time[1] |= tm->tm_hour; | ||
260 | else | ||
261 | time[1] |= WM8350_RTC_ALMHRS_MASK; | ||
262 | |||
263 | if (tm->tm_wday != -1) | ||
264 | time[1] |= (tm->tm_wday + 1) << WM8350_RTC_ALMDAY_SHIFT; | ||
265 | else | ||
266 | time[1] |= WM8350_RTC_ALMDAY_MASK; | ||
267 | |||
268 | if (tm->tm_mday != -1) | ||
269 | time[2] |= tm->tm_mday; | ||
270 | else | ||
271 | time[2] |= WM8350_RTC_ALMDATE_MASK; | ||
272 | |||
273 | if (tm->tm_mon != -1) | ||
274 | time[2] |= (tm->tm_mon + 1) << WM8350_RTC_ALMMTH_SHIFT; | ||
275 | else | ||
276 | time[2] |= WM8350_RTC_ALMMTH_MASK; | ||
277 | |||
278 | ret = wm8350_rtc_stop_alarm(wm8350); | ||
279 | if (ret < 0) | ||
280 | return ret; | ||
281 | |||
282 | /* Write time to RTC */ | ||
283 | ret = wm8350_block_write(wm8350, WM8350_ALARM_SECONDS_MINUTES, | ||
284 | 3, time); | ||
285 | if (ret < 0) | ||
286 | return ret; | ||
287 | |||
288 | if (alrm->enabled) | ||
289 | ret = wm8350_rtc_start_alarm(wm8350); | ||
290 | |||
291 | return ret; | ||
292 | } | ||
293 | |||
294 | /* | ||
295 | * Handle commands from user-space | ||
296 | */ | ||
297 | static int wm8350_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
298 | unsigned long arg) | ||
299 | { | ||
300 | struct wm8350 *wm8350 = dev_get_drvdata(dev); | ||
301 | |||
302 | switch (cmd) { | ||
303 | case RTC_AIE_OFF: | ||
304 | return wm8350_rtc_stop_alarm(wm8350); | ||
305 | case RTC_AIE_ON: | ||
306 | return wm8350_rtc_start_alarm(wm8350); | ||
307 | |||
308 | case RTC_UIE_OFF: | ||
309 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
310 | break; | ||
311 | case RTC_UIE_ON: | ||
312 | wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
313 | break; | ||
314 | |||
315 | default: | ||
316 | return -ENOIOCTLCMD; | ||
317 | } | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static void wm8350_rtc_alarm_handler(struct wm8350 *wm8350, int irq, | ||
323 | void *data) | ||
324 | { | ||
325 | struct rtc_device *rtc = wm8350->rtc.rtc; | ||
326 | int ret; | ||
327 | |||
328 | rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF); | ||
329 | |||
330 | /* Make it one shot */ | ||
331 | ret = wm8350_set_bits(wm8350, WM8350_RTC_TIME_CONTROL, | ||
332 | WM8350_RTC_ALMSET); | ||
333 | if (ret != 0) { | ||
334 | dev_err(&(wm8350->rtc.pdev->dev), | ||
335 | "Failed to disable alarm: %d\n", ret); | ||
336 | } | ||
337 | } | ||
338 | |||
339 | static void wm8350_rtc_update_handler(struct wm8350 *wm8350, int irq, | ||
340 | void *data) | ||
341 | { | ||
342 | struct rtc_device *rtc = wm8350->rtc.rtc; | ||
343 | |||
344 | rtc_update_irq(rtc, 1, RTC_IRQF | RTC_UF); | ||
345 | } | ||
346 | |||
347 | static const struct rtc_class_ops wm8350_rtc_ops = { | ||
348 | .ioctl = wm8350_rtc_ioctl, | ||
349 | .read_time = wm8350_rtc_readtime, | ||
350 | .set_time = wm8350_rtc_settime, | ||
351 | .read_alarm = wm8350_rtc_readalarm, | ||
352 | .set_alarm = wm8350_rtc_setalarm, | ||
353 | }; | ||
354 | |||
355 | #ifdef CONFIG_PM | ||
356 | static int wm8350_rtc_suspend(struct platform_device *pdev, pm_message_t state) | ||
357 | { | ||
358 | struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); | ||
359 | int ret = 0; | ||
360 | u16 reg; | ||
361 | |||
362 | reg = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); | ||
363 | |||
364 | if (device_may_wakeup(&wm8350->rtc.pdev->dev) && | ||
365 | reg & WM8350_RTC_ALMSTS) { | ||
366 | ret = wm8350_rtc_stop_alarm(wm8350); | ||
367 | if (ret != 0) | ||
368 | dev_err(&pdev->dev, "Failed to stop RTC alarm: %d\n", | ||
369 | ret); | ||
370 | } | ||
371 | |||
372 | return ret; | ||
373 | } | ||
374 | |||
375 | static int wm8350_rtc_resume(struct platform_device *pdev) | ||
376 | { | ||
377 | struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); | ||
378 | int ret; | ||
379 | |||
380 | if (wm8350->rtc.alarm_enabled) { | ||
381 | ret = wm8350_rtc_start_alarm(wm8350); | ||
382 | if (ret != 0) | ||
383 | dev_err(&pdev->dev, | ||
384 | "Failed to restart RTC alarm: %d\n", ret); | ||
385 | } | ||
386 | |||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | #else | ||
391 | #define wm8350_rtc_suspend NULL | ||
392 | #define wm8350_rtc_resume NULL | ||
393 | #endif | ||
394 | |||
395 | static int wm8350_rtc_probe(struct platform_device *pdev) | ||
396 | { | ||
397 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | ||
398 | struct wm8350_rtc *wm_rtc = &wm8350->rtc; | ||
399 | int ret = 0; | ||
400 | u16 timectl, power5; | ||
401 | |||
402 | timectl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); | ||
403 | if (timectl & WM8350_RTC_BCD) { | ||
404 | dev_err(&pdev->dev, "RTC BCD mode not supported\n"); | ||
405 | return -EINVAL; | ||
406 | } | ||
407 | if (timectl & WM8350_RTC_12HR) { | ||
408 | dev_err(&pdev->dev, "RTC 12 hour mode not supported\n"); | ||
409 | return -EINVAL; | ||
410 | } | ||
411 | |||
412 | /* enable the RTC if it's not already enabled */ | ||
413 | power5 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5); | ||
414 | if (!(power5 & WM8350_RTC_TICK_ENA)) { | ||
415 | dev_info(wm8350->dev, "Starting RTC\n"); | ||
416 | |||
417 | wm8350_reg_unlock(wm8350); | ||
418 | |||
419 | ret = wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, | ||
420 | WM8350_RTC_TICK_ENA); | ||
421 | if (ret < 0) { | ||
422 | dev_err(&pdev->dev, "failed to enable RTC: %d\n", ret); | ||
423 | return ret; | ||
424 | } | ||
425 | |||
426 | wm8350_reg_lock(wm8350); | ||
427 | } | ||
428 | |||
429 | if (timectl & WM8350_RTC_STS) { | ||
430 | int retries; | ||
431 | |||
432 | ret = wm8350_clear_bits(wm8350, WM8350_RTC_TIME_CONTROL, | ||
433 | WM8350_RTC_SET); | ||
434 | if (ret < 0) { | ||
435 | dev_err(&pdev->dev, "failed to start: %d\n", ret); | ||
436 | return ret; | ||
437 | } | ||
438 | |||
439 | retries = WM8350_SET_TIME_RETRIES; | ||
440 | do { | ||
441 | timectl = wm8350_reg_read(wm8350, | ||
442 | WM8350_RTC_TIME_CONTROL); | ||
443 | } while (timectl & WM8350_RTC_STS && retries--); | ||
444 | |||
445 | if (retries == 0) { | ||
446 | dev_err(&pdev->dev, "failed to start: timeout\n"); | ||
447 | return -ENODEV; | ||
448 | } | ||
449 | } | ||
450 | |||
451 | device_init_wakeup(&pdev->dev, 1); | ||
452 | |||
453 | wm_rtc->rtc = rtc_device_register("wm8350", &pdev->dev, | ||
454 | &wm8350_rtc_ops, THIS_MODULE); | ||
455 | if (IS_ERR(wm_rtc->rtc)) { | ||
456 | ret = PTR_ERR(wm_rtc->rtc); | ||
457 | dev_err(&pdev->dev, "failed to register RTC: %d\n", ret); | ||
458 | return ret; | ||
459 | } | ||
460 | |||
461 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
462 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_PER); | ||
463 | |||
464 | wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC, | ||
465 | wm8350_rtc_update_handler, NULL); | ||
466 | |||
467 | wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM, | ||
468 | wm8350_rtc_alarm_handler, NULL); | ||
469 | wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_ALM); | ||
470 | |||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | static int __devexit wm8350_rtc_remove(struct platform_device *pdev) | ||
475 | { | ||
476 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | ||
477 | struct wm8350_rtc *wm_rtc = &wm8350->rtc; | ||
478 | |||
479 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
480 | |||
481 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
482 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM); | ||
483 | |||
484 | rtc_device_unregister(wm_rtc->rtc); | ||
485 | |||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | static struct platform_driver wm8350_rtc_driver = { | ||
490 | .probe = wm8350_rtc_probe, | ||
491 | .remove = __devexit_p(wm8350_rtc_remove), | ||
492 | .suspend = wm8350_rtc_suspend, | ||
493 | .resume = wm8350_rtc_resume, | ||
494 | .driver = { | ||
495 | .name = "wm8350-rtc", | ||
496 | }, | ||
497 | }; | ||
498 | |||
499 | static int __init wm8350_rtc_init(void) | ||
500 | { | ||
501 | return platform_driver_register(&wm8350_rtc_driver); | ||
502 | } | ||
503 | module_init(wm8350_rtc_init); | ||
504 | |||
505 | static void __exit wm8350_rtc_exit(void) | ||
506 | { | ||
507 | platform_driver_unregister(&wm8350_rtc_driver); | ||
508 | } | ||
509 | module_exit(wm8350_rtc_exit); | ||
510 | |||
511 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
512 | MODULE_DESCRIPTION("RTC driver for the WM8350"); | ||
513 | MODULE_LICENSE("GPL"); | ||
514 | MODULE_ALIAS("platform:wm8350-rtc"); | ||
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index 02f9320f3efc..8abae4ad0fa5 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c | |||
@@ -766,6 +766,7 @@ static int __init atmel_spi_probe(struct platform_device *pdev) | |||
766 | /* Initialize the hardware */ | 766 | /* Initialize the hardware */ |
767 | clk_enable(clk); | 767 | clk_enable(clk); |
768 | spi_writel(as, CR, SPI_BIT(SWRST)); | 768 | spi_writel(as, CR, SPI_BIT(SWRST)); |
769 | spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ | ||
769 | spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS)); | 770 | spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS)); |
770 | spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); | 771 | spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); |
771 | spi_writel(as, CR, SPI_BIT(SPIEN)); | 772 | spi_writel(as, CR, SPI_BIT(SPIEN)); |
@@ -782,6 +783,7 @@ static int __init atmel_spi_probe(struct platform_device *pdev) | |||
782 | 783 | ||
783 | out_reset_hw: | 784 | out_reset_hw: |
784 | spi_writel(as, CR, SPI_BIT(SWRST)); | 785 | spi_writel(as, CR, SPI_BIT(SWRST)); |
786 | spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ | ||
785 | clk_disable(clk); | 787 | clk_disable(clk); |
786 | free_irq(irq, master); | 788 | free_irq(irq, master); |
787 | out_unmap_regs: | 789 | out_unmap_regs: |
@@ -805,6 +807,7 @@ static int __exit atmel_spi_remove(struct platform_device *pdev) | |||
805 | spin_lock_irq(&as->lock); | 807 | spin_lock_irq(&as->lock); |
806 | as->stopping = 1; | 808 | as->stopping = 1; |
807 | spi_writel(as, CR, SPI_BIT(SWRST)); | 809 | spi_writel(as, CR, SPI_BIT(SWRST)); |
810 | spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ | ||
808 | spi_readl(as, SR); | 811 | spi_readl(as, SR); |
809 | spin_unlock_irq(&as->lock); | 812 | spin_unlock_irq(&as->lock); |
810 | 813 | ||
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index c4493091c655..a14d5b6e4c7c 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig | |||
@@ -52,5 +52,12 @@ config W1_MASTER_GPIO | |||
52 | This support is also available as a module. If so, the module | 52 | This support is also available as a module. If so, the module |
53 | will be called w1-gpio.ko. | 53 | will be called w1-gpio.ko. |
54 | 54 | ||
55 | config HDQ_MASTER_OMAP | ||
56 | tristate "OMAP HDQ driver" | ||
57 | depends on ARCH_OMAP2430 || ARCH_OMAP34XX | ||
58 | help | ||
59 | Say Y here if you want support for the 1-wire or HDQ Interface | ||
60 | on an OMAP processor. | ||
61 | |||
55 | endmenu | 62 | endmenu |
56 | 63 | ||
diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile index 1420b5bbdda8..bc4714a75f3a 100644 --- a/drivers/w1/masters/Makefile +++ b/drivers/w1/masters/Makefile | |||
@@ -7,3 +7,4 @@ obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o | |||
7 | obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o | 7 | obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o |
8 | obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o | 8 | obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o |
9 | obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o | 9 | obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o |
10 | obj-$(CONFIG_HDQ_MASTER_OMAP) += omap_hdq.o | ||
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c new file mode 100644 index 000000000000..1295625c4825 --- /dev/null +++ b/drivers/w1/masters/omap_hdq.c | |||
@@ -0,0 +1,725 @@ | |||
1 | /* | ||
2 | * drivers/w1/masters/omap_hdq.c | ||
3 | * | ||
4 | * Copyright (C) 2007 Texas Instruments, Inc. | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public License | ||
7 | * version 2. This program is licensed "as is" without any warranty of any | ||
8 | * kind, whether express or implied. | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/clk.h> | ||
17 | #include <linux/io.h> | ||
18 | |||
19 | #include <asm/irq.h> | ||
20 | #include <mach/hardware.h> | ||
21 | |||
22 | #include "../w1.h" | ||
23 | #include "../w1_int.h" | ||
24 | |||
25 | #define MOD_NAME "OMAP_HDQ:" | ||
26 | |||
27 | #define OMAP_HDQ_REVISION 0x00 | ||
28 | #define OMAP_HDQ_TX_DATA 0x04 | ||
29 | #define OMAP_HDQ_RX_DATA 0x08 | ||
30 | #define OMAP_HDQ_CTRL_STATUS 0x0c | ||
31 | #define OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK (1<<6) | ||
32 | #define OMAP_HDQ_CTRL_STATUS_CLOCKENABLE (1<<5) | ||
33 | #define OMAP_HDQ_CTRL_STATUS_GO (1<<4) | ||
34 | #define OMAP_HDQ_CTRL_STATUS_INITIALIZATION (1<<2) | ||
35 | #define OMAP_HDQ_CTRL_STATUS_DIR (1<<1) | ||
36 | #define OMAP_HDQ_CTRL_STATUS_MODE (1<<0) | ||
37 | #define OMAP_HDQ_INT_STATUS 0x10 | ||
38 | #define OMAP_HDQ_INT_STATUS_TXCOMPLETE (1<<2) | ||
39 | #define OMAP_HDQ_INT_STATUS_RXCOMPLETE (1<<1) | ||
40 | #define OMAP_HDQ_INT_STATUS_TIMEOUT (1<<0) | ||
41 | #define OMAP_HDQ_SYSCONFIG 0x14 | ||
42 | #define OMAP_HDQ_SYSCONFIG_SOFTRESET (1<<1) | ||
43 | #define OMAP_HDQ_SYSCONFIG_AUTOIDLE (1<<0) | ||
44 | #define OMAP_HDQ_SYSSTATUS 0x18 | ||
45 | #define OMAP_HDQ_SYSSTATUS_RESETDONE (1<<0) | ||
46 | |||
47 | #define OMAP_HDQ_FLAG_CLEAR 0 | ||
48 | #define OMAP_HDQ_FLAG_SET 1 | ||
49 | #define OMAP_HDQ_TIMEOUT (HZ/5) | ||
50 | |||
51 | #define OMAP_HDQ_MAX_USER 4 | ||
52 | |||
53 | static DECLARE_WAIT_QUEUE_HEAD(hdq_wait_queue); | ||
54 | static int w1_id; | ||
55 | |||
56 | struct hdq_data { | ||
57 | struct device *dev; | ||
58 | void __iomem *hdq_base; | ||
59 | /* lock status update */ | ||
60 | struct mutex hdq_mutex; | ||
61 | int hdq_usecount; | ||
62 | struct clk *hdq_ick; | ||
63 | struct clk *hdq_fck; | ||
64 | u8 hdq_irqstatus; | ||
65 | /* device lock */ | ||
66 | spinlock_t hdq_spinlock; | ||
67 | /* | ||
68 | * Used to control the call to omap_hdq_get and omap_hdq_put. | ||
69 | * HDQ Protocol: Write the CMD|REG_address first, followed by | ||
70 | * the data wrire or read. | ||
71 | */ | ||
72 | int init_trans; | ||
73 | }; | ||
74 | |||
75 | static int __init omap_hdq_probe(struct platform_device *pdev); | ||
76 | static int omap_hdq_remove(struct platform_device *pdev); | ||
77 | |||
78 | static struct platform_driver omap_hdq_driver = { | ||
79 | .probe = omap_hdq_probe, | ||
80 | .remove = omap_hdq_remove, | ||
81 | .driver = { | ||
82 | .name = "omap_hdq", | ||
83 | }, | ||
84 | }; | ||
85 | |||
86 | static u8 omap_w1_read_byte(void *_hdq); | ||
87 | static void omap_w1_write_byte(void *_hdq, u8 byte); | ||
88 | static u8 omap_w1_reset_bus(void *_hdq); | ||
89 | static void omap_w1_search_bus(void *_hdq, u8 search_type, | ||
90 | w1_slave_found_callback slave_found); | ||
91 | |||
92 | |||
93 | static struct w1_bus_master omap_w1_master = { | ||
94 | .read_byte = omap_w1_read_byte, | ||
95 | .write_byte = omap_w1_write_byte, | ||
96 | .reset_bus = omap_w1_reset_bus, | ||
97 | .search = omap_w1_search_bus, | ||
98 | }; | ||
99 | |||
100 | /* HDQ register I/O routines */ | ||
101 | static inline u8 hdq_reg_in(struct hdq_data *hdq_data, u32 offset) | ||
102 | { | ||
103 | return __raw_readb(hdq_data->hdq_base + offset); | ||
104 | } | ||
105 | |||
106 | static inline void hdq_reg_out(struct hdq_data *hdq_data, u32 offset, u8 val) | ||
107 | { | ||
108 | __raw_writeb(val, hdq_data->hdq_base + offset); | ||
109 | } | ||
110 | |||
111 | static inline u8 hdq_reg_merge(struct hdq_data *hdq_data, u32 offset, | ||
112 | u8 val, u8 mask) | ||
113 | { | ||
114 | u8 new_val = (__raw_readb(hdq_data->hdq_base + offset) & ~mask) | ||
115 | | (val & mask); | ||
116 | __raw_writeb(new_val, hdq_data->hdq_base + offset); | ||
117 | |||
118 | return new_val; | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * Wait for one or more bits in flag change. | ||
123 | * HDQ_FLAG_SET: wait until any bit in the flag is set. | ||
124 | * HDQ_FLAG_CLEAR: wait until all bits in the flag are cleared. | ||
125 | * return 0 on success and -ETIMEDOUT in the case of timeout. | ||
126 | */ | ||
127 | static int hdq_wait_for_flag(struct hdq_data *hdq_data, u32 offset, | ||
128 | u8 flag, u8 flag_set, u8 *status) | ||
129 | { | ||
130 | int ret = 0; | ||
131 | unsigned long timeout = jiffies + OMAP_HDQ_TIMEOUT; | ||
132 | |||
133 | if (flag_set == OMAP_HDQ_FLAG_CLEAR) { | ||
134 | /* wait for the flag clear */ | ||
135 | while (((*status = hdq_reg_in(hdq_data, offset)) & flag) | ||
136 | && time_before(jiffies, timeout)) { | ||
137 | schedule_timeout_uninterruptible(1); | ||
138 | } | ||
139 | if (*status & flag) | ||
140 | ret = -ETIMEDOUT; | ||
141 | } else if (flag_set == OMAP_HDQ_FLAG_SET) { | ||
142 | /* wait for the flag set */ | ||
143 | while (!((*status = hdq_reg_in(hdq_data, offset)) & flag) | ||
144 | && time_before(jiffies, timeout)) { | ||
145 | schedule_timeout_uninterruptible(1); | ||
146 | } | ||
147 | if (!(*status & flag)) | ||
148 | ret = -ETIMEDOUT; | ||
149 | } else | ||
150 | return -EINVAL; | ||
151 | |||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | /* write out a byte and fill *status with HDQ_INT_STATUS */ | ||
156 | static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status) | ||
157 | { | ||
158 | int ret; | ||
159 | u8 tmp_status; | ||
160 | unsigned long irqflags; | ||
161 | |||
162 | *status = 0; | ||
163 | |||
164 | spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags); | ||
165 | /* clear interrupt flags via a dummy read */ | ||
166 | hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS); | ||
167 | /* ISR loads it with new INT_STATUS */ | ||
168 | hdq_data->hdq_irqstatus = 0; | ||
169 | spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags); | ||
170 | |||
171 | hdq_reg_out(hdq_data, OMAP_HDQ_TX_DATA, val); | ||
172 | |||
173 | /* set the GO bit */ | ||
174 | hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, OMAP_HDQ_CTRL_STATUS_GO, | ||
175 | OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO); | ||
176 | /* wait for the TXCOMPLETE bit */ | ||
177 | ret = wait_event_timeout(hdq_wait_queue, | ||
178 | hdq_data->hdq_irqstatus, OMAP_HDQ_TIMEOUT); | ||
179 | if (ret == 0) { | ||
180 | dev_dbg(hdq_data->dev, "TX wait elapsed\n"); | ||
181 | goto out; | ||
182 | } | ||
183 | |||
184 | *status = hdq_data->hdq_irqstatus; | ||
185 | /* check irqstatus */ | ||
186 | if (!(*status & OMAP_HDQ_INT_STATUS_TXCOMPLETE)) { | ||
187 | dev_dbg(hdq_data->dev, "timeout waiting for" | ||
188 | "TXCOMPLETE/RXCOMPLETE, %x", *status); | ||
189 | ret = -ETIMEDOUT; | ||
190 | goto out; | ||
191 | } | ||
192 | |||
193 | /* wait for the GO bit return to zero */ | ||
194 | ret = hdq_wait_for_flag(hdq_data, OMAP_HDQ_CTRL_STATUS, | ||
195 | OMAP_HDQ_CTRL_STATUS_GO, | ||
196 | OMAP_HDQ_FLAG_CLEAR, &tmp_status); | ||
197 | if (ret) { | ||
198 | dev_dbg(hdq_data->dev, "timeout waiting GO bit" | ||
199 | "return to zero, %x", tmp_status); | ||
200 | } | ||
201 | |||
202 | out: | ||
203 | return ret; | ||
204 | } | ||
205 | |||
206 | /* HDQ Interrupt service routine */ | ||
207 | static irqreturn_t hdq_isr(int irq, void *_hdq) | ||
208 | { | ||
209 | struct hdq_data *hdq_data = _hdq; | ||
210 | unsigned long irqflags; | ||
211 | |||
212 | spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags); | ||
213 | hdq_data->hdq_irqstatus = hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS); | ||
214 | spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags); | ||
215 | dev_dbg(hdq_data->dev, "hdq_isr: %x", hdq_data->hdq_irqstatus); | ||
216 | |||
217 | if (hdq_data->hdq_irqstatus & | ||
218 | (OMAP_HDQ_INT_STATUS_TXCOMPLETE | OMAP_HDQ_INT_STATUS_RXCOMPLETE | ||
219 | | OMAP_HDQ_INT_STATUS_TIMEOUT)) { | ||
220 | /* wake up sleeping process */ | ||
221 | wake_up(&hdq_wait_queue); | ||
222 | } | ||
223 | |||
224 | return IRQ_HANDLED; | ||
225 | } | ||
226 | |||
227 | /* HDQ Mode: always return success */ | ||
228 | static u8 omap_w1_reset_bus(void *_hdq) | ||
229 | { | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | /* W1 search callback function */ | ||
234 | static void omap_w1_search_bus(void *_hdq, u8 search_type, | ||
235 | w1_slave_found_callback slave_found) | ||
236 | { | ||
237 | u64 module_id, rn_le, cs, id; | ||
238 | |||
239 | if (w1_id) | ||
240 | module_id = w1_id; | ||
241 | else | ||
242 | module_id = 0x1; | ||
243 | |||
244 | rn_le = cpu_to_le64(module_id); | ||
245 | /* | ||
246 | * HDQ might not obey truly the 1-wire spec. | ||
247 | * So calculate CRC based on module parameter. | ||
248 | */ | ||
249 | cs = w1_calc_crc8((u8 *)&rn_le, 7); | ||
250 | id = (cs << 56) | module_id; | ||
251 | |||
252 | slave_found(_hdq, id); | ||
253 | } | ||
254 | |||
255 | static int _omap_hdq_reset(struct hdq_data *hdq_data) | ||
256 | { | ||
257 | int ret; | ||
258 | u8 tmp_status; | ||
259 | |||
260 | hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG, OMAP_HDQ_SYSCONFIG_SOFTRESET); | ||
261 | /* | ||
262 | * Select HDQ mode & enable clocks. | ||
263 | * It is observed that INT flags can't be cleared via a read and GO/INIT | ||
264 | * won't return to zero if interrupt is disabled. So we always enable | ||
265 | * interrupt. | ||
266 | */ | ||
267 | hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS, | ||
268 | OMAP_HDQ_CTRL_STATUS_CLOCKENABLE | | ||
269 | OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK); | ||
270 | |||
271 | /* wait for reset to complete */ | ||
272 | ret = hdq_wait_for_flag(hdq_data, OMAP_HDQ_SYSSTATUS, | ||
273 | OMAP_HDQ_SYSSTATUS_RESETDONE, OMAP_HDQ_FLAG_SET, &tmp_status); | ||
274 | if (ret) | ||
275 | dev_dbg(hdq_data->dev, "timeout waiting HDQ reset, %x", | ||
276 | tmp_status); | ||
277 | else { | ||
278 | hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS, | ||
279 | OMAP_HDQ_CTRL_STATUS_CLOCKENABLE | | ||
280 | OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK); | ||
281 | hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG, | ||
282 | OMAP_HDQ_SYSCONFIG_AUTOIDLE); | ||
283 | } | ||
284 | |||
285 | return ret; | ||
286 | } | ||
287 | |||
288 | /* Issue break pulse to the device */ | ||
289 | static int omap_hdq_break(struct hdq_data *hdq_data) | ||
290 | { | ||
291 | int ret = 0; | ||
292 | u8 tmp_status; | ||
293 | unsigned long irqflags; | ||
294 | |||
295 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | ||
296 | if (ret < 0) { | ||
297 | dev_dbg(hdq_data->dev, "Could not acquire mutex\n"); | ||
298 | ret = -EINTR; | ||
299 | goto rtn; | ||
300 | } | ||
301 | |||
302 | spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags); | ||
303 | /* clear interrupt flags via a dummy read */ | ||
304 | hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS); | ||
305 | /* ISR loads it with new INT_STATUS */ | ||
306 | hdq_data->hdq_irqstatus = 0; | ||
307 | spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags); | ||
308 | |||
309 | /* set the INIT and GO bit */ | ||
310 | hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, | ||
311 | OMAP_HDQ_CTRL_STATUS_INITIALIZATION | OMAP_HDQ_CTRL_STATUS_GO, | ||
312 | OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_INITIALIZATION | | ||
313 | OMAP_HDQ_CTRL_STATUS_GO); | ||
314 | |||
315 | /* wait for the TIMEOUT bit */ | ||
316 | ret = wait_event_timeout(hdq_wait_queue, | ||
317 | hdq_data->hdq_irqstatus, OMAP_HDQ_TIMEOUT); | ||
318 | if (ret == 0) { | ||
319 | dev_dbg(hdq_data->dev, "break wait elapsed\n"); | ||
320 | ret = -EINTR; | ||
321 | goto out; | ||
322 | } | ||
323 | |||
324 | tmp_status = hdq_data->hdq_irqstatus; | ||
325 | /* check irqstatus */ | ||
326 | if (!(tmp_status & OMAP_HDQ_INT_STATUS_TIMEOUT)) { | ||
327 | dev_dbg(hdq_data->dev, "timeout waiting for TIMEOUT, %x", | ||
328 | tmp_status); | ||
329 | ret = -ETIMEDOUT; | ||
330 | goto out; | ||
331 | } | ||
332 | /* | ||
333 | * wait for both INIT and GO bits rerurn to zero. | ||
334 | * zero wait time expected for interrupt mode. | ||
335 | */ | ||
336 | ret = hdq_wait_for_flag(hdq_data, OMAP_HDQ_CTRL_STATUS, | ||
337 | OMAP_HDQ_CTRL_STATUS_INITIALIZATION | | ||
338 | OMAP_HDQ_CTRL_STATUS_GO, OMAP_HDQ_FLAG_CLEAR, | ||
339 | &tmp_status); | ||
340 | if (ret) | ||
341 | dev_dbg(hdq_data->dev, "timeout waiting INIT&GO bits" | ||
342 | "return to zero, %x", tmp_status); | ||
343 | |||
344 | out: | ||
345 | mutex_unlock(&hdq_data->hdq_mutex); | ||
346 | rtn: | ||
347 | return ret; | ||
348 | } | ||
349 | |||
350 | static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val) | ||
351 | { | ||
352 | int ret = 0; | ||
353 | u8 status; | ||
354 | unsigned long timeout = jiffies + OMAP_HDQ_TIMEOUT; | ||
355 | |||
356 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | ||
357 | if (ret < 0) { | ||
358 | ret = -EINTR; | ||
359 | goto rtn; | ||
360 | } | ||
361 | |||
362 | if (!hdq_data->hdq_usecount) { | ||
363 | ret = -EINVAL; | ||
364 | goto out; | ||
365 | } | ||
366 | |||
367 | if (!(hdq_data->hdq_irqstatus & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) { | ||
368 | hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, | ||
369 | OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO, | ||
370 | OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO); | ||
371 | /* | ||
372 | * The RX comes immediately after TX. It | ||
373 | * triggers another interrupt before we | ||
374 | * sleep. So we have to wait for RXCOMPLETE bit. | ||
375 | */ | ||
376 | while (!(hdq_data->hdq_irqstatus | ||
377 | & OMAP_HDQ_INT_STATUS_RXCOMPLETE) | ||
378 | && time_before(jiffies, timeout)) { | ||
379 | schedule_timeout_uninterruptible(1); | ||
380 | } | ||
381 | hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, 0, | ||
382 | OMAP_HDQ_CTRL_STATUS_DIR); | ||
383 | status = hdq_data->hdq_irqstatus; | ||
384 | /* check irqstatus */ | ||
385 | if (!(status & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) { | ||
386 | dev_dbg(hdq_data->dev, "timeout waiting for" | ||
387 | "RXCOMPLETE, %x", status); | ||
388 | ret = -ETIMEDOUT; | ||
389 | goto out; | ||
390 | } | ||
391 | } | ||
392 | /* the data is ready. Read it in! */ | ||
393 | *val = hdq_reg_in(hdq_data, OMAP_HDQ_RX_DATA); | ||
394 | out: | ||
395 | mutex_unlock(&hdq_data->hdq_mutex); | ||
396 | rtn: | ||
397 | return 0; | ||
398 | |||
399 | } | ||
400 | |||
401 | /* Enable clocks and set the controller to HDQ mode */ | ||
402 | static int omap_hdq_get(struct hdq_data *hdq_data) | ||
403 | { | ||
404 | int ret = 0; | ||
405 | |||
406 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | ||
407 | if (ret < 0) { | ||
408 | ret = -EINTR; | ||
409 | goto rtn; | ||
410 | } | ||
411 | |||
412 | if (OMAP_HDQ_MAX_USER == hdq_data->hdq_usecount) { | ||
413 | dev_dbg(hdq_data->dev, "attempt to exceed the max use count"); | ||
414 | ret = -EINVAL; | ||
415 | goto out; | ||
416 | } else { | ||
417 | hdq_data->hdq_usecount++; | ||
418 | try_module_get(THIS_MODULE); | ||
419 | if (1 == hdq_data->hdq_usecount) { | ||
420 | if (clk_enable(hdq_data->hdq_ick)) { | ||
421 | dev_dbg(hdq_data->dev, "Can not enable ick\n"); | ||
422 | ret = -ENODEV; | ||
423 | goto clk_err; | ||
424 | } | ||
425 | if (clk_enable(hdq_data->hdq_fck)) { | ||
426 | dev_dbg(hdq_data->dev, "Can not enable fck\n"); | ||
427 | clk_disable(hdq_data->hdq_ick); | ||
428 | ret = -ENODEV; | ||
429 | goto clk_err; | ||
430 | } | ||
431 | |||
432 | /* make sure HDQ is out of reset */ | ||
433 | if (!(hdq_reg_in(hdq_data, OMAP_HDQ_SYSSTATUS) & | ||
434 | OMAP_HDQ_SYSSTATUS_RESETDONE)) { | ||
435 | ret = _omap_hdq_reset(hdq_data); | ||
436 | if (ret) | ||
437 | /* back up the count */ | ||
438 | hdq_data->hdq_usecount--; | ||
439 | } else { | ||
440 | /* select HDQ mode & enable clocks */ | ||
441 | hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS, | ||
442 | OMAP_HDQ_CTRL_STATUS_CLOCKENABLE | | ||
443 | OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK); | ||
444 | hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG, | ||
445 | OMAP_HDQ_SYSCONFIG_AUTOIDLE); | ||
446 | hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS); | ||
447 | } | ||
448 | } | ||
449 | } | ||
450 | |||
451 | clk_err: | ||
452 | clk_put(hdq_data->hdq_ick); | ||
453 | clk_put(hdq_data->hdq_fck); | ||
454 | out: | ||
455 | mutex_unlock(&hdq_data->hdq_mutex); | ||
456 | rtn: | ||
457 | return ret; | ||
458 | } | ||
459 | |||
460 | /* Disable clocks to the module */ | ||
461 | static int omap_hdq_put(struct hdq_data *hdq_data) | ||
462 | { | ||
463 | int ret = 0; | ||
464 | |||
465 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | ||
466 | if (ret < 0) | ||
467 | return -EINTR; | ||
468 | |||
469 | if (0 == hdq_data->hdq_usecount) { | ||
470 | dev_dbg(hdq_data->dev, "attempt to decrement use count" | ||
471 | "when it is zero"); | ||
472 | ret = -EINVAL; | ||
473 | } else { | ||
474 | hdq_data->hdq_usecount--; | ||
475 | module_put(THIS_MODULE); | ||
476 | if (0 == hdq_data->hdq_usecount) { | ||
477 | clk_disable(hdq_data->hdq_ick); | ||
478 | clk_disable(hdq_data->hdq_fck); | ||
479 | } | ||
480 | } | ||
481 | mutex_unlock(&hdq_data->hdq_mutex); | ||
482 | |||
483 | return ret; | ||
484 | } | ||
485 | |||
486 | /* Read a byte of data from the device */ | ||
487 | static u8 omap_w1_read_byte(void *_hdq) | ||
488 | { | ||
489 | struct hdq_data *hdq_data = _hdq; | ||
490 | u8 val = 0; | ||
491 | int ret; | ||
492 | |||
493 | ret = hdq_read_byte(hdq_data, &val); | ||
494 | if (ret) { | ||
495 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | ||
496 | if (ret < 0) { | ||
497 | dev_dbg(hdq_data->dev, "Could not acquire mutex\n"); | ||
498 | return -EINTR; | ||
499 | } | ||
500 | hdq_data->init_trans = 0; | ||
501 | mutex_unlock(&hdq_data->hdq_mutex); | ||
502 | omap_hdq_put(hdq_data); | ||
503 | return -1; | ||
504 | } | ||
505 | |||
506 | /* Write followed by a read, release the module */ | ||
507 | if (hdq_data->init_trans) { | ||
508 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | ||
509 | if (ret < 0) { | ||
510 | dev_dbg(hdq_data->dev, "Could not acquire mutex\n"); | ||
511 | return -EINTR; | ||
512 | } | ||
513 | hdq_data->init_trans = 0; | ||
514 | mutex_unlock(&hdq_data->hdq_mutex); | ||
515 | omap_hdq_put(hdq_data); | ||
516 | } | ||
517 | |||
518 | return val; | ||
519 | } | ||
520 | |||
521 | /* Write a byte of data to the device */ | ||
522 | static void omap_w1_write_byte(void *_hdq, u8 byte) | ||
523 | { | ||
524 | struct hdq_data *hdq_data = _hdq; | ||
525 | int ret; | ||
526 | u8 status; | ||
527 | |||
528 | /* First write to initialize the transfer */ | ||
529 | if (hdq_data->init_trans == 0) | ||
530 | omap_hdq_get(hdq_data); | ||
531 | |||
532 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | ||
533 | if (ret < 0) { | ||
534 | dev_dbg(hdq_data->dev, "Could not acquire mutex\n"); | ||
535 | return; | ||
536 | } | ||
537 | hdq_data->init_trans++; | ||
538 | mutex_unlock(&hdq_data->hdq_mutex); | ||
539 | |||
540 | ret = hdq_write_byte(hdq_data, byte, &status); | ||
541 | if (ret == 0) { | ||
542 | dev_dbg(hdq_data->dev, "TX failure:Ctrl status %x\n", status); | ||
543 | return; | ||
544 | } | ||
545 | |||
546 | /* Second write, data transfered. Release the module */ | ||
547 | if (hdq_data->init_trans > 1) { | ||
548 | omap_hdq_put(hdq_data); | ||
549 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | ||
550 | if (ret < 0) { | ||
551 | dev_dbg(hdq_data->dev, "Could not acquire mutex\n"); | ||
552 | return; | ||
553 | } | ||
554 | hdq_data->init_trans = 0; | ||
555 | mutex_unlock(&hdq_data->hdq_mutex); | ||
556 | } | ||
557 | |||
558 | return; | ||
559 | } | ||
560 | |||
561 | static int __init omap_hdq_probe(struct platform_device *pdev) | ||
562 | { | ||
563 | struct hdq_data *hdq_data; | ||
564 | struct resource *res; | ||
565 | int ret, irq; | ||
566 | u8 rev; | ||
567 | |||
568 | hdq_data = kmalloc(sizeof(*hdq_data), GFP_KERNEL); | ||
569 | if (!hdq_data) { | ||
570 | dev_dbg(&pdev->dev, "unable to allocate memory\n"); | ||
571 | ret = -ENOMEM; | ||
572 | goto err_kmalloc; | ||
573 | } | ||
574 | |||
575 | hdq_data->dev = &pdev->dev; | ||
576 | platform_set_drvdata(pdev, hdq_data); | ||
577 | |||
578 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
579 | if (!res) { | ||
580 | dev_dbg(&pdev->dev, "unable to get resource\n"); | ||
581 | ret = -ENXIO; | ||
582 | goto err_resource; | ||
583 | } | ||
584 | |||
585 | hdq_data->hdq_base = ioremap(res->start, SZ_4K); | ||
586 | if (!hdq_data->hdq_base) { | ||
587 | dev_dbg(&pdev->dev, "ioremap failed\n"); | ||
588 | ret = -EINVAL; | ||
589 | goto err_ioremap; | ||
590 | } | ||
591 | |||
592 | /* get interface & functional clock objects */ | ||
593 | hdq_data->hdq_ick = clk_get(&pdev->dev, "hdq_ick"); | ||
594 | hdq_data->hdq_fck = clk_get(&pdev->dev, "hdq_fck"); | ||
595 | |||
596 | if (IS_ERR(hdq_data->hdq_ick) || IS_ERR(hdq_data->hdq_fck)) { | ||
597 | dev_dbg(&pdev->dev, "Can't get HDQ clock objects\n"); | ||
598 | if (IS_ERR(hdq_data->hdq_ick)) { | ||
599 | ret = PTR_ERR(hdq_data->hdq_ick); | ||
600 | goto err_clk; | ||
601 | } | ||
602 | if (IS_ERR(hdq_data->hdq_fck)) { | ||
603 | ret = PTR_ERR(hdq_data->hdq_fck); | ||
604 | clk_put(hdq_data->hdq_ick); | ||
605 | goto err_clk; | ||
606 | } | ||
607 | } | ||
608 | |||
609 | hdq_data->hdq_usecount = 0; | ||
610 | mutex_init(&hdq_data->hdq_mutex); | ||
611 | |||
612 | if (clk_enable(hdq_data->hdq_ick)) { | ||
613 | dev_dbg(&pdev->dev, "Can not enable ick\n"); | ||
614 | ret = -ENODEV; | ||
615 | goto err_intfclk; | ||
616 | } | ||
617 | |||
618 | if (clk_enable(hdq_data->hdq_fck)) { | ||
619 | dev_dbg(&pdev->dev, "Can not enable fck\n"); | ||
620 | ret = -ENODEV; | ||
621 | goto err_fnclk; | ||
622 | } | ||
623 | |||
624 | rev = hdq_reg_in(hdq_data, OMAP_HDQ_REVISION); | ||
625 | dev_info(&pdev->dev, "OMAP HDQ Hardware Rev %c.%c. Driver in %s mode\n", | ||
626 | (rev >> 4) + '0', (rev & 0x0f) + '0', "Interrupt"); | ||
627 | |||
628 | spin_lock_init(&hdq_data->hdq_spinlock); | ||
629 | |||
630 | irq = platform_get_irq(pdev, 0); | ||
631 | if (irq < 0) { | ||
632 | ret = -ENXIO; | ||
633 | goto err_irq; | ||
634 | } | ||
635 | |||
636 | ret = request_irq(irq, hdq_isr, IRQF_DISABLED, "omap_hdq", hdq_data); | ||
637 | if (ret < 0) { | ||
638 | dev_dbg(&pdev->dev, "could not request irq\n"); | ||
639 | goto err_irq; | ||
640 | } | ||
641 | |||
642 | omap_hdq_break(hdq_data); | ||
643 | |||
644 | /* don't clock the HDQ until it is needed */ | ||
645 | clk_disable(hdq_data->hdq_ick); | ||
646 | clk_disable(hdq_data->hdq_fck); | ||
647 | |||
648 | omap_w1_master.data = hdq_data; | ||
649 | |||
650 | ret = w1_add_master_device(&omap_w1_master); | ||
651 | if (ret) { | ||
652 | dev_dbg(&pdev->dev, "Failure in registering w1 master\n"); | ||
653 | goto err_w1; | ||
654 | } | ||
655 | |||
656 | return 0; | ||
657 | |||
658 | err_w1: | ||
659 | err_irq: | ||
660 | clk_disable(hdq_data->hdq_fck); | ||
661 | |||
662 | err_fnclk: | ||
663 | clk_disable(hdq_data->hdq_ick); | ||
664 | |||
665 | err_intfclk: | ||
666 | clk_put(hdq_data->hdq_ick); | ||
667 | clk_put(hdq_data->hdq_fck); | ||
668 | |||
669 | err_clk: | ||
670 | iounmap(hdq_data->hdq_base); | ||
671 | |||
672 | err_ioremap: | ||
673 | err_resource: | ||
674 | platform_set_drvdata(pdev, NULL); | ||
675 | kfree(hdq_data); | ||
676 | |||
677 | err_kmalloc: | ||
678 | return ret; | ||
679 | |||
680 | } | ||
681 | |||
682 | static int omap_hdq_remove(struct platform_device *pdev) | ||
683 | { | ||
684 | struct hdq_data *hdq_data = platform_get_drvdata(pdev); | ||
685 | |||
686 | mutex_lock(&hdq_data->hdq_mutex); | ||
687 | |||
688 | if (hdq_data->hdq_usecount) { | ||
689 | dev_dbg(&pdev->dev, "removed when use count is not zero\n"); | ||
690 | return -EBUSY; | ||
691 | } | ||
692 | |||
693 | mutex_unlock(&hdq_data->hdq_mutex); | ||
694 | |||
695 | /* remove module dependency */ | ||
696 | clk_put(hdq_data->hdq_ick); | ||
697 | clk_put(hdq_data->hdq_fck); | ||
698 | free_irq(INT_24XX_HDQ_IRQ, hdq_data); | ||
699 | platform_set_drvdata(pdev, NULL); | ||
700 | iounmap(hdq_data->hdq_base); | ||
701 | kfree(hdq_data); | ||
702 | |||
703 | return 0; | ||
704 | } | ||
705 | |||
706 | static int __init | ||
707 | omap_hdq_init(void) | ||
708 | { | ||
709 | return platform_driver_register(&omap_hdq_driver); | ||
710 | } | ||
711 | module_init(omap_hdq_init); | ||
712 | |||
713 | static void __exit | ||
714 | omap_hdq_exit(void) | ||
715 | { | ||
716 | platform_driver_unregister(&omap_hdq_driver); | ||
717 | } | ||
718 | module_exit(omap_hdq_exit); | ||
719 | |||
720 | module_param(w1_id, int, S_IRUSR); | ||
721 | MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection"); | ||
722 | |||
723 | MODULE_AUTHOR("Texas Instruments"); | ||
724 | MODULE_DESCRIPTION("HDQ driver Library"); | ||
725 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig index 3df29a122f84..8d0b1fb1e52e 100644 --- a/drivers/w1/slaves/Kconfig +++ b/drivers/w1/slaves/Kconfig | |||
@@ -44,4 +44,11 @@ config W1_SLAVE_DS2760 | |||
44 | 44 | ||
45 | If you are unsure, say N. | 45 | If you are unsure, say N. |
46 | 46 | ||
47 | config W1_SLAVE_BQ27000 | ||
48 | tristate "BQ27000 slave support" | ||
49 | depends on W1 | ||
50 | help | ||
51 | Say Y here if you want to use a hdq | ||
52 | bq27000 slave support. | ||
53 | |||
47 | endmenu | 54 | endmenu |
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile index a8eb7524df1d..990f400b6d22 100644 --- a/drivers/w1/slaves/Makefile +++ b/drivers/w1/slaves/Makefile | |||
@@ -6,4 +6,4 @@ obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o | |||
6 | obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o | 6 | obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o |
7 | obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o | 7 | obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o |
8 | obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o | 8 | obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o |
9 | 9 | obj-$(CONFIG_W1_SLAVE_BQ27000) += w1_bq27000.o | |
diff --git a/drivers/w1/slaves/w1_bq27000.c b/drivers/w1/slaves/w1_bq27000.c new file mode 100644 index 000000000000..8f4c91f6c680 --- /dev/null +++ b/drivers/w1/slaves/w1_bq27000.c | |||
@@ -0,0 +1,123 @@ | |||
1 | /* | ||
2 | * drivers/w1/slaves/w1_bq27000.c | ||
3 | * | ||
4 | * Copyright (C) 2007 Texas Instruments, Inc. | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public License | ||
7 | * version 2. This program is licensed "as is" without any warranty of any | ||
8 | * kind, whether express or implied. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/types.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/mutex.h> | ||
18 | |||
19 | #include "../w1.h" | ||
20 | #include "../w1_int.h" | ||
21 | #include "../w1_family.h" | ||
22 | |||
23 | #define HDQ_CMD_READ (0) | ||
24 | #define HDQ_CMD_WRITE (1<<7) | ||
25 | |||
26 | static int F_ID; | ||
27 | |||
28 | void w1_bq27000_write(struct device *dev, u8 buf, u8 reg) | ||
29 | { | ||
30 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | ||
31 | |||
32 | if (!dev) { | ||
33 | pr_info("Could not obtain slave dev ptr\n"); | ||
34 | return; | ||
35 | } | ||
36 | |||
37 | w1_write_8(sl->master, HDQ_CMD_WRITE | reg); | ||
38 | w1_write_8(sl->master, buf); | ||
39 | } | ||
40 | EXPORT_SYMBOL(w1_bq27000_write); | ||
41 | |||
42 | int w1_bq27000_read(struct device *dev, u8 reg) | ||
43 | { | ||
44 | u8 val; | ||
45 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | ||
46 | |||
47 | if (!dev) | ||
48 | return 0; | ||
49 | |||
50 | w1_write_8(sl->master, HDQ_CMD_READ | reg); | ||
51 | val = w1_read_8(sl->master); | ||
52 | |||
53 | return val; | ||
54 | } | ||
55 | EXPORT_SYMBOL(w1_bq27000_read); | ||
56 | |||
57 | static int w1_bq27000_add_slave(struct w1_slave *sl) | ||
58 | { | ||
59 | int ret; | ||
60 | int id = 1; | ||
61 | struct platform_device *pdev; | ||
62 | |||
63 | pdev = platform_device_alloc("bq27000-battery", id); | ||
64 | if (!pdev) { | ||
65 | ret = -ENOMEM; | ||
66 | return ret; | ||
67 | } | ||
68 | pdev->dev.parent = &sl->dev; | ||
69 | |||
70 | ret = platform_device_add(pdev); | ||
71 | if (ret) | ||
72 | goto pdev_add_failed; | ||
73 | |||
74 | dev_set_drvdata(&sl->dev, pdev); | ||
75 | |||
76 | goto success; | ||
77 | |||
78 | pdev_add_failed: | ||
79 | platform_device_unregister(pdev); | ||
80 | success: | ||
81 | return ret; | ||
82 | } | ||
83 | |||
84 | static void w1_bq27000_remove_slave(struct w1_slave *sl) | ||
85 | { | ||
86 | struct platform_device *pdev = dev_get_drvdata(&sl->dev); | ||
87 | |||
88 | platform_device_unregister(pdev); | ||
89 | } | ||
90 | |||
91 | static struct w1_family_ops w1_bq27000_fops = { | ||
92 | .add_slave = w1_bq27000_add_slave, | ||
93 | .remove_slave = w1_bq27000_remove_slave, | ||
94 | }; | ||
95 | |||
96 | static struct w1_family w1_bq27000_family = { | ||
97 | .fid = 1, | ||
98 | .fops = &w1_bq27000_fops, | ||
99 | }; | ||
100 | |||
101 | static int __init w1_bq27000_init(void) | ||
102 | { | ||
103 | if (F_ID) | ||
104 | w1_bq27000_family.fid = F_ID; | ||
105 | |||
106 | return w1_register_family(&w1_bq27000_family); | ||
107 | } | ||
108 | |||
109 | static void __exit w1_bq27000_exit(void) | ||
110 | { | ||
111 | w1_unregister_family(&w1_bq27000_family); | ||
112 | } | ||
113 | |||
114 | |||
115 | module_init(w1_bq27000_init); | ||
116 | module_exit(w1_bq27000_exit); | ||
117 | |||
118 | module_param(F_ID, int, S_IRUSR); | ||
119 | MODULE_PARM_DESC(F_ID, "1-wire slave FID for BQ device"); | ||
120 | |||
121 | MODULE_LICENSE("GPL"); | ||
122 | MODULE_AUTHOR("Texas Instruments Ltd"); | ||
123 | MODULE_DESCRIPTION("HDQ/1-wire slave driver bq27000 battery monitor chip"); | ||
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index cdaa6fffbfc7..97304bd83ec9 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h | |||
@@ -206,6 +206,7 @@ void w1_slave_detach(struct w1_slave *sl); | |||
206 | 206 | ||
207 | u8 w1_triplet(struct w1_master *dev, int bdir); | 207 | u8 w1_triplet(struct w1_master *dev, int bdir); |
208 | void w1_write_8(struct w1_master *, u8); | 208 | void w1_write_8(struct w1_master *, u8); |
209 | u8 w1_read_8(struct w1_master *); | ||
209 | int w1_reset_bus(struct w1_master *); | 210 | int w1_reset_bus(struct w1_master *); |
210 | u8 w1_calc_crc8(u8 *, int); | 211 | u8 w1_calc_crc8(u8 *, int); |
211 | void w1_write_block(struct w1_master *, const u8 *, int); | 212 | void w1_write_block(struct w1_master *, const u8 *, int); |
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c index f4f82f1f486e..0d15b0eaf79a 100644 --- a/drivers/w1/w1_io.c +++ b/drivers/w1/w1_io.c | |||
@@ -217,7 +217,7 @@ u8 w1_triplet(struct w1_master *dev, int bdir) | |||
217 | * @param dev the master device | 217 | * @param dev the master device |
218 | * @return the byte read | 218 | * @return the byte read |
219 | */ | 219 | */ |
220 | static u8 w1_read_8(struct w1_master * dev) | 220 | u8 w1_read_8(struct w1_master *dev) |
221 | { | 221 | { |
222 | int i; | 222 | int i; |
223 | u8 res = 0; | 223 | u8 res = 0; |
@@ -230,6 +230,7 @@ static u8 w1_read_8(struct w1_master * dev) | |||
230 | 230 | ||
231 | return res; | 231 | return res; |
232 | } | 232 | } |
233 | EXPORT_SYMBOL_GPL(w1_read_8); | ||
233 | 234 | ||
234 | /** | 235 | /** |
235 | * Writes a series of bytes. | 236 | * Writes a series of bytes. |
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index d910501de6d2..8d86b7960f0d 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c | |||
@@ -812,7 +812,7 @@ int dlm_release_lockspace(void *lockspace, int force) | |||
812 | error = release_lockspace(ls, force); | 812 | error = release_lockspace(ls, force); |
813 | if (!error) | 813 | if (!error) |
814 | ls_count--; | 814 | ls_count--; |
815 | else if (!ls_count) | 815 | if (!ls_count) |
816 | threads_stop(); | 816 | threads_stop(); |
817 | mutex_unlock(&ls_lock); | 817 | mutex_unlock(&ls_lock); |
818 | 818 | ||
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 5dec6d1356c4..f6c94f232ec1 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -2375,12 +2375,9 @@ int ext3_force_commit(struct super_block *sb) | |||
2375 | /* | 2375 | /* |
2376 | * Ext3 always journals updates to the superblock itself, so we don't | 2376 | * Ext3 always journals updates to the superblock itself, so we don't |
2377 | * have to propagate any other updates to the superblock on disk at this | 2377 | * have to propagate any other updates to the superblock on disk at this |
2378 | * point. Just start an async writeback to get the buffers on their way | 2378 | * point. (We can probably nuke this function altogether, and remove |
2379 | * to the disk. | 2379 | * any mention to sb->s_dirt in all of fs/ext3; eventual cleanup...) |
2380 | * | ||
2381 | * This implicitly triggers the writebehind on sync(). | ||
2382 | */ | 2380 | */ |
2383 | |||
2384 | static void ext3_write_super (struct super_block * sb) | 2381 | static void ext3_write_super (struct super_block * sb) |
2385 | { | 2382 | { |
2386 | if (mutex_trylock(&sb->s_lock) != 0) | 2383 | if (mutex_trylock(&sb->s_lock) != 0) |
diff --git a/fs/namespace.c b/fs/namespace.c index cce46702d33c..65b3dc844c87 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -1815,8 +1815,8 @@ static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts) | |||
1815 | while (!list_empty(&graveyard)) { | 1815 | while (!list_empty(&graveyard)) { |
1816 | m = list_first_entry(&graveyard, struct vfsmount, | 1816 | m = list_first_entry(&graveyard, struct vfsmount, |
1817 | mnt_expire); | 1817 | mnt_expire); |
1818 | touch_mnt_namespace(mnt->mnt_ns); | 1818 | touch_mnt_namespace(m->mnt_ns); |
1819 | umount_tree(mnt, 1, umounts); | 1819 | umount_tree(m, 1, umounts); |
1820 | } | 1820 | } |
1821 | } | 1821 | } |
1822 | } | 1822 | } |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 54a279e44c9a..e9f6574930ef 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -380,6 +380,8 @@ struct acpi_bus_type { | |||
380 | int register_acpi_bus_type(struct acpi_bus_type *); | 380 | int register_acpi_bus_type(struct acpi_bus_type *); |
381 | int unregister_acpi_bus_type(struct acpi_bus_type *); | 381 | int unregister_acpi_bus_type(struct acpi_bus_type *); |
382 | struct device *acpi_get_physical_device(acpi_handle); | 382 | struct device *acpi_get_physical_device(acpi_handle); |
383 | struct device *acpi_get_physical_pci_device(acpi_handle); | ||
384 | |||
383 | /* helper */ | 385 | /* helper */ |
384 | acpi_handle acpi_get_child(acpi_handle, acpi_integer); | 386 | acpi_handle acpi_get_child(acpi_handle, acpi_integer); |
385 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); | 387 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); |
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index cf04c6011c2a..5fc1bb0f4a90 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h | |||
@@ -31,8 +31,24 @@ | |||
31 | 31 | ||
32 | #define ACPI_MAX_STRING 80 | 32 | #define ACPI_MAX_STRING 80 |
33 | 33 | ||
34 | /* | ||
35 | * Please update drivers/acpi/debug.c and Documentation/acpi/debug.txt | ||
36 | * if you add to this list. | ||
37 | */ | ||
34 | #define ACPI_BUS_COMPONENT 0x00010000 | 38 | #define ACPI_BUS_COMPONENT 0x00010000 |
39 | #define ACPI_AC_COMPONENT 0x00020000 | ||
40 | #define ACPI_BATTERY_COMPONENT 0x00040000 | ||
41 | #define ACPI_BUTTON_COMPONENT 0x00080000 | ||
42 | #define ACPI_SBS_COMPONENT 0x00100000 | ||
43 | #define ACPI_FAN_COMPONENT 0x00200000 | ||
44 | #define ACPI_PCI_COMPONENT 0x00400000 | ||
45 | #define ACPI_POWER_COMPONENT 0x00800000 | ||
46 | #define ACPI_CONTAINER_COMPONENT 0x01000000 | ||
35 | #define ACPI_SYSTEM_COMPONENT 0x02000000 | 47 | #define ACPI_SYSTEM_COMPONENT 0x02000000 |
48 | #define ACPI_THERMAL_COMPONENT 0x04000000 | ||
49 | #define ACPI_MEMORY_DEVICE_COMPONENT 0x08000000 | ||
50 | #define ACPI_VIDEO_COMPONENT 0x10000000 | ||
51 | #define ACPI_PROCESSOR_COMPONENT 0x20000000 | ||
36 | 52 | ||
37 | /* | 53 | /* |
38 | * _HID definitions | 54 | * _HID definitions |
@@ -41,6 +57,7 @@ | |||
41 | */ | 57 | */ |
42 | 58 | ||
43 | #define ACPI_POWER_HID "LNXPOWER" | 59 | #define ACPI_POWER_HID "LNXPOWER" |
60 | #define ACPI_PROCESSOR_OBJECT_HID "ACPI_CPU" | ||
44 | #define ACPI_PROCESSOR_HID "ACPI0007" | 61 | #define ACPI_PROCESSOR_HID "ACPI0007" |
45 | #define ACPI_SYSTEM_HID "LNXSYSTM" | 62 | #define ACPI_SYSTEM_HID "LNXSYSTM" |
46 | #define ACPI_THERMAL_HID "LNXTHERM" | 63 | #define ACPI_THERMAL_HID "LNXTHERM" |
@@ -54,7 +71,6 @@ | |||
54 | PCI | 71 | PCI |
55 | -------------------------------------------------------------------------- */ | 72 | -------------------------------------------------------------------------- */ |
56 | 73 | ||
57 | #define ACPI_PCI_COMPONENT 0x00400000 | ||
58 | 74 | ||
59 | /* ACPI PCI Interrupt Link (pci_link.c) */ | 75 | /* ACPI PCI Interrupt Link (pci_link.c) */ |
60 | 76 | ||
@@ -86,7 +102,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_device *device, int domain, | |||
86 | Power Resource | 102 | Power Resource |
87 | -------------------------------------------------------------------------- */ | 103 | -------------------------------------------------------------------------- */ |
88 | 104 | ||
89 | #ifdef CONFIG_ACPI_POWER | ||
90 | int acpi_device_sleep_wake(struct acpi_device *dev, | 105 | int acpi_device_sleep_wake(struct acpi_device *dev, |
91 | int enable, int sleep_state, int dev_state); | 106 | int enable, int sleep_state, int dev_state); |
92 | int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state); | 107 | int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state); |
@@ -94,15 +109,12 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev); | |||
94 | int acpi_power_get_inferred_state(struct acpi_device *device); | 109 | int acpi_power_get_inferred_state(struct acpi_device *device); |
95 | int acpi_power_transition(struct acpi_device *device, int state); | 110 | int acpi_power_transition(struct acpi_device *device, int state); |
96 | extern int acpi_power_nocheck; | 111 | extern int acpi_power_nocheck; |
97 | #endif | ||
98 | 112 | ||
99 | /* -------------------------------------------------------------------------- | 113 | /* -------------------------------------------------------------------------- |
100 | Embedded Controller | 114 | Embedded Controller |
101 | -------------------------------------------------------------------------- */ | 115 | -------------------------------------------------------------------------- */ |
102 | #ifdef CONFIG_ACPI_EC | ||
103 | int acpi_ec_ecdt_probe(void); | 116 | int acpi_ec_ecdt_probe(void); |
104 | int acpi_boot_ec_enable(void); | 117 | int acpi_boot_ec_enable(void); |
105 | #endif | ||
106 | 118 | ||
107 | /* -------------------------------------------------------------------------- | 119 | /* -------------------------------------------------------------------------- |
108 | Processor | 120 | Processor |
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 94d94e126e9f..33bc0e3b1954 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h | |||
@@ -252,9 +252,9 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status); | |||
252 | 252 | ||
253 | acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type); | 253 | acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type); |
254 | 254 | ||
255 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags); | 255 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number); |
256 | 256 | ||
257 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags); | 257 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number); |
258 | 258 | ||
259 | acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags); | 259 | acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags); |
260 | 260 | ||
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index e8936ab59627..7220361790b3 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h | |||
@@ -525,6 +525,7 @@ typedef u32 acpi_event_status; | |||
525 | #define ACPI_EVENT_FLAG_ENABLED (acpi_event_status) 0x01 | 525 | #define ACPI_EVENT_FLAG_ENABLED (acpi_event_status) 0x01 |
526 | #define ACPI_EVENT_FLAG_WAKE_ENABLED (acpi_event_status) 0x02 | 526 | #define ACPI_EVENT_FLAG_WAKE_ENABLED (acpi_event_status) 0x02 |
527 | #define ACPI_EVENT_FLAG_SET (acpi_event_status) 0x04 | 527 | #define ACPI_EVENT_FLAG_SET (acpi_event_status) 0x04 |
528 | #define ACPI_EVENT_FLAG_HANDLE (acpi_event_status) 0x08 | ||
528 | 529 | ||
529 | /* | 530 | /* |
530 | * General Purpose Events (GPE) | 531 | * General Purpose Events (GPE) |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index fd6a452b0ceb..fba8051fb297 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
@@ -163,8 +163,6 @@ struct acpi_pci_driver { | |||
163 | int acpi_pci_register_driver(struct acpi_pci_driver *driver); | 163 | int acpi_pci_register_driver(struct acpi_pci_driver *driver); |
164 | void acpi_pci_unregister_driver(struct acpi_pci_driver *driver); | 164 | void acpi_pci_unregister_driver(struct acpi_pci_driver *driver); |
165 | 165 | ||
166 | #ifdef CONFIG_ACPI_EC | ||
167 | |||
168 | extern int ec_read(u8 addr, u8 *val); | 166 | extern int ec_read(u8 addr, u8 *val); |
169 | extern int ec_write(u8 addr, u8 val); | 167 | extern int ec_write(u8 addr, u8 val); |
170 | extern int ec_transaction(u8 command, | 168 | extern int ec_transaction(u8 command, |
@@ -172,8 +170,6 @@ extern int ec_transaction(u8 command, | |||
172 | u8 *rdata, unsigned rdata_len, | 170 | u8 *rdata, unsigned rdata_len, |
173 | int force_poll); | 171 | int force_poll); |
174 | 172 | ||
175 | #endif /*CONFIG_ACPI_EC*/ | ||
176 | |||
177 | #if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE) | 173 | #if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE) |
178 | 174 | ||
179 | typedef void (*wmi_notify_handler) (u32 value, void *context); | 175 | typedef void (*wmi_notify_handler) (u32 value, void *context); |
@@ -194,6 +190,50 @@ extern bool wmi_has_guid(const char *guid); | |||
194 | 190 | ||
195 | #endif /* CONFIG_ACPI_WMI */ | 191 | #endif /* CONFIG_ACPI_WMI */ |
196 | 192 | ||
193 | #define ACPI_VIDEO_OUTPUT_SWITCHING 0x0001 | ||
194 | #define ACPI_VIDEO_DEVICE_POSTING 0x0002 | ||
195 | #define ACPI_VIDEO_ROM_AVAILABLE 0x0004 | ||
196 | #define ACPI_VIDEO_BACKLIGHT 0x0008 | ||
197 | #define ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR 0x0010 | ||
198 | #define ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO 0x0020 | ||
199 | #define ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR 0x0040 | ||
200 | #define ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO 0x0080 | ||
201 | #define ACPI_VIDEO_BACKLIGHT_DMI_VENDOR 0x0100 | ||
202 | #define ACPI_VIDEO_BACKLIGHT_DMI_VIDEO 0x0200 | ||
203 | #define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR 0x0400 | ||
204 | #define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO 0x0800 | ||
205 | |||
206 | #if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE) | ||
207 | |||
208 | extern long acpi_video_get_capabilities(acpi_handle graphics_dev_handle); | ||
209 | extern long acpi_is_video_device(struct acpi_device *device); | ||
210 | extern int acpi_video_backlight_support(void); | ||
211 | extern int acpi_video_display_switch_support(void); | ||
212 | |||
213 | #else | ||
214 | |||
215 | static inline long acpi_video_get_capabilities(acpi_handle graphics_dev_handle) | ||
216 | { | ||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static inline long acpi_is_video_device(struct acpi_device *device) | ||
221 | { | ||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static inline int acpi_video_backlight_support(void) | ||
226 | { | ||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static inline int acpi_video_display_switch_support(void) | ||
231 | { | ||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | #endif /* defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE) */ | ||
236 | |||
197 | extern int acpi_blacklisted(void); | 237 | extern int acpi_blacklisted(void); |
198 | #ifdef CONFIG_DMI | 238 | #ifdef CONFIG_DMI |
199 | extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d); | 239 | extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d); |
diff --git a/include/linux/c2port.h b/include/linux/c2port.h new file mode 100644 index 000000000000..7b5a2388ba67 --- /dev/null +++ b/include/linux/c2port.h | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | * Silicon Labs C2 port Linux support | ||
3 | * | ||
4 | * Copyright (c) 2007 Rodolfo Giometti <giometti@linux.it> | ||
5 | * Copyright (c) 2007 Eurotech S.p.A. <info@eurotech.it> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License version 2 as published by | ||
9 | * the Free Software Foundation | ||
10 | */ | ||
11 | |||
12 | #include <linux/device.h> | ||
13 | |||
14 | #define C2PORT_NAME_LEN 32 | ||
15 | |||
16 | /* | ||
17 | * C2 port basic structs | ||
18 | */ | ||
19 | |||
20 | /* Main struct */ | ||
21 | struct c2port_ops; | ||
22 | struct c2port_device { | ||
23 | unsigned int access:1; | ||
24 | unsigned int flash_access:1; | ||
25 | |||
26 | int id; | ||
27 | char name[C2PORT_NAME_LEN]; | ||
28 | struct c2port_ops *ops; | ||
29 | struct mutex mutex; /* prevent races during read/write */ | ||
30 | |||
31 | struct device *dev; | ||
32 | |||
33 | void *private_data; | ||
34 | }; | ||
35 | |||
36 | /* Basic operations */ | ||
37 | struct c2port_ops { | ||
38 | /* Flash layout */ | ||
39 | unsigned short block_size; /* flash block size in bytes */ | ||
40 | unsigned short blocks_num; /* flash blocks number */ | ||
41 | |||
42 | /* Enable or disable the access to C2 port */ | ||
43 | void (*access)(struct c2port_device *dev, int status); | ||
44 | |||
45 | /* Set C2D data line as input/output */ | ||
46 | void (*c2d_dir)(struct c2port_device *dev, int dir); | ||
47 | |||
48 | /* Read/write C2D data line */ | ||
49 | int (*c2d_get)(struct c2port_device *dev); | ||
50 | void (*c2d_set)(struct c2port_device *dev, int status); | ||
51 | |||
52 | /* Write C2CK clock line */ | ||
53 | void (*c2ck_set)(struct c2port_device *dev, int status); | ||
54 | }; | ||
55 | |||
56 | /* | ||
57 | * Exported functions | ||
58 | */ | ||
59 | |||
60 | #define to_class_dev(obj) container_of((obj), struct class_device, kobj) | ||
61 | #define to_c2port_device(obj) container_of((obj), struct c2port_device, class) | ||
62 | |||
63 | extern struct c2port_device *c2port_device_register(char *name, | ||
64 | struct c2port_ops *ops, void *devdata); | ||
65 | extern void c2port_device_unregister(struct c2port_device *dev); | ||
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 07e510a3b00a..3eba43878dcb 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h | |||
@@ -46,9 +46,6 @@ enum hrtimer_restart { | |||
46 | * hrtimer callback modes: | 46 | * hrtimer callback modes: |
47 | * | 47 | * |
48 | * HRTIMER_CB_SOFTIRQ: Callback must run in softirq context | 48 | * HRTIMER_CB_SOFTIRQ: Callback must run in softirq context |
49 | * HRTIMER_CB_IRQSAFE: Callback may run in hardirq context | ||
50 | * HRTIMER_CB_IRQSAFE_NO_RESTART: Callback may run in hardirq context and | ||
51 | * does not restart the timer | ||
52 | * HRTIMER_CB_IRQSAFE_PERCPU: Callback must run in hardirq context | 49 | * HRTIMER_CB_IRQSAFE_PERCPU: Callback must run in hardirq context |
53 | * Special mode for tick emulation and | 50 | * Special mode for tick emulation and |
54 | * scheduler timer. Such timers are per | 51 | * scheduler timer. Such timers are per |
@@ -61,8 +58,6 @@ enum hrtimer_restart { | |||
61 | */ | 58 | */ |
62 | enum hrtimer_cb_mode { | 59 | enum hrtimer_cb_mode { |
63 | HRTIMER_CB_SOFTIRQ, | 60 | HRTIMER_CB_SOFTIRQ, |
64 | HRTIMER_CB_IRQSAFE, | ||
65 | HRTIMER_CB_IRQSAFE_NO_RESTART, | ||
66 | HRTIMER_CB_IRQSAFE_PERCPU, | 61 | HRTIMER_CB_IRQSAFE_PERCPU, |
67 | HRTIMER_CB_IRQSAFE_UNLOCKED, | 62 | HRTIMER_CB_IRQSAFE_UNLOCKED, |
68 | }; | 63 | }; |
diff --git a/include/linux/mfd/wm8350/rtc.h b/include/linux/mfd/wm8350/rtc.h index dfda69e9f440..24add2bef6c9 100644 --- a/include/linux/mfd/wm8350/rtc.h +++ b/include/linux/mfd/wm8350/rtc.h | |||
@@ -261,6 +261,8 @@ | |||
261 | 261 | ||
262 | struct wm8350_rtc { | 262 | struct wm8350_rtc { |
263 | struct platform_device *pdev; | 263 | struct platform_device *pdev; |
264 | struct rtc_device *rtc; | ||
265 | int alarm_enabled; /* used over suspend/resume */ | ||
264 | }; | 266 | }; |
265 | 267 | ||
266 | #endif | 268 | #endif |
diff --git a/include/linux/ratelimit.h b/include/linux/ratelimit.h index 18a5b9ba9d40..00044b856453 100644 --- a/include/linux/ratelimit.h +++ b/include/linux/ratelimit.h | |||
@@ -17,11 +17,4 @@ struct ratelimit_state { | |||
17 | struct ratelimit_state name = {interval, burst,} | 17 | struct ratelimit_state name = {interval, burst,} |
18 | 18 | ||
19 | extern int __ratelimit(struct ratelimit_state *rs); | 19 | extern int __ratelimit(struct ratelimit_state *rs); |
20 | |||
21 | static inline int ratelimit(void) | ||
22 | { | ||
23 | static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, | ||
24 | DEFAULT_RATELIMIT_BURST); | ||
25 | return __ratelimit(&rs); | ||
26 | } | ||
27 | #endif | 20 | #endif |
diff --git a/include/linux/slab.h b/include/linux/slab.h index ba965c84ae06..000da12b5cf0 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h | |||
@@ -23,6 +23,34 @@ | |||
23 | #define SLAB_CACHE_DMA 0x00004000UL /* Use GFP_DMA memory */ | 23 | #define SLAB_CACHE_DMA 0x00004000UL /* Use GFP_DMA memory */ |
24 | #define SLAB_STORE_USER 0x00010000UL /* DEBUG: Store the last owner for bug hunting */ | 24 | #define SLAB_STORE_USER 0x00010000UL /* DEBUG: Store the last owner for bug hunting */ |
25 | #define SLAB_PANIC 0x00040000UL /* Panic if kmem_cache_create() fails */ | 25 | #define SLAB_PANIC 0x00040000UL /* Panic if kmem_cache_create() fails */ |
26 | /* | ||
27 | * SLAB_DESTROY_BY_RCU - **WARNING** READ THIS! | ||
28 | * | ||
29 | * This delays freeing the SLAB page by a grace period, it does _NOT_ | ||
30 | * delay object freeing. This means that if you do kmem_cache_free() | ||
31 | * that memory location is free to be reused at any time. Thus it may | ||
32 | * be possible to see another object there in the same RCU grace period. | ||
33 | * | ||
34 | * This feature only ensures the memory location backing the object | ||
35 | * stays valid, the trick to using this is relying on an independent | ||
36 | * object validation pass. Something like: | ||
37 | * | ||
38 | * rcu_read_lock() | ||
39 | * again: | ||
40 | * obj = lockless_lookup(key); | ||
41 | * if (obj) { | ||
42 | * if (!try_get_ref(obj)) // might fail for free objects | ||
43 | * goto again; | ||
44 | * | ||
45 | * if (obj->key != key) { // not the object we expected | ||
46 | * put_ref(obj); | ||
47 | * goto again; | ||
48 | * } | ||
49 | * } | ||
50 | * rcu_read_unlock(); | ||
51 | * | ||
52 | * See also the comment on struct slab_rcu in mm/slab.c. | ||
53 | */ | ||
26 | #define SLAB_DESTROY_BY_RCU 0x00080000UL /* Defer freeing slabs to RCU */ | 54 | #define SLAB_DESTROY_BY_RCU 0x00080000UL /* Defer freeing slabs to RCU */ |
27 | #define SLAB_MEM_SPREAD 0x00100000UL /* Spread some memory over cpuset */ | 55 | #define SLAB_MEM_SPREAD 0x00100000UL /* Spread some memory over cpuset */ |
28 | #define SLAB_TRACE 0x00200000UL /* Trace allocations and frees */ | 56 | #define SLAB_TRACE 0x00200000UL /* Trace allocations and frees */ |
diff --git a/include/video/atmel_lcdc.h b/include/video/atmel_lcdc.h index 6ad87f485992..0c864db1a466 100644 --- a/include/video/atmel_lcdc.h +++ b/include/video/atmel_lcdc.h | |||
@@ -38,7 +38,7 @@ struct atmel_lcdfb_info { | |||
38 | spinlock_t lock; | 38 | spinlock_t lock; |
39 | struct fb_info *info; | 39 | struct fb_info *info; |
40 | void __iomem *mmio; | 40 | void __iomem *mmio; |
41 | unsigned long irq_base; | 41 | int irq_base; |
42 | struct work_struct task; | 42 | struct work_struct task; |
43 | 43 | ||
44 | unsigned int guard_time; | 44 | unsigned int guard_time; |
diff --git a/init/Kconfig b/init/Kconfig index 86b00c53fade..226da2733c1e 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -771,8 +771,7 @@ config SLAB | |||
771 | help | 771 | help |
772 | The regular slab allocator that is established and known to work | 772 | The regular slab allocator that is established and known to work |
773 | well in all environments. It organizes cache hot objects in | 773 | well in all environments. It organizes cache hot objects in |
774 | per cpu and per node queues. SLAB is the default choice for | 774 | per cpu and per node queues. |
775 | a slab allocator. | ||
776 | 775 | ||
777 | config SLUB | 776 | config SLUB |
778 | bool "SLUB (Unqueued Allocator)" | 777 | bool "SLUB (Unqueued Allocator)" |
@@ -781,7 +780,8 @@ config SLUB | |||
781 | instead of managing queues of cached objects (SLAB approach). | 780 | instead of managing queues of cached objects (SLAB approach). |
782 | Per cpu caching is realized using slabs of objects instead | 781 | Per cpu caching is realized using slabs of objects instead |
783 | of queues of objects. SLUB can use memory efficiently | 782 | of queues of objects. SLUB can use memory efficiently |
784 | and has enhanced diagnostics. | 783 | and has enhanced diagnostics. SLUB is the default choice for |
784 | a slab allocator. | ||
785 | 785 | ||
786 | config SLOB | 786 | config SLOB |
787 | depends on EMBEDDED | 787 | depends on EMBEDDED |
diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c index 7fa476f01d05..fb249e2bcada 100644 --- a/kernel/cgroup_freezer.c +++ b/kernel/cgroup_freezer.c | |||
@@ -184,9 +184,20 @@ static void freezer_fork(struct cgroup_subsys *ss, struct task_struct *task) | |||
184 | { | 184 | { |
185 | struct freezer *freezer; | 185 | struct freezer *freezer; |
186 | 186 | ||
187 | task_lock(task); | 187 | /* |
188 | * No lock is needed, since the task isn't on tasklist yet, | ||
189 | * so it can't be moved to another cgroup, which means the | ||
190 | * freezer won't be removed and will be valid during this | ||
191 | * function call. | ||
192 | */ | ||
188 | freezer = task_freezer(task); | 193 | freezer = task_freezer(task); |
189 | task_unlock(task); | 194 | |
195 | /* | ||
196 | * The root cgroup is non-freezable, so we can skip the | ||
197 | * following check. | ||
198 | */ | ||
199 | if (!freezer->css.cgroup->parent) | ||
200 | return; | ||
190 | 201 | ||
191 | spin_lock_irq(&freezer->lock); | 202 | spin_lock_irq(&freezer->lock); |
192 | BUG_ON(freezer->state == CGROUP_FROZEN); | 203 | BUG_ON(freezer->state == CGROUP_FROZEN); |
@@ -331,7 +342,7 @@ static int freezer_write(struct cgroup *cgroup, | |||
331 | else if (strcmp(buffer, freezer_state_strs[CGROUP_FROZEN]) == 0) | 342 | else if (strcmp(buffer, freezer_state_strs[CGROUP_FROZEN]) == 0) |
332 | goal_state = CGROUP_FROZEN; | 343 | goal_state = CGROUP_FROZEN; |
333 | else | 344 | else |
334 | return -EIO; | 345 | return -EINVAL; |
335 | 346 | ||
336 | if (!cgroup_lock_live_group(cgroup)) | 347 | if (!cgroup_lock_live_group(cgroup)) |
337 | return -ENODEV; | 348 | return -ENODEV; |
@@ -350,6 +361,8 @@ static struct cftype files[] = { | |||
350 | 361 | ||
351 | static int freezer_populate(struct cgroup_subsys *ss, struct cgroup *cgroup) | 362 | static int freezer_populate(struct cgroup_subsys *ss, struct cgroup *cgroup) |
352 | { | 363 | { |
364 | if (!cgroup->parent) | ||
365 | return 0; | ||
353 | return cgroup_add_files(cgroup, ss, files, ARRAY_SIZE(files)); | 366 | return cgroup_add_files(cgroup, ss, files, ARRAY_SIZE(files)); |
354 | } | 367 | } |
355 | 368 | ||
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 95d3949f2ae5..47e63349d1b2 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -664,14 +664,6 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, | |||
664 | 664 | ||
665 | /* Timer is expired, act upon the callback mode */ | 665 | /* Timer is expired, act upon the callback mode */ |
666 | switch(timer->cb_mode) { | 666 | switch(timer->cb_mode) { |
667 | case HRTIMER_CB_IRQSAFE_NO_RESTART: | ||
668 | debug_hrtimer_deactivate(timer); | ||
669 | /* | ||
670 | * We can call the callback from here. No restart | ||
671 | * happens, so no danger of recursion | ||
672 | */ | ||
673 | BUG_ON(timer->function(timer) != HRTIMER_NORESTART); | ||
674 | return 1; | ||
675 | case HRTIMER_CB_IRQSAFE_PERCPU: | 667 | case HRTIMER_CB_IRQSAFE_PERCPU: |
676 | case HRTIMER_CB_IRQSAFE_UNLOCKED: | 668 | case HRTIMER_CB_IRQSAFE_UNLOCKED: |
677 | /* | 669 | /* |
@@ -683,7 +675,6 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, | |||
683 | */ | 675 | */ |
684 | debug_hrtimer_deactivate(timer); | 676 | debug_hrtimer_deactivate(timer); |
685 | return 1; | 677 | return 1; |
686 | case HRTIMER_CB_IRQSAFE: | ||
687 | case HRTIMER_CB_SOFTIRQ: | 678 | case HRTIMER_CB_SOFTIRQ: |
688 | /* | 679 | /* |
689 | * Move everything else into the softirq pending list ! | 680 | * Move everything else into the softirq pending list ! |
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 8b57a2597f21..9f8a3f25259a 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
@@ -72,7 +72,7 @@ static bool kprobe_enabled; | |||
72 | DEFINE_MUTEX(kprobe_mutex); /* Protects kprobe_table */ | 72 | DEFINE_MUTEX(kprobe_mutex); /* Protects kprobe_table */ |
73 | static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; | 73 | static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; |
74 | static struct { | 74 | static struct { |
75 | spinlock_t lock ____cacheline_aligned; | 75 | spinlock_t lock ____cacheline_aligned_in_smp; |
76 | } kretprobe_table_locks[KPROBE_TABLE_SIZE]; | 76 | } kretprobe_table_locks[KPROBE_TABLE_SIZE]; |
77 | 77 | ||
78 | static spinlock_t *kretprobe_table_lock_ptr(unsigned long hash) | 78 | static spinlock_t *kretprobe_table_lock_ptr(unsigned long hash) |
@@ -613,30 +613,37 @@ static int __kprobes __register_kprobe(struct kprobe *p, | |||
613 | return -EINVAL; | 613 | return -EINVAL; |
614 | p->addr = addr; | 614 | p->addr = addr; |
615 | 615 | ||
616 | if (!kernel_text_address((unsigned long) p->addr) || | 616 | preempt_disable(); |
617 | in_kprobes_functions((unsigned long) p->addr)) | 617 | if (!__kernel_text_address((unsigned long) p->addr) || |
618 | in_kprobes_functions((unsigned long) p->addr)) { | ||
619 | preempt_enable(); | ||
618 | return -EINVAL; | 620 | return -EINVAL; |
621 | } | ||
619 | 622 | ||
620 | p->mod_refcounted = 0; | 623 | p->mod_refcounted = 0; |
621 | 624 | ||
622 | /* | 625 | /* |
623 | * Check if are we probing a module. | 626 | * Check if are we probing a module. |
624 | */ | 627 | */ |
625 | probed_mod = module_text_address((unsigned long) p->addr); | 628 | probed_mod = __module_text_address((unsigned long) p->addr); |
626 | if (probed_mod) { | 629 | if (probed_mod) { |
627 | struct module *calling_mod = module_text_address(called_from); | 630 | struct module *calling_mod; |
631 | calling_mod = __module_text_address(called_from); | ||
628 | /* | 632 | /* |
629 | * We must allow modules to probe themself and in this case | 633 | * We must allow modules to probe themself and in this case |
630 | * avoid incrementing the module refcount, so as to allow | 634 | * avoid incrementing the module refcount, so as to allow |
631 | * unloading of self probing modules. | 635 | * unloading of self probing modules. |
632 | */ | 636 | */ |
633 | if (calling_mod && calling_mod != probed_mod) { | 637 | if (calling_mod && calling_mod != probed_mod) { |
634 | if (unlikely(!try_module_get(probed_mod))) | 638 | if (unlikely(!try_module_get(probed_mod))) { |
639 | preempt_enable(); | ||
635 | return -EINVAL; | 640 | return -EINVAL; |
641 | } | ||
636 | p->mod_refcounted = 1; | 642 | p->mod_refcounted = 1; |
637 | } else | 643 | } else |
638 | probed_mod = NULL; | 644 | probed_mod = NULL; |
639 | } | 645 | } |
646 | preempt_enable(); | ||
640 | 647 | ||
641 | p->nmissed = 0; | 648 | p->nmissed = 0; |
642 | INIT_LIST_HEAD(&p->list); | 649 | INIT_LIST_HEAD(&p->list); |
@@ -718,6 +725,10 @@ static void __kprobes __unregister_kprobe_bottom(struct kprobe *p) | |||
718 | struct kprobe *old_p; | 725 | struct kprobe *old_p; |
719 | 726 | ||
720 | if (p->mod_refcounted) { | 727 | if (p->mod_refcounted) { |
728 | /* | ||
729 | * Since we've already incremented refcount, | ||
730 | * we don't need to disable preemption. | ||
731 | */ | ||
721 | mod = module_text_address((unsigned long)p->addr); | 732 | mod = module_text_address((unsigned long)p->addr); |
722 | if (mod) | 733 | if (mod) |
723 | module_put(mod); | 734 | module_put(mod); |
diff --git a/kernel/sched.c b/kernel/sched.c index 50a21f964679..c94baf2969e7 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -1456,6 +1456,8 @@ static unsigned long cpu_avg_load_per_task(int cpu) | |||
1456 | 1456 | ||
1457 | if (rq->nr_running) | 1457 | if (rq->nr_running) |
1458 | rq->avg_load_per_task = rq->load.weight / rq->nr_running; | 1458 | rq->avg_load_per_task = rq->load.weight / rq->nr_running; |
1459 | else | ||
1460 | rq->avg_load_per_task = 0; | ||
1459 | 1461 | ||
1460 | return rq->avg_load_per_task; | 1462 | return rq->avg_load_per_task; |
1461 | } | 1463 | } |
@@ -5868,6 +5870,8 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu) | |||
5868 | struct rq *rq = cpu_rq(cpu); | 5870 | struct rq *rq = cpu_rq(cpu); |
5869 | unsigned long flags; | 5871 | unsigned long flags; |
5870 | 5872 | ||
5873 | spin_lock_irqsave(&rq->lock, flags); | ||
5874 | |||
5871 | __sched_fork(idle); | 5875 | __sched_fork(idle); |
5872 | idle->se.exec_start = sched_clock(); | 5876 | idle->se.exec_start = sched_clock(); |
5873 | 5877 | ||
@@ -5875,7 +5879,6 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu) | |||
5875 | idle->cpus_allowed = cpumask_of_cpu(cpu); | 5879 | idle->cpus_allowed = cpumask_of_cpu(cpu); |
5876 | __set_task_cpu(idle, cpu); | 5880 | __set_task_cpu(idle, cpu); |
5877 | 5881 | ||
5878 | spin_lock_irqsave(&rq->lock, flags); | ||
5879 | rq->curr = rq->idle = idle; | 5882 | rq->curr = rq->idle = idle; |
5880 | #if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW) | 5883 | #if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW) |
5881 | idle->oncpu = 1; | 5884 | idle->oncpu = 1; |
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index d143ab67be44..6058b53dcb89 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -1796,6 +1796,7 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, | |||
1796 | static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma, | 1796 | static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma, |
1797 | struct page *page, unsigned long address) | 1797 | struct page *page, unsigned long address) |
1798 | { | 1798 | { |
1799 | struct hstate *h = hstate_vma(vma); | ||
1799 | struct vm_area_struct *iter_vma; | 1800 | struct vm_area_struct *iter_vma; |
1800 | struct address_space *mapping; | 1801 | struct address_space *mapping; |
1801 | struct prio_tree_iter iter; | 1802 | struct prio_tree_iter iter; |
@@ -1805,7 +1806,7 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma, | |||
1805 | * vm_pgoff is in PAGE_SIZE units, hence the different calculation | 1806 | * vm_pgoff is in PAGE_SIZE units, hence the different calculation |
1806 | * from page cache lookup which is in HPAGE_SIZE units. | 1807 | * from page cache lookup which is in HPAGE_SIZE units. |
1807 | */ | 1808 | */ |
1808 | address = address & huge_page_mask(hstate_vma(vma)); | 1809 | address = address & huge_page_mask(h); |
1809 | pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) | 1810 | pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) |
1810 | + (vma->vm_pgoff >> PAGE_SHIFT); | 1811 | + (vma->vm_pgoff >> PAGE_SHIFT); |
1811 | mapping = (struct address_space *)page_private(page); | 1812 | mapping = (struct address_space *)page_private(page); |
@@ -1824,7 +1825,7 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma, | |||
1824 | */ | 1825 | */ |
1825 | if (!is_vma_resv_set(iter_vma, HPAGE_RESV_OWNER)) | 1826 | if (!is_vma_resv_set(iter_vma, HPAGE_RESV_OWNER)) |
1826 | unmap_hugepage_range(iter_vma, | 1827 | unmap_hugepage_range(iter_vma, |
1827 | address, address + HPAGE_SIZE, | 1828 | address, address + huge_page_size(h), |
1828 | page); | 1829 | page); |
1829 | } | 1830 | } |
1830 | 1831 | ||
diff --git a/mm/mlock.c b/mm/mlock.c index 008ea70b7afa..a6da2aee940a 100644 --- a/mm/mlock.c +++ b/mm/mlock.c | |||
@@ -66,14 +66,10 @@ void __clear_page_mlock(struct page *page) | |||
66 | putback_lru_page(page); | 66 | putback_lru_page(page); |
67 | } else { | 67 | } else { |
68 | /* | 68 | /* |
69 | * Page not on the LRU yet. Flush all pagevecs and retry. | 69 | * We lost the race. the page already moved to evictable list. |
70 | */ | 70 | */ |
71 | lru_add_drain_all(); | 71 | if (PageUnevictable(page)) |
72 | if (!isolate_lru_page(page)) | ||
73 | putback_lru_page(page); | ||
74 | else if (PageUnevictable(page)) | ||
75 | count_vm_event(UNEVICTABLE_PGSTRANDED); | 72 | count_vm_event(UNEVICTABLE_PGSTRANDED); |
76 | |||
77 | } | 73 | } |
78 | } | 74 | } |
79 | 75 | ||
@@ -187,8 +183,6 @@ static long __mlock_vma_pages_range(struct vm_area_struct *vma, | |||
187 | if (vma->vm_flags & VM_WRITE) | 183 | if (vma->vm_flags & VM_WRITE) |
188 | gup_flags |= GUP_FLAGS_WRITE; | 184 | gup_flags |= GUP_FLAGS_WRITE; |
189 | 185 | ||
190 | lru_add_drain_all(); /* push cached pages to LRU */ | ||
191 | |||
192 | while (nr_pages > 0) { | 186 | while (nr_pages > 0) { |
193 | int i; | 187 | int i; |
194 | 188 | ||
@@ -251,8 +245,6 @@ static long __mlock_vma_pages_range(struct vm_area_struct *vma, | |||
251 | ret = 0; | 245 | ret = 0; |
252 | } | 246 | } |
253 | 247 | ||
254 | lru_add_drain_all(); /* to update stats */ | ||
255 | |||
256 | return ret; /* count entire vma as locked_vm */ | 248 | return ret; /* count entire vma as locked_vm */ |
257 | } | 249 | } |
258 | 250 | ||
@@ -546,6 +538,8 @@ asmlinkage long sys_mlock(unsigned long start, size_t len) | |||
546 | if (!can_do_mlock()) | 538 | if (!can_do_mlock()) |
547 | return -EPERM; | 539 | return -EPERM; |
548 | 540 | ||
541 | lru_add_drain_all(); /* flush pagevec */ | ||
542 | |||
549 | down_write(¤t->mm->mmap_sem); | 543 | down_write(¤t->mm->mmap_sem); |
550 | len = PAGE_ALIGN(len + (start & ~PAGE_MASK)); | 544 | len = PAGE_ALIGN(len + (start & ~PAGE_MASK)); |
551 | start &= PAGE_MASK; | 545 | start &= PAGE_MASK; |
@@ -612,6 +606,8 @@ asmlinkage long sys_mlockall(int flags) | |||
612 | if (!can_do_mlock()) | 606 | if (!can_do_mlock()) |
613 | goto out; | 607 | goto out; |
614 | 608 | ||
609 | lru_add_drain_all(); /* flush pagevec */ | ||
610 | |||
615 | down_write(¤t->mm->mmap_sem); | 611 | down_write(¤t->mm->mmap_sem); |
616 | 612 | ||
617 | lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur; | 613 | lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur; |
@@ -1704,7 +1704,7 @@ find_extend_vma(struct mm_struct *mm, unsigned long addr) | |||
1704 | vma = find_vma_prev(mm, addr, &prev); | 1704 | vma = find_vma_prev(mm, addr, &prev); |
1705 | if (vma && (vma->vm_start <= addr)) | 1705 | if (vma && (vma->vm_start <= addr)) |
1706 | return vma; | 1706 | return vma; |
1707 | if (expand_stack(prev, addr)) | 1707 | if (!prev || expand_stack(prev, addr)) |
1708 | return NULL; | 1708 | return NULL; |
1709 | if (prev->vm_flags & VM_LOCKED) { | 1709 | if (prev->vm_flags & VM_LOCKED) { |
1710 | if (mlock_vma_pages_range(prev, addr, prev->vm_end) < 0) | 1710 | if (mlock_vma_pages_range(prev, addr, prev->vm_end) < 0) |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 54069e64e3a8..d8ac01474563 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -1561,6 +1561,10 @@ nofail_alloc: | |||
1561 | 1561 | ||
1562 | /* We now go into synchronous reclaim */ | 1562 | /* We now go into synchronous reclaim */ |
1563 | cpuset_memory_pressure_bump(); | 1563 | cpuset_memory_pressure_bump(); |
1564 | /* | ||
1565 | * The task's cpuset might have expanded its set of allowable nodes | ||
1566 | */ | ||
1567 | cpuset_update_task_memory_state(); | ||
1564 | p->flags |= PF_MEMALLOC; | 1568 | p->flags |= PF_MEMALLOC; |
1565 | reclaim_state.reclaimed_slab = 0; | 1569 | reclaim_state.reclaimed_slab = 0; |
1566 | p->reclaim_state = &reclaim_state; | 1570 | p->reclaim_state = &reclaim_state; |
diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c index f59d797dc5a9..1223d927904d 100644 --- a/mm/page_cgroup.c +++ b/mm/page_cgroup.c | |||
@@ -165,7 +165,7 @@ int online_page_cgroup(unsigned long start_pfn, | |||
165 | unsigned long start, end, pfn; | 165 | unsigned long start, end, pfn; |
166 | int fail = 0; | 166 | int fail = 0; |
167 | 167 | ||
168 | start = start_pfn & (PAGES_PER_SECTION - 1); | 168 | start = start_pfn & ~(PAGES_PER_SECTION - 1); |
169 | end = ALIGN(start_pfn + nr_pages, PAGES_PER_SECTION); | 169 | end = ALIGN(start_pfn + nr_pages, PAGES_PER_SECTION); |
170 | 170 | ||
171 | for (pfn = start; !fail && pfn < end; pfn += PAGES_PER_SECTION) { | 171 | for (pfn = start; !fail && pfn < end; pfn += PAGES_PER_SECTION) { |
@@ -188,7 +188,7 @@ int offline_page_cgroup(unsigned long start_pfn, | |||
188 | { | 188 | { |
189 | unsigned long start, end, pfn; | 189 | unsigned long start, end, pfn; |
190 | 190 | ||
191 | start = start_pfn & (PAGES_PER_SECTION - 1); | 191 | start = start_pfn & ~(PAGES_PER_SECTION - 1); |
192 | end = ALIGN(start_pfn + nr_pages, PAGES_PER_SECTION); | 192 | end = ALIGN(start_pfn + nr_pages, PAGES_PER_SECTION); |
193 | 193 | ||
194 | for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) | 194 | for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) |
diff --git a/net/compat.c b/net/compat.c index 67fb6a3834a3..6ce1a1cadcc0 100644 --- a/net/compat.c +++ b/net/compat.c | |||
@@ -226,14 +226,14 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat | |||
226 | return 0; /* XXX: return error? check spec. */ | 226 | return 0; /* XXX: return error? check spec. */ |
227 | } | 227 | } |
228 | 228 | ||
229 | if (level == SOL_SOCKET && type == SO_TIMESTAMP) { | 229 | if (level == SOL_SOCKET && type == SCM_TIMESTAMP) { |
230 | struct timeval *tv = (struct timeval *)data; | 230 | struct timeval *tv = (struct timeval *)data; |
231 | ctv.tv_sec = tv->tv_sec; | 231 | ctv.tv_sec = tv->tv_sec; |
232 | ctv.tv_usec = tv->tv_usec; | 232 | ctv.tv_usec = tv->tv_usec; |
233 | data = &ctv; | 233 | data = &ctv; |
234 | len = sizeof(ctv); | 234 | len = sizeof(ctv); |
235 | } | 235 | } |
236 | if (level == SOL_SOCKET && type == SO_TIMESTAMPNS) { | 236 | if (level == SOL_SOCKET && type == SCM_TIMESTAMPNS) { |
237 | struct timespec *ts = (struct timespec *)data; | 237 | struct timespec *ts = (struct timespec *)data; |
238 | cts.tv_sec = ts->tv_sec; | 238 | cts.tv_sec = ts->tv_sec; |
239 | cts.tv_nsec = ts->tv_nsec; | 239 | cts.tv_nsec = ts->tv_nsec; |
diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c index af99776146ff..937549b8a921 100644 --- a/net/ipv4/tcp_htcp.c +++ b/net/ipv4/tcp_htcp.c | |||
@@ -69,9 +69,12 @@ static u32 htcp_cwnd_undo(struct sock *sk) | |||
69 | const struct tcp_sock *tp = tcp_sk(sk); | 69 | const struct tcp_sock *tp = tcp_sk(sk); |
70 | struct htcp *ca = inet_csk_ca(sk); | 70 | struct htcp *ca = inet_csk_ca(sk); |
71 | 71 | ||
72 | ca->last_cong = ca->undo_last_cong; | 72 | if (ca->undo_last_cong) { |
73 | ca->maxRTT = ca->undo_maxRTT; | 73 | ca->last_cong = ca->undo_last_cong; |
74 | ca->old_maxB = ca->undo_old_maxB; | 74 | ca->maxRTT = ca->undo_maxRTT; |
75 | ca->old_maxB = ca->undo_old_maxB; | ||
76 | ca->undo_last_cong = 0; | ||
77 | } | ||
75 | 78 | ||
76 | return max(tp->snd_cwnd, (tp->snd_ssthresh << 7) / ca->beta); | 79 | return max(tp->snd_cwnd, (tp->snd_ssthresh << 7) / ca->beta); |
77 | } | 80 | } |
@@ -268,7 +271,10 @@ static void htcp_state(struct sock *sk, u8 new_state) | |||
268 | case TCP_CA_Open: | 271 | case TCP_CA_Open: |
269 | { | 272 | { |
270 | struct htcp *ca = inet_csk_ca(sk); | 273 | struct htcp *ca = inet_csk_ca(sk); |
271 | ca->last_cong = jiffies; | 274 | if (ca->undo_last_cong) { |
275 | ca->last_cong = jiffies; | ||
276 | ca->undo_last_cong = 0; | ||
277 | } | ||
272 | } | 278 | } |
273 | break; | 279 | break; |
274 | case TCP_CA_CWR: | 280 | case TCP_CA_CWR: |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 87665d7bb4f9..14d165f0df75 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -2570,14 +2570,14 @@ void ieee80211_notify_mac(struct ieee80211_hw *hw, | |||
2570 | 2570 | ||
2571 | switch (notif_type) { | 2571 | switch (notif_type) { |
2572 | case IEEE80211_NOTIFY_RE_ASSOC: | 2572 | case IEEE80211_NOTIFY_RE_ASSOC: |
2573 | rcu_read_lock(); | 2573 | rtnl_lock(); |
2574 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 2574 | list_for_each_entry(sdata, &local->interfaces, list) { |
2575 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 2575 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
2576 | continue; | 2576 | continue; |
2577 | 2577 | ||
2578 | ieee80211_sta_req_auth(sdata, &sdata->u.sta); | 2578 | ieee80211_sta_req_auth(sdata, &sdata->u.sta); |
2579 | } | 2579 | } |
2580 | rcu_read_unlock(); | 2580 | rtnl_unlock(); |
2581 | break; | 2581 | break; |
2582 | } | 2582 | } |
2583 | } | 2583 | } |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index e6085915d86d..4300a679cd86 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -212,7 +212,7 @@ struct sigmatel_spec { | |||
212 | /* i/o switches */ | 212 | /* i/o switches */ |
213 | unsigned int io_switch[2]; | 213 | unsigned int io_switch[2]; |
214 | unsigned int clfe_swap; | 214 | unsigned int clfe_swap; |
215 | unsigned int hp_switch; | 215 | unsigned int hp_switch; /* NID of HP as line-out */ |
216 | unsigned int aloopback; | 216 | unsigned int aloopback; |
217 | 217 | ||
218 | struct hda_pcm pcm_rec[2]; /* PCM information */ | 218 | struct hda_pcm pcm_rec[2]; /* PCM information */ |
@@ -2443,7 +2443,7 @@ static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol, | |||
2443 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2443 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
2444 | struct sigmatel_spec *spec = codec->spec; | 2444 | struct sigmatel_spec *spec = codec->spec; |
2445 | 2445 | ||
2446 | ucontrol->value.integer.value[0] = spec->hp_switch; | 2446 | ucontrol->value.integer.value[0] = !!spec->hp_switch; |
2447 | return 0; | 2447 | return 0; |
2448 | } | 2448 | } |
2449 | 2449 | ||
@@ -2452,8 +2452,9 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, | |||
2452 | { | 2452 | { |
2453 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2453 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
2454 | struct sigmatel_spec *spec = codec->spec; | 2454 | struct sigmatel_spec *spec = codec->spec; |
2455 | 2455 | int nid = kcontrol->private_value; | |
2456 | spec->hp_switch = ucontrol->value.integer.value[0]; | 2456 | |
2457 | spec->hp_switch = ucontrol->value.integer.value[0] ? nid : 0; | ||
2457 | 2458 | ||
2458 | /* check to be sure that the ports are upto date with | 2459 | /* check to be sure that the ports are upto date with |
2459 | * switch changes | 2460 | * switch changes |
@@ -2862,7 +2863,8 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
2862 | if (cfg->hp_outs > 1) { | 2863 | if (cfg->hp_outs > 1) { |
2863 | err = stac92xx_add_control(spec, | 2864 | err = stac92xx_add_control(spec, |
2864 | STAC_CTL_WIDGET_HP_SWITCH, | 2865 | STAC_CTL_WIDGET_HP_SWITCH, |
2865 | "Headphone as Line Out Switch", 0); | 2866 | "Headphone as Line Out Switch", |
2867 | cfg->hp_pins[cfg->hp_outs - 1]); | ||
2866 | if (err < 0) | 2868 | if (err < 0) |
2867 | return err; | 2869 | return err; |
2868 | } | 2870 | } |
@@ -3530,6 +3532,12 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) | |||
3530 | if ((err = stac9200_auto_create_lfe_ctls(codec, &spec->autocfg)) < 0) | 3532 | if ((err = stac9200_auto_create_lfe_ctls(codec, &spec->autocfg)) < 0) |
3531 | return err; | 3533 | return err; |
3532 | 3534 | ||
3535 | if (spec->num_muxes > 0) { | ||
3536 | err = stac92xx_auto_create_mux_input_ctls(codec); | ||
3537 | if (err < 0) | ||
3538 | return err; | ||
3539 | } | ||
3540 | |||
3533 | if (spec->autocfg.dig_out_pin) | 3541 | if (spec->autocfg.dig_out_pin) |
3534 | spec->multiout.dig_out_nid = 0x05; | 3542 | spec->multiout.dig_out_nid = 0x05; |
3535 | if (spec->autocfg.dig_in_pin) | 3543 | if (spec->autocfg.dig_in_pin) |
@@ -3647,14 +3655,18 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3647 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 3655 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
3648 | hda_nid_t nid = cfg->input_pins[i]; | 3656 | hda_nid_t nid = cfg->input_pins[i]; |
3649 | if (nid) { | 3657 | if (nid) { |
3650 | unsigned int pinctl = snd_hda_codec_read(codec, nid, | 3658 | unsigned int pinctl; |
3651 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 3659 | if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) { |
3652 | /* if PINCTL already set then skip */ | 3660 | /* for mic pins, force to initialize */ |
3653 | if (pinctl & AC_PINCAP_IN) | 3661 | pinctl = stac92xx_get_vref(codec, nid); |
3654 | continue; | 3662 | } else { |
3655 | pinctl = AC_PINCTL_IN_EN; | 3663 | pinctl = snd_hda_codec_read(codec, nid, 0, |
3656 | if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) | 3664 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
3657 | pinctl |= stac92xx_get_vref(codec, nid); | 3665 | /* if PINCTL already set then skip */ |
3666 | if (pinctl & AC_PINCTL_IN_EN) | ||
3667 | continue; | ||
3668 | } | ||
3669 | pinctl |= AC_PINCTL_IN_EN; | ||
3658 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | 3670 | stac92xx_auto_set_pinctl(codec, nid, pinctl); |
3659 | } | 3671 | } |
3660 | } | 3672 | } |
@@ -3776,11 +3788,30 @@ static int get_hp_pin_presence(struct hda_codec *codec, hda_nid_t nid) | |||
3776 | return 0; | 3788 | return 0; |
3777 | } | 3789 | } |
3778 | 3790 | ||
3791 | /* return non-zero if the hp-pin of the given array index isn't | ||
3792 | * a jack-detection target | ||
3793 | */ | ||
3794 | static int no_hp_sensing(struct sigmatel_spec *spec, int i) | ||
3795 | { | ||
3796 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3797 | |||
3798 | /* ignore sensing of shared line and mic jacks */ | ||
3799 | if (spec->line_switch && | ||
3800 | cfg->hp_pins[i] == cfg->input_pins[AUTO_PIN_LINE]) | ||
3801 | return 1; | ||
3802 | if (spec->mic_switch && | ||
3803 | cfg->hp_pins[i] == cfg->input_pins[AUTO_PIN_MIC]) | ||
3804 | return 1; | ||
3805 | /* ignore if the pin is set as line-out */ | ||
3806 | if (cfg->hp_pins[i] == spec->hp_switch) | ||
3807 | return 1; | ||
3808 | return 0; | ||
3809 | } | ||
3810 | |||
3779 | static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) | 3811 | static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) |
3780 | { | 3812 | { |
3781 | struct sigmatel_spec *spec = codec->spec; | 3813 | struct sigmatel_spec *spec = codec->spec; |
3782 | struct auto_pin_cfg *cfg = &spec->autocfg; | 3814 | struct auto_pin_cfg *cfg = &spec->autocfg; |
3783 | int nid = cfg->hp_pins[cfg->hp_outs - 1]; | ||
3784 | int i, presence; | 3815 | int i, presence; |
3785 | 3816 | ||
3786 | presence = 0; | 3817 | presence = 0; |
@@ -3791,15 +3822,16 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) | |||
3791 | for (i = 0; i < cfg->hp_outs; i++) { | 3822 | for (i = 0; i < cfg->hp_outs; i++) { |
3792 | if (presence) | 3823 | if (presence) |
3793 | break; | 3824 | break; |
3794 | if (spec->hp_switch && cfg->hp_pins[i] == nid) | 3825 | if (no_hp_sensing(spec, i)) |
3795 | break; | 3826 | continue; |
3796 | presence = get_hp_pin_presence(codec, cfg->hp_pins[i]); | 3827 | presence = get_hp_pin_presence(codec, cfg->hp_pins[i]); |
3797 | } | 3828 | } |
3798 | 3829 | ||
3799 | if (presence) { | 3830 | if (presence) { |
3800 | /* disable lineouts, enable hp */ | 3831 | /* disable lineouts */ |
3801 | if (spec->hp_switch) | 3832 | if (spec->hp_switch) |
3802 | stac92xx_reset_pinctl(codec, nid, AC_PINCTL_OUT_EN); | 3833 | stac92xx_reset_pinctl(codec, spec->hp_switch, |
3834 | AC_PINCTL_OUT_EN); | ||
3803 | for (i = 0; i < cfg->line_outs; i++) | 3835 | for (i = 0; i < cfg->line_outs; i++) |
3804 | stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], | 3836 | stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], |
3805 | AC_PINCTL_OUT_EN); | 3837 | AC_PINCTL_OUT_EN); |
@@ -3811,9 +3843,10 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) | |||
3811 | spec->gpio_dir, spec->gpio_data & | 3843 | spec->gpio_dir, spec->gpio_data & |
3812 | ~spec->eapd_mask); | 3844 | ~spec->eapd_mask); |
3813 | } else { | 3845 | } else { |
3814 | /* enable lineouts, disable hp */ | 3846 | /* enable lineouts */ |
3815 | if (spec->hp_switch) | 3847 | if (spec->hp_switch) |
3816 | stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); | 3848 | stac92xx_set_pinctl(codec, spec->hp_switch, |
3849 | AC_PINCTL_OUT_EN); | ||
3817 | for (i = 0; i < cfg->line_outs; i++) | 3850 | for (i = 0; i < cfg->line_outs; i++) |
3818 | stac92xx_set_pinctl(codec, cfg->line_out_pins[i], | 3851 | stac92xx_set_pinctl(codec, cfg->line_out_pins[i], |
3819 | AC_PINCTL_OUT_EN); | 3852 | AC_PINCTL_OUT_EN); |
@@ -3825,8 +3858,16 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) | |||
3825 | spec->gpio_dir, spec->gpio_data | | 3858 | spec->gpio_dir, spec->gpio_data | |
3826 | spec->eapd_mask); | 3859 | spec->eapd_mask); |
3827 | } | 3860 | } |
3828 | if (!spec->hp_switch && cfg->hp_outs > 1 && presence) | 3861 | /* toggle hp outs */ |
3829 | stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); | 3862 | for (i = 0; i < cfg->hp_outs; i++) { |
3863 | unsigned int val = AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN; | ||
3864 | if (no_hp_sensing(spec, i)) | ||
3865 | continue; | ||
3866 | if (presence) | ||
3867 | stac92xx_set_pinctl(codec, cfg->hp_pins[i], val); | ||
3868 | else | ||
3869 | stac92xx_reset_pinctl(codec, cfg->hp_pins[i], val); | ||
3870 | } | ||
3830 | } | 3871 | } |
3831 | 3872 | ||
3832 | static void stac92xx_pin_sense(struct hda_codec *codec, int idx) | 3873 | static void stac92xx_pin_sense(struct hda_codec *codec, int idx) |