diff options
96 files changed, 1113 insertions, 432 deletions
diff --git a/Documentation/power/regulator/overview.txt b/Documentation/power/regulator/overview.txt index 9363e056188a..8ed17587a74b 100644 --- a/Documentation/power/regulator/overview.txt +++ b/Documentation/power/regulator/overview.txt | |||
@@ -13,7 +13,7 @@ regulators (where voltage output is controllable) and current sinks (where | |||
13 | current limit is controllable). | 13 | current limit is controllable). |
14 | 14 | ||
15 | (C) 2008 Wolfson Microelectronics PLC. | 15 | (C) 2008 Wolfson Microelectronics PLC. |
16 | Author: Liam Girdwood <lg@opensource.wolfsonmicro.com> | 16 | Author: Liam Girdwood <lrg@slimlogic.co.uk> |
17 | 17 | ||
18 | 18 | ||
19 | Nomenclature | 19 | Nomenclature |
diff --git a/Documentation/workqueue.txt b/Documentation/workqueue.txt new file mode 100644 index 000000000000..e4498a2872c3 --- /dev/null +++ b/Documentation/workqueue.txt | |||
@@ -0,0 +1,380 @@ | |||
1 | |||
2 | Concurrency Managed Workqueue (cmwq) | ||
3 | |||
4 | September, 2010 Tejun Heo <tj@kernel.org> | ||
5 | Florian Mickler <florian@mickler.org> | ||
6 | |||
7 | CONTENTS | ||
8 | |||
9 | 1. Introduction | ||
10 | 2. Why cmwq? | ||
11 | 3. The Design | ||
12 | 4. Application Programming Interface (API) | ||
13 | 5. Example Execution Scenarios | ||
14 | 6. Guidelines | ||
15 | |||
16 | |||
17 | 1. Introduction | ||
18 | |||
19 | There are many cases where an asynchronous process execution context | ||
20 | is needed and the workqueue (wq) API is the most commonly used | ||
21 | mechanism for such cases. | ||
22 | |||
23 | When such an asynchronous execution context is needed, a work item | ||
24 | describing which function to execute is put on a queue. An | ||
25 | independent thread serves as the asynchronous execution context. The | ||
26 | queue is called workqueue and the thread is called worker. | ||
27 | |||
28 | While there are work items on the workqueue the worker executes the | ||
29 | functions associated with the work items one after the other. When | ||
30 | there is no work item left on the workqueue the worker becomes idle. | ||
31 | When a new work item gets queued, the worker begins executing again. | ||
32 | |||
33 | |||
34 | 2. Why cmwq? | ||
35 | |||
36 | In the original wq implementation, a multi threaded (MT) wq had one | ||
37 | worker thread per CPU and a single threaded (ST) wq had one worker | ||
38 | thread system-wide. A single MT wq needed to keep around the same | ||
39 | number of workers as the number of CPUs. The kernel grew a lot of MT | ||
40 | wq users over the years and with the number of CPU cores continuously | ||
41 | rising, some systems saturated the default 32k PID space just booting | ||
42 | up. | ||
43 | |||
44 | Although MT wq wasted a lot of resource, the level of concurrency | ||
45 | provided was unsatisfactory. The limitation was common to both ST and | ||
46 | MT wq albeit less severe on MT. Each wq maintained its own separate | ||
47 | worker pool. A MT wq could provide only one execution context per CPU | ||
48 | while a ST wq one for the whole system. Work items had to compete for | ||
49 | those very limited execution contexts leading to various problems | ||
50 | including proneness to deadlocks around the single execution context. | ||
51 | |||
52 | The tension between the provided level of concurrency and resource | ||
53 | usage also forced its users to make unnecessary tradeoffs like libata | ||
54 | choosing to use ST wq for polling PIOs and accepting an unnecessary | ||
55 | limitation that no two polling PIOs can progress at the same time. As | ||
56 | MT wq don't provide much better concurrency, users which require | ||
57 | higher level of concurrency, like async or fscache, had to implement | ||
58 | their own thread pool. | ||
59 | |||
60 | Concurrency Managed Workqueue (cmwq) is a reimplementation of wq with | ||
61 | focus on the following goals. | ||
62 | |||
63 | * Maintain compatibility with the original workqueue API. | ||
64 | |||
65 | * Use per-CPU unified worker pools shared by all wq to provide | ||
66 | flexible level of concurrency on demand without wasting a lot of | ||
67 | resource. | ||
68 | |||
69 | * Automatically regulate worker pool and level of concurrency so that | ||
70 | the API users don't need to worry about such details. | ||
71 | |||
72 | |||
73 | 3. The Design | ||
74 | |||
75 | In order to ease the asynchronous execution of functions a new | ||
76 | abstraction, the work item, is introduced. | ||
77 | |||
78 | A work item is a simple struct that holds a pointer to the function | ||
79 | that is to be executed asynchronously. Whenever a driver or subsystem | ||
80 | wants a function to be executed asynchronously it has to set up a work | ||
81 | item pointing to that function and queue that work item on a | ||
82 | workqueue. | ||
83 | |||
84 | Special purpose threads, called worker threads, execute the functions | ||
85 | off of the queue, one after the other. If no work is queued, the | ||
86 | worker threads become idle. These worker threads are managed in so | ||
87 | called thread-pools. | ||
88 | |||
89 | The cmwq design differentiates between the user-facing workqueues that | ||
90 | subsystems and drivers queue work items on and the backend mechanism | ||
91 | which manages thread-pool and processes the queued work items. | ||
92 | |||
93 | The backend is called gcwq. There is one gcwq for each possible CPU | ||
94 | and one gcwq to serve work items queued on unbound workqueues. | ||
95 | |||
96 | Subsystems and drivers can create and queue work items through special | ||
97 | workqueue API functions as they see fit. They can influence some | ||
98 | aspects of the way the work items are executed by setting flags on the | ||
99 | workqueue they are putting the work item on. These flags include | ||
100 | things like CPU locality, reentrancy, concurrency limits and more. To | ||
101 | get a detailed overview refer to the API description of | ||
102 | alloc_workqueue() below. | ||
103 | |||
104 | When a work item is queued to a workqueue, the target gcwq is | ||
105 | determined according to the queue parameters and workqueue attributes | ||
106 | and appended on the shared worklist of the gcwq. For example, unless | ||
107 | specifically overridden, a work item of a bound workqueue will be | ||
108 | queued on the worklist of exactly that gcwq that is associated to the | ||
109 | CPU the issuer is running on. | ||
110 | |||
111 | For any worker pool implementation, managing the concurrency level | ||
112 | (how many execution contexts are active) is an important issue. cmwq | ||
113 | tries to keep the concurrency at a minimal but sufficient level. | ||
114 | Minimal to save resources and sufficient in that the system is used at | ||
115 | its full capacity. | ||
116 | |||
117 | Each gcwq bound to an actual CPU implements concurrency management by | ||
118 | hooking into the scheduler. The gcwq is notified whenever an active | ||
119 | worker wakes up or sleeps and keeps track of the number of the | ||
120 | currently runnable workers. Generally, work items are not expected to | ||
121 | hog a CPU and consume many cycles. That means maintaining just enough | ||
122 | concurrency to prevent work processing from stalling should be | ||
123 | optimal. As long as there are one or more runnable workers on the | ||
124 | CPU, the gcwq doesn't start execution of a new work, but, when the | ||
125 | last running worker goes to sleep, it immediately schedules a new | ||
126 | worker so that the CPU doesn't sit idle while there are pending work | ||
127 | items. This allows using a minimal number of workers without losing | ||
128 | execution bandwidth. | ||
129 | |||
130 | Keeping idle workers around doesn't cost other than the memory space | ||
131 | for kthreads, so cmwq holds onto idle ones for a while before killing | ||
132 | them. | ||
133 | |||
134 | For an unbound wq, the above concurrency management doesn't apply and | ||
135 | the gcwq for the pseudo unbound CPU tries to start executing all work | ||
136 | items as soon as possible. The responsibility of regulating | ||
137 | concurrency level is on the users. There is also a flag to mark a | ||
138 | bound wq to ignore the concurrency management. Please refer to the | ||
139 | API section for details. | ||
140 | |||
141 | Forward progress guarantee relies on that workers can be created when | ||
142 | more execution contexts are necessary, which in turn is guaranteed | ||
143 | through the use of rescue workers. All work items which might be used | ||
144 | on code paths that handle memory reclaim are required to be queued on | ||
145 | wq's that have a rescue-worker reserved for execution under memory | ||
146 | pressure. Else it is possible that the thread-pool deadlocks waiting | ||
147 | for execution contexts to free up. | ||
148 | |||
149 | |||
150 | 4. Application Programming Interface (API) | ||
151 | |||
152 | alloc_workqueue() allocates a wq. The original create_*workqueue() | ||
153 | functions are deprecated and scheduled for removal. alloc_workqueue() | ||
154 | takes three arguments - @name, @flags and @max_active. @name is the | ||
155 | name of the wq and also used as the name of the rescuer thread if | ||
156 | there is one. | ||
157 | |||
158 | A wq no longer manages execution resources but serves as a domain for | ||
159 | forward progress guarantee, flush and work item attributes. @flags | ||
160 | and @max_active control how work items are assigned execution | ||
161 | resources, scheduled and executed. | ||
162 | |||
163 | @flags: | ||
164 | |||
165 | WQ_NON_REENTRANT | ||
166 | |||
167 | By default, a wq guarantees non-reentrance only on the same | ||
168 | CPU. A work item may not be executed concurrently on the same | ||
169 | CPU by multiple workers but is allowed to be executed | ||
170 | concurrently on multiple CPUs. This flag makes sure | ||
171 | non-reentrance is enforced across all CPUs. Work items queued | ||
172 | to a non-reentrant wq are guaranteed to be executed by at most | ||
173 | one worker system-wide at any given time. | ||
174 | |||
175 | WQ_UNBOUND | ||
176 | |||
177 | Work items queued to an unbound wq are served by a special | ||
178 | gcwq which hosts workers which are not bound to any specific | ||
179 | CPU. This makes the wq behave as a simple execution context | ||
180 | provider without concurrency management. The unbound gcwq | ||
181 | tries to start execution of work items as soon as possible. | ||
182 | Unbound wq sacrifices locality but is useful for the following | ||
183 | cases. | ||
184 | |||
185 | * Wide fluctuation in the concurrency level requirement is | ||
186 | expected and using bound wq may end up creating large number | ||
187 | of mostly unused workers across different CPUs as the issuer | ||
188 | hops through different CPUs. | ||
189 | |||
190 | * Long running CPU intensive workloads which can be better | ||
191 | managed by the system scheduler. | ||
192 | |||
193 | WQ_FREEZEABLE | ||
194 | |||
195 | A freezeable wq participates in the freeze phase of the system | ||
196 | suspend operations. Work items on the wq are drained and no | ||
197 | new work item starts execution until thawed. | ||
198 | |||
199 | WQ_RESCUER | ||
200 | |||
201 | All wq which might be used in the memory reclaim paths _MUST_ | ||
202 | have this flag set. This reserves one worker exclusively for | ||
203 | the execution of this wq under memory pressure. | ||
204 | |||
205 | WQ_HIGHPRI | ||
206 | |||
207 | Work items of a highpri wq are queued at the head of the | ||
208 | worklist of the target gcwq and start execution regardless of | ||
209 | the current concurrency level. In other words, highpri work | ||
210 | items will always start execution as soon as execution | ||
211 | resource is available. | ||
212 | |||
213 | Ordering among highpri work items is preserved - a highpri | ||
214 | work item queued after another highpri work item will start | ||
215 | execution after the earlier highpri work item starts. | ||
216 | |||
217 | Although highpri work items are not held back by other | ||
218 | runnable work items, they still contribute to the concurrency | ||
219 | level. Highpri work items in runnable state will prevent | ||
220 | non-highpri work items from starting execution. | ||
221 | |||
222 | This flag is meaningless for unbound wq. | ||
223 | |||
224 | WQ_CPU_INTENSIVE | ||
225 | |||
226 | Work items of a CPU intensive wq do not contribute to the | ||
227 | concurrency level. In other words, runnable CPU intensive | ||
228 | work items will not prevent other work items from starting | ||
229 | execution. This is useful for bound work items which are | ||
230 | expected to hog CPU cycles so that their execution is | ||
231 | regulated by the system scheduler. | ||
232 | |||
233 | Although CPU intensive work items don't contribute to the | ||
234 | concurrency level, start of their executions is still | ||
235 | regulated by the concurrency management and runnable | ||
236 | non-CPU-intensive work items can delay execution of CPU | ||
237 | intensive work items. | ||
238 | |||
239 | This flag is meaningless for unbound wq. | ||
240 | |||
241 | WQ_HIGHPRI | WQ_CPU_INTENSIVE | ||
242 | |||
243 | This combination makes the wq avoid interaction with | ||
244 | concurrency management completely and behave as a simple | ||
245 | per-CPU execution context provider. Work items queued on a | ||
246 | highpri CPU-intensive wq start execution as soon as resources | ||
247 | are available and don't affect execution of other work items. | ||
248 | |||
249 | @max_active: | ||
250 | |||
251 | @max_active determines the maximum number of execution contexts per | ||
252 | CPU which can be assigned to the work items of a wq. For example, | ||
253 | with @max_active of 16, at most 16 work items of the wq can be | ||
254 | executing at the same time per CPU. | ||
255 | |||
256 | Currently, for a bound wq, the maximum limit for @max_active is 512 | ||
257 | and the default value used when 0 is specified is 256. For an unbound | ||
258 | wq, the limit is higher of 512 and 4 * num_possible_cpus(). These | ||
259 | values are chosen sufficiently high such that they are not the | ||
260 | limiting factor while providing protection in runaway cases. | ||
261 | |||
262 | The number of active work items of a wq is usually regulated by the | ||
263 | users of the wq, more specifically, by how many work items the users | ||
264 | may queue at the same time. Unless there is a specific need for | ||
265 | throttling the number of active work items, specifying '0' is | ||
266 | recommended. | ||
267 | |||
268 | Some users depend on the strict execution ordering of ST wq. The | ||
269 | combination of @max_active of 1 and WQ_UNBOUND is used to achieve this | ||
270 | behavior. Work items on such wq are always queued to the unbound gcwq | ||
271 | and only one work item can be active at any given time thus achieving | ||
272 | the same ordering property as ST wq. | ||
273 | |||
274 | |||
275 | 5. Example Execution Scenarios | ||
276 | |||
277 | The following example execution scenarios try to illustrate how cmwq | ||
278 | behave under different configurations. | ||
279 | |||
280 | Work items w0, w1, w2 are queued to a bound wq q0 on the same CPU. | ||
281 | w0 burns CPU for 5ms then sleeps for 10ms then burns CPU for 5ms | ||
282 | again before finishing. w1 and w2 burn CPU for 5ms then sleep for | ||
283 | 10ms. | ||
284 | |||
285 | Ignoring all other tasks, works and processing overhead, and assuming | ||
286 | simple FIFO scheduling, the following is one highly simplified version | ||
287 | of possible sequences of events with the original wq. | ||
288 | |||
289 | TIME IN MSECS EVENT | ||
290 | 0 w0 starts and burns CPU | ||
291 | 5 w0 sleeps | ||
292 | 15 w0 wakes up and burns CPU | ||
293 | 20 w0 finishes | ||
294 | 20 w1 starts and burns CPU | ||
295 | 25 w1 sleeps | ||
296 | 35 w1 wakes up and finishes | ||
297 | 35 w2 starts and burns CPU | ||
298 | 40 w2 sleeps | ||
299 | 50 w2 wakes up and finishes | ||
300 | |||
301 | And with cmwq with @max_active >= 3, | ||
302 | |||
303 | TIME IN MSECS EVENT | ||
304 | 0 w0 starts and burns CPU | ||
305 | 5 w0 sleeps | ||
306 | 5 w1 starts and burns CPU | ||
307 | 10 w1 sleeps | ||
308 | 10 w2 starts and burns CPU | ||
309 | 15 w2 sleeps | ||
310 | 15 w0 wakes up and burns CPU | ||
311 | 20 w0 finishes | ||
312 | 20 w1 wakes up and finishes | ||
313 | 25 w2 wakes up and finishes | ||
314 | |||
315 | If @max_active == 2, | ||
316 | |||
317 | TIME IN MSECS EVENT | ||
318 | 0 w0 starts and burns CPU | ||
319 | 5 w0 sleeps | ||
320 | 5 w1 starts and burns CPU | ||
321 | 10 w1 sleeps | ||
322 | 15 w0 wakes up and burns CPU | ||
323 | 20 w0 finishes | ||
324 | 20 w1 wakes up and finishes | ||
325 | 20 w2 starts and burns CPU | ||
326 | 25 w2 sleeps | ||
327 | 35 w2 wakes up and finishes | ||
328 | |||
329 | Now, let's assume w1 and w2 are queued to a different wq q1 which has | ||
330 | WQ_HIGHPRI set, | ||
331 | |||
332 | TIME IN MSECS EVENT | ||
333 | 0 w1 and w2 start and burn CPU | ||
334 | 5 w1 sleeps | ||
335 | 10 w2 sleeps | ||
336 | 10 w0 starts and burns CPU | ||
337 | 15 w0 sleeps | ||
338 | 15 w1 wakes up and finishes | ||
339 | 20 w2 wakes up and finishes | ||
340 | 25 w0 wakes up and burns CPU | ||
341 | 30 w0 finishes | ||
342 | |||
343 | If q1 has WQ_CPU_INTENSIVE set, | ||
344 | |||
345 | TIME IN MSECS EVENT | ||
346 | 0 w0 starts and burns CPU | ||
347 | 5 w0 sleeps | ||
348 | 5 w1 and w2 start and burn CPU | ||
349 | 10 w1 sleeps | ||
350 | 15 w2 sleeps | ||
351 | 15 w0 wakes up and burns CPU | ||
352 | 20 w0 finishes | ||
353 | 20 w1 wakes up and finishes | ||
354 | 25 w2 wakes up and finishes | ||
355 | |||
356 | |||
357 | 6. Guidelines | ||
358 | |||
359 | * Do not forget to use WQ_RESCUER if a wq may process work items which | ||
360 | are used during memory reclaim. Each wq with WQ_RESCUER set has one | ||
361 | rescuer thread reserved for it. If there is dependency among | ||
362 | multiple work items used during memory reclaim, they should be | ||
363 | queued to separate wq each with WQ_RESCUER. | ||
364 | |||
365 | * Unless strict ordering is required, there is no need to use ST wq. | ||
366 | |||
367 | * Unless there is a specific need, using 0 for @max_active is | ||
368 | recommended. In most use cases, concurrency level usually stays | ||
369 | well under the default limit. | ||
370 | |||
371 | * A wq serves as a domain for forward progress guarantee (WQ_RESCUER), | ||
372 | flush and work item attributes. Work items which are not involved | ||
373 | in memory reclaim and don't need to be flushed as a part of a group | ||
374 | of work items, and don't require any special attribute, can use one | ||
375 | of the system wq. There is no difference in execution | ||
376 | characteristics between using a dedicated wq and a system wq. | ||
377 | |||
378 | * Unless work items are expected to consume a huge amount of CPU | ||
379 | cycles, using a bound wq is usually beneficial due to the increased | ||
380 | level of locality in wq operations and work item execution. | ||
diff --git a/arch/ia64/include/asm/compat.h b/arch/ia64/include/asm/compat.h index f90edc85b509..9301a2821615 100644 --- a/arch/ia64/include/asm/compat.h +++ b/arch/ia64/include/asm/compat.h | |||
@@ -199,7 +199,7 @@ ptr_to_compat(void __user *uptr) | |||
199 | } | 199 | } |
200 | 200 | ||
201 | static __inline__ void __user * | 201 | static __inline__ void __user * |
202 | compat_alloc_user_space (long len) | 202 | arch_compat_alloc_user_space (long len) |
203 | { | 203 | { |
204 | struct pt_regs *regs = task_pt_regs(current); | 204 | struct pt_regs *regs = task_pt_regs(current); |
205 | return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len); | 205 | return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len); |
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h index 613f6912dfc1..dbc51065df5b 100644 --- a/arch/mips/include/asm/compat.h +++ b/arch/mips/include/asm/compat.h | |||
@@ -145,7 +145,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
145 | return (u32)(unsigned long)uptr; | 145 | return (u32)(unsigned long)uptr; |
146 | } | 146 | } |
147 | 147 | ||
148 | static inline void __user *compat_alloc_user_space(long len) | 148 | static inline void __user *arch_compat_alloc_user_space(long len) |
149 | { | 149 | { |
150 | struct pt_regs *regs = (struct pt_regs *) | 150 | struct pt_regs *regs = (struct pt_regs *) |
151 | ((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1; | 151 | ((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1; |
diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c index 9d49073e827a..db509dd80565 100644 --- a/arch/mn10300/kernel/mn10300-serial.c +++ b/arch/mn10300/kernel/mn10300-serial.c | |||
@@ -156,17 +156,17 @@ struct mn10300_serial_port mn10300_serial_port_sif0 = { | |||
156 | ._intr = &SC0ICR, | 156 | ._intr = &SC0ICR, |
157 | ._rxb = &SC0RXB, | 157 | ._rxb = &SC0RXB, |
158 | ._txb = &SC0TXB, | 158 | ._txb = &SC0TXB, |
159 | .rx_name = "ttySM0/Rx", | 159 | .rx_name = "ttySM0:Rx", |
160 | .tx_name = "ttySM0/Tx", | 160 | .tx_name = "ttySM0:Tx", |
161 | #ifdef CONFIG_MN10300_TTYSM0_TIMER8 | 161 | #ifdef CONFIG_MN10300_TTYSM0_TIMER8 |
162 | .tm_name = "ttySM0/Timer8", | 162 | .tm_name = "ttySM0:Timer8", |
163 | ._tmxmd = &TM8MD, | 163 | ._tmxmd = &TM8MD, |
164 | ._tmxbr = &TM8BR, | 164 | ._tmxbr = &TM8BR, |
165 | ._tmicr = &TM8ICR, | 165 | ._tmicr = &TM8ICR, |
166 | .tm_irq = TM8IRQ, | 166 | .tm_irq = TM8IRQ, |
167 | .div_timer = MNSCx_DIV_TIMER_16BIT, | 167 | .div_timer = MNSCx_DIV_TIMER_16BIT, |
168 | #else /* CONFIG_MN10300_TTYSM0_TIMER2 */ | 168 | #else /* CONFIG_MN10300_TTYSM0_TIMER2 */ |
169 | .tm_name = "ttySM0/Timer2", | 169 | .tm_name = "ttySM0:Timer2", |
170 | ._tmxmd = &TM2MD, | 170 | ._tmxmd = &TM2MD, |
171 | ._tmxbr = (volatile u16 *) &TM2BR, | 171 | ._tmxbr = (volatile u16 *) &TM2BR, |
172 | ._tmicr = &TM2ICR, | 172 | ._tmicr = &TM2ICR, |
@@ -209,17 +209,17 @@ struct mn10300_serial_port mn10300_serial_port_sif1 = { | |||
209 | ._intr = &SC1ICR, | 209 | ._intr = &SC1ICR, |
210 | ._rxb = &SC1RXB, | 210 | ._rxb = &SC1RXB, |
211 | ._txb = &SC1TXB, | 211 | ._txb = &SC1TXB, |
212 | .rx_name = "ttySM1/Rx", | 212 | .rx_name = "ttySM1:Rx", |
213 | .tx_name = "ttySM1/Tx", | 213 | .tx_name = "ttySM1:Tx", |
214 | #ifdef CONFIG_MN10300_TTYSM1_TIMER9 | 214 | #ifdef CONFIG_MN10300_TTYSM1_TIMER9 |
215 | .tm_name = "ttySM1/Timer9", | 215 | .tm_name = "ttySM1:Timer9", |
216 | ._tmxmd = &TM9MD, | 216 | ._tmxmd = &TM9MD, |
217 | ._tmxbr = &TM9BR, | 217 | ._tmxbr = &TM9BR, |
218 | ._tmicr = &TM9ICR, | 218 | ._tmicr = &TM9ICR, |
219 | .tm_irq = TM9IRQ, | 219 | .tm_irq = TM9IRQ, |
220 | .div_timer = MNSCx_DIV_TIMER_16BIT, | 220 | .div_timer = MNSCx_DIV_TIMER_16BIT, |
221 | #else /* CONFIG_MN10300_TTYSM1_TIMER3 */ | 221 | #else /* CONFIG_MN10300_TTYSM1_TIMER3 */ |
222 | .tm_name = "ttySM1/Timer3", | 222 | .tm_name = "ttySM1:Timer3", |
223 | ._tmxmd = &TM3MD, | 223 | ._tmxmd = &TM3MD, |
224 | ._tmxbr = (volatile u16 *) &TM3BR, | 224 | ._tmxbr = (volatile u16 *) &TM3BR, |
225 | ._tmicr = &TM3ICR, | 225 | ._tmicr = &TM3ICR, |
@@ -260,9 +260,9 @@ struct mn10300_serial_port mn10300_serial_port_sif2 = { | |||
260 | .uart.lock = | 260 | .uart.lock = |
261 | __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif2.uart.lock), | 261 | __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif2.uart.lock), |
262 | .name = "ttySM2", | 262 | .name = "ttySM2", |
263 | .rx_name = "ttySM2/Rx", | 263 | .rx_name = "ttySM2:Rx", |
264 | .tx_name = "ttySM2/Tx", | 264 | .tx_name = "ttySM2:Tx", |
265 | .tm_name = "ttySM2/Timer10", | 265 | .tm_name = "ttySM2:Timer10", |
266 | ._iobase = &SC2CTR, | 266 | ._iobase = &SC2CTR, |
267 | ._control = &SC2CTR, | 267 | ._control = &SC2CTR, |
268 | ._status = &SC2STR, | 268 | ._status = &SC2STR, |
diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h index 02b77baa5da6..efa0b60c63fe 100644 --- a/arch/parisc/include/asm/compat.h +++ b/arch/parisc/include/asm/compat.h | |||
@@ -147,7 +147,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
147 | return (u32)(unsigned long)uptr; | 147 | return (u32)(unsigned long)uptr; |
148 | } | 148 | } |
149 | 149 | ||
150 | static __inline__ void __user *compat_alloc_user_space(long len) | 150 | static __inline__ void __user *arch_compat_alloc_user_space(long len) |
151 | { | 151 | { |
152 | struct pt_regs *regs = ¤t->thread.regs; | 152 | struct pt_regs *regs = ¤t->thread.regs; |
153 | return (void __user *)regs->gr[30]; | 153 | return (void __user *)regs->gr[30]; |
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h index 396d21a80058..a11d4eac4f97 100644 --- a/arch/powerpc/include/asm/compat.h +++ b/arch/powerpc/include/asm/compat.h | |||
@@ -134,7 +134,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
134 | return (u32)(unsigned long)uptr; | 134 | return (u32)(unsigned long)uptr; |
135 | } | 135 | } |
136 | 136 | ||
137 | static inline void __user *compat_alloc_user_space(long len) | 137 | static inline void __user *arch_compat_alloc_user_space(long len) |
138 | { | 138 | { |
139 | struct pt_regs *regs = current->thread.regs; | 139 | struct pt_regs *regs = current->thread.regs; |
140 | unsigned long usp = regs->gpr[1]; | 140 | unsigned long usp = regs->gpr[1]; |
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index 104f2007f097..a875c2f542e1 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h | |||
@@ -181,7 +181,7 @@ static inline int is_compat_task(void) | |||
181 | 181 | ||
182 | #endif | 182 | #endif |
183 | 183 | ||
184 | static inline void __user *compat_alloc_user_space(long len) | 184 | static inline void __user *arch_compat_alloc_user_space(long len) |
185 | { | 185 | { |
186 | unsigned long stack; | 186 | unsigned long stack; |
187 | 187 | ||
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h index 5016f76ea98a..6f57325bb883 100644 --- a/arch/sparc/include/asm/compat.h +++ b/arch/sparc/include/asm/compat.h | |||
@@ -167,7 +167,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
167 | return (u32)(unsigned long)uptr; | 167 | return (u32)(unsigned long)uptr; |
168 | } | 168 | } |
169 | 169 | ||
170 | static inline void __user *compat_alloc_user_space(long len) | 170 | static inline void __user *arch_compat_alloc_user_space(long len) |
171 | { | 171 | { |
172 | struct pt_regs *regs = current_thread_info()->kregs; | 172 | struct pt_regs *regs = current_thread_info()->kregs; |
173 | unsigned long usp = regs->u_regs[UREG_I6]; | 173 | unsigned long usp = regs->u_regs[UREG_I6]; |
diff --git a/arch/tile/include/arch/chip_tile64.h b/arch/tile/include/arch/chip_tile64.h index 1246573be59e..261aaba092d4 100644 --- a/arch/tile/include/arch/chip_tile64.h +++ b/arch/tile/include/arch/chip_tile64.h | |||
@@ -150,6 +150,9 @@ | |||
150 | /** Is the PROC_STATUS SPR supported? */ | 150 | /** Is the PROC_STATUS SPR supported? */ |
151 | #define CHIP_HAS_PROC_STATUS_SPR() 0 | 151 | #define CHIP_HAS_PROC_STATUS_SPR() 0 |
152 | 152 | ||
153 | /** Is the DSTREAM_PF SPR supported? */ | ||
154 | #define CHIP_HAS_DSTREAM_PF() 0 | ||
155 | |||
153 | /** Log of the number of mshims we have. */ | 156 | /** Log of the number of mshims we have. */ |
154 | #define CHIP_LOG_NUM_MSHIMS() 2 | 157 | #define CHIP_LOG_NUM_MSHIMS() 2 |
155 | 158 | ||
diff --git a/arch/tile/include/arch/chip_tilepro.h b/arch/tile/include/arch/chip_tilepro.h index e864c47fc89c..70017699a74c 100644 --- a/arch/tile/include/arch/chip_tilepro.h +++ b/arch/tile/include/arch/chip_tilepro.h | |||
@@ -150,6 +150,9 @@ | |||
150 | /** Is the PROC_STATUS SPR supported? */ | 150 | /** Is the PROC_STATUS SPR supported? */ |
151 | #define CHIP_HAS_PROC_STATUS_SPR() 1 | 151 | #define CHIP_HAS_PROC_STATUS_SPR() 1 |
152 | 152 | ||
153 | /** Is the DSTREAM_PF SPR supported? */ | ||
154 | #define CHIP_HAS_DSTREAM_PF() 0 | ||
155 | |||
153 | /** Log of the number of mshims we have. */ | 156 | /** Log of the number of mshims we have. */ |
154 | #define CHIP_LOG_NUM_MSHIMS() 2 | 157 | #define CHIP_LOG_NUM_MSHIMS() 2 |
155 | 158 | ||
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h index 5a34da6cdd79..8b60ec8b2d19 100644 --- a/arch/tile/include/asm/compat.h +++ b/arch/tile/include/asm/compat.h | |||
@@ -195,7 +195,7 @@ static inline unsigned long ptr_to_compat_reg(void __user *uptr) | |||
195 | return (long)(int)(long __force)uptr; | 195 | return (long)(int)(long __force)uptr; |
196 | } | 196 | } |
197 | 197 | ||
198 | static inline void __user *compat_alloc_user_space(long len) | 198 | static inline void __user *arch_compat_alloc_user_space(long len) |
199 | { | 199 | { |
200 | struct pt_regs *regs = task_pt_regs(current); | 200 | struct pt_regs *regs = task_pt_regs(current); |
201 | return (void __user *)regs->sp - len; | 201 | return (void __user *)regs->sp - len; |
@@ -214,8 +214,9 @@ extern int compat_setup_rt_frame(int sig, struct k_sigaction *ka, | |||
214 | struct compat_sigaction; | 214 | struct compat_sigaction; |
215 | struct compat_siginfo; | 215 | struct compat_siginfo; |
216 | struct compat_sigaltstack; | 216 | struct compat_sigaltstack; |
217 | long compat_sys_execve(char __user *path, compat_uptr_t __user *argv, | 217 | long compat_sys_execve(const char __user *path, |
218 | compat_uptr_t __user *envp); | 218 | const compat_uptr_t __user *argv, |
219 | const compat_uptr_t __user *envp); | ||
219 | long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act, | 220 | long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act, |
220 | struct compat_sigaction __user *oact, | 221 | struct compat_sigaction __user *oact, |
221 | size_t sigsetsize); | 222 | size_t sigsetsize); |
diff --git a/arch/tile/include/asm/io.h b/arch/tile/include/asm/io.h index 8c95bef3fa45..ee43328713ab 100644 --- a/arch/tile/include/asm/io.h +++ b/arch/tile/include/asm/io.h | |||
@@ -164,22 +164,22 @@ static inline void _tile_writeq(u64 val, unsigned long addr) | |||
164 | #define iowrite32 writel | 164 | #define iowrite32 writel |
165 | #define iowrite64 writeq | 165 | #define iowrite64 writeq |
166 | 166 | ||
167 | static inline void *memcpy_fromio(void *dst, void *src, int len) | 167 | static inline void memcpy_fromio(void *dst, const volatile void __iomem *src, |
168 | size_t len) | ||
168 | { | 169 | { |
169 | int x; | 170 | int x; |
170 | BUG_ON((unsigned long)src & 0x3); | 171 | BUG_ON((unsigned long)src & 0x3); |
171 | for (x = 0; x < len; x += 4) | 172 | for (x = 0; x < len; x += 4) |
172 | *(u32 *)(dst + x) = readl(src + x); | 173 | *(u32 *)(dst + x) = readl(src + x); |
173 | return dst; | ||
174 | } | 174 | } |
175 | 175 | ||
176 | static inline void *memcpy_toio(void *dst, void *src, int len) | 176 | static inline void memcpy_toio(volatile void __iomem *dst, const void *src, |
177 | size_t len) | ||
177 | { | 178 | { |
178 | int x; | 179 | int x; |
179 | BUG_ON((unsigned long)dst & 0x3); | 180 | BUG_ON((unsigned long)dst & 0x3); |
180 | for (x = 0; x < len; x += 4) | 181 | for (x = 0; x < len; x += 4) |
181 | writel(*(u32 *)(src + x), dst + x); | 182 | writel(*(u32 *)(src + x), dst + x); |
182 | return dst; | ||
183 | } | 183 | } |
184 | 184 | ||
185 | /* | 185 | /* |
diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h index d942d09b252e..ccd5f8425688 100644 --- a/arch/tile/include/asm/processor.h +++ b/arch/tile/include/asm/processor.h | |||
@@ -103,6 +103,18 @@ struct thread_struct { | |||
103 | /* Any other miscellaneous processor state bits */ | 103 | /* Any other miscellaneous processor state bits */ |
104 | unsigned long proc_status; | 104 | unsigned long proc_status; |
105 | #endif | 105 | #endif |
106 | #if !CHIP_HAS_FIXED_INTVEC_BASE() | ||
107 | /* Interrupt base for PL0 interrupts */ | ||
108 | unsigned long interrupt_vector_base; | ||
109 | #endif | ||
110 | #if CHIP_HAS_TILE_RTF_HWM() | ||
111 | /* Tile cache retry fifo high-water mark */ | ||
112 | unsigned long tile_rtf_hwm; | ||
113 | #endif | ||
114 | #if CHIP_HAS_DSTREAM_PF() | ||
115 | /* Data stream prefetch control */ | ||
116 | unsigned long dstream_pf; | ||
117 | #endif | ||
106 | #ifdef CONFIG_HARDWALL | 118 | #ifdef CONFIG_HARDWALL |
107 | /* Is this task tied to an activated hardwall? */ | 119 | /* Is this task tied to an activated hardwall? */ |
108 | struct hardwall_info *hardwall; | 120 | struct hardwall_info *hardwall; |
diff --git a/arch/tile/include/asm/ptrace.h b/arch/tile/include/asm/ptrace.h index acdae814e016..4a02bb073979 100644 --- a/arch/tile/include/asm/ptrace.h +++ b/arch/tile/include/asm/ptrace.h | |||
@@ -51,10 +51,7 @@ typedef uint_reg_t pt_reg_t; | |||
51 | 51 | ||
52 | /* | 52 | /* |
53 | * This struct defines the way the registers are stored on the stack during a | 53 | * This struct defines the way the registers are stored on the stack during a |
54 | * system call/exception. It should be a multiple of 8 bytes to preserve | 54 | * system call or exception. "struct sigcontext" has the same shape. |
55 | * normal stack alignment rules. | ||
56 | * | ||
57 | * Must track <sys/ucontext.h> and <sys/procfs.h> | ||
58 | */ | 55 | */ |
59 | struct pt_regs { | 56 | struct pt_regs { |
60 | /* Saved main processor registers; 56..63 are special. */ | 57 | /* Saved main processor registers; 56..63 are special. */ |
@@ -80,11 +77,6 @@ struct pt_regs { | |||
80 | 77 | ||
81 | #endif /* __ASSEMBLY__ */ | 78 | #endif /* __ASSEMBLY__ */ |
82 | 79 | ||
83 | /* Flag bits in pt_regs.flags */ | ||
84 | #define PT_FLAGS_DISABLE_IRQ 1 /* on return to kernel, disable irqs */ | ||
85 | #define PT_FLAGS_CALLER_SAVES 2 /* caller-save registers are valid */ | ||
86 | #define PT_FLAGS_RESTORE_REGS 4 /* restore callee-save regs on return */ | ||
87 | |||
88 | #define PTRACE_GETREGS 12 | 80 | #define PTRACE_GETREGS 12 |
89 | #define PTRACE_SETREGS 13 | 81 | #define PTRACE_SETREGS 13 |
90 | #define PTRACE_GETFPREGS 14 | 82 | #define PTRACE_GETFPREGS 14 |
@@ -101,6 +93,11 @@ struct pt_regs { | |||
101 | 93 | ||
102 | #ifdef __KERNEL__ | 94 | #ifdef __KERNEL__ |
103 | 95 | ||
96 | /* Flag bits in pt_regs.flags */ | ||
97 | #define PT_FLAGS_DISABLE_IRQ 1 /* on return to kernel, disable irqs */ | ||
98 | #define PT_FLAGS_CALLER_SAVES 2 /* caller-save registers are valid */ | ||
99 | #define PT_FLAGS_RESTORE_REGS 4 /* restore callee-save regs on return */ | ||
100 | |||
104 | #ifndef __ASSEMBLY__ | 101 | #ifndef __ASSEMBLY__ |
105 | 102 | ||
106 | #define instruction_pointer(regs) ((regs)->pc) | 103 | #define instruction_pointer(regs) ((regs)->pc) |
diff --git a/arch/tile/include/asm/sigcontext.h b/arch/tile/include/asm/sigcontext.h index 7cd7672e3ad4..5e2d03336f53 100644 --- a/arch/tile/include/asm/sigcontext.h +++ b/arch/tile/include/asm/sigcontext.h | |||
@@ -15,13 +15,21 @@ | |||
15 | #ifndef _ASM_TILE_SIGCONTEXT_H | 15 | #ifndef _ASM_TILE_SIGCONTEXT_H |
16 | #define _ASM_TILE_SIGCONTEXT_H | 16 | #define _ASM_TILE_SIGCONTEXT_H |
17 | 17 | ||
18 | /* NOTE: we can't include <linux/ptrace.h> due to #include dependencies. */ | 18 | #include <arch/abi.h> |
19 | #include <asm/ptrace.h> | ||
20 | |||
21 | /* Must track <sys/ucontext.h> */ | ||
22 | 19 | ||
20 | /* | ||
21 | * struct sigcontext has the same shape as struct pt_regs, | ||
22 | * but is simplified since we know the fault is from userspace. | ||
23 | */ | ||
23 | struct sigcontext { | 24 | struct sigcontext { |
24 | struct pt_regs regs; | 25 | uint_reg_t gregs[53]; /* General-purpose registers. */ |
26 | uint_reg_t tp; /* Aliases gregs[TREG_TP]. */ | ||
27 | uint_reg_t sp; /* Aliases gregs[TREG_SP]. */ | ||
28 | uint_reg_t lr; /* Aliases gregs[TREG_LR]. */ | ||
29 | uint_reg_t pc; /* Program counter. */ | ||
30 | uint_reg_t ics; /* In Interrupt Critical Section? */ | ||
31 | uint_reg_t faultnum; /* Fault number. */ | ||
32 | uint_reg_t pad[5]; | ||
25 | }; | 33 | }; |
26 | 34 | ||
27 | #endif /* _ASM_TILE_SIGCONTEXT_H */ | 35 | #endif /* _ASM_TILE_SIGCONTEXT_H */ |
diff --git a/arch/tile/include/asm/signal.h b/arch/tile/include/asm/signal.h index eb0253f32202..c1ee1d61d44c 100644 --- a/arch/tile/include/asm/signal.h +++ b/arch/tile/include/asm/signal.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm-generic/signal.h> | 24 | #include <asm-generic/signal.h> |
25 | 25 | ||
26 | #if defined(__KERNEL__) && !defined(__ASSEMBLY__) | 26 | #if defined(__KERNEL__) && !defined(__ASSEMBLY__) |
27 | struct pt_regs; | ||
27 | int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *); | 28 | int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *); |
28 | int setup_sigcontext(struct sigcontext __user *, struct pt_regs *); | 29 | int setup_sigcontext(struct sigcontext __user *, struct pt_regs *); |
29 | void do_signal(struct pt_regs *regs); | 30 | void do_signal(struct pt_regs *regs); |
diff --git a/arch/tile/include/asm/syscalls.h b/arch/tile/include/asm/syscalls.h index af165a74537f..ce99ffefeacf 100644 --- a/arch/tile/include/asm/syscalls.h +++ b/arch/tile/include/asm/syscalls.h | |||
@@ -62,10 +62,12 @@ long sys_fork(void); | |||
62 | long _sys_fork(struct pt_regs *regs); | 62 | long _sys_fork(struct pt_regs *regs); |
63 | long sys_vfork(void); | 63 | long sys_vfork(void); |
64 | long _sys_vfork(struct pt_regs *regs); | 64 | long _sys_vfork(struct pt_regs *regs); |
65 | long sys_execve(char __user *filename, char __user * __user *argv, | 65 | long sys_execve(const char __user *filename, |
66 | char __user * __user *envp); | 66 | const char __user *const __user *argv, |
67 | long _sys_execve(char __user *filename, char __user * __user *argv, | 67 | const char __user *const __user *envp); |
68 | char __user * __user *envp, struct pt_regs *regs); | 68 | long _sys_execve(const char __user *filename, |
69 | const char __user *const __user *argv, | ||
70 | const char __user *const __user *envp, struct pt_regs *regs); | ||
69 | 71 | ||
70 | /* kernel/signal.c */ | 72 | /* kernel/signal.c */ |
71 | long sys_sigaltstack(const stack_t __user *, stack_t __user *); | 73 | long sys_sigaltstack(const stack_t __user *, stack_t __user *); |
@@ -86,10 +88,13 @@ int _sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *); | |||
86 | #endif | 88 | #endif |
87 | 89 | ||
88 | #ifdef CONFIG_COMPAT | 90 | #ifdef CONFIG_COMPAT |
89 | long compat_sys_execve(char __user *path, compat_uptr_t __user *argv, | 91 | long compat_sys_execve(const char __user *path, |
90 | compat_uptr_t __user *envp); | 92 | const compat_uptr_t __user *argv, |
91 | long _compat_sys_execve(char __user *path, compat_uptr_t __user *argv, | 93 | const compat_uptr_t __user *envp); |
92 | compat_uptr_t __user *envp, struct pt_regs *regs); | 94 | long _compat_sys_execve(const char __user *path, |
95 | const compat_uptr_t __user *argv, | ||
96 | const compat_uptr_t __user *envp, | ||
97 | struct pt_regs *regs); | ||
93 | long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, | 98 | long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, |
94 | struct compat_sigaltstack __user *uoss_ptr); | 99 | struct compat_sigaltstack __user *uoss_ptr); |
95 | long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, | 100 | long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, |
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index 985cc28c74c5..84c29111756c 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c | |||
@@ -408,6 +408,15 @@ static void save_arch_state(struct thread_struct *t) | |||
408 | #if CHIP_HAS_PROC_STATUS_SPR() | 408 | #if CHIP_HAS_PROC_STATUS_SPR() |
409 | t->proc_status = __insn_mfspr(SPR_PROC_STATUS); | 409 | t->proc_status = __insn_mfspr(SPR_PROC_STATUS); |
410 | #endif | 410 | #endif |
411 | #if !CHIP_HAS_FIXED_INTVEC_BASE() | ||
412 | t->interrupt_vector_base = __insn_mfspr(SPR_INTERRUPT_VECTOR_BASE_0); | ||
413 | #endif | ||
414 | #if CHIP_HAS_TILE_RTF_HWM() | ||
415 | t->tile_rtf_hwm = __insn_mfspr(SPR_TILE_RTF_HWM); | ||
416 | #endif | ||
417 | #if CHIP_HAS_DSTREAM_PF() | ||
418 | t->dstream_pf = __insn_mfspr(SPR_DSTREAM_PF); | ||
419 | #endif | ||
411 | } | 420 | } |
412 | 421 | ||
413 | static void restore_arch_state(const struct thread_struct *t) | 422 | static void restore_arch_state(const struct thread_struct *t) |
@@ -428,14 +437,14 @@ static void restore_arch_state(const struct thread_struct *t) | |||
428 | #if CHIP_HAS_PROC_STATUS_SPR() | 437 | #if CHIP_HAS_PROC_STATUS_SPR() |
429 | __insn_mtspr(SPR_PROC_STATUS, t->proc_status); | 438 | __insn_mtspr(SPR_PROC_STATUS, t->proc_status); |
430 | #endif | 439 | #endif |
440 | #if !CHIP_HAS_FIXED_INTVEC_BASE() | ||
441 | __insn_mtspr(SPR_INTERRUPT_VECTOR_BASE_0, t->interrupt_vector_base); | ||
442 | #endif | ||
431 | #if CHIP_HAS_TILE_RTF_HWM() | 443 | #if CHIP_HAS_TILE_RTF_HWM() |
432 | /* | 444 | __insn_mtspr(SPR_TILE_RTF_HWM, t->tile_rtf_hwm); |
433 | * Clear this whenever we switch back to a process in case | 445 | #endif |
434 | * the previous process was monkeying with it. Even if enabled | 446 | #if CHIP_HAS_DSTREAM_PF() |
435 | * in CBOX_MSR1 via TILE_RTF_HWM_MIN, it's still just a | 447 | __insn_mtspr(SPR_DSTREAM_PF, t->dstream_pf); |
436 | * performance hint, so isn't worth a full save/restore. | ||
437 | */ | ||
438 | __insn_mtspr(SPR_TILE_RTF_HWM, 0); | ||
439 | #endif | 448 | #endif |
440 | } | 449 | } |
441 | 450 | ||
@@ -561,8 +570,9 @@ out: | |||
561 | } | 570 | } |
562 | 571 | ||
563 | #ifdef CONFIG_COMPAT | 572 | #ifdef CONFIG_COMPAT |
564 | long _compat_sys_execve(char __user *path, compat_uptr_t __user *argv, | 573 | long _compat_sys_execve(const char __user *path, |
565 | compat_uptr_t __user *envp, struct pt_regs *regs) | 574 | const compat_uptr_t __user *argv, |
575 | const compat_uptr_t __user *envp, struct pt_regs *regs) | ||
566 | { | 576 | { |
567 | long error; | 577 | long error; |
568 | char *filename; | 578 | char *filename; |
@@ -657,7 +667,7 @@ void show_regs(struct pt_regs *regs) | |||
657 | regs->regs[51], regs->regs[52], regs->tp); | 667 | regs->regs[51], regs->regs[52], regs->tp); |
658 | pr_err(" sp : "REGFMT" lr : "REGFMT"\n", regs->sp, regs->lr); | 668 | pr_err(" sp : "REGFMT" lr : "REGFMT"\n", regs->sp, regs->lr); |
659 | #else | 669 | #else |
660 | for (i = 0; i < 52; i += 3) | 670 | for (i = 0; i < 52; i += 4) |
661 | pr_err(" r%-2d: "REGFMT" r%-2d: "REGFMT | 671 | pr_err(" r%-2d: "REGFMT" r%-2d: "REGFMT |
662 | " r%-2d: "REGFMT" r%-2d: "REGFMT"\n", | 672 | " r%-2d: "REGFMT" r%-2d: "REGFMT"\n", |
663 | i, regs->regs[i], i+1, regs->regs[i+1], | 673 | i, regs->regs[i], i+1, regs->regs[i+1], |
diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c index 45b66a3c991f..ce183aa1492c 100644 --- a/arch/tile/kernel/signal.c +++ b/arch/tile/kernel/signal.c | |||
@@ -61,13 +61,19 @@ int restore_sigcontext(struct pt_regs *regs, | |||
61 | /* Always make any pending restarted system calls return -EINTR */ | 61 | /* Always make any pending restarted system calls return -EINTR */ |
62 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 62 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
63 | 63 | ||
64 | /* | ||
65 | * Enforce that sigcontext is like pt_regs, and doesn't mess | ||
66 | * up our stack alignment rules. | ||
67 | */ | ||
68 | BUILD_BUG_ON(sizeof(struct sigcontext) != sizeof(struct pt_regs)); | ||
69 | BUILD_BUG_ON(sizeof(struct sigcontext) % 8 != 0); | ||
70 | |||
64 | for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) | 71 | for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) |
65 | err |= __get_user(((long *)regs)[i], | 72 | err |= __get_user(regs->regs[i], &sc->gregs[i]); |
66 | &((long __user *)(&sc->regs))[i]); | ||
67 | 73 | ||
68 | regs->faultnum = INT_SWINT_1_SIGRETURN; | 74 | regs->faultnum = INT_SWINT_1_SIGRETURN; |
69 | 75 | ||
70 | err |= __get_user(*pr0, &sc->regs.regs[0]); | 76 | err |= __get_user(*pr0, &sc->gregs[0]); |
71 | return err; | 77 | return err; |
72 | } | 78 | } |
73 | 79 | ||
@@ -112,8 +118,7 @@ int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) | |||
112 | int i, err = 0; | 118 | int i, err = 0; |
113 | 119 | ||
114 | for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) | 120 | for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) |
115 | err |= __put_user(((long *)regs)[i], | 121 | err |= __put_user(regs->regs[i], &sc->gregs[i]); |
116 | &((long __user *)(&sc->regs))[i]); | ||
117 | 122 | ||
118 | return err; | 123 | return err; |
119 | } | 124 | } |
@@ -203,19 +208,17 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
203 | * Set up registers for signal handler. | 208 | * Set up registers for signal handler. |
204 | * Registers that we don't modify keep the value they had from | 209 | * Registers that we don't modify keep the value they had from |
205 | * user-space at the time we took the signal. | 210 | * user-space at the time we took the signal. |
211 | * We always pass siginfo and mcontext, regardless of SA_SIGINFO, | ||
212 | * since some things rely on this (e.g. glibc's debug/segfault.c). | ||
206 | */ | 213 | */ |
207 | regs->pc = (unsigned long) ka->sa.sa_handler; | 214 | regs->pc = (unsigned long) ka->sa.sa_handler; |
208 | regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */ | 215 | regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */ |
209 | regs->sp = (unsigned long) frame; | 216 | regs->sp = (unsigned long) frame; |
210 | regs->lr = restorer; | 217 | regs->lr = restorer; |
211 | regs->regs[0] = (unsigned long) usig; | 218 | regs->regs[0] = (unsigned long) usig; |
212 | 219 | regs->regs[1] = (unsigned long) &frame->info; | |
213 | if (ka->sa.sa_flags & SA_SIGINFO) { | 220 | regs->regs[2] = (unsigned long) &frame->uc; |
214 | /* Need extra arguments, so mark to restore caller-saves. */ | 221 | regs->flags |= PT_FLAGS_CALLER_SAVES; |
215 | regs->regs[1] = (unsigned long) &frame->info; | ||
216 | regs->regs[2] = (unsigned long) &frame->uc; | ||
217 | regs->flags |= PT_FLAGS_CALLER_SAVES; | ||
218 | } | ||
219 | 222 | ||
220 | /* | 223 | /* |
221 | * Notify any tracer that was single-stepping it. | 224 | * Notify any tracer that was single-stepping it. |
diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c index 38a68b0b4581..ea2e0ce28380 100644 --- a/arch/tile/kernel/stack.c +++ b/arch/tile/kernel/stack.c | |||
@@ -175,7 +175,7 @@ static struct pt_regs *valid_sigframe(struct KBacktraceIterator* kbt) | |||
175 | pr_err(" <received signal %d>\n", | 175 | pr_err(" <received signal %d>\n", |
176 | frame->info.si_signo); | 176 | frame->info.si_signo); |
177 | } | 177 | } |
178 | return &frame->uc.uc_mcontext.regs; | 178 | return (struct pt_regs *)&frame->uc.uc_mcontext; |
179 | } | 179 | } |
180 | return NULL; | 180 | return NULL; |
181 | } | 181 | } |
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index b86feabed69b..518bb99c3394 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S | |||
@@ -50,7 +50,12 @@ | |||
50 | /* | 50 | /* |
51 | * Reload arg registers from stack in case ptrace changed them. | 51 | * Reload arg registers from stack in case ptrace changed them. |
52 | * We don't reload %eax because syscall_trace_enter() returned | 52 | * We don't reload %eax because syscall_trace_enter() returned |
53 | * the value it wants us to use in the table lookup. | 53 | * the %rax value we should see. Instead, we just truncate that |
54 | * value to 32 bits again as we did on entry from user mode. | ||
55 | * If it's a new value set by user_regset during entry tracing, | ||
56 | * this matches the normal truncation of the user-mode value. | ||
57 | * If it's -1 to make us punt the syscall, then (u32)-1 is still | ||
58 | * an appropriately invalid value. | ||
54 | */ | 59 | */ |
55 | .macro LOAD_ARGS32 offset, _r9=0 | 60 | .macro LOAD_ARGS32 offset, _r9=0 |
56 | .if \_r9 | 61 | .if \_r9 |
@@ -60,6 +65,7 @@ | |||
60 | movl \offset+48(%rsp),%edx | 65 | movl \offset+48(%rsp),%edx |
61 | movl \offset+56(%rsp),%esi | 66 | movl \offset+56(%rsp),%esi |
62 | movl \offset+64(%rsp),%edi | 67 | movl \offset+64(%rsp),%edi |
68 | movl %eax,%eax /* zero extension */ | ||
63 | .endm | 69 | .endm |
64 | 70 | ||
65 | .macro CFI_STARTPROC32 simple | 71 | .macro CFI_STARTPROC32 simple |
@@ -153,7 +159,7 @@ ENTRY(ia32_sysenter_target) | |||
153 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) | 159 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) |
154 | CFI_REMEMBER_STATE | 160 | CFI_REMEMBER_STATE |
155 | jnz sysenter_tracesys | 161 | jnz sysenter_tracesys |
156 | cmpl $(IA32_NR_syscalls-1),%eax | 162 | cmpq $(IA32_NR_syscalls-1),%rax |
157 | ja ia32_badsys | 163 | ja ia32_badsys |
158 | sysenter_do_call: | 164 | sysenter_do_call: |
159 | IA32_ARG_FIXUP | 165 | IA32_ARG_FIXUP |
@@ -195,7 +201,7 @@ sysexit_from_sys_call: | |||
195 | movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */ | 201 | movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */ |
196 | call audit_syscall_entry | 202 | call audit_syscall_entry |
197 | movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */ | 203 | movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */ |
198 | cmpl $(IA32_NR_syscalls-1),%eax | 204 | cmpq $(IA32_NR_syscalls-1),%rax |
199 | ja ia32_badsys | 205 | ja ia32_badsys |
200 | movl %ebx,%edi /* reload 1st syscall arg */ | 206 | movl %ebx,%edi /* reload 1st syscall arg */ |
201 | movl RCX-ARGOFFSET(%rsp),%esi /* reload 2nd syscall arg */ | 207 | movl RCX-ARGOFFSET(%rsp),%esi /* reload 2nd syscall arg */ |
@@ -248,7 +254,7 @@ sysenter_tracesys: | |||
248 | call syscall_trace_enter | 254 | call syscall_trace_enter |
249 | LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ | 255 | LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ |
250 | RESTORE_REST | 256 | RESTORE_REST |
251 | cmpl $(IA32_NR_syscalls-1),%eax | 257 | cmpq $(IA32_NR_syscalls-1),%rax |
252 | ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */ | 258 | ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */ |
253 | jmp sysenter_do_call | 259 | jmp sysenter_do_call |
254 | CFI_ENDPROC | 260 | CFI_ENDPROC |
@@ -314,7 +320,7 @@ ENTRY(ia32_cstar_target) | |||
314 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) | 320 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) |
315 | CFI_REMEMBER_STATE | 321 | CFI_REMEMBER_STATE |
316 | jnz cstar_tracesys | 322 | jnz cstar_tracesys |
317 | cmpl $IA32_NR_syscalls-1,%eax | 323 | cmpq $IA32_NR_syscalls-1,%rax |
318 | ja ia32_badsys | 324 | ja ia32_badsys |
319 | cstar_do_call: | 325 | cstar_do_call: |
320 | IA32_ARG_FIXUP 1 | 326 | IA32_ARG_FIXUP 1 |
@@ -367,7 +373,7 @@ cstar_tracesys: | |||
367 | LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */ | 373 | LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */ |
368 | RESTORE_REST | 374 | RESTORE_REST |
369 | xchgl %ebp,%r9d | 375 | xchgl %ebp,%r9d |
370 | cmpl $(IA32_NR_syscalls-1),%eax | 376 | cmpq $(IA32_NR_syscalls-1),%rax |
371 | ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */ | 377 | ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */ |
372 | jmp cstar_do_call | 378 | jmp cstar_do_call |
373 | END(ia32_cstar_target) | 379 | END(ia32_cstar_target) |
@@ -425,7 +431,7 @@ ENTRY(ia32_syscall) | |||
425 | orl $TS_COMPAT,TI_status(%r10) | 431 | orl $TS_COMPAT,TI_status(%r10) |
426 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) | 432 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) |
427 | jnz ia32_tracesys | 433 | jnz ia32_tracesys |
428 | cmpl $(IA32_NR_syscalls-1),%eax | 434 | cmpq $(IA32_NR_syscalls-1),%rax |
429 | ja ia32_badsys | 435 | ja ia32_badsys |
430 | ia32_do_call: | 436 | ia32_do_call: |
431 | IA32_ARG_FIXUP | 437 | IA32_ARG_FIXUP |
@@ -444,7 +450,7 @@ ia32_tracesys: | |||
444 | call syscall_trace_enter | 450 | call syscall_trace_enter |
445 | LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ | 451 | LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ |
446 | RESTORE_REST | 452 | RESTORE_REST |
447 | cmpl $(IA32_NR_syscalls-1),%eax | 453 | cmpq $(IA32_NR_syscalls-1),%rax |
448 | ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */ | 454 | ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */ |
449 | jmp ia32_do_call | 455 | jmp ia32_do_call |
450 | END(ia32_syscall) | 456 | END(ia32_syscall) |
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h index 306160e58b48..1d9cd27c2920 100644 --- a/arch/x86/include/asm/compat.h +++ b/arch/x86/include/asm/compat.h | |||
@@ -205,7 +205,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
205 | return (u32)(unsigned long)uptr; | 205 | return (u32)(unsigned long)uptr; |
206 | } | 206 | } |
207 | 207 | ||
208 | static inline void __user *compat_alloc_user_space(long len) | 208 | static inline void __user *arch_compat_alloc_user_space(long len) |
209 | { | 209 | { |
210 | struct pt_regs *regs = task_pt_regs(current); | 210 | struct pt_regs *regs = task_pt_regs(current); |
211 | return (void __user *)regs->sp - len; | 211 | return (void __user *)regs->sp - len; |
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index d2ab01e90a96..dcbeb98f195a 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
@@ -103,8 +103,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, | |||
103 | if (connector->funcs->force) | 103 | if (connector->funcs->force) |
104 | connector->funcs->force(connector); | 104 | connector->funcs->force(connector); |
105 | } else { | 105 | } else { |
106 | connector->status = connector->funcs->detect(connector); | 106 | connector->status = connector->funcs->detect(connector, true); |
107 | drm_helper_hpd_irq_event(dev); | 107 | drm_kms_helper_poll_enable(dev); |
108 | } | 108 | } |
109 | 109 | ||
110 | if (connector->status == connector_status_disconnected) { | 110 | if (connector->status == connector_status_disconnected) { |
@@ -637,13 +637,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
637 | mode_changed = true; | 637 | mode_changed = true; |
638 | 638 | ||
639 | if (mode_changed) { | 639 | if (mode_changed) { |
640 | old_fb = set->crtc->fb; | ||
641 | set->crtc->fb = set->fb; | ||
642 | set->crtc->enabled = (set->mode != NULL); | 640 | set->crtc->enabled = (set->mode != NULL); |
643 | if (set->mode != NULL) { | 641 | if (set->mode != NULL) { |
644 | DRM_DEBUG_KMS("attempting to set mode from" | 642 | DRM_DEBUG_KMS("attempting to set mode from" |
645 | " userspace\n"); | 643 | " userspace\n"); |
646 | drm_mode_debug_printmodeline(set->mode); | 644 | drm_mode_debug_printmodeline(set->mode); |
645 | old_fb = set->crtc->fb; | ||
646 | set->crtc->fb = set->fb; | ||
647 | if (!drm_crtc_helper_set_mode(set->crtc, set->mode, | 647 | if (!drm_crtc_helper_set_mode(set->crtc, set->mode, |
648 | set->x, set->y, | 648 | set->x, set->y, |
649 | old_fb)) { | 649 | old_fb)) { |
@@ -866,7 +866,7 @@ static void output_poll_execute(struct work_struct *work) | |||
866 | !(connector->polled & DRM_CONNECTOR_POLL_HPD)) | 866 | !(connector->polled & DRM_CONNECTOR_POLL_HPD)) |
867 | continue; | 867 | continue; |
868 | 868 | ||
869 | status = connector->funcs->detect(connector); | 869 | status = connector->funcs->detect(connector, false); |
870 | if (old_status != status) | 870 | if (old_status != status) |
871 | changed = true; | 871 | changed = true; |
872 | } | 872 | } |
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index e20f78b542a7..f5bd9e590c80 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c | |||
@@ -164,6 +164,8 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, | |||
164 | dev->hose = pdev->sysdata; | 164 | dev->hose = pdev->sysdata; |
165 | #endif | 165 | #endif |
166 | 166 | ||
167 | mutex_lock(&drm_global_mutex); | ||
168 | |||
167 | if ((ret = drm_fill_in_dev(dev, ent, driver))) { | 169 | if ((ret = drm_fill_in_dev(dev, ent, driver))) { |
168 | printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); | 170 | printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); |
169 | goto err_g2; | 171 | goto err_g2; |
@@ -199,6 +201,7 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, | |||
199 | driver->name, driver->major, driver->minor, driver->patchlevel, | 201 | driver->name, driver->major, driver->minor, driver->patchlevel, |
200 | driver->date, pci_name(pdev), dev->primary->index); | 202 | driver->date, pci_name(pdev), dev->primary->index); |
201 | 203 | ||
204 | mutex_unlock(&drm_global_mutex); | ||
202 | return 0; | 205 | return 0; |
203 | 206 | ||
204 | err_g4: | 207 | err_g4: |
@@ -210,6 +213,7 @@ err_g2: | |||
210 | pci_disable_device(pdev); | 213 | pci_disable_device(pdev); |
211 | err_g1: | 214 | err_g1: |
212 | kfree(dev); | 215 | kfree(dev); |
216 | mutex_unlock(&drm_global_mutex); | ||
213 | return ret; | 217 | return ret; |
214 | } | 218 | } |
215 | EXPORT_SYMBOL(drm_get_pci_dev); | 219 | EXPORT_SYMBOL(drm_get_pci_dev); |
diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c index 460e9a3afa8d..92d1d0fb7b75 100644 --- a/drivers/gpu/drm/drm_platform.c +++ b/drivers/gpu/drm/drm_platform.c | |||
@@ -53,6 +53,8 @@ int drm_get_platform_dev(struct platform_device *platdev, | |||
53 | dev->platformdev = platdev; | 53 | dev->platformdev = platdev; |
54 | dev->dev = &platdev->dev; | 54 | dev->dev = &platdev->dev; |
55 | 55 | ||
56 | mutex_lock(&drm_global_mutex); | ||
57 | |||
56 | ret = drm_fill_in_dev(dev, NULL, driver); | 58 | ret = drm_fill_in_dev(dev, NULL, driver); |
57 | 59 | ||
58 | if (ret) { | 60 | if (ret) { |
@@ -87,6 +89,8 @@ int drm_get_platform_dev(struct platform_device *platdev, | |||
87 | 89 | ||
88 | list_add_tail(&dev->driver_item, &driver->device_list); | 90 | list_add_tail(&dev->driver_item, &driver->device_list); |
89 | 91 | ||
92 | mutex_unlock(&drm_global_mutex); | ||
93 | |||
90 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", | 94 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", |
91 | driver->name, driver->major, driver->minor, driver->patchlevel, | 95 | driver->name, driver->major, driver->minor, driver->patchlevel, |
92 | driver->date, dev->primary->index); | 96 | driver->date, dev->primary->index); |
@@ -100,6 +104,7 @@ err_g2: | |||
100 | drm_put_minor(&dev->control); | 104 | drm_put_minor(&dev->control); |
101 | err_g1: | 105 | err_g1: |
102 | kfree(dev); | 106 | kfree(dev); |
107 | mutex_unlock(&drm_global_mutex); | ||
103 | return ret; | 108 | return ret; |
104 | } | 109 | } |
105 | EXPORT_SYMBOL(drm_get_platform_dev); | 110 | EXPORT_SYMBOL(drm_get_platform_dev); |
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 86118a742231..85da4c40694c 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c | |||
@@ -159,7 +159,7 @@ static ssize_t status_show(struct device *device, | |||
159 | struct drm_connector *connector = to_drm_connector(device); | 159 | struct drm_connector *connector = to_drm_connector(device); |
160 | enum drm_connector_status status; | 160 | enum drm_connector_status status; |
161 | 161 | ||
162 | status = connector->funcs->detect(connector); | 162 | status = connector->funcs->detect(connector, true); |
163 | return snprintf(buf, PAGE_SIZE, "%s\n", | 163 | return snprintf(buf, PAGE_SIZE, "%s\n", |
164 | drm_get_connector_status_name(status)); | 164 | drm_get_connector_status_name(status)); |
165 | } | 165 | } |
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 4b7735196cd5..a02a8df73727 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
@@ -400,7 +400,8 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder | |||
400 | return status; | 400 | return status; |
401 | } | 401 | } |
402 | 402 | ||
403 | static enum drm_connector_status intel_crt_detect(struct drm_connector *connector) | 403 | static enum drm_connector_status |
404 | intel_crt_detect(struct drm_connector *connector, bool force) | ||
404 | { | 405 | { |
405 | struct drm_device *dev = connector->dev; | 406 | struct drm_device *dev = connector->dev; |
406 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 407 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
@@ -419,6 +420,9 @@ static enum drm_connector_status intel_crt_detect(struct drm_connector *connecto | |||
419 | if (intel_crt_detect_ddc(encoder)) | 420 | if (intel_crt_detect_ddc(encoder)) |
420 | return connector_status_connected; | 421 | return connector_status_connected; |
421 | 422 | ||
423 | if (!force) | ||
424 | return connector->status; | ||
425 | |||
422 | /* for pre-945g platforms use load detect */ | 426 | /* for pre-945g platforms use load detect */ |
423 | if (encoder->crtc && encoder->crtc->enabled) { | 427 | if (encoder->crtc && encoder->crtc->enabled) { |
424 | status = intel_crt_load_detect(encoder->crtc, intel_encoder); | 428 | status = intel_crt_load_detect(encoder->crtc, intel_encoder); |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 51d142939a26..1a51ee07de3e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -1386,7 +1386,7 @@ ironlake_dp_detect(struct drm_connector *connector) | |||
1386 | * \return false if DP port is disconnected. | 1386 | * \return false if DP port is disconnected. |
1387 | */ | 1387 | */ |
1388 | static enum drm_connector_status | 1388 | static enum drm_connector_status |
1389 | intel_dp_detect(struct drm_connector *connector) | 1389 | intel_dp_detect(struct drm_connector *connector, bool force) |
1390 | { | 1390 | { |
1391 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1391 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
1392 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); | 1392 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index a399f4b2c1c5..7c9ec1472d46 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c | |||
@@ -221,7 +221,8 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder, | |||
221 | * | 221 | * |
222 | * Unimplemented. | 222 | * Unimplemented. |
223 | */ | 223 | */ |
224 | static enum drm_connector_status intel_dvo_detect(struct drm_connector *connector) | 224 | static enum drm_connector_status |
225 | intel_dvo_detect(struct drm_connector *connector, bool force) | ||
225 | { | 226 | { |
226 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 227 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
227 | struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); | 228 | struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); |
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index ccd4c97e6524..926934a482ec 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
@@ -139,7 +139,7 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, | |||
139 | } | 139 | } |
140 | 140 | ||
141 | static enum drm_connector_status | 141 | static enum drm_connector_status |
142 | intel_hdmi_detect(struct drm_connector *connector) | 142 | intel_hdmi_detect(struct drm_connector *connector, bool force) |
143 | { | 143 | { |
144 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 144 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
145 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | 145 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 4fbb0165b26f..6ec39a86ed06 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
@@ -445,7 +445,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, | |||
445 | * connected and closed means disconnected. We also send hotplug events as | 445 | * connected and closed means disconnected. We also send hotplug events as |
446 | * needed, using lid status notification from the input layer. | 446 | * needed, using lid status notification from the input layer. |
447 | */ | 447 | */ |
448 | static enum drm_connector_status intel_lvds_detect(struct drm_connector *connector) | 448 | static enum drm_connector_status |
449 | intel_lvds_detect(struct drm_connector *connector, bool force) | ||
449 | { | 450 | { |
450 | struct drm_device *dev = connector->dev; | 451 | struct drm_device *dev = connector->dev; |
451 | enum drm_connector_status status = connector_status_connected; | 452 | enum drm_connector_status status = connector_status_connected; |
@@ -540,7 +541,9 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, | |||
540 | * the LID nofication event. | 541 | * the LID nofication event. |
541 | */ | 542 | */ |
542 | if (connector) | 543 | if (connector) |
543 | connector->status = connector->funcs->detect(connector); | 544 | connector->status = connector->funcs->detect(connector, |
545 | false); | ||
546 | |||
544 | /* Don't force modeset on machines where it causes a GPU lockup */ | 547 | /* Don't force modeset on machines where it causes a GPU lockup */ |
545 | if (dmi_check_system(intel_no_modeset_on_lid)) | 548 | if (dmi_check_system(intel_no_modeset_on_lid)) |
546 | return NOTIFY_OK; | 549 | return NOTIFY_OK; |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index e3b7a7ee39cb..e8e902d614ed 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
@@ -1417,7 +1417,7 @@ intel_analog_is_connected(struct drm_device *dev) | |||
1417 | if (!analog_connector) | 1417 | if (!analog_connector) |
1418 | return false; | 1418 | return false; |
1419 | 1419 | ||
1420 | if (analog_connector->funcs->detect(analog_connector) == | 1420 | if (analog_connector->funcs->detect(analog_connector, false) == |
1421 | connector_status_disconnected) | 1421 | connector_status_disconnected) |
1422 | return false; | 1422 | return false; |
1423 | 1423 | ||
@@ -1486,7 +1486,8 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) | |||
1486 | return status; | 1486 | return status; |
1487 | } | 1487 | } |
1488 | 1488 | ||
1489 | static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector) | 1489 | static enum drm_connector_status |
1490 | intel_sdvo_detect(struct drm_connector *connector, bool force) | ||
1490 | { | 1491 | { |
1491 | uint16_t response; | 1492 | uint16_t response; |
1492 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1493 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index c671f60ce80b..4a117e318a73 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c | |||
@@ -1341,7 +1341,7 @@ static void intel_tv_find_better_format(struct drm_connector *connector) | |||
1341 | * we have a pipe programmed in order to probe the TV. | 1341 | * we have a pipe programmed in order to probe the TV. |
1342 | */ | 1342 | */ |
1343 | static enum drm_connector_status | 1343 | static enum drm_connector_status |
1344 | intel_tv_detect(struct drm_connector *connector) | 1344 | intel_tv_detect(struct drm_connector *connector, bool force) |
1345 | { | 1345 | { |
1346 | struct drm_display_mode mode; | 1346 | struct drm_display_mode mode; |
1347 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1347 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
@@ -1353,7 +1353,7 @@ intel_tv_detect(struct drm_connector *connector) | |||
1353 | 1353 | ||
1354 | if (encoder->crtc && encoder->crtc->enabled) { | 1354 | if (encoder->crtc && encoder->crtc->enabled) { |
1355 | type = intel_tv_detect_type(intel_tv); | 1355 | type = intel_tv_detect_type(intel_tv); |
1356 | } else { | 1356 | } else if (force) { |
1357 | struct drm_crtc *crtc; | 1357 | struct drm_crtc *crtc; |
1358 | int dpms_mode; | 1358 | int dpms_mode; |
1359 | 1359 | ||
@@ -1364,10 +1364,9 @@ intel_tv_detect(struct drm_connector *connector) | |||
1364 | intel_release_load_detect_pipe(&intel_tv->base, connector, | 1364 | intel_release_load_detect_pipe(&intel_tv->base, connector, |
1365 | dpms_mode); | 1365 | dpms_mode); |
1366 | } else | 1366 | } else |
1367 | type = -1; | 1367 | return connector_status_unknown; |
1368 | } | 1368 | } else |
1369 | 1369 | return connector->status; | |
1370 | intel_tv->type = type; | ||
1371 | 1370 | ||
1372 | if (type < 0) | 1371 | if (type < 0) |
1373 | return connector_status_disconnected; | 1372 | return connector_status_disconnected; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index a1473fff06ac..87186a4bbf03 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -168,7 +168,7 @@ nouveau_connector_set_encoder(struct drm_connector *connector, | |||
168 | } | 168 | } |
169 | 169 | ||
170 | static enum drm_connector_status | 170 | static enum drm_connector_status |
171 | nouveau_connector_detect(struct drm_connector *connector) | 171 | nouveau_connector_detect(struct drm_connector *connector, bool force) |
172 | { | 172 | { |
173 | struct drm_device *dev = connector->dev; | 173 | struct drm_device *dev = connector->dev; |
174 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 174 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
@@ -246,7 +246,7 @@ detect_analog: | |||
246 | } | 246 | } |
247 | 247 | ||
248 | static enum drm_connector_status | 248 | static enum drm_connector_status |
249 | nouveau_connector_detect_lvds(struct drm_connector *connector) | 249 | nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) |
250 | { | 250 | { |
251 | struct drm_device *dev = connector->dev; | 251 | struct drm_device *dev = connector->dev; |
252 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 252 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
@@ -267,7 +267,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector) | |||
267 | 267 | ||
268 | /* Try retrieving EDID via DDC */ | 268 | /* Try retrieving EDID via DDC */ |
269 | if (!dev_priv->vbios.fp_no_ddc) { | 269 | if (!dev_priv->vbios.fp_no_ddc) { |
270 | status = nouveau_connector_detect(connector); | 270 | status = nouveau_connector_detect(connector, force); |
271 | if (status == connector_status_connected) | 271 | if (status == connector_status_connected) |
272 | goto out; | 272 | goto out; |
273 | } | 273 | } |
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 464a81a1990f..cd0290f946cf 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
@@ -539,14 +539,15 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
539 | pll->algo = PLL_ALGO_LEGACY; | 539 | pll->algo = PLL_ALGO_LEGACY; |
540 | pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; | 540 | pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; |
541 | } | 541 | } |
542 | /* There is some evidence (often anecdotal) that RV515 LVDS | 542 | /* There is some evidence (often anecdotal) that RV515/RV620 LVDS |
543 | * (on some boards at least) prefers the legacy algo. I'm not | 543 | * (on some boards at least) prefers the legacy algo. I'm not |
544 | * sure whether this should handled generically or on a | 544 | * sure whether this should handled generically or on a |
545 | * case-by-case quirk basis. Both algos should work fine in the | 545 | * case-by-case quirk basis. Both algos should work fine in the |
546 | * majority of cases. | 546 | * majority of cases. |
547 | */ | 547 | */ |
548 | if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) && | 548 | if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) && |
549 | (rdev->family == CHIP_RV515)) { | 549 | ((rdev->family == CHIP_RV515) || |
550 | (rdev->family == CHIP_RV620))) { | ||
550 | /* allow the user to overrride just in case */ | 551 | /* allow the user to overrride just in case */ |
551 | if (radeon_new_pll == 1) | 552 | if (radeon_new_pll == 1) |
552 | pll->algo = PLL_ALGO_NEW; | 553 | pll->algo = PLL_ALGO_NEW; |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index b8b7f010b25f..79082d4398ae 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -1160,14 +1160,25 @@ static void evergreen_gpu_init(struct radeon_device *rdev) | |||
1160 | EVERGREEN_MAX_BACKENDS_MASK)); | 1160 | EVERGREEN_MAX_BACKENDS_MASK)); |
1161 | break; | 1161 | break; |
1162 | } | 1162 | } |
1163 | } else | 1163 | } else { |
1164 | gb_backend_map = | 1164 | switch (rdev->family) { |
1165 | evergreen_get_tile_pipe_to_backend_map(rdev, | 1165 | case CHIP_CYPRESS: |
1166 | rdev->config.evergreen.max_tile_pipes, | 1166 | case CHIP_HEMLOCK: |
1167 | rdev->config.evergreen.max_backends, | 1167 | gb_backend_map = 0x66442200; |
1168 | ((EVERGREEN_MAX_BACKENDS_MASK << | 1168 | break; |
1169 | rdev->config.evergreen.max_backends) & | 1169 | case CHIP_JUNIPER: |
1170 | EVERGREEN_MAX_BACKENDS_MASK)); | 1170 | gb_backend_map = 0x00006420; |
1171 | break; | ||
1172 | default: | ||
1173 | gb_backend_map = | ||
1174 | evergreen_get_tile_pipe_to_backend_map(rdev, | ||
1175 | rdev->config.evergreen.max_tile_pipes, | ||
1176 | rdev->config.evergreen.max_backends, | ||
1177 | ((EVERGREEN_MAX_BACKENDS_MASK << | ||
1178 | rdev->config.evergreen.max_backends) & | ||
1179 | EVERGREEN_MAX_BACKENDS_MASK)); | ||
1180 | } | ||
1181 | } | ||
1171 | 1182 | ||
1172 | rdev->config.evergreen.tile_config = gb_addr_config; | 1183 | rdev->config.evergreen.tile_config = gb_addr_config; |
1173 | WREG32(GB_BACKEND_MAP, gb_backend_map); | 1184 | WREG32(GB_BACKEND_MAP, gb_backend_map); |
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index e817a0bb5eb4..e151f16a8f86 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
@@ -2020,18 +2020,7 @@ bool r100_gpu_cp_is_lockup(struct radeon_device *rdev, struct r100_gpu_lockup *l | |||
2020 | return false; | 2020 | return false; |
2021 | } | 2021 | } |
2022 | elapsed = jiffies_to_msecs(cjiffies - lockup->last_jiffies); | 2022 | elapsed = jiffies_to_msecs(cjiffies - lockup->last_jiffies); |
2023 | if (elapsed >= 3000) { | 2023 | if (elapsed >= 10000) { |
2024 | /* very likely the improbable case where current | ||
2025 | * rptr is equal to last recorded, a while ago, rptr | ||
2026 | * this is more likely a false positive update tracking | ||
2027 | * information which should force us to be recall at | ||
2028 | * latter point | ||
2029 | */ | ||
2030 | lockup->last_cp_rptr = cp->rptr; | ||
2031 | lockup->last_jiffies = jiffies; | ||
2032 | return false; | ||
2033 | } | ||
2034 | if (elapsed >= 1000) { | ||
2035 | dev_err(rdev->dev, "GPU lockup CP stall for more than %lumsec\n", elapsed); | 2024 | dev_err(rdev->dev, "GPU lockup CP stall for more than %lumsec\n", elapsed); |
2036 | return true; | 2025 | return true; |
2037 | } | 2026 | } |
@@ -3308,13 +3297,14 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) | |||
3308 | unsigned long size; | 3297 | unsigned long size; |
3309 | unsigned prim_walk; | 3298 | unsigned prim_walk; |
3310 | unsigned nverts; | 3299 | unsigned nverts; |
3300 | unsigned num_cb = track->num_cb; | ||
3311 | 3301 | ||
3312 | for (i = 0; i < track->num_cb; i++) { | 3302 | if (!track->zb_cb_clear && !track->color_channel_mask && |
3303 | !track->blend_read_enable) | ||
3304 | num_cb = 0; | ||
3305 | |||
3306 | for (i = 0; i < num_cb; i++) { | ||
3313 | if (track->cb[i].robj == NULL) { | 3307 | if (track->cb[i].robj == NULL) { |
3314 | if (!(track->zb_cb_clear || track->color_channel_mask || | ||
3315 | track->blend_read_enable)) { | ||
3316 | continue; | ||
3317 | } | ||
3318 | DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); | 3308 | DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); |
3319 | return -EINVAL; | 3309 | return -EINVAL; |
3320 | } | 3310 | } |
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index d13622ae74e9..9ceb2a1ce799 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c | |||
@@ -1,3 +1,28 @@ | |||
1 | /* | ||
2 | * Copyright 2009 Advanced Micro Devices, Inc. | ||
3 | * Copyright 2009 Red Hat Inc. | ||
4 | * | ||
5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | * copy of this software and associated documentation files (the "Software"), | ||
7 | * to deal in the Software without restriction, including without limitation | ||
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
10 | * Software is furnished to do so, subject to the following conditions: | ||
11 | * | ||
12 | * The above copyright notice and this permission notice (including the next | ||
13 | * paragraph) shall be included in all copies or substantial portions of the | ||
14 | * Software. | ||
15 | * | ||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
19 | * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
22 | * DEALINGS IN THE SOFTWARE. | ||
23 | * | ||
24 | */ | ||
25 | |||
1 | #include "drmP.h" | 26 | #include "drmP.h" |
2 | #include "drm.h" | 27 | #include "drm.h" |
3 | #include "radeon_drm.h" | 28 | #include "radeon_drm.h" |
diff --git a/drivers/gpu/drm/radeon/r600_blit_shaders.h b/drivers/gpu/drm/radeon/r600_blit_shaders.h index fdc3b378cbb0..f437d36dd98c 100644 --- a/drivers/gpu/drm/radeon/r600_blit_shaders.h +++ b/drivers/gpu/drm/radeon/r600_blit_shaders.h | |||
@@ -1,3 +1,27 @@ | |||
1 | /* | ||
2 | * Copyright 2009 Advanced Micro Devices, Inc. | ||
3 | * Copyright 2009 Red Hat Inc. | ||
4 | * | ||
5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | * copy of this software and associated documentation files (the "Software"), | ||
7 | * to deal in the Software without restriction, including without limitation | ||
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
10 | * Software is furnished to do so, subject to the following conditions: | ||
11 | * | ||
12 | * The above copyright notice and this permission notice (including the next | ||
13 | * paragraph) shall be included in all copies or substantial portions of the | ||
14 | * Software. | ||
15 | * | ||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
19 | * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
22 | * DEALINGS IN THE SOFTWARE. | ||
23 | * | ||
24 | */ | ||
1 | 25 | ||
2 | #ifndef R600_BLIT_SHADERS_H | 26 | #ifndef R600_BLIT_SHADERS_H |
3 | #define R600_BLIT_SHADERS_H | 27 | #define R600_BLIT_SHADERS_H |
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index d8864949e387..250a3a918193 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c | |||
@@ -1170,9 +1170,8 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i | |||
1170 | /* using get ib will give us the offset into the mipmap bo */ | 1170 | /* using get ib will give us the offset into the mipmap bo */ |
1171 | word0 = radeon_get_ib_value(p, idx + 3) << 8; | 1171 | word0 = radeon_get_ib_value(p, idx + 3) << 8; |
1172 | if ((mipmap_size + word0) > radeon_bo_size(mipmap)) { | 1172 | if ((mipmap_size + word0) > radeon_bo_size(mipmap)) { |
1173 | dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", | 1173 | /*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", |
1174 | w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture)); | 1174 | w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));*/ |
1175 | return -EINVAL; | ||
1176 | } | 1175 | } |
1177 | return 0; | 1176 | return 0; |
1178 | } | 1177 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index bd74e428bd14..a04b7a6ad95f 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c | |||
@@ -1485,6 +1485,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1485 | /* PowerMac8,1 ? */ | 1485 | /* PowerMac8,1 ? */ |
1486 | /* imac g5 isight */ | 1486 | /* imac g5 isight */ |
1487 | rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT; | 1487 | rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT; |
1488 | } else if ((rdev->pdev->device == 0x4a48) && | ||
1489 | (rdev->pdev->subsystem_vendor == 0x1002) && | ||
1490 | (rdev->pdev->subsystem_device == 0x4a48)) { | ||
1491 | /* Mac X800 */ | ||
1492 | rdev->mode_info.connector_table = CT_MAC_X800; | ||
1488 | } else | 1493 | } else |
1489 | #endif /* CONFIG_PPC_PMAC */ | 1494 | #endif /* CONFIG_PPC_PMAC */ |
1490 | #ifdef CONFIG_PPC64 | 1495 | #ifdef CONFIG_PPC64 |
@@ -1961,6 +1966,48 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1961 | CONNECTOR_OBJECT_ID_VGA, | 1966 | CONNECTOR_OBJECT_ID_VGA, |
1962 | &hpd); | 1967 | &hpd); |
1963 | break; | 1968 | break; |
1969 | case CT_MAC_X800: | ||
1970 | DRM_INFO("Connector Table: %d (mac x800)\n", | ||
1971 | rdev->mode_info.connector_table); | ||
1972 | /* DVI - primary dac, internal tmds */ | ||
1973 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); | ||
1974 | hpd.hpd = RADEON_HPD_1; /* ??? */ | ||
1975 | radeon_add_legacy_encoder(dev, | ||
1976 | radeon_get_encoder_enum(dev, | ||
1977 | ATOM_DEVICE_DFP1_SUPPORT, | ||
1978 | 0), | ||
1979 | ATOM_DEVICE_DFP1_SUPPORT); | ||
1980 | radeon_add_legacy_encoder(dev, | ||
1981 | radeon_get_encoder_enum(dev, | ||
1982 | ATOM_DEVICE_CRT1_SUPPORT, | ||
1983 | 1), | ||
1984 | ATOM_DEVICE_CRT1_SUPPORT); | ||
1985 | radeon_add_legacy_connector(dev, 0, | ||
1986 | ATOM_DEVICE_DFP1_SUPPORT | | ||
1987 | ATOM_DEVICE_CRT1_SUPPORT, | ||
1988 | DRM_MODE_CONNECTOR_DVII, &ddc_i2c, | ||
1989 | CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, | ||
1990 | &hpd); | ||
1991 | /* DVI - tv dac, dvo */ | ||
1992 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); | ||
1993 | hpd.hpd = RADEON_HPD_2; /* ??? */ | ||
1994 | radeon_add_legacy_encoder(dev, | ||
1995 | radeon_get_encoder_enum(dev, | ||
1996 | ATOM_DEVICE_DFP2_SUPPORT, | ||
1997 | 0), | ||
1998 | ATOM_DEVICE_DFP2_SUPPORT); | ||
1999 | radeon_add_legacy_encoder(dev, | ||
2000 | radeon_get_encoder_enum(dev, | ||
2001 | ATOM_DEVICE_CRT2_SUPPORT, | ||
2002 | 2), | ||
2003 | ATOM_DEVICE_CRT2_SUPPORT); | ||
2004 | radeon_add_legacy_connector(dev, 1, | ||
2005 | ATOM_DEVICE_DFP2_SUPPORT | | ||
2006 | ATOM_DEVICE_CRT2_SUPPORT, | ||
2007 | DRM_MODE_CONNECTOR_DVII, &ddc_i2c, | ||
2008 | CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I, | ||
2009 | &hpd); | ||
2010 | break; | ||
1964 | default: | 2011 | default: |
1965 | DRM_INFO("Connector table: %d (invalid)\n", | 2012 | DRM_INFO("Connector table: %d (invalid)\n", |
1966 | rdev->mode_info.connector_table); | 2013 | rdev->mode_info.connector_table); |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index a9dd7847d96e..ecc1a8fafbfd 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
@@ -481,7 +481,8 @@ static int radeon_lvds_mode_valid(struct drm_connector *connector, | |||
481 | return MODE_OK; | 481 | return MODE_OK; |
482 | } | 482 | } |
483 | 483 | ||
484 | static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector) | 484 | static enum drm_connector_status |
485 | radeon_lvds_detect(struct drm_connector *connector, bool force) | ||
485 | { | 486 | { |
486 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 487 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
487 | struct drm_encoder *encoder = radeon_best_single_encoder(connector); | 488 | struct drm_encoder *encoder = radeon_best_single_encoder(connector); |
@@ -594,7 +595,8 @@ static int radeon_vga_mode_valid(struct drm_connector *connector, | |||
594 | return MODE_OK; | 595 | return MODE_OK; |
595 | } | 596 | } |
596 | 597 | ||
597 | static enum drm_connector_status radeon_vga_detect(struct drm_connector *connector) | 598 | static enum drm_connector_status |
599 | radeon_vga_detect(struct drm_connector *connector, bool force) | ||
598 | { | 600 | { |
599 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 601 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
600 | struct drm_encoder *encoder; | 602 | struct drm_encoder *encoder; |
@@ -691,7 +693,8 @@ static int radeon_tv_mode_valid(struct drm_connector *connector, | |||
691 | return MODE_OK; | 693 | return MODE_OK; |
692 | } | 694 | } |
693 | 695 | ||
694 | static enum drm_connector_status radeon_tv_detect(struct drm_connector *connector) | 696 | static enum drm_connector_status |
697 | radeon_tv_detect(struct drm_connector *connector, bool force) | ||
695 | { | 698 | { |
696 | struct drm_encoder *encoder; | 699 | struct drm_encoder *encoder; |
697 | struct drm_encoder_helper_funcs *encoder_funcs; | 700 | struct drm_encoder_helper_funcs *encoder_funcs; |
@@ -748,7 +751,8 @@ static int radeon_dvi_get_modes(struct drm_connector *connector) | |||
748 | * we have to check if this analog encoder is shared with anyone else (TV) | 751 | * we have to check if this analog encoder is shared with anyone else (TV) |
749 | * if its shared we have to set the other connector to disconnected. | 752 | * if its shared we have to set the other connector to disconnected. |
750 | */ | 753 | */ |
751 | static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector) | 754 | static enum drm_connector_status |
755 | radeon_dvi_detect(struct drm_connector *connector, bool force) | ||
752 | { | 756 | { |
753 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 757 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
754 | struct drm_encoder *encoder = NULL; | 758 | struct drm_encoder *encoder = NULL; |
@@ -972,7 +976,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector) | |||
972 | return ret; | 976 | return ret; |
973 | } | 977 | } |
974 | 978 | ||
975 | static enum drm_connector_status radeon_dp_detect(struct drm_connector *connector) | 979 | static enum drm_connector_status |
980 | radeon_dp_detect(struct drm_connector *connector, bool force) | ||
976 | { | 981 | { |
977 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 982 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
978 | enum drm_connector_status ret = connector_status_disconnected; | 983 | enum drm_connector_status ret = connector_status_disconnected; |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 6dd434ad2429..127a395f70fb 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -1140,17 +1140,18 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | |||
1140 | radeon_crtc->rmx_type = radeon_encoder->rmx_type; | 1140 | radeon_crtc->rmx_type = radeon_encoder->rmx_type; |
1141 | else | 1141 | else |
1142 | radeon_crtc->rmx_type = RMX_OFF; | 1142 | radeon_crtc->rmx_type = RMX_OFF; |
1143 | src_v = crtc->mode.vdisplay; | ||
1144 | dst_v = radeon_crtc->native_mode.vdisplay; | ||
1145 | src_h = crtc->mode.hdisplay; | ||
1146 | dst_h = radeon_crtc->native_mode.vdisplay; | ||
1147 | /* copy native mode */ | 1143 | /* copy native mode */ |
1148 | memcpy(&radeon_crtc->native_mode, | 1144 | memcpy(&radeon_crtc->native_mode, |
1149 | &radeon_encoder->native_mode, | 1145 | &radeon_encoder->native_mode, |
1150 | sizeof(struct drm_display_mode)); | 1146 | sizeof(struct drm_display_mode)); |
1147 | src_v = crtc->mode.vdisplay; | ||
1148 | dst_v = radeon_crtc->native_mode.vdisplay; | ||
1149 | src_h = crtc->mode.hdisplay; | ||
1150 | dst_h = radeon_crtc->native_mode.hdisplay; | ||
1151 | 1151 | ||
1152 | /* fix up for overscan on hdmi */ | 1152 | /* fix up for overscan on hdmi */ |
1153 | if (ASIC_IS_AVIVO(rdev) && | 1153 | if (ASIC_IS_AVIVO(rdev) && |
1154 | (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) && | ||
1154 | ((radeon_encoder->underscan_type == UNDERSCAN_ON) || | 1155 | ((radeon_encoder->underscan_type == UNDERSCAN_ON) || |
1155 | ((radeon_encoder->underscan_type == UNDERSCAN_AUTO) && | 1156 | ((radeon_encoder->underscan_type == UNDERSCAN_AUTO) && |
1156 | drm_detect_hdmi_monitor(radeon_connector->edid) && | 1157 | drm_detect_hdmi_monitor(radeon_connector->edid) && |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index efbe975312dc..17a6602b5885 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
@@ -204,7 +204,7 @@ struct radeon_i2c_chan { | |||
204 | 204 | ||
205 | /* mostly for macs, but really any system without connector tables */ | 205 | /* mostly for macs, but really any system without connector tables */ |
206 | enum radeon_connector_table { | 206 | enum radeon_connector_table { |
207 | CT_NONE, | 207 | CT_NONE = 0, |
208 | CT_GENERIC, | 208 | CT_GENERIC, |
209 | CT_IBOOK, | 209 | CT_IBOOK, |
210 | CT_POWERBOOK_EXTERNAL, | 210 | CT_POWERBOOK_EXTERNAL, |
@@ -215,6 +215,7 @@ enum radeon_connector_table { | |||
215 | CT_IMAC_G5_ISIGHT, | 215 | CT_IMAC_G5_ISIGHT, |
216 | CT_EMAC, | 216 | CT_EMAC, |
217 | CT_RN50_POWER, | 217 | CT_RN50_POWER, |
218 | CT_MAC_X800, | ||
218 | }; | 219 | }; |
219 | 220 | ||
220 | enum radeon_dvo_chip { | 221 | enum radeon_dvo_chip { |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 2ff5cf78235f..7083b1a24df3 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | |||
@@ -335,7 +335,8 @@ static void vmw_ldu_connector_restore(struct drm_connector *connector) | |||
335 | } | 335 | } |
336 | 336 | ||
337 | static enum drm_connector_status | 337 | static enum drm_connector_status |
338 | vmw_ldu_connector_detect(struct drm_connector *connector) | 338 | vmw_ldu_connector_detect(struct drm_connector *connector, |
339 | bool force) | ||
339 | { | 340 | { |
340 | if (vmw_connector_to_ldu(connector)->pref_active) | 341 | if (vmw_connector_to_ldu(connector)->pref_active) |
341 | return connector_status_connected; | 342 | return connector_status_connected; |
@@ -516,7 +517,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) | |||
516 | 517 | ||
517 | drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, | 518 | drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, |
518 | DRM_MODE_CONNECTOR_LVDS); | 519 | DRM_MODE_CONNECTOR_LVDS); |
519 | connector->status = vmw_ldu_connector_detect(connector); | 520 | connector->status = vmw_ldu_connector_detect(connector, true); |
520 | 521 | ||
521 | drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs, | 522 | drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs, |
522 | DRM_MODE_ENCODER_LVDS); | 523 | DRM_MODE_ENCODER_LVDS); |
@@ -610,7 +611,7 @@ int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num, | |||
610 | ldu->pref_height = 600; | 611 | ldu->pref_height = 600; |
611 | ldu->pref_active = false; | 612 | ldu->pref_active = false; |
612 | } | 613 | } |
613 | con->status = vmw_ldu_connector_detect(con); | 614 | con->status = vmw_ldu_connector_detect(con, true); |
614 | } | 615 | } |
615 | 616 | ||
616 | mutex_unlock(&dev->mode_config.mutex); | 617 | mutex_unlock(&dev->mode_config.mutex); |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 0c52899be964..3f7292486024 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1285,8 +1285,11 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1285 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, | 1285 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, |
1286 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 1286 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
1287 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1287 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
1288 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, | ||
1289 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, | ||
1288 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, | 1290 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, |
1289 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, | 1291 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, |
1292 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, | ||
1290 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, | 1293 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, |
1291 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, | 1294 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, |
1292 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, | 1295 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, |
@@ -1578,7 +1581,6 @@ static const struct hid_device_id hid_ignore_list[] = { | |||
1578 | { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) }, | 1581 | { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) }, |
1579 | { HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) }, | 1582 | { HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) }, |
1580 | { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, | 1583 | { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, |
1581 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT)}, | ||
1582 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM)}, | 1584 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM)}, |
1583 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM2)}, | 1585 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM2)}, |
1584 | { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, | 1586 | { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 85c6d13c9ffa..765a4f53eb5c 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -105,6 +105,7 @@ | |||
105 | 105 | ||
106 | #define USB_VENDOR_ID_ASUS 0x0486 | 106 | #define USB_VENDOR_ID_ASUS 0x0486 |
107 | #define USB_DEVICE_ID_ASUS_T91MT 0x0185 | 107 | #define USB_DEVICE_ID_ASUS_T91MT 0x0185 |
108 | #define USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO 0x0186 | ||
108 | 109 | ||
109 | #define USB_VENDOR_ID_ASUSTEK 0x0b05 | 110 | #define USB_VENDOR_ID_ASUSTEK 0x0b05 |
110 | #define USB_DEVICE_ID_ASUSTEK_LCM 0x1726 | 111 | #define USB_DEVICE_ID_ASUSTEK_LCM 0x1726 |
@@ -128,6 +129,7 @@ | |||
128 | 129 | ||
129 | #define USB_VENDOR_ID_BTC 0x046e | 130 | #define USB_VENDOR_ID_BTC 0x046e |
130 | #define USB_DEVICE_ID_BTC_EMPREX_REMOTE 0x5578 | 131 | #define USB_DEVICE_ID_BTC_EMPREX_REMOTE 0x5578 |
132 | #define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2 0x5577 | ||
131 | 133 | ||
132 | #define USB_VENDOR_ID_CANDO 0x2087 | 134 | #define USB_VENDOR_ID_CANDO 0x2087 |
133 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 | 135 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 |
@@ -149,6 +151,7 @@ | |||
149 | 151 | ||
150 | #define USB_VENDOR_ID_CHICONY 0x04f2 | 152 | #define USB_VENDOR_ID_CHICONY 0x04f2 |
151 | #define USB_DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418 | 153 | #define USB_DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418 |
154 | #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d | ||
152 | 155 | ||
153 | #define USB_VENDOR_ID_CIDC 0x1677 | 156 | #define USB_VENDOR_ID_CIDC 0x1677 |
154 | 157 | ||
@@ -507,6 +510,7 @@ | |||
507 | #define USB_VENDOR_ID_UCLOGIC 0x5543 | 510 | #define USB_VENDOR_ID_UCLOGIC 0x5543 |
508 | #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 | 511 | #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 |
509 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 | 512 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 |
513 | #define USB_DEVICE_ID_UCLOGIC_TABLET_KNA5 0x6001 | ||
510 | 514 | ||
511 | #define USB_VENDOR_ID_VERNIER 0x08f7 | 515 | #define USB_VENDOR_ID_VERNIER 0x08f7 |
512 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 | 516 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 |
diff --git a/drivers/hid/hid-mosart.c b/drivers/hid/hid-mosart.c index e91437c18906..ac5421d568f1 100644 --- a/drivers/hid/hid-mosart.c +++ b/drivers/hid/hid-mosart.c | |||
@@ -239,6 +239,7 @@ static void mosart_remove(struct hid_device *hdev) | |||
239 | 239 | ||
240 | static const struct hid_device_id mosart_devices[] = { | 240 | static const struct hid_device_id mosart_devices[] = { |
241 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, | 241 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, |
242 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, | ||
242 | { } | 243 | { } |
243 | }; | 244 | }; |
244 | MODULE_DEVICE_TABLE(hid, mosart_devices); | 245 | MODULE_DEVICE_TABLE(hid, mosart_devices); |
diff --git a/drivers/hid/hid-topseed.c b/drivers/hid/hid-topseed.c index 5771f851f856..956ed9ac19d4 100644 --- a/drivers/hid/hid-topseed.c +++ b/drivers/hid/hid-topseed.c | |||
@@ -64,6 +64,7 @@ static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
64 | static const struct hid_device_id ts_devices[] = { | 64 | static const struct hid_device_id ts_devices[] = { |
65 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, | 65 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, |
66 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, | 66 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, |
67 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, | ||
67 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, | 68 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, |
68 | { } | 69 | { } |
69 | }; | 70 | }; |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index b729c0286679..599041a7f670 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -828,6 +828,7 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co | |||
828 | } | 828 | } |
829 | } else { | 829 | } else { |
830 | int skipped_report_id = 0; | 830 | int skipped_report_id = 0; |
831 | int report_id = buf[0]; | ||
831 | if (buf[0] == 0x0) { | 832 | if (buf[0] == 0x0) { |
832 | /* Don't send the Report ID */ | 833 | /* Don't send the Report ID */ |
833 | buf++; | 834 | buf++; |
@@ -837,7 +838,7 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co | |||
837 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 838 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
838 | HID_REQ_SET_REPORT, | 839 | HID_REQ_SET_REPORT, |
839 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | 840 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, |
840 | ((report_type + 1) << 8) | *buf, | 841 | ((report_type + 1) << 8) | report_id, |
841 | interface->desc.bInterfaceNumber, buf, count, | 842 | interface->desc.bInterfaceNumber, buf, count, |
842 | USB_CTRL_SET_TIMEOUT); | 843 | USB_CTRL_SET_TIMEOUT); |
843 | /* count also the report id, if this was a numbered report. */ | 844 | /* count also the report id, if this was a numbered report. */ |
@@ -1445,6 +1446,11 @@ static const struct hid_device_id hid_usb_table[] = { | |||
1445 | { } | 1446 | { } |
1446 | }; | 1447 | }; |
1447 | 1448 | ||
1449 | struct usb_interface *usbhid_find_interface(int minor) | ||
1450 | { | ||
1451 | return usb_find_interface(&hid_driver, minor); | ||
1452 | } | ||
1453 | |||
1448 | static struct hid_driver hid_usb_driver = { | 1454 | static struct hid_driver hid_usb_driver = { |
1449 | .name = "generic-usb", | 1455 | .name = "generic-usb", |
1450 | .id_table = hid_usb_table, | 1456 | .id_table = hid_usb_table, |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 2643d3147621..70da3181c8a0 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -33,6 +33,7 @@ static const struct hid_blacklist { | |||
33 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, | 33 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, |
34 | { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, | 34 | { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, |
35 | { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, | 35 | { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, |
36 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, | ||
36 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT }, | 37 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT }, |
37 | { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, | 38 | { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, |
38 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | 39 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
@@ -69,6 +70,7 @@ static const struct hid_blacklist { | |||
69 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, | 70 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, |
70 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, | 71 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, |
71 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, | 72 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, |
73 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT }, | ||
72 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | 74 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, |
73 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | 75 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, |
74 | 76 | ||
@@ -77,6 +79,8 @@ static const struct hid_blacklist { | |||
77 | 79 | ||
78 | { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE }, | 80 | { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE }, |
79 | 81 | ||
82 | { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH, HID_QUIRK_MULTI_INPUT }, | ||
83 | |||
80 | { 0, 0 } | 84 | { 0, 0 } |
81 | }; | 85 | }; |
82 | 86 | ||
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 0a29c51114aa..681e620eb95b 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c | |||
@@ -270,7 +270,7 @@ static int hiddev_open(struct inode *inode, struct file *file) | |||
270 | struct hiddev *hiddev; | 270 | struct hiddev *hiddev; |
271 | int res; | 271 | int res; |
272 | 272 | ||
273 | intf = usb_find_interface(&hiddev_driver, iminor(inode)); | 273 | intf = usbhid_find_interface(iminor(inode)); |
274 | if (!intf) | 274 | if (!intf) |
275 | return -ENODEV; | 275 | return -ENODEV; |
276 | hid = usb_get_intfdata(intf); | 276 | hid = usb_get_intfdata(intf); |
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index 693fd3e720df..89d2e847dcc6 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h | |||
@@ -42,6 +42,7 @@ void usbhid_submit_report | |||
42 | (struct hid_device *hid, struct hid_report *report, unsigned char dir); | 42 | (struct hid_device *hid, struct hid_report *report, unsigned char dir); |
43 | int usbhid_get_power(struct hid_device *hid); | 43 | int usbhid_get_power(struct hid_device *hid); |
44 | void usbhid_put_power(struct hid_device *hid); | 44 | void usbhid_put_power(struct hid_device *hid); |
45 | struct usb_interface *usbhid_find_interface(int minor); | ||
45 | 46 | ||
46 | /* iofl flags */ | 47 | /* iofl flags */ |
47 | #define HID_CTRL_RUNNING 1 | 48 | #define HID_CTRL_RUNNING 1 |
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index a382e3dd0a5d..6fbeefa3a766 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c | |||
@@ -682,7 +682,6 @@ static int __devinit bf5xx_nand_add_partition(struct bf5xx_nand_info *info) | |||
682 | static int __devexit bf5xx_nand_remove(struct platform_device *pdev) | 682 | static int __devexit bf5xx_nand_remove(struct platform_device *pdev) |
683 | { | 683 | { |
684 | struct bf5xx_nand_info *info = to_nand_info(pdev); | 684 | struct bf5xx_nand_info *info = to_nand_info(pdev); |
685 | struct mtd_info *mtd = NULL; | ||
686 | 685 | ||
687 | platform_set_drvdata(pdev, NULL); | 686 | platform_set_drvdata(pdev, NULL); |
688 | 687 | ||
@@ -690,11 +689,7 @@ static int __devexit bf5xx_nand_remove(struct platform_device *pdev) | |||
690 | * and their partitions, then go through freeing the | 689 | * and their partitions, then go through freeing the |
691 | * resources used | 690 | * resources used |
692 | */ | 691 | */ |
693 | mtd = &info->mtd; | 692 | nand_release(&info->mtd); |
694 | if (mtd) { | ||
695 | nand_release(mtd); | ||
696 | kfree(mtd); | ||
697 | } | ||
698 | 693 | ||
699 | peripheral_free_list(bfin_nfc_pin_req); | 694 | peripheral_free_list(bfin_nfc_pin_req); |
700 | bf5xx_nand_dma_remove(info); | 695 | bf5xx_nand_dma_remove(info); |
@@ -710,7 +705,7 @@ static int bf5xx_nand_scan(struct mtd_info *mtd) | |||
710 | struct nand_chip *chip = mtd->priv; | 705 | struct nand_chip *chip = mtd->priv; |
711 | int ret; | 706 | int ret; |
712 | 707 | ||
713 | ret = nand_scan_ident(mtd, 1); | 708 | ret = nand_scan_ident(mtd, 1, NULL); |
714 | if (ret) | 709 | if (ret) |
715 | return ret; | 710 | return ret; |
716 | 711 | ||
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index fcf8ceb277d4..b2828e84d243 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -67,7 +67,9 @@ | |||
67 | #define NFC_V1_V2_CONFIG1_BIG (1 << 5) | 67 | #define NFC_V1_V2_CONFIG1_BIG (1 << 5) |
68 | #define NFC_V1_V2_CONFIG1_RST (1 << 6) | 68 | #define NFC_V1_V2_CONFIG1_RST (1 << 6) |
69 | #define NFC_V1_V2_CONFIG1_CE (1 << 7) | 69 | #define NFC_V1_V2_CONFIG1_CE (1 << 7) |
70 | #define NFC_V1_V2_CONFIG1_ONE_CYCLE (1 << 8) | 70 | #define NFC_V2_CONFIG1_ONE_CYCLE (1 << 8) |
71 | #define NFC_V2_CONFIG1_PPB(x) (((x) & 0x3) << 9) | ||
72 | #define NFC_V2_CONFIG1_FP_INT (1 << 11) | ||
71 | 73 | ||
72 | #define NFC_V1_V2_CONFIG2_INT (1 << 15) | 74 | #define NFC_V1_V2_CONFIG2_INT (1 << 15) |
73 | 75 | ||
@@ -402,16 +404,16 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host) | |||
402 | /* Wait for operation to complete */ | 404 | /* Wait for operation to complete */ |
403 | wait_op_done(host, true); | 405 | wait_op_done(host, true); |
404 | 406 | ||
407 | memcpy(host->data_buf, host->main_area0, 16); | ||
408 | |||
405 | if (this->options & NAND_BUSWIDTH_16) { | 409 | if (this->options & NAND_BUSWIDTH_16) { |
406 | void __iomem *main_buf = host->main_area0; | ||
407 | /* compress the ID info */ | 410 | /* compress the ID info */ |
408 | writeb(readb(main_buf + 2), main_buf + 1); | 411 | host->data_buf[1] = host->data_buf[2]; |
409 | writeb(readb(main_buf + 4), main_buf + 2); | 412 | host->data_buf[2] = host->data_buf[4]; |
410 | writeb(readb(main_buf + 6), main_buf + 3); | 413 | host->data_buf[3] = host->data_buf[6]; |
411 | writeb(readb(main_buf + 8), main_buf + 4); | 414 | host->data_buf[4] = host->data_buf[8]; |
412 | writeb(readb(main_buf + 10), main_buf + 5); | 415 | host->data_buf[5] = host->data_buf[10]; |
413 | } | 416 | } |
414 | memcpy(host->data_buf, host->main_area0, 16); | ||
415 | } | 417 | } |
416 | 418 | ||
417 | static uint16_t get_dev_status_v3(struct mxc_nand_host *host) | 419 | static uint16_t get_dev_status_v3(struct mxc_nand_host *host) |
@@ -729,27 +731,30 @@ static void preset_v1_v2(struct mtd_info *mtd) | |||
729 | { | 731 | { |
730 | struct nand_chip *nand_chip = mtd->priv; | 732 | struct nand_chip *nand_chip = mtd->priv; |
731 | struct mxc_nand_host *host = nand_chip->priv; | 733 | struct mxc_nand_host *host = nand_chip->priv; |
732 | uint16_t tmp; | 734 | uint16_t config1 = 0; |
733 | 735 | ||
734 | /* enable interrupt, disable spare enable */ | 736 | if (nand_chip->ecc.mode == NAND_ECC_HW) |
735 | tmp = readw(NFC_V1_V2_CONFIG1); | 737 | config1 |= NFC_V1_V2_CONFIG1_ECC_EN; |
736 | tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK; | 738 | |
737 | tmp &= ~NFC_V1_V2_CONFIG1_SP_EN; | 739 | if (nfc_is_v21()) |
738 | if (nand_chip->ecc.mode == NAND_ECC_HW) { | 740 | config1 |= NFC_V2_CONFIG1_FP_INT; |
739 | tmp |= NFC_V1_V2_CONFIG1_ECC_EN; | 741 | |
740 | } else { | 742 | if (!cpu_is_mx21()) |
741 | tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN; | 743 | config1 |= NFC_V1_V2_CONFIG1_INT_MSK; |
742 | } | ||
743 | 744 | ||
744 | if (nfc_is_v21() && mtd->writesize) { | 745 | if (nfc_is_v21() && mtd->writesize) { |
746 | uint16_t pages_per_block = mtd->erasesize / mtd->writesize; | ||
747 | |||
745 | host->eccsize = get_eccsize(mtd); | 748 | host->eccsize = get_eccsize(mtd); |
746 | if (host->eccsize == 4) | 749 | if (host->eccsize == 4) |
747 | tmp |= NFC_V2_CONFIG1_ECC_MODE_4; | 750 | config1 |= NFC_V2_CONFIG1_ECC_MODE_4; |
751 | |||
752 | config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6); | ||
748 | } else { | 753 | } else { |
749 | host->eccsize = 1; | 754 | host->eccsize = 1; |
750 | } | 755 | } |
751 | 756 | ||
752 | writew(tmp, NFC_V1_V2_CONFIG1); | 757 | writew(config1, NFC_V1_V2_CONFIG1); |
753 | /* preset operation */ | 758 | /* preset operation */ |
754 | 759 | ||
755 | /* Unlock the internal RAM Buffer */ | 760 | /* Unlock the internal RAM Buffer */ |
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 4d89f3780207..4d01cda68844 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
@@ -1320,6 +1320,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
1320 | goto fail_free_irq; | 1320 | goto fail_free_irq; |
1321 | } | 1321 | } |
1322 | 1322 | ||
1323 | #ifdef CONFIG_MTD_PARTITIONS | ||
1323 | if (mtd_has_cmdlinepart()) { | 1324 | if (mtd_has_cmdlinepart()) { |
1324 | static const char *probes[] = { "cmdlinepart", NULL }; | 1325 | static const char *probes[] = { "cmdlinepart", NULL }; |
1325 | struct mtd_partition *parts; | 1326 | struct mtd_partition *parts; |
@@ -1332,6 +1333,9 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
1332 | } | 1333 | } |
1333 | 1334 | ||
1334 | return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); | 1335 | return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); |
1336 | #else | ||
1337 | return 0; | ||
1338 | #endif | ||
1335 | 1339 | ||
1336 | fail_free_irq: | 1340 | fail_free_irq: |
1337 | free_irq(irq, info); | 1341 | free_irq(irq, info); |
@@ -1364,7 +1368,9 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) | |||
1364 | platform_set_drvdata(pdev, NULL); | 1368 | platform_set_drvdata(pdev, NULL); |
1365 | 1369 | ||
1366 | del_mtd_device(mtd); | 1370 | del_mtd_device(mtd); |
1371 | #ifdef CONFIG_MTD_PARTITIONS | ||
1367 | del_mtd_partitions(mtd); | 1372 | del_mtd_partitions(mtd); |
1373 | #endif | ||
1368 | irq = platform_get_irq(pdev, 0); | 1374 | irq = platform_get_irq(pdev, 0); |
1369 | if (irq >= 0) | 1375 | if (irq >= 0) |
1370 | free_irq(irq, info); | 1376 | free_irq(irq, info); |
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index cb443af3d45f..a460f1b748c2 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c | |||
@@ -554,14 +554,13 @@ static int s5pc110_dma_ops(void *dst, void *src, size_t count, int direction) | |||
554 | 554 | ||
555 | do { | 555 | do { |
556 | status = readl(base + S5PC110_DMA_TRANS_STATUS); | 556 | status = readl(base + S5PC110_DMA_TRANS_STATUS); |
557 | if (status & S5PC110_DMA_TRANS_STATUS_TE) { | ||
558 | writel(S5PC110_DMA_TRANS_CMD_TEC, | ||
559 | base + S5PC110_DMA_TRANS_CMD); | ||
560 | return -EIO; | ||
561 | } | ||
557 | } while (!(status & S5PC110_DMA_TRANS_STATUS_TD)); | 562 | } while (!(status & S5PC110_DMA_TRANS_STATUS_TD)); |
558 | 563 | ||
559 | if (status & S5PC110_DMA_TRANS_STATUS_TE) { | ||
560 | writel(S5PC110_DMA_TRANS_CMD_TEC, base + S5PC110_DMA_TRANS_CMD); | ||
561 | writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD); | ||
562 | return -EIO; | ||
563 | } | ||
564 | |||
565 | writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD); | 564 | writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD); |
566 | 565 | ||
567 | return 0; | 566 | return 0; |
@@ -571,13 +570,12 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, | |||
571 | unsigned char *buffer, int offset, size_t count) | 570 | unsigned char *buffer, int offset, size_t count) |
572 | { | 571 | { |
573 | struct onenand_chip *this = mtd->priv; | 572 | struct onenand_chip *this = mtd->priv; |
574 | void __iomem *bufferram; | ||
575 | void __iomem *p; | 573 | void __iomem *p; |
576 | void *buf = (void *) buffer; | 574 | void *buf = (void *) buffer; |
577 | dma_addr_t dma_src, dma_dst; | 575 | dma_addr_t dma_src, dma_dst; |
578 | int err; | 576 | int err; |
579 | 577 | ||
580 | p = bufferram = this->base + area; | 578 | p = this->base + area; |
581 | if (ONENAND_CURRENT_BUFFERRAM(this)) { | 579 | if (ONENAND_CURRENT_BUFFERRAM(this)) { |
582 | if (area == ONENAND_DATARAM) | 580 | if (area == ONENAND_DATARAM) |
583 | p += this->writesize; | 581 | p += this->writesize; |
@@ -621,7 +619,7 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, | |||
621 | normal: | 619 | normal: |
622 | if (count != mtd->writesize) { | 620 | if (count != mtd->writesize) { |
623 | /* Copy the bufferram to memory to prevent unaligned access */ | 621 | /* Copy the bufferram to memory to prevent unaligned access */ |
624 | memcpy(this->page_buf, bufferram, mtd->writesize); | 622 | memcpy(this->page_buf, p, mtd->writesize); |
625 | p = this->page_buf + offset; | 623 | p = this->page_buf + offset; |
626 | } | 624 | } |
627 | 625 | ||
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 49279b0ee526..f9b509a6b09a 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c | |||
@@ -508,7 +508,8 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev, | |||
508 | unsigned int vcc, | 508 | unsigned int vcc, |
509 | void *priv_data) | 509 | void *priv_data) |
510 | { | 510 | { |
511 | int *has_shmem = priv_data; | 511 | int *priv = priv_data; |
512 | int try = (*priv & 0x1); | ||
512 | int i; | 513 | int i; |
513 | cistpl_io_t *io = &cfg->io; | 514 | cistpl_io_t *io = &cfg->io; |
514 | 515 | ||
@@ -525,77 +526,103 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev, | |||
525 | i = p_dev->resource[1]->end = 0; | 526 | i = p_dev->resource[1]->end = 0; |
526 | } | 527 | } |
527 | 528 | ||
528 | *has_shmem = ((cfg->mem.nwin == 1) && | 529 | *priv &= ((cfg->mem.nwin == 1) && |
529 | (cfg->mem.win[0].len >= 0x4000)); | 530 | (cfg->mem.win[0].len >= 0x4000)) ? 0x10 : ~0x10; |
531 | |||
530 | p_dev->resource[0]->start = io->win[i].base; | 532 | p_dev->resource[0]->start = io->win[i].base; |
531 | p_dev->resource[0]->end = io->win[i].len; | 533 | p_dev->resource[0]->end = io->win[i].len; |
532 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | 534 | if (!try) |
535 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | ||
536 | else | ||
537 | p_dev->io_lines = 16; | ||
533 | if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32) | 538 | if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32) |
534 | return try_io_port(p_dev); | 539 | return try_io_port(p_dev); |
535 | 540 | ||
536 | return 0; | 541 | return -EINVAL; |
542 | } | ||
543 | |||
544 | static hw_info_t *pcnet_try_config(struct pcmcia_device *link, | ||
545 | int *has_shmem, int try) | ||
546 | { | ||
547 | struct net_device *dev = link->priv; | ||
548 | hw_info_t *local_hw_info; | ||
549 | pcnet_dev_t *info = PRIV(dev); | ||
550 | int priv = try; | ||
551 | int ret; | ||
552 | |||
553 | ret = pcmcia_loop_config(link, pcnet_confcheck, &priv); | ||
554 | if (ret) { | ||
555 | dev_warn(&link->dev, "no useable port range found\n"); | ||
556 | return NULL; | ||
557 | } | ||
558 | *has_shmem = (priv & 0x10); | ||
559 | |||
560 | if (!link->irq) | ||
561 | return NULL; | ||
562 | |||
563 | if (resource_size(link->resource[1]) == 8) { | ||
564 | link->conf.Attributes |= CONF_ENABLE_SPKR; | ||
565 | link->conf.Status = CCSR_AUDIO_ENA; | ||
566 | } | ||
567 | if ((link->manf_id == MANFID_IBM) && | ||
568 | (link->card_id == PRODID_IBM_HOME_AND_AWAY)) | ||
569 | link->conf.ConfigIndex |= 0x10; | ||
570 | |||
571 | ret = pcmcia_request_configuration(link, &link->conf); | ||
572 | if (ret) | ||
573 | return NULL; | ||
574 | |||
575 | dev->irq = link->irq; | ||
576 | dev->base_addr = link->resource[0]->start; | ||
577 | |||
578 | if (info->flags & HAS_MISC_REG) { | ||
579 | if ((if_port == 1) || (if_port == 2)) | ||
580 | dev->if_port = if_port; | ||
581 | else | ||
582 | dev_notice(&link->dev, "invalid if_port requested\n"); | ||
583 | } else | ||
584 | dev->if_port = 0; | ||
585 | |||
586 | if ((link->conf.ConfigBase == 0x03c0) && | ||
587 | (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) { | ||
588 | dev_info(&link->dev, | ||
589 | "this is an AX88190 card - use axnet_cs instead.\n"); | ||
590 | return NULL; | ||
591 | } | ||
592 | |||
593 | local_hw_info = get_hwinfo(link); | ||
594 | if (!local_hw_info) | ||
595 | local_hw_info = get_prom(link); | ||
596 | if (!local_hw_info) | ||
597 | local_hw_info = get_dl10019(link); | ||
598 | if (!local_hw_info) | ||
599 | local_hw_info = get_ax88190(link); | ||
600 | if (!local_hw_info) | ||
601 | local_hw_info = get_hwired(link); | ||
602 | |||
603 | return local_hw_info; | ||
537 | } | 604 | } |
538 | 605 | ||
539 | static int pcnet_config(struct pcmcia_device *link) | 606 | static int pcnet_config(struct pcmcia_device *link) |
540 | { | 607 | { |
541 | struct net_device *dev = link->priv; | 608 | struct net_device *dev = link->priv; |
542 | pcnet_dev_t *info = PRIV(dev); | 609 | pcnet_dev_t *info = PRIV(dev); |
543 | int ret, start_pg, stop_pg, cm_offset; | 610 | int start_pg, stop_pg, cm_offset; |
544 | int has_shmem = 0; | 611 | int has_shmem = 0; |
545 | hw_info_t *local_hw_info; | 612 | hw_info_t *local_hw_info; |
546 | 613 | ||
547 | dev_dbg(&link->dev, "pcnet_config\n"); | 614 | dev_dbg(&link->dev, "pcnet_config\n"); |
548 | 615 | ||
549 | ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem); | 616 | local_hw_info = pcnet_try_config(link, &has_shmem, 0); |
550 | if (ret) | 617 | if (!local_hw_info) { |
551 | goto failed; | 618 | /* check whether forcing io_lines to 16 helps... */ |
552 | 619 | pcmcia_disable_device(link); | |
553 | if (!link->irq) | 620 | local_hw_info = pcnet_try_config(link, &has_shmem, 1); |
554 | goto failed; | 621 | if (local_hw_info == NULL) { |
555 | 622 | dev_notice(&link->dev, "unable to read hardware net" | |
556 | if (resource_size(link->resource[1]) == 8) { | 623 | " address for io base %#3lx\n", dev->base_addr); |
557 | link->conf.Attributes |= CONF_ENABLE_SPKR; | 624 | goto failed; |
558 | link->conf.Status = CCSR_AUDIO_ENA; | 625 | } |
559 | } | ||
560 | if ((link->manf_id == MANFID_IBM) && | ||
561 | (link->card_id == PRODID_IBM_HOME_AND_AWAY)) | ||
562 | link->conf.ConfigIndex |= 0x10; | ||
563 | |||
564 | ret = pcmcia_request_configuration(link, &link->conf); | ||
565 | if (ret) | ||
566 | goto failed; | ||
567 | dev->irq = link->irq; | ||
568 | dev->base_addr = link->resource[0]->start; | ||
569 | if (info->flags & HAS_MISC_REG) { | ||
570 | if ((if_port == 1) || (if_port == 2)) | ||
571 | dev->if_port = if_port; | ||
572 | else | ||
573 | printk(KERN_NOTICE "pcnet_cs: invalid if_port requested\n"); | ||
574 | } else { | ||
575 | dev->if_port = 0; | ||
576 | } | ||
577 | |||
578 | if ((link->conf.ConfigBase == 0x03c0) && | ||
579 | (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) { | ||
580 | printk(KERN_INFO "pcnet_cs: this is an AX88190 card!\n"); | ||
581 | printk(KERN_INFO "pcnet_cs: use axnet_cs instead.\n"); | ||
582 | goto failed; | ||
583 | } | ||
584 | |||
585 | local_hw_info = get_hwinfo(link); | ||
586 | if (local_hw_info == NULL) | ||
587 | local_hw_info = get_prom(link); | ||
588 | if (local_hw_info == NULL) | ||
589 | local_hw_info = get_dl10019(link); | ||
590 | if (local_hw_info == NULL) | ||
591 | local_hw_info = get_ax88190(link); | ||
592 | if (local_hw_info == NULL) | ||
593 | local_hw_info = get_hwired(link); | ||
594 | |||
595 | if (local_hw_info == NULL) { | ||
596 | printk(KERN_NOTICE "pcnet_cs: unable to read hardware net" | ||
597 | " address for io base %#3lx\n", dev->base_addr); | ||
598 | goto failed; | ||
599 | } | 626 | } |
600 | 627 | ||
601 | info->flags = local_hw_info->flags; | 628 | info->flags = local_hw_info->flags; |
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 54aa1c238cb3..a5c176598d95 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c | |||
@@ -163,7 +163,7 @@ static int pcmcia_access_config(struct pcmcia_device *p_dev, | |||
163 | c = p_dev->function_config; | 163 | c = p_dev->function_config; |
164 | 164 | ||
165 | if (!(c->state & CONFIG_LOCKED)) { | 165 | if (!(c->state & CONFIG_LOCKED)) { |
166 | dev_dbg(&s->dev, "Configuration isnt't locked\n"); | 166 | dev_dbg(&p_dev->dev, "Configuration isnt't locked\n"); |
167 | mutex_unlock(&s->ops_mutex); | 167 | mutex_unlock(&s->ops_mutex); |
168 | return -EACCES; | 168 | return -EACCES; |
169 | } | 169 | } |
@@ -220,7 +220,7 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh, | |||
220 | s->win[w].card_start = offset; | 220 | s->win[w].card_start = offset; |
221 | ret = s->ops->set_mem_map(s, &s->win[w]); | 221 | ret = s->ops->set_mem_map(s, &s->win[w]); |
222 | if (ret) | 222 | if (ret) |
223 | dev_warn(&s->dev, "failed to set_mem_map\n"); | 223 | dev_warn(&p_dev->dev, "failed to set_mem_map\n"); |
224 | mutex_unlock(&s->ops_mutex); | 224 | mutex_unlock(&s->ops_mutex); |
225 | return ret; | 225 | return ret; |
226 | } /* pcmcia_map_mem_page */ | 226 | } /* pcmcia_map_mem_page */ |
@@ -244,18 +244,18 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
244 | c = p_dev->function_config; | 244 | c = p_dev->function_config; |
245 | 245 | ||
246 | if (!(s->state & SOCKET_PRESENT)) { | 246 | if (!(s->state & SOCKET_PRESENT)) { |
247 | dev_dbg(&s->dev, "No card present\n"); | 247 | dev_dbg(&p_dev->dev, "No card present\n"); |
248 | ret = -ENODEV; | 248 | ret = -ENODEV; |
249 | goto unlock; | 249 | goto unlock; |
250 | } | 250 | } |
251 | if (!(c->state & CONFIG_LOCKED)) { | 251 | if (!(c->state & CONFIG_LOCKED)) { |
252 | dev_dbg(&s->dev, "Configuration isnt't locked\n"); | 252 | dev_dbg(&p_dev->dev, "Configuration isnt't locked\n"); |
253 | ret = -EACCES; | 253 | ret = -EACCES; |
254 | goto unlock; | 254 | goto unlock; |
255 | } | 255 | } |
256 | 256 | ||
257 | if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) { | 257 | if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) { |
258 | dev_dbg(&s->dev, | 258 | dev_dbg(&p_dev->dev, |
259 | "changing Vcc or IRQ is not allowed at this time\n"); | 259 | "changing Vcc or IRQ is not allowed at this time\n"); |
260 | ret = -EINVAL; | 260 | ret = -EINVAL; |
261 | goto unlock; | 261 | goto unlock; |
@@ -265,20 +265,22 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
265 | if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && | 265 | if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && |
266 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | 266 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { |
267 | if (mod->Vpp1 != mod->Vpp2) { | 267 | if (mod->Vpp1 != mod->Vpp2) { |
268 | dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n"); | 268 | dev_dbg(&p_dev->dev, |
269 | "Vpp1 and Vpp2 must be the same\n"); | ||
269 | ret = -EINVAL; | 270 | ret = -EINVAL; |
270 | goto unlock; | 271 | goto unlock; |
271 | } | 272 | } |
272 | s->socket.Vpp = mod->Vpp1; | 273 | s->socket.Vpp = mod->Vpp1; |
273 | if (s->ops->set_socket(s, &s->socket)) { | 274 | if (s->ops->set_socket(s, &s->socket)) { |
274 | dev_printk(KERN_WARNING, &s->dev, | 275 | dev_printk(KERN_WARNING, &p_dev->dev, |
275 | "Unable to set VPP\n"); | 276 | "Unable to set VPP\n"); |
276 | ret = -EIO; | 277 | ret = -EIO; |
277 | goto unlock; | 278 | goto unlock; |
278 | } | 279 | } |
279 | } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || | 280 | } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || |
280 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | 281 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { |
281 | dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n"); | 282 | dev_dbg(&p_dev->dev, |
283 | "changing Vcc is not allowed at this time\n"); | ||
282 | ret = -EINVAL; | 284 | ret = -EINVAL; |
283 | goto unlock; | 285 | goto unlock; |
284 | } | 286 | } |
@@ -401,7 +403,7 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res) | |||
401 | win = &s->win[w]; | 403 | win = &s->win[w]; |
402 | 404 | ||
403 | if (!(p_dev->_win & CLIENT_WIN_REQ(w))) { | 405 | if (!(p_dev->_win & CLIENT_WIN_REQ(w))) { |
404 | dev_dbg(&s->dev, "not releasing unknown window\n"); | 406 | dev_dbg(&p_dev->dev, "not releasing unknown window\n"); |
405 | mutex_unlock(&s->ops_mutex); | 407 | mutex_unlock(&s->ops_mutex); |
406 | return -EINVAL; | 408 | return -EINVAL; |
407 | } | 409 | } |
@@ -439,7 +441,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
439 | return -ENODEV; | 441 | return -ENODEV; |
440 | 442 | ||
441 | if (req->IntType & INT_CARDBUS) { | 443 | if (req->IntType & INT_CARDBUS) { |
442 | dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n"); | 444 | dev_dbg(&p_dev->dev, "IntType may not be INT_CARDBUS\n"); |
443 | return -EINVAL; | 445 | return -EINVAL; |
444 | } | 446 | } |
445 | 447 | ||
@@ -447,7 +449,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
447 | c = p_dev->function_config; | 449 | c = p_dev->function_config; |
448 | if (c->state & CONFIG_LOCKED) { | 450 | if (c->state & CONFIG_LOCKED) { |
449 | mutex_unlock(&s->ops_mutex); | 451 | mutex_unlock(&s->ops_mutex); |
450 | dev_dbg(&s->dev, "Configuration is locked\n"); | 452 | dev_dbg(&p_dev->dev, "Configuration is locked\n"); |
451 | return -EACCES; | 453 | return -EACCES; |
452 | } | 454 | } |
453 | 455 | ||
@@ -455,7 +457,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
455 | s->socket.Vpp = req->Vpp; | 457 | s->socket.Vpp = req->Vpp; |
456 | if (s->ops->set_socket(s, &s->socket)) { | 458 | if (s->ops->set_socket(s, &s->socket)) { |
457 | mutex_unlock(&s->ops_mutex); | 459 | mutex_unlock(&s->ops_mutex); |
458 | dev_printk(KERN_WARNING, &s->dev, | 460 | dev_printk(KERN_WARNING, &p_dev->dev, |
459 | "Unable to set socket state\n"); | 461 | "Unable to set socket state\n"); |
460 | return -EINVAL; | 462 | return -EINVAL; |
461 | } | 463 | } |
@@ -569,19 +571,20 @@ int pcmcia_request_io(struct pcmcia_device *p_dev) | |||
569 | int ret = -EINVAL; | 571 | int ret = -EINVAL; |
570 | 572 | ||
571 | mutex_lock(&s->ops_mutex); | 573 | mutex_lock(&s->ops_mutex); |
572 | dev_dbg(&s->dev, "pcmcia_request_io: %pR , %pR", &c->io[0], &c->io[1]); | 574 | dev_dbg(&p_dev->dev, "pcmcia_request_io: %pR , %pR", |
575 | &c->io[0], &c->io[1]); | ||
573 | 576 | ||
574 | if (!(s->state & SOCKET_PRESENT)) { | 577 | if (!(s->state & SOCKET_PRESENT)) { |
575 | dev_dbg(&s->dev, "pcmcia_request_io: No card present\n"); | 578 | dev_dbg(&p_dev->dev, "pcmcia_request_io: No card present\n"); |
576 | goto out; | 579 | goto out; |
577 | } | 580 | } |
578 | 581 | ||
579 | if (c->state & CONFIG_LOCKED) { | 582 | if (c->state & CONFIG_LOCKED) { |
580 | dev_dbg(&s->dev, "Configuration is locked\n"); | 583 | dev_dbg(&p_dev->dev, "Configuration is locked\n"); |
581 | goto out; | 584 | goto out; |
582 | } | 585 | } |
583 | if (c->state & CONFIG_IO_REQ) { | 586 | if (c->state & CONFIG_IO_REQ) { |
584 | dev_dbg(&s->dev, "IO already configured\n"); | 587 | dev_dbg(&p_dev->dev, "IO already configured\n"); |
585 | goto out; | 588 | goto out; |
586 | } | 589 | } |
587 | 590 | ||
@@ -601,7 +604,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev) | |||
601 | c->state |= CONFIG_IO_REQ; | 604 | c->state |= CONFIG_IO_REQ; |
602 | p_dev->_io = 1; | 605 | p_dev->_io = 1; |
603 | 606 | ||
604 | dev_dbg(&s->dev, "pcmcia_request_io succeeded: %pR , %pR", | 607 | dev_dbg(&p_dev->dev, "pcmcia_request_io succeeded: %pR , %pR", |
605 | &c->io[0], &c->io[1]); | 608 | &c->io[0], &c->io[1]); |
606 | out: | 609 | out: |
607 | mutex_unlock(&s->ops_mutex); | 610 | mutex_unlock(&s->ops_mutex); |
@@ -800,7 +803,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
800 | int w; | 803 | int w; |
801 | 804 | ||
802 | if (!(s->state & SOCKET_PRESENT)) { | 805 | if (!(s->state & SOCKET_PRESENT)) { |
803 | dev_dbg(&s->dev, "No card present\n"); | 806 | dev_dbg(&p_dev->dev, "No card present\n"); |
804 | return -ENODEV; | 807 | return -ENODEV; |
805 | } | 808 | } |
806 | 809 | ||
@@ -809,12 +812,12 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
809 | req->Size = s->map_size; | 812 | req->Size = s->map_size; |
810 | align = (s->features & SS_CAP_MEM_ALIGN) ? req->Size : s->map_size; | 813 | align = (s->features & SS_CAP_MEM_ALIGN) ? req->Size : s->map_size; |
811 | if (req->Size & (s->map_size-1)) { | 814 | if (req->Size & (s->map_size-1)) { |
812 | dev_dbg(&s->dev, "invalid map size\n"); | 815 | dev_dbg(&p_dev->dev, "invalid map size\n"); |
813 | return -EINVAL; | 816 | return -EINVAL; |
814 | } | 817 | } |
815 | if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) || | 818 | if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) || |
816 | (req->Base & (align-1))) { | 819 | (req->Base & (align-1))) { |
817 | dev_dbg(&s->dev, "invalid base address\n"); | 820 | dev_dbg(&p_dev->dev, "invalid base address\n"); |
818 | return -EINVAL; | 821 | return -EINVAL; |
819 | } | 822 | } |
820 | if (req->Base) | 823 | if (req->Base) |
@@ -826,7 +829,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
826 | if (!(s->state & SOCKET_WIN_REQ(w))) | 829 | if (!(s->state & SOCKET_WIN_REQ(w))) |
827 | break; | 830 | break; |
828 | if (w == MAX_WIN) { | 831 | if (w == MAX_WIN) { |
829 | dev_dbg(&s->dev, "all windows are used already\n"); | 832 | dev_dbg(&p_dev->dev, "all windows are used already\n"); |
830 | mutex_unlock(&s->ops_mutex); | 833 | mutex_unlock(&s->ops_mutex); |
831 | return -EINVAL; | 834 | return -EINVAL; |
832 | } | 835 | } |
@@ -837,7 +840,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
837 | win->res = pcmcia_find_mem_region(req->Base, req->Size, align, | 840 | win->res = pcmcia_find_mem_region(req->Base, req->Size, align, |
838 | 0, s); | 841 | 0, s); |
839 | if (!win->res) { | 842 | if (!win->res) { |
840 | dev_dbg(&s->dev, "allocating mem region failed\n"); | 843 | dev_dbg(&p_dev->dev, "allocating mem region failed\n"); |
841 | mutex_unlock(&s->ops_mutex); | 844 | mutex_unlock(&s->ops_mutex); |
842 | return -EINVAL; | 845 | return -EINVAL; |
843 | } | 846 | } |
@@ -851,7 +854,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
851 | win->card_start = 0; | 854 | win->card_start = 0; |
852 | 855 | ||
853 | if (s->ops->set_mem_map(s, win) != 0) { | 856 | if (s->ops->set_mem_map(s, win) != 0) { |
854 | dev_dbg(&s->dev, "failed to set memory mapping\n"); | 857 | dev_dbg(&p_dev->dev, "failed to set memory mapping\n"); |
855 | mutex_unlock(&s->ops_mutex); | 858 | mutex_unlock(&s->ops_mutex); |
856 | return -EIO; | 859 | return -EIO; |
857 | } | 860 | } |
@@ -874,7 +877,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
874 | if (win->res) | 877 | if (win->res) |
875 | request_resource(&iomem_resource, res); | 878 | request_resource(&iomem_resource, res); |
876 | 879 | ||
877 | dev_dbg(&s->dev, "request_window results in %pR\n", res); | 880 | dev_dbg(&p_dev->dev, "request_window results in %pR\n", res); |
878 | 881 | ||
879 | mutex_unlock(&s->ops_mutex); | 882 | mutex_unlock(&s->ops_mutex); |
880 | *wh = res; | 883 | *wh = res; |
diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c index 936bae560fa1..dc628cb2e762 100644 --- a/drivers/power/apm_power.c +++ b/drivers/power/apm_power.c | |||
@@ -233,6 +233,7 @@ static int calculate_capacity(enum apm_source source) | |||
233 | empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN; | 233 | empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN; |
234 | now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; | 234 | now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; |
235 | avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; | 235 | avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; |
236 | break; | ||
236 | case SOURCE_VOLTAGE: | 237 | case SOURCE_VOLTAGE: |
237 | full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX; | 238 | full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX; |
238 | empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN; | 239 | empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN; |
diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c index c61ffec2ff10..2a10cd361181 100644 --- a/drivers/power/intel_mid_battery.c +++ b/drivers/power/intel_mid_battery.c | |||
@@ -185,8 +185,8 @@ static int pmic_scu_ipc_battery_property_get(struct battery_property *prop) | |||
185 | { | 185 | { |
186 | u32 data[3]; | 186 | u32 data[3]; |
187 | u8 *p = (u8 *)&data[1]; | 187 | u8 *p = (u8 *)&data[1]; |
188 | int err = intel_scu_ipc_command(IPC_CMD_BATTERY_PROPERTY, | 188 | int err = intel_scu_ipc_command(IPCMSG_BATTERY, |
189 | IPCMSG_BATTERY, NULL, 0, data, 3); | 189 | IPC_CMD_BATTERY_PROPERTY, NULL, 0, data, 3); |
190 | 190 | ||
191 | prop->capacity = data[0]; | 191 | prop->capacity = data[0]; |
192 | prop->crnt = *p++; | 192 | prop->crnt = *p++; |
@@ -207,7 +207,7 @@ static int pmic_scu_ipc_battery_property_get(struct battery_property *prop) | |||
207 | 207 | ||
208 | static int pmic_scu_ipc_set_charger(int charger) | 208 | static int pmic_scu_ipc_set_charger(int charger) |
209 | { | 209 | { |
210 | return intel_scu_ipc_simple_command(charger, IPCMSG_BATTERY); | 210 | return intel_scu_ipc_simple_command(IPCMSG_BATTERY, charger); |
211 | } | 211 | } |
212 | 212 | ||
213 | /** | 213 | /** |
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 7d149a8d8d9b..2ce2eb71d0f5 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c | |||
@@ -215,7 +215,7 @@ static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index) | |||
215 | struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); | 215 | struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); |
216 | int ret = -EINVAL; | 216 | int ret = -EINVAL; |
217 | 217 | ||
218 | if (info->vol_table && (index < (2 << info->vol_nbits))) { | 218 | if (info->vol_table && (index < (1 << info->vol_nbits))) { |
219 | ret = info->vol_table[index]; | 219 | ret = info->vol_table[index]; |
220 | if (info->slope_double) | 220 | if (info->slope_double) |
221 | ret <<= 1; | 221 | ret <<= 1; |
@@ -233,7 +233,7 @@ static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) | |||
233 | max_uV = max_uV >> 1; | 233 | max_uV = max_uV >> 1; |
234 | } | 234 | } |
235 | if (info->vol_table) { | 235 | if (info->vol_table) { |
236 | for (i = 0; i < (2 << info->vol_nbits); i++) { | 236 | for (i = 0; i < (1 << info->vol_nbits); i++) { |
237 | if (!info->vol_table[i]) | 237 | if (!info->vol_table[i]) |
238 | break; | 238 | break; |
239 | if ((min_uV <= info->vol_table[i]) | 239 | if ((min_uV <= info->vol_table[i]) |
diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 11790990277a..b349266a43de 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c | |||
@@ -634,12 +634,9 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev) | |||
634 | "%s: failed to register regulator %s err %d\n", | 634 | "%s: failed to register regulator %s err %d\n", |
635 | __func__, ab3100_regulator_desc[i].name, | 635 | __func__, ab3100_regulator_desc[i].name, |
636 | err); | 636 | err); |
637 | i--; | ||
638 | /* remove the already registered regulators */ | 637 | /* remove the already registered regulators */ |
639 | while (i > 0) { | 638 | while (--i >= 0) |
640 | regulator_unregister(ab3100_regulators[i].rdev); | 639 | regulator_unregister(ab3100_regulators[i].rdev); |
641 | i--; | ||
642 | } | ||
643 | return err; | 640 | return err; |
644 | } | 641 | } |
645 | 642 | ||
diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index dc3f1a491675..28c7ae67cec9 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c | |||
@@ -157,7 +157,7 @@ static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector) | |||
157 | if (info->fixed_uV) | 157 | if (info->fixed_uV) |
158 | return info->fixed_uV; | 158 | return info->fixed_uV; |
159 | 159 | ||
160 | if (selector > info->voltages_len) | 160 | if (selector >= info->voltages_len) |
161 | return -EINVAL; | 161 | return -EINVAL; |
162 | 162 | ||
163 | return info->supported_voltages[selector]; | 163 | return info->supported_voltages[selector]; |
@@ -344,13 +344,14 @@ static inline struct ab8500_regulator_info *find_regulator_info(int id) | |||
344 | static __devinit int ab8500_regulator_probe(struct platform_device *pdev) | 344 | static __devinit int ab8500_regulator_probe(struct platform_device *pdev) |
345 | { | 345 | { |
346 | struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); | 346 | struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); |
347 | struct ab8500_platform_data *pdata = dev_get_platdata(ab8500->dev); | 347 | struct ab8500_platform_data *pdata; |
348 | int i, err; | 348 | int i, err; |
349 | 349 | ||
350 | if (!ab8500) { | 350 | if (!ab8500) { |
351 | dev_err(&pdev->dev, "null mfd parent\n"); | 351 | dev_err(&pdev->dev, "null mfd parent\n"); |
352 | return -EINVAL; | 352 | return -EINVAL; |
353 | } | 353 | } |
354 | pdata = dev_get_platdata(ab8500->dev); | ||
354 | 355 | ||
355 | /* register all regulators */ | 356 | /* register all regulators */ |
356 | for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { | 357 | for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { |
@@ -368,11 +369,9 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev) | |||
368 | dev_err(&pdev->dev, "failed to register regulator %s\n", | 369 | dev_err(&pdev->dev, "failed to register regulator %s\n", |
369 | info->desc.name); | 370 | info->desc.name); |
370 | /* when we fail, un-register all earlier regulators */ | 371 | /* when we fail, un-register all earlier regulators */ |
371 | i--; | 372 | while (--i >= 0) { |
372 | while (i > 0) { | ||
373 | info = &ab8500_regulator_info[i]; | 373 | info = &ab8500_regulator_info[i]; |
374 | regulator_unregister(info->regulator); | 374 | regulator_unregister(info->regulator); |
375 | i--; | ||
376 | } | 375 | } |
377 | return err; | 376 | return err; |
378 | } | 377 | } |
diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c index d59d2f2314af..df1fb53c09d2 100644 --- a/drivers/regulator/ad5398.c +++ b/drivers/regulator/ad5398.c | |||
@@ -25,7 +25,7 @@ struct ad5398_chip_info { | |||
25 | unsigned int current_level; | 25 | unsigned int current_level; |
26 | unsigned int current_mask; | 26 | unsigned int current_mask; |
27 | unsigned int current_offset; | 27 | unsigned int current_offset; |
28 | struct regulator_dev rdev; | 28 | struct regulator_dev *rdev; |
29 | }; | 29 | }; |
30 | 30 | ||
31 | static int ad5398_calc_current(struct ad5398_chip_info *chip, | 31 | static int ad5398_calc_current(struct ad5398_chip_info *chip, |
@@ -211,7 +211,6 @@ MODULE_DEVICE_TABLE(i2c, ad5398_id); | |||
211 | static int __devinit ad5398_probe(struct i2c_client *client, | 211 | static int __devinit ad5398_probe(struct i2c_client *client, |
212 | const struct i2c_device_id *id) | 212 | const struct i2c_device_id *id) |
213 | { | 213 | { |
214 | struct regulator_dev *rdev; | ||
215 | struct regulator_init_data *init_data = client->dev.platform_data; | 214 | struct regulator_init_data *init_data = client->dev.platform_data; |
216 | struct ad5398_chip_info *chip; | 215 | struct ad5398_chip_info *chip; |
217 | const struct ad5398_current_data_format *df = | 216 | const struct ad5398_current_data_format *df = |
@@ -233,9 +232,10 @@ static int __devinit ad5398_probe(struct i2c_client *client, | |||
233 | chip->current_offset = df->current_offset; | 232 | chip->current_offset = df->current_offset; |
234 | chip->current_mask = (chip->current_level - 1) << chip->current_offset; | 233 | chip->current_mask = (chip->current_level - 1) << chip->current_offset; |
235 | 234 | ||
236 | rdev = regulator_register(&ad5398_reg, &client->dev, init_data, chip); | 235 | chip->rdev = regulator_register(&ad5398_reg, &client->dev, |
237 | if (IS_ERR(rdev)) { | 236 | init_data, chip); |
238 | ret = PTR_ERR(rdev); | 237 | if (IS_ERR(chip->rdev)) { |
238 | ret = PTR_ERR(chip->rdev); | ||
239 | dev_err(&client->dev, "failed to register %s %s\n", | 239 | dev_err(&client->dev, "failed to register %s %s\n", |
240 | id->name, ad5398_reg.name); | 240 | id->name, ad5398_reg.name); |
241 | goto err; | 241 | goto err; |
@@ -254,7 +254,7 @@ static int __devexit ad5398_remove(struct i2c_client *client) | |||
254 | { | 254 | { |
255 | struct ad5398_chip_info *chip = i2c_get_clientdata(client); | 255 | struct ad5398_chip_info *chip = i2c_get_clientdata(client); |
256 | 256 | ||
257 | regulator_unregister(&chip->rdev); | 257 | regulator_unregister(chip->rdev); |
258 | kfree(chip); | 258 | kfree(chip); |
259 | i2c_set_clientdata(client, NULL); | 259 | i2c_set_clientdata(client, NULL); |
260 | 260 | ||
diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index e49d2bd393f2..d61ecb885a8c 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c | |||
@@ -165,7 +165,7 @@ static int __devinit isl6271a_probe(struct i2c_client *i2c, | |||
165 | mutex_init(&pmic->mtx); | 165 | mutex_init(&pmic->mtx); |
166 | 166 | ||
167 | for (i = 0; i < 3; i++) { | 167 | for (i = 0; i < 3; i++) { |
168 | pmic->rdev[i] = regulator_register(&isl_rd[0], &i2c->dev, | 168 | pmic->rdev[i] = regulator_register(&isl_rd[i], &i2c->dev, |
169 | init_data, pmic); | 169 | init_data, pmic); |
170 | if (IS_ERR(pmic->rdev[i])) { | 170 | if (IS_ERR(pmic->rdev[i])) { |
171 | dev_err(&i2c->dev, "failed to register %s\n", id->name); | 171 | dev_err(&i2c->dev, "failed to register %s\n", id->name); |
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index 8867c2710a6d..559cfa271a44 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c | |||
@@ -121,14 +121,14 @@ static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV) | |||
121 | if (max_uV < MAX1586_V6_MIN_UV || max_uV > MAX1586_V6_MAX_UV) | 121 | if (max_uV < MAX1586_V6_MIN_UV || max_uV > MAX1586_V6_MAX_UV) |
122 | return -EINVAL; | 122 | return -EINVAL; |
123 | 123 | ||
124 | if (min_uV >= 3000000) | ||
125 | selector = 3; | ||
126 | if (min_uV < 3000000) | ||
127 | selector = 2; | ||
128 | if (min_uV < 2500000) | ||
129 | selector = 1; | ||
130 | if (min_uV < 1800000) | 124 | if (min_uV < 1800000) |
131 | selector = 0; | 125 | selector = 0; |
126 | else if (min_uV < 2500000) | ||
127 | selector = 1; | ||
128 | else if (min_uV < 3000000) | ||
129 | selector = 2; | ||
130 | else if (min_uV >= 3000000) | ||
131 | selector = 3; | ||
132 | 132 | ||
133 | if (max1586_v6_calc_voltage(selector) > max_uV) | 133 | if (max1586_v6_calc_voltage(selector) > max_uV) |
134 | return -EINVAL; | 134 | return -EINVAL; |
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index ab67298799f9..a1baf1fbe004 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c | |||
@@ -549,7 +549,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) | |||
549 | if (!max8998) | 549 | if (!max8998) |
550 | return -ENOMEM; | 550 | return -ENOMEM; |
551 | 551 | ||
552 | size = sizeof(struct regulator_dev *) * (pdata->num_regulators + 1); | 552 | size = sizeof(struct regulator_dev *) * pdata->num_regulators; |
553 | max8998->rdev = kzalloc(size, GFP_KERNEL); | 553 | max8998->rdev = kzalloc(size, GFP_KERNEL); |
554 | if (!max8998->rdev) { | 554 | if (!max8998->rdev) { |
555 | kfree(max8998); | 555 | kfree(max8998); |
@@ -557,7 +557,9 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) | |||
557 | } | 557 | } |
558 | 558 | ||
559 | rdev = max8998->rdev; | 559 | rdev = max8998->rdev; |
560 | max8998->dev = &pdev->dev; | ||
560 | max8998->iodev = iodev; | 561 | max8998->iodev = iodev; |
562 | max8998->num_regulators = pdata->num_regulators; | ||
561 | platform_set_drvdata(pdev, max8998); | 563 | platform_set_drvdata(pdev, max8998); |
562 | 564 | ||
563 | for (i = 0; i < pdata->num_regulators; i++) { | 565 | for (i = 0; i < pdata->num_regulators; i++) { |
@@ -583,7 +585,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) | |||
583 | 585 | ||
584 | return 0; | 586 | return 0; |
585 | err: | 587 | err: |
586 | for (i = 0; i <= max8998->num_regulators; i++) | 588 | for (i = 0; i < max8998->num_regulators; i++) |
587 | if (rdev[i]) | 589 | if (rdev[i]) |
588 | regulator_unregister(rdev[i]); | 590 | regulator_unregister(rdev[i]); |
589 | 591 | ||
@@ -599,7 +601,7 @@ static int __devexit max8998_pmic_remove(struct platform_device *pdev) | |||
599 | struct regulator_dev **rdev = max8998->rdev; | 601 | struct regulator_dev **rdev = max8998->rdev; |
600 | int i; | 602 | int i; |
601 | 603 | ||
602 | for (i = 0; i <= max8998->num_regulators; i++) | 604 | for (i = 0; i < max8998->num_regulators; i++) |
603 | if (rdev[i]) | 605 | if (rdev[i]) |
604 | regulator_unregister(rdev[i]); | 606 | regulator_unregister(rdev[i]); |
605 | 607 | ||
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index c239f42aa4a3..020f5878d7ff 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c | |||
@@ -626,12 +626,6 @@ fail: | |||
626 | return error; | 626 | return error; |
627 | } | 627 | } |
628 | 628 | ||
629 | /** | ||
630 | * tps6507x_remove - TPS6507x driver i2c remove handler | ||
631 | * @client: i2c driver client device structure | ||
632 | * | ||
633 | * Unregister TPS driver as an i2c client device driver | ||
634 | */ | ||
635 | static int __devexit tps6507x_pmic_remove(struct platform_device *pdev) | 629 | static int __devexit tps6507x_pmic_remove(struct platform_device *pdev) |
636 | { | 630 | { |
637 | struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev); | 631 | struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev); |
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 8cff1413a147..51237fbb1bbb 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c | |||
@@ -133,7 +133,7 @@ static int tps6586x_ldo_get_voltage(struct regulator_dev *rdev) | |||
133 | mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; | 133 | mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; |
134 | val = (val & mask) >> ri->volt_shift; | 134 | val = (val & mask) >> ri->volt_shift; |
135 | 135 | ||
136 | if (val > ri->desc.n_voltages) | 136 | if (val >= ri->desc.n_voltages) |
137 | BUG(); | 137 | BUG(); |
138 | 138 | ||
139 | return ri->voltages[val] * 1000; | 139 | return ri->voltages[val] * 1000; |
@@ -150,7 +150,7 @@ static int tps6586x_dvm_set_voltage(struct regulator_dev *rdev, | |||
150 | if (ret) | 150 | if (ret) |
151 | return ret; | 151 | return ret; |
152 | 152 | ||
153 | return tps6586x_set_bits(parent, ri->go_reg, ri->go_bit); | 153 | return tps6586x_set_bits(parent, ri->go_reg, 1 << ri->go_bit); |
154 | } | 154 | } |
155 | 155 | ||
156 | static int tps6586x_regulator_enable(struct regulator_dev *rdev) | 156 | static int tps6586x_regulator_enable(struct regulator_dev *rdev) |
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index e686cdb61b97..9edf8f692341 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c | |||
@@ -215,8 +215,7 @@ static int wm831x_gp_ldo_set_mode(struct regulator_dev *rdev, | |||
215 | 215 | ||
216 | case REGULATOR_MODE_IDLE: | 216 | case REGULATOR_MODE_IDLE: |
217 | ret = wm831x_set_bits(wm831x, ctrl_reg, | 217 | ret = wm831x_set_bits(wm831x, ctrl_reg, |
218 | WM831X_LDO1_LP_MODE, | 218 | WM831X_LDO1_LP_MODE, 0); |
219 | WM831X_LDO1_LP_MODE); | ||
220 | if (ret < 0) | 219 | if (ret < 0) |
221 | return ret; | 220 | return ret; |
222 | 221 | ||
@@ -225,10 +224,12 @@ static int wm831x_gp_ldo_set_mode(struct regulator_dev *rdev, | |||
225 | WM831X_LDO1_ON_MODE); | 224 | WM831X_LDO1_ON_MODE); |
226 | if (ret < 0) | 225 | if (ret < 0) |
227 | return ret; | 226 | return ret; |
227 | break; | ||
228 | 228 | ||
229 | case REGULATOR_MODE_STANDBY: | 229 | case REGULATOR_MODE_STANDBY: |
230 | ret = wm831x_set_bits(wm831x, ctrl_reg, | 230 | ret = wm831x_set_bits(wm831x, ctrl_reg, |
231 | WM831X_LDO1_LP_MODE, 0); | 231 | WM831X_LDO1_LP_MODE, |
232 | WM831X_LDO1_LP_MODE); | ||
232 | if (ret < 0) | 233 | if (ret < 0) |
233 | return ret; | 234 | return ret; |
234 | 235 | ||
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 0e6ed7db9364..fe4b8a8a9dfd 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c | |||
@@ -1129,7 +1129,7 @@ static unsigned int wm8350_dcdc_get_mode(struct regulator_dev *rdev) | |||
1129 | mode = REGULATOR_MODE_NORMAL; | 1129 | mode = REGULATOR_MODE_NORMAL; |
1130 | } else if (!active && !sleep) | 1130 | } else if (!active && !sleep) |
1131 | mode = REGULATOR_MODE_IDLE; | 1131 | mode = REGULATOR_MODE_IDLE; |
1132 | else if (!sleep) | 1132 | else if (sleep) |
1133 | mode = REGULATOR_MODE_STANDBY; | 1133 | mode = REGULATOR_MODE_STANDBY; |
1134 | 1134 | ||
1135 | return mode; | 1135 | return mode; |
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 141c69554bd4..7d475b2a79e8 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c | |||
@@ -335,8 +335,6 @@ static int serial_probe(struct pcmcia_device *link) | |||
335 | info->p_dev = link; | 335 | info->p_dev = link; |
336 | link->priv = info; | 336 | link->priv = info; |
337 | 337 | ||
338 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | ||
339 | link->resource[0]->end = 8; | ||
340 | link->conf.Attributes = CONF_ENABLE_IRQ; | 338 | link->conf.Attributes = CONF_ENABLE_IRQ; |
341 | if (do_sound) { | 339 | if (do_sound) { |
342 | link->conf.Attributes |= CONF_ENABLE_SPKR; | 340 | link->conf.Attributes |= CONF_ENABLE_SPKR; |
@@ -411,6 +409,27 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info, | |||
411 | 409 | ||
412 | /*====================================================================*/ | 410 | /*====================================================================*/ |
413 | 411 | ||
412 | static int pfc_config(struct pcmcia_device *p_dev) | ||
413 | { | ||
414 | unsigned int port = 0; | ||
415 | struct serial_info *info = p_dev->priv; | ||
416 | |||
417 | if ((p_dev->resource[1]->end != 0) && | ||
418 | (resource_size(p_dev->resource[1]) == 8)) { | ||
419 | port = p_dev->resource[1]->start; | ||
420 | info->slave = 1; | ||
421 | } else if ((info->manfid == MANFID_OSITECH) && | ||
422 | (resource_size(p_dev->resource[0]) == 0x40)) { | ||
423 | port = p_dev->resource[0]->start + 0x28; | ||
424 | info->slave = 1; | ||
425 | } | ||
426 | if (info->slave) | ||
427 | return setup_serial(p_dev, info, port, p_dev->irq); | ||
428 | |||
429 | dev_warn(&p_dev->dev, "no usable port range found, giving up\n"); | ||
430 | return -ENODEV; | ||
431 | } | ||
432 | |||
414 | static int simple_config_check(struct pcmcia_device *p_dev, | 433 | static int simple_config_check(struct pcmcia_device *p_dev, |
415 | cistpl_cftable_entry_t *cf, | 434 | cistpl_cftable_entry_t *cf, |
416 | cistpl_cftable_entry_t *dflt, | 435 | cistpl_cftable_entry_t *dflt, |
@@ -461,23 +480,8 @@ static int simple_config(struct pcmcia_device *link) | |||
461 | struct serial_info *info = link->priv; | 480 | struct serial_info *info = link->priv; |
462 | int i = -ENODEV, try; | 481 | int i = -ENODEV, try; |
463 | 482 | ||
464 | /* If the card is already configured, look up the port and irq */ | 483 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
465 | if (link->function_config) { | 484 | link->resource[0]->end = 8; |
466 | unsigned int port = 0; | ||
467 | if ((link->resource[1]->end != 0) && | ||
468 | (resource_size(link->resource[1]) == 8)) { | ||
469 | port = link->resource[1]->end; | ||
470 | info->slave = 1; | ||
471 | } else if ((info->manfid == MANFID_OSITECH) && | ||
472 | (resource_size(link->resource[0]) == 0x40)) { | ||
473 | port = link->resource[0]->start + 0x28; | ||
474 | info->slave = 1; | ||
475 | } | ||
476 | if (info->slave) { | ||
477 | return setup_serial(link, info, port, | ||
478 | link->irq); | ||
479 | } | ||
480 | } | ||
481 | 485 | ||
482 | /* First pass: look for a config entry that looks normal. | 486 | /* First pass: look for a config entry that looks normal. |
483 | * Two tries: without IO aliases, then with aliases */ | 487 | * Two tries: without IO aliases, then with aliases */ |
@@ -491,8 +495,7 @@ static int simple_config(struct pcmcia_device *link) | |||
491 | if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL)) | 495 | if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL)) |
492 | goto found_port; | 496 | goto found_port; |
493 | 497 | ||
494 | printk(KERN_NOTICE | 498 | dev_warn(&link->dev, "no usable port range found, giving up\n"); |
495 | "serial_cs: no usable port range found, giving up\n"); | ||
496 | return -1; | 499 | return -1; |
497 | 500 | ||
498 | found_port: | 501 | found_port: |
@@ -558,6 +561,7 @@ static int multi_config(struct pcmcia_device *link) | |||
558 | int i, base2 = 0; | 561 | int i, base2 = 0; |
559 | 562 | ||
560 | /* First, look for a generic full-sized window */ | 563 | /* First, look for a generic full-sized window */ |
564 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | ||
561 | link->resource[0]->end = info->multi * 8; | 565 | link->resource[0]->end = info->multi * 8; |
562 | if (pcmcia_loop_config(link, multi_config_check, &base2)) { | 566 | if (pcmcia_loop_config(link, multi_config_check, &base2)) { |
563 | /* If that didn't work, look for two windows */ | 567 | /* If that didn't work, look for two windows */ |
@@ -565,15 +569,14 @@ static int multi_config(struct pcmcia_device *link) | |||
565 | info->multi = 2; | 569 | info->multi = 2; |
566 | if (pcmcia_loop_config(link, multi_config_check_notpicky, | 570 | if (pcmcia_loop_config(link, multi_config_check_notpicky, |
567 | &base2)) { | 571 | &base2)) { |
568 | printk(KERN_NOTICE "serial_cs: no usable port range" | 572 | dev_warn(&link->dev, "no usable port range " |
569 | "found, giving up\n"); | 573 | "found, giving up\n"); |
570 | return -ENODEV; | 574 | return -ENODEV; |
571 | } | 575 | } |
572 | } | 576 | } |
573 | 577 | ||
574 | if (!link->irq) | 578 | if (!link->irq) |
575 | dev_warn(&link->dev, | 579 | dev_warn(&link->dev, "no usable IRQ found, continuing...\n"); |
576 | "serial_cs: no usable IRQ found, continuing...\n"); | ||
577 | 580 | ||
578 | /* | 581 | /* |
579 | * Apply any configuration quirks. | 582 | * Apply any configuration quirks. |
@@ -675,6 +678,7 @@ static int serial_config(struct pcmcia_device * link) | |||
675 | multifunction cards that ask for appropriate IO port ranges */ | 678 | multifunction cards that ask for appropriate IO port ranges */ |
676 | if ((info->multi == 0) && | 679 | if ((info->multi == 0) && |
677 | (link->has_func_id) && | 680 | (link->has_func_id) && |
681 | (link->socket->pcmcia_pfc == 0) && | ||
678 | ((link->func_id == CISTPL_FUNCID_MULTI) || | 682 | ((link->func_id == CISTPL_FUNCID_MULTI) || |
679 | (link->func_id == CISTPL_FUNCID_SERIAL))) | 683 | (link->func_id == CISTPL_FUNCID_SERIAL))) |
680 | pcmcia_loop_config(link, serial_check_for_multi, info); | 684 | pcmcia_loop_config(link, serial_check_for_multi, info); |
@@ -685,7 +689,13 @@ static int serial_config(struct pcmcia_device * link) | |||
685 | if (info->quirk && info->quirk->multi != -1) | 689 | if (info->quirk && info->quirk->multi != -1) |
686 | info->multi = info->quirk->multi; | 690 | info->multi = info->quirk->multi; |
687 | 691 | ||
688 | if (info->multi > 1) | 692 | dev_info(&link->dev, |
693 | "trying to set up [0x%04x:0x%04x] (pfc: %d, multi: %d, quirk: %p)\n", | ||
694 | link->manf_id, link->card_id, | ||
695 | link->socket->pcmcia_pfc, info->multi, info->quirk); | ||
696 | if (link->socket->pcmcia_pfc) | ||
697 | i = pfc_config(link); | ||
698 | else if (info->multi > 1) | ||
689 | i = multi_config(link); | 699 | i = multi_config(link); |
690 | else | 700 | else |
691 | i = simple_config(link); | 701 | i = simple_config(link); |
@@ -704,7 +714,7 @@ static int serial_config(struct pcmcia_device * link) | |||
704 | return 0; | 714 | return 0; |
705 | 715 | ||
706 | failed: | 716 | failed: |
707 | dev_warn(&link->dev, "serial_cs: failed to initialize\n"); | 717 | dev_warn(&link->dev, "failed to initialize\n"); |
708 | serial_remove(link); | 718 | serial_remove(link); |
709 | return -ENODEV; | 719 | return -ENODEV; |
710 | } | 720 | } |
diff --git a/drivers/video/via/ioctl.c b/drivers/video/via/ioctl.c index da03c074e32a..4d553d0b8d7a 100644 --- a/drivers/video/via/ioctl.c +++ b/drivers/video/via/ioctl.c | |||
@@ -25,6 +25,8 @@ int viafb_ioctl_get_viafb_info(u_long arg) | |||
25 | { | 25 | { |
26 | struct viafb_ioctl_info viainfo; | 26 | struct viafb_ioctl_info viainfo; |
27 | 27 | ||
28 | memset(&viainfo, 0, sizeof(struct viafb_ioctl_info)); | ||
29 | |||
28 | viainfo.viafb_id = VIAID; | 30 | viainfo.viafb_id = VIAID; |
29 | viainfo.vendor_id = PCI_VIA_VENDOR_ID; | 31 | viainfo.vendor_id = PCI_VIA_VENDOR_ID; |
30 | 32 | ||
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b036677df8c4..24efd8ea41bb 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
@@ -213,11 +213,11 @@ config OMAP_WATCHDOG | |||
213 | here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog timer. | 213 | here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog timer. |
214 | 214 | ||
215 | config PNX4008_WATCHDOG | 215 | config PNX4008_WATCHDOG |
216 | tristate "PNX4008 Watchdog" | 216 | tristate "PNX4008 and LPC32XX Watchdog" |
217 | depends on ARCH_PNX4008 | 217 | depends on ARCH_PNX4008 || ARCH_LPC32XX |
218 | help | 218 | help |
219 | Say Y here if to include support for the watchdog timer | 219 | Say Y here if to include support for the watchdog timer |
220 | in the PNX4008 processor. | 220 | in the PNX4008 or LPC32XX processor. |
221 | This driver can be built as a module by choosing M. The module | 221 | This driver can be built as a module by choosing M. The module |
222 | will be called pnx4008_wdt. | 222 | will be called pnx4008_wdt. |
223 | 223 | ||
diff --git a/drivers/watchdog/sb_wdog.c b/drivers/watchdog/sb_wdog.c index 88c83aa57303..f31493e65b38 100644 --- a/drivers/watchdog/sb_wdog.c +++ b/drivers/watchdog/sb_wdog.c | |||
@@ -305,7 +305,7 @@ static int __init sbwdog_init(void) | |||
305 | if (ret) { | 305 | if (ret) { |
306 | printk(KERN_ERR "%s: failed to request irq 1 - %d\n", | 306 | printk(KERN_ERR "%s: failed to request irq 1 - %d\n", |
307 | ident.identity, ret); | 307 | ident.identity, ret); |
308 | return ret; | 308 | goto out; |
309 | } | 309 | } |
310 | 310 | ||
311 | ret = misc_register(&sbwdog_miscdev); | 311 | ret = misc_register(&sbwdog_miscdev); |
@@ -313,14 +313,20 @@ static int __init sbwdog_init(void) | |||
313 | printk(KERN_INFO "%s: timeout is %ld.%ld secs\n", | 313 | printk(KERN_INFO "%s: timeout is %ld.%ld secs\n", |
314 | ident.identity, | 314 | ident.identity, |
315 | timeout / 1000000, (timeout / 100000) % 10); | 315 | timeout / 1000000, (timeout / 100000) % 10); |
316 | } else | 316 | return 0; |
317 | free_irq(1, (void *)user_dog); | 317 | } |
318 | free_irq(1, (void *)user_dog); | ||
319 | out: | ||
320 | unregister_reboot_notifier(&sbwdog_notifier); | ||
321 | |||
318 | return ret; | 322 | return ret; |
319 | } | 323 | } |
320 | 324 | ||
321 | static void __exit sbwdog_exit(void) | 325 | static void __exit sbwdog_exit(void) |
322 | { | 326 | { |
323 | misc_deregister(&sbwdog_miscdev); | 327 | misc_deregister(&sbwdog_miscdev); |
328 | free_irq(1, (void *)user_dog); | ||
329 | unregister_reboot_notifier(&sbwdog_notifier); | ||
324 | } | 330 | } |
325 | 331 | ||
326 | module_init(sbwdog_init); | 332 | module_init(sbwdog_init); |
diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c index 458c499c1223..18cdeb4c4258 100644 --- a/drivers/watchdog/ts72xx_wdt.c +++ b/drivers/watchdog/ts72xx_wdt.c | |||
@@ -449,6 +449,9 @@ static __devinit int ts72xx_wdt_probe(struct platform_device *pdev) | |||
449 | wdt->pdev = pdev; | 449 | wdt->pdev = pdev; |
450 | mutex_init(&wdt->lock); | 450 | mutex_init(&wdt->lock); |
451 | 451 | ||
452 | /* make sure that the watchdog is disabled */ | ||
453 | ts72xx_wdt_stop(wdt); | ||
454 | |||
452 | error = misc_register(&ts72xx_wdt_miscdev); | 455 | error = misc_register(&ts72xx_wdt_miscdev); |
453 | if (error) { | 456 | if (error) { |
454 | dev_err(&pdev->dev, "failed to register miscdev\n"); | 457 | dev_err(&pdev->dev, "failed to register miscdev\n"); |
@@ -1659,6 +1659,9 @@ long do_io_submit(aio_context_t ctx_id, long nr, | |||
1659 | if (unlikely(nr < 0)) | 1659 | if (unlikely(nr < 0)) |
1660 | return -EINVAL; | 1660 | return -EINVAL; |
1661 | 1661 | ||
1662 | if (unlikely(nr > LONG_MAX/sizeof(*iocbpp))) | ||
1663 | nr = LONG_MAX/sizeof(*iocbpp); | ||
1664 | |||
1662 | if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(*iocbpp))))) | 1665 | if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(*iocbpp))))) |
1663 | return -EFAULT; | 1666 | return -EFAULT; |
1664 | 1667 | ||
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index 6c2aad49d731..f7e13db613cb 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig | |||
@@ -63,6 +63,7 @@ config NFS_V3_ACL | |||
63 | config NFS_V4 | 63 | config NFS_V4 |
64 | bool "NFS client support for NFS version 4" | 64 | bool "NFS client support for NFS version 4" |
65 | depends on NFS_FS | 65 | depends on NFS_FS |
66 | select SUNRPC_GSS | ||
66 | help | 67 | help |
67 | This option enables support for version 4 of the NFS protocol | 68 | This option enables support for version 4 of the NFS protocol |
68 | (RFC 3530) in the kernel's NFS client. | 69 | (RFC 3530) in the kernel's NFS client. |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 4e7df2adb212..e7340729af89 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -275,7 +275,7 @@ static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, | |||
275 | sin1->sin6_scope_id != sin2->sin6_scope_id) | 275 | sin1->sin6_scope_id != sin2->sin6_scope_id) |
276 | return 0; | 276 | return 0; |
277 | 277 | ||
278 | return ipv6_addr_equal(&sin1->sin6_addr, &sin1->sin6_addr); | 278 | return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr); |
279 | } | 279 | } |
280 | #else /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */ | 280 | #else /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */ |
281 | static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, | 281 | static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index eb51bd6201da..05bf3c0dc751 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -723,10 +723,6 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl) | |||
723 | default: | 723 | default: |
724 | BUG(); | 724 | BUG(); |
725 | } | 725 | } |
726 | if (res < 0) | ||
727 | dprintk(KERN_WARNING "%s: VFS is out of sync with lock manager" | ||
728 | " - error %d!\n", | ||
729 | __func__, res); | ||
730 | return res; | 726 | return res; |
731 | } | 727 | } |
732 | 728 | ||
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index ec3966e4706b..f4cbf0c306c6 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -431,7 +431,15 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
431 | goto out_err; | 431 | goto out_err; |
432 | 432 | ||
433 | error = server->nfs_client->rpc_ops->statfs(server, fh, &res); | 433 | error = server->nfs_client->rpc_ops->statfs(server, fh, &res); |
434 | if (unlikely(error == -ESTALE)) { | ||
435 | struct dentry *pd_dentry; | ||
434 | 436 | ||
437 | pd_dentry = dget_parent(dentry); | ||
438 | if (pd_dentry != NULL) { | ||
439 | nfs_zap_caches(pd_dentry->d_inode); | ||
440 | dput(pd_dentry); | ||
441 | } | ||
442 | } | ||
435 | nfs_free_fattr(res.fattr); | 443 | nfs_free_fattr(res.fattr); |
436 | if (error < 0) | 444 | if (error < 0) |
437 | goto out_err; | 445 | goto out_err; |
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig index 95932f523aef..4264377552e2 100644 --- a/fs/nfsd/Kconfig +++ b/fs/nfsd/Kconfig | |||
@@ -69,6 +69,7 @@ config NFSD_V4 | |||
69 | depends on NFSD && PROC_FS && EXPERIMENTAL | 69 | depends on NFSD && PROC_FS && EXPERIMENTAL |
70 | select NFSD_V3 | 70 | select NFSD_V3 |
71 | select FS_POSIX_ACL | 71 | select FS_POSIX_ACL |
72 | select SUNRPC_GSS | ||
72 | help | 73 | help |
73 | This option enables support in your system's NFS server for | 74 | This option enables support in your system's NFS server for |
74 | version 4 of the NFS protocol (RFC 3530). | 75 | version 4 of the NFS protocol (RFC 3530). |
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c9f3cc5949a8..3e5a51af757c 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
@@ -386,7 +386,15 @@ struct drm_connector_funcs { | |||
386 | void (*dpms)(struct drm_connector *connector, int mode); | 386 | void (*dpms)(struct drm_connector *connector, int mode); |
387 | void (*save)(struct drm_connector *connector); | 387 | void (*save)(struct drm_connector *connector); |
388 | void (*restore)(struct drm_connector *connector); | 388 | void (*restore)(struct drm_connector *connector); |
389 | enum drm_connector_status (*detect)(struct drm_connector *connector); | 389 | |
390 | /* Check to see if anything is attached to the connector. | ||
391 | * @force is set to false whilst polling, true when checking the | ||
392 | * connector due to user request. @force can be used by the driver | ||
393 | * to avoid expensive, destructive operations during automated | ||
394 | * probing. | ||
395 | */ | ||
396 | enum drm_connector_status (*detect)(struct drm_connector *connector, | ||
397 | bool force); | ||
390 | int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height); | 398 | int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height); |
391 | int (*set_property)(struct drm_connector *connector, struct drm_property *property, | 399 | int (*set_property)(struct drm_connector *connector, struct drm_property *property, |
392 | uint64_t val); | 400 | uint64_t val); |
diff --git a/include/linux/compat.h b/include/linux/compat.h index 9ddc8780e8db..5778b559d59c 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h | |||
@@ -360,5 +360,8 @@ extern ssize_t compat_rw_copy_check_uvector(int type, | |||
360 | const struct compat_iovec __user *uvector, unsigned long nr_segs, | 360 | const struct compat_iovec __user *uvector, unsigned long nr_segs, |
361 | unsigned long fast_segs, struct iovec *fast_pointer, | 361 | unsigned long fast_segs, struct iovec *fast_pointer, |
362 | struct iovec **ret_pointer); | 362 | struct iovec **ret_pointer); |
363 | |||
364 | extern void __user *compat_alloc_user_space(unsigned long len); | ||
365 | |||
363 | #endif /* CONFIG_COMPAT */ | 366 | #endif /* CONFIG_COMPAT */ |
364 | #endif /* _LINUX_COMPAT_H */ | 367 | #endif /* _LINUX_COMPAT_H */ |
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index 569dc722a600..85f38a63f098 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h | |||
@@ -30,7 +30,7 @@ struct rpc_inode; | |||
30 | * The high-level client handle | 30 | * The high-level client handle |
31 | */ | 31 | */ |
32 | struct rpc_clnt { | 32 | struct rpc_clnt { |
33 | struct kref cl_kref; /* Number of references */ | 33 | atomic_t cl_count; /* Number of references */ |
34 | struct list_head cl_clients; /* Global list of clients */ | 34 | struct list_head cl_clients; /* Global list of clients */ |
35 | struct list_head cl_tasks; /* List of tasks */ | 35 | struct list_head cl_tasks; /* List of tasks */ |
36 | spinlock_t cl_lock; /* spinlock */ | 36 | spinlock_t cl_lock; /* spinlock */ |
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index f11100f96482..25e02c941bac 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h | |||
@@ -235,6 +235,10 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; } | |||
235 | #define work_clear_pending(work) \ | 235 | #define work_clear_pending(work) \ |
236 | clear_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work)) | 236 | clear_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work)) |
237 | 237 | ||
238 | /* | ||
239 | * Workqueue flags and constants. For details, please refer to | ||
240 | * Documentation/workqueue.txt. | ||
241 | */ | ||
238 | enum { | 242 | enum { |
239 | WQ_NON_REENTRANT = 1 << 0, /* guarantee non-reentrance */ | 243 | WQ_NON_REENTRANT = 1 << 0, /* guarantee non-reentrance */ |
240 | WQ_UNBOUND = 1 << 1, /* not bound to any cpu */ | 244 | WQ_UNBOUND = 1 << 1, /* not bound to any cpu */ |
diff --git a/kernel/compat.c b/kernel/compat.c index e167efce8423..c9e2ec0b34a8 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
@@ -1126,3 +1126,24 @@ compat_sys_sysinfo(struct compat_sysinfo __user *info) | |||
1126 | 1126 | ||
1127 | return 0; | 1127 | return 0; |
1128 | } | 1128 | } |
1129 | |||
1130 | /* | ||
1131 | * Allocate user-space memory for the duration of a single system call, | ||
1132 | * in order to marshall parameters inside a compat thunk. | ||
1133 | */ | ||
1134 | void __user *compat_alloc_user_space(unsigned long len) | ||
1135 | { | ||
1136 | void __user *ptr; | ||
1137 | |||
1138 | /* If len would occupy more than half of the entire compat space... */ | ||
1139 | if (unlikely(len > (((compat_uptr_t)~0) >> 1))) | ||
1140 | return NULL; | ||
1141 | |||
1142 | ptr = arch_compat_alloc_user_space(len); | ||
1143 | |||
1144 | if (unlikely(!access_ok(VERIFY_WRITE, ptr, len))) | ||
1145 | return NULL; | ||
1146 | |||
1147 | return ptr; | ||
1148 | } | ||
1149 | EXPORT_SYMBOL_GPL(compat_alloc_user_space); | ||
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 727f24e563ae..f77afd939229 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -1,19 +1,26 @@ | |||
1 | /* | 1 | /* |
2 | * linux/kernel/workqueue.c | 2 | * kernel/workqueue.c - generic async execution with shared worker pool |
3 | * | 3 | * |
4 | * Generic mechanism for defining kernel helper threads for running | 4 | * Copyright (C) 2002 Ingo Molnar |
5 | * arbitrary tasks in process context. | ||
6 | * | 5 | * |
7 | * Started by Ingo Molnar, Copyright (C) 2002 | 6 | * Derived from the taskqueue/keventd code by: |
7 | * David Woodhouse <dwmw2@infradead.org> | ||
8 | * Andrew Morton | ||
9 | * Kai Petzke <wpp@marie.physik.tu-berlin.de> | ||
10 | * Theodore Ts'o <tytso@mit.edu> | ||
8 | * | 11 | * |
9 | * Derived from the taskqueue/keventd code by: | 12 | * Made to use alloc_percpu by Christoph Lameter. |
10 | * | 13 | * |
11 | * David Woodhouse <dwmw2@infradead.org> | 14 | * Copyright (C) 2010 SUSE Linux Products GmbH |
12 | * Andrew Morton | 15 | * Copyright (C) 2010 Tejun Heo <tj@kernel.org> |
13 | * Kai Petzke <wpp@marie.physik.tu-berlin.de> | ||
14 | * Theodore Ts'o <tytso@mit.edu> | ||
15 | * | 16 | * |
16 | * Made to use alloc_percpu by Christoph Lameter. | 17 | * This is the generic async execution mechanism. Work items as are |
18 | * executed in process context. The worker pool is shared and | ||
19 | * automatically managed. There is one worker pool for each CPU and | ||
20 | * one extra for works which are better served by workers which are | ||
21 | * not bound to any specific CPU. | ||
22 | * | ||
23 | * Please read Documentation/workqueue.txt for details. | ||
17 | */ | 24 | */ |
18 | 25 | ||
19 | #include <linux/module.h> | 26 | #include <linux/module.h> |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 36cb66022a27..e9eaaf7d43c1 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -38,7 +38,7 @@ static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { | |||
38 | static LIST_HEAD(cred_unused); | 38 | static LIST_HEAD(cred_unused); |
39 | static unsigned long number_cred_unused; | 39 | static unsigned long number_cred_unused; |
40 | 40 | ||
41 | #define MAX_HASHTABLE_BITS (10) | 41 | #define MAX_HASHTABLE_BITS (14) |
42 | static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp) | 42 | static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp) |
43 | { | 43 | { |
44 | unsigned long num; | 44 | unsigned long num; |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index dcfc66bab2bb..12c485982814 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -745,17 +745,18 @@ gss_pipe_release(struct inode *inode) | |||
745 | struct rpc_inode *rpci = RPC_I(inode); | 745 | struct rpc_inode *rpci = RPC_I(inode); |
746 | struct gss_upcall_msg *gss_msg; | 746 | struct gss_upcall_msg *gss_msg; |
747 | 747 | ||
748 | restart: | ||
748 | spin_lock(&inode->i_lock); | 749 | spin_lock(&inode->i_lock); |
749 | while (!list_empty(&rpci->in_downcall)) { | 750 | list_for_each_entry(gss_msg, &rpci->in_downcall, list) { |
750 | 751 | ||
751 | gss_msg = list_entry(rpci->in_downcall.next, | 752 | if (!list_empty(&gss_msg->msg.list)) |
752 | struct gss_upcall_msg, list); | 753 | continue; |
753 | gss_msg->msg.errno = -EPIPE; | 754 | gss_msg->msg.errno = -EPIPE; |
754 | atomic_inc(&gss_msg->count); | 755 | atomic_inc(&gss_msg->count); |
755 | __gss_unhash_msg(gss_msg); | 756 | __gss_unhash_msg(gss_msg); |
756 | spin_unlock(&inode->i_lock); | 757 | spin_unlock(&inode->i_lock); |
757 | gss_release_msg(gss_msg); | 758 | gss_release_msg(gss_msg); |
758 | spin_lock(&inode->i_lock); | 759 | goto restart; |
759 | } | 760 | } |
760 | spin_unlock(&inode->i_lock); | 761 | spin_unlock(&inode->i_lock); |
761 | 762 | ||
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 032644610524..778e5dfc5144 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c | |||
@@ -237,6 +237,7 @@ get_key(const void *p, const void *end, | |||
237 | if (!supported_gss_krb5_enctype(alg)) { | 237 | if (!supported_gss_krb5_enctype(alg)) { |
238 | printk(KERN_WARNING "gss_kerberos_mech: unsupported " | 238 | printk(KERN_WARNING "gss_kerberos_mech: unsupported " |
239 | "encryption key algorithm %d\n", alg); | 239 | "encryption key algorithm %d\n", alg); |
240 | p = ERR_PTR(-EINVAL); | ||
240 | goto out_err; | 241 | goto out_err; |
241 | } | 242 | } |
242 | p = simple_get_netobj(p, end, &key); | 243 | p = simple_get_netobj(p, end, &key); |
@@ -282,15 +283,19 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx) | |||
282 | ctx->enctype = ENCTYPE_DES_CBC_RAW; | 283 | ctx->enctype = ENCTYPE_DES_CBC_RAW; |
283 | 284 | ||
284 | ctx->gk5e = get_gss_krb5_enctype(ctx->enctype); | 285 | ctx->gk5e = get_gss_krb5_enctype(ctx->enctype); |
285 | if (ctx->gk5e == NULL) | 286 | if (ctx->gk5e == NULL) { |
287 | p = ERR_PTR(-EINVAL); | ||
286 | goto out_err; | 288 | goto out_err; |
289 | } | ||
287 | 290 | ||
288 | /* The downcall format was designed before we completely understood | 291 | /* The downcall format was designed before we completely understood |
289 | * the uses of the context fields; so it includes some stuff we | 292 | * the uses of the context fields; so it includes some stuff we |
290 | * just give some minimal sanity-checking, and some we ignore | 293 | * just give some minimal sanity-checking, and some we ignore |
291 | * completely (like the next twenty bytes): */ | 294 | * completely (like the next twenty bytes): */ |
292 | if (unlikely(p + 20 > end || p + 20 < p)) | 295 | if (unlikely(p + 20 > end || p + 20 < p)) { |
296 | p = ERR_PTR(-EFAULT); | ||
293 | goto out_err; | 297 | goto out_err; |
298 | } | ||
294 | p += 20; | 299 | p += 20; |
295 | p = simple_get_bytes(p, end, &tmp, sizeof(tmp)); | 300 | p = simple_get_bytes(p, end, &tmp, sizeof(tmp)); |
296 | if (IS_ERR(p)) | 301 | if (IS_ERR(p)) |
@@ -619,6 +624,7 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, | |||
619 | if (ctx->seq_send64 != ctx->seq_send) { | 624 | if (ctx->seq_send64 != ctx->seq_send) { |
620 | dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__, | 625 | dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__, |
621 | (long unsigned)ctx->seq_send64, ctx->seq_send); | 626 | (long unsigned)ctx->seq_send64, ctx->seq_send); |
627 | p = ERR_PTR(-EINVAL); | ||
622 | goto out_err; | 628 | goto out_err; |
623 | } | 629 | } |
624 | p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype)); | 630 | p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype)); |
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c index dc3f1f5ed865..adade3d313f2 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_mech.c +++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c | |||
@@ -100,6 +100,7 @@ gss_import_sec_context_spkm3(const void *p, size_t len, | |||
100 | if (version != 1) { | 100 | if (version != 1) { |
101 | dprintk("RPC: unknown spkm3 token format: " | 101 | dprintk("RPC: unknown spkm3 token format: " |
102 | "obsolete nfs-utils?\n"); | 102 | "obsolete nfs-utils?\n"); |
103 | p = ERR_PTR(-EINVAL); | ||
103 | goto out_err_free_ctx; | 104 | goto out_err_free_ctx; |
104 | } | 105 | } |
105 | 106 | ||
@@ -135,8 +136,10 @@ gss_import_sec_context_spkm3(const void *p, size_t len, | |||
135 | if (IS_ERR(p)) | 136 | if (IS_ERR(p)) |
136 | goto out_err_free_intg_alg; | 137 | goto out_err_free_intg_alg; |
137 | 138 | ||
138 | if (p != end) | 139 | if (p != end) { |
140 | p = ERR_PTR(-EFAULT); | ||
139 | goto out_err_free_intg_key; | 141 | goto out_err_free_intg_key; |
142 | } | ||
140 | 143 | ||
141 | ctx_id->internal_ctx_id = ctx; | 144 | ctx_id->internal_ctx_id = ctx; |
142 | 145 | ||
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 2388d83b68ff..fa5549079d79 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -226,7 +226,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
226 | goto out_no_principal; | 226 | goto out_no_principal; |
227 | } | 227 | } |
228 | 228 | ||
229 | kref_init(&clnt->cl_kref); | 229 | atomic_set(&clnt->cl_count, 1); |
230 | 230 | ||
231 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name); | 231 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name); |
232 | if (err < 0) | 232 | if (err < 0) |
@@ -390,14 +390,14 @@ rpc_clone_client(struct rpc_clnt *clnt) | |||
390 | if (new->cl_principal == NULL) | 390 | if (new->cl_principal == NULL) |
391 | goto out_no_principal; | 391 | goto out_no_principal; |
392 | } | 392 | } |
393 | kref_init(&new->cl_kref); | 393 | atomic_set(&new->cl_count, 1); |
394 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); | 394 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); |
395 | if (err != 0) | 395 | if (err != 0) |
396 | goto out_no_path; | 396 | goto out_no_path; |
397 | if (new->cl_auth) | 397 | if (new->cl_auth) |
398 | atomic_inc(&new->cl_auth->au_count); | 398 | atomic_inc(&new->cl_auth->au_count); |
399 | xprt_get(clnt->cl_xprt); | 399 | xprt_get(clnt->cl_xprt); |
400 | kref_get(&clnt->cl_kref); | 400 | atomic_inc(&clnt->cl_count); |
401 | rpc_register_client(new); | 401 | rpc_register_client(new); |
402 | rpciod_up(); | 402 | rpciod_up(); |
403 | return new; | 403 | return new; |
@@ -465,10 +465,8 @@ EXPORT_SYMBOL_GPL(rpc_shutdown_client); | |||
465 | * Free an RPC client | 465 | * Free an RPC client |
466 | */ | 466 | */ |
467 | static void | 467 | static void |
468 | rpc_free_client(struct kref *kref) | 468 | rpc_free_client(struct rpc_clnt *clnt) |
469 | { | 469 | { |
470 | struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref); | ||
471 | |||
472 | dprintk("RPC: destroying %s client for %s\n", | 470 | dprintk("RPC: destroying %s client for %s\n", |
473 | clnt->cl_protname, clnt->cl_server); | 471 | clnt->cl_protname, clnt->cl_server); |
474 | if (!IS_ERR(clnt->cl_path.dentry)) { | 472 | if (!IS_ERR(clnt->cl_path.dentry)) { |
@@ -495,12 +493,10 @@ out_free: | |||
495 | * Free an RPC client | 493 | * Free an RPC client |
496 | */ | 494 | */ |
497 | static void | 495 | static void |
498 | rpc_free_auth(struct kref *kref) | 496 | rpc_free_auth(struct rpc_clnt *clnt) |
499 | { | 497 | { |
500 | struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref); | ||
501 | |||
502 | if (clnt->cl_auth == NULL) { | 498 | if (clnt->cl_auth == NULL) { |
503 | rpc_free_client(kref); | 499 | rpc_free_client(clnt); |
504 | return; | 500 | return; |
505 | } | 501 | } |
506 | 502 | ||
@@ -509,10 +505,11 @@ rpc_free_auth(struct kref *kref) | |||
509 | * release remaining GSS contexts. This mechanism ensures | 505 | * release remaining GSS contexts. This mechanism ensures |
510 | * that it can do so safely. | 506 | * that it can do so safely. |
511 | */ | 507 | */ |
512 | kref_init(kref); | 508 | atomic_inc(&clnt->cl_count); |
513 | rpcauth_release(clnt->cl_auth); | 509 | rpcauth_release(clnt->cl_auth); |
514 | clnt->cl_auth = NULL; | 510 | clnt->cl_auth = NULL; |
515 | kref_put(kref, rpc_free_client); | 511 | if (atomic_dec_and_test(&clnt->cl_count)) |
512 | rpc_free_client(clnt); | ||
516 | } | 513 | } |
517 | 514 | ||
518 | /* | 515 | /* |
@@ -525,7 +522,8 @@ rpc_release_client(struct rpc_clnt *clnt) | |||
525 | 522 | ||
526 | if (list_empty(&clnt->cl_tasks)) | 523 | if (list_empty(&clnt->cl_tasks)) |
527 | wake_up(&destroy_wait); | 524 | wake_up(&destroy_wait); |
528 | kref_put(&clnt->cl_kref, rpc_free_auth); | 525 | if (atomic_dec_and_test(&clnt->cl_count)) |
526 | rpc_free_auth(clnt); | ||
529 | } | 527 | } |
530 | 528 | ||
531 | /** | 529 | /** |
@@ -588,7 +586,7 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt) | |||
588 | if (clnt != NULL) { | 586 | if (clnt != NULL) { |
589 | rpc_task_release_client(task); | 587 | rpc_task_release_client(task); |
590 | task->tk_client = clnt; | 588 | task->tk_client = clnt; |
591 | kref_get(&clnt->cl_kref); | 589 | atomic_inc(&clnt->cl_count); |
592 | if (clnt->cl_softrtry) | 590 | if (clnt->cl_softrtry) |
593 | task->tk_flags |= RPC_TASK_SOFT; | 591 | task->tk_flags |= RPC_TASK_SOFT; |
594 | /* Add to the client's list of all tasks */ | 592 | /* Add to the client's list of all tasks */ |
@@ -931,7 +929,7 @@ call_reserveresult(struct rpc_task *task) | |||
931 | task->tk_status = 0; | 929 | task->tk_status = 0; |
932 | if (status >= 0) { | 930 | if (status >= 0) { |
933 | if (task->tk_rqstp) { | 931 | if (task->tk_rqstp) { |
934 | task->tk_action = call_allocate; | 932 | task->tk_action = call_refresh; |
935 | return; | 933 | return; |
936 | } | 934 | } |
937 | 935 | ||
@@ -966,13 +964,54 @@ call_reserveresult(struct rpc_task *task) | |||
966 | } | 964 | } |
967 | 965 | ||
968 | /* | 966 | /* |
969 | * 2. Allocate the buffer. For details, see sched.c:rpc_malloc. | 967 | * 2. Bind and/or refresh the credentials |
968 | */ | ||
969 | static void | ||
970 | call_refresh(struct rpc_task *task) | ||
971 | { | ||
972 | dprint_status(task); | ||
973 | |||
974 | task->tk_action = call_refreshresult; | ||
975 | task->tk_status = 0; | ||
976 | task->tk_client->cl_stats->rpcauthrefresh++; | ||
977 | rpcauth_refreshcred(task); | ||
978 | } | ||
979 | |||
980 | /* | ||
981 | * 2a. Process the results of a credential refresh | ||
982 | */ | ||
983 | static void | ||
984 | call_refreshresult(struct rpc_task *task) | ||
985 | { | ||
986 | int status = task->tk_status; | ||
987 | |||
988 | dprint_status(task); | ||
989 | |||
990 | task->tk_status = 0; | ||
991 | task->tk_action = call_allocate; | ||
992 | if (status >= 0 && rpcauth_uptodatecred(task)) | ||
993 | return; | ||
994 | switch (status) { | ||
995 | case -EACCES: | ||
996 | rpc_exit(task, -EACCES); | ||
997 | return; | ||
998 | case -ENOMEM: | ||
999 | rpc_exit(task, -ENOMEM); | ||
1000 | return; | ||
1001 | case -ETIMEDOUT: | ||
1002 | rpc_delay(task, 3*HZ); | ||
1003 | } | ||
1004 | task->tk_action = call_refresh; | ||
1005 | } | ||
1006 | |||
1007 | /* | ||
1008 | * 2b. Allocate the buffer. For details, see sched.c:rpc_malloc. | ||
970 | * (Note: buffer memory is freed in xprt_release). | 1009 | * (Note: buffer memory is freed in xprt_release). |
971 | */ | 1010 | */ |
972 | static void | 1011 | static void |
973 | call_allocate(struct rpc_task *task) | 1012 | call_allocate(struct rpc_task *task) |
974 | { | 1013 | { |
975 | unsigned int slack = task->tk_client->cl_auth->au_cslack; | 1014 | unsigned int slack = task->tk_rqstp->rq_cred->cr_auth->au_cslack; |
976 | struct rpc_rqst *req = task->tk_rqstp; | 1015 | struct rpc_rqst *req = task->tk_rqstp; |
977 | struct rpc_xprt *xprt = task->tk_xprt; | 1016 | struct rpc_xprt *xprt = task->tk_xprt; |
978 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; | 1017 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; |
@@ -980,7 +1019,7 @@ call_allocate(struct rpc_task *task) | |||
980 | dprint_status(task); | 1019 | dprint_status(task); |
981 | 1020 | ||
982 | task->tk_status = 0; | 1021 | task->tk_status = 0; |
983 | task->tk_action = call_refresh; | 1022 | task->tk_action = call_bind; |
984 | 1023 | ||
985 | if (req->rq_buffer) | 1024 | if (req->rq_buffer) |
986 | return; | 1025 | return; |
@@ -1017,47 +1056,6 @@ call_allocate(struct rpc_task *task) | |||
1017 | rpc_exit(task, -ERESTARTSYS); | 1056 | rpc_exit(task, -ERESTARTSYS); |
1018 | } | 1057 | } |
1019 | 1058 | ||
1020 | /* | ||
1021 | * 2a. Bind and/or refresh the credentials | ||
1022 | */ | ||
1023 | static void | ||
1024 | call_refresh(struct rpc_task *task) | ||
1025 | { | ||
1026 | dprint_status(task); | ||
1027 | |||
1028 | task->tk_action = call_refreshresult; | ||
1029 | task->tk_status = 0; | ||
1030 | task->tk_client->cl_stats->rpcauthrefresh++; | ||
1031 | rpcauth_refreshcred(task); | ||
1032 | } | ||
1033 | |||
1034 | /* | ||
1035 | * 2b. Process the results of a credential refresh | ||
1036 | */ | ||
1037 | static void | ||
1038 | call_refreshresult(struct rpc_task *task) | ||
1039 | { | ||
1040 | int status = task->tk_status; | ||
1041 | |||
1042 | dprint_status(task); | ||
1043 | |||
1044 | task->tk_status = 0; | ||
1045 | task->tk_action = call_bind; | ||
1046 | if (status >= 0 && rpcauth_uptodatecred(task)) | ||
1047 | return; | ||
1048 | switch (status) { | ||
1049 | case -EACCES: | ||
1050 | rpc_exit(task, -EACCES); | ||
1051 | return; | ||
1052 | case -ENOMEM: | ||
1053 | rpc_exit(task, -ENOMEM); | ||
1054 | return; | ||
1055 | case -ETIMEDOUT: | ||
1056 | rpc_delay(task, 3*HZ); | ||
1057 | } | ||
1058 | task->tk_action = call_refresh; | ||
1059 | } | ||
1060 | |||
1061 | static inline int | 1059 | static inline int |
1062 | rpc_task_need_encode(struct rpc_task *task) | 1060 | rpc_task_need_encode(struct rpc_task *task) |
1063 | { | 1061 | { |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 95ccbcf45d3e..8c8eef2b8f26 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -48,7 +48,7 @@ static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, | |||
48 | return; | 48 | return; |
49 | do { | 49 | do { |
50 | msg = list_entry(head->next, struct rpc_pipe_msg, list); | 50 | msg = list_entry(head->next, struct rpc_pipe_msg, list); |
51 | list_del(&msg->list); | 51 | list_del_init(&msg->list); |
52 | msg->errno = err; | 52 | msg->errno = err; |
53 | destroy_msg(msg); | 53 | destroy_msg(msg); |
54 | } while (!list_empty(head)); | 54 | } while (!list_empty(head)); |
@@ -208,7 +208,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp) | |||
208 | if (msg != NULL) { | 208 | if (msg != NULL) { |
209 | spin_lock(&inode->i_lock); | 209 | spin_lock(&inode->i_lock); |
210 | msg->errno = -EAGAIN; | 210 | msg->errno = -EAGAIN; |
211 | list_del(&msg->list); | 211 | list_del_init(&msg->list); |
212 | spin_unlock(&inode->i_lock); | 212 | spin_unlock(&inode->i_lock); |
213 | rpci->ops->destroy_msg(msg); | 213 | rpci->ops->destroy_msg(msg); |
214 | } | 214 | } |
@@ -268,7 +268,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) | |||
268 | if (res < 0 || msg->len == msg->copied) { | 268 | if (res < 0 || msg->len == msg->copied) { |
269 | filp->private_data = NULL; | 269 | filp->private_data = NULL; |
270 | spin_lock(&inode->i_lock); | 270 | spin_lock(&inode->i_lock); |
271 | list_del(&msg->list); | 271 | list_del_init(&msg->list); |
272 | spin_unlock(&inode->i_lock); | 272 | spin_unlock(&inode->i_lock); |
273 | rpci->ops->destroy_msg(msg); | 273 | rpci->ops->destroy_msg(msg); |
274 | } | 274 | } |
@@ -371,21 +371,23 @@ rpc_show_info(struct seq_file *m, void *v) | |||
371 | static int | 371 | static int |
372 | rpc_info_open(struct inode *inode, struct file *file) | 372 | rpc_info_open(struct inode *inode, struct file *file) |
373 | { | 373 | { |
374 | struct rpc_clnt *clnt; | 374 | struct rpc_clnt *clnt = NULL; |
375 | int ret = single_open(file, rpc_show_info, NULL); | 375 | int ret = single_open(file, rpc_show_info, NULL); |
376 | 376 | ||
377 | if (!ret) { | 377 | if (!ret) { |
378 | struct seq_file *m = file->private_data; | 378 | struct seq_file *m = file->private_data; |
379 | mutex_lock(&inode->i_mutex); | 379 | |
380 | clnt = RPC_I(inode)->private; | 380 | spin_lock(&file->f_path.dentry->d_lock); |
381 | if (clnt) { | 381 | if (!d_unhashed(file->f_path.dentry)) |
382 | kref_get(&clnt->cl_kref); | 382 | clnt = RPC_I(inode)->private; |
383 | if (clnt != NULL && atomic_inc_not_zero(&clnt->cl_count)) { | ||
384 | spin_unlock(&file->f_path.dentry->d_lock); | ||
383 | m->private = clnt; | 385 | m->private = clnt; |
384 | } else { | 386 | } else { |
387 | spin_unlock(&file->f_path.dentry->d_lock); | ||
385 | single_release(inode, file); | 388 | single_release(inode, file); |
386 | ret = -EINVAL; | 389 | ret = -EINVAL; |
387 | } | 390 | } |
388 | mutex_unlock(&inode->i_mutex); | ||
389 | } | 391 | } |
390 | return ret; | 392 | return ret; |
391 | } | 393 | } |