diff options
Diffstat (limited to 'drivers/char')
164 files changed, 10927 insertions, 5517 deletions
diff --git a/drivers/char/ChangeLog b/drivers/char/ChangeLog deleted file mode 100644 index 56b8a2e76ab1..000000000000 --- a/drivers/char/ChangeLog +++ /dev/null | |||
@@ -1,775 +0,0 @@ | |||
1 | 2001-08-11 Tim Waugh <twaugh@redhat.com> | ||
2 | |||
3 | * serial.c (get_pci_port): Deal with awkward Titan cards. | ||
4 | |||
5 | 1998-08-26 Theodore Ts'o <tytso@rsts-11.mit.edu> | ||
6 | |||
7 | * serial.c (rs_open): Correctly decrement the module in-use count | ||
8 | on errors. | ||
9 | |||
10 | Thu Feb 19 14:24:08 1998 Theodore Ts'o <tytso@rsts-11.mit.edu> | ||
11 | |||
12 | * tty_io.c (tty_name): Remove the non-reentrant (and non-SMP safe) | ||
13 | version of tty_name, and rename the reentrant _tty_name | ||
14 | function to be tty_name. | ||
15 | (tty_open): Add a warning message stating callout devices | ||
16 | are deprecated. | ||
17 | |||
18 | Mon Dec 1 08:24:15 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> | ||
19 | |||
20 | * tty_io.c (tty_get_baud_rate): Print a warning syslog if the | ||
21 | tty->alt_speed kludge is used; this means the system is | ||
22 | using the deprecated SPD_HI ioctls. | ||
23 | |||
24 | Mon Nov 24 10:37:49 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> | ||
25 | |||
26 | * serial.c, esp.c, rocket.c: Change drivers to take advantage of | ||
27 | tty_get_baud_rate(). | ||
28 | |||
29 | * tty_io.c (tty_get_baud_rate): New function which computes the | ||
30 | correct baud rate for the tty. More factoring out of | ||
31 | common code out of the serial driver to the high-level tty | ||
32 | functions.... | ||
33 | |||
34 | Sat Nov 22 07:53:36 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> | ||
35 | |||
36 | * serial.c, esp.c, rocket.c: Add tty->driver.break() routine, and | ||
37 | allow high-level tty code to handle the break and soft | ||
38 | carrier ioctls. | ||
39 | |||
40 | * tty_ioctl.c (n_tty_ioctl): Support TIOCGSOFTCAR and | ||
41 | TIOCSSOFTCAR, so that device drivers don't have to support | ||
42 | it. | ||
43 | |||
44 | * serial.c (autoconfig): Change 16750 test to hopefully eliminate | ||
45 | false results by people with strange 16550As being | ||
46 | detected as 16750s. Hopefully 16750s will still be | ||
47 | detected as 16750, and other weird UARTs won't get poorly | ||
48 | autodetected. If this doesn't work, I'll have to disable | ||
49 | the auto identification for the 16750. | ||
50 | |||
51 | * tty_io.c (tty_hangup): Now actually do the tty hangup | ||
52 | processing during the timer processing, and disable | ||
53 | interrupts while doing the hangup processing. This avoids | ||
54 | several nasty race conditions which happened when the | ||
55 | hangup processing was done asynchronously. | ||
56 | (tty_ioctl): Do break handling in the tty driver if | ||
57 | driver's break function is supported. | ||
58 | (tty_flip_buffer_push): New exported function which should | ||
59 | be used by drivers to push characters in the flip buffer | ||
60 | to the tty handler. This may either be done using a task | ||
61 | queue function for better CPU efficiency, or directly for | ||
62 | low latency operation. | ||
63 | |||
64 | * serial.c (rs_set_termios): Fix bug rs_set_termios when | ||
65 | transitioning away from B0, submitted by Stanislav | ||
66 | Voronyi. | ||
67 | |||
68 | Thu Jun 19 20:05:58 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> | ||
69 | |||
70 | * serial.c (begin_break, end_break, rs_ioctl): Applied patch | ||
71 | to support BSD ioctls to set and clear the break | ||
72 | condition explicitly. | ||
73 | |||
74 | * console.c (scrup, scrdown, insert_line, delete_line): Applied | ||
75 | fix suggested by Aaron Tiensivu to speed up block scrolls | ||
76 | up and down. | ||
77 | |||
78 | * n_tty.c (opost_block, write_chan): Added a modified "fast | ||
79 | console" patch which processes a block of text via | ||
80 | "cooking" efficiently. | ||
81 | |||
82 | Wed Jun 18 15:25:50 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> | ||
83 | |||
84 | * tty_io.c (init_dev, release_dev): Applied fix suggested by Bill | ||
85 | Hawes to prevent race conditions in the tty code. | ||
86 | |||
87 | * n_tty.c (n_tty_chars_in_buffer): Applied fix suggested by Bill | ||
88 | Hawes so that n_tty_chars_in_buffer returns the correct | ||
89 | value in the case when the tty is in cannonical mode. (To | ||
90 | avoid a pty deadlock with telnetd.) | ||
91 | |||
92 | Thu Feb 27 01:53:08 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> | ||
93 | |||
94 | * serial.c (change_speed): Add support for the termios flag | ||
95 | CMSPAR, which allows the user to select stick parity. | ||
96 | (i.e, if PARODD is set, the parity bit is always 1; if | ||
97 | PARRODD is not set, then the parity bit is always 0). | ||
98 | |||
99 | Wed Feb 26 19:03:10 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> | ||
100 | |||
101 | * serial.c (cleanup_module): Fix memory leak when using the serial | ||
102 | driver as a module; make sure tmp_buf gets freed! | ||
103 | |||
104 | Tue Feb 25 11:01:59 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> | ||
105 | |||
106 | * serial.c (set_modem_info): Add support for setting and clearing | ||
107 | the OUT1 and OUT2 bits. (For special case UART's, usually | ||
108 | for half-duplex.) | ||
109 | (autoconfig, change_speed): Fix TI 16750 support. | ||
110 | |||
111 | Sun Feb 16 00:14:43 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> | ||
112 | |||
113 | * tty_io.c (release_dev): Add sanity check to make sure there are | ||
114 | no waiters on tty->read_wait or tty->write_wait. | ||
115 | |||
116 | * serial.c (rs_init): Don't autoconfig a device if the I/O region | ||
117 | is already reserved. | ||
118 | |||
119 | * serial.c (serial_proc_info): Add support for /proc/serial. | ||
120 | |||
121 | Thu Feb 13 00:49:10 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> | ||
122 | |||
123 | * serial.c (receive_chars): When the UART repotrs an overrun | ||
124 | condition, it does so with a valid character. Changed to | ||
125 | not throw away the valid character, but instead report the | ||
126 | overrun after the valid character. | ||
127 | |||
128 | * serial.c: Added new #ifdef's for some of the advanced serial | ||
129 | driver features. A minimal driver that only supports COM | ||
130 | 1/2/3/4 without sharing serial interrupts only takes 17k; | ||
131 | the full driver takes 32k. | ||
132 | |||
133 | Wed Feb 12 14:50:44 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> | ||
134 | |||
135 | * vt.c: | ||
136 | * pty.c: | ||
137 | * tty_ioctl.c: | ||
138 | * serial.c: Update routines to use the new 2.1 memory access | ||
139 | routines. | ||
140 | |||
141 | Wed Dec 4 07:51:52 1996 Theodore Ts'o <tytso@localhost.mit.edu> | ||
142 | |||
143 | * serial.c (change_speed): Use save_flags(); cli() and | ||
144 | restore_flags() in order to ensure we don't accidentally | ||
145 | turn on interrupts when starting up the port. | ||
146 | (startup): Move the insertion of serial structure into the | ||
147 | IRQ chain earlier into the startup processing. Interrupts | ||
148 | should be off this whole time, but we eventually will want | ||
149 | to reduce this window. | ||
150 | |||
151 | Thu Nov 21 10:05:22 1996 Theodore Ts'o <tytso@localhost.mit.edu> | ||
152 | |||
153 | * tty_ioctl.c (tty_wait_until_sent): Always check the driver | ||
154 | wait_until_ready routine, even if there are no characters | ||
155 | in the xmit buffer. (There may be charactes in the device | ||
156 | FIFO.) | ||
157 | (n_tty_ioctl): Add new flag tty->flow_stopped which | ||
158 | indicates whether the tty is stopped due to a request by | ||
159 | the TCXONC ioctl (used by tcflow). If so, don't let an | ||
160 | incoming XOFF character restart the tty. The tty can only | ||
161 | be restarted by another TCXONC request. | ||
162 | |||
163 | * tty_io.c (start_tty): Don't allow the tty to be restarted if | ||
164 | tty->flow_stopped is true. | ||
165 | |||
166 | * n_tty.c (n_tty_receive_char): If tty->flow_stopped is true, and | ||
167 | IXANY is set, don't eat a character trying to restart the | ||
168 | tty. | ||
169 | |||
170 | * serial.c (startup): Remove need for MCR_noint from the | ||
171 | async_struct structure. Only turn on DTR and RTS if the | ||
172 | baud rate is not zero. | ||
173 | (change_speed): More accurately calculate the timeout | ||
174 | value based on the word size. Move responsibility of | ||
175 | hangup when speed becomes B0 to rs_set_termios() | ||
176 | (set_serial_info): When changing the UART type set the | ||
177 | current xmit_fifo_size as well as the permanent | ||
178 | xmit_fifo_size. | ||
179 | (rs_ioctl): Fix TCSBRK (used by tcdrain) and TCSBRKP | ||
180 | ioctls to return EINTR if interrupted by a signal. | ||
181 | (rs_set_termios): If the baud rate changes to or from B0, | ||
182 | this function is now responsible for setting or clearing | ||
183 | DTR and RTS. DTR and RTS are only be changed on the | ||
184 | transition to or from the B0 state. | ||
185 | (rs_close): Wait for the characters to drain based on | ||
186 | info->timeout. At low baud rates (50 bps), it may take a | ||
187 | long time for the FIFO to completely drain out! | ||
188 | (rs_wait_until_sent): Fixed timeout handling. Now | ||
189 | releases control to the scheduler, but checks frequently | ||
190 | enough so that the function is sensitive enough to pass | ||
191 | the timing requirements of the NIST-PCTS. | ||
192 | (block_til_ready): When opening the device, don't turn on | ||
193 | DTR and RTS if the baud rate is B0. | ||
194 | |||
195 | Thu Nov 14 00:06:09 1996 Theodore Ts'o <tytso@rsts-11.mit.edu> | ||
196 | |||
197 | * serial.c (autoconfig): Fix autoconfiguration problems; | ||
198 | info->flags wasn't getting initialized from the state | ||
199 | structure. Put in more paranoid test for the 16750. | ||
200 | |||
201 | Fri Nov 8 20:19:50 1996 Theodore Ts'o <tytso@rsts-11.mit.edu> | ||
202 | |||
203 | * n_tty.c (n_tty_flush_buffer): Only call driver->unthrottle() if | ||
204 | the tty was previous throttled. | ||
205 | (n_tty_set_termios, write_chan): Add changes suggested by | ||
206 | Simon P. Allen to allow hardware cooking. | ||
207 | |||
208 | * tty_ioctl.c (set_termios): If we get a signal while waiting for | ||
209 | the tty to drain, return -EINTR. | ||
210 | |||
211 | * serial.c (change_speed): Add support for CREAD, as required by | ||
212 | POSIX. | ||
213 | |||
214 | Sat Nov 2 20:43:10 1996 Theodore Ts'o <tytso@rsts-11.mit.edu> | ||
215 | |||
216 | * serial.c: Wholesale changes. Added support for the Startech | ||
217 | 16650 and 16650V2 chips. (WARNING: the new startech | ||
218 | 16650A may or may not work!) Added support for the | ||
219 | TI16750 (not yet tested). Split async_struct into a | ||
220 | transient part (async_struct) and a permanent part | ||
221 | (serial_state) which contains the configuration | ||
222 | information for the ports. Added new driver routines | ||
223 | wait_until_sent() and send_xchar() to help with POSIX | ||
224 | compliance. Added support for radio clocks which waggle | ||
225 | the carrier detect line (CONFIG_HARD_PPS). | ||
226 | |||
227 | * tty_ioctl.c (tty_wait_until_sent): Added call to new driver | ||
228 | function tty->driver.wait_until_sent(), which returns when | ||
229 | the tty's device xmit buffers are drained. Needed for | ||
230 | full POSIX compliance. | ||
231 | |||
232 | (send_prio_char): New function, called by the ioctl's | ||
233 | TCIOFF and TCION; uses the new driver call send_xchar(), | ||
234 | which will send the XON or XOFF character at high priority | ||
235 | (and even if tty output is stopped). | ||
236 | |||
237 | Wed Jun 5 18:52:04 1996 Theodore Ts'o <tytso@rsts-11.mit.edu> | ||
238 | |||
239 | * pty.c (pty_close): When closing a pty, make sure packet mode is | ||
240 | cleared. | ||
241 | |||
242 | Sun May 26 09:33:52 1996 Theodore Ts'o <tytso@rsts-11.mit.edu> | ||
243 | |||
244 | * vesa_blank.c (set_vesa_blanking): Add missing verify_area() call. | ||
245 | |||
246 | * selection.c (set_selection): Add missing verify_area() call. | ||
247 | |||
248 | * tty_io.c (tty_ioctl): Add missing verify_area() calls. | ||
249 | |||
250 | * serial.c (rs_ioctl): Add missing verify_area() calls. | ||
251 | (rs_init): Allow initialization of serial driver | ||
252 | configuration from a module. | ||
253 | |||
254 | * random.c (extract_entropy): Add missing verify_area call. | ||
255 | Don't limit number of characters returned to | ||
256 | 32,768. Extract entropy is now no longer a inlined | ||
257 | function. | ||
258 | |||
259 | (random_read): Check return value in case extract_entropy | ||
260 | returns an error. | ||
261 | |||
262 | (secure_tcp_sequence_number): New function which returns a | ||
263 | secure TCP sequence number. This is needed to prevent some | ||
264 | nasty TCP hijacking attacks. | ||
265 | |||
266 | (init_std_data): Initialize using gettimeofday() instead of | ||
267 | struct timeval xtime. | ||
268 | |||
269 | (fast_add_entropy_word, add_entropy_word): Rename the | ||
270 | inline function add_entropy_word() to | ||
271 | fast_add_entropy_word(). Make add_entropy_word() be the | ||
272 | non-inlined function which is used in non-timing critical | ||
273 | places, in order to save space. | ||
274 | |||
275 | (initialize_benchmark, begin_benchmark, end_benchmark): New | ||
276 | functions defined when RANDOM_BENCHMARK is defined. They | ||
277 | allow us to benchmark the speed of the | ||
278 | add_timer_randomness() call. | ||
279 | |||
280 | (int_ln, rotate_left): Add two new inline functions with | ||
281 | i386 optimized asm instructions. This speeds up the | ||
282 | critical add_entropy_word() and add_timer_randomness() | ||
283 | functions, which are called from interrupt handlers. | ||
284 | |||
285 | Tue May 7 22:51:11 1996 <tytso@rsts-11.mit.edu> | ||
286 | |||
287 | * random.c (add_timer_randomness): Limit the amount randomness | ||
288 | that we estimate to 12 bits. (An arbitrary amount). | ||
289 | |||
290 | (extract_entropy): To make it harder to analyze the hash | ||
291 | function, fold the hash function in half using XOR, and | ||
292 | use the folded result as the value to emit to the user. | ||
293 | Also, add timer randomness each pass through the | ||
294 | exact_entropy call, to increase the amount of unknown | ||
295 | values during the extraction process. | ||
296 | |||
297 | (random_ioctl): Use IOR/IOW definitions to define the | ||
298 | ioctl values used by the /dev/random driver. Allow the | ||
299 | old ioctl values to be used for backwards compatibility | ||
300 | (for a limited amount of time). | ||
301 | |||
302 | Wed Apr 24 14:02:04 1996 Theodore Ts'o <tytso@rsts-11.mit.edu> | ||
303 | |||
304 | * random.c (add_timer_randomness): Use 2nd derivative as well to | ||
305 | better estimate entropy. | ||
306 | |||
307 | (rand_initialize): Explicitly initialize all the pointers | ||
308 | to NULL. (Clearing pointers using memset isn't portable.) | ||
309 | Initialize the random pool with OS-dependent data. | ||
310 | |||
311 | (random_write): Add sanity checking to the arguments to | ||
312 | random_write(), so that bad arguments won't cause a kernel | ||
313 | SEGV. | ||
314 | |||
315 | (random_read): Update the access time of the device inode | ||
316 | when you return data to the user. | ||
317 | |||
318 | (random_ioctl): Wake up the random_wait channel when there | ||
319 | are only WAIT_INPUT_BITS available. Add more paranoia | ||
320 | checks to make sure entropy_count doesn't go beyond the | ||
321 | bounds of (0, POOLSIZE). Add a few missing verify_area | ||
322 | checks. Add support for the RNDCLEARPOOL ioctl, which | ||
323 | zaps the random pool. | ||
324 | |||
325 | (add_timer_randomness): Wake up the random_wait | ||
326 | channel only when there are WAIT_INPUT_BITS available. | ||
327 | |||
328 | (random_select): Allow a random refresh daemon process to | ||
329 | select on /dev/random for writing; wake up the daemon when | ||
330 | there are less than WAIT_OUTPUT_BITS bits of randomness | ||
331 | available. | ||
332 | |||
333 | Tue Apr 23 22:56:07 1996 <tytso@rsts-11.mit.edu> | ||
334 | |||
335 | * tty_io.c (init_dev): Change return code when user attempts to | ||
336 | open master pty which is already open from EAGAIN to EIO, | ||
337 | to match with BSD expectations. EIO is more correct | ||
338 | anyway, since EAGAIN implies that retrying will be | ||
339 | successful --- which it might be.... Eventually!! | ||
340 | |||
341 | * pty.c (pty_open, pty_close): Fix wait loop so that we don't | ||
342 | busy loop while waiting for the master side to open. | ||
343 | Fix tty opening/closing logic. TTY_SLAVE_CLOSED was | ||
344 | renamed to TTY_OTHER_CLOSED, so that the name is more | ||
345 | descriptive. Also fixed code so that the tty flag | ||
346 | actually works correctly now.... | ||
347 | |||
348 | Mon Apr 1 10:22:01 1996 <tytso@rsts-11.mit.edu> | ||
349 | |||
350 | * serial.c (rs_close): Cleaned up modularization changes. | ||
351 | Remove code which forced line discipline back to N_TTY | ||
352 | this is done in the tty upper layers, and there's no | ||
353 | reason to do it here. (Making this change also | ||
354 | removed the requirement that the serial module access | ||
355 | the internal kernel symbol "ldiscs".) | ||
356 | |||
357 | * tty_io.c (tty_init): Formally register a tty_driver entry for | ||
358 | /dev/tty (device 4, 0) and /dev/console (device 5, 0). | ||
359 | This guarantees that major device numbers 4 and 5 will be | ||
360 | reserved for the tty subsystem (as they have to be because | ||
361 | of /dev/tty and /dev/console). Removed tty_regdev, as | ||
362 | this interface is no longer necessary. | ||
363 | |||
364 | Sun Mar 17 20:42:47 GMT 1996 <ah@doc.ic.ac.uk> | ||
365 | |||
366 | * serial.c : modularisation (changes in linux/fs/device.c allow | ||
367 | kerneld to automatically load the serial module). | ||
368 | |||
369 | * Makefile, Config.in : serial modularisation adds. | ||
370 | |||
371 | * tty_io.c : tty_init_ctty used by to register "cua" driver just | ||
372 | for the /dev/tty device (5,0). Added tty_regdev. | ||
373 | |||
374 | * serial.c (shutdown, rs_ioctl) : when port shuts down wakeup processes | ||
375 | waiting on delta_msr_wait. The TIOCMIWAIT ioctl returns EIO | ||
376 | if no change was done since the time of call. | ||
377 | |||
378 | Sat Mar 16 14:33:13 1996 <aeb@cwi.nl> | ||
379 | |||
380 | * tty_io.c (disassociate_ctty): If disassociate_ctty is called by | ||
381 | exit, do not perform an implicit vhangup on a pty. | ||
382 | |||
383 | Fri Feb 9 14:15:47 1996 <tytso@rsts-11.mit.edu> | ||
384 | |||
385 | * serial.c (block_til_ready): Fixed another race condition which | ||
386 | happens if a hangup happens during the open. | ||
387 | |||
388 | Wed Jan 10 10:08:00 1996 <tytso@rsts-11.mit.edu> | ||
389 | |||
390 | * serial.c (block_til_ready): Remove race condition which happened | ||
391 | if a hangup condition happened during the setup of the | ||
392 | UART, before rs_open() called block_til_ready(). This | ||
393 | caused the info->count counter to be erroneously | ||
394 | decremented. | ||
395 | |||
396 | * serial.c (startup, rs_open): Remove race condition that could | ||
397 | cause a memory leak of one page. (Fortunately, both race | ||
398 | conditions were relatively rare in practice.) | ||
399 | |||
400 | Tue Dec 5 13:21:27 1995 <tytso@rsts-11.mit.edu> | ||
401 | |||
402 | * serial.c (check_modem_status, rs_ioctl): Support the new | ||
403 | ioctl()'s TIOCGICOUNT, TIOCMIWAIT. These allow an | ||
404 | application program to wait on a modem serial register | ||
405 | status bit change, and to find out how many changes have | ||
406 | taken place for the MSR bits. | ||
407 | |||
408 | (rs_write): Eliminate a race condition which is introduced | ||
409 | if it is necessary to wait for the semaphore. | ||
410 | |||
411 | Sat Nov 4 17:14:45 1995 <tytso@rsts-11.mit.edu> | ||
412 | |||
413 | * tty_io.c (tty_init): Move registration of TTY_MAJOR and | ||
414 | TTY_AUX_MAJOR to the end, so that /proc/devices looks | ||
415 | prettier. | ||
416 | |||
417 | * pty.c (pty_init): Use new major numbers for PTY master and slave | ||
418 | devices. This allow us to have more than 64 pty's. We | ||
419 | register the old pty devices for backwards compatibility. | ||
420 | Note that a system should either be using the old pty | ||
421 | devices or the new pty devices --- in general, it should | ||
422 | try to use both, since they map into the same pty table. | ||
423 | The old pty devices are strictly for backwards compatibility. | ||
424 | |||
425 | Wed Oct 11 12:45:24 1995 <tytso@rsts-11.mit.edu> | ||
426 | |||
427 | * tty_io.c (disassociate_ctty): If disassociate_ctty is called by | ||
428 | exit, perform an implicit vhangup on the tty. | ||
429 | |||
430 | * pty.c (pty_close): When the master pty is closed, send a hangup | ||
431 | to the slave pty. | ||
432 | (pty_open): Use the flag TTY_SLAVE_CLOSED to test to see | ||
433 | if there are any open slave ptys, instead of using | ||
434 | tty->link->count. The old method got confused if there | ||
435 | were processes that had hung-up file descriptors on the | ||
436 | slave tty. | ||
437 | |||
438 | Tue May 2 00:53:25 1995 <tytso@rsx-11.mit.edu> | ||
439 | |||
440 | * tty_io.c (tty_set_ldisc): Wait until the output buffer is | ||
441 | drained before closing the old line discipline --- needed | ||
442 | in only one case: XON/XOFF processing. | ||
443 | |||
444 | * n_tty.c (n_tty_close): Don't bother waiting until the output | ||
445 | driver is closed; in general, the line discipline | ||
446 | shouldn't care if the hardware is finished | ||
447 | transmitting before the line discipline terminates. | ||
448 | |||
449 | * tty_io.c (release_dev): Shutdown the line discipline after | ||
450 | decrementing the tty count variable; but set the | ||
451 | TTY_CLOSING flag so that we know that this tty structure | ||
452 | isn't long for this world. | ||
453 | |||
454 | * tty_io.c (init_dev): Add sanity code to check to see if | ||
455 | TTY_CLOSING is set on a tty structure; if so, something | ||
456 | bad has happened (probably a line discipline close blocked | ||
457 | when it shouldn't have; so do a kernel printk and then | ||
458 | return an error). | ||
459 | |||
460 | Wed Apr 26 10:23:44 1995 Theodore Y. Ts'o <tytso@localhost> | ||
461 | |||
462 | * tty_io.c (release_dev): Try to shutdown the line discipline | ||
463 | *before* decrementing the tty count variable; this removes | ||
464 | a potential race condition which occurs when the line | ||
465 | discipline close blocks, and another process then tries | ||
466 | open the same serial port. | ||
467 | |||
468 | * serial.c (rs_hangup): When hanging up, flush the output buffer | ||
469 | before shutting down the UART. Otherwise the line | ||
470 | discipline close blocks waiting for the characters to get | ||
471 | flushed, which never happens until the serial port gets reused. | ||
472 | |||
473 | Wed Apr 12 08:06:16 1995 Theodore Y. Ts'o <tytso@localhost> | ||
474 | |||
475 | * serial.c (do_serial_hangup, do_softint, check_modem_status, | ||
476 | rs_init): Hangups are now scheduled via a separate tqueue | ||
477 | structure in the async_struct structure, tqueue_hangup. | ||
478 | This task is pushed on to the tq_schedule queue, so that | ||
479 | it is processed synchronously by the scheduler. | ||
480 | |||
481 | Sat Feb 18 12:13:51 1995 Theodore Y. Ts'o (tytso@rt-11) | ||
482 | |||
483 | * tty_io.c (disassociate_ctty, tty_open, tty_ioctl): Clear | ||
484 | current->tty_old_pgrp field when a session leader | ||
485 | acquires a controlling tty, and after a session leader | ||
486 | has disassociated from a controlling tty. | ||
487 | |||
488 | Fri Feb 17 09:34:09 1995 Theodore Y. Ts'o (tytso@rt-11) | ||
489 | |||
490 | * serial.c (rs_interrupt_single, rs_interrupt, rs_interrupt_multi): | ||
491 | Change the number of passes made from 64 to be 256, | ||
492 | configurable with the #define RS_ISR_PASS_LIMIT. | ||
493 | |||
494 | * serial.c (rs_init, set_serial_info, get_serial_info, rs_close): | ||
495 | Remove support for closing_wait2. Instead, set | ||
496 | tty->closing and rely on the line discipline to prevent | ||
497 | echo wars. | ||
498 | |||
499 | * n_tty.c (n_tty_receive_char): IEXTEN does not need to be | ||
500 | enabled in order for IXANY to be active. | ||
501 | |||
502 | If tty->closing is set, then only process XON and XOFF | ||
503 | characters. | ||
504 | |||
505 | Sun Feb 12 23:57:48 1995 Theodore Y. Ts'o (tytso@rt-11) | ||
506 | |||
507 | * serial.c (rs_timer): Change the interrupt poll time from 60 | ||
508 | seconds to 10 seconds, configurable with the #define | ||
509 | RS_STROBE_TIME. | ||
510 | |||
511 | * serial.c (rs_interrupt_multi, startup, shutdown, rs_ioctl, | ||
512 | set_multiport_struct, get_multiport_struct): Add | ||
513 | provisions for a new type of interrupt service routine, | ||
514 | which better supports multiple serial ports on a single | ||
515 | IRQ. | ||
516 | |||
517 | Sun Feb 5 19:35:11 1995 Theodore Y. Ts'o (tytso@rt-11) | ||
518 | |||
519 | * tty_ioctl.c (n_tty_ioctl, set_termios, tty_wait_until_sent): | ||
520 | * serial.c (rs_ioctl, rs_close): | ||
521 | * cyclades.c (cy_ioctl, cy_close): | ||
522 | * n_tty.c (n_tty_close): Rename wait_until_sent to | ||
523 | tty_wait_until_sent, so that it's a better name to export | ||
524 | in ksyms.c. | ||
525 | |||
526 | Sat Feb 4 23:36:20 1995 Theodore Y. Ts'o (tytso@rt-11) | ||
527 | |||
528 | * serial.c (rs_close): Added missing check for closing_wait2 being | ||
529 | ASYNC_CLOSING_WAIT_NONE. | ||
530 | |||
531 | Thu Jan 26 09:02:49 1995 Theodore Y. Ts'o (tytso@rt-11) | ||
532 | |||
533 | * serial.c (rs_init, set_serial_info, get_serial_info, | ||
534 | rs_close): Support close_wait in the serial driver. | ||
535 | This is helpful for slow devices (like serial | ||
536 | plotters) so that their outputs don't get flushed upon | ||
537 | device close. This has to be configurable because | ||
538 | normally we don't want ports to be hung up for long | ||
539 | periods of time during a close when they are not | ||
540 | connected to a device, or the device is powered off. | ||
541 | |||
542 | The default is to wait 30 seconds; in the case of a | ||
543 | very slow device, the close_wait timeout should be | ||
544 | lengthened. If it is set to 0, the kernel will wait | ||
545 | forever for all of the data to be transmitted. | ||
546 | |||
547 | Thu Jan 17 01:17:20 1995 Theodore Y. Ts'o (tytso@rt-11) | ||
548 | |||
549 | * serial.c (startup, change_speed, rs_init): Add support to detect | ||
550 | the StarTech 16650 chip. Treat it as a 16450 for now, | ||
551 | because of its FIFO bugs. | ||
552 | |||
553 | Thu Jan 5 21:21:57 1995 <dahinds@users.sourceforge.net> | ||
554 | |||
555 | * serial.c: (receive_char): Added counter to prevent infinite loop | ||
556 | when a PCMCIA serial device is ejected. | ||
557 | |||
558 | Thu Dec 29 17:53:48 1994 <tytso@rsx-11.mit.edu> | ||
559 | |||
560 | * tty_io.c (check_tty_count): New procedure which checks | ||
561 | tty->count to make sure that it matches with the number of | ||
562 | open file descriptors which point at the structure. If | ||
563 | the number doesn't match, it prints a warning message. | ||
564 | |||
565 | Wed Dec 28 15:41:51 1994 <tytso@rsx-11.mit.edu> | ||
566 | |||
567 | * tty_io.c (do_tty_hangup, disassociate_ctty): At hangup time, | ||
568 | save the tty's current foreground process group in the | ||
569 | session leader's task structure. When the session leader | ||
570 | terminates, send a SIGHUP, SIGCONT to that process group. | ||
571 | This is not required by POSIX, but it's not prohibited | ||
572 | either, and it appears to be the least intrusive way | ||
573 | to fix a problem that dialup servers have with | ||
574 | orphaned process groups caused by modem hangups. | ||
575 | |||
576 | Thu Dec 8 14:52:11 1994 <tytso@rsx-11.mit.edu> | ||
577 | |||
578 | * serial.c (rs_ioctl): Don't allow most ioctl's if the serial port | ||
579 | isn't initialized. | ||
580 | |||
581 | * serial.c (rs_close): Don't clear the IER if the serial port | ||
582 | isn't initialized. | ||
583 | |||
584 | * serial.c (block_til_ready): Don't try to block on the dialin | ||
585 | port if the serial port isn't initialized. | ||
586 | |||
587 | Wed Dec 7 10:48:30 1994 Si Park (si@wimpol.demon.co.uk) | ||
588 | * tty_io.c (tty_register_driver): Fix bug when linking onto | ||
589 | the tty_drivers list. We now test that there are elements | ||
590 | already on the list before setting the back link from the | ||
591 | first element to the new driver. | ||
592 | |||
593 | * tty_io.c (tty_unregister_driver): Fix bug in unlinking the | ||
594 | specified driver from the tty_drivers list. We were not | ||
595 | setting the back link correctly. This used to result in | ||
596 | a dangling back link pointer and cause panics on the next | ||
597 | call to get_tty_driver(). | ||
598 | |||
599 | Tue Nov 29 10:21:09 1994 Theodore Y. Ts'o (tytso@rt-11) | ||
600 | |||
601 | * tty_io.c (tty_unregister_driver): Fix bug in | ||
602 | tty_unregister_driver where the pointer to the refcount is | ||
603 | tested, instead of the refcount itself. This caused | ||
604 | tty_unregister_driver to always return EBUSY. | ||
605 | |||
606 | Sat Nov 26 11:59:24 1994 Theodore Y. Ts'o (tytso@rt-11) | ||
607 | |||
608 | * tty_io.c (tty_ioctl): Add support for the new ioctl | ||
609 | TIOCTTYGSTRUCT, which allow a kernel debugging program | ||
610 | direct read access to the tty and tty_driver structures. | ||
611 | |||
612 | Fri Nov 25 17:26:22 1994 Theodore Y. Ts'o (tytso@rt-11) | ||
613 | |||
614 | * serial.c (rs_set_termios): Don't wake up processes blocked in | ||
615 | open when the CLOCAL flag changes, since a blocking | ||
616 | open only samples the CLOCAL flag once when it blocks, | ||
617 | and doesn't check it again. (n.b. FreeBSD has a | ||
618 | different behavior for blocking opens; it's not clear | ||
619 | whether Linux or FreeBSD's interpretation is correct. | ||
620 | POSIX doesn't give clear guidance on this issue, so | ||
621 | this may change in the future....) | ||
622 | |||
623 | * serial.c (block_til_ready): Use the correct termios structure to | ||
624 | check the CLOCAL flag. If the cuaXX device is active, | ||
625 | then check the saved termios for the ttySXX device. | ||
626 | Otherwise, use the currently active termios structure. | ||
627 | |||
628 | Sun Nov 6 21:05:44 1994 Theodore Y. Ts'o (tytso@rt-11) | ||
629 | |||
630 | * serial.c (change_speed): Add support for direct access of | ||
631 | 57,600 and 115,200 bps. | ||
632 | |||
633 | Wed Nov 2 10:32:36 1994 Theodore Y. Ts'o (tytso@rt-11) | ||
634 | |||
635 | * n_tty.c (n_tty_receive_room): Only allow excess characters | ||
636 | through if we are in ICANON mode *and* there are other no | ||
637 | pending lines in the buffer. Otherwise cut and paste over | ||
638 | 4k breaks. | ||
639 | |||
640 | Sat Oct 29 18:17:34 1994 Theodore Y. Ts'o (tytso@rt-11) | ||
641 | |||
642 | * serial.c (rs_ioctl, get_lsr_info): Added patch suggested by Arne | ||
643 | Riiber so that user mode programs can tell when the | ||
644 | transmitter shift register is empty. | ||
645 | |||
646 | Thu Oct 27 23:14:29 1994 Theodore Y. Ts'o (tytso@rt-11) | ||
647 | |||
648 | * tty_ioctl.c (wait_until_sent): Added debugging printk statements | ||
649 | (under the #ifdef TTY_DEBUG_WAIT_UNTIL_SENT) | ||
650 | |||
651 | * serial.c (rs_interrupt, rs_interrupt_single, receive_chars, | ||
652 | change_speed, rs_close): rs_close now disables receiver | ||
653 | interrupts when closing the serial port. This allows the | ||
654 | serial port to close quickly when Linux and a modem (or a | ||
655 | mouse) are engaged in an echo war; when closing the serial | ||
656 | port, we now first stop listening to incoming characters, | ||
657 | and *then* wait for the transmit buffer to drain. | ||
658 | |||
659 | In order to make this change, the info->read_status_mask | ||
660 | is now used to control what bits of the line status | ||
661 | register are looked at in the interrupt routine in all | ||
662 | cases; previously it was only used in receive_chars to | ||
663 | select a few of the status bits. | ||
664 | |||
665 | Mon Oct 24 23:36:21 1994 Theodore Y. Ts'o (tytso@rt-11) | ||
666 | |||
667 | * serial.c (rs_close): Add a timeout to the transmitter flush | ||
668 | loop; this is just a sanity check in case we have flaky | ||
669 | (or non-existent-but-configured-by-the-user) hardware. | ||
670 | |||
671 | Fri Oct 21 09:37:23 1994 Theodore Y. Ts'o (tytso@rt-11) | ||
672 | |||
673 | * tty_io.c (tty_fasync): When asynchronous I/O is enabled, if the | ||
674 | process or process group has not be specified yet, set it | ||
675 | to be the tty's process group, or if that is not yet set, | ||
676 | to the current process's pid. | ||
677 | |||
678 | Thu Oct 20 23:17:28 1994 Theodore Y. Ts'o (tytso@rt-11) | ||
679 | |||
680 | * n_tty.c (n_tty_receive_room): If we are doing input | ||
681 | canonicalization, let as many characters through as | ||
682 | possible, so that the excess characters can be "beeped". | ||
683 | |||
684 | Tue Oct 18 10:02:43 1994 Theodore Y. Ts'o (tytso@rt-11) | ||
685 | |||
686 | * serial.c (rs_start): Removed an incorrect '!' that was | ||
687 | preventing transmit interrupts from being re-enabled in | ||
688 | rs_start(). Fortunately in most cases it would be | ||
689 | re-enabled elsewhere, but this still should be fixed | ||
690 | correctly. | ||
691 | |||
692 | Sun Oct 9 23:46:03 1994 Theodore Y. Ts'o (tytso@rt-11) | ||
693 | |||
694 | * tty_io.c (do_tty_hangup): If the tty driver flags | ||
695 | TTY_DRIVER_RESET_TERMIOS is set, then reset the termios | ||
696 | settings back to the driver's initial configuration. This | ||
697 | allows the termios settings to be reset even if a process | ||
698 | has hung up file descriptors keeping a pty's termios from | ||
699 | being freed and reset. | ||
700 | |||
701 | * tty_io.c (release_dev): Fix memory leak. The pty's other | ||
702 | termios structure should also be freed. | ||
703 | |||
704 | * serial.c (rs_close, shutdown): Change how we wait for the | ||
705 | transmitter to completely drain before shutting down the | ||
706 | serial port. We now do it by scheduling in another | ||
707 | process instead of busy looping with the interrupts turned | ||
708 | on. This may eliminate some race condition problems that | ||
709 | some people seem to be reporting. | ||
710 | |||
711 | Sun Sep 25 14:18:14 1994 Theodore Y. Ts'o (tytso@rt-11) | ||
712 | |||
713 | * tty_io.c (release_dev): When freeing a tty make sure that both | ||
714 | the tty and the o_tty (if present) aren't a process's | ||
715 | controlling tty. (Previously, we only checked the tty.) | ||
716 | |||
717 | * serial.c (change_speed): Only enable the Modem Status | ||
718 | Interrupt for a port if CLOCAL is not set or CRTSCTS | ||
719 | is set. If we're not checking the carrier detect and | ||
720 | CTS line, there's no point in enabling the modem | ||
721 | status interrupt. This will save spurious interrupts | ||
722 | from slowing down systems who have terminals that | ||
723 | don't support either line. (Of course, if you want | ||
724 | only one of CD and CTS support, you will need a | ||
725 | properly wired serial cable.) | ||
726 | |||
727 | Thu Sep 22 08:32:48 1994 Theodore Y. Ts'o (tytso@rt-11) | ||
728 | |||
729 | * tty_io.c (do_SAK): Return if tty is null. | ||
730 | |||
731 | * tty_io.c (_tty_name): Return "NULL tty" if the passed in tty is | ||
732 | NULL. | ||
733 | |||
734 | Sat Sep 17 13:19:25 1994 Theodore Y. Ts'o (tytso@rt-11) | ||
735 | |||
736 | * tty_ioctl.c (n_tty_ioctl): Fix TIOCGLCKTRMIOS and | ||
737 | TIOCSLCKTRMIOS, which were totally broken. Remove | ||
738 | extra indirection from argument; it should be a struct | ||
739 | termios *, not a struct termios **. | ||
740 | &real_tty->termios_locked should have been | ||
741 | real_tty->termios_locked. This caused us to be | ||
742 | reading and writing the termios_locked structure to | ||
743 | random places in kernel memory. | ||
744 | |||
745 | * tty_io.c (release_dev): Oops! Forgot to delete a critical kfree | ||
746 | of the locked_termios. This leaves the locked_termios | ||
747 | structure pointed at a freed object. | ||
748 | |||
749 | Fri Sep 16 08:13:25 1994 Theodore Y. Ts'o (tytso@rt-11) | ||
750 | |||
751 | * tty_io.c (tty_open): Don't check for an exclusive open until | ||
752 | after the device specific open routine has been called. | ||
753 | Otherwise, the serial device ref counting will be screwed | ||
754 | up. | ||
755 | |||
756 | * serial.c (rs_open, block_til_ready): Don't set termios structure | ||
757 | until after block_til_ready has returned successfully. | ||
758 | Modify block_til_ready to check the normal_termios | ||
759 | structure directly, so it doesn't rely on termios being | ||
760 | set before it's called. | ||
761 | |||
762 | Thu Sep 15 23:34:01 1994 Theodore Y. Ts'o (tytso@rt-11) | ||
763 | |||
764 | * serial.c (rs_close): Turn off interrupts during rs_close() to | ||
765 | prevent a race condition with the hangup code (which | ||
766 | runs during a software interrupt). | ||
767 | |||
768 | * tty_io.c (release_dev): Don't free the locked_termios structure; | ||
769 | its state must be retained across device opens. | ||
770 | |||
771 | |||
772 | * tty_io.c (tty_unregister_driver): Added function to unregister a | ||
773 | tty driver. (For loadable device drivers.) | ||
774 | |||
775 | |||
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index e023682be2c4..43d3395325c5 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -276,11 +276,19 @@ config N_HDLC | |||
276 | Allows synchronous HDLC communications with tty device drivers that | 276 | Allows synchronous HDLC communications with tty device drivers that |
277 | support synchronous HDLC such as the Microgate SyncLink adapter. | 277 | support synchronous HDLC such as the Microgate SyncLink adapter. |
278 | 278 | ||
279 | This driver can only be built as a module ( = code which can be | 279 | This driver can be built as a module ( = code which can be |
280 | inserted in and removed from the running kernel whenever you want). | 280 | inserted in and removed from the running kernel whenever you want). |
281 | The module will be called n_hdlc. If you want to do that, say M | 281 | The module will be called n_hdlc. If you want to do that, say M |
282 | here. | 282 | here. |
283 | 283 | ||
284 | config N_GSM | ||
285 | tristate "GSM MUX line discipline support (EXPERIMENTAL)" | ||
286 | depends on EXPERIMENTAL | ||
287 | depends on NET | ||
288 | help | ||
289 | This line discipline provides support for the GSM MUX protocol and | ||
290 | presents the mux as a set of 61 individual tty devices. | ||
291 | |||
284 | config RISCOM8 | 292 | config RISCOM8 |
285 | tristate "SDL RISCom/8 card support" | 293 | tristate "SDL RISCom/8 card support" |
286 | depends on SERIAL_NONSTANDARD | 294 | depends on SERIAL_NONSTANDARD |
@@ -485,6 +493,21 @@ config LEGACY_PTY_COUNT | |||
485 | When not in use, each legacy PTY occupies 12 bytes on 32-bit | 493 | When not in use, each legacy PTY occupies 12 bytes on 32-bit |
486 | architectures and 24 bytes on 64-bit architectures. | 494 | architectures and 24 bytes on 64-bit architectures. |
487 | 495 | ||
496 | config TTY_PRINTK | ||
497 | bool "TTY driver to output user messages via printk" | ||
498 | depends on EMBEDDED | ||
499 | default n | ||
500 | ---help--- | ||
501 | If you say Y here, the support for writing user messages (i.e. | ||
502 | console messages) via printk is available. | ||
503 | |||
504 | The feature is useful to inline user messages with kernel | ||
505 | messages. | ||
506 | In order to use this feature, you should output user messages | ||
507 | to /dev/ttyprintk or redirect console to this TTY. | ||
508 | |||
509 | If unsure, say N. | ||
510 | |||
488 | config BRIQ_PANEL | 511 | config BRIQ_PANEL |
489 | tristate 'Total Impact briQ front panel driver' | 512 | tristate 'Total Impact briQ front panel driver' |
490 | depends on PPC_CHRP | 513 | depends on PPC_CHRP |
@@ -666,6 +689,14 @@ config VIRTIO_CONSOLE | |||
666 | help | 689 | help |
667 | Virtio console for use with lguest and other hypervisors. | 690 | Virtio console for use with lguest and other hypervisors. |
668 | 691 | ||
692 | Also serves as a general-purpose serial device for data | ||
693 | transfer between the guest and host. Character devices at | ||
694 | /dev/vportNpn will be created when corresponding ports are | ||
695 | found, where N is the device number and n is the port number | ||
696 | within that device. If specified by the host, a sysfs | ||
697 | attribute called 'name' will be populated with a name for | ||
698 | the port which can be used by udev scripts to create a | ||
699 | symlink to the device. | ||
669 | 700 | ||
670 | config HVCS | 701 | config HVCS |
671 | tristate "IBM Hypervisor Virtual Console Server support" | 702 | tristate "IBM Hypervisor Virtual Console Server support" |
@@ -986,7 +1017,7 @@ config SCx200_GPIO | |||
986 | 1017 | ||
987 | config PC8736x_GPIO | 1018 | config PC8736x_GPIO |
988 | tristate "NatSemi PC8736x GPIO Support" | 1019 | tristate "NatSemi PC8736x GPIO Support" |
989 | depends on X86 | 1020 | depends on X86_32 |
990 | default SCx200_GPIO # mostly N | 1021 | default SCx200_GPIO # mostly N |
991 | select NSC_GPIO # needed for support routines | 1022 | select NSC_GPIO # needed for support routines |
992 | help | 1023 | help |
@@ -1105,5 +1136,13 @@ config DEVPORT | |||
1105 | 1136 | ||
1106 | source "drivers/s390/char/Kconfig" | 1137 | source "drivers/s390/char/Kconfig" |
1107 | 1138 | ||
1139 | config RAMOOPS | ||
1140 | tristate "Log panic/oops to a RAM buffer" | ||
1141 | depends on HAS_IOMEM | ||
1142 | default n | ||
1143 | help | ||
1144 | This enables panic and oops messages to be logged to a circular | ||
1145 | buffer in RAM where it can be read back at some later point. | ||
1146 | |||
1108 | endmenu | 1147 | endmenu |
1109 | 1148 | ||
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index f957edf7e45d..3a9c01416839 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -9,8 +9,10 @@ FONTMAPFILE = cp437.uni | |||
9 | 9 | ||
10 | obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o tty_port.o | 10 | obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o tty_port.o |
11 | 11 | ||
12 | obj-y += tty_mutex.o | ||
12 | obj-$(CONFIG_LEGACY_PTYS) += pty.o | 13 | obj-$(CONFIG_LEGACY_PTYS) += pty.o |
13 | obj-$(CONFIG_UNIX98_PTYS) += pty.o | 14 | obj-$(CONFIG_UNIX98_PTYS) += pty.o |
15 | obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o | ||
14 | obj-y += misc.o | 16 | obj-y += misc.o |
15 | obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o | 17 | obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o |
16 | obj-$(CONFIG_BFIN_JTAG_COMM) += bfin_jtag_comm.o | 18 | obj-$(CONFIG_BFIN_JTAG_COMM) += bfin_jtag_comm.o |
@@ -40,12 +42,14 @@ obj-$(CONFIG_SYNCLINK) += synclink.o | |||
40 | obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o | 42 | obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o |
41 | obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o | 43 | obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o |
42 | obj-$(CONFIG_N_HDLC) += n_hdlc.o | 44 | obj-$(CONFIG_N_HDLC) += n_hdlc.o |
45 | obj-$(CONFIG_N_GSM) += n_gsm.o | ||
43 | obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o | 46 | obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o |
44 | obj-$(CONFIG_SX) += sx.o generic_serial.o | 47 | obj-$(CONFIG_SX) += sx.o generic_serial.o |
45 | obj-$(CONFIG_RIO) += rio/ generic_serial.o | 48 | obj-$(CONFIG_RIO) += rio/ generic_serial.o |
46 | obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o | 49 | obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o |
47 | obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o | 50 | obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o |
48 | obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o | 51 | obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o |
52 | obj-$(CONFIG_HVC_TILE) += hvc_tile.o | ||
49 | obj-$(CONFIG_HVC_BEAT) += hvc_beat.o | 53 | obj-$(CONFIG_HVC_BEAT) += hvc_beat.o |
50 | obj-$(CONFIG_HVC_DRIVER) += hvc_console.o | 54 | obj-$(CONFIG_HVC_DRIVER) += hvc_console.o |
51 | obj-$(CONFIG_HVC_IRQ) += hvc_irq.o | 55 | obj-$(CONFIG_HVC_IRQ) += hvc_irq.o |
@@ -107,6 +111,7 @@ obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o | |||
107 | obj-$(CONFIG_TCG_TPM) += tpm/ | 111 | obj-$(CONFIG_TCG_TPM) += tpm/ |
108 | 112 | ||
109 | obj-$(CONFIG_PS3_FLASH) += ps3flash.o | 113 | obj-$(CONFIG_PS3_FLASH) += ps3flash.o |
114 | obj-$(CONFIG_RAMOOPS) += ramoops.o | ||
110 | 115 | ||
111 | obj-$(CONFIG_JS_RTC) += js-rtc.o | 116 | obj-$(CONFIG_JS_RTC) += js-rtc.o |
112 | js-rtc-y = rtc.o | 117 | js-rtc-y = rtc.o |
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index 2fb3a480f6b0..fcd867d923ba 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig | |||
@@ -34,7 +34,7 @@ config AGP_ALI | |||
34 | X on the following ALi chipsets. The supported chipsets | 34 | X on the following ALi chipsets. The supported chipsets |
35 | include M1541, M1621, M1631, M1632, M1641,M1647,and M1651. | 35 | include M1541, M1621, M1631, M1632, M1641,M1647,and M1651. |
36 | For the ALi-chipset question, ALi suggests you refer to | 36 | For the ALi-chipset question, ALi suggests you refer to |
37 | <http://www.ali.com.tw/eng/support/index.shtml>. | 37 | <http://www.ali.com.tw/>. |
38 | 38 | ||
39 | The M1541 chipset can do AGP 1x and 2x, but note that there is an | 39 | The M1541 chipset can do AGP 1x and 2x, but note that there is an |
40 | acknowledged incompatibility with Matrox G200 cards. Due to | 40 | acknowledged incompatibility with Matrox G200 cards. Due to |
@@ -57,7 +57,7 @@ config AGP_AMD | |||
57 | 57 | ||
58 | config AGP_AMD64 | 58 | config AGP_AMD64 |
59 | tristate "AMD Opteron/Athlon64 on-CPU GART support" | 59 | tristate "AMD Opteron/Athlon64 on-CPU GART support" |
60 | depends on AGP && X86 | 60 | depends on AGP && X86 && AMD_NB |
61 | help | 61 | help |
62 | This option gives you AGP support for the GLX component of | 62 | This option gives you AGP support for the GLX component of |
63 | X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs. | 63 | X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs. |
diff --git a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile index 627f542827c7..8eb56e273e75 100644 --- a/drivers/char/agp/Makefile +++ b/drivers/char/agp/Makefile | |||
@@ -13,6 +13,7 @@ obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o | |||
13 | obj-$(CONFIG_AGP_PARISC) += parisc-agp.o | 13 | obj-$(CONFIG_AGP_PARISC) += parisc-agp.o |
14 | obj-$(CONFIG_AGP_I460) += i460-agp.o | 14 | obj-$(CONFIG_AGP_I460) += i460-agp.o |
15 | obj-$(CONFIG_AGP_INTEL) += intel-agp.o | 15 | obj-$(CONFIG_AGP_INTEL) += intel-agp.o |
16 | obj-$(CONFIG_AGP_INTEL) += intel-gtt.o | ||
16 | obj-$(CONFIG_AGP_NVIDIA) += nvidia-agp.o | 17 | obj-$(CONFIG_AGP_NVIDIA) += nvidia-agp.o |
17 | obj-$(CONFIG_AGP_SGI_TIOCA) += sgi-agp.o | 18 | obj-$(CONFIG_AGP_SGI_TIOCA) += sgi-agp.o |
18 | obj-$(CONFIG_AGP_SIS) += sis-agp.o | 19 | obj-$(CONFIG_AGP_SIS) += sis-agp.o |
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index 870f12cfed93..5259065f3c79 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h | |||
@@ -121,11 +121,6 @@ struct agp_bridge_driver { | |||
121 | void (*agp_destroy_pages)(struct agp_memory *); | 121 | void (*agp_destroy_pages)(struct agp_memory *); |
122 | int (*agp_type_to_mask_type) (struct agp_bridge_data *, int); | 122 | int (*agp_type_to_mask_type) (struct agp_bridge_data *, int); |
123 | void (*chipset_flush)(struct agp_bridge_data *); | 123 | void (*chipset_flush)(struct agp_bridge_data *); |
124 | |||
125 | int (*agp_map_page)(struct page *page, dma_addr_t *ret); | ||
126 | void (*agp_unmap_page)(struct page *page, dma_addr_t dma); | ||
127 | int (*agp_map_memory)(struct agp_memory *mem); | ||
128 | void (*agp_unmap_memory)(struct agp_memory *mem); | ||
129 | }; | 124 | }; |
130 | 125 | ||
131 | struct agp_bridge_data { | 126 | struct agp_bridge_data { |
@@ -178,86 +173,6 @@ struct agp_bridge_data { | |||
178 | #define PGE_EMPTY(b, p) (!(p) || (p) == (unsigned long) (b)->scratch_page) | 173 | #define PGE_EMPTY(b, p) (!(p) || (p) == (unsigned long) (b)->scratch_page) |
179 | 174 | ||
180 | 175 | ||
181 | /* Intel registers */ | ||
182 | #define INTEL_APSIZE 0xb4 | ||
183 | #define INTEL_ATTBASE 0xb8 | ||
184 | #define INTEL_AGPCTRL 0xb0 | ||
185 | #define INTEL_NBXCFG 0x50 | ||
186 | #define INTEL_ERRSTS 0x91 | ||
187 | |||
188 | /* Intel i830 registers */ | ||
189 | #define I830_GMCH_CTRL 0x52 | ||
190 | #define I830_GMCH_ENABLED 0x4 | ||
191 | #define I830_GMCH_MEM_MASK 0x1 | ||
192 | #define I830_GMCH_MEM_64M 0x1 | ||
193 | #define I830_GMCH_MEM_128M 0 | ||
194 | #define I830_GMCH_GMS_MASK 0x70 | ||
195 | #define I830_GMCH_GMS_DISABLED 0x00 | ||
196 | #define I830_GMCH_GMS_LOCAL 0x10 | ||
197 | #define I830_GMCH_GMS_STOLEN_512 0x20 | ||
198 | #define I830_GMCH_GMS_STOLEN_1024 0x30 | ||
199 | #define I830_GMCH_GMS_STOLEN_8192 0x40 | ||
200 | #define I830_RDRAM_CHANNEL_TYPE 0x03010 | ||
201 | #define I830_RDRAM_ND(x) (((x) & 0x20) >> 5) | ||
202 | #define I830_RDRAM_DDT(x) (((x) & 0x18) >> 3) | ||
203 | |||
204 | /* This one is for I830MP w. an external graphic card */ | ||
205 | #define INTEL_I830_ERRSTS 0x92 | ||
206 | |||
207 | /* Intel 855GM/852GM registers */ | ||
208 | #define I855_GMCH_GMS_MASK 0xF0 | ||
209 | #define I855_GMCH_GMS_STOLEN_0M 0x0 | ||
210 | #define I855_GMCH_GMS_STOLEN_1M (0x1 << 4) | ||
211 | #define I855_GMCH_GMS_STOLEN_4M (0x2 << 4) | ||
212 | #define I855_GMCH_GMS_STOLEN_8M (0x3 << 4) | ||
213 | #define I855_GMCH_GMS_STOLEN_16M (0x4 << 4) | ||
214 | #define I855_GMCH_GMS_STOLEN_32M (0x5 << 4) | ||
215 | #define I85X_CAPID 0x44 | ||
216 | #define I85X_VARIANT_MASK 0x7 | ||
217 | #define I85X_VARIANT_SHIFT 5 | ||
218 | #define I855_GME 0x0 | ||
219 | #define I855_GM 0x4 | ||
220 | #define I852_GME 0x2 | ||
221 | #define I852_GM 0x5 | ||
222 | |||
223 | /* Intel i845 registers */ | ||
224 | #define INTEL_I845_AGPM 0x51 | ||
225 | #define INTEL_I845_ERRSTS 0xc8 | ||
226 | |||
227 | /* Intel i860 registers */ | ||
228 | #define INTEL_I860_MCHCFG 0x50 | ||
229 | #define INTEL_I860_ERRSTS 0xc8 | ||
230 | |||
231 | /* Intel i810 registers */ | ||
232 | #define I810_GMADDR 0x10 | ||
233 | #define I810_MMADDR 0x14 | ||
234 | #define I810_PTE_BASE 0x10000 | ||
235 | #define I810_PTE_MAIN_UNCACHED 0x00000000 | ||
236 | #define I810_PTE_LOCAL 0x00000002 | ||
237 | #define I810_PTE_VALID 0x00000001 | ||
238 | #define I830_PTE_SYSTEM_CACHED 0x00000006 | ||
239 | #define I810_SMRAM_MISCC 0x70 | ||
240 | #define I810_GFX_MEM_WIN_SIZE 0x00010000 | ||
241 | #define I810_GFX_MEM_WIN_32M 0x00010000 | ||
242 | #define I810_GMS 0x000000c0 | ||
243 | #define I810_GMS_DISABLE 0x00000000 | ||
244 | #define I810_PGETBL_CTL 0x2020 | ||
245 | #define I810_PGETBL_ENABLED 0x00000001 | ||
246 | #define I965_PGETBL_SIZE_MASK 0x0000000e | ||
247 | #define I965_PGETBL_SIZE_512KB (0 << 1) | ||
248 | #define I965_PGETBL_SIZE_256KB (1 << 1) | ||
249 | #define I965_PGETBL_SIZE_128KB (2 << 1) | ||
250 | #define I965_PGETBL_SIZE_1MB (3 << 1) | ||
251 | #define I965_PGETBL_SIZE_2MB (4 << 1) | ||
252 | #define I965_PGETBL_SIZE_1_5MB (5 << 1) | ||
253 | #define G33_PGETBL_SIZE_MASK (3 << 8) | ||
254 | #define G33_PGETBL_SIZE_1M (1 << 8) | ||
255 | #define G33_PGETBL_SIZE_2M (2 << 8) | ||
256 | |||
257 | #define I810_DRAM_CTL 0x3000 | ||
258 | #define I810_DRAM_ROW_0 0x00000001 | ||
259 | #define I810_DRAM_ROW_0_SDRAM 0x00000001 | ||
260 | |||
261 | struct agp_device_ids { | 176 | struct agp_device_ids { |
262 | unsigned short device_id; /* first, to make table easier to read */ | 177 | unsigned short device_id; /* first, to make table easier to read */ |
263 | enum chipset_type chipset; | 178 | enum chipset_type chipset; |
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index d2ce68f27e4b..fd793519ea2b 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c | |||
@@ -204,6 +204,7 @@ static const struct agp_bridge_driver ali_generic_bridge = { | |||
204 | .aperture_sizes = ali_generic_sizes, | 204 | .aperture_sizes = ali_generic_sizes, |
205 | .size_type = U32_APER_SIZE, | 205 | .size_type = U32_APER_SIZE, |
206 | .num_aperture_sizes = 7, | 206 | .num_aperture_sizes = 7, |
207 | .needs_scratch_page = true, | ||
207 | .configure = ali_configure, | 208 | .configure = ali_configure, |
208 | .fetch_size = ali_fetch_size, | 209 | .fetch_size = ali_fetch_size, |
209 | .cleanup = ali_cleanup, | 210 | .cleanup = ali_cleanup, |
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index 73dbf40c874d..b1b4362bc648 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c | |||
@@ -6,9 +6,9 @@ | |||
6 | #include <linux/pci.h> | 6 | #include <linux/pci.h> |
7 | #include <linux/init.h> | 7 | #include <linux/init.h> |
8 | #include <linux/agp_backend.h> | 8 | #include <linux/agp_backend.h> |
9 | #include <linux/gfp.h> | ||
10 | #include <linux/page-flags.h> | 9 | #include <linux/page-flags.h> |
11 | #include <linux/mm.h> | 10 | #include <linux/mm.h> |
11 | #include <linux/slab.h> | ||
12 | #include "agp.h" | 12 | #include "agp.h" |
13 | 13 | ||
14 | #define AMD_MMBASE 0x14 | 14 | #define AMD_MMBASE 0x14 |
@@ -142,6 +142,7 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge) | |||
142 | { | 142 | { |
143 | struct aper_size_info_lvl2 *value; | 143 | struct aper_size_info_lvl2 *value; |
144 | struct amd_page_map page_dir; | 144 | struct amd_page_map page_dir; |
145 | unsigned long __iomem *cur_gatt; | ||
145 | unsigned long addr; | 146 | unsigned long addr; |
146 | int retval; | 147 | int retval; |
147 | u32 temp; | 148 | u32 temp; |
@@ -178,6 +179,13 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge) | |||
178 | readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */ | 179 | readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */ |
179 | } | 180 | } |
180 | 181 | ||
182 | for (i = 0; i < value->num_entries; i++) { | ||
183 | addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr; | ||
184 | cur_gatt = GET_GATT(addr); | ||
185 | writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr)); | ||
186 | readl(cur_gatt+GET_GATT_OFF(addr)); /* PCI Posting. */ | ||
187 | } | ||
188 | |||
181 | return 0; | 189 | return 0; |
182 | } | 190 | } |
183 | 191 | ||
@@ -301,7 +309,8 @@ static int amd_insert_memory(struct agp_memory *mem, off_t pg_start, int type) | |||
301 | 309 | ||
302 | num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries; | 310 | num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries; |
303 | 311 | ||
304 | if (type != 0 || mem->type != 0) | 312 | if (type != mem->type || |
313 | agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) | ||
305 | return -EINVAL; | 314 | return -EINVAL; |
306 | 315 | ||
307 | if ((pg_start + mem->page_count) > num_entries) | 316 | if ((pg_start + mem->page_count) > num_entries) |
@@ -340,7 +349,8 @@ static int amd_remove_memory(struct agp_memory *mem, off_t pg_start, int type) | |||
340 | unsigned long __iomem *cur_gatt; | 349 | unsigned long __iomem *cur_gatt; |
341 | unsigned long addr; | 350 | unsigned long addr; |
342 | 351 | ||
343 | if (type != 0 || mem->type != 0) | 352 | if (type != mem->type || |
353 | agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) | ||
344 | return -EINVAL; | 354 | return -EINVAL; |
345 | 355 | ||
346 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | 356 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { |
@@ -375,6 +385,7 @@ static const struct agp_bridge_driver amd_irongate_driver = { | |||
375 | .aperture_sizes = amd_irongate_sizes, | 385 | .aperture_sizes = amd_irongate_sizes, |
376 | .size_type = LVL2_APER_SIZE, | 386 | .size_type = LVL2_APER_SIZE, |
377 | .num_aperture_sizes = 7, | 387 | .num_aperture_sizes = 7, |
388 | .needs_scratch_page = true, | ||
378 | .configure = amd_irongate_configure, | 389 | .configure = amd_irongate_configure, |
379 | .fetch_size = amd_irongate_fetch_size, | 390 | .fetch_size = amd_irongate_fetch_size, |
380 | .cleanup = amd_irongate_cleanup, | 391 | .cleanup = amd_irongate_cleanup, |
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 1afb8968a342..42396df55556 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/mmzone.h> | 15 | #include <linux/mmzone.h> |
16 | #include <asm/page.h> /* PAGE_SIZE */ | 16 | #include <asm/page.h> /* PAGE_SIZE */ |
17 | #include <asm/e820.h> | 17 | #include <asm/e820.h> |
18 | #include <asm/k8.h> | 18 | #include <asm/amd_nb.h> |
19 | #include <asm/gart.h> | 19 | #include <asm/gart.h> |
20 | #include "agp.h" | 20 | #include "agp.h" |
21 | 21 | ||
@@ -124,7 +124,7 @@ static int amd64_fetch_size(void) | |||
124 | u32 temp; | 124 | u32 temp; |
125 | struct aper_size_info_32 *values; | 125 | struct aper_size_info_32 *values; |
126 | 126 | ||
127 | dev = k8_northbridges[0]; | 127 | dev = k8_northbridges.nb_misc[0]; |
128 | if (dev==NULL) | 128 | if (dev==NULL) |
129 | return 0; | 129 | return 0; |
130 | 130 | ||
@@ -181,10 +181,14 @@ static int amd_8151_configure(void) | |||
181 | unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real); | 181 | unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real); |
182 | int i; | 182 | int i; |
183 | 183 | ||
184 | if (!k8_northbridges.gart_supported) | ||
185 | return 0; | ||
186 | |||
184 | /* Configure AGP regs in each x86-64 host bridge. */ | 187 | /* Configure AGP regs in each x86-64 host bridge. */ |
185 | for (i = 0; i < num_k8_northbridges; i++) { | 188 | for (i = 0; i < k8_northbridges.num; i++) { |
186 | agp_bridge->gart_bus_addr = | 189 | agp_bridge->gart_bus_addr = |
187 | amd64_configure(k8_northbridges[i], gatt_bus); | 190 | amd64_configure(k8_northbridges.nb_misc[i], |
191 | gatt_bus); | ||
188 | } | 192 | } |
189 | k8_flush_garts(); | 193 | k8_flush_garts(); |
190 | return 0; | 194 | return 0; |
@@ -195,11 +199,15 @@ static void amd64_cleanup(void) | |||
195 | { | 199 | { |
196 | u32 tmp; | 200 | u32 tmp; |
197 | int i; | 201 | int i; |
198 | for (i = 0; i < num_k8_northbridges; i++) { | 202 | |
199 | struct pci_dev *dev = k8_northbridges[i]; | 203 | if (!k8_northbridges.gart_supported) |
204 | return; | ||
205 | |||
206 | for (i = 0; i < k8_northbridges.num; i++) { | ||
207 | struct pci_dev *dev = k8_northbridges.nb_misc[i]; | ||
200 | /* disable gart translation */ | 208 | /* disable gart translation */ |
201 | pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &tmp); | 209 | pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &tmp); |
202 | tmp &= ~AMD64_GARTEN; | 210 | tmp &= ~GARTEN; |
203 | pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, tmp); | 211 | pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, tmp); |
204 | } | 212 | } |
205 | } | 213 | } |
@@ -210,6 +218,7 @@ static const struct agp_bridge_driver amd_8151_driver = { | |||
210 | .aperture_sizes = amd_8151_sizes, | 218 | .aperture_sizes = amd_8151_sizes, |
211 | .size_type = U32_APER_SIZE, | 219 | .size_type = U32_APER_SIZE, |
212 | .num_aperture_sizes = 7, | 220 | .num_aperture_sizes = 7, |
221 | .needs_scratch_page = true, | ||
213 | .configure = amd_8151_configure, | 222 | .configure = amd_8151_configure, |
214 | .fetch_size = amd64_fetch_size, | 223 | .fetch_size = amd64_fetch_size, |
215 | .cleanup = amd64_cleanup, | 224 | .cleanup = amd64_cleanup, |
@@ -312,22 +321,25 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, | |||
312 | if (order < 0 || !agp_aperture_valid(aper, (32*1024*1024)<<order)) | 321 | if (order < 0 || !agp_aperture_valid(aper, (32*1024*1024)<<order)) |
313 | return -1; | 322 | return -1; |
314 | 323 | ||
315 | pci_write_config_dword(nb, AMD64_GARTAPERTURECTL, order << 1); | 324 | gart_set_size_and_enable(nb, order); |
316 | pci_write_config_dword(nb, AMD64_GARTAPERTUREBASE, aper >> 25); | 325 | pci_write_config_dword(nb, AMD64_GARTAPERTUREBASE, aper >> 25); |
317 | 326 | ||
318 | return 0; | 327 | return 0; |
319 | } | 328 | } |
320 | 329 | ||
321 | static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) | 330 | static __devinit int cache_nbs(struct pci_dev *pdev, u32 cap_ptr) |
322 | { | 331 | { |
323 | int i; | 332 | int i; |
324 | 333 | ||
325 | if (cache_k8_northbridges() < 0) | 334 | if (cache_k8_northbridges() < 0) |
326 | return -ENODEV; | 335 | return -ENODEV; |
327 | 336 | ||
337 | if (!k8_northbridges.gart_supported) | ||
338 | return -ENODEV; | ||
339 | |||
328 | i = 0; | 340 | i = 0; |
329 | for (i = 0; i < num_k8_northbridges; i++) { | 341 | for (i = 0; i < k8_northbridges.num; i++) { |
330 | struct pci_dev *dev = k8_northbridges[i]; | 342 | struct pci_dev *dev = k8_northbridges.nb_misc[i]; |
331 | if (fix_northbridge(dev, pdev, cap_ptr) < 0) { | 343 | if (fix_northbridge(dev, pdev, cap_ptr) < 0) { |
332 | dev_err(&dev->dev, "no usable aperture found\n"); | 344 | dev_err(&dev->dev, "no usable aperture found\n"); |
333 | #ifdef __x86_64__ | 345 | #ifdef __x86_64__ |
@@ -383,7 +395,7 @@ static int __devinit uli_agp_init(struct pci_dev *pdev) | |||
383 | { | 395 | { |
384 | u32 httfea,baseaddr,enuscr; | 396 | u32 httfea,baseaddr,enuscr; |
385 | struct pci_dev *dev1; | 397 | struct pci_dev *dev1; |
386 | int i; | 398 | int i, ret; |
387 | unsigned size = amd64_fetch_size(); | 399 | unsigned size = amd64_fetch_size(); |
388 | 400 | ||
389 | dev_info(&pdev->dev, "setting up ULi AGP\n"); | 401 | dev_info(&pdev->dev, "setting up ULi AGP\n"); |
@@ -399,15 +411,19 @@ static int __devinit uli_agp_init(struct pci_dev *pdev) | |||
399 | 411 | ||
400 | if (i == ARRAY_SIZE(uli_sizes)) { | 412 | if (i == ARRAY_SIZE(uli_sizes)) { |
401 | dev_info(&pdev->dev, "no ULi size found for %d\n", size); | 413 | dev_info(&pdev->dev, "no ULi size found for %d\n", size); |
402 | return -ENODEV; | 414 | ret = -ENODEV; |
415 | goto put; | ||
403 | } | 416 | } |
404 | 417 | ||
405 | /* shadow x86-64 registers into ULi registers */ | 418 | /* shadow x86-64 registers into ULi registers */ |
406 | pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &httfea); | 419 | pci_read_config_dword (k8_northbridges.nb_misc[0], AMD64_GARTAPERTUREBASE, |
420 | &httfea); | ||
407 | 421 | ||
408 | /* if x86-64 aperture base is beyond 4G, exit here */ | 422 | /* if x86-64 aperture base is beyond 4G, exit here */ |
409 | if ((httfea & 0x7fff) >> (32 - 25)) | 423 | if ((httfea & 0x7fff) >> (32 - 25)) { |
410 | return -ENODEV; | 424 | ret = -ENODEV; |
425 | goto put; | ||
426 | } | ||
411 | 427 | ||
412 | httfea = (httfea& 0x7fff) << 25; | 428 | httfea = (httfea& 0x7fff) << 25; |
413 | 429 | ||
@@ -419,9 +435,10 @@ static int __devinit uli_agp_init(struct pci_dev *pdev) | |||
419 | enuscr= httfea+ (size * 1024 * 1024) - 1; | 435 | enuscr= httfea+ (size * 1024 * 1024) - 1; |
420 | pci_write_config_dword(dev1, ULI_X86_64_HTT_FEA_REG, httfea); | 436 | pci_write_config_dword(dev1, ULI_X86_64_HTT_FEA_REG, httfea); |
421 | pci_write_config_dword(dev1, ULI_X86_64_ENU_SCR_REG, enuscr); | 437 | pci_write_config_dword(dev1, ULI_X86_64_ENU_SCR_REG, enuscr); |
422 | 438 | ret = 0; | |
439 | put: | ||
423 | pci_dev_put(dev1); | 440 | pci_dev_put(dev1); |
424 | return 0; | 441 | return ret; |
425 | } | 442 | } |
426 | 443 | ||
427 | 444 | ||
@@ -440,7 +457,7 @@ static int nforce3_agp_init(struct pci_dev *pdev) | |||
440 | { | 457 | { |
441 | u32 tmp, apbase, apbar, aplimit; | 458 | u32 tmp, apbase, apbar, aplimit; |
442 | struct pci_dev *dev1; | 459 | struct pci_dev *dev1; |
443 | int i; | 460 | int i, ret; |
444 | unsigned size = amd64_fetch_size(); | 461 | unsigned size = amd64_fetch_size(); |
445 | 462 | ||
446 | dev_info(&pdev->dev, "setting up Nforce3 AGP\n"); | 463 | dev_info(&pdev->dev, "setting up Nforce3 AGP\n"); |
@@ -457,7 +474,8 @@ static int nforce3_agp_init(struct pci_dev *pdev) | |||
457 | 474 | ||
458 | if (i == ARRAY_SIZE(nforce3_sizes)) { | 475 | if (i == ARRAY_SIZE(nforce3_sizes)) { |
459 | dev_info(&pdev->dev, "no NForce3 size found for %d\n", size); | 476 | dev_info(&pdev->dev, "no NForce3 size found for %d\n", size); |
460 | return -ENODEV; | 477 | ret = -ENODEV; |
478 | goto put; | ||
461 | } | 479 | } |
462 | 480 | ||
463 | pci_read_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, &tmp); | 481 | pci_read_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, &tmp); |
@@ -466,12 +484,14 @@ static int nforce3_agp_init(struct pci_dev *pdev) | |||
466 | pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp); | 484 | pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp); |
467 | 485 | ||
468 | /* shadow x86-64 registers into NVIDIA registers */ | 486 | /* shadow x86-64 registers into NVIDIA registers */ |
469 | pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &apbase); | 487 | pci_read_config_dword (k8_northbridges.nb_misc[0], AMD64_GARTAPERTUREBASE, |
488 | &apbase); | ||
470 | 489 | ||
471 | /* if x86-64 aperture base is beyond 4G, exit here */ | 490 | /* if x86-64 aperture base is beyond 4G, exit here */ |
472 | if ( (apbase & 0x7fff) >> (32 - 25) ) { | 491 | if ( (apbase & 0x7fff) >> (32 - 25) ) { |
473 | dev_info(&pdev->dev, "aperture base > 4G\n"); | 492 | dev_info(&pdev->dev, "aperture base > 4G\n"); |
474 | return -ENODEV; | 493 | ret = -ENODEV; |
494 | goto put; | ||
475 | } | 495 | } |
476 | 496 | ||
477 | apbase = (apbase & 0x7fff) << 25; | 497 | apbase = (apbase & 0x7fff) << 25; |
@@ -487,9 +507,11 @@ static int nforce3_agp_init(struct pci_dev *pdev) | |||
487 | pci_write_config_dword(dev1, NVIDIA_X86_64_1_APBASE2, apbase); | 507 | pci_write_config_dword(dev1, NVIDIA_X86_64_1_APBASE2, apbase); |
488 | pci_write_config_dword(dev1, NVIDIA_X86_64_1_APLIMIT2, aplimit); | 508 | pci_write_config_dword(dev1, NVIDIA_X86_64_1_APLIMIT2, aplimit); |
489 | 509 | ||
510 | ret = 0; | ||
511 | put: | ||
490 | pci_dev_put(dev1); | 512 | pci_dev_put(dev1); |
491 | 513 | ||
492 | return 0; | 514 | return ret; |
493 | } | 515 | } |
494 | 516 | ||
495 | static int __devinit agp_amd64_probe(struct pci_dev *pdev, | 517 | static int __devinit agp_amd64_probe(struct pci_dev *pdev, |
@@ -499,6 +521,10 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev, | |||
499 | u8 cap_ptr; | 521 | u8 cap_ptr; |
500 | int err; | 522 | int err; |
501 | 523 | ||
524 | /* The Highlander principle */ | ||
525 | if (agp_bridges_found) | ||
526 | return -ENODEV; | ||
527 | |||
502 | cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); | 528 | cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); |
503 | if (!cap_ptr) | 529 | if (!cap_ptr) |
504 | return -ENODEV; | 530 | return -ENODEV; |
@@ -562,6 +588,8 @@ static void __devexit agp_amd64_remove(struct pci_dev *pdev) | |||
562 | amd64_aperture_sizes[bridge->aperture_size_idx].size); | 588 | amd64_aperture_sizes[bridge->aperture_size_idx].size); |
563 | agp_remove_bridge(bridge); | 589 | agp_remove_bridge(bridge); |
564 | agp_put_bridge(bridge); | 590 | agp_put_bridge(bridge); |
591 | |||
592 | agp_bridges_found--; | ||
565 | } | 593 | } |
566 | 594 | ||
567 | #ifdef CONFIG_PM | 595 | #ifdef CONFIG_PM |
@@ -709,6 +737,11 @@ static struct pci_device_id agp_amd64_pci_table[] = { | |||
709 | 737 | ||
710 | MODULE_DEVICE_TABLE(pci, agp_amd64_pci_table); | 738 | MODULE_DEVICE_TABLE(pci, agp_amd64_pci_table); |
711 | 739 | ||
740 | static DEFINE_PCI_DEVICE_TABLE(agp_amd64_pci_promisc_table) = { | ||
741 | { PCI_DEVICE_CLASS(0, 0) }, | ||
742 | { } | ||
743 | }; | ||
744 | |||
712 | static struct pci_driver agp_amd64_pci_driver = { | 745 | static struct pci_driver agp_amd64_pci_driver = { |
713 | .name = "agpgart-amd64", | 746 | .name = "agpgart-amd64", |
714 | .id_table = agp_amd64_pci_table, | 747 | .id_table = agp_amd64_pci_table, |
@@ -729,15 +762,11 @@ int __init agp_amd64_init(void) | |||
729 | if (agp_off) | 762 | if (agp_off) |
730 | return -EINVAL; | 763 | return -EINVAL; |
731 | 764 | ||
732 | if (gart_iommu_aperture) | ||
733 | return agp_bridges_found ? 0 : -ENODEV; | ||
734 | |||
735 | err = pci_register_driver(&agp_amd64_pci_driver); | 765 | err = pci_register_driver(&agp_amd64_pci_driver); |
736 | if (err < 0) | 766 | if (err < 0) |
737 | return err; | 767 | return err; |
738 | 768 | ||
739 | if (agp_bridges_found == 0) { | 769 | if (agp_bridges_found == 0) { |
740 | struct pci_dev *dev; | ||
741 | if (!agp_try_unsupported && !agp_try_unsupported_boot) { | 770 | if (!agp_try_unsupported && !agp_try_unsupported_boot) { |
742 | printk(KERN_INFO PFX "No supported AGP bridge found.\n"); | 771 | printk(KERN_INFO PFX "No supported AGP bridge found.\n"); |
743 | #ifdef MODULE | 772 | #ifdef MODULE |
@@ -753,31 +782,35 @@ int __init agp_amd64_init(void) | |||
753 | return -ENODEV; | 782 | return -ENODEV; |
754 | 783 | ||
755 | /* Look for any AGP bridge */ | 784 | /* Look for any AGP bridge */ |
756 | dev = NULL; | 785 | agp_amd64_pci_driver.id_table = agp_amd64_pci_promisc_table; |
757 | err = -ENODEV; | 786 | err = driver_attach(&agp_amd64_pci_driver.driver); |
758 | for_each_pci_dev(dev) { | 787 | if (err == 0 && agp_bridges_found == 0) |
759 | if (!pci_find_capability(dev, PCI_CAP_ID_AGP)) | 788 | err = -ENODEV; |
760 | continue; | ||
761 | /* Only one bridge supported right now */ | ||
762 | if (agp_amd64_probe(dev, NULL) == 0) { | ||
763 | err = 0; | ||
764 | break; | ||
765 | } | ||
766 | } | ||
767 | } | 789 | } |
768 | return err; | 790 | return err; |
769 | } | 791 | } |
770 | 792 | ||
793 | static int __init agp_amd64_mod_init(void) | ||
794 | { | ||
795 | #ifndef MODULE | ||
796 | if (gart_iommu_aperture) | ||
797 | return agp_bridges_found ? 0 : -ENODEV; | ||
798 | #endif | ||
799 | return agp_amd64_init(); | ||
800 | } | ||
801 | |||
771 | static void __exit agp_amd64_cleanup(void) | 802 | static void __exit agp_amd64_cleanup(void) |
772 | { | 803 | { |
804 | #ifndef MODULE | ||
773 | if (gart_iommu_aperture) | 805 | if (gart_iommu_aperture) |
774 | return; | 806 | return; |
807 | #endif | ||
775 | if (aperture_resource) | 808 | if (aperture_resource) |
776 | release_resource(aperture_resource); | 809 | release_resource(aperture_resource); |
777 | pci_unregister_driver(&agp_amd64_pci_driver); | 810 | pci_unregister_driver(&agp_amd64_pci_driver); |
778 | } | 811 | } |
779 | 812 | ||
780 | module_init(agp_amd64_init); | 813 | module_init(agp_amd64_mod_init); |
781 | module_exit(agp_amd64_cleanup); | 814 | module_exit(agp_amd64_cleanup); |
782 | 815 | ||
783 | MODULE_AUTHOR("Dave Jones <davej@redhat.com>, Andi Kleen"); | 816 | MODULE_AUTHOR("Dave Jones <davej@redhat.com>, Andi Kleen"); |
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index 3b2ecbe86ebe..dc30e2243494 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c | |||
@@ -341,6 +341,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge) | |||
341 | { | 341 | { |
342 | struct aper_size_info_lvl2 *value; | 342 | struct aper_size_info_lvl2 *value; |
343 | struct ati_page_map page_dir; | 343 | struct ati_page_map page_dir; |
344 | unsigned long __iomem *cur_gatt; | ||
344 | unsigned long addr; | 345 | unsigned long addr; |
345 | int retval; | 346 | int retval; |
346 | u32 temp; | 347 | u32 temp; |
@@ -395,6 +396,12 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge) | |||
395 | readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */ | 396 | readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */ |
396 | } | 397 | } |
397 | 398 | ||
399 | for (i = 0; i < value->num_entries; i++) { | ||
400 | addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr; | ||
401 | cur_gatt = GET_GATT(addr); | ||
402 | writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr)); | ||
403 | } | ||
404 | |||
398 | return 0; | 405 | return 0; |
399 | } | 406 | } |
400 | 407 | ||
@@ -415,6 +422,7 @@ static const struct agp_bridge_driver ati_generic_bridge = { | |||
415 | .aperture_sizes = ati_generic_sizes, | 422 | .aperture_sizes = ati_generic_sizes, |
416 | .size_type = LVL2_APER_SIZE, | 423 | .size_type = LVL2_APER_SIZE, |
417 | .num_aperture_sizes = 7, | 424 | .num_aperture_sizes = 7, |
425 | .needs_scratch_page = true, | ||
418 | .configure = ati_configure, | 426 | .configure = ati_configure, |
419 | .fetch_size = ati_fetch_size, | 427 | .fetch_size = ati_fetch_size, |
420 | .cleanup = ati_cleanup, | 428 | .cleanup = ati_cleanup, |
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index c3ab46da51a3..f27d0d0816d3 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/slab.h> | ||
33 | #include <linux/pagemap.h> | 34 | #include <linux/pagemap.h> |
34 | #include <linux/miscdevice.h> | 35 | #include <linux/miscdevice.h> |
35 | #include <linux/pm.h> | 36 | #include <linux/pm.h> |
@@ -150,17 +151,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) | |||
150 | } | 151 | } |
151 | 152 | ||
152 | bridge->scratch_page_page = page; | 153 | bridge->scratch_page_page = page; |
153 | if (bridge->driver->agp_map_page) { | 154 | bridge->scratch_page_dma = page_to_phys(page); |
154 | if (bridge->driver->agp_map_page(page, | ||
155 | &bridge->scratch_page_dma)) { | ||
156 | dev_err(&bridge->dev->dev, | ||
157 | "unable to dma-map scratch page\n"); | ||
158 | rc = -ENOMEM; | ||
159 | goto err_out_nounmap; | ||
160 | } | ||
161 | } else { | ||
162 | bridge->scratch_page_dma = page_to_phys(page); | ||
163 | } | ||
164 | 155 | ||
165 | bridge->scratch_page = bridge->driver->mask_memory(bridge, | 156 | bridge->scratch_page = bridge->driver->mask_memory(bridge, |
166 | bridge->scratch_page_dma, 0); | 157 | bridge->scratch_page_dma, 0); |
@@ -203,12 +194,6 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) | |||
203 | return 0; | 194 | return 0; |
204 | 195 | ||
205 | err_out: | 196 | err_out: |
206 | if (bridge->driver->needs_scratch_page && | ||
207 | bridge->driver->agp_unmap_page) { | ||
208 | bridge->driver->agp_unmap_page(bridge->scratch_page_page, | ||
209 | bridge->scratch_page_dma); | ||
210 | } | ||
211 | err_out_nounmap: | ||
212 | if (bridge->driver->needs_scratch_page) { | 197 | if (bridge->driver->needs_scratch_page) { |
213 | void *va = page_address(bridge->scratch_page_page); | 198 | void *va = page_address(bridge->scratch_page_page); |
214 | 199 | ||
@@ -239,10 +224,6 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge) | |||
239 | bridge->driver->needs_scratch_page) { | 224 | bridge->driver->needs_scratch_page) { |
240 | void *va = page_address(bridge->scratch_page_page); | 225 | void *va = page_address(bridge->scratch_page_page); |
241 | 226 | ||
242 | if (bridge->driver->agp_unmap_page) | ||
243 | bridge->driver->agp_unmap_page(bridge->scratch_page_page, | ||
244 | bridge->scratch_page_dma); | ||
245 | |||
246 | bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP); | 227 | bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP); |
247 | bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE); | 228 | bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE); |
248 | } | 229 | } |
diff --git a/drivers/char/agp/compat_ioctl.c b/drivers/char/agp/compat_ioctl.c index 58c57cb2518c..9d2c97a69cdd 100644 --- a/drivers/char/agp/compat_ioctl.c +++ b/drivers/char/agp/compat_ioctl.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/pci.h> | 30 | #include <linux/pci.h> |
31 | #include <linux/fs.h> | 31 | #include <linux/fs.h> |
32 | #include <linux/agpgart.h> | 32 | #include <linux/agpgart.h> |
33 | #include <linux/slab.h> | ||
33 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
34 | #include "agp.h" | 35 | #include "agp.h" |
35 | #include "compat_ioctl.h" | 36 | #include "compat_ioctl.h" |
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c index 793f39ea9618..d607f53d8afc 100644 --- a/drivers/char/agp/efficeon-agp.c +++ b/drivers/char/agp/efficeon-agp.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/page-flags.h> | 28 | #include <linux/page-flags.h> |
29 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
30 | #include "agp.h" | 30 | #include "agp.h" |
31 | #include "intel-agp.h" | ||
31 | 32 | ||
32 | /* | 33 | /* |
33 | * The real differences to the generic AGP code is | 34 | * The real differences to the generic AGP code is |
@@ -371,6 +372,17 @@ static int __devinit agp_efficeon_probe(struct pci_dev *pdev, | |||
371 | bridge->capndx = cap_ptr; | 372 | bridge->capndx = cap_ptr; |
372 | 373 | ||
373 | /* | 374 | /* |
375 | * If the device has not been properly setup, the following will catch | ||
376 | * the problem and should stop the system from crashing. | ||
377 | * 20030610 - hamish@zot.org | ||
378 | */ | ||
379 | if (pci_enable_device(pdev)) { | ||
380 | printk(KERN_ERR PFX "Unable to Enable PCI device\n"); | ||
381 | agp_put_bridge(bridge); | ||
382 | return -ENODEV; | ||
383 | } | ||
384 | |||
385 | /* | ||
374 | * The following fixes the case where the BIOS has "forgotten" to | 386 | * The following fixes the case where the BIOS has "forgotten" to |
375 | * provide an address range for the GART. | 387 | * provide an address range for the GART. |
376 | * 20030610 - hamish@zot.org | 388 | * 20030610 - hamish@zot.org |
@@ -384,17 +396,6 @@ static int __devinit agp_efficeon_probe(struct pci_dev *pdev, | |||
384 | } | 396 | } |
385 | } | 397 | } |
386 | 398 | ||
387 | /* | ||
388 | * If the device has not been properly setup, the following will catch | ||
389 | * the problem and should stop the system from crashing. | ||
390 | * 20030610 - hamish@zot.org | ||
391 | */ | ||
392 | if (pci_enable_device(pdev)) { | ||
393 | printk(KERN_ERR PFX "Unable to Enable PCI device\n"); | ||
394 | agp_put_bridge(bridge); | ||
395 | return -ENODEV; | ||
396 | } | ||
397 | |||
398 | /* Fill in the mode register */ | 399 | /* Fill in the mode register */ |
399 | if (cap_ptr) { | 400 | if (cap_ptr) { |
400 | pci_read_config_dword(pdev, | 401 | pci_read_config_dword(pdev, |
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index c50543966eb2..4956f1c8f9d5 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/dma-mapping.h> | 38 | #include <linux/dma-mapping.h> |
39 | #include <linux/mm.h> | 39 | #include <linux/mm.h> |
40 | #include <linux/sched.h> | 40 | #include <linux/sched.h> |
41 | #include <linux/slab.h> | ||
41 | #include <asm/io.h> | 42 | #include <asm/io.h> |
42 | #include <asm/cacheflush.h> | 43 | #include <asm/cacheflush.h> |
43 | #include <asm/pgtable.h> | 44 | #include <asm/pgtable.h> |
@@ -96,20 +97,18 @@ EXPORT_SYMBOL(agp_flush_chipset); | |||
96 | void agp_alloc_page_array(size_t size, struct agp_memory *mem) | 97 | void agp_alloc_page_array(size_t size, struct agp_memory *mem) |
97 | { | 98 | { |
98 | mem->pages = NULL; | 99 | mem->pages = NULL; |
99 | mem->vmalloc_flag = false; | ||
100 | 100 | ||
101 | if (size <= 2*PAGE_SIZE) | 101 | if (size <= 2*PAGE_SIZE) |
102 | mem->pages = kmalloc(size, GFP_KERNEL | __GFP_NORETRY); | 102 | mem->pages = kmalloc(size, GFP_KERNEL | __GFP_NOWARN); |
103 | if (mem->pages == NULL) { | 103 | if (mem->pages == NULL) { |
104 | mem->pages = vmalloc(size); | 104 | mem->pages = vmalloc(size); |
105 | mem->vmalloc_flag = true; | ||
106 | } | 105 | } |
107 | } | 106 | } |
108 | EXPORT_SYMBOL(agp_alloc_page_array); | 107 | EXPORT_SYMBOL(agp_alloc_page_array); |
109 | 108 | ||
110 | void agp_free_page_array(struct agp_memory *mem) | 109 | void agp_free_page_array(struct agp_memory *mem) |
111 | { | 110 | { |
112 | if (mem->vmalloc_flag) { | 111 | if (is_vmalloc_addr(mem->pages)) { |
113 | vfree(mem->pages); | 112 | vfree(mem->pages); |
114 | } else { | 113 | } else { |
115 | kfree(mem->pages); | 114 | kfree(mem->pages); |
@@ -438,11 +437,6 @@ int agp_bind_memory(struct agp_memory *curr, off_t pg_start) | |||
438 | curr->is_flushed = true; | 437 | curr->is_flushed = true; |
439 | } | 438 | } |
440 | 439 | ||
441 | if (curr->bridge->driver->agp_map_memory) { | ||
442 | ret_val = curr->bridge->driver->agp_map_memory(curr); | ||
443 | if (ret_val) | ||
444 | return ret_val; | ||
445 | } | ||
446 | ret_val = curr->bridge->driver->insert_memory(curr, pg_start, curr->type); | 440 | ret_val = curr->bridge->driver->insert_memory(curr, pg_start, curr->type); |
447 | 441 | ||
448 | if (ret_val != 0) | 442 | if (ret_val != 0) |
@@ -484,9 +478,6 @@ int agp_unbind_memory(struct agp_memory *curr) | |||
484 | if (ret_val != 0) | 478 | if (ret_val != 0) |
485 | return ret_val; | 479 | return ret_val; |
486 | 480 | ||
487 | if (curr->bridge->driver->agp_unmap_memory) | ||
488 | curr->bridge->driver->agp_unmap_memory(curr); | ||
489 | |||
490 | curr->is_bound = false; | 481 | curr->is_bound = false; |
491 | curr->pg_start = 0; | 482 | curr->pg_start = 0; |
492 | spin_lock(&curr->bridge->mapped_lock); | 483 | spin_lock(&curr->bridge->mapped_lock); |
@@ -985,7 +976,9 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge) | |||
985 | 976 | ||
986 | bridge->driver->cache_flush(); | 977 | bridge->driver->cache_flush(); |
987 | #ifdef CONFIG_X86 | 978 | #ifdef CONFIG_X86 |
988 | set_memory_uc((unsigned long)table, 1 << page_order); | 979 | if (set_memory_uc((unsigned long)table, 1 << page_order)) |
980 | printk(KERN_WARNING "Could not set GATT table memory to UC!"); | ||
981 | |||
989 | bridge->gatt_table = (void *)table; | 982 | bridge->gatt_table = (void *)table; |
990 | #else | 983 | #else |
991 | bridge->gatt_table = ioremap_nocache(virt_to_phys(table), | 984 | bridge->gatt_table = ioremap_nocache(virt_to_phys(table), |
@@ -1213,7 +1206,7 @@ struct agp_memory *agp_generic_alloc_user(size_t page_count, int type) | |||
1213 | return NULL; | 1206 | return NULL; |
1214 | 1207 | ||
1215 | for (i = 0; i < page_count; i++) | 1208 | for (i = 0; i < page_count; i++) |
1216 | new->pages[i] = 0; | 1209 | new->pages[i] = NULL; |
1217 | new->page_count = 0; | 1210 | new->page_count = 0; |
1218 | new->type = type; | 1211 | new->type = type; |
1219 | new->num_scratch_pages = pages; | 1212 | new->num_scratch_pages = pages; |
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index 58752b70efea..056b289a1e89 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/agp_backend.h> | 16 | #include <linux/agp_backend.h> |
17 | #include <linux/log2.h> | 17 | #include <linux/log2.h> |
18 | #include <linux/slab.h> | ||
18 | 19 | ||
19 | #include <asm/acpi-ext.h> | 20 | #include <asm/acpi-ext.h> |
20 | 21 | ||
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index e763d3312ce7..75b763cb3ea1 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * For documentation on the i460 AGP interface, see Chapter 7 (AGP Subsystem) of | 2 | * For documentation on the i460 AGP interface, see Chapter 7 (AGP Subsystem) of |
3 | * the "Intel 460GTX Chipset Software Developer's Manual": | 3 | * the "Intel 460GTX Chipset Software Developer's Manual": |
4 | * http://developer.intel.com/design/itanium/downloads/24870401s.htm | 4 | * http://www.intel.com/design/archives/itanium/downloads/248704.htm |
5 | */ | 5 | */ |
6 | /* | 6 | /* |
7 | * 460GX support by Chris Ahna <christopher.j.ahna@intel.com> | 7 | * 460GX support by Chris Ahna <christopher.j.ahna@intel.com> |
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 3999a5f25f38..e72f49d52202 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c | |||
@@ -4,1421 +4,17 @@ | |||
4 | 4 | ||
5 | #include <linux/module.h> | 5 | #include <linux/module.h> |
6 | #include <linux/pci.h> | 6 | #include <linux/pci.h> |
7 | #include <linux/slab.h> | ||
7 | #include <linux/init.h> | 8 | #include <linux/init.h> |
8 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
9 | #include <linux/pagemap.h> | 10 | #include <linux/pagemap.h> |
10 | #include <linux/agp_backend.h> | 11 | #include <linux/agp_backend.h> |
12 | #include <asm/smp.h> | ||
11 | #include "agp.h" | 13 | #include "agp.h" |
14 | #include "intel-agp.h" | ||
12 | 15 | ||
13 | /* | 16 | int intel_agp_enabled; |
14 | * If we have Intel graphics, we're not going to have anything other than | 17 | EXPORT_SYMBOL(intel_agp_enabled); |
15 | * an Intel IOMMU. So make the correct use of the PCI DMA API contingent | ||
16 | * on the Intel IOMMU support (CONFIG_DMAR). | ||
17 | * Only newer chipsets need to bother with this, of course. | ||
18 | */ | ||
19 | #ifdef CONFIG_DMAR | ||
20 | #define USE_PCI_DMA_API 1 | ||
21 | #endif | ||
22 | |||
23 | #define PCI_DEVICE_ID_INTEL_E7221_HB 0x2588 | ||
24 | #define PCI_DEVICE_ID_INTEL_E7221_IG 0x258a | ||
25 | #define PCI_DEVICE_ID_INTEL_82946GZ_HB 0x2970 | ||
26 | #define PCI_DEVICE_ID_INTEL_82946GZ_IG 0x2972 | ||
27 | #define PCI_DEVICE_ID_INTEL_82G35_HB 0x2980 | ||
28 | #define PCI_DEVICE_ID_INTEL_82G35_IG 0x2982 | ||
29 | #define PCI_DEVICE_ID_INTEL_82965Q_HB 0x2990 | ||
30 | #define PCI_DEVICE_ID_INTEL_82965Q_IG 0x2992 | ||
31 | #define PCI_DEVICE_ID_INTEL_82965G_HB 0x29A0 | ||
32 | #define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2 | ||
33 | #define PCI_DEVICE_ID_INTEL_82965GM_HB 0x2A00 | ||
34 | #define PCI_DEVICE_ID_INTEL_82965GM_IG 0x2A02 | ||
35 | #define PCI_DEVICE_ID_INTEL_82965GME_HB 0x2A10 | ||
36 | #define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12 | ||
37 | #define PCI_DEVICE_ID_INTEL_82945GME_HB 0x27AC | ||
38 | #define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE | ||
39 | #define PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB 0xA010 | ||
40 | #define PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG 0xA011 | ||
41 | #define PCI_DEVICE_ID_INTEL_PINEVIEW_HB 0xA000 | ||
42 | #define PCI_DEVICE_ID_INTEL_PINEVIEW_IG 0xA001 | ||
43 | #define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0 | ||
44 | #define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2 | ||
45 | #define PCI_DEVICE_ID_INTEL_Q35_HB 0x29B0 | ||
46 | #define PCI_DEVICE_ID_INTEL_Q35_IG 0x29B2 | ||
47 | #define PCI_DEVICE_ID_INTEL_Q33_HB 0x29D0 | ||
48 | #define PCI_DEVICE_ID_INTEL_Q33_IG 0x29D2 | ||
49 | #define PCI_DEVICE_ID_INTEL_B43_HB 0x2E40 | ||
50 | #define PCI_DEVICE_ID_INTEL_B43_IG 0x2E42 | ||
51 | #define PCI_DEVICE_ID_INTEL_GM45_HB 0x2A40 | ||
52 | #define PCI_DEVICE_ID_INTEL_GM45_IG 0x2A42 | ||
53 | #define PCI_DEVICE_ID_INTEL_EAGLELAKE_HB 0x2E00 | ||
54 | #define PCI_DEVICE_ID_INTEL_EAGLELAKE_IG 0x2E02 | ||
55 | #define PCI_DEVICE_ID_INTEL_Q45_HB 0x2E10 | ||
56 | #define PCI_DEVICE_ID_INTEL_Q45_IG 0x2E12 | ||
57 | #define PCI_DEVICE_ID_INTEL_G45_HB 0x2E20 | ||
58 | #define PCI_DEVICE_ID_INTEL_G45_IG 0x2E22 | ||
59 | #define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30 | ||
60 | #define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32 | ||
61 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB 0x0040 | ||
62 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG 0x0042 | ||
63 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB 0x0044 | ||
64 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062 | ||
65 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a | ||
66 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046 | ||
67 | |||
68 | /* cover 915 and 945 variants */ | ||
69 | #define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \ | ||
70 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || \ | ||
71 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || \ | ||
72 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || \ | ||
73 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || \ | ||
74 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GME_HB) | ||
75 | |||
76 | #define IS_I965 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \ | ||
77 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82G35_HB || \ | ||
78 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \ | ||
79 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \ | ||
80 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB || \ | ||
81 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB) | ||
82 | |||
83 | #define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \ | ||
84 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \ | ||
85 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q33_HB || \ | ||
86 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB || \ | ||
87 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB) | ||
88 | |||
89 | #define IS_PINEVIEW (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB || \ | ||
90 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB) | ||
91 | |||
92 | #define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_EAGLELAKE_HB || \ | ||
93 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \ | ||
94 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB || \ | ||
95 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB || \ | ||
96 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G41_HB || \ | ||
97 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_B43_HB || \ | ||
98 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB || \ | ||
99 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || \ | ||
100 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB || \ | ||
101 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB) | ||
102 | |||
103 | extern int agp_memory_reserved; | ||
104 | |||
105 | |||
106 | /* Intel 815 register */ | ||
107 | #define INTEL_815_APCONT 0x51 | ||
108 | #define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF | ||
109 | |||
110 | /* Intel i820 registers */ | ||
111 | #define INTEL_I820_RDCR 0x51 | ||
112 | #define INTEL_I820_ERRSTS 0xc8 | ||
113 | |||
114 | /* Intel i840 registers */ | ||
115 | #define INTEL_I840_MCHCFG 0x50 | ||
116 | #define INTEL_I840_ERRSTS 0xc8 | ||
117 | |||
118 | /* Intel i850 registers */ | ||
119 | #define INTEL_I850_MCHCFG 0x50 | ||
120 | #define INTEL_I850_ERRSTS 0xc8 | ||
121 | |||
122 | /* intel 915G registers */ | ||
123 | #define I915_GMADDR 0x18 | ||
124 | #define I915_MMADDR 0x10 | ||
125 | #define I915_PTEADDR 0x1C | ||
126 | #define I915_GMCH_GMS_STOLEN_48M (0x6 << 4) | ||
127 | #define I915_GMCH_GMS_STOLEN_64M (0x7 << 4) | ||
128 | #define G33_GMCH_GMS_STOLEN_128M (0x8 << 4) | ||
129 | #define G33_GMCH_GMS_STOLEN_256M (0x9 << 4) | ||
130 | #define INTEL_GMCH_GMS_STOLEN_96M (0xa << 4) | ||
131 | #define INTEL_GMCH_GMS_STOLEN_160M (0xb << 4) | ||
132 | #define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4) | ||
133 | #define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4) | ||
134 | |||
135 | #define I915_IFPADDR 0x60 | ||
136 | |||
137 | /* Intel 965G registers */ | ||
138 | #define I965_MSAC 0x62 | ||
139 | #define I965_IFPADDR 0x70 | ||
140 | |||
141 | /* Intel 7505 registers */ | ||
142 | #define INTEL_I7505_APSIZE 0x74 | ||
143 | #define INTEL_I7505_NCAPID 0x60 | ||
144 | #define INTEL_I7505_NISTAT 0x6c | ||
145 | #define INTEL_I7505_ATTBASE 0x78 | ||
146 | #define INTEL_I7505_ERRSTS 0x42 | ||
147 | #define INTEL_I7505_AGPCTRL 0x70 | ||
148 | #define INTEL_I7505_MCHCFG 0x50 | ||
149 | |||
150 | static const struct aper_size_info_fixed intel_i810_sizes[] = | ||
151 | { | ||
152 | {64, 16384, 4}, | ||
153 | /* The 32M mode still requires a 64k gatt */ | ||
154 | {32, 8192, 4} | ||
155 | }; | ||
156 | |||
157 | #define AGP_DCACHE_MEMORY 1 | ||
158 | #define AGP_PHYS_MEMORY 2 | ||
159 | #define INTEL_AGP_CACHED_MEMORY 3 | ||
160 | |||
161 | static struct gatt_mask intel_i810_masks[] = | ||
162 | { | ||
163 | {.mask = I810_PTE_VALID, .type = 0}, | ||
164 | {.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY}, | ||
165 | {.mask = I810_PTE_VALID, .type = 0}, | ||
166 | {.mask = I810_PTE_VALID | I830_PTE_SYSTEM_CACHED, | ||
167 | .type = INTEL_AGP_CACHED_MEMORY} | ||
168 | }; | ||
169 | |||
170 | static struct _intel_private { | ||
171 | struct pci_dev *pcidev; /* device one */ | ||
172 | u8 __iomem *registers; | ||
173 | u32 __iomem *gtt; /* I915G */ | ||
174 | int num_dcache_entries; | ||
175 | /* gtt_entries is the number of gtt entries that are already mapped | ||
176 | * to stolen memory. Stolen memory is larger than the memory mapped | ||
177 | * through gtt_entries, as it includes some reserved space for the BIOS | ||
178 | * popup and for the GTT. | ||
179 | */ | ||
180 | int gtt_entries; /* i830+ */ | ||
181 | int gtt_total_size; | ||
182 | union { | ||
183 | void __iomem *i9xx_flush_page; | ||
184 | void *i8xx_flush_page; | ||
185 | }; | ||
186 | struct page *i8xx_page; | ||
187 | struct resource ifp_resource; | ||
188 | int resource_valid; | ||
189 | } intel_private; | ||
190 | |||
191 | #ifdef USE_PCI_DMA_API | ||
192 | static int intel_agp_map_page(struct page *page, dma_addr_t *ret) | ||
193 | { | ||
194 | *ret = pci_map_page(intel_private.pcidev, page, 0, | ||
195 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | ||
196 | if (pci_dma_mapping_error(intel_private.pcidev, *ret)) | ||
197 | return -EINVAL; | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static void intel_agp_unmap_page(struct page *page, dma_addr_t dma) | ||
202 | { | ||
203 | pci_unmap_page(intel_private.pcidev, dma, | ||
204 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | ||
205 | } | ||
206 | |||
207 | static void intel_agp_free_sglist(struct agp_memory *mem) | ||
208 | { | ||
209 | struct sg_table st; | ||
210 | |||
211 | st.sgl = mem->sg_list; | ||
212 | st.orig_nents = st.nents = mem->page_count; | ||
213 | |||
214 | sg_free_table(&st); | ||
215 | |||
216 | mem->sg_list = NULL; | ||
217 | mem->num_sg = 0; | ||
218 | } | ||
219 | |||
220 | static int intel_agp_map_memory(struct agp_memory *mem) | ||
221 | { | ||
222 | struct sg_table st; | ||
223 | struct scatterlist *sg; | ||
224 | int i; | ||
225 | |||
226 | DBG("try mapping %lu pages\n", (unsigned long)mem->page_count); | ||
227 | |||
228 | if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL)) | ||
229 | return -ENOMEM; | ||
230 | |||
231 | mem->sg_list = sg = st.sgl; | ||
232 | |||
233 | for (i = 0 ; i < mem->page_count; i++, sg = sg_next(sg)) | ||
234 | sg_set_page(sg, mem->pages[i], PAGE_SIZE, 0); | ||
235 | |||
236 | mem->num_sg = pci_map_sg(intel_private.pcidev, mem->sg_list, | ||
237 | mem->page_count, PCI_DMA_BIDIRECTIONAL); | ||
238 | if (unlikely(!mem->num_sg)) { | ||
239 | intel_agp_free_sglist(mem); | ||
240 | return -ENOMEM; | ||
241 | } | ||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static void intel_agp_unmap_memory(struct agp_memory *mem) | ||
246 | { | ||
247 | DBG("try unmapping %lu pages\n", (unsigned long)mem->page_count); | ||
248 | |||
249 | pci_unmap_sg(intel_private.pcidev, mem->sg_list, | ||
250 | mem->page_count, PCI_DMA_BIDIRECTIONAL); | ||
251 | intel_agp_free_sglist(mem); | ||
252 | } | ||
253 | |||
254 | static void intel_agp_insert_sg_entries(struct agp_memory *mem, | ||
255 | off_t pg_start, int mask_type) | ||
256 | { | ||
257 | struct scatterlist *sg; | ||
258 | int i, j; | ||
259 | |||
260 | j = pg_start; | ||
261 | |||
262 | WARN_ON(!mem->num_sg); | ||
263 | |||
264 | if (mem->num_sg == mem->page_count) { | ||
265 | for_each_sg(mem->sg_list, sg, mem->page_count, i) { | ||
266 | writel(agp_bridge->driver->mask_memory(agp_bridge, | ||
267 | sg_dma_address(sg), mask_type), | ||
268 | intel_private.gtt+j); | ||
269 | j++; | ||
270 | } | ||
271 | } else { | ||
272 | /* sg may merge pages, but we have to seperate | ||
273 | * per-page addr for GTT */ | ||
274 | unsigned int len, m; | ||
275 | |||
276 | for_each_sg(mem->sg_list, sg, mem->num_sg, i) { | ||
277 | len = sg_dma_len(sg) / PAGE_SIZE; | ||
278 | for (m = 0; m < len; m++) { | ||
279 | writel(agp_bridge->driver->mask_memory(agp_bridge, | ||
280 | sg_dma_address(sg) + m * PAGE_SIZE, | ||
281 | mask_type), | ||
282 | intel_private.gtt+j); | ||
283 | j++; | ||
284 | } | ||
285 | } | ||
286 | } | ||
287 | readl(intel_private.gtt+j-1); | ||
288 | } | ||
289 | |||
290 | #else | ||
291 | |||
292 | static void intel_agp_insert_sg_entries(struct agp_memory *mem, | ||
293 | off_t pg_start, int mask_type) | ||
294 | { | ||
295 | int i, j; | ||
296 | |||
297 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | ||
298 | writel(agp_bridge->driver->mask_memory(agp_bridge, | ||
299 | page_to_phys(mem->pages[i]), mask_type), | ||
300 | intel_private.gtt+j); | ||
301 | } | ||
302 | |||
303 | readl(intel_private.gtt+j-1); | ||
304 | } | ||
305 | |||
306 | #endif | ||
307 | |||
308 | static int intel_i810_fetch_size(void) | ||
309 | { | ||
310 | u32 smram_miscc; | ||
311 | struct aper_size_info_fixed *values; | ||
312 | |||
313 | pci_read_config_dword(agp_bridge->dev, I810_SMRAM_MISCC, &smram_miscc); | ||
314 | values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); | ||
315 | |||
316 | if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) { | ||
317 | dev_warn(&agp_bridge->dev->dev, "i810 is disabled\n"); | ||
318 | return 0; | ||
319 | } | ||
320 | if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) { | ||
321 | agp_bridge->previous_size = | ||
322 | agp_bridge->current_size = (void *) (values + 1); | ||
323 | agp_bridge->aperture_size_idx = 1; | ||
324 | return values[1].size; | ||
325 | } else { | ||
326 | agp_bridge->previous_size = | ||
327 | agp_bridge->current_size = (void *) (values); | ||
328 | agp_bridge->aperture_size_idx = 0; | ||
329 | return values[0].size; | ||
330 | } | ||
331 | |||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | static int intel_i810_configure(void) | ||
336 | { | ||
337 | struct aper_size_info_fixed *current_size; | ||
338 | u32 temp; | ||
339 | int i; | ||
340 | |||
341 | current_size = A_SIZE_FIX(agp_bridge->current_size); | ||
342 | |||
343 | if (!intel_private.registers) { | ||
344 | pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp); | ||
345 | temp &= 0xfff80000; | ||
346 | |||
347 | intel_private.registers = ioremap(temp, 128 * 4096); | ||
348 | if (!intel_private.registers) { | ||
349 | dev_err(&intel_private.pcidev->dev, | ||
350 | "can't remap memory\n"); | ||
351 | return -ENOMEM; | ||
352 | } | ||
353 | } | ||
354 | |||
355 | if ((readl(intel_private.registers+I810_DRAM_CTL) | ||
356 | & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) { | ||
357 | /* This will need to be dynamically assigned */ | ||
358 | dev_info(&intel_private.pcidev->dev, | ||
359 | "detected 4MB dedicated video ram\n"); | ||
360 | intel_private.num_dcache_entries = 1024; | ||
361 | } | ||
362 | pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp); | ||
363 | agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); | ||
364 | writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL); | ||
365 | readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ | ||
366 | |||
367 | if (agp_bridge->driver->needs_scratch_page) { | ||
368 | for (i = 0; i < current_size->num_entries; i++) { | ||
369 | writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); | ||
370 | } | ||
371 | readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI posting. */ | ||
372 | } | ||
373 | global_cache_flush(); | ||
374 | return 0; | ||
375 | } | ||
376 | |||
377 | static void intel_i810_cleanup(void) | ||
378 | { | ||
379 | writel(0, intel_private.registers+I810_PGETBL_CTL); | ||
380 | readl(intel_private.registers); /* PCI Posting. */ | ||
381 | iounmap(intel_private.registers); | ||
382 | } | ||
383 | |||
384 | static void intel_i810_tlbflush(struct agp_memory *mem) | ||
385 | { | ||
386 | return; | ||
387 | } | ||
388 | |||
389 | static void intel_i810_agp_enable(struct agp_bridge_data *bridge, u32 mode) | ||
390 | { | ||
391 | return; | ||
392 | } | ||
393 | |||
394 | /* Exists to support ARGB cursors */ | ||
395 | static struct page *i8xx_alloc_pages(void) | ||
396 | { | ||
397 | struct page *page; | ||
398 | |||
399 | page = alloc_pages(GFP_KERNEL | GFP_DMA32, 2); | ||
400 | if (page == NULL) | ||
401 | return NULL; | ||
402 | |||
403 | if (set_pages_uc(page, 4) < 0) { | ||
404 | set_pages_wb(page, 4); | ||
405 | __free_pages(page, 2); | ||
406 | return NULL; | ||
407 | } | ||
408 | get_page(page); | ||
409 | atomic_inc(&agp_bridge->current_memory_agp); | ||
410 | return page; | ||
411 | } | ||
412 | |||
413 | static void i8xx_destroy_pages(struct page *page) | ||
414 | { | ||
415 | if (page == NULL) | ||
416 | return; | ||
417 | |||
418 | set_pages_wb(page, 4); | ||
419 | put_page(page); | ||
420 | __free_pages(page, 2); | ||
421 | atomic_dec(&agp_bridge->current_memory_agp); | ||
422 | } | ||
423 | |||
424 | static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge, | ||
425 | int type) | ||
426 | { | ||
427 | if (type < AGP_USER_TYPES) | ||
428 | return type; | ||
429 | else if (type == AGP_USER_CACHED_MEMORY) | ||
430 | return INTEL_AGP_CACHED_MEMORY; | ||
431 | else | ||
432 | return 0; | ||
433 | } | ||
434 | |||
435 | static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, | ||
436 | int type) | ||
437 | { | ||
438 | int i, j, num_entries; | ||
439 | void *temp; | ||
440 | int ret = -EINVAL; | ||
441 | int mask_type; | ||
442 | |||
443 | if (mem->page_count == 0) | ||
444 | goto out; | ||
445 | |||
446 | temp = agp_bridge->current_size; | ||
447 | num_entries = A_SIZE_FIX(temp)->num_entries; | ||
448 | |||
449 | if ((pg_start + mem->page_count) > num_entries) | ||
450 | goto out_err; | ||
451 | |||
452 | |||
453 | for (j = pg_start; j < (pg_start + mem->page_count); j++) { | ||
454 | if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) { | ||
455 | ret = -EBUSY; | ||
456 | goto out_err; | ||
457 | } | ||
458 | } | ||
459 | |||
460 | if (type != mem->type) | ||
461 | goto out_err; | ||
462 | |||
463 | mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); | ||
464 | |||
465 | switch (mask_type) { | ||
466 | case AGP_DCACHE_MEMORY: | ||
467 | if (!mem->is_flushed) | ||
468 | global_cache_flush(); | ||
469 | for (i = pg_start; i < (pg_start + mem->page_count); i++) { | ||
470 | writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, | ||
471 | intel_private.registers+I810_PTE_BASE+(i*4)); | ||
472 | } | ||
473 | readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); | ||
474 | break; | ||
475 | case AGP_PHYS_MEMORY: | ||
476 | case AGP_NORMAL_MEMORY: | ||
477 | if (!mem->is_flushed) | ||
478 | global_cache_flush(); | ||
479 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | ||
480 | writel(agp_bridge->driver->mask_memory(agp_bridge, | ||
481 | page_to_phys(mem->pages[i]), mask_type), | ||
482 | intel_private.registers+I810_PTE_BASE+(j*4)); | ||
483 | } | ||
484 | readl(intel_private.registers+I810_PTE_BASE+((j-1)*4)); | ||
485 | break; | ||
486 | default: | ||
487 | goto out_err; | ||
488 | } | ||
489 | |||
490 | agp_bridge->driver->tlb_flush(mem); | ||
491 | out: | ||
492 | ret = 0; | ||
493 | out_err: | ||
494 | mem->is_flushed = true; | ||
495 | return ret; | ||
496 | } | ||
497 | |||
498 | static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start, | ||
499 | int type) | ||
500 | { | ||
501 | int i; | ||
502 | |||
503 | if (mem->page_count == 0) | ||
504 | return 0; | ||
505 | |||
506 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | ||
507 | writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); | ||
508 | } | ||
509 | readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); | ||
510 | |||
511 | agp_bridge->driver->tlb_flush(mem); | ||
512 | return 0; | ||
513 | } | ||
514 | |||
515 | /* | ||
516 | * The i810/i830 requires a physical address to program its mouse | ||
517 | * pointer into hardware. | ||
518 | * However the Xserver still writes to it through the agp aperture. | ||
519 | */ | ||
520 | static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type) | ||
521 | { | ||
522 | struct agp_memory *new; | ||
523 | struct page *page; | ||
524 | |||
525 | switch (pg_count) { | ||
526 | case 1: page = agp_bridge->driver->agp_alloc_page(agp_bridge); | ||
527 | break; | ||
528 | case 4: | ||
529 | /* kludge to get 4 physical pages for ARGB cursor */ | ||
530 | page = i8xx_alloc_pages(); | ||
531 | break; | ||
532 | default: | ||
533 | return NULL; | ||
534 | } | ||
535 | |||
536 | if (page == NULL) | ||
537 | return NULL; | ||
538 | |||
539 | new = agp_create_memory(pg_count); | ||
540 | if (new == NULL) | ||
541 | return NULL; | ||
542 | |||
543 | new->pages[0] = page; | ||
544 | if (pg_count == 4) { | ||
545 | /* kludge to get 4 physical pages for ARGB cursor */ | ||
546 | new->pages[1] = new->pages[0] + 1; | ||
547 | new->pages[2] = new->pages[1] + 1; | ||
548 | new->pages[3] = new->pages[2] + 1; | ||
549 | } | ||
550 | new->page_count = pg_count; | ||
551 | new->num_scratch_pages = pg_count; | ||
552 | new->type = AGP_PHYS_MEMORY; | ||
553 | new->physical = page_to_phys(new->pages[0]); | ||
554 | return new; | ||
555 | } | ||
556 | |||
557 | static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type) | ||
558 | { | ||
559 | struct agp_memory *new; | ||
560 | |||
561 | if (type == AGP_DCACHE_MEMORY) { | ||
562 | if (pg_count != intel_private.num_dcache_entries) | ||
563 | return NULL; | ||
564 | |||
565 | new = agp_create_memory(1); | ||
566 | if (new == NULL) | ||
567 | return NULL; | ||
568 | |||
569 | new->type = AGP_DCACHE_MEMORY; | ||
570 | new->page_count = pg_count; | ||
571 | new->num_scratch_pages = 0; | ||
572 | agp_free_page_array(new); | ||
573 | return new; | ||
574 | } | ||
575 | if (type == AGP_PHYS_MEMORY) | ||
576 | return alloc_agpphysmem_i8xx(pg_count, type); | ||
577 | return NULL; | ||
578 | } | ||
579 | |||
580 | static void intel_i810_free_by_type(struct agp_memory *curr) | ||
581 | { | ||
582 | agp_free_key(curr->key); | ||
583 | if (curr->type == AGP_PHYS_MEMORY) { | ||
584 | if (curr->page_count == 4) | ||
585 | i8xx_destroy_pages(curr->pages[0]); | ||
586 | else { | ||
587 | agp_bridge->driver->agp_destroy_page(curr->pages[0], | ||
588 | AGP_PAGE_DESTROY_UNMAP); | ||
589 | agp_bridge->driver->agp_destroy_page(curr->pages[0], | ||
590 | AGP_PAGE_DESTROY_FREE); | ||
591 | } | ||
592 | agp_free_page_array(curr); | ||
593 | } | ||
594 | kfree(curr); | ||
595 | } | ||
596 | |||
597 | static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge, | ||
598 | dma_addr_t addr, int type) | ||
599 | { | ||
600 | /* Type checking must be done elsewhere */ | ||
601 | return addr | bridge->driver->masks[type].mask; | ||
602 | } | ||
603 | |||
604 | static struct aper_size_info_fixed intel_i830_sizes[] = | ||
605 | { | ||
606 | {128, 32768, 5}, | ||
607 | /* The 64M mode still requires a 128k gatt */ | ||
608 | {64, 16384, 5}, | ||
609 | {256, 65536, 6}, | ||
610 | {512, 131072, 7}, | ||
611 | }; | ||
612 | |||
613 | static void intel_i830_init_gtt_entries(void) | ||
614 | { | ||
615 | u16 gmch_ctrl; | ||
616 | int gtt_entries; | ||
617 | u8 rdct; | ||
618 | int local = 0; | ||
619 | static const int ddt[4] = { 0, 16, 32, 64 }; | ||
620 | int size; /* reserved space (in kb) at the top of stolen memory */ | ||
621 | |||
622 | pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl); | ||
623 | |||
624 | if (IS_I965) { | ||
625 | u32 pgetbl_ctl; | ||
626 | pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL); | ||
627 | |||
628 | /* The 965 has a field telling us the size of the GTT, | ||
629 | * which may be larger than what is necessary to map the | ||
630 | * aperture. | ||
631 | */ | ||
632 | switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) { | ||
633 | case I965_PGETBL_SIZE_128KB: | ||
634 | size = 128; | ||
635 | break; | ||
636 | case I965_PGETBL_SIZE_256KB: | ||
637 | size = 256; | ||
638 | break; | ||
639 | case I965_PGETBL_SIZE_512KB: | ||
640 | size = 512; | ||
641 | break; | ||
642 | case I965_PGETBL_SIZE_1MB: | ||
643 | size = 1024; | ||
644 | break; | ||
645 | case I965_PGETBL_SIZE_2MB: | ||
646 | size = 2048; | ||
647 | break; | ||
648 | case I965_PGETBL_SIZE_1_5MB: | ||
649 | size = 1024 + 512; | ||
650 | break; | ||
651 | default: | ||
652 | dev_info(&intel_private.pcidev->dev, | ||
653 | "unknown page table size, assuming 512KB\n"); | ||
654 | size = 512; | ||
655 | } | ||
656 | size += 4; /* add in BIOS popup space */ | ||
657 | } else if (IS_G33 && !IS_PINEVIEW) { | ||
658 | /* G33's GTT size defined in gmch_ctrl */ | ||
659 | switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) { | ||
660 | case G33_PGETBL_SIZE_1M: | ||
661 | size = 1024; | ||
662 | break; | ||
663 | case G33_PGETBL_SIZE_2M: | ||
664 | size = 2048; | ||
665 | break; | ||
666 | default: | ||
667 | dev_info(&agp_bridge->dev->dev, | ||
668 | "unknown page table size 0x%x, assuming 512KB\n", | ||
669 | (gmch_ctrl & G33_PGETBL_SIZE_MASK)); | ||
670 | size = 512; | ||
671 | } | ||
672 | size += 4; | ||
673 | } else if (IS_G4X || IS_PINEVIEW) { | ||
674 | /* On 4 series hardware, GTT stolen is separate from graphics | ||
675 | * stolen, ignore it in stolen gtt entries counting. However, | ||
676 | * 4KB of the stolen memory doesn't get mapped to the GTT. | ||
677 | */ | ||
678 | size = 4; | ||
679 | } else { | ||
680 | /* On previous hardware, the GTT size was just what was | ||
681 | * required to map the aperture. | ||
682 | */ | ||
683 | size = agp_bridge->driver->fetch_size() + 4; | ||
684 | } | ||
685 | |||
686 | if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB || | ||
687 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) { | ||
688 | switch (gmch_ctrl & I830_GMCH_GMS_MASK) { | ||
689 | case I830_GMCH_GMS_STOLEN_512: | ||
690 | gtt_entries = KB(512) - KB(size); | ||
691 | break; | ||
692 | case I830_GMCH_GMS_STOLEN_1024: | ||
693 | gtt_entries = MB(1) - KB(size); | ||
694 | break; | ||
695 | case I830_GMCH_GMS_STOLEN_8192: | ||
696 | gtt_entries = MB(8) - KB(size); | ||
697 | break; | ||
698 | case I830_GMCH_GMS_LOCAL: | ||
699 | rdct = readb(intel_private.registers+I830_RDRAM_CHANNEL_TYPE); | ||
700 | gtt_entries = (I830_RDRAM_ND(rdct) + 1) * | ||
701 | MB(ddt[I830_RDRAM_DDT(rdct)]); | ||
702 | local = 1; | ||
703 | break; | ||
704 | default: | ||
705 | gtt_entries = 0; | ||
706 | break; | ||
707 | } | ||
708 | } else { | ||
709 | switch (gmch_ctrl & I855_GMCH_GMS_MASK) { | ||
710 | case I855_GMCH_GMS_STOLEN_1M: | ||
711 | gtt_entries = MB(1) - KB(size); | ||
712 | break; | ||
713 | case I855_GMCH_GMS_STOLEN_4M: | ||
714 | gtt_entries = MB(4) - KB(size); | ||
715 | break; | ||
716 | case I855_GMCH_GMS_STOLEN_8M: | ||
717 | gtt_entries = MB(8) - KB(size); | ||
718 | break; | ||
719 | case I855_GMCH_GMS_STOLEN_16M: | ||
720 | gtt_entries = MB(16) - KB(size); | ||
721 | break; | ||
722 | case I855_GMCH_GMS_STOLEN_32M: | ||
723 | gtt_entries = MB(32) - KB(size); | ||
724 | break; | ||
725 | case I915_GMCH_GMS_STOLEN_48M: | ||
726 | /* Check it's really I915G */ | ||
727 | if (IS_I915 || IS_I965 || IS_G33 || IS_G4X) | ||
728 | gtt_entries = MB(48) - KB(size); | ||
729 | else | ||
730 | gtt_entries = 0; | ||
731 | break; | ||
732 | case I915_GMCH_GMS_STOLEN_64M: | ||
733 | /* Check it's really I915G */ | ||
734 | if (IS_I915 || IS_I965 || IS_G33 || IS_G4X) | ||
735 | gtt_entries = MB(64) - KB(size); | ||
736 | else | ||
737 | gtt_entries = 0; | ||
738 | break; | ||
739 | case G33_GMCH_GMS_STOLEN_128M: | ||
740 | if (IS_G33 || IS_I965 || IS_G4X) | ||
741 | gtt_entries = MB(128) - KB(size); | ||
742 | else | ||
743 | gtt_entries = 0; | ||
744 | break; | ||
745 | case G33_GMCH_GMS_STOLEN_256M: | ||
746 | if (IS_G33 || IS_I965 || IS_G4X) | ||
747 | gtt_entries = MB(256) - KB(size); | ||
748 | else | ||
749 | gtt_entries = 0; | ||
750 | break; | ||
751 | case INTEL_GMCH_GMS_STOLEN_96M: | ||
752 | if (IS_I965 || IS_G4X) | ||
753 | gtt_entries = MB(96) - KB(size); | ||
754 | else | ||
755 | gtt_entries = 0; | ||
756 | break; | ||
757 | case INTEL_GMCH_GMS_STOLEN_160M: | ||
758 | if (IS_I965 || IS_G4X) | ||
759 | gtt_entries = MB(160) - KB(size); | ||
760 | else | ||
761 | gtt_entries = 0; | ||
762 | break; | ||
763 | case INTEL_GMCH_GMS_STOLEN_224M: | ||
764 | if (IS_I965 || IS_G4X) | ||
765 | gtt_entries = MB(224) - KB(size); | ||
766 | else | ||
767 | gtt_entries = 0; | ||
768 | break; | ||
769 | case INTEL_GMCH_GMS_STOLEN_352M: | ||
770 | if (IS_I965 || IS_G4X) | ||
771 | gtt_entries = MB(352) - KB(size); | ||
772 | else | ||
773 | gtt_entries = 0; | ||
774 | break; | ||
775 | default: | ||
776 | gtt_entries = 0; | ||
777 | break; | ||
778 | } | ||
779 | } | ||
780 | if (gtt_entries > 0) { | ||
781 | dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n", | ||
782 | gtt_entries / KB(1), local ? "local" : "stolen"); | ||
783 | gtt_entries /= KB(4); | ||
784 | } else { | ||
785 | dev_info(&agp_bridge->dev->dev, | ||
786 | "no pre-allocated video memory detected\n"); | ||
787 | gtt_entries = 0; | ||
788 | } | ||
789 | |||
790 | intel_private.gtt_entries = gtt_entries; | ||
791 | } | ||
792 | |||
793 | static void intel_i830_fini_flush(void) | ||
794 | { | ||
795 | kunmap(intel_private.i8xx_page); | ||
796 | intel_private.i8xx_flush_page = NULL; | ||
797 | unmap_page_from_agp(intel_private.i8xx_page); | ||
798 | |||
799 | __free_page(intel_private.i8xx_page); | ||
800 | intel_private.i8xx_page = NULL; | ||
801 | } | ||
802 | |||
803 | static void intel_i830_setup_flush(void) | ||
804 | { | ||
805 | /* return if we've already set the flush mechanism up */ | ||
806 | if (intel_private.i8xx_page) | ||
807 | return; | ||
808 | |||
809 | intel_private.i8xx_page = alloc_page(GFP_KERNEL | __GFP_ZERO | GFP_DMA32); | ||
810 | if (!intel_private.i8xx_page) | ||
811 | return; | ||
812 | |||
813 | intel_private.i8xx_flush_page = kmap(intel_private.i8xx_page); | ||
814 | if (!intel_private.i8xx_flush_page) | ||
815 | intel_i830_fini_flush(); | ||
816 | } | ||
817 | |||
818 | static void | ||
819 | do_wbinvd(void *null) | ||
820 | { | ||
821 | wbinvd(); | ||
822 | } | ||
823 | |||
824 | /* The chipset_flush interface needs to get data that has already been | ||
825 | * flushed out of the CPU all the way out to main memory, because the GPU | ||
826 | * doesn't snoop those buffers. | ||
827 | * | ||
828 | * The 8xx series doesn't have the same lovely interface for flushing the | ||
829 | * chipset write buffers that the later chips do. According to the 865 | ||
830 | * specs, it's 64 octwords, or 1KB. So, to get those previous things in | ||
831 | * that buffer out, we just fill 1KB and clflush it out, on the assumption | ||
832 | * that it'll push whatever was in there out. It appears to work. | ||
833 | */ | ||
834 | static void intel_i830_chipset_flush(struct agp_bridge_data *bridge) | ||
835 | { | ||
836 | unsigned int *pg = intel_private.i8xx_flush_page; | ||
837 | |||
838 | memset(pg, 0, 1024); | ||
839 | |||
840 | if (cpu_has_clflush) { | ||
841 | clflush_cache_range(pg, 1024); | ||
842 | } else { | ||
843 | if (on_each_cpu(do_wbinvd, NULL, 1) != 0) | ||
844 | printk(KERN_ERR "Timed out waiting for cache flush.\n"); | ||
845 | } | ||
846 | } | ||
847 | |||
848 | /* The intel i830 automatically initializes the agp aperture during POST. | ||
849 | * Use the memory already set aside for in the GTT. | ||
850 | */ | ||
851 | static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge) | ||
852 | { | ||
853 | int page_order; | ||
854 | struct aper_size_info_fixed *size; | ||
855 | int num_entries; | ||
856 | u32 temp; | ||
857 | |||
858 | size = agp_bridge->current_size; | ||
859 | page_order = size->page_order; | ||
860 | num_entries = size->num_entries; | ||
861 | agp_bridge->gatt_table_real = NULL; | ||
862 | |||
863 | pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp); | ||
864 | temp &= 0xfff80000; | ||
865 | |||
866 | intel_private.registers = ioremap(temp, 128 * 4096); | ||
867 | if (!intel_private.registers) | ||
868 | return -ENOMEM; | ||
869 | |||
870 | temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; | ||
871 | global_cache_flush(); /* FIXME: ?? */ | ||
872 | |||
873 | /* we have to call this as early as possible after the MMIO base address is known */ | ||
874 | intel_i830_init_gtt_entries(); | ||
875 | |||
876 | agp_bridge->gatt_table = NULL; | ||
877 | |||
878 | agp_bridge->gatt_bus_addr = temp; | ||
879 | |||
880 | return 0; | ||
881 | } | ||
882 | |||
883 | /* Return the gatt table to a sane state. Use the top of stolen | ||
884 | * memory for the GTT. | ||
885 | */ | ||
886 | static int intel_i830_free_gatt_table(struct agp_bridge_data *bridge) | ||
887 | { | ||
888 | return 0; | ||
889 | } | ||
890 | |||
891 | static int intel_i830_fetch_size(void) | ||
892 | { | ||
893 | u16 gmch_ctrl; | ||
894 | struct aper_size_info_fixed *values; | ||
895 | |||
896 | values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); | ||
897 | |||
898 | if (agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82830_HB && | ||
899 | agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82845G_HB) { | ||
900 | /* 855GM/852GM/865G has 128MB aperture size */ | ||
901 | agp_bridge->previous_size = agp_bridge->current_size = (void *) values; | ||
902 | agp_bridge->aperture_size_idx = 0; | ||
903 | return values[0].size; | ||
904 | } | ||
905 | |||
906 | pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl); | ||
907 | |||
908 | if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) { | ||
909 | agp_bridge->previous_size = agp_bridge->current_size = (void *) values; | ||
910 | agp_bridge->aperture_size_idx = 0; | ||
911 | return values[0].size; | ||
912 | } else { | ||
913 | agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + 1); | ||
914 | agp_bridge->aperture_size_idx = 1; | ||
915 | return values[1].size; | ||
916 | } | ||
917 | |||
918 | return 0; | ||
919 | } | ||
920 | |||
921 | static int intel_i830_configure(void) | ||
922 | { | ||
923 | struct aper_size_info_fixed *current_size; | ||
924 | u32 temp; | ||
925 | u16 gmch_ctrl; | ||
926 | int i; | ||
927 | |||
928 | current_size = A_SIZE_FIX(agp_bridge->current_size); | ||
929 | |||
930 | pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp); | ||
931 | agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); | ||
932 | |||
933 | pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl); | ||
934 | gmch_ctrl |= I830_GMCH_ENABLED; | ||
935 | pci_write_config_word(agp_bridge->dev, I830_GMCH_CTRL, gmch_ctrl); | ||
936 | |||
937 | writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL); | ||
938 | readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ | ||
939 | |||
940 | if (agp_bridge->driver->needs_scratch_page) { | ||
941 | for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) { | ||
942 | writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); | ||
943 | } | ||
944 | readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */ | ||
945 | } | ||
946 | |||
947 | global_cache_flush(); | ||
948 | |||
949 | intel_i830_setup_flush(); | ||
950 | return 0; | ||
951 | } | ||
952 | |||
953 | static void intel_i830_cleanup(void) | ||
954 | { | ||
955 | iounmap(intel_private.registers); | ||
956 | } | ||
957 | |||
958 | static int intel_i830_insert_entries(struct agp_memory *mem, off_t pg_start, | ||
959 | int type) | ||
960 | { | ||
961 | int i, j, num_entries; | ||
962 | void *temp; | ||
963 | int ret = -EINVAL; | ||
964 | int mask_type; | ||
965 | |||
966 | if (mem->page_count == 0) | ||
967 | goto out; | ||
968 | |||
969 | temp = agp_bridge->current_size; | ||
970 | num_entries = A_SIZE_FIX(temp)->num_entries; | ||
971 | |||
972 | if (pg_start < intel_private.gtt_entries) { | ||
973 | dev_printk(KERN_DEBUG, &intel_private.pcidev->dev, | ||
974 | "pg_start == 0x%.8lx, intel_private.gtt_entries == 0x%.8x\n", | ||
975 | pg_start, intel_private.gtt_entries); | ||
976 | |||
977 | dev_info(&intel_private.pcidev->dev, | ||
978 | "trying to insert into local/stolen memory\n"); | ||
979 | goto out_err; | ||
980 | } | ||
981 | |||
982 | if ((pg_start + mem->page_count) > num_entries) | ||
983 | goto out_err; | ||
984 | |||
985 | /* The i830 can't check the GTT for entries since its read only, | ||
986 | * depend on the caller to make the correct offset decisions. | ||
987 | */ | ||
988 | |||
989 | if (type != mem->type) | ||
990 | goto out_err; | ||
991 | |||
992 | mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); | ||
993 | |||
994 | if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY && | ||
995 | mask_type != INTEL_AGP_CACHED_MEMORY) | ||
996 | goto out_err; | ||
997 | |||
998 | if (!mem->is_flushed) | ||
999 | global_cache_flush(); | ||
1000 | |||
1001 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | ||
1002 | writel(agp_bridge->driver->mask_memory(agp_bridge, | ||
1003 | page_to_phys(mem->pages[i]), mask_type), | ||
1004 | intel_private.registers+I810_PTE_BASE+(j*4)); | ||
1005 | } | ||
1006 | readl(intel_private.registers+I810_PTE_BASE+((j-1)*4)); | ||
1007 | agp_bridge->driver->tlb_flush(mem); | ||
1008 | |||
1009 | out: | ||
1010 | ret = 0; | ||
1011 | out_err: | ||
1012 | mem->is_flushed = true; | ||
1013 | return ret; | ||
1014 | } | ||
1015 | |||
1016 | static int intel_i830_remove_entries(struct agp_memory *mem, off_t pg_start, | ||
1017 | int type) | ||
1018 | { | ||
1019 | int i; | ||
1020 | |||
1021 | if (mem->page_count == 0) | ||
1022 | return 0; | ||
1023 | |||
1024 | if (pg_start < intel_private.gtt_entries) { | ||
1025 | dev_info(&intel_private.pcidev->dev, | ||
1026 | "trying to disable local/stolen memory\n"); | ||
1027 | return -EINVAL; | ||
1028 | } | ||
1029 | |||
1030 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | ||
1031 | writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); | ||
1032 | } | ||
1033 | readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); | ||
1034 | |||
1035 | agp_bridge->driver->tlb_flush(mem); | ||
1036 | return 0; | ||
1037 | } | ||
1038 | |||
1039 | static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count, int type) | ||
1040 | { | ||
1041 | if (type == AGP_PHYS_MEMORY) | ||
1042 | return alloc_agpphysmem_i8xx(pg_count, type); | ||
1043 | /* always return NULL for other allocation types for now */ | ||
1044 | return NULL; | ||
1045 | } | ||
1046 | |||
1047 | static int intel_alloc_chipset_flush_resource(void) | ||
1048 | { | ||
1049 | int ret; | ||
1050 | ret = pci_bus_alloc_resource(agp_bridge->dev->bus, &intel_private.ifp_resource, PAGE_SIZE, | ||
1051 | PAGE_SIZE, PCIBIOS_MIN_MEM, 0, | ||
1052 | pcibios_align_resource, agp_bridge->dev); | ||
1053 | |||
1054 | return ret; | ||
1055 | } | ||
1056 | |||
1057 | static void intel_i915_setup_chipset_flush(void) | ||
1058 | { | ||
1059 | int ret; | ||
1060 | u32 temp; | ||
1061 | |||
1062 | pci_read_config_dword(agp_bridge->dev, I915_IFPADDR, &temp); | ||
1063 | if (!(temp & 0x1)) { | ||
1064 | intel_alloc_chipset_flush_resource(); | ||
1065 | intel_private.resource_valid = 1; | ||
1066 | pci_write_config_dword(agp_bridge->dev, I915_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); | ||
1067 | } else { | ||
1068 | temp &= ~1; | ||
1069 | |||
1070 | intel_private.resource_valid = 1; | ||
1071 | intel_private.ifp_resource.start = temp; | ||
1072 | intel_private.ifp_resource.end = temp + PAGE_SIZE; | ||
1073 | ret = request_resource(&iomem_resource, &intel_private.ifp_resource); | ||
1074 | /* some BIOSes reserve this area in a pnp some don't */ | ||
1075 | if (ret) | ||
1076 | intel_private.resource_valid = 0; | ||
1077 | } | ||
1078 | } | ||
1079 | |||
1080 | static void intel_i965_g33_setup_chipset_flush(void) | ||
1081 | { | ||
1082 | u32 temp_hi, temp_lo; | ||
1083 | int ret; | ||
1084 | |||
1085 | pci_read_config_dword(agp_bridge->dev, I965_IFPADDR + 4, &temp_hi); | ||
1086 | pci_read_config_dword(agp_bridge->dev, I965_IFPADDR, &temp_lo); | ||
1087 | |||
1088 | if (!(temp_lo & 0x1)) { | ||
1089 | |||
1090 | intel_alloc_chipset_flush_resource(); | ||
1091 | |||
1092 | intel_private.resource_valid = 1; | ||
1093 | pci_write_config_dword(agp_bridge->dev, I965_IFPADDR + 4, | ||
1094 | upper_32_bits(intel_private.ifp_resource.start)); | ||
1095 | pci_write_config_dword(agp_bridge->dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); | ||
1096 | } else { | ||
1097 | u64 l64; | ||
1098 | |||
1099 | temp_lo &= ~0x1; | ||
1100 | l64 = ((u64)temp_hi << 32) | temp_lo; | ||
1101 | |||
1102 | intel_private.resource_valid = 1; | ||
1103 | intel_private.ifp_resource.start = l64; | ||
1104 | intel_private.ifp_resource.end = l64 + PAGE_SIZE; | ||
1105 | ret = request_resource(&iomem_resource, &intel_private.ifp_resource); | ||
1106 | /* some BIOSes reserve this area in a pnp some don't */ | ||
1107 | if (ret) | ||
1108 | intel_private.resource_valid = 0; | ||
1109 | } | ||
1110 | } | ||
1111 | |||
1112 | static void intel_i9xx_setup_flush(void) | ||
1113 | { | ||
1114 | /* return if already configured */ | ||
1115 | if (intel_private.ifp_resource.start) | ||
1116 | return; | ||
1117 | |||
1118 | /* setup a resource for this object */ | ||
1119 | intel_private.ifp_resource.name = "Intel Flush Page"; | ||
1120 | intel_private.ifp_resource.flags = IORESOURCE_MEM; | ||
1121 | |||
1122 | /* Setup chipset flush for 915 */ | ||
1123 | if (IS_I965 || IS_G33 || IS_G4X) { | ||
1124 | intel_i965_g33_setup_chipset_flush(); | ||
1125 | } else { | ||
1126 | intel_i915_setup_chipset_flush(); | ||
1127 | } | ||
1128 | |||
1129 | if (intel_private.ifp_resource.start) { | ||
1130 | intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE); | ||
1131 | if (!intel_private.i9xx_flush_page) | ||
1132 | dev_info(&intel_private.pcidev->dev, "can't ioremap flush page - no chipset flushing"); | ||
1133 | } | ||
1134 | } | ||
1135 | |||
1136 | static int intel_i915_configure(void) | ||
1137 | { | ||
1138 | struct aper_size_info_fixed *current_size; | ||
1139 | u32 temp; | ||
1140 | u16 gmch_ctrl; | ||
1141 | int i; | ||
1142 | |||
1143 | current_size = A_SIZE_FIX(agp_bridge->current_size); | ||
1144 | |||
1145 | pci_read_config_dword(intel_private.pcidev, I915_GMADDR, &temp); | ||
1146 | |||
1147 | agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); | ||
1148 | |||
1149 | pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl); | ||
1150 | gmch_ctrl |= I830_GMCH_ENABLED; | ||
1151 | pci_write_config_word(agp_bridge->dev, I830_GMCH_CTRL, gmch_ctrl); | ||
1152 | |||
1153 | writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL); | ||
1154 | readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ | ||
1155 | |||
1156 | if (agp_bridge->driver->needs_scratch_page) { | ||
1157 | for (i = intel_private.gtt_entries; i < intel_private.gtt_total_size; i++) { | ||
1158 | writel(agp_bridge->scratch_page, intel_private.gtt+i); | ||
1159 | } | ||
1160 | readl(intel_private.gtt+i-1); /* PCI Posting. */ | ||
1161 | } | ||
1162 | |||
1163 | global_cache_flush(); | ||
1164 | |||
1165 | intel_i9xx_setup_flush(); | ||
1166 | |||
1167 | return 0; | ||
1168 | } | ||
1169 | |||
1170 | static void intel_i915_cleanup(void) | ||
1171 | { | ||
1172 | if (intel_private.i9xx_flush_page) | ||
1173 | iounmap(intel_private.i9xx_flush_page); | ||
1174 | if (intel_private.resource_valid) | ||
1175 | release_resource(&intel_private.ifp_resource); | ||
1176 | intel_private.ifp_resource.start = 0; | ||
1177 | intel_private.resource_valid = 0; | ||
1178 | iounmap(intel_private.gtt); | ||
1179 | iounmap(intel_private.registers); | ||
1180 | } | ||
1181 | |||
1182 | static void intel_i915_chipset_flush(struct agp_bridge_data *bridge) | ||
1183 | { | ||
1184 | if (intel_private.i9xx_flush_page) | ||
1185 | writel(1, intel_private.i9xx_flush_page); | ||
1186 | } | ||
1187 | |||
1188 | static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start, | ||
1189 | int type) | ||
1190 | { | ||
1191 | int num_entries; | ||
1192 | void *temp; | ||
1193 | int ret = -EINVAL; | ||
1194 | int mask_type; | ||
1195 | |||
1196 | if (mem->page_count == 0) | ||
1197 | goto out; | ||
1198 | |||
1199 | temp = agp_bridge->current_size; | ||
1200 | num_entries = A_SIZE_FIX(temp)->num_entries; | ||
1201 | |||
1202 | if (pg_start < intel_private.gtt_entries) { | ||
1203 | dev_printk(KERN_DEBUG, &intel_private.pcidev->dev, | ||
1204 | "pg_start == 0x%.8lx, intel_private.gtt_entries == 0x%.8x\n", | ||
1205 | pg_start, intel_private.gtt_entries); | ||
1206 | |||
1207 | dev_info(&intel_private.pcidev->dev, | ||
1208 | "trying to insert into local/stolen memory\n"); | ||
1209 | goto out_err; | ||
1210 | } | ||
1211 | |||
1212 | if ((pg_start + mem->page_count) > num_entries) | ||
1213 | goto out_err; | ||
1214 | |||
1215 | /* The i915 can't check the GTT for entries since it's read only; | ||
1216 | * depend on the caller to make the correct offset decisions. | ||
1217 | */ | ||
1218 | |||
1219 | if (type != mem->type) | ||
1220 | goto out_err; | ||
1221 | |||
1222 | mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); | ||
1223 | |||
1224 | if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY && | ||
1225 | mask_type != INTEL_AGP_CACHED_MEMORY) | ||
1226 | goto out_err; | ||
1227 | |||
1228 | if (!mem->is_flushed) | ||
1229 | global_cache_flush(); | ||
1230 | |||
1231 | intel_agp_insert_sg_entries(mem, pg_start, mask_type); | ||
1232 | agp_bridge->driver->tlb_flush(mem); | ||
1233 | |||
1234 | out: | ||
1235 | ret = 0; | ||
1236 | out_err: | ||
1237 | mem->is_flushed = true; | ||
1238 | return ret; | ||
1239 | } | ||
1240 | |||
1241 | static int intel_i915_remove_entries(struct agp_memory *mem, off_t pg_start, | ||
1242 | int type) | ||
1243 | { | ||
1244 | int i; | ||
1245 | |||
1246 | if (mem->page_count == 0) | ||
1247 | return 0; | ||
1248 | |||
1249 | if (pg_start < intel_private.gtt_entries) { | ||
1250 | dev_info(&intel_private.pcidev->dev, | ||
1251 | "trying to disable local/stolen memory\n"); | ||
1252 | return -EINVAL; | ||
1253 | } | ||
1254 | |||
1255 | for (i = pg_start; i < (mem->page_count + pg_start); i++) | ||
1256 | writel(agp_bridge->scratch_page, intel_private.gtt+i); | ||
1257 | |||
1258 | readl(intel_private.gtt+i-1); | ||
1259 | |||
1260 | agp_bridge->driver->tlb_flush(mem); | ||
1261 | return 0; | ||
1262 | } | ||
1263 | |||
1264 | /* Return the aperture size by just checking the resource length. The effect | ||
1265 | * described in the spec of the MSAC registers is just changing of the | ||
1266 | * resource size. | ||
1267 | */ | ||
1268 | static int intel_i9xx_fetch_size(void) | ||
1269 | { | ||
1270 | int num_sizes = ARRAY_SIZE(intel_i830_sizes); | ||
1271 | int aper_size; /* size in megabytes */ | ||
1272 | int i; | ||
1273 | |||
1274 | aper_size = pci_resource_len(intel_private.pcidev, 2) / MB(1); | ||
1275 | |||
1276 | for (i = 0; i < num_sizes; i++) { | ||
1277 | if (aper_size == intel_i830_sizes[i].size) { | ||
1278 | agp_bridge->current_size = intel_i830_sizes + i; | ||
1279 | agp_bridge->previous_size = agp_bridge->current_size; | ||
1280 | return aper_size; | ||
1281 | } | ||
1282 | } | ||
1283 | |||
1284 | return 0; | ||
1285 | } | ||
1286 | |||
1287 | /* The intel i915 automatically initializes the agp aperture during POST. | ||
1288 | * Use the memory already set aside for in the GTT. | ||
1289 | */ | ||
1290 | static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge) | ||
1291 | { | ||
1292 | int page_order; | ||
1293 | struct aper_size_info_fixed *size; | ||
1294 | int num_entries; | ||
1295 | u32 temp, temp2; | ||
1296 | int gtt_map_size = 256 * 1024; | ||
1297 | |||
1298 | size = agp_bridge->current_size; | ||
1299 | page_order = size->page_order; | ||
1300 | num_entries = size->num_entries; | ||
1301 | agp_bridge->gatt_table_real = NULL; | ||
1302 | |||
1303 | pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp); | ||
1304 | pci_read_config_dword(intel_private.pcidev, I915_PTEADDR, &temp2); | ||
1305 | |||
1306 | if (IS_G33) | ||
1307 | gtt_map_size = 1024 * 1024; /* 1M on G33 */ | ||
1308 | intel_private.gtt = ioremap(temp2, gtt_map_size); | ||
1309 | if (!intel_private.gtt) | ||
1310 | return -ENOMEM; | ||
1311 | |||
1312 | intel_private.gtt_total_size = gtt_map_size / 4; | ||
1313 | |||
1314 | temp &= 0xfff80000; | ||
1315 | |||
1316 | intel_private.registers = ioremap(temp, 128 * 4096); | ||
1317 | if (!intel_private.registers) { | ||
1318 | iounmap(intel_private.gtt); | ||
1319 | return -ENOMEM; | ||
1320 | } | ||
1321 | |||
1322 | temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; | ||
1323 | global_cache_flush(); /* FIXME: ? */ | ||
1324 | |||
1325 | /* we have to call this as early as possible after the MMIO base address is known */ | ||
1326 | intel_i830_init_gtt_entries(); | ||
1327 | |||
1328 | agp_bridge->gatt_table = NULL; | ||
1329 | |||
1330 | agp_bridge->gatt_bus_addr = temp; | ||
1331 | |||
1332 | return 0; | ||
1333 | } | ||
1334 | |||
1335 | /* | ||
1336 | * The i965 supports 36-bit physical addresses, but to keep | ||
1337 | * the format of the GTT the same, the bits that don't fit | ||
1338 | * in a 32-bit word are shifted down to bits 4..7. | ||
1339 | * | ||
1340 | * Gcc is smart enough to notice that "(addr >> 28) & 0xf0" | ||
1341 | * is always zero on 32-bit architectures, so no need to make | ||
1342 | * this conditional. | ||
1343 | */ | ||
1344 | static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge, | ||
1345 | dma_addr_t addr, int type) | ||
1346 | { | ||
1347 | /* Shift high bits down */ | ||
1348 | addr |= (addr >> 28) & 0xf0; | ||
1349 | |||
1350 | /* Type checking must be done elsewhere */ | ||
1351 | return addr | bridge->driver->masks[type].mask; | ||
1352 | } | ||
1353 | |||
1354 | static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size) | ||
1355 | { | ||
1356 | switch (agp_bridge->dev->device) { | ||
1357 | case PCI_DEVICE_ID_INTEL_GM45_HB: | ||
1358 | case PCI_DEVICE_ID_INTEL_EAGLELAKE_HB: | ||
1359 | case PCI_DEVICE_ID_INTEL_Q45_HB: | ||
1360 | case PCI_DEVICE_ID_INTEL_G45_HB: | ||
1361 | case PCI_DEVICE_ID_INTEL_G41_HB: | ||
1362 | case PCI_DEVICE_ID_INTEL_B43_HB: | ||
1363 | case PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB: | ||
1364 | case PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB: | ||
1365 | case PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB: | ||
1366 | case PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB: | ||
1367 | *gtt_offset = *gtt_size = MB(2); | ||
1368 | break; | ||
1369 | default: | ||
1370 | *gtt_offset = *gtt_size = KB(512); | ||
1371 | } | ||
1372 | } | ||
1373 | |||
1374 | /* The intel i965 automatically initializes the agp aperture during POST. | ||
1375 | * Use the memory already set aside for in the GTT. | ||
1376 | */ | ||
1377 | static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge) | ||
1378 | { | ||
1379 | int page_order; | ||
1380 | struct aper_size_info_fixed *size; | ||
1381 | int num_entries; | ||
1382 | u32 temp; | ||
1383 | int gtt_offset, gtt_size; | ||
1384 | |||
1385 | size = agp_bridge->current_size; | ||
1386 | page_order = size->page_order; | ||
1387 | num_entries = size->num_entries; | ||
1388 | agp_bridge->gatt_table_real = NULL; | ||
1389 | |||
1390 | pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp); | ||
1391 | |||
1392 | temp &= 0xfff00000; | ||
1393 | |||
1394 | intel_i965_get_gtt_range(>t_offset, >t_size); | ||
1395 | |||
1396 | intel_private.gtt = ioremap((temp + gtt_offset) , gtt_size); | ||
1397 | |||
1398 | if (!intel_private.gtt) | ||
1399 | return -ENOMEM; | ||
1400 | |||
1401 | intel_private.gtt_total_size = gtt_size / 4; | ||
1402 | |||
1403 | intel_private.registers = ioremap(temp, 128 * 4096); | ||
1404 | if (!intel_private.registers) { | ||
1405 | iounmap(intel_private.gtt); | ||
1406 | return -ENOMEM; | ||
1407 | } | ||
1408 | |||
1409 | temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; | ||
1410 | global_cache_flush(); /* FIXME: ? */ | ||
1411 | |||
1412 | /* we have to call this as early as possible after the MMIO base address is known */ | ||
1413 | intel_i830_init_gtt_entries(); | ||
1414 | |||
1415 | agp_bridge->gatt_table = NULL; | ||
1416 | |||
1417 | agp_bridge->gatt_bus_addr = temp; | ||
1418 | |||
1419 | return 0; | ||
1420 | } | ||
1421 | |||
1422 | 18 | ||
1423 | static int intel_fetch_size(void) | 19 | static int intel_fetch_size(void) |
1424 | { | 20 | { |
@@ -1701,8 +297,6 @@ static int intel_845_configure(void) | |||
1701 | pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1)); | 297 | pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1)); |
1702 | /* clear any possible error conditions */ | 298 | /* clear any possible error conditions */ |
1703 | pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c); | 299 | pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c); |
1704 | |||
1705 | intel_i830_setup_flush(); | ||
1706 | return 0; | 300 | return 0; |
1707 | } | 301 | } |
1708 | 302 | ||
@@ -1868,6 +462,7 @@ static const struct agp_bridge_driver intel_generic_driver = { | |||
1868 | .aperture_sizes = intel_generic_sizes, | 462 | .aperture_sizes = intel_generic_sizes, |
1869 | .size_type = U16_APER_SIZE, | 463 | .size_type = U16_APER_SIZE, |
1870 | .num_aperture_sizes = 7, | 464 | .num_aperture_sizes = 7, |
465 | .needs_scratch_page = true, | ||
1871 | .configure = intel_configure, | 466 | .configure = intel_configure, |
1872 | .fetch_size = intel_fetch_size, | 467 | .fetch_size = intel_fetch_size, |
1873 | .cleanup = intel_cleanup, | 468 | .cleanup = intel_cleanup, |
@@ -1889,38 +484,12 @@ static const struct agp_bridge_driver intel_generic_driver = { | |||
1889 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 484 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
1890 | }; | 485 | }; |
1891 | 486 | ||
1892 | static const struct agp_bridge_driver intel_810_driver = { | ||
1893 | .owner = THIS_MODULE, | ||
1894 | .aperture_sizes = intel_i810_sizes, | ||
1895 | .size_type = FIXED_APER_SIZE, | ||
1896 | .num_aperture_sizes = 2, | ||
1897 | .needs_scratch_page = true, | ||
1898 | .configure = intel_i810_configure, | ||
1899 | .fetch_size = intel_i810_fetch_size, | ||
1900 | .cleanup = intel_i810_cleanup, | ||
1901 | .tlb_flush = intel_i810_tlbflush, | ||
1902 | .mask_memory = intel_i810_mask_memory, | ||
1903 | .masks = intel_i810_masks, | ||
1904 | .agp_enable = intel_i810_agp_enable, | ||
1905 | .cache_flush = global_cache_flush, | ||
1906 | .create_gatt_table = agp_generic_create_gatt_table, | ||
1907 | .free_gatt_table = agp_generic_free_gatt_table, | ||
1908 | .insert_memory = intel_i810_insert_entries, | ||
1909 | .remove_memory = intel_i810_remove_entries, | ||
1910 | .alloc_by_type = intel_i810_alloc_by_type, | ||
1911 | .free_by_type = intel_i810_free_by_type, | ||
1912 | .agp_alloc_page = agp_generic_alloc_page, | ||
1913 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
1914 | .agp_destroy_page = agp_generic_destroy_page, | ||
1915 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
1916 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | ||
1917 | }; | ||
1918 | |||
1919 | static const struct agp_bridge_driver intel_815_driver = { | 487 | static const struct agp_bridge_driver intel_815_driver = { |
1920 | .owner = THIS_MODULE, | 488 | .owner = THIS_MODULE, |
1921 | .aperture_sizes = intel_815_sizes, | 489 | .aperture_sizes = intel_815_sizes, |
1922 | .size_type = U8_APER_SIZE, | 490 | .size_type = U8_APER_SIZE, |
1923 | .num_aperture_sizes = 2, | 491 | .num_aperture_sizes = 2, |
492 | .needs_scratch_page = true, | ||
1924 | .configure = intel_815_configure, | 493 | .configure = intel_815_configure, |
1925 | .fetch_size = intel_815_fetch_size, | 494 | .fetch_size = intel_815_fetch_size, |
1926 | .cleanup = intel_8xx_cleanup, | 495 | .cleanup = intel_8xx_cleanup, |
@@ -1942,39 +511,12 @@ static const struct agp_bridge_driver intel_815_driver = { | |||
1942 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 511 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
1943 | }; | 512 | }; |
1944 | 513 | ||
1945 | static const struct agp_bridge_driver intel_830_driver = { | ||
1946 | .owner = THIS_MODULE, | ||
1947 | .aperture_sizes = intel_i830_sizes, | ||
1948 | .size_type = FIXED_APER_SIZE, | ||
1949 | .num_aperture_sizes = 4, | ||
1950 | .needs_scratch_page = true, | ||
1951 | .configure = intel_i830_configure, | ||
1952 | .fetch_size = intel_i830_fetch_size, | ||
1953 | .cleanup = intel_i830_cleanup, | ||
1954 | .tlb_flush = intel_i810_tlbflush, | ||
1955 | .mask_memory = intel_i810_mask_memory, | ||
1956 | .masks = intel_i810_masks, | ||
1957 | .agp_enable = intel_i810_agp_enable, | ||
1958 | .cache_flush = global_cache_flush, | ||
1959 | .create_gatt_table = intel_i830_create_gatt_table, | ||
1960 | .free_gatt_table = intel_i830_free_gatt_table, | ||
1961 | .insert_memory = intel_i830_insert_entries, | ||
1962 | .remove_memory = intel_i830_remove_entries, | ||
1963 | .alloc_by_type = intel_i830_alloc_by_type, | ||
1964 | .free_by_type = intel_i810_free_by_type, | ||
1965 | .agp_alloc_page = agp_generic_alloc_page, | ||
1966 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
1967 | .agp_destroy_page = agp_generic_destroy_page, | ||
1968 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
1969 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, | ||
1970 | .chipset_flush = intel_i830_chipset_flush, | ||
1971 | }; | ||
1972 | |||
1973 | static const struct agp_bridge_driver intel_820_driver = { | 514 | static const struct agp_bridge_driver intel_820_driver = { |
1974 | .owner = THIS_MODULE, | 515 | .owner = THIS_MODULE, |
1975 | .aperture_sizes = intel_8xx_sizes, | 516 | .aperture_sizes = intel_8xx_sizes, |
1976 | .size_type = U8_APER_SIZE, | 517 | .size_type = U8_APER_SIZE, |
1977 | .num_aperture_sizes = 7, | 518 | .num_aperture_sizes = 7, |
519 | .needs_scratch_page = true, | ||
1978 | .configure = intel_820_configure, | 520 | .configure = intel_820_configure, |
1979 | .fetch_size = intel_8xx_fetch_size, | 521 | .fetch_size = intel_8xx_fetch_size, |
1980 | .cleanup = intel_820_cleanup, | 522 | .cleanup = intel_820_cleanup, |
@@ -2001,6 +543,7 @@ static const struct agp_bridge_driver intel_830mp_driver = { | |||
2001 | .aperture_sizes = intel_830mp_sizes, | 543 | .aperture_sizes = intel_830mp_sizes, |
2002 | .size_type = U8_APER_SIZE, | 544 | .size_type = U8_APER_SIZE, |
2003 | .num_aperture_sizes = 4, | 545 | .num_aperture_sizes = 4, |
546 | .needs_scratch_page = true, | ||
2004 | .configure = intel_830mp_configure, | 547 | .configure = intel_830mp_configure, |
2005 | .fetch_size = intel_8xx_fetch_size, | 548 | .fetch_size = intel_8xx_fetch_size, |
2006 | .cleanup = intel_8xx_cleanup, | 549 | .cleanup = intel_8xx_cleanup, |
@@ -2027,6 +570,7 @@ static const struct agp_bridge_driver intel_840_driver = { | |||
2027 | .aperture_sizes = intel_8xx_sizes, | 570 | .aperture_sizes = intel_8xx_sizes, |
2028 | .size_type = U8_APER_SIZE, | 571 | .size_type = U8_APER_SIZE, |
2029 | .num_aperture_sizes = 7, | 572 | .num_aperture_sizes = 7, |
573 | .needs_scratch_page = true, | ||
2030 | .configure = intel_840_configure, | 574 | .configure = intel_840_configure, |
2031 | .fetch_size = intel_8xx_fetch_size, | 575 | .fetch_size = intel_8xx_fetch_size, |
2032 | .cleanup = intel_8xx_cleanup, | 576 | .cleanup = intel_8xx_cleanup, |
@@ -2053,6 +597,7 @@ static const struct agp_bridge_driver intel_845_driver = { | |||
2053 | .aperture_sizes = intel_8xx_sizes, | 597 | .aperture_sizes = intel_8xx_sizes, |
2054 | .size_type = U8_APER_SIZE, | 598 | .size_type = U8_APER_SIZE, |
2055 | .num_aperture_sizes = 7, | 599 | .num_aperture_sizes = 7, |
600 | .needs_scratch_page = true, | ||
2056 | .configure = intel_845_configure, | 601 | .configure = intel_845_configure, |
2057 | .fetch_size = intel_8xx_fetch_size, | 602 | .fetch_size = intel_8xx_fetch_size, |
2058 | .cleanup = intel_8xx_cleanup, | 603 | .cleanup = intel_8xx_cleanup, |
@@ -2072,7 +617,6 @@ static const struct agp_bridge_driver intel_845_driver = { | |||
2072 | .agp_destroy_page = agp_generic_destroy_page, | 617 | .agp_destroy_page = agp_generic_destroy_page, |
2073 | .agp_destroy_pages = agp_generic_destroy_pages, | 618 | .agp_destroy_pages = agp_generic_destroy_pages, |
2074 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 619 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
2075 | .chipset_flush = intel_i830_chipset_flush, | ||
2076 | }; | 620 | }; |
2077 | 621 | ||
2078 | static const struct agp_bridge_driver intel_850_driver = { | 622 | static const struct agp_bridge_driver intel_850_driver = { |
@@ -2080,6 +624,7 @@ static const struct agp_bridge_driver intel_850_driver = { | |||
2080 | .aperture_sizes = intel_8xx_sizes, | 624 | .aperture_sizes = intel_8xx_sizes, |
2081 | .size_type = U8_APER_SIZE, | 625 | .size_type = U8_APER_SIZE, |
2082 | .num_aperture_sizes = 7, | 626 | .num_aperture_sizes = 7, |
627 | .needs_scratch_page = true, | ||
2083 | .configure = intel_850_configure, | 628 | .configure = intel_850_configure, |
2084 | .fetch_size = intel_8xx_fetch_size, | 629 | .fetch_size = intel_8xx_fetch_size, |
2085 | .cleanup = intel_8xx_cleanup, | 630 | .cleanup = intel_8xx_cleanup, |
@@ -2106,6 +651,7 @@ static const struct agp_bridge_driver intel_860_driver = { | |||
2106 | .aperture_sizes = intel_8xx_sizes, | 651 | .aperture_sizes = intel_8xx_sizes, |
2107 | .size_type = U8_APER_SIZE, | 652 | .size_type = U8_APER_SIZE, |
2108 | .num_aperture_sizes = 7, | 653 | .num_aperture_sizes = 7, |
654 | .needs_scratch_page = true, | ||
2109 | .configure = intel_860_configure, | 655 | .configure = intel_860_configure, |
2110 | .fetch_size = intel_8xx_fetch_size, | 656 | .fetch_size = intel_8xx_fetch_size, |
2111 | .cleanup = intel_8xx_cleanup, | 657 | .cleanup = intel_8xx_cleanup, |
@@ -2127,79 +673,12 @@ static const struct agp_bridge_driver intel_860_driver = { | |||
2127 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 673 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
2128 | }; | 674 | }; |
2129 | 675 | ||
2130 | static const struct agp_bridge_driver intel_915_driver = { | ||
2131 | .owner = THIS_MODULE, | ||
2132 | .aperture_sizes = intel_i830_sizes, | ||
2133 | .size_type = FIXED_APER_SIZE, | ||
2134 | .num_aperture_sizes = 4, | ||
2135 | .needs_scratch_page = true, | ||
2136 | .configure = intel_i915_configure, | ||
2137 | .fetch_size = intel_i9xx_fetch_size, | ||
2138 | .cleanup = intel_i915_cleanup, | ||
2139 | .tlb_flush = intel_i810_tlbflush, | ||
2140 | .mask_memory = intel_i810_mask_memory, | ||
2141 | .masks = intel_i810_masks, | ||
2142 | .agp_enable = intel_i810_agp_enable, | ||
2143 | .cache_flush = global_cache_flush, | ||
2144 | .create_gatt_table = intel_i915_create_gatt_table, | ||
2145 | .free_gatt_table = intel_i830_free_gatt_table, | ||
2146 | .insert_memory = intel_i915_insert_entries, | ||
2147 | .remove_memory = intel_i915_remove_entries, | ||
2148 | .alloc_by_type = intel_i830_alloc_by_type, | ||
2149 | .free_by_type = intel_i810_free_by_type, | ||
2150 | .agp_alloc_page = agp_generic_alloc_page, | ||
2151 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
2152 | .agp_destroy_page = agp_generic_destroy_page, | ||
2153 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
2154 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, | ||
2155 | .chipset_flush = intel_i915_chipset_flush, | ||
2156 | #ifdef USE_PCI_DMA_API | ||
2157 | .agp_map_page = intel_agp_map_page, | ||
2158 | .agp_unmap_page = intel_agp_unmap_page, | ||
2159 | .agp_map_memory = intel_agp_map_memory, | ||
2160 | .agp_unmap_memory = intel_agp_unmap_memory, | ||
2161 | #endif | ||
2162 | }; | ||
2163 | |||
2164 | static const struct agp_bridge_driver intel_i965_driver = { | ||
2165 | .owner = THIS_MODULE, | ||
2166 | .aperture_sizes = intel_i830_sizes, | ||
2167 | .size_type = FIXED_APER_SIZE, | ||
2168 | .num_aperture_sizes = 4, | ||
2169 | .needs_scratch_page = true, | ||
2170 | .configure = intel_i915_configure, | ||
2171 | .fetch_size = intel_i9xx_fetch_size, | ||
2172 | .cleanup = intel_i915_cleanup, | ||
2173 | .tlb_flush = intel_i810_tlbflush, | ||
2174 | .mask_memory = intel_i965_mask_memory, | ||
2175 | .masks = intel_i810_masks, | ||
2176 | .agp_enable = intel_i810_agp_enable, | ||
2177 | .cache_flush = global_cache_flush, | ||
2178 | .create_gatt_table = intel_i965_create_gatt_table, | ||
2179 | .free_gatt_table = intel_i830_free_gatt_table, | ||
2180 | .insert_memory = intel_i915_insert_entries, | ||
2181 | .remove_memory = intel_i915_remove_entries, | ||
2182 | .alloc_by_type = intel_i830_alloc_by_type, | ||
2183 | .free_by_type = intel_i810_free_by_type, | ||
2184 | .agp_alloc_page = agp_generic_alloc_page, | ||
2185 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
2186 | .agp_destroy_page = agp_generic_destroy_page, | ||
2187 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
2188 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, | ||
2189 | .chipset_flush = intel_i915_chipset_flush, | ||
2190 | #ifdef USE_PCI_DMA_API | ||
2191 | .agp_map_page = intel_agp_map_page, | ||
2192 | .agp_unmap_page = intel_agp_unmap_page, | ||
2193 | .agp_map_memory = intel_agp_map_memory, | ||
2194 | .agp_unmap_memory = intel_agp_unmap_memory, | ||
2195 | #endif | ||
2196 | }; | ||
2197 | |||
2198 | static const struct agp_bridge_driver intel_7505_driver = { | 676 | static const struct agp_bridge_driver intel_7505_driver = { |
2199 | .owner = THIS_MODULE, | 677 | .owner = THIS_MODULE, |
2200 | .aperture_sizes = intel_8xx_sizes, | 678 | .aperture_sizes = intel_8xx_sizes, |
2201 | .size_type = U8_APER_SIZE, | 679 | .size_type = U8_APER_SIZE, |
2202 | .num_aperture_sizes = 7, | 680 | .num_aperture_sizes = 7, |
681 | .needs_scratch_page = true, | ||
2203 | .configure = intel_7505_configure, | 682 | .configure = intel_7505_configure, |
2204 | .fetch_size = intel_8xx_fetch_size, | 683 | .fetch_size = intel_8xx_fetch_size, |
2205 | .cleanup = intel_8xx_cleanup, | 684 | .cleanup = intel_8xx_cleanup, |
@@ -2221,155 +700,35 @@ static const struct agp_bridge_driver intel_7505_driver = { | |||
2221 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 700 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
2222 | }; | 701 | }; |
2223 | 702 | ||
2224 | static const struct agp_bridge_driver intel_g33_driver = { | ||
2225 | .owner = THIS_MODULE, | ||
2226 | .aperture_sizes = intel_i830_sizes, | ||
2227 | .size_type = FIXED_APER_SIZE, | ||
2228 | .num_aperture_sizes = 4, | ||
2229 | .needs_scratch_page = true, | ||
2230 | .configure = intel_i915_configure, | ||
2231 | .fetch_size = intel_i9xx_fetch_size, | ||
2232 | .cleanup = intel_i915_cleanup, | ||
2233 | .tlb_flush = intel_i810_tlbflush, | ||
2234 | .mask_memory = intel_i965_mask_memory, | ||
2235 | .masks = intel_i810_masks, | ||
2236 | .agp_enable = intel_i810_agp_enable, | ||
2237 | .cache_flush = global_cache_flush, | ||
2238 | .create_gatt_table = intel_i915_create_gatt_table, | ||
2239 | .free_gatt_table = intel_i830_free_gatt_table, | ||
2240 | .insert_memory = intel_i915_insert_entries, | ||
2241 | .remove_memory = intel_i915_remove_entries, | ||
2242 | .alloc_by_type = intel_i830_alloc_by_type, | ||
2243 | .free_by_type = intel_i810_free_by_type, | ||
2244 | .agp_alloc_page = agp_generic_alloc_page, | ||
2245 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
2246 | .agp_destroy_page = agp_generic_destroy_page, | ||
2247 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
2248 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, | ||
2249 | .chipset_flush = intel_i915_chipset_flush, | ||
2250 | #ifdef USE_PCI_DMA_API | ||
2251 | .agp_map_page = intel_agp_map_page, | ||
2252 | .agp_unmap_page = intel_agp_unmap_page, | ||
2253 | .agp_map_memory = intel_agp_map_memory, | ||
2254 | .agp_unmap_memory = intel_agp_unmap_memory, | ||
2255 | #endif | ||
2256 | }; | ||
2257 | |||
2258 | static int find_gmch(u16 device) | ||
2259 | { | ||
2260 | struct pci_dev *gmch_device; | ||
2261 | |||
2262 | gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL); | ||
2263 | if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) { | ||
2264 | gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
2265 | device, gmch_device); | ||
2266 | } | ||
2267 | |||
2268 | if (!gmch_device) | ||
2269 | return 0; | ||
2270 | |||
2271 | intel_private.pcidev = gmch_device; | ||
2272 | return 1; | ||
2273 | } | ||
2274 | |||
2275 | /* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of | 703 | /* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of |
2276 | * driver and gmch_driver must be non-null, and find_gmch will determine | 704 | * driver and gmch_driver must be non-null, and find_gmch will determine |
2277 | * which one should be used if a gmch_chip_id is present. | 705 | * which one should be used if a gmch_chip_id is present. |
2278 | */ | 706 | */ |
2279 | static const struct intel_driver_description { | 707 | static const struct intel_agp_driver_description { |
2280 | unsigned int chip_id; | 708 | unsigned int chip_id; |
2281 | unsigned int gmch_chip_id; | ||
2282 | unsigned int multi_gmch_chip; /* if we have more gfx chip type on this HB. */ | ||
2283 | char *name; | 709 | char *name; |
2284 | const struct agp_bridge_driver *driver; | 710 | const struct agp_bridge_driver *driver; |
2285 | const struct agp_bridge_driver *gmch_driver; | ||
2286 | } intel_agp_chipsets[] = { | 711 | } intel_agp_chipsets[] = { |
2287 | { PCI_DEVICE_ID_INTEL_82443LX_0, 0, 0, "440LX", &intel_generic_driver, NULL }, | 712 | { PCI_DEVICE_ID_INTEL_82443LX_0, "440LX", &intel_generic_driver }, |
2288 | { PCI_DEVICE_ID_INTEL_82443BX_0, 0, 0, "440BX", &intel_generic_driver, NULL }, | 713 | { PCI_DEVICE_ID_INTEL_82443BX_0, "440BX", &intel_generic_driver }, |
2289 | { PCI_DEVICE_ID_INTEL_82443GX_0, 0, 0, "440GX", &intel_generic_driver, NULL }, | 714 | { PCI_DEVICE_ID_INTEL_82443GX_0, "440GX", &intel_generic_driver }, |
2290 | { PCI_DEVICE_ID_INTEL_82810_MC1, PCI_DEVICE_ID_INTEL_82810_IG1, 0, "i810", | 715 | { PCI_DEVICE_ID_INTEL_82815_MC, "i815", &intel_815_driver }, |
2291 | NULL, &intel_810_driver }, | 716 | { PCI_DEVICE_ID_INTEL_82820_HB, "i820", &intel_820_driver }, |
2292 | { PCI_DEVICE_ID_INTEL_82810_MC3, PCI_DEVICE_ID_INTEL_82810_IG3, 0, "i810", | 717 | { PCI_DEVICE_ID_INTEL_82820_UP_HB, "i820", &intel_820_driver }, |
2293 | NULL, &intel_810_driver }, | 718 | { PCI_DEVICE_ID_INTEL_82830_HB, "830M", &intel_830mp_driver }, |
2294 | { PCI_DEVICE_ID_INTEL_82810E_MC, PCI_DEVICE_ID_INTEL_82810E_IG, 0, "i810", | 719 | { PCI_DEVICE_ID_INTEL_82840_HB, "i840", &intel_840_driver }, |
2295 | NULL, &intel_810_driver }, | 720 | { PCI_DEVICE_ID_INTEL_82845_HB, "845G", &intel_845_driver }, |
2296 | { PCI_DEVICE_ID_INTEL_82815_MC, PCI_DEVICE_ID_INTEL_82815_CGC, 0, "i815", | 721 | { PCI_DEVICE_ID_INTEL_82845G_HB, "830M", &intel_845_driver }, |
2297 | &intel_815_driver, &intel_810_driver }, | 722 | { PCI_DEVICE_ID_INTEL_82850_HB, "i850", &intel_850_driver }, |
2298 | { PCI_DEVICE_ID_INTEL_82820_HB, 0, 0, "i820", &intel_820_driver, NULL }, | 723 | { PCI_DEVICE_ID_INTEL_82854_HB, "854", &intel_845_driver }, |
2299 | { PCI_DEVICE_ID_INTEL_82820_UP_HB, 0, 0, "i820", &intel_820_driver, NULL }, | 724 | { PCI_DEVICE_ID_INTEL_82855PM_HB, "855PM", &intel_845_driver }, |
2300 | { PCI_DEVICE_ID_INTEL_82830_HB, PCI_DEVICE_ID_INTEL_82830_CGC, 0, "830M", | 725 | { PCI_DEVICE_ID_INTEL_82855GM_HB, "855GM", &intel_845_driver }, |
2301 | &intel_830mp_driver, &intel_830_driver }, | 726 | { PCI_DEVICE_ID_INTEL_82860_HB, "i860", &intel_860_driver }, |
2302 | { PCI_DEVICE_ID_INTEL_82840_HB, 0, 0, "i840", &intel_840_driver, NULL }, | 727 | { PCI_DEVICE_ID_INTEL_82865_HB, "865", &intel_845_driver }, |
2303 | { PCI_DEVICE_ID_INTEL_82845_HB, 0, 0, "845G", &intel_845_driver, NULL }, | 728 | { PCI_DEVICE_ID_INTEL_82875_HB, "i875", &intel_845_driver }, |
2304 | { PCI_DEVICE_ID_INTEL_82845G_HB, PCI_DEVICE_ID_INTEL_82845G_IG, 0, "830M", | 729 | { PCI_DEVICE_ID_INTEL_7505_0, "E7505", &intel_7505_driver }, |
2305 | &intel_845_driver, &intel_830_driver }, | 730 | { PCI_DEVICE_ID_INTEL_7205_0, "E7205", &intel_7505_driver }, |
2306 | { PCI_DEVICE_ID_INTEL_82850_HB, 0, 0, "i850", &intel_850_driver, NULL }, | 731 | { 0, NULL, NULL } |
2307 | { PCI_DEVICE_ID_INTEL_82854_HB, PCI_DEVICE_ID_INTEL_82854_IG, 0, "854", | ||
2308 | &intel_845_driver, &intel_830_driver }, | ||
2309 | { PCI_DEVICE_ID_INTEL_82855PM_HB, 0, 0, "855PM", &intel_845_driver, NULL }, | ||
2310 | { PCI_DEVICE_ID_INTEL_82855GM_HB, PCI_DEVICE_ID_INTEL_82855GM_IG, 0, "855GM", | ||
2311 | &intel_845_driver, &intel_830_driver }, | ||
2312 | { PCI_DEVICE_ID_INTEL_82860_HB, 0, 0, "i860", &intel_860_driver, NULL }, | ||
2313 | { PCI_DEVICE_ID_INTEL_82865_HB, PCI_DEVICE_ID_INTEL_82865_IG, 0, "865", | ||
2314 | &intel_845_driver, &intel_830_driver }, | ||
2315 | { PCI_DEVICE_ID_INTEL_82875_HB, 0, 0, "i875", &intel_845_driver, NULL }, | ||
2316 | { PCI_DEVICE_ID_INTEL_E7221_HB, PCI_DEVICE_ID_INTEL_E7221_IG, 0, "E7221 (i915)", | ||
2317 | NULL, &intel_915_driver }, | ||
2318 | { PCI_DEVICE_ID_INTEL_82915G_HB, PCI_DEVICE_ID_INTEL_82915G_IG, 0, "915G", | ||
2319 | NULL, &intel_915_driver }, | ||
2320 | { PCI_DEVICE_ID_INTEL_82915GM_HB, PCI_DEVICE_ID_INTEL_82915GM_IG, 0, "915GM", | ||
2321 | NULL, &intel_915_driver }, | ||
2322 | { PCI_DEVICE_ID_INTEL_82945G_HB, PCI_DEVICE_ID_INTEL_82945G_IG, 0, "945G", | ||
2323 | NULL, &intel_915_driver }, | ||
2324 | { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, 0, "945GM", | ||
2325 | NULL, &intel_915_driver }, | ||
2326 | { PCI_DEVICE_ID_INTEL_82945GME_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, 0, "945GME", | ||
2327 | NULL, &intel_915_driver }, | ||
2328 | { PCI_DEVICE_ID_INTEL_82946GZ_HB, PCI_DEVICE_ID_INTEL_82946GZ_IG, 0, "946GZ", | ||
2329 | NULL, &intel_i965_driver }, | ||
2330 | { PCI_DEVICE_ID_INTEL_82G35_HB, PCI_DEVICE_ID_INTEL_82G35_IG, 0, "G35", | ||
2331 | NULL, &intel_i965_driver }, | ||
2332 | { PCI_DEVICE_ID_INTEL_82965Q_HB, PCI_DEVICE_ID_INTEL_82965Q_IG, 0, "965Q", | ||
2333 | NULL, &intel_i965_driver }, | ||
2334 | { PCI_DEVICE_ID_INTEL_82965G_HB, PCI_DEVICE_ID_INTEL_82965G_IG, 0, "965G", | ||
2335 | NULL, &intel_i965_driver }, | ||
2336 | { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, 0, "965GM", | ||
2337 | NULL, &intel_i965_driver }, | ||
2338 | { PCI_DEVICE_ID_INTEL_82965GME_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, 0, "965GME/GLE", | ||
2339 | NULL, &intel_i965_driver }, | ||
2340 | { PCI_DEVICE_ID_INTEL_7505_0, 0, 0, "E7505", &intel_7505_driver, NULL }, | ||
2341 | { PCI_DEVICE_ID_INTEL_7205_0, 0, 0, "E7205", &intel_7505_driver, NULL }, | ||
2342 | { PCI_DEVICE_ID_INTEL_G33_HB, PCI_DEVICE_ID_INTEL_G33_IG, 0, "G33", | ||
2343 | NULL, &intel_g33_driver }, | ||
2344 | { PCI_DEVICE_ID_INTEL_Q35_HB, PCI_DEVICE_ID_INTEL_Q35_IG, 0, "Q35", | ||
2345 | NULL, &intel_g33_driver }, | ||
2346 | { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33", | ||
2347 | NULL, &intel_g33_driver }, | ||
2348 | { PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, 0, "Pineview", | ||
2349 | NULL, &intel_g33_driver }, | ||
2350 | { PCI_DEVICE_ID_INTEL_PINEVIEW_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_IG, 0, "Pineview", | ||
2351 | NULL, &intel_g33_driver }, | ||
2352 | { PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0, | ||
2353 | "GM45", NULL, &intel_i965_driver }, | ||
2354 | { PCI_DEVICE_ID_INTEL_EAGLELAKE_HB, PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, 0, | ||
2355 | "Eaglelake", NULL, &intel_i965_driver }, | ||
2356 | { PCI_DEVICE_ID_INTEL_Q45_HB, PCI_DEVICE_ID_INTEL_Q45_IG, 0, | ||
2357 | "Q45/Q43", NULL, &intel_i965_driver }, | ||
2358 | { PCI_DEVICE_ID_INTEL_G45_HB, PCI_DEVICE_ID_INTEL_G45_IG, 0, | ||
2359 | "G45/G43", NULL, &intel_i965_driver }, | ||
2360 | { PCI_DEVICE_ID_INTEL_B43_HB, PCI_DEVICE_ID_INTEL_B43_IG, 0, | ||
2361 | "B43", NULL, &intel_i965_driver }, | ||
2362 | { PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0, | ||
2363 | "G41", NULL, &intel_i965_driver }, | ||
2364 | { PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, 0, | ||
2365 | "Ironlake/D", NULL, &intel_i965_driver }, | ||
2366 | { PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0, | ||
2367 | "Ironlake/M", NULL, &intel_i965_driver }, | ||
2368 | { PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0, | ||
2369 | "Ironlake/MA", NULL, &intel_i965_driver }, | ||
2370 | { PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0, | ||
2371 | "Ironlake/MC2", NULL, &intel_i965_driver }, | ||
2372 | { 0, 0, 0, NULL, NULL, NULL } | ||
2373 | }; | 732 | }; |
2374 | 733 | ||
2375 | static int __devinit agp_intel_probe(struct pci_dev *pdev, | 734 | static int __devinit agp_intel_probe(struct pci_dev *pdev, |
@@ -2378,7 +737,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, | |||
2378 | struct agp_bridge_data *bridge; | 737 | struct agp_bridge_data *bridge; |
2379 | u8 cap_ptr = 0; | 738 | u8 cap_ptr = 0; |
2380 | struct resource *r; | 739 | struct resource *r; |
2381 | int i; | 740 | int i, err; |
2382 | 741 | ||
2383 | cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); | 742 | cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); |
2384 | 743 | ||
@@ -2386,26 +745,22 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, | |||
2386 | if (!bridge) | 745 | if (!bridge) |
2387 | return -ENOMEM; | 746 | return -ENOMEM; |
2388 | 747 | ||
748 | bridge->capndx = cap_ptr; | ||
749 | |||
750 | if (intel_gmch_probe(pdev, bridge)) | ||
751 | goto found_gmch; | ||
752 | |||
2389 | for (i = 0; intel_agp_chipsets[i].name != NULL; i++) { | 753 | for (i = 0; intel_agp_chipsets[i].name != NULL; i++) { |
2390 | /* In case that multiple models of gfx chip may | 754 | /* In case that multiple models of gfx chip may |
2391 | stand on same host bridge type, this can be | 755 | stand on same host bridge type, this can be |
2392 | sure we detect the right IGD. */ | 756 | sure we detect the right IGD. */ |
2393 | if (pdev->device == intel_agp_chipsets[i].chip_id) { | 757 | if (pdev->device == intel_agp_chipsets[i].chip_id) { |
2394 | if ((intel_agp_chipsets[i].gmch_chip_id != 0) && | 758 | bridge->driver = intel_agp_chipsets[i].driver; |
2395 | find_gmch(intel_agp_chipsets[i].gmch_chip_id)) { | 759 | break; |
2396 | bridge->driver = | ||
2397 | intel_agp_chipsets[i].gmch_driver; | ||
2398 | break; | ||
2399 | } else if (intel_agp_chipsets[i].multi_gmch_chip) { | ||
2400 | continue; | ||
2401 | } else { | ||
2402 | bridge->driver = intel_agp_chipsets[i].driver; | ||
2403 | break; | ||
2404 | } | ||
2405 | } | 760 | } |
2406 | } | 761 | } |
2407 | 762 | ||
2408 | if (intel_agp_chipsets[i].name == NULL) { | 763 | if (!bridge->driver) { |
2409 | if (cap_ptr) | 764 | if (cap_ptr) |
2410 | dev_warn(&pdev->dev, "unsupported Intel chipset [%04x/%04x]\n", | 765 | dev_warn(&pdev->dev, "unsupported Intel chipset [%04x/%04x]\n", |
2411 | pdev->vendor, pdev->device); | 766 | pdev->vendor, pdev->device); |
@@ -2413,22 +768,23 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, | |||
2413 | return -ENODEV; | 768 | return -ENODEV; |
2414 | } | 769 | } |
2415 | 770 | ||
2416 | if (bridge->driver == NULL) { | ||
2417 | /* bridge has no AGP and no IGD detected */ | ||
2418 | if (cap_ptr) | ||
2419 | dev_warn(&pdev->dev, "can't find bridge device (chip_id: %04x)\n", | ||
2420 | intel_agp_chipsets[i].gmch_chip_id); | ||
2421 | agp_put_bridge(bridge); | ||
2422 | return -ENODEV; | ||
2423 | } | ||
2424 | |||
2425 | bridge->dev = pdev; | 771 | bridge->dev = pdev; |
2426 | bridge->capndx = cap_ptr; | 772 | bridge->dev_private_data = NULL; |
2427 | bridge->dev_private_data = &intel_private; | ||
2428 | 773 | ||
2429 | dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name); | 774 | dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name); |
2430 | 775 | ||
2431 | /* | 776 | /* |
777 | * If the device has not been properly setup, the following will catch | ||
778 | * the problem and should stop the system from crashing. | ||
779 | * 20030610 - hamish@zot.org | ||
780 | */ | ||
781 | if (pci_enable_device(pdev)) { | ||
782 | dev_err(&pdev->dev, "can't enable PCI device\n"); | ||
783 | agp_put_bridge(bridge); | ||
784 | return -ENODEV; | ||
785 | } | ||
786 | |||
787 | /* | ||
2432 | * The following fixes the case where the BIOS has "forgotten" to | 788 | * The following fixes the case where the BIOS has "forgotten" to |
2433 | * provide an address range for the GART. | 789 | * provide an address range for the GART. |
2434 | * 20030610 - hamish@zot.org | 790 | * 20030610 - hamish@zot.org |
@@ -2442,17 +798,6 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, | |||
2442 | } | 798 | } |
2443 | } | 799 | } |
2444 | 800 | ||
2445 | /* | ||
2446 | * If the device has not been properly setup, the following will catch | ||
2447 | * the problem and should stop the system from crashing. | ||
2448 | * 20030610 - hamish@zot.org | ||
2449 | */ | ||
2450 | if (pci_enable_device(pdev)) { | ||
2451 | dev_err(&pdev->dev, "can't enable PCI device\n"); | ||
2452 | agp_put_bridge(bridge); | ||
2453 | return -ENODEV; | ||
2454 | } | ||
2455 | |||
2456 | /* Fill in the mode register */ | 801 | /* Fill in the mode register */ |
2457 | if (cap_ptr) { | 802 | if (cap_ptr) { |
2458 | pci_read_config_dword(pdev, | 803 | pci_read_config_dword(pdev, |
@@ -2460,17 +805,12 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, | |||
2460 | &bridge->mode); | 805 | &bridge->mode); |
2461 | } | 806 | } |
2462 | 807 | ||
2463 | if (bridge->driver->mask_memory == intel_i965_mask_memory) { | 808 | found_gmch: |
2464 | if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(36))) | ||
2465 | dev_err(&intel_private.pcidev->dev, | ||
2466 | "set gfx device dma mask 36bit failed!\n"); | ||
2467 | else | ||
2468 | pci_set_consistent_dma_mask(intel_private.pcidev, | ||
2469 | DMA_BIT_MASK(36)); | ||
2470 | } | ||
2471 | |||
2472 | pci_set_drvdata(pdev, bridge); | 809 | pci_set_drvdata(pdev, bridge); |
2473 | return agp_add_bridge(bridge); | 810 | err = agp_add_bridge(bridge); |
811 | if (!err) | ||
812 | intel_agp_enabled = 1; | ||
813 | return err; | ||
2474 | } | 814 | } |
2475 | 815 | ||
2476 | static void __devexit agp_intel_remove(struct pci_dev *pdev) | 816 | static void __devexit agp_intel_remove(struct pci_dev *pdev) |
@@ -2479,8 +819,7 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev) | |||
2479 | 819 | ||
2480 | agp_remove_bridge(bridge); | 820 | agp_remove_bridge(bridge); |
2481 | 821 | ||
2482 | if (intel_private.pcidev) | 822 | intel_gmch_remove(pdev); |
2483 | pci_dev_put(intel_private.pcidev); | ||
2484 | 823 | ||
2485 | agp_put_bridge(bridge); | 824 | agp_put_bridge(bridge); |
2486 | } | 825 | } |
@@ -2491,22 +830,7 @@ static int agp_intel_resume(struct pci_dev *pdev) | |||
2491 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | 830 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
2492 | int ret_val; | 831 | int ret_val; |
2493 | 832 | ||
2494 | if (bridge->driver == &intel_generic_driver) | 833 | bridge->driver->configure(); |
2495 | intel_configure(); | ||
2496 | else if (bridge->driver == &intel_850_driver) | ||
2497 | intel_850_configure(); | ||
2498 | else if (bridge->driver == &intel_845_driver) | ||
2499 | intel_845_configure(); | ||
2500 | else if (bridge->driver == &intel_830mp_driver) | ||
2501 | intel_830mp_configure(); | ||
2502 | else if (bridge->driver == &intel_915_driver) | ||
2503 | intel_i915_configure(); | ||
2504 | else if (bridge->driver == &intel_830_driver) | ||
2505 | intel_i830_configure(); | ||
2506 | else if (bridge->driver == &intel_810_driver) | ||
2507 | intel_i810_configure(); | ||
2508 | else if (bridge->driver == &intel_i965_driver) | ||
2509 | intel_i915_configure(); | ||
2510 | 834 | ||
2511 | ret_val = agp_rebind_memory(); | 835 | ret_val = agp_rebind_memory(); |
2512 | if (ret_val != 0) | 836 | if (ret_val != 0) |
@@ -2571,10 +895,14 @@ static struct pci_device_id agp_intel_pci_table[] = { | |||
2571 | ID(PCI_DEVICE_ID_INTEL_G45_HB), | 895 | ID(PCI_DEVICE_ID_INTEL_G45_HB), |
2572 | ID(PCI_DEVICE_ID_INTEL_G41_HB), | 896 | ID(PCI_DEVICE_ID_INTEL_G41_HB), |
2573 | ID(PCI_DEVICE_ID_INTEL_B43_HB), | 897 | ID(PCI_DEVICE_ID_INTEL_B43_HB), |
898 | ID(PCI_DEVICE_ID_INTEL_B43_1_HB), | ||
2574 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB), | 899 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB), |
2575 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB), | 900 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB), |
2576 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB), | 901 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB), |
2577 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), | 902 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), |
903 | ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB), | ||
904 | ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB), | ||
905 | ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB), | ||
2578 | { } | 906 | { } |
2579 | }; | 907 | }; |
2580 | 908 | ||
diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h new file mode 100644 index 000000000000..90539df02504 --- /dev/null +++ b/drivers/char/agp/intel-agp.h | |||
@@ -0,0 +1,221 @@ | |||
1 | /* | ||
2 | * Common Intel AGPGART and GTT definitions. | ||
3 | */ | ||
4 | #ifndef _INTEL_AGP_H | ||
5 | #define _INTEL_AGP_H | ||
6 | |||
7 | /* Intel registers */ | ||
8 | #define INTEL_APSIZE 0xb4 | ||
9 | #define INTEL_ATTBASE 0xb8 | ||
10 | #define INTEL_AGPCTRL 0xb0 | ||
11 | #define INTEL_NBXCFG 0x50 | ||
12 | #define INTEL_ERRSTS 0x91 | ||
13 | |||
14 | /* Intel i830 registers */ | ||
15 | #define I830_GMCH_CTRL 0x52 | ||
16 | #define I830_GMCH_ENABLED 0x4 | ||
17 | #define I830_GMCH_MEM_MASK 0x1 | ||
18 | #define I830_GMCH_MEM_64M 0x1 | ||
19 | #define I830_GMCH_MEM_128M 0 | ||
20 | #define I830_GMCH_GMS_MASK 0x70 | ||
21 | #define I830_GMCH_GMS_DISABLED 0x00 | ||
22 | #define I830_GMCH_GMS_LOCAL 0x10 | ||
23 | #define I830_GMCH_GMS_STOLEN_512 0x20 | ||
24 | #define I830_GMCH_GMS_STOLEN_1024 0x30 | ||
25 | #define I830_GMCH_GMS_STOLEN_8192 0x40 | ||
26 | #define I830_RDRAM_CHANNEL_TYPE 0x03010 | ||
27 | #define I830_RDRAM_ND(x) (((x) & 0x20) >> 5) | ||
28 | #define I830_RDRAM_DDT(x) (((x) & 0x18) >> 3) | ||
29 | |||
30 | /* This one is for I830MP w. an external graphic card */ | ||
31 | #define INTEL_I830_ERRSTS 0x92 | ||
32 | |||
33 | /* Intel 855GM/852GM registers */ | ||
34 | #define I855_GMCH_GMS_MASK 0xF0 | ||
35 | #define I855_GMCH_GMS_STOLEN_0M 0x0 | ||
36 | #define I855_GMCH_GMS_STOLEN_1M (0x1 << 4) | ||
37 | #define I855_GMCH_GMS_STOLEN_4M (0x2 << 4) | ||
38 | #define I855_GMCH_GMS_STOLEN_8M (0x3 << 4) | ||
39 | #define I855_GMCH_GMS_STOLEN_16M (0x4 << 4) | ||
40 | #define I855_GMCH_GMS_STOLEN_32M (0x5 << 4) | ||
41 | #define I85X_CAPID 0x44 | ||
42 | #define I85X_VARIANT_MASK 0x7 | ||
43 | #define I85X_VARIANT_SHIFT 5 | ||
44 | #define I855_GME 0x0 | ||
45 | #define I855_GM 0x4 | ||
46 | #define I852_GME 0x2 | ||
47 | #define I852_GM 0x5 | ||
48 | |||
49 | /* Intel i845 registers */ | ||
50 | #define INTEL_I845_AGPM 0x51 | ||
51 | #define INTEL_I845_ERRSTS 0xc8 | ||
52 | |||
53 | /* Intel i860 registers */ | ||
54 | #define INTEL_I860_MCHCFG 0x50 | ||
55 | #define INTEL_I860_ERRSTS 0xc8 | ||
56 | |||
57 | /* Intel i810 registers */ | ||
58 | #define I810_GMADDR 0x10 | ||
59 | #define I810_MMADDR 0x14 | ||
60 | #define I810_PTE_BASE 0x10000 | ||
61 | #define I810_PTE_MAIN_UNCACHED 0x00000000 | ||
62 | #define I810_PTE_LOCAL 0x00000002 | ||
63 | #define I810_PTE_VALID 0x00000001 | ||
64 | #define I830_PTE_SYSTEM_CACHED 0x00000006 | ||
65 | /* GT PTE cache control fields */ | ||
66 | #define GEN6_PTE_UNCACHED 0x00000002 | ||
67 | #define GEN6_PTE_LLC 0x00000004 | ||
68 | #define GEN6_PTE_LLC_MLC 0x00000006 | ||
69 | #define GEN6_PTE_GFDT 0x00000008 | ||
70 | |||
71 | #define I810_SMRAM_MISCC 0x70 | ||
72 | #define I810_GFX_MEM_WIN_SIZE 0x00010000 | ||
73 | #define I810_GFX_MEM_WIN_32M 0x00010000 | ||
74 | #define I810_GMS 0x000000c0 | ||
75 | #define I810_GMS_DISABLE 0x00000000 | ||
76 | #define I810_PGETBL_CTL 0x2020 | ||
77 | #define I810_PGETBL_ENABLED 0x00000001 | ||
78 | #define I965_PGETBL_SIZE_MASK 0x0000000e | ||
79 | #define I965_PGETBL_SIZE_512KB (0 << 1) | ||
80 | #define I965_PGETBL_SIZE_256KB (1 << 1) | ||
81 | #define I965_PGETBL_SIZE_128KB (2 << 1) | ||
82 | #define I965_PGETBL_SIZE_1MB (3 << 1) | ||
83 | #define I965_PGETBL_SIZE_2MB (4 << 1) | ||
84 | #define I965_PGETBL_SIZE_1_5MB (5 << 1) | ||
85 | #define G33_PGETBL_SIZE_MASK (3 << 8) | ||
86 | #define G33_PGETBL_SIZE_1M (1 << 8) | ||
87 | #define G33_PGETBL_SIZE_2M (2 << 8) | ||
88 | |||
89 | #define I810_DRAM_CTL 0x3000 | ||
90 | #define I810_DRAM_ROW_0 0x00000001 | ||
91 | #define I810_DRAM_ROW_0_SDRAM 0x00000001 | ||
92 | |||
93 | /* Intel 815 register */ | ||
94 | #define INTEL_815_APCONT 0x51 | ||
95 | #define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF | ||
96 | |||
97 | /* Intel i820 registers */ | ||
98 | #define INTEL_I820_RDCR 0x51 | ||
99 | #define INTEL_I820_ERRSTS 0xc8 | ||
100 | |||
101 | /* Intel i840 registers */ | ||
102 | #define INTEL_I840_MCHCFG 0x50 | ||
103 | #define INTEL_I840_ERRSTS 0xc8 | ||
104 | |||
105 | /* Intel i850 registers */ | ||
106 | #define INTEL_I850_MCHCFG 0x50 | ||
107 | #define INTEL_I850_ERRSTS 0xc8 | ||
108 | |||
109 | /* intel 915G registers */ | ||
110 | #define I915_GMADDR 0x18 | ||
111 | #define I915_MMADDR 0x10 | ||
112 | #define I915_PTEADDR 0x1C | ||
113 | #define I915_GMCH_GMS_STOLEN_48M (0x6 << 4) | ||
114 | #define I915_GMCH_GMS_STOLEN_64M (0x7 << 4) | ||
115 | #define G33_GMCH_GMS_STOLEN_128M (0x8 << 4) | ||
116 | #define G33_GMCH_GMS_STOLEN_256M (0x9 << 4) | ||
117 | #define INTEL_GMCH_GMS_STOLEN_96M (0xa << 4) | ||
118 | #define INTEL_GMCH_GMS_STOLEN_160M (0xb << 4) | ||
119 | #define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4) | ||
120 | #define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4) | ||
121 | |||
122 | #define I915_IFPADDR 0x60 | ||
123 | |||
124 | /* Intel 965G registers */ | ||
125 | #define I965_MSAC 0x62 | ||
126 | #define I965_IFPADDR 0x70 | ||
127 | |||
128 | /* Intel 7505 registers */ | ||
129 | #define INTEL_I7505_APSIZE 0x74 | ||
130 | #define INTEL_I7505_NCAPID 0x60 | ||
131 | #define INTEL_I7505_NISTAT 0x6c | ||
132 | #define INTEL_I7505_ATTBASE 0x78 | ||
133 | #define INTEL_I7505_ERRSTS 0x42 | ||
134 | #define INTEL_I7505_AGPCTRL 0x70 | ||
135 | #define INTEL_I7505_MCHCFG 0x50 | ||
136 | |||
137 | #define SNB_GMCH_CTRL 0x50 | ||
138 | #define SNB_GMCH_GMS_STOLEN_MASK 0xF8 | ||
139 | #define SNB_GMCH_GMS_STOLEN_32M (1 << 3) | ||
140 | #define SNB_GMCH_GMS_STOLEN_64M (2 << 3) | ||
141 | #define SNB_GMCH_GMS_STOLEN_96M (3 << 3) | ||
142 | #define SNB_GMCH_GMS_STOLEN_128M (4 << 3) | ||
143 | #define SNB_GMCH_GMS_STOLEN_160M (5 << 3) | ||
144 | #define SNB_GMCH_GMS_STOLEN_192M (6 << 3) | ||
145 | #define SNB_GMCH_GMS_STOLEN_224M (7 << 3) | ||
146 | #define SNB_GMCH_GMS_STOLEN_256M (8 << 3) | ||
147 | #define SNB_GMCH_GMS_STOLEN_288M (9 << 3) | ||
148 | #define SNB_GMCH_GMS_STOLEN_320M (0xa << 3) | ||
149 | #define SNB_GMCH_GMS_STOLEN_352M (0xb << 3) | ||
150 | #define SNB_GMCH_GMS_STOLEN_384M (0xc << 3) | ||
151 | #define SNB_GMCH_GMS_STOLEN_416M (0xd << 3) | ||
152 | #define SNB_GMCH_GMS_STOLEN_448M (0xe << 3) | ||
153 | #define SNB_GMCH_GMS_STOLEN_480M (0xf << 3) | ||
154 | #define SNB_GMCH_GMS_STOLEN_512M (0x10 << 3) | ||
155 | #define SNB_GTT_SIZE_0M (0 << 8) | ||
156 | #define SNB_GTT_SIZE_1M (1 << 8) | ||
157 | #define SNB_GTT_SIZE_2M (2 << 8) | ||
158 | #define SNB_GTT_SIZE_MASK (3 << 8) | ||
159 | |||
160 | /* pci devices ids */ | ||
161 | #define PCI_DEVICE_ID_INTEL_E7221_HB 0x2588 | ||
162 | #define PCI_DEVICE_ID_INTEL_E7221_IG 0x258a | ||
163 | #define PCI_DEVICE_ID_INTEL_82946GZ_HB 0x2970 | ||
164 | #define PCI_DEVICE_ID_INTEL_82946GZ_IG 0x2972 | ||
165 | #define PCI_DEVICE_ID_INTEL_82G35_HB 0x2980 | ||
166 | #define PCI_DEVICE_ID_INTEL_82G35_IG 0x2982 | ||
167 | #define PCI_DEVICE_ID_INTEL_82965Q_HB 0x2990 | ||
168 | #define PCI_DEVICE_ID_INTEL_82965Q_IG 0x2992 | ||
169 | #define PCI_DEVICE_ID_INTEL_82965G_HB 0x29A0 | ||
170 | #define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2 | ||
171 | #define PCI_DEVICE_ID_INTEL_82965GM_HB 0x2A00 | ||
172 | #define PCI_DEVICE_ID_INTEL_82965GM_IG 0x2A02 | ||
173 | #define PCI_DEVICE_ID_INTEL_82965GME_HB 0x2A10 | ||
174 | #define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12 | ||
175 | #define PCI_DEVICE_ID_INTEL_82945GME_HB 0x27AC | ||
176 | #define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE | ||
177 | #define PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB 0xA010 | ||
178 | #define PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG 0xA011 | ||
179 | #define PCI_DEVICE_ID_INTEL_PINEVIEW_HB 0xA000 | ||
180 | #define PCI_DEVICE_ID_INTEL_PINEVIEW_IG 0xA001 | ||
181 | #define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0 | ||
182 | #define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2 | ||
183 | #define PCI_DEVICE_ID_INTEL_Q35_HB 0x29B0 | ||
184 | #define PCI_DEVICE_ID_INTEL_Q35_IG 0x29B2 | ||
185 | #define PCI_DEVICE_ID_INTEL_Q33_HB 0x29D0 | ||
186 | #define PCI_DEVICE_ID_INTEL_Q33_IG 0x29D2 | ||
187 | #define PCI_DEVICE_ID_INTEL_B43_HB 0x2E40 | ||
188 | #define PCI_DEVICE_ID_INTEL_B43_IG 0x2E42 | ||
189 | #define PCI_DEVICE_ID_INTEL_B43_1_HB 0x2E90 | ||
190 | #define PCI_DEVICE_ID_INTEL_B43_1_IG 0x2E92 | ||
191 | #define PCI_DEVICE_ID_INTEL_GM45_HB 0x2A40 | ||
192 | #define PCI_DEVICE_ID_INTEL_GM45_IG 0x2A42 | ||
193 | #define PCI_DEVICE_ID_INTEL_EAGLELAKE_HB 0x2E00 | ||
194 | #define PCI_DEVICE_ID_INTEL_EAGLELAKE_IG 0x2E02 | ||
195 | #define PCI_DEVICE_ID_INTEL_Q45_HB 0x2E10 | ||
196 | #define PCI_DEVICE_ID_INTEL_Q45_IG 0x2E12 | ||
197 | #define PCI_DEVICE_ID_INTEL_G45_HB 0x2E20 | ||
198 | #define PCI_DEVICE_ID_INTEL_G45_IG 0x2E22 | ||
199 | #define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30 | ||
200 | #define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32 | ||
201 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB 0x0040 | ||
202 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG 0x0042 | ||
203 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB 0x0044 | ||
204 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062 | ||
205 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a | ||
206 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046 | ||
207 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100 /* Desktop */ | ||
208 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG 0x0102 | ||
209 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG 0x0112 | ||
210 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG 0x0122 | ||
211 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104 /* Mobile */ | ||
212 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG 0x0106 | ||
213 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG 0x0116 | ||
214 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG 0x0126 | ||
215 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB 0x0108 /* Server */ | ||
216 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG 0x010A | ||
217 | |||
218 | int intel_gmch_probe(struct pci_dev *pdev, | ||
219 | struct agp_bridge_data *bridge); | ||
220 | void intel_gmch_remove(struct pci_dev *pdev); | ||
221 | #endif | ||
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c new file mode 100644 index 000000000000..6b6760ea2435 --- /dev/null +++ b/drivers/char/agp/intel-gtt.c | |||
@@ -0,0 +1,1580 @@ | |||
1 | /* | ||
2 | * Intel GTT (Graphics Translation Table) routines | ||
3 | * | ||
4 | * Caveat: This driver implements the linux agp interface, but this is far from | ||
5 | * a agp driver! GTT support ended up here for purely historical reasons: The | ||
6 | * old userspace intel graphics drivers needed an interface to map memory into | ||
7 | * the GTT. And the drm provides a default interface for graphic devices sitting | ||
8 | * on an agp port. So it made sense to fake the GTT support as an agp port to | ||
9 | * avoid having to create a new api. | ||
10 | * | ||
11 | * With gem this does not make much sense anymore, just needlessly complicates | ||
12 | * the code. But as long as the old graphics stack is still support, it's stuck | ||
13 | * here. | ||
14 | * | ||
15 | * /fairy-tale-mode off | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/pci.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/pagemap.h> | ||
23 | #include <linux/agp_backend.h> | ||
24 | #include <asm/smp.h> | ||
25 | #include "agp.h" | ||
26 | #include "intel-agp.h" | ||
27 | #include <linux/intel-gtt.h> | ||
28 | #include <drm/intel-gtt.h> | ||
29 | |||
30 | /* | ||
31 | * If we have Intel graphics, we're not going to have anything other than | ||
32 | * an Intel IOMMU. So make the correct use of the PCI DMA API contingent | ||
33 | * on the Intel IOMMU support (CONFIG_DMAR). | ||
34 | * Only newer chipsets need to bother with this, of course. | ||
35 | */ | ||
36 | #ifdef CONFIG_DMAR | ||
37 | #define USE_PCI_DMA_API 1 | ||
38 | #else | ||
39 | #define USE_PCI_DMA_API 0 | ||
40 | #endif | ||
41 | |||
42 | /* Max amount of stolen space, anything above will be returned to Linux */ | ||
43 | int intel_max_stolen = 32 * 1024 * 1024; | ||
44 | |||
45 | static const struct aper_size_info_fixed intel_i810_sizes[] = | ||
46 | { | ||
47 | {64, 16384, 4}, | ||
48 | /* The 32M mode still requires a 64k gatt */ | ||
49 | {32, 8192, 4} | ||
50 | }; | ||
51 | |||
52 | #define AGP_DCACHE_MEMORY 1 | ||
53 | #define AGP_PHYS_MEMORY 2 | ||
54 | #define INTEL_AGP_CACHED_MEMORY 3 | ||
55 | |||
56 | static struct gatt_mask intel_i810_masks[] = | ||
57 | { | ||
58 | {.mask = I810_PTE_VALID, .type = 0}, | ||
59 | {.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY}, | ||
60 | {.mask = I810_PTE_VALID, .type = 0}, | ||
61 | {.mask = I810_PTE_VALID | I830_PTE_SYSTEM_CACHED, | ||
62 | .type = INTEL_AGP_CACHED_MEMORY} | ||
63 | }; | ||
64 | |||
65 | #define INTEL_AGP_UNCACHED_MEMORY 0 | ||
66 | #define INTEL_AGP_CACHED_MEMORY_LLC 1 | ||
67 | #define INTEL_AGP_CACHED_MEMORY_LLC_GFDT 2 | ||
68 | #define INTEL_AGP_CACHED_MEMORY_LLC_MLC 3 | ||
69 | #define INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT 4 | ||
70 | |||
71 | struct intel_gtt_driver { | ||
72 | unsigned int gen : 8; | ||
73 | unsigned int is_g33 : 1; | ||
74 | unsigned int is_pineview : 1; | ||
75 | unsigned int is_ironlake : 1; | ||
76 | unsigned int dma_mask_size : 8; | ||
77 | /* Chipset specific GTT setup */ | ||
78 | int (*setup)(void); | ||
79 | /* This should undo anything done in ->setup() save the unmapping | ||
80 | * of the mmio register file, that's done in the generic code. */ | ||
81 | void (*cleanup)(void); | ||
82 | void (*write_entry)(dma_addr_t addr, unsigned int entry, unsigned int flags); | ||
83 | /* Flags is a more or less chipset specific opaque value. | ||
84 | * For chipsets that need to support old ums (non-gem) code, this | ||
85 | * needs to be identical to the various supported agp memory types! */ | ||
86 | bool (*check_flags)(unsigned int flags); | ||
87 | void (*chipset_flush)(void); | ||
88 | }; | ||
89 | |||
90 | static struct _intel_private { | ||
91 | struct intel_gtt base; | ||
92 | const struct intel_gtt_driver *driver; | ||
93 | struct pci_dev *pcidev; /* device one */ | ||
94 | struct pci_dev *bridge_dev; | ||
95 | u8 __iomem *registers; | ||
96 | phys_addr_t gtt_bus_addr; | ||
97 | phys_addr_t gma_bus_addr; | ||
98 | phys_addr_t pte_bus_addr; | ||
99 | u32 __iomem *gtt; /* I915G */ | ||
100 | int num_dcache_entries; | ||
101 | union { | ||
102 | void __iomem *i9xx_flush_page; | ||
103 | void *i8xx_flush_page; | ||
104 | }; | ||
105 | struct page *i8xx_page; | ||
106 | struct resource ifp_resource; | ||
107 | int resource_valid; | ||
108 | struct page *scratch_page; | ||
109 | dma_addr_t scratch_page_dma; | ||
110 | } intel_private; | ||
111 | |||
112 | #define INTEL_GTT_GEN intel_private.driver->gen | ||
113 | #define IS_G33 intel_private.driver->is_g33 | ||
114 | #define IS_PINEVIEW intel_private.driver->is_pineview | ||
115 | #define IS_IRONLAKE intel_private.driver->is_ironlake | ||
116 | |||
117 | static void intel_agp_free_sglist(struct agp_memory *mem) | ||
118 | { | ||
119 | struct sg_table st; | ||
120 | |||
121 | st.sgl = mem->sg_list; | ||
122 | st.orig_nents = st.nents = mem->page_count; | ||
123 | |||
124 | sg_free_table(&st); | ||
125 | |||
126 | mem->sg_list = NULL; | ||
127 | mem->num_sg = 0; | ||
128 | } | ||
129 | |||
130 | static int intel_agp_map_memory(struct agp_memory *mem) | ||
131 | { | ||
132 | struct sg_table st; | ||
133 | struct scatterlist *sg; | ||
134 | int i; | ||
135 | |||
136 | if (mem->sg_list) | ||
137 | return 0; /* already mapped (for e.g. resume */ | ||
138 | |||
139 | DBG("try mapping %lu pages\n", (unsigned long)mem->page_count); | ||
140 | |||
141 | if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL)) | ||
142 | goto err; | ||
143 | |||
144 | mem->sg_list = sg = st.sgl; | ||
145 | |||
146 | for (i = 0 ; i < mem->page_count; i++, sg = sg_next(sg)) | ||
147 | sg_set_page(sg, mem->pages[i], PAGE_SIZE, 0); | ||
148 | |||
149 | mem->num_sg = pci_map_sg(intel_private.pcidev, mem->sg_list, | ||
150 | mem->page_count, PCI_DMA_BIDIRECTIONAL); | ||
151 | if (unlikely(!mem->num_sg)) | ||
152 | goto err; | ||
153 | |||
154 | return 0; | ||
155 | |||
156 | err: | ||
157 | sg_free_table(&st); | ||
158 | return -ENOMEM; | ||
159 | } | ||
160 | |||
161 | static void intel_agp_unmap_memory(struct agp_memory *mem) | ||
162 | { | ||
163 | DBG("try unmapping %lu pages\n", (unsigned long)mem->page_count); | ||
164 | |||
165 | pci_unmap_sg(intel_private.pcidev, mem->sg_list, | ||
166 | mem->page_count, PCI_DMA_BIDIRECTIONAL); | ||
167 | intel_agp_free_sglist(mem); | ||
168 | } | ||
169 | |||
170 | static int intel_i810_fetch_size(void) | ||
171 | { | ||
172 | u32 smram_miscc; | ||
173 | struct aper_size_info_fixed *values; | ||
174 | |||
175 | pci_read_config_dword(intel_private.bridge_dev, | ||
176 | I810_SMRAM_MISCC, &smram_miscc); | ||
177 | values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); | ||
178 | |||
179 | if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) { | ||
180 | dev_warn(&intel_private.bridge_dev->dev, "i810 is disabled\n"); | ||
181 | return 0; | ||
182 | } | ||
183 | if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) { | ||
184 | agp_bridge->current_size = (void *) (values + 1); | ||
185 | agp_bridge->aperture_size_idx = 1; | ||
186 | return values[1].size; | ||
187 | } else { | ||
188 | agp_bridge->current_size = (void *) (values); | ||
189 | agp_bridge->aperture_size_idx = 0; | ||
190 | return values[0].size; | ||
191 | } | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static int intel_i810_configure(void) | ||
197 | { | ||
198 | struct aper_size_info_fixed *current_size; | ||
199 | u32 temp; | ||
200 | int i; | ||
201 | |||
202 | current_size = A_SIZE_FIX(agp_bridge->current_size); | ||
203 | |||
204 | if (!intel_private.registers) { | ||
205 | pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp); | ||
206 | temp &= 0xfff80000; | ||
207 | |||
208 | intel_private.registers = ioremap(temp, 128 * 4096); | ||
209 | if (!intel_private.registers) { | ||
210 | dev_err(&intel_private.pcidev->dev, | ||
211 | "can't remap memory\n"); | ||
212 | return -ENOMEM; | ||
213 | } | ||
214 | } | ||
215 | |||
216 | if ((readl(intel_private.registers+I810_DRAM_CTL) | ||
217 | & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) { | ||
218 | /* This will need to be dynamically assigned */ | ||
219 | dev_info(&intel_private.pcidev->dev, | ||
220 | "detected 4MB dedicated video ram\n"); | ||
221 | intel_private.num_dcache_entries = 1024; | ||
222 | } | ||
223 | pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp); | ||
224 | agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); | ||
225 | writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL); | ||
226 | readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ | ||
227 | |||
228 | if (agp_bridge->driver->needs_scratch_page) { | ||
229 | for (i = 0; i < current_size->num_entries; i++) { | ||
230 | writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); | ||
231 | } | ||
232 | readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI posting. */ | ||
233 | } | ||
234 | global_cache_flush(); | ||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | static void intel_i810_cleanup(void) | ||
239 | { | ||
240 | writel(0, intel_private.registers+I810_PGETBL_CTL); | ||
241 | readl(intel_private.registers); /* PCI Posting. */ | ||
242 | iounmap(intel_private.registers); | ||
243 | } | ||
244 | |||
245 | static void intel_fake_agp_enable(struct agp_bridge_data *bridge, u32 mode) | ||
246 | { | ||
247 | return; | ||
248 | } | ||
249 | |||
250 | /* Exists to support ARGB cursors */ | ||
251 | static struct page *i8xx_alloc_pages(void) | ||
252 | { | ||
253 | struct page *page; | ||
254 | |||
255 | page = alloc_pages(GFP_KERNEL | GFP_DMA32, 2); | ||
256 | if (page == NULL) | ||
257 | return NULL; | ||
258 | |||
259 | if (set_pages_uc(page, 4) < 0) { | ||
260 | set_pages_wb(page, 4); | ||
261 | __free_pages(page, 2); | ||
262 | return NULL; | ||
263 | } | ||
264 | get_page(page); | ||
265 | atomic_inc(&agp_bridge->current_memory_agp); | ||
266 | return page; | ||
267 | } | ||
268 | |||
269 | static void i8xx_destroy_pages(struct page *page) | ||
270 | { | ||
271 | if (page == NULL) | ||
272 | return; | ||
273 | |||
274 | set_pages_wb(page, 4); | ||
275 | put_page(page); | ||
276 | __free_pages(page, 2); | ||
277 | atomic_dec(&agp_bridge->current_memory_agp); | ||
278 | } | ||
279 | |||
280 | static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, | ||
281 | int type) | ||
282 | { | ||
283 | int i, j, num_entries; | ||
284 | void *temp; | ||
285 | int ret = -EINVAL; | ||
286 | int mask_type; | ||
287 | |||
288 | if (mem->page_count == 0) | ||
289 | goto out; | ||
290 | |||
291 | temp = agp_bridge->current_size; | ||
292 | num_entries = A_SIZE_FIX(temp)->num_entries; | ||
293 | |||
294 | if ((pg_start + mem->page_count) > num_entries) | ||
295 | goto out_err; | ||
296 | |||
297 | |||
298 | for (j = pg_start; j < (pg_start + mem->page_count); j++) { | ||
299 | if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) { | ||
300 | ret = -EBUSY; | ||
301 | goto out_err; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | if (type != mem->type) | ||
306 | goto out_err; | ||
307 | |||
308 | mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); | ||
309 | |||
310 | switch (mask_type) { | ||
311 | case AGP_DCACHE_MEMORY: | ||
312 | if (!mem->is_flushed) | ||
313 | global_cache_flush(); | ||
314 | for (i = pg_start; i < (pg_start + mem->page_count); i++) { | ||
315 | writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, | ||
316 | intel_private.registers+I810_PTE_BASE+(i*4)); | ||
317 | } | ||
318 | readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); | ||
319 | break; | ||
320 | case AGP_PHYS_MEMORY: | ||
321 | case AGP_NORMAL_MEMORY: | ||
322 | if (!mem->is_flushed) | ||
323 | global_cache_flush(); | ||
324 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | ||
325 | writel(agp_bridge->driver->mask_memory(agp_bridge, | ||
326 | page_to_phys(mem->pages[i]), mask_type), | ||
327 | intel_private.registers+I810_PTE_BASE+(j*4)); | ||
328 | } | ||
329 | readl(intel_private.registers+I810_PTE_BASE+((j-1)*4)); | ||
330 | break; | ||
331 | default: | ||
332 | goto out_err; | ||
333 | } | ||
334 | |||
335 | out: | ||
336 | ret = 0; | ||
337 | out_err: | ||
338 | mem->is_flushed = true; | ||
339 | return ret; | ||
340 | } | ||
341 | |||
342 | static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start, | ||
343 | int type) | ||
344 | { | ||
345 | int i; | ||
346 | |||
347 | if (mem->page_count == 0) | ||
348 | return 0; | ||
349 | |||
350 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | ||
351 | writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); | ||
352 | } | ||
353 | readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); | ||
354 | |||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | /* | ||
359 | * The i810/i830 requires a physical address to program its mouse | ||
360 | * pointer into hardware. | ||
361 | * However the Xserver still writes to it through the agp aperture. | ||
362 | */ | ||
363 | static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type) | ||
364 | { | ||
365 | struct agp_memory *new; | ||
366 | struct page *page; | ||
367 | |||
368 | switch (pg_count) { | ||
369 | case 1: page = agp_bridge->driver->agp_alloc_page(agp_bridge); | ||
370 | break; | ||
371 | case 4: | ||
372 | /* kludge to get 4 physical pages for ARGB cursor */ | ||
373 | page = i8xx_alloc_pages(); | ||
374 | break; | ||
375 | default: | ||
376 | return NULL; | ||
377 | } | ||
378 | |||
379 | if (page == NULL) | ||
380 | return NULL; | ||
381 | |||
382 | new = agp_create_memory(pg_count); | ||
383 | if (new == NULL) | ||
384 | return NULL; | ||
385 | |||
386 | new->pages[0] = page; | ||
387 | if (pg_count == 4) { | ||
388 | /* kludge to get 4 physical pages for ARGB cursor */ | ||
389 | new->pages[1] = new->pages[0] + 1; | ||
390 | new->pages[2] = new->pages[1] + 1; | ||
391 | new->pages[3] = new->pages[2] + 1; | ||
392 | } | ||
393 | new->page_count = pg_count; | ||
394 | new->num_scratch_pages = pg_count; | ||
395 | new->type = AGP_PHYS_MEMORY; | ||
396 | new->physical = page_to_phys(new->pages[0]); | ||
397 | return new; | ||
398 | } | ||
399 | |||
400 | static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type) | ||
401 | { | ||
402 | struct agp_memory *new; | ||
403 | |||
404 | if (type == AGP_DCACHE_MEMORY) { | ||
405 | if (pg_count != intel_private.num_dcache_entries) | ||
406 | return NULL; | ||
407 | |||
408 | new = agp_create_memory(1); | ||
409 | if (new == NULL) | ||
410 | return NULL; | ||
411 | |||
412 | new->type = AGP_DCACHE_MEMORY; | ||
413 | new->page_count = pg_count; | ||
414 | new->num_scratch_pages = 0; | ||
415 | agp_free_page_array(new); | ||
416 | return new; | ||
417 | } | ||
418 | if (type == AGP_PHYS_MEMORY) | ||
419 | return alloc_agpphysmem_i8xx(pg_count, type); | ||
420 | return NULL; | ||
421 | } | ||
422 | |||
423 | static void intel_i810_free_by_type(struct agp_memory *curr) | ||
424 | { | ||
425 | agp_free_key(curr->key); | ||
426 | if (curr->type == AGP_PHYS_MEMORY) { | ||
427 | if (curr->page_count == 4) | ||
428 | i8xx_destroy_pages(curr->pages[0]); | ||
429 | else { | ||
430 | agp_bridge->driver->agp_destroy_page(curr->pages[0], | ||
431 | AGP_PAGE_DESTROY_UNMAP); | ||
432 | agp_bridge->driver->agp_destroy_page(curr->pages[0], | ||
433 | AGP_PAGE_DESTROY_FREE); | ||
434 | } | ||
435 | agp_free_page_array(curr); | ||
436 | } | ||
437 | kfree(curr); | ||
438 | } | ||
439 | |||
440 | static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge, | ||
441 | dma_addr_t addr, int type) | ||
442 | { | ||
443 | /* Type checking must be done elsewhere */ | ||
444 | return addr | bridge->driver->masks[type].mask; | ||
445 | } | ||
446 | |||
447 | static int intel_gtt_setup_scratch_page(void) | ||
448 | { | ||
449 | struct page *page; | ||
450 | dma_addr_t dma_addr; | ||
451 | |||
452 | page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); | ||
453 | if (page == NULL) | ||
454 | return -ENOMEM; | ||
455 | get_page(page); | ||
456 | set_pages_uc(page, 1); | ||
457 | |||
458 | if (USE_PCI_DMA_API && INTEL_GTT_GEN > 2) { | ||
459 | dma_addr = pci_map_page(intel_private.pcidev, page, 0, | ||
460 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | ||
461 | if (pci_dma_mapping_error(intel_private.pcidev, dma_addr)) | ||
462 | return -EINVAL; | ||
463 | |||
464 | intel_private.scratch_page_dma = dma_addr; | ||
465 | } else | ||
466 | intel_private.scratch_page_dma = page_to_phys(page); | ||
467 | |||
468 | intel_private.scratch_page = page; | ||
469 | |||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | static const struct aper_size_info_fixed const intel_fake_agp_sizes[] = { | ||
474 | {128, 32768, 5}, | ||
475 | /* The 64M mode still requires a 128k gatt */ | ||
476 | {64, 16384, 5}, | ||
477 | {256, 65536, 6}, | ||
478 | {512, 131072, 7}, | ||
479 | }; | ||
480 | |||
481 | static unsigned int intel_gtt_stolen_entries(void) | ||
482 | { | ||
483 | u16 gmch_ctrl; | ||
484 | u8 rdct; | ||
485 | int local = 0; | ||
486 | static const int ddt[4] = { 0, 16, 32, 64 }; | ||
487 | unsigned int overhead_entries, stolen_entries; | ||
488 | unsigned int stolen_size = 0; | ||
489 | |||
490 | pci_read_config_word(intel_private.bridge_dev, | ||
491 | I830_GMCH_CTRL, &gmch_ctrl); | ||
492 | |||
493 | if (INTEL_GTT_GEN > 4 || IS_PINEVIEW) | ||
494 | overhead_entries = 0; | ||
495 | else | ||
496 | overhead_entries = intel_private.base.gtt_mappable_entries | ||
497 | / 1024; | ||
498 | |||
499 | overhead_entries += 1; /* BIOS popup */ | ||
500 | |||
501 | if (intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82830_HB || | ||
502 | intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) { | ||
503 | switch (gmch_ctrl & I830_GMCH_GMS_MASK) { | ||
504 | case I830_GMCH_GMS_STOLEN_512: | ||
505 | stolen_size = KB(512); | ||
506 | break; | ||
507 | case I830_GMCH_GMS_STOLEN_1024: | ||
508 | stolen_size = MB(1); | ||
509 | break; | ||
510 | case I830_GMCH_GMS_STOLEN_8192: | ||
511 | stolen_size = MB(8); | ||
512 | break; | ||
513 | case I830_GMCH_GMS_LOCAL: | ||
514 | rdct = readb(intel_private.registers+I830_RDRAM_CHANNEL_TYPE); | ||
515 | stolen_size = (I830_RDRAM_ND(rdct) + 1) * | ||
516 | MB(ddt[I830_RDRAM_DDT(rdct)]); | ||
517 | local = 1; | ||
518 | break; | ||
519 | default: | ||
520 | stolen_size = 0; | ||
521 | break; | ||
522 | } | ||
523 | } else if (INTEL_GTT_GEN == 6) { | ||
524 | /* | ||
525 | * SandyBridge has new memory control reg at 0x50.w | ||
526 | */ | ||
527 | u16 snb_gmch_ctl; | ||
528 | pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); | ||
529 | switch (snb_gmch_ctl & SNB_GMCH_GMS_STOLEN_MASK) { | ||
530 | case SNB_GMCH_GMS_STOLEN_32M: | ||
531 | stolen_size = MB(32); | ||
532 | break; | ||
533 | case SNB_GMCH_GMS_STOLEN_64M: | ||
534 | stolen_size = MB(64); | ||
535 | break; | ||
536 | case SNB_GMCH_GMS_STOLEN_96M: | ||
537 | stolen_size = MB(96); | ||
538 | break; | ||
539 | case SNB_GMCH_GMS_STOLEN_128M: | ||
540 | stolen_size = MB(128); | ||
541 | break; | ||
542 | case SNB_GMCH_GMS_STOLEN_160M: | ||
543 | stolen_size = MB(160); | ||
544 | break; | ||
545 | case SNB_GMCH_GMS_STOLEN_192M: | ||
546 | stolen_size = MB(192); | ||
547 | break; | ||
548 | case SNB_GMCH_GMS_STOLEN_224M: | ||
549 | stolen_size = MB(224); | ||
550 | break; | ||
551 | case SNB_GMCH_GMS_STOLEN_256M: | ||
552 | stolen_size = MB(256); | ||
553 | break; | ||
554 | case SNB_GMCH_GMS_STOLEN_288M: | ||
555 | stolen_size = MB(288); | ||
556 | break; | ||
557 | case SNB_GMCH_GMS_STOLEN_320M: | ||
558 | stolen_size = MB(320); | ||
559 | break; | ||
560 | case SNB_GMCH_GMS_STOLEN_352M: | ||
561 | stolen_size = MB(352); | ||
562 | break; | ||
563 | case SNB_GMCH_GMS_STOLEN_384M: | ||
564 | stolen_size = MB(384); | ||
565 | break; | ||
566 | case SNB_GMCH_GMS_STOLEN_416M: | ||
567 | stolen_size = MB(416); | ||
568 | break; | ||
569 | case SNB_GMCH_GMS_STOLEN_448M: | ||
570 | stolen_size = MB(448); | ||
571 | break; | ||
572 | case SNB_GMCH_GMS_STOLEN_480M: | ||
573 | stolen_size = MB(480); | ||
574 | break; | ||
575 | case SNB_GMCH_GMS_STOLEN_512M: | ||
576 | stolen_size = MB(512); | ||
577 | break; | ||
578 | } | ||
579 | } else { | ||
580 | switch (gmch_ctrl & I855_GMCH_GMS_MASK) { | ||
581 | case I855_GMCH_GMS_STOLEN_1M: | ||
582 | stolen_size = MB(1); | ||
583 | break; | ||
584 | case I855_GMCH_GMS_STOLEN_4M: | ||
585 | stolen_size = MB(4); | ||
586 | break; | ||
587 | case I855_GMCH_GMS_STOLEN_8M: | ||
588 | stolen_size = MB(8); | ||
589 | break; | ||
590 | case I855_GMCH_GMS_STOLEN_16M: | ||
591 | stolen_size = MB(16); | ||
592 | break; | ||
593 | case I855_GMCH_GMS_STOLEN_32M: | ||
594 | stolen_size = MB(32); | ||
595 | break; | ||
596 | case I915_GMCH_GMS_STOLEN_48M: | ||
597 | stolen_size = MB(48); | ||
598 | break; | ||
599 | case I915_GMCH_GMS_STOLEN_64M: | ||
600 | stolen_size = MB(64); | ||
601 | break; | ||
602 | case G33_GMCH_GMS_STOLEN_128M: | ||
603 | stolen_size = MB(128); | ||
604 | break; | ||
605 | case G33_GMCH_GMS_STOLEN_256M: | ||
606 | stolen_size = MB(256); | ||
607 | break; | ||
608 | case INTEL_GMCH_GMS_STOLEN_96M: | ||
609 | stolen_size = MB(96); | ||
610 | break; | ||
611 | case INTEL_GMCH_GMS_STOLEN_160M: | ||
612 | stolen_size = MB(160); | ||
613 | break; | ||
614 | case INTEL_GMCH_GMS_STOLEN_224M: | ||
615 | stolen_size = MB(224); | ||
616 | break; | ||
617 | case INTEL_GMCH_GMS_STOLEN_352M: | ||
618 | stolen_size = MB(352); | ||
619 | break; | ||
620 | default: | ||
621 | stolen_size = 0; | ||
622 | break; | ||
623 | } | ||
624 | } | ||
625 | |||
626 | if (!local && stolen_size > intel_max_stolen) { | ||
627 | dev_info(&intel_private.bridge_dev->dev, | ||
628 | "detected %dK stolen memory, trimming to %dK\n", | ||
629 | stolen_size / KB(1), intel_max_stolen / KB(1)); | ||
630 | stolen_size = intel_max_stolen; | ||
631 | } else if (stolen_size > 0) { | ||
632 | dev_info(&intel_private.bridge_dev->dev, "detected %dK %s memory\n", | ||
633 | stolen_size / KB(1), local ? "local" : "stolen"); | ||
634 | } else { | ||
635 | dev_info(&intel_private.bridge_dev->dev, | ||
636 | "no pre-allocated video memory detected\n"); | ||
637 | stolen_size = 0; | ||
638 | } | ||
639 | |||
640 | stolen_entries = stolen_size/KB(4) - overhead_entries; | ||
641 | |||
642 | return stolen_entries; | ||
643 | } | ||
644 | |||
645 | static unsigned int intel_gtt_total_entries(void) | ||
646 | { | ||
647 | int size; | ||
648 | |||
649 | if (IS_G33 || INTEL_GTT_GEN == 4 || INTEL_GTT_GEN == 5) { | ||
650 | u32 pgetbl_ctl; | ||
651 | pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL); | ||
652 | |||
653 | switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) { | ||
654 | case I965_PGETBL_SIZE_128KB: | ||
655 | size = KB(128); | ||
656 | break; | ||
657 | case I965_PGETBL_SIZE_256KB: | ||
658 | size = KB(256); | ||
659 | break; | ||
660 | case I965_PGETBL_SIZE_512KB: | ||
661 | size = KB(512); | ||
662 | break; | ||
663 | case I965_PGETBL_SIZE_1MB: | ||
664 | size = KB(1024); | ||
665 | break; | ||
666 | case I965_PGETBL_SIZE_2MB: | ||
667 | size = KB(2048); | ||
668 | break; | ||
669 | case I965_PGETBL_SIZE_1_5MB: | ||
670 | size = KB(1024 + 512); | ||
671 | break; | ||
672 | default: | ||
673 | dev_info(&intel_private.pcidev->dev, | ||
674 | "unknown page table size, assuming 512KB\n"); | ||
675 | size = KB(512); | ||
676 | } | ||
677 | |||
678 | return size/4; | ||
679 | } else if (INTEL_GTT_GEN == 6) { | ||
680 | u16 snb_gmch_ctl; | ||
681 | |||
682 | pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); | ||
683 | switch (snb_gmch_ctl & SNB_GTT_SIZE_MASK) { | ||
684 | default: | ||
685 | case SNB_GTT_SIZE_0M: | ||
686 | printk(KERN_ERR "Bad GTT size mask: 0x%04x.\n", snb_gmch_ctl); | ||
687 | size = MB(0); | ||
688 | break; | ||
689 | case SNB_GTT_SIZE_1M: | ||
690 | size = MB(1); | ||
691 | break; | ||
692 | case SNB_GTT_SIZE_2M: | ||
693 | size = MB(2); | ||
694 | break; | ||
695 | } | ||
696 | return size/4; | ||
697 | } else { | ||
698 | /* On previous hardware, the GTT size was just what was | ||
699 | * required to map the aperture. | ||
700 | */ | ||
701 | return intel_private.base.gtt_mappable_entries; | ||
702 | } | ||
703 | } | ||
704 | |||
705 | static unsigned int intel_gtt_mappable_entries(void) | ||
706 | { | ||
707 | unsigned int aperture_size; | ||
708 | |||
709 | if (INTEL_GTT_GEN == 2) { | ||
710 | u16 gmch_ctrl; | ||
711 | |||
712 | pci_read_config_word(intel_private.bridge_dev, | ||
713 | I830_GMCH_CTRL, &gmch_ctrl); | ||
714 | |||
715 | if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_64M) | ||
716 | aperture_size = MB(64); | ||
717 | else | ||
718 | aperture_size = MB(128); | ||
719 | } else { | ||
720 | /* 9xx supports large sizes, just look at the length */ | ||
721 | aperture_size = pci_resource_len(intel_private.pcidev, 2); | ||
722 | } | ||
723 | |||
724 | return aperture_size >> PAGE_SHIFT; | ||
725 | } | ||
726 | |||
727 | static void intel_gtt_teardown_scratch_page(void) | ||
728 | { | ||
729 | set_pages_wb(intel_private.scratch_page, 1); | ||
730 | pci_unmap_page(intel_private.pcidev, intel_private.scratch_page_dma, | ||
731 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | ||
732 | put_page(intel_private.scratch_page); | ||
733 | __free_page(intel_private.scratch_page); | ||
734 | } | ||
735 | |||
736 | static void intel_gtt_cleanup(void) | ||
737 | { | ||
738 | intel_private.driver->cleanup(); | ||
739 | |||
740 | iounmap(intel_private.gtt); | ||
741 | iounmap(intel_private.registers); | ||
742 | |||
743 | intel_gtt_teardown_scratch_page(); | ||
744 | } | ||
745 | |||
746 | static int intel_gtt_init(void) | ||
747 | { | ||
748 | u32 gtt_map_size; | ||
749 | int ret; | ||
750 | |||
751 | ret = intel_private.driver->setup(); | ||
752 | if (ret != 0) | ||
753 | return ret; | ||
754 | |||
755 | intel_private.base.gtt_mappable_entries = intel_gtt_mappable_entries(); | ||
756 | intel_private.base.gtt_total_entries = intel_gtt_total_entries(); | ||
757 | |||
758 | dev_info(&intel_private.bridge_dev->dev, | ||
759 | "detected gtt size: %dK total, %dK mappable\n", | ||
760 | intel_private.base.gtt_total_entries * 4, | ||
761 | intel_private.base.gtt_mappable_entries * 4); | ||
762 | |||
763 | gtt_map_size = intel_private.base.gtt_total_entries * 4; | ||
764 | |||
765 | intel_private.gtt = ioremap(intel_private.gtt_bus_addr, | ||
766 | gtt_map_size); | ||
767 | if (!intel_private.gtt) { | ||
768 | intel_private.driver->cleanup(); | ||
769 | iounmap(intel_private.registers); | ||
770 | return -ENOMEM; | ||
771 | } | ||
772 | |||
773 | global_cache_flush(); /* FIXME: ? */ | ||
774 | |||
775 | /* we have to call this as early as possible after the MMIO base address is known */ | ||
776 | intel_private.base.gtt_stolen_entries = intel_gtt_stolen_entries(); | ||
777 | if (intel_private.base.gtt_stolen_entries == 0) { | ||
778 | intel_private.driver->cleanup(); | ||
779 | iounmap(intel_private.registers); | ||
780 | iounmap(intel_private.gtt); | ||
781 | return -ENOMEM; | ||
782 | } | ||
783 | |||
784 | ret = intel_gtt_setup_scratch_page(); | ||
785 | if (ret != 0) { | ||
786 | intel_gtt_cleanup(); | ||
787 | return ret; | ||
788 | } | ||
789 | |||
790 | return 0; | ||
791 | } | ||
792 | |||
793 | static int intel_fake_agp_fetch_size(void) | ||
794 | { | ||
795 | int num_sizes = ARRAY_SIZE(intel_fake_agp_sizes); | ||
796 | unsigned int aper_size; | ||
797 | int i; | ||
798 | |||
799 | aper_size = (intel_private.base.gtt_mappable_entries << PAGE_SHIFT) | ||
800 | / MB(1); | ||
801 | |||
802 | for (i = 0; i < num_sizes; i++) { | ||
803 | if (aper_size == intel_fake_agp_sizes[i].size) { | ||
804 | agp_bridge->current_size = | ||
805 | (void *) (intel_fake_agp_sizes + i); | ||
806 | return aper_size; | ||
807 | } | ||
808 | } | ||
809 | |||
810 | return 0; | ||
811 | } | ||
812 | |||
813 | static void i830_cleanup(void) | ||
814 | { | ||
815 | kunmap(intel_private.i8xx_page); | ||
816 | intel_private.i8xx_flush_page = NULL; | ||
817 | |||
818 | __free_page(intel_private.i8xx_page); | ||
819 | intel_private.i8xx_page = NULL; | ||
820 | } | ||
821 | |||
822 | static void intel_i830_setup_flush(void) | ||
823 | { | ||
824 | /* return if we've already set the flush mechanism up */ | ||
825 | if (intel_private.i8xx_page) | ||
826 | return; | ||
827 | |||
828 | intel_private.i8xx_page = alloc_page(GFP_KERNEL); | ||
829 | if (!intel_private.i8xx_page) | ||
830 | return; | ||
831 | |||
832 | intel_private.i8xx_flush_page = kmap(intel_private.i8xx_page); | ||
833 | if (!intel_private.i8xx_flush_page) | ||
834 | i830_cleanup(); | ||
835 | } | ||
836 | |||
837 | /* The chipset_flush interface needs to get data that has already been | ||
838 | * flushed out of the CPU all the way out to main memory, because the GPU | ||
839 | * doesn't snoop those buffers. | ||
840 | * | ||
841 | * The 8xx series doesn't have the same lovely interface for flushing the | ||
842 | * chipset write buffers that the later chips do. According to the 865 | ||
843 | * specs, it's 64 octwords, or 1KB. So, to get those previous things in | ||
844 | * that buffer out, we just fill 1KB and clflush it out, on the assumption | ||
845 | * that it'll push whatever was in there out. It appears to work. | ||
846 | */ | ||
847 | static void i830_chipset_flush(void) | ||
848 | { | ||
849 | unsigned int *pg = intel_private.i8xx_flush_page; | ||
850 | |||
851 | memset(pg, 0, 1024); | ||
852 | |||
853 | if (cpu_has_clflush) | ||
854 | clflush_cache_range(pg, 1024); | ||
855 | else if (wbinvd_on_all_cpus() != 0) | ||
856 | printk(KERN_ERR "Timed out waiting for cache flush.\n"); | ||
857 | } | ||
858 | |||
859 | static void i830_write_entry(dma_addr_t addr, unsigned int entry, | ||
860 | unsigned int flags) | ||
861 | { | ||
862 | u32 pte_flags = I810_PTE_VALID; | ||
863 | |||
864 | switch (flags) { | ||
865 | case AGP_DCACHE_MEMORY: | ||
866 | pte_flags |= I810_PTE_LOCAL; | ||
867 | break; | ||
868 | case AGP_USER_CACHED_MEMORY: | ||
869 | pte_flags |= I830_PTE_SYSTEM_CACHED; | ||
870 | break; | ||
871 | } | ||
872 | |||
873 | writel(addr | pte_flags, intel_private.gtt + entry); | ||
874 | } | ||
875 | |||
876 | static void intel_enable_gtt(void) | ||
877 | { | ||
878 | u32 gma_addr; | ||
879 | u16 gmch_ctrl; | ||
880 | |||
881 | if (INTEL_GTT_GEN == 2) | ||
882 | pci_read_config_dword(intel_private.pcidev, I810_GMADDR, | ||
883 | &gma_addr); | ||
884 | else | ||
885 | pci_read_config_dword(intel_private.pcidev, I915_GMADDR, | ||
886 | &gma_addr); | ||
887 | |||
888 | intel_private.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); | ||
889 | |||
890 | pci_read_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, &gmch_ctrl); | ||
891 | gmch_ctrl |= I830_GMCH_ENABLED; | ||
892 | pci_write_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, gmch_ctrl); | ||
893 | |||
894 | writel(intel_private.pte_bus_addr|I810_PGETBL_ENABLED, | ||
895 | intel_private.registers+I810_PGETBL_CTL); | ||
896 | readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ | ||
897 | } | ||
898 | |||
899 | static int i830_setup(void) | ||
900 | { | ||
901 | u32 reg_addr; | ||
902 | |||
903 | pci_read_config_dword(intel_private.pcidev, I810_MMADDR, ®_addr); | ||
904 | reg_addr &= 0xfff80000; | ||
905 | |||
906 | intel_private.registers = ioremap(reg_addr, KB(64)); | ||
907 | if (!intel_private.registers) | ||
908 | return -ENOMEM; | ||
909 | |||
910 | intel_private.gtt_bus_addr = reg_addr + I810_PTE_BASE; | ||
911 | intel_private.pte_bus_addr = | ||
912 | readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; | ||
913 | |||
914 | intel_i830_setup_flush(); | ||
915 | |||
916 | return 0; | ||
917 | } | ||
918 | |||
919 | static int intel_fake_agp_create_gatt_table(struct agp_bridge_data *bridge) | ||
920 | { | ||
921 | agp_bridge->gatt_table_real = NULL; | ||
922 | agp_bridge->gatt_table = NULL; | ||
923 | agp_bridge->gatt_bus_addr = 0; | ||
924 | |||
925 | return 0; | ||
926 | } | ||
927 | |||
928 | static int intel_fake_agp_free_gatt_table(struct agp_bridge_data *bridge) | ||
929 | { | ||
930 | return 0; | ||
931 | } | ||
932 | |||
933 | static int intel_fake_agp_configure(void) | ||
934 | { | ||
935 | int i; | ||
936 | |||
937 | intel_enable_gtt(); | ||
938 | |||
939 | agp_bridge->gart_bus_addr = intel_private.gma_bus_addr; | ||
940 | |||
941 | for (i = intel_private.base.gtt_stolen_entries; | ||
942 | i < intel_private.base.gtt_total_entries; i++) { | ||
943 | intel_private.driver->write_entry(intel_private.scratch_page_dma, | ||
944 | i, 0); | ||
945 | } | ||
946 | readl(intel_private.gtt+i-1); /* PCI Posting. */ | ||
947 | |||
948 | global_cache_flush(); | ||
949 | |||
950 | return 0; | ||
951 | } | ||
952 | |||
953 | static bool i830_check_flags(unsigned int flags) | ||
954 | { | ||
955 | switch (flags) { | ||
956 | case 0: | ||
957 | case AGP_PHYS_MEMORY: | ||
958 | case AGP_USER_CACHED_MEMORY: | ||
959 | case AGP_USER_MEMORY: | ||
960 | return true; | ||
961 | } | ||
962 | |||
963 | return false; | ||
964 | } | ||
965 | |||
966 | static void intel_gtt_insert_sg_entries(struct scatterlist *sg_list, | ||
967 | unsigned int sg_len, | ||
968 | unsigned int pg_start, | ||
969 | unsigned int flags) | ||
970 | { | ||
971 | struct scatterlist *sg; | ||
972 | unsigned int len, m; | ||
973 | int i, j; | ||
974 | |||
975 | j = pg_start; | ||
976 | |||
977 | /* sg may merge pages, but we have to separate | ||
978 | * per-page addr for GTT */ | ||
979 | for_each_sg(sg_list, sg, sg_len, i) { | ||
980 | len = sg_dma_len(sg) >> PAGE_SHIFT; | ||
981 | for (m = 0; m < len; m++) { | ||
982 | dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT); | ||
983 | intel_private.driver->write_entry(addr, | ||
984 | j, flags); | ||
985 | j++; | ||
986 | } | ||
987 | } | ||
988 | readl(intel_private.gtt+j-1); | ||
989 | } | ||
990 | |||
991 | static int intel_fake_agp_insert_entries(struct agp_memory *mem, | ||
992 | off_t pg_start, int type) | ||
993 | { | ||
994 | int i, j; | ||
995 | int ret = -EINVAL; | ||
996 | |||
997 | if (mem->page_count == 0) | ||
998 | goto out; | ||
999 | |||
1000 | if (pg_start < intel_private.base.gtt_stolen_entries) { | ||
1001 | dev_printk(KERN_DEBUG, &intel_private.pcidev->dev, | ||
1002 | "pg_start == 0x%.8lx, gtt_stolen_entries == 0x%.8x\n", | ||
1003 | pg_start, intel_private.base.gtt_stolen_entries); | ||
1004 | |||
1005 | dev_info(&intel_private.pcidev->dev, | ||
1006 | "trying to insert into local/stolen memory\n"); | ||
1007 | goto out_err; | ||
1008 | } | ||
1009 | |||
1010 | if ((pg_start + mem->page_count) > intel_private.base.gtt_total_entries) | ||
1011 | goto out_err; | ||
1012 | |||
1013 | if (type != mem->type) | ||
1014 | goto out_err; | ||
1015 | |||
1016 | if (!intel_private.driver->check_flags(type)) | ||
1017 | goto out_err; | ||
1018 | |||
1019 | if (!mem->is_flushed) | ||
1020 | global_cache_flush(); | ||
1021 | |||
1022 | if (USE_PCI_DMA_API && INTEL_GTT_GEN > 2) { | ||
1023 | ret = intel_agp_map_memory(mem); | ||
1024 | if (ret != 0) | ||
1025 | return ret; | ||
1026 | |||
1027 | intel_gtt_insert_sg_entries(mem->sg_list, mem->num_sg, | ||
1028 | pg_start, type); | ||
1029 | } else { | ||
1030 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | ||
1031 | dma_addr_t addr = page_to_phys(mem->pages[i]); | ||
1032 | intel_private.driver->write_entry(addr, | ||
1033 | j, type); | ||
1034 | } | ||
1035 | readl(intel_private.gtt+j-1); | ||
1036 | } | ||
1037 | |||
1038 | out: | ||
1039 | ret = 0; | ||
1040 | out_err: | ||
1041 | mem->is_flushed = true; | ||
1042 | return ret; | ||
1043 | } | ||
1044 | |||
1045 | static int intel_fake_agp_remove_entries(struct agp_memory *mem, | ||
1046 | off_t pg_start, int type) | ||
1047 | { | ||
1048 | int i; | ||
1049 | |||
1050 | if (mem->page_count == 0) | ||
1051 | return 0; | ||
1052 | |||
1053 | if (pg_start < intel_private.base.gtt_stolen_entries) { | ||
1054 | dev_info(&intel_private.pcidev->dev, | ||
1055 | "trying to disable local/stolen memory\n"); | ||
1056 | return -EINVAL; | ||
1057 | } | ||
1058 | |||
1059 | if (USE_PCI_DMA_API && INTEL_GTT_GEN > 2) | ||
1060 | intel_agp_unmap_memory(mem); | ||
1061 | |||
1062 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | ||
1063 | intel_private.driver->write_entry(intel_private.scratch_page_dma, | ||
1064 | i, 0); | ||
1065 | } | ||
1066 | readl(intel_private.gtt+i-1); | ||
1067 | |||
1068 | return 0; | ||
1069 | } | ||
1070 | |||
1071 | static void intel_fake_agp_chipset_flush(struct agp_bridge_data *bridge) | ||
1072 | { | ||
1073 | intel_private.driver->chipset_flush(); | ||
1074 | } | ||
1075 | |||
1076 | static struct agp_memory *intel_fake_agp_alloc_by_type(size_t pg_count, | ||
1077 | int type) | ||
1078 | { | ||
1079 | if (type == AGP_PHYS_MEMORY) | ||
1080 | return alloc_agpphysmem_i8xx(pg_count, type); | ||
1081 | /* always return NULL for other allocation types for now */ | ||
1082 | return NULL; | ||
1083 | } | ||
1084 | |||
1085 | static int intel_alloc_chipset_flush_resource(void) | ||
1086 | { | ||
1087 | int ret; | ||
1088 | ret = pci_bus_alloc_resource(intel_private.bridge_dev->bus, &intel_private.ifp_resource, PAGE_SIZE, | ||
1089 | PAGE_SIZE, PCIBIOS_MIN_MEM, 0, | ||
1090 | pcibios_align_resource, intel_private.bridge_dev); | ||
1091 | |||
1092 | return ret; | ||
1093 | } | ||
1094 | |||
1095 | static void intel_i915_setup_chipset_flush(void) | ||
1096 | { | ||
1097 | int ret; | ||
1098 | u32 temp; | ||
1099 | |||
1100 | pci_read_config_dword(intel_private.bridge_dev, I915_IFPADDR, &temp); | ||
1101 | if (!(temp & 0x1)) { | ||
1102 | intel_alloc_chipset_flush_resource(); | ||
1103 | intel_private.resource_valid = 1; | ||
1104 | pci_write_config_dword(intel_private.bridge_dev, I915_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); | ||
1105 | } else { | ||
1106 | temp &= ~1; | ||
1107 | |||
1108 | intel_private.resource_valid = 1; | ||
1109 | intel_private.ifp_resource.start = temp; | ||
1110 | intel_private.ifp_resource.end = temp + PAGE_SIZE; | ||
1111 | ret = request_resource(&iomem_resource, &intel_private.ifp_resource); | ||
1112 | /* some BIOSes reserve this area in a pnp some don't */ | ||
1113 | if (ret) | ||
1114 | intel_private.resource_valid = 0; | ||
1115 | } | ||
1116 | } | ||
1117 | |||
1118 | static void intel_i965_g33_setup_chipset_flush(void) | ||
1119 | { | ||
1120 | u32 temp_hi, temp_lo; | ||
1121 | int ret; | ||
1122 | |||
1123 | pci_read_config_dword(intel_private.bridge_dev, I965_IFPADDR + 4, &temp_hi); | ||
1124 | pci_read_config_dword(intel_private.bridge_dev, I965_IFPADDR, &temp_lo); | ||
1125 | |||
1126 | if (!(temp_lo & 0x1)) { | ||
1127 | |||
1128 | intel_alloc_chipset_flush_resource(); | ||
1129 | |||
1130 | intel_private.resource_valid = 1; | ||
1131 | pci_write_config_dword(intel_private.bridge_dev, I965_IFPADDR + 4, | ||
1132 | upper_32_bits(intel_private.ifp_resource.start)); | ||
1133 | pci_write_config_dword(intel_private.bridge_dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); | ||
1134 | } else { | ||
1135 | u64 l64; | ||
1136 | |||
1137 | temp_lo &= ~0x1; | ||
1138 | l64 = ((u64)temp_hi << 32) | temp_lo; | ||
1139 | |||
1140 | intel_private.resource_valid = 1; | ||
1141 | intel_private.ifp_resource.start = l64; | ||
1142 | intel_private.ifp_resource.end = l64 + PAGE_SIZE; | ||
1143 | ret = request_resource(&iomem_resource, &intel_private.ifp_resource); | ||
1144 | /* some BIOSes reserve this area in a pnp some don't */ | ||
1145 | if (ret) | ||
1146 | intel_private.resource_valid = 0; | ||
1147 | } | ||
1148 | } | ||
1149 | |||
1150 | static void intel_i9xx_setup_flush(void) | ||
1151 | { | ||
1152 | /* return if already configured */ | ||
1153 | if (intel_private.ifp_resource.start) | ||
1154 | return; | ||
1155 | |||
1156 | if (INTEL_GTT_GEN == 6) | ||
1157 | return; | ||
1158 | |||
1159 | /* setup a resource for this object */ | ||
1160 | intel_private.ifp_resource.name = "Intel Flush Page"; | ||
1161 | intel_private.ifp_resource.flags = IORESOURCE_MEM; | ||
1162 | |||
1163 | /* Setup chipset flush for 915 */ | ||
1164 | if (IS_G33 || INTEL_GTT_GEN >= 4) { | ||
1165 | intel_i965_g33_setup_chipset_flush(); | ||
1166 | } else { | ||
1167 | intel_i915_setup_chipset_flush(); | ||
1168 | } | ||
1169 | |||
1170 | if (intel_private.ifp_resource.start) | ||
1171 | intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE); | ||
1172 | if (!intel_private.i9xx_flush_page) | ||
1173 | dev_err(&intel_private.pcidev->dev, | ||
1174 | "can't ioremap flush page - no chipset flushing\n"); | ||
1175 | } | ||
1176 | |||
1177 | static void i9xx_cleanup(void) | ||
1178 | { | ||
1179 | if (intel_private.i9xx_flush_page) | ||
1180 | iounmap(intel_private.i9xx_flush_page); | ||
1181 | if (intel_private.resource_valid) | ||
1182 | release_resource(&intel_private.ifp_resource); | ||
1183 | intel_private.ifp_resource.start = 0; | ||
1184 | intel_private.resource_valid = 0; | ||
1185 | } | ||
1186 | |||
1187 | static void i9xx_chipset_flush(void) | ||
1188 | { | ||
1189 | if (intel_private.i9xx_flush_page) | ||
1190 | writel(1, intel_private.i9xx_flush_page); | ||
1191 | } | ||
1192 | |||
1193 | static void i965_write_entry(dma_addr_t addr, unsigned int entry, | ||
1194 | unsigned int flags) | ||
1195 | { | ||
1196 | /* Shift high bits down */ | ||
1197 | addr |= (addr >> 28) & 0xf0; | ||
1198 | writel(addr | I810_PTE_VALID, intel_private.gtt + entry); | ||
1199 | } | ||
1200 | |||
1201 | static bool gen6_check_flags(unsigned int flags) | ||
1202 | { | ||
1203 | return true; | ||
1204 | } | ||
1205 | |||
1206 | static void gen6_write_entry(dma_addr_t addr, unsigned int entry, | ||
1207 | unsigned int flags) | ||
1208 | { | ||
1209 | unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT; | ||
1210 | unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; | ||
1211 | u32 pte_flags; | ||
1212 | |||
1213 | if (type_mask == AGP_USER_UNCACHED_MEMORY) | ||
1214 | pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID; | ||
1215 | else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) { | ||
1216 | pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; | ||
1217 | if (gfdt) | ||
1218 | pte_flags |= GEN6_PTE_GFDT; | ||
1219 | } else { /* set 'normal'/'cached' to LLC by default */ | ||
1220 | pte_flags = GEN6_PTE_LLC_MLC | I810_PTE_VALID; | ||
1221 | if (gfdt) | ||
1222 | pte_flags |= GEN6_PTE_GFDT; | ||
1223 | } | ||
1224 | |||
1225 | /* gen6 has bit11-4 for physical addr bit39-32 */ | ||
1226 | addr |= (addr >> 28) & 0xff0; | ||
1227 | writel(addr | pte_flags, intel_private.gtt + entry); | ||
1228 | } | ||
1229 | |||
1230 | static void gen6_cleanup(void) | ||
1231 | { | ||
1232 | } | ||
1233 | |||
1234 | static int i9xx_setup(void) | ||
1235 | { | ||
1236 | u32 reg_addr; | ||
1237 | |||
1238 | pci_read_config_dword(intel_private.pcidev, I915_MMADDR, ®_addr); | ||
1239 | |||
1240 | reg_addr &= 0xfff80000; | ||
1241 | |||
1242 | intel_private.registers = ioremap(reg_addr, 128 * 4096); | ||
1243 | if (!intel_private.registers) | ||
1244 | return -ENOMEM; | ||
1245 | |||
1246 | if (INTEL_GTT_GEN == 3) { | ||
1247 | u32 gtt_addr; | ||
1248 | |||
1249 | pci_read_config_dword(intel_private.pcidev, | ||
1250 | I915_PTEADDR, >t_addr); | ||
1251 | intel_private.gtt_bus_addr = gtt_addr; | ||
1252 | } else { | ||
1253 | u32 gtt_offset; | ||
1254 | |||
1255 | switch (INTEL_GTT_GEN) { | ||
1256 | case 5: | ||
1257 | case 6: | ||
1258 | gtt_offset = MB(2); | ||
1259 | break; | ||
1260 | case 4: | ||
1261 | default: | ||
1262 | gtt_offset = KB(512); | ||
1263 | break; | ||
1264 | } | ||
1265 | intel_private.gtt_bus_addr = reg_addr + gtt_offset; | ||
1266 | } | ||
1267 | |||
1268 | intel_private.pte_bus_addr = | ||
1269 | readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; | ||
1270 | |||
1271 | intel_i9xx_setup_flush(); | ||
1272 | |||
1273 | return 0; | ||
1274 | } | ||
1275 | |||
1276 | static const struct agp_bridge_driver intel_810_driver = { | ||
1277 | .owner = THIS_MODULE, | ||
1278 | .aperture_sizes = intel_i810_sizes, | ||
1279 | .size_type = FIXED_APER_SIZE, | ||
1280 | .num_aperture_sizes = 2, | ||
1281 | .needs_scratch_page = true, | ||
1282 | .configure = intel_i810_configure, | ||
1283 | .fetch_size = intel_i810_fetch_size, | ||
1284 | .cleanup = intel_i810_cleanup, | ||
1285 | .mask_memory = intel_i810_mask_memory, | ||
1286 | .masks = intel_i810_masks, | ||
1287 | .agp_enable = intel_fake_agp_enable, | ||
1288 | .cache_flush = global_cache_flush, | ||
1289 | .create_gatt_table = agp_generic_create_gatt_table, | ||
1290 | .free_gatt_table = agp_generic_free_gatt_table, | ||
1291 | .insert_memory = intel_i810_insert_entries, | ||
1292 | .remove_memory = intel_i810_remove_entries, | ||
1293 | .alloc_by_type = intel_i810_alloc_by_type, | ||
1294 | .free_by_type = intel_i810_free_by_type, | ||
1295 | .agp_alloc_page = agp_generic_alloc_page, | ||
1296 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
1297 | .agp_destroy_page = agp_generic_destroy_page, | ||
1298 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
1299 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | ||
1300 | }; | ||
1301 | |||
1302 | static const struct agp_bridge_driver intel_fake_agp_driver = { | ||
1303 | .owner = THIS_MODULE, | ||
1304 | .size_type = FIXED_APER_SIZE, | ||
1305 | .aperture_sizes = intel_fake_agp_sizes, | ||
1306 | .num_aperture_sizes = ARRAY_SIZE(intel_fake_agp_sizes), | ||
1307 | .configure = intel_fake_agp_configure, | ||
1308 | .fetch_size = intel_fake_agp_fetch_size, | ||
1309 | .cleanup = intel_gtt_cleanup, | ||
1310 | .agp_enable = intel_fake_agp_enable, | ||
1311 | .cache_flush = global_cache_flush, | ||
1312 | .create_gatt_table = intel_fake_agp_create_gatt_table, | ||
1313 | .free_gatt_table = intel_fake_agp_free_gatt_table, | ||
1314 | .insert_memory = intel_fake_agp_insert_entries, | ||
1315 | .remove_memory = intel_fake_agp_remove_entries, | ||
1316 | .alloc_by_type = intel_fake_agp_alloc_by_type, | ||
1317 | .free_by_type = intel_i810_free_by_type, | ||
1318 | .agp_alloc_page = agp_generic_alloc_page, | ||
1319 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
1320 | .agp_destroy_page = agp_generic_destroy_page, | ||
1321 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
1322 | .chipset_flush = intel_fake_agp_chipset_flush, | ||
1323 | }; | ||
1324 | |||
1325 | static const struct intel_gtt_driver i81x_gtt_driver = { | ||
1326 | .gen = 1, | ||
1327 | .dma_mask_size = 32, | ||
1328 | }; | ||
1329 | static const struct intel_gtt_driver i8xx_gtt_driver = { | ||
1330 | .gen = 2, | ||
1331 | .setup = i830_setup, | ||
1332 | .cleanup = i830_cleanup, | ||
1333 | .write_entry = i830_write_entry, | ||
1334 | .dma_mask_size = 32, | ||
1335 | .check_flags = i830_check_flags, | ||
1336 | .chipset_flush = i830_chipset_flush, | ||
1337 | }; | ||
1338 | static const struct intel_gtt_driver i915_gtt_driver = { | ||
1339 | .gen = 3, | ||
1340 | .setup = i9xx_setup, | ||
1341 | .cleanup = i9xx_cleanup, | ||
1342 | /* i945 is the last gpu to need phys mem (for overlay and cursors). */ | ||
1343 | .write_entry = i830_write_entry, | ||
1344 | .dma_mask_size = 32, | ||
1345 | .check_flags = i830_check_flags, | ||
1346 | .chipset_flush = i9xx_chipset_flush, | ||
1347 | }; | ||
1348 | static const struct intel_gtt_driver g33_gtt_driver = { | ||
1349 | .gen = 3, | ||
1350 | .is_g33 = 1, | ||
1351 | .setup = i9xx_setup, | ||
1352 | .cleanup = i9xx_cleanup, | ||
1353 | .write_entry = i965_write_entry, | ||
1354 | .dma_mask_size = 36, | ||
1355 | .check_flags = i830_check_flags, | ||
1356 | .chipset_flush = i9xx_chipset_flush, | ||
1357 | }; | ||
1358 | static const struct intel_gtt_driver pineview_gtt_driver = { | ||
1359 | .gen = 3, | ||
1360 | .is_pineview = 1, .is_g33 = 1, | ||
1361 | .setup = i9xx_setup, | ||
1362 | .cleanup = i9xx_cleanup, | ||
1363 | .write_entry = i965_write_entry, | ||
1364 | .dma_mask_size = 36, | ||
1365 | .check_flags = i830_check_flags, | ||
1366 | .chipset_flush = i9xx_chipset_flush, | ||
1367 | }; | ||
1368 | static const struct intel_gtt_driver i965_gtt_driver = { | ||
1369 | .gen = 4, | ||
1370 | .setup = i9xx_setup, | ||
1371 | .cleanup = i9xx_cleanup, | ||
1372 | .write_entry = i965_write_entry, | ||
1373 | .dma_mask_size = 36, | ||
1374 | .check_flags = i830_check_flags, | ||
1375 | .chipset_flush = i9xx_chipset_flush, | ||
1376 | }; | ||
1377 | static const struct intel_gtt_driver g4x_gtt_driver = { | ||
1378 | .gen = 5, | ||
1379 | .setup = i9xx_setup, | ||
1380 | .cleanup = i9xx_cleanup, | ||
1381 | .write_entry = i965_write_entry, | ||
1382 | .dma_mask_size = 36, | ||
1383 | .check_flags = i830_check_flags, | ||
1384 | .chipset_flush = i9xx_chipset_flush, | ||
1385 | }; | ||
1386 | static const struct intel_gtt_driver ironlake_gtt_driver = { | ||
1387 | .gen = 5, | ||
1388 | .is_ironlake = 1, | ||
1389 | .setup = i9xx_setup, | ||
1390 | .cleanup = i9xx_cleanup, | ||
1391 | .write_entry = i965_write_entry, | ||
1392 | .dma_mask_size = 36, | ||
1393 | .check_flags = i830_check_flags, | ||
1394 | .chipset_flush = i9xx_chipset_flush, | ||
1395 | }; | ||
1396 | static const struct intel_gtt_driver sandybridge_gtt_driver = { | ||
1397 | .gen = 6, | ||
1398 | .setup = i9xx_setup, | ||
1399 | .cleanup = gen6_cleanup, | ||
1400 | .write_entry = gen6_write_entry, | ||
1401 | .dma_mask_size = 40, | ||
1402 | .check_flags = gen6_check_flags, | ||
1403 | .chipset_flush = i9xx_chipset_flush, | ||
1404 | }; | ||
1405 | |||
1406 | /* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of | ||
1407 | * driver and gmch_driver must be non-null, and find_gmch will determine | ||
1408 | * which one should be used if a gmch_chip_id is present. | ||
1409 | */ | ||
1410 | static const struct intel_gtt_driver_description { | ||
1411 | unsigned int gmch_chip_id; | ||
1412 | char *name; | ||
1413 | const struct agp_bridge_driver *gmch_driver; | ||
1414 | const struct intel_gtt_driver *gtt_driver; | ||
1415 | } intel_gtt_chipsets[] = { | ||
1416 | { PCI_DEVICE_ID_INTEL_82810_IG1, "i810", &intel_810_driver, | ||
1417 | &i81x_gtt_driver}, | ||
1418 | { PCI_DEVICE_ID_INTEL_82810_IG3, "i810", &intel_810_driver, | ||
1419 | &i81x_gtt_driver}, | ||
1420 | { PCI_DEVICE_ID_INTEL_82810E_IG, "i810", &intel_810_driver, | ||
1421 | &i81x_gtt_driver}, | ||
1422 | { PCI_DEVICE_ID_INTEL_82815_CGC, "i815", &intel_810_driver, | ||
1423 | &i81x_gtt_driver}, | ||
1424 | { PCI_DEVICE_ID_INTEL_82830_CGC, "830M", | ||
1425 | &intel_fake_agp_driver, &i8xx_gtt_driver}, | ||
1426 | { PCI_DEVICE_ID_INTEL_82845G_IG, "830M", | ||
1427 | &intel_fake_agp_driver, &i8xx_gtt_driver}, | ||
1428 | { PCI_DEVICE_ID_INTEL_82854_IG, "854", | ||
1429 | &intel_fake_agp_driver, &i8xx_gtt_driver}, | ||
1430 | { PCI_DEVICE_ID_INTEL_82855GM_IG, "855GM", | ||
1431 | &intel_fake_agp_driver, &i8xx_gtt_driver}, | ||
1432 | { PCI_DEVICE_ID_INTEL_82865_IG, "865", | ||
1433 | &intel_fake_agp_driver, &i8xx_gtt_driver}, | ||
1434 | { PCI_DEVICE_ID_INTEL_E7221_IG, "E7221 (i915)", | ||
1435 | &intel_fake_agp_driver, &i915_gtt_driver }, | ||
1436 | { PCI_DEVICE_ID_INTEL_82915G_IG, "915G", | ||
1437 | &intel_fake_agp_driver, &i915_gtt_driver }, | ||
1438 | { PCI_DEVICE_ID_INTEL_82915GM_IG, "915GM", | ||
1439 | &intel_fake_agp_driver, &i915_gtt_driver }, | ||
1440 | { PCI_DEVICE_ID_INTEL_82945G_IG, "945G", | ||
1441 | &intel_fake_agp_driver, &i915_gtt_driver }, | ||
1442 | { PCI_DEVICE_ID_INTEL_82945GM_IG, "945GM", | ||
1443 | &intel_fake_agp_driver, &i915_gtt_driver }, | ||
1444 | { PCI_DEVICE_ID_INTEL_82945GME_IG, "945GME", | ||
1445 | &intel_fake_agp_driver, &i915_gtt_driver }, | ||
1446 | { PCI_DEVICE_ID_INTEL_82946GZ_IG, "946GZ", | ||
1447 | &intel_fake_agp_driver, &i965_gtt_driver }, | ||
1448 | { PCI_DEVICE_ID_INTEL_82G35_IG, "G35", | ||
1449 | &intel_fake_agp_driver, &i965_gtt_driver }, | ||
1450 | { PCI_DEVICE_ID_INTEL_82965Q_IG, "965Q", | ||
1451 | &intel_fake_agp_driver, &i965_gtt_driver }, | ||
1452 | { PCI_DEVICE_ID_INTEL_82965G_IG, "965G", | ||
1453 | &intel_fake_agp_driver, &i965_gtt_driver }, | ||
1454 | { PCI_DEVICE_ID_INTEL_82965GM_IG, "965GM", | ||
1455 | &intel_fake_agp_driver, &i965_gtt_driver }, | ||
1456 | { PCI_DEVICE_ID_INTEL_82965GME_IG, "965GME/GLE", | ||
1457 | &intel_fake_agp_driver, &i965_gtt_driver }, | ||
1458 | { PCI_DEVICE_ID_INTEL_G33_IG, "G33", | ||
1459 | &intel_fake_agp_driver, &g33_gtt_driver }, | ||
1460 | { PCI_DEVICE_ID_INTEL_Q35_IG, "Q35", | ||
1461 | &intel_fake_agp_driver, &g33_gtt_driver }, | ||
1462 | { PCI_DEVICE_ID_INTEL_Q33_IG, "Q33", | ||
1463 | &intel_fake_agp_driver, &g33_gtt_driver }, | ||
1464 | { PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, "GMA3150", | ||
1465 | &intel_fake_agp_driver, &pineview_gtt_driver }, | ||
1466 | { PCI_DEVICE_ID_INTEL_PINEVIEW_IG, "GMA3150", | ||
1467 | &intel_fake_agp_driver, &pineview_gtt_driver }, | ||
1468 | { PCI_DEVICE_ID_INTEL_GM45_IG, "GM45", | ||
1469 | &intel_fake_agp_driver, &g4x_gtt_driver }, | ||
1470 | { PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, "Eaglelake", | ||
1471 | &intel_fake_agp_driver, &g4x_gtt_driver }, | ||
1472 | { PCI_DEVICE_ID_INTEL_Q45_IG, "Q45/Q43", | ||
1473 | &intel_fake_agp_driver, &g4x_gtt_driver }, | ||
1474 | { PCI_DEVICE_ID_INTEL_G45_IG, "G45/G43", | ||
1475 | &intel_fake_agp_driver, &g4x_gtt_driver }, | ||
1476 | { PCI_DEVICE_ID_INTEL_B43_IG, "B43", | ||
1477 | &intel_fake_agp_driver, &g4x_gtt_driver }, | ||
1478 | { PCI_DEVICE_ID_INTEL_B43_1_IG, "B43", | ||
1479 | &intel_fake_agp_driver, &g4x_gtt_driver }, | ||
1480 | { PCI_DEVICE_ID_INTEL_G41_IG, "G41", | ||
1481 | &intel_fake_agp_driver, &g4x_gtt_driver }, | ||
1482 | { PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, | ||
1483 | "HD Graphics", &intel_fake_agp_driver, &ironlake_gtt_driver }, | ||
1484 | { PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, | ||
1485 | "HD Graphics", &intel_fake_agp_driver, &ironlake_gtt_driver }, | ||
1486 | { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG, | ||
1487 | "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, | ||
1488 | { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG, | ||
1489 | "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, | ||
1490 | { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG, | ||
1491 | "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, | ||
1492 | { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG, | ||
1493 | "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, | ||
1494 | { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG, | ||
1495 | "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, | ||
1496 | { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG, | ||
1497 | "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, | ||
1498 | { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG, | ||
1499 | "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, | ||
1500 | { 0, NULL, NULL } | ||
1501 | }; | ||
1502 | |||
1503 | static int find_gmch(u16 device) | ||
1504 | { | ||
1505 | struct pci_dev *gmch_device; | ||
1506 | |||
1507 | gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL); | ||
1508 | if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) { | ||
1509 | gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1510 | device, gmch_device); | ||
1511 | } | ||
1512 | |||
1513 | if (!gmch_device) | ||
1514 | return 0; | ||
1515 | |||
1516 | intel_private.pcidev = gmch_device; | ||
1517 | return 1; | ||
1518 | } | ||
1519 | |||
1520 | int intel_gmch_probe(struct pci_dev *pdev, | ||
1521 | struct agp_bridge_data *bridge) | ||
1522 | { | ||
1523 | int i, mask; | ||
1524 | bridge->driver = NULL; | ||
1525 | |||
1526 | for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) { | ||
1527 | if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) { | ||
1528 | bridge->driver = | ||
1529 | intel_gtt_chipsets[i].gmch_driver; | ||
1530 | intel_private.driver = | ||
1531 | intel_gtt_chipsets[i].gtt_driver; | ||
1532 | break; | ||
1533 | } | ||
1534 | } | ||
1535 | |||
1536 | if (!bridge->driver) | ||
1537 | return 0; | ||
1538 | |||
1539 | bridge->dev_private_data = &intel_private; | ||
1540 | bridge->dev = pdev; | ||
1541 | |||
1542 | intel_private.bridge_dev = pci_dev_get(pdev); | ||
1543 | |||
1544 | dev_info(&pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name); | ||
1545 | |||
1546 | mask = intel_private.driver->dma_mask_size; | ||
1547 | if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask))) | ||
1548 | dev_err(&intel_private.pcidev->dev, | ||
1549 | "set gfx device dma mask %d-bit failed!\n", mask); | ||
1550 | else | ||
1551 | pci_set_consistent_dma_mask(intel_private.pcidev, | ||
1552 | DMA_BIT_MASK(mask)); | ||
1553 | |||
1554 | if (bridge->driver == &intel_810_driver) | ||
1555 | return 1; | ||
1556 | |||
1557 | if (intel_gtt_init() != 0) | ||
1558 | return 0; | ||
1559 | |||
1560 | return 1; | ||
1561 | } | ||
1562 | EXPORT_SYMBOL(intel_gmch_probe); | ||
1563 | |||
1564 | struct intel_gtt *intel_gtt_get(void) | ||
1565 | { | ||
1566 | return &intel_private.base; | ||
1567 | } | ||
1568 | EXPORT_SYMBOL(intel_gtt_get); | ||
1569 | |||
1570 | void intel_gmch_remove(struct pci_dev *pdev) | ||
1571 | { | ||
1572 | if (intel_private.pcidev) | ||
1573 | pci_dev_put(intel_private.pcidev); | ||
1574 | if (intel_private.bridge_dev) | ||
1575 | pci_dev_put(intel_private.bridge_dev); | ||
1576 | } | ||
1577 | EXPORT_SYMBOL(intel_gmch_remove); | ||
1578 | |||
1579 | MODULE_AUTHOR("Dave Jones <davej@redhat.com>"); | ||
1580 | MODULE_LICENSE("GPL and additional rights"); | ||
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c index 7e36d2b4f9d4..b9734a978186 100644 --- a/drivers/char/agp/nvidia-agp.c +++ b/drivers/char/agp/nvidia-agp.c | |||
@@ -8,7 +8,6 @@ | |||
8 | #include <linux/pci.h> | 8 | #include <linux/pci.h> |
9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
10 | #include <linux/agp_backend.h> | 10 | #include <linux/agp_backend.h> |
11 | #include <linux/gfp.h> | ||
12 | #include <linux/page-flags.h> | 11 | #include <linux/page-flags.h> |
13 | #include <linux/mm.h> | 12 | #include <linux/mm.h> |
14 | #include <linux/jiffies.h> | 13 | #include <linux/jiffies.h> |
@@ -311,6 +310,7 @@ static const struct agp_bridge_driver nvidia_driver = { | |||
311 | .aperture_sizes = nvidia_generic_sizes, | 310 | .aperture_sizes = nvidia_generic_sizes, |
312 | .size_type = U8_APER_SIZE, | 311 | .size_type = U8_APER_SIZE, |
313 | .num_aperture_sizes = 5, | 312 | .num_aperture_sizes = 5, |
313 | .needs_scratch_page = true, | ||
314 | .configure = nvidia_configure, | 314 | .configure = nvidia_configure, |
315 | .fetch_size = nvidia_fetch_size, | 315 | .fetch_size = nvidia_fetch_size, |
316 | .cleanup = nvidia_cleanup, | 316 | .cleanup = nvidia_cleanup, |
diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c index 1c129211302d..17e380f5f818 100644 --- a/drivers/char/agp/parisc-agp.c +++ b/drivers/char/agp/parisc-agp.c | |||
@@ -358,8 +358,12 @@ parisc_agp_setup(void __iomem *ioc_hpa, void __iomem *lba_hpa) | |||
358 | bridge->dev = fake_bridge_dev; | 358 | bridge->dev = fake_bridge_dev; |
359 | 359 | ||
360 | error = agp_add_bridge(bridge); | 360 | error = agp_add_bridge(bridge); |
361 | if (error) | ||
362 | goto fail; | ||
363 | return 0; | ||
361 | 364 | ||
362 | fail: | 365 | fail: |
366 | kfree(fake_bridge_dev); | ||
363 | return error; | 367 | return error; |
364 | } | 368 | } |
365 | 369 | ||
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c index 0d426ae39c85..ffa888cd1c88 100644 --- a/drivers/char/agp/sgi-agp.c +++ b/drivers/char/agp/sgi-agp.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/acpi.h> | 14 | #include <linux/acpi.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/pci.h> | 16 | #include <linux/pci.h> |
17 | #include <linux/slab.h> | ||
17 | #include <linux/init.h> | 18 | #include <linux/init.h> |
18 | #include <linux/agp_backend.h> | 19 | #include <linux/agp_backend.h> |
19 | #include <asm/sn/addrs.h> | 20 | #include <asm/sn/addrs.h> |
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c index 6c3837a0184d..29aacd81de78 100644 --- a/drivers/char/agp/sis-agp.c +++ b/drivers/char/agp/sis-agp.c | |||
@@ -125,6 +125,7 @@ static struct agp_bridge_driver sis_driver = { | |||
125 | .aperture_sizes = sis_generic_sizes, | 125 | .aperture_sizes = sis_generic_sizes, |
126 | .size_type = U8_APER_SIZE, | 126 | .size_type = U8_APER_SIZE, |
127 | .num_aperture_sizes = 7, | 127 | .num_aperture_sizes = 7, |
128 | .needs_scratch_page = true, | ||
128 | .configure = sis_configure, | 129 | .configure = sis_configure, |
129 | .fetch_size = sis_fetch_size, | 130 | .fetch_size = sis_fetch_size, |
130 | .cleanup = sis_cleanup, | 131 | .cleanup = sis_cleanup, |
@@ -415,14 +416,6 @@ static struct pci_device_id agp_sis_pci_table[] = { | |||
415 | .subvendor = PCI_ANY_ID, | 416 | .subvendor = PCI_ANY_ID, |
416 | .subdevice = PCI_ANY_ID, | 417 | .subdevice = PCI_ANY_ID, |
417 | }, | 418 | }, |
418 | { | ||
419 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
420 | .class_mask = ~0, | ||
421 | .vendor = PCI_VENDOR_ID_SI, | ||
422 | .device = PCI_DEVICE_ID_SI_760, | ||
423 | .subvendor = PCI_ANY_ID, | ||
424 | .subdevice = PCI_ANY_ID, | ||
425 | }, | ||
426 | { } | 419 | { } |
427 | }; | 420 | }; |
428 | 421 | ||
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index d89da4ac061f..f845a8f718b3 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c | |||
@@ -3,6 +3,7 @@ | |||
3 | */ | 3 | */ |
4 | #include <linux/module.h> | 4 | #include <linux/module.h> |
5 | #include <linux/pci.h> | 5 | #include <linux/pci.h> |
6 | #include <linux/slab.h> | ||
6 | #include <linux/init.h> | 7 | #include <linux/init.h> |
7 | #include <linux/pagemap.h> | 8 | #include <linux/pagemap.h> |
8 | #include <linux/agp_backend.h> | 9 | #include <linux/agp_backend.h> |
@@ -27,6 +28,7 @@ | |||
27 | */ | 28 | */ |
28 | static int uninorth_rev; | 29 | static int uninorth_rev; |
29 | static int is_u3; | 30 | static int is_u3; |
31 | static u32 scratch_value; | ||
30 | 32 | ||
31 | #define DEFAULT_APERTURE_SIZE 256 | 33 | #define DEFAULT_APERTURE_SIZE 256 |
32 | #define DEFAULT_APERTURE_STRING "256" | 34 | #define DEFAULT_APERTURE_STRING "256" |
@@ -171,7 +173,7 @@ static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start, int ty | |||
171 | 173 | ||
172 | gp = (u32 *) &agp_bridge->gatt_table[pg_start]; | 174 | gp = (u32 *) &agp_bridge->gatt_table[pg_start]; |
173 | for (i = 0; i < mem->page_count; ++i) { | 175 | for (i = 0; i < mem->page_count; ++i) { |
174 | if (gp[i]) { | 176 | if (gp[i] != scratch_value) { |
175 | dev_info(&agp_bridge->dev->dev, | 177 | dev_info(&agp_bridge->dev->dev, |
176 | "uninorth_insert_memory: entry 0x%x occupied (%x)\n", | 178 | "uninorth_insert_memory: entry 0x%x occupied (%x)\n", |
177 | i, gp[i]); | 179 | i, gp[i]); |
@@ -213,8 +215,9 @@ int uninorth_remove_memory(struct agp_memory *mem, off_t pg_start, int type) | |||
213 | return 0; | 215 | return 0; |
214 | 216 | ||
215 | gp = (u32 *) &agp_bridge->gatt_table[pg_start]; | 217 | gp = (u32 *) &agp_bridge->gatt_table[pg_start]; |
216 | for (i = 0; i < mem->page_count; ++i) | 218 | for (i = 0; i < mem->page_count; ++i) { |
217 | gp[i] = 0; | 219 | gp[i] = scratch_value; |
220 | } | ||
218 | mb(); | 221 | mb(); |
219 | uninorth_tlbflush(mem); | 222 | uninorth_tlbflush(mem); |
220 | 223 | ||
@@ -412,7 +415,7 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge) | |||
412 | bridge->gatt_table_real = (u32 *) table; | 415 | bridge->gatt_table_real = (u32 *) table; |
413 | /* Need to clear out any dirty data still sitting in caches */ | 416 | /* Need to clear out any dirty data still sitting in caches */ |
414 | flush_dcache_range((unsigned long)table, | 417 | flush_dcache_range((unsigned long)table, |
415 | (unsigned long)(table_end + PAGE_SIZE)); | 418 | (unsigned long)table_end + 1); |
416 | bridge->gatt_table = vmap(pages, (1 << page_order), 0, PAGE_KERNEL_NCG); | 419 | bridge->gatt_table = vmap(pages, (1 << page_order), 0, PAGE_KERNEL_NCG); |
417 | 420 | ||
418 | if (bridge->gatt_table == NULL) | 421 | if (bridge->gatt_table == NULL) |
@@ -420,8 +423,13 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge) | |||
420 | 423 | ||
421 | bridge->gatt_bus_addr = virt_to_phys(table); | 424 | bridge->gatt_bus_addr = virt_to_phys(table); |
422 | 425 | ||
426 | if (is_u3) | ||
427 | scratch_value = (page_to_phys(agp_bridge->scratch_page_page) >> PAGE_SHIFT) | 0x80000000UL; | ||
428 | else | ||
429 | scratch_value = cpu_to_le32((page_to_phys(agp_bridge->scratch_page_page) & 0xFFFFF000UL) | | ||
430 | 0x1UL); | ||
423 | for (i = 0; i < num_entries; i++) | 431 | for (i = 0; i < num_entries; i++) |
424 | bridge->gatt_table[i] = 0; | 432 | bridge->gatt_table[i] = scratch_value; |
425 | 433 | ||
426 | return 0; | 434 | return 0; |
427 | 435 | ||
@@ -518,6 +526,7 @@ const struct agp_bridge_driver uninorth_agp_driver = { | |||
518 | .agp_destroy_pages = agp_generic_destroy_pages, | 526 | .agp_destroy_pages = agp_generic_destroy_pages, |
519 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 527 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
520 | .cant_use_aperture = true, | 528 | .cant_use_aperture = true, |
529 | .needs_scratch_page = true, | ||
521 | }; | 530 | }; |
522 | 531 | ||
523 | const struct agp_bridge_driver u3_agp_driver = { | 532 | const struct agp_bridge_driver u3_agp_driver = { |
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c index d3bd243867fc..df67e80019d2 100644 --- a/drivers/char/agp/via-agp.c +++ b/drivers/char/agp/via-agp.c | |||
@@ -175,6 +175,7 @@ static const struct agp_bridge_driver via_agp3_driver = { | |||
175 | .aperture_sizes = agp3_generic_sizes, | 175 | .aperture_sizes = agp3_generic_sizes, |
176 | .size_type = U8_APER_SIZE, | 176 | .size_type = U8_APER_SIZE, |
177 | .num_aperture_sizes = 10, | 177 | .num_aperture_sizes = 10, |
178 | .needs_scratch_page = true, | ||
178 | .configure = via_configure_agp3, | 179 | .configure = via_configure_agp3, |
179 | .fetch_size = via_fetch_size_agp3, | 180 | .fetch_size = via_fetch_size_agp3, |
180 | .cleanup = via_cleanup_agp3, | 181 | .cleanup = via_cleanup_agp3, |
@@ -201,6 +202,7 @@ static const struct agp_bridge_driver via_driver = { | |||
201 | .aperture_sizes = via_generic_sizes, | 202 | .aperture_sizes = via_generic_sizes, |
202 | .size_type = U8_APER_SIZE, | 203 | .size_type = U8_APER_SIZE, |
203 | .num_aperture_sizes = 9, | 204 | .num_aperture_sizes = 9, |
205 | .needs_scratch_page = true, | ||
204 | .configure = via_configure, | 206 | .configure = via_configure, |
205 | .fetch_size = via_fetch_size, | 207 | .fetch_size = via_fetch_size, |
206 | .cleanup = via_cleanup, | 208 | .cleanup = via_cleanup, |
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 6c32fbf07164..b0a70461a12c 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
@@ -84,6 +84,7 @@ static char *serial_version = "4.30"; | |||
84 | #include <linux/smp_lock.h> | 84 | #include <linux/smp_lock.h> |
85 | #include <linux/init.h> | 85 | #include <linux/init.h> |
86 | #include <linux/bitops.h> | 86 | #include <linux/bitops.h> |
87 | #include <linux/platform_device.h> | ||
87 | 88 | ||
88 | #include <asm/setup.h> | 89 | #include <asm/setup.h> |
89 | 90 | ||
@@ -1071,7 +1072,7 @@ static int get_serial_info(struct async_struct * info, | |||
1071 | if (!retinfo) | 1072 | if (!retinfo) |
1072 | return -EFAULT; | 1073 | return -EFAULT; |
1073 | memset(&tmp, 0, sizeof(tmp)); | 1074 | memset(&tmp, 0, sizeof(tmp)); |
1074 | lock_kernel(); | 1075 | tty_lock(); |
1075 | tmp.type = state->type; | 1076 | tmp.type = state->type; |
1076 | tmp.line = state->line; | 1077 | tmp.line = state->line; |
1077 | tmp.port = state->port; | 1078 | tmp.port = state->port; |
@@ -1082,7 +1083,7 @@ static int get_serial_info(struct async_struct * info, | |||
1082 | tmp.close_delay = state->close_delay; | 1083 | tmp.close_delay = state->close_delay; |
1083 | tmp.closing_wait = state->closing_wait; | 1084 | tmp.closing_wait = state->closing_wait; |
1084 | tmp.custom_divisor = state->custom_divisor; | 1085 | tmp.custom_divisor = state->custom_divisor; |
1085 | unlock_kernel(); | 1086 | tty_unlock(); |
1086 | if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) | 1087 | if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) |
1087 | return -EFAULT; | 1088 | return -EFAULT; |
1088 | return 0; | 1089 | return 0; |
@@ -1099,14 +1100,14 @@ static int set_serial_info(struct async_struct * info, | |||
1099 | if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) | 1100 | if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) |
1100 | return -EFAULT; | 1101 | return -EFAULT; |
1101 | 1102 | ||
1102 | lock_kernel(); | 1103 | tty_lock(); |
1103 | state = info->state; | 1104 | state = info->state; |
1104 | old_state = *state; | 1105 | old_state = *state; |
1105 | 1106 | ||
1106 | change_irq = new_serial.irq != state->irq; | 1107 | change_irq = new_serial.irq != state->irq; |
1107 | change_port = (new_serial.port != state->port); | 1108 | change_port = (new_serial.port != state->port); |
1108 | if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) { | 1109 | if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) { |
1109 | unlock_kernel(); | 1110 | tty_unlock(); |
1110 | return -EINVAL; | 1111 | return -EINVAL; |
1111 | } | 1112 | } |
1112 | 1113 | ||
@@ -1126,7 +1127,7 @@ static int set_serial_info(struct async_struct * info, | |||
1126 | } | 1127 | } |
1127 | 1128 | ||
1128 | if (new_serial.baud_base < 9600) { | 1129 | if (new_serial.baud_base < 9600) { |
1129 | unlock_kernel(); | 1130 | tty_unlock(); |
1130 | return -EINVAL; | 1131 | return -EINVAL; |
1131 | } | 1132 | } |
1132 | 1133 | ||
@@ -1162,7 +1163,7 @@ check_and_exit: | |||
1162 | } | 1163 | } |
1163 | } else | 1164 | } else |
1164 | retval = startup(info); | 1165 | retval = startup(info); |
1165 | unlock_kernel(); | 1166 | tty_unlock(); |
1166 | return retval; | 1167 | return retval; |
1167 | } | 1168 | } |
1168 | 1169 | ||
@@ -1262,6 +1263,36 @@ static int rs_break(struct tty_struct *tty, int break_state) | |||
1262 | return 0; | 1263 | return 0; |
1263 | } | 1264 | } |
1264 | 1265 | ||
1266 | /* | ||
1267 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) | ||
1268 | * Return: write counters to the user passed counter struct | ||
1269 | * NB: both 1->0 and 0->1 transitions are counted except for | ||
1270 | * RI where only 0->1 is counted. | ||
1271 | */ | ||
1272 | static int rs_get_icount(struct tty_struct *tty, | ||
1273 | struct serial_icounter_struct *icount) | ||
1274 | { | ||
1275 | struct async_struct *info = tty->driver_data; | ||
1276 | struct async_icount cnow; | ||
1277 | unsigned long flags; | ||
1278 | |||
1279 | local_irq_save(flags); | ||
1280 | cnow = info->state->icount; | ||
1281 | local_irq_restore(flags); | ||
1282 | icount->cts = cnow.cts; | ||
1283 | icount->dsr = cnow.dsr; | ||
1284 | icount->rng = cnow.rng; | ||
1285 | icount->dcd = cnow.dcd; | ||
1286 | icount->rx = cnow.rx; | ||
1287 | icount->tx = cnow.tx; | ||
1288 | icount->frame = cnow.frame; | ||
1289 | icount->overrun = cnow.overrun; | ||
1290 | icount->parity = cnow.parity; | ||
1291 | icount->brk = cnow.brk; | ||
1292 | icount->buf_overrun = cnow.buf_overrun; | ||
1293 | |||
1294 | return 0; | ||
1295 | } | ||
1265 | 1296 | ||
1266 | static int rs_ioctl(struct tty_struct *tty, struct file * file, | 1297 | static int rs_ioctl(struct tty_struct *tty, struct file * file, |
1267 | unsigned int cmd, unsigned long arg) | 1298 | unsigned int cmd, unsigned long arg) |
@@ -1331,31 +1362,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, | |||
1331 | } | 1362 | } |
1332 | /* NOTREACHED */ | 1363 | /* NOTREACHED */ |
1333 | 1364 | ||
1334 | /* | ||
1335 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) | ||
1336 | * Return: write counters to the user passed counter struct | ||
1337 | * NB: both 1->0 and 0->1 transitions are counted except for | ||
1338 | * RI where only 0->1 is counted. | ||
1339 | */ | ||
1340 | case TIOCGICOUNT: | ||
1341 | local_irq_save(flags); | ||
1342 | cnow = info->state->icount; | ||
1343 | local_irq_restore(flags); | ||
1344 | icount.cts = cnow.cts; | ||
1345 | icount.dsr = cnow.dsr; | ||
1346 | icount.rng = cnow.rng; | ||
1347 | icount.dcd = cnow.dcd; | ||
1348 | icount.rx = cnow.rx; | ||
1349 | icount.tx = cnow.tx; | ||
1350 | icount.frame = cnow.frame; | ||
1351 | icount.overrun = cnow.overrun; | ||
1352 | icount.parity = cnow.parity; | ||
1353 | icount.brk = cnow.brk; | ||
1354 | icount.buf_overrun = cnow.buf_overrun; | ||
1355 | |||
1356 | if (copy_to_user(argp, &icount, sizeof(icount))) | ||
1357 | return -EFAULT; | ||
1358 | return 0; | ||
1359 | case TIOCSERGWILD: | 1365 | case TIOCSERGWILD: |
1360 | case TIOCSERSWILD: | 1366 | case TIOCSERSWILD: |
1361 | /* "setserial -W" is called in Debian boot */ | 1367 | /* "setserial -W" is called in Debian boot */ |
@@ -1527,6 +1533,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1527 | { | 1533 | { |
1528 | struct async_struct * info = tty->driver_data; | 1534 | struct async_struct * info = tty->driver_data; |
1529 | unsigned long orig_jiffies, char_time; | 1535 | unsigned long orig_jiffies, char_time; |
1536 | int tty_was_locked = tty_locked(); | ||
1530 | int lsr; | 1537 | int lsr; |
1531 | 1538 | ||
1532 | if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) | 1539 | if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) |
@@ -1537,7 +1544,12 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1537 | 1544 | ||
1538 | orig_jiffies = jiffies; | 1545 | orig_jiffies = jiffies; |
1539 | 1546 | ||
1540 | lock_kernel(); | 1547 | /* |
1548 | * tty_wait_until_sent is called from lots of places, | ||
1549 | * with or without the BTM. | ||
1550 | */ | ||
1551 | if (!tty_was_locked) | ||
1552 | tty_lock(); | ||
1541 | /* | 1553 | /* |
1542 | * Set the check interval to be 1/5 of the estimated time to | 1554 | * Set the check interval to be 1/5 of the estimated time to |
1543 | * send a single character, and make it at least 1. The check | 1555 | * send a single character, and make it at least 1. The check |
@@ -1578,7 +1590,8 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1578 | break; | 1590 | break; |
1579 | } | 1591 | } |
1580 | __set_current_state(TASK_RUNNING); | 1592 | __set_current_state(TASK_RUNNING); |
1581 | unlock_kernel(); | 1593 | if (!tty_was_locked) |
1594 | tty_unlock(); | ||
1582 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | 1595 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT |
1583 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); | 1596 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); |
1584 | #endif | 1597 | #endif |
@@ -1702,7 +1715,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
1702 | printk("block_til_ready blocking: ttys%d, count = %d\n", | 1715 | printk("block_til_ready blocking: ttys%d, count = %d\n", |
1703 | info->line, state->count); | 1716 | info->line, state->count); |
1704 | #endif | 1717 | #endif |
1718 | tty_unlock(); | ||
1705 | schedule(); | 1719 | schedule(); |
1720 | tty_lock(); | ||
1706 | } | 1721 | } |
1707 | __set_current_state(TASK_RUNNING); | 1722 | __set_current_state(TASK_RUNNING); |
1708 | remove_wait_queue(&info->open_wait, &wait); | 1723 | remove_wait_queue(&info->open_wait, &wait); |
@@ -1948,35 +1963,23 @@ static const struct tty_operations serial_ops = { | |||
1948 | .wait_until_sent = rs_wait_until_sent, | 1963 | .wait_until_sent = rs_wait_until_sent, |
1949 | .tiocmget = rs_tiocmget, | 1964 | .tiocmget = rs_tiocmget, |
1950 | .tiocmset = rs_tiocmset, | 1965 | .tiocmset = rs_tiocmset, |
1966 | .get_icount = rs_get_icount, | ||
1951 | .proc_fops = &rs_proc_fops, | 1967 | .proc_fops = &rs_proc_fops, |
1952 | }; | 1968 | }; |
1953 | 1969 | ||
1954 | /* | 1970 | /* |
1955 | * The serial driver boot-time initialization code! | 1971 | * The serial driver boot-time initialization code! |
1956 | */ | 1972 | */ |
1957 | static int __init rs_init(void) | 1973 | static int __init amiga_serial_probe(struct platform_device *pdev) |
1958 | { | 1974 | { |
1959 | unsigned long flags; | 1975 | unsigned long flags; |
1960 | struct serial_state * state; | 1976 | struct serial_state * state; |
1961 | int error; | 1977 | int error; |
1962 | 1978 | ||
1963 | if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_SERIAL)) | ||
1964 | return -ENODEV; | ||
1965 | |||
1966 | serial_driver = alloc_tty_driver(1); | 1979 | serial_driver = alloc_tty_driver(1); |
1967 | if (!serial_driver) | 1980 | if (!serial_driver) |
1968 | return -ENOMEM; | 1981 | return -ENOMEM; |
1969 | 1982 | ||
1970 | /* | ||
1971 | * We request SERDAT and SERPER only, because the serial registers are | ||
1972 | * too spreaded over the custom register space | ||
1973 | */ | ||
1974 | if (!request_mem_region(CUSTOM_PHYSADDR+0x30, 4, | ||
1975 | "amiserial [Paula]")) { | ||
1976 | error = -EBUSY; | ||
1977 | goto fail_put_tty_driver; | ||
1978 | } | ||
1979 | |||
1980 | IRQ_ports = NULL; | 1983 | IRQ_ports = NULL; |
1981 | 1984 | ||
1982 | show_serial_version(); | 1985 | show_serial_version(); |
@@ -1998,7 +2001,7 @@ static int __init rs_init(void) | |||
1998 | 2001 | ||
1999 | error = tty_register_driver(serial_driver); | 2002 | error = tty_register_driver(serial_driver); |
2000 | if (error) | 2003 | if (error) |
2001 | goto fail_release_mem_region; | 2004 | goto fail_put_tty_driver; |
2002 | 2005 | ||
2003 | state = rs_table; | 2006 | state = rs_table; |
2004 | state->magic = SSTATE_MAGIC; | 2007 | state->magic = SSTATE_MAGIC; |
@@ -2021,8 +2024,6 @@ static int __init rs_init(void) | |||
2021 | state->baud_base = amiga_colorclock; | 2024 | state->baud_base = amiga_colorclock; |
2022 | state->xmit_fifo_size = 1; | 2025 | state->xmit_fifo_size = 1; |
2023 | 2026 | ||
2024 | local_irq_save(flags); | ||
2025 | |||
2026 | /* set ISRs, and then disable the rx interrupts */ | 2027 | /* set ISRs, and then disable the rx interrupts */ |
2027 | error = request_irq(IRQ_AMIGA_TBE, ser_tx_int, 0, "serial TX", state); | 2028 | error = request_irq(IRQ_AMIGA_TBE, ser_tx_int, 0, "serial TX", state); |
2028 | if (error) | 2029 | if (error) |
@@ -2033,6 +2034,8 @@ static int __init rs_init(void) | |||
2033 | if (error) | 2034 | if (error) |
2034 | goto fail_free_irq; | 2035 | goto fail_free_irq; |
2035 | 2036 | ||
2037 | local_irq_save(flags); | ||
2038 | |||
2036 | /* turn off Rx and Tx interrupts */ | 2039 | /* turn off Rx and Tx interrupts */ |
2037 | custom.intena = IF_RBF | IF_TBE; | 2040 | custom.intena = IF_RBF | IF_TBE; |
2038 | mb(); | 2041 | mb(); |
@@ -2050,23 +2053,24 @@ static int __init rs_init(void) | |||
2050 | ciab.ddra |= (SER_DTR | SER_RTS); /* outputs */ | 2053 | ciab.ddra |= (SER_DTR | SER_RTS); /* outputs */ |
2051 | ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR); /* inputs */ | 2054 | ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR); /* inputs */ |
2052 | 2055 | ||
2056 | platform_set_drvdata(pdev, state); | ||
2057 | |||
2053 | return 0; | 2058 | return 0; |
2054 | 2059 | ||
2055 | fail_free_irq: | 2060 | fail_free_irq: |
2056 | free_irq(IRQ_AMIGA_TBE, state); | 2061 | free_irq(IRQ_AMIGA_TBE, state); |
2057 | fail_unregister: | 2062 | fail_unregister: |
2058 | tty_unregister_driver(serial_driver); | 2063 | tty_unregister_driver(serial_driver); |
2059 | fail_release_mem_region: | ||
2060 | release_mem_region(CUSTOM_PHYSADDR+0x30, 4); | ||
2061 | fail_put_tty_driver: | 2064 | fail_put_tty_driver: |
2062 | put_tty_driver(serial_driver); | 2065 | put_tty_driver(serial_driver); |
2063 | return error; | 2066 | return error; |
2064 | } | 2067 | } |
2065 | 2068 | ||
2066 | static __exit void rs_exit(void) | 2069 | static int __exit amiga_serial_remove(struct platform_device *pdev) |
2067 | { | 2070 | { |
2068 | int error; | 2071 | int error; |
2069 | struct async_struct *info = rs_table[0].info; | 2072 | struct serial_state *state = platform_get_drvdata(pdev); |
2073 | struct async_struct *info = state->info; | ||
2070 | 2074 | ||
2071 | /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ | 2075 | /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ |
2072 | tasklet_kill(&info->tlet); | 2076 | tasklet_kill(&info->tlet); |
@@ -2075,19 +2079,38 @@ static __exit void rs_exit(void) | |||
2075 | error); | 2079 | error); |
2076 | put_tty_driver(serial_driver); | 2080 | put_tty_driver(serial_driver); |
2077 | 2081 | ||
2078 | if (info) { | 2082 | rs_table[0].info = NULL; |
2079 | rs_table[0].info = NULL; | 2083 | kfree(info); |
2080 | kfree(info); | ||
2081 | } | ||
2082 | 2084 | ||
2083 | free_irq(IRQ_AMIGA_TBE, rs_table); | 2085 | free_irq(IRQ_AMIGA_TBE, rs_table); |
2084 | free_irq(IRQ_AMIGA_RBF, rs_table); | 2086 | free_irq(IRQ_AMIGA_RBF, rs_table); |
2085 | 2087 | ||
2086 | release_mem_region(CUSTOM_PHYSADDR+0x30, 4); | 2088 | platform_set_drvdata(pdev, NULL); |
2089 | |||
2090 | return error; | ||
2091 | } | ||
2092 | |||
2093 | static struct platform_driver amiga_serial_driver = { | ||
2094 | .remove = __exit_p(amiga_serial_remove), | ||
2095 | .driver = { | ||
2096 | .name = "amiga-serial", | ||
2097 | .owner = THIS_MODULE, | ||
2098 | }, | ||
2099 | }; | ||
2100 | |||
2101 | static int __init amiga_serial_init(void) | ||
2102 | { | ||
2103 | return platform_driver_probe(&amiga_serial_driver, amiga_serial_probe); | ||
2104 | } | ||
2105 | |||
2106 | module_init(amiga_serial_init); | ||
2107 | |||
2108 | static void __exit amiga_serial_exit(void) | ||
2109 | { | ||
2110 | platform_driver_unregister(&amiga_serial_driver); | ||
2087 | } | 2111 | } |
2088 | 2112 | ||
2089 | module_init(rs_init) | 2113 | module_exit(amiga_serial_exit); |
2090 | module_exit(rs_exit) | ||
2091 | 2114 | ||
2092 | 2115 | ||
2093 | #if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE) | 2116 | #if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE) |
@@ -2154,3 +2177,4 @@ console_initcall(amiserial_console_init); | |||
2154 | #endif /* CONFIG_SERIAL_CONSOLE && !MODULE */ | 2177 | #endif /* CONFIG_SERIAL_CONSOLE && !MODULE */ |
2155 | 2178 | ||
2156 | MODULE_LICENSE("GPL"); | 2179 | MODULE_LICENSE("GPL"); |
2180 | MODULE_ALIAS("platform:amiga-serial"); | ||
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c index 4f568cb9af3f..45b987c9889e 100644 --- a/drivers/char/apm-emulation.c +++ b/drivers/char/apm-emulation.c | |||
@@ -7,13 +7,13 @@ | |||
7 | * Intel Corporation, Microsoft Corporation. Advanced Power Management | 7 | * Intel Corporation, Microsoft Corporation. Advanced Power Management |
8 | * (APM) BIOS Interface Specification, Revision 1.2, February 1996. | 8 | * (APM) BIOS Interface Specification, Revision 1.2, February 1996. |
9 | * | 9 | * |
10 | * [This document is available from Microsoft at: | 10 | * This document is available from Microsoft at: |
11 | * http://www.microsoft.com/hwdev/busbios/amp_12.htm] | 11 | * http://www.microsoft.com/whdc/archive/amp_12.mspx |
12 | */ | 12 | */ |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/poll.h> | 14 | #include <linux/poll.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/smp_lock.h> | 16 | #include <linux/mutex.h> |
17 | #include <linux/proc_fs.h> | 17 | #include <linux/proc_fs.h> |
18 | #include <linux/seq_file.h> | 18 | #include <linux/seq_file.h> |
19 | #include <linux/miscdevice.h> | 19 | #include <linux/miscdevice.h> |
@@ -126,6 +126,7 @@ struct apm_user { | |||
126 | /* | 126 | /* |
127 | * Local variables | 127 | * Local variables |
128 | */ | 128 | */ |
129 | static DEFINE_MUTEX(apm_mutex); | ||
129 | static atomic_t suspend_acks_pending = ATOMIC_INIT(0); | 130 | static atomic_t suspend_acks_pending = ATOMIC_INIT(0); |
130 | static atomic_t userspace_notification_inhibit = ATOMIC_INIT(0); | 131 | static atomic_t userspace_notification_inhibit = ATOMIC_INIT(0); |
131 | static int apm_disabled; | 132 | static int apm_disabled; |
@@ -265,8 +266,8 @@ static unsigned int apm_poll(struct file *fp, poll_table * wait) | |||
265 | * Only when everyone who has opened /dev/apm_bios with write permission | 266 | * Only when everyone who has opened /dev/apm_bios with write permission |
266 | * has acknowledge does the actual suspend happen. | 267 | * has acknowledge does the actual suspend happen. |
267 | */ | 268 | */ |
268 | static int | 269 | static long |
269 | apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) | 270 | apm_ioctl(struct file *filp, u_int cmd, u_long arg) |
270 | { | 271 | { |
271 | struct apm_user *as = filp->private_data; | 272 | struct apm_user *as = filp->private_data; |
272 | int err = -EINVAL; | 273 | int err = -EINVAL; |
@@ -274,6 +275,7 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) | |||
274 | if (!as->suser || !as->writer) | 275 | if (!as->suser || !as->writer) |
275 | return -EPERM; | 276 | return -EPERM; |
276 | 277 | ||
278 | mutex_lock(&apm_mutex); | ||
277 | switch (cmd) { | 279 | switch (cmd) { |
278 | case APM_IOC_SUSPEND: | 280 | case APM_IOC_SUSPEND: |
279 | mutex_lock(&state_lock); | 281 | mutex_lock(&state_lock); |
@@ -334,6 +336,7 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) | |||
334 | mutex_unlock(&state_lock); | 336 | mutex_unlock(&state_lock); |
335 | break; | 337 | break; |
336 | } | 338 | } |
339 | mutex_unlock(&apm_mutex); | ||
337 | 340 | ||
338 | return err; | 341 | return err; |
339 | } | 342 | } |
@@ -368,7 +371,7 @@ static int apm_open(struct inode * inode, struct file * filp) | |||
368 | { | 371 | { |
369 | struct apm_user *as; | 372 | struct apm_user *as; |
370 | 373 | ||
371 | lock_kernel(); | 374 | mutex_lock(&apm_mutex); |
372 | as = kzalloc(sizeof(*as), GFP_KERNEL); | 375 | as = kzalloc(sizeof(*as), GFP_KERNEL); |
373 | if (as) { | 376 | if (as) { |
374 | /* | 377 | /* |
@@ -388,7 +391,7 @@ static int apm_open(struct inode * inode, struct file * filp) | |||
388 | 391 | ||
389 | filp->private_data = as; | 392 | filp->private_data = as; |
390 | } | 393 | } |
391 | unlock_kernel(); | 394 | mutex_unlock(&apm_mutex); |
392 | 395 | ||
393 | return as ? 0 : -ENOMEM; | 396 | return as ? 0 : -ENOMEM; |
394 | } | 397 | } |
@@ -397,9 +400,10 @@ static const struct file_operations apm_bios_fops = { | |||
397 | .owner = THIS_MODULE, | 400 | .owner = THIS_MODULE, |
398 | .read = apm_read, | 401 | .read = apm_read, |
399 | .poll = apm_poll, | 402 | .poll = apm_poll, |
400 | .ioctl = apm_ioctl, | 403 | .unlocked_ioctl = apm_ioctl, |
401 | .open = apm_open, | 404 | .open = apm_open, |
402 | .release = apm_release, | 405 | .release = apm_release, |
406 | .llseek = noop_llseek, | ||
403 | }; | 407 | }; |
404 | 408 | ||
405 | static struct miscdevice apm_device = { | 409 | static struct miscdevice apm_device = { |
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c index fe2cb2f5db17..25373df1dcf8 100644 --- a/drivers/char/applicom.c +++ b/drivers/char/applicom.c | |||
@@ -14,7 +14,7 @@ | |||
14 | /* et passe en argument a acinit, mais est scrute sur le bus pour s'adapter */ | 14 | /* et passe en argument a acinit, mais est scrute sur le bus pour s'adapter */ |
15 | /* au nombre de cartes presentes sur le bus. IOCL code 6 affichait V2.4.3 */ | 15 | /* au nombre de cartes presentes sur le bus. IOCL code 6 affichait V2.4.3 */ |
16 | /* F.LAFORSE 28/11/95 creation de fichiers acXX.o avec les differentes */ | 16 | /* F.LAFORSE 28/11/95 creation de fichiers acXX.o avec les differentes */ |
17 | /* adresses de base des cartes, IOCTL 6 plus complet */ | 17 | /* addresses de base des cartes, IOCTL 6 plus complet */ |
18 | /* J.PAGET le 19/08/96 copie de la version V2.6 en V2.8.0 sans modification */ | 18 | /* J.PAGET le 19/08/96 copie de la version V2.6 en V2.8.0 sans modification */ |
19 | /* de code autre que le texte V2.6.1 en V2.8.0 */ | 19 | /* de code autre que le texte V2.6.1 en V2.8.0 */ |
20 | /*****************************************************************************/ | 20 | /*****************************************************************************/ |
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/errno.h> | 28 | #include <linux/errno.h> |
29 | #include <linux/mutex.h> | ||
29 | #include <linux/miscdevice.h> | 30 | #include <linux/miscdevice.h> |
30 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
31 | #include <linux/wait.h> | 32 | #include <linux/wait.h> |
@@ -59,6 +60,7 @@ | |||
59 | #define PCI_DEVICE_ID_APPLICOM_PCI2000PFB 0x0003 | 60 | #define PCI_DEVICE_ID_APPLICOM_PCI2000PFB 0x0003 |
60 | #endif | 61 | #endif |
61 | 62 | ||
63 | static DEFINE_MUTEX(ac_mutex); | ||
62 | static char *applicom_pci_devnames[] = { | 64 | static char *applicom_pci_devnames[] = { |
63 | "PCI board", | 65 | "PCI board", |
64 | "PCI2000IBS / PCI2000CAN", | 66 | "PCI2000IBS / PCI2000CAN", |
@@ -106,8 +108,7 @@ static unsigned int DeviceErrorCount; /* number of device error */ | |||
106 | 108 | ||
107 | static ssize_t ac_read (struct file *, char __user *, size_t, loff_t *); | 109 | static ssize_t ac_read (struct file *, char __user *, size_t, loff_t *); |
108 | static ssize_t ac_write (struct file *, const char __user *, size_t, loff_t *); | 110 | static ssize_t ac_write (struct file *, const char __user *, size_t, loff_t *); |
109 | static int ac_ioctl(struct inode *, struct file *, unsigned int, | 111 | static long ac_ioctl(struct file *, unsigned int, unsigned long); |
110 | unsigned long); | ||
111 | static irqreturn_t ac_interrupt(int, void *); | 112 | static irqreturn_t ac_interrupt(int, void *); |
112 | 113 | ||
113 | static const struct file_operations ac_fops = { | 114 | static const struct file_operations ac_fops = { |
@@ -115,7 +116,7 @@ static const struct file_operations ac_fops = { | |||
115 | .llseek = no_llseek, | 116 | .llseek = no_llseek, |
116 | .read = ac_read, | 117 | .read = ac_read, |
117 | .write = ac_write, | 118 | .write = ac_write, |
118 | .ioctl = ac_ioctl, | 119 | .unlocked_ioctl = ac_ioctl, |
119 | }; | 120 | }; |
120 | 121 | ||
121 | static struct miscdevice ac_miscdev = { | 122 | static struct miscdevice ac_miscdev = { |
@@ -565,6 +566,7 @@ static ssize_t ac_read (struct file *filp, char __user *buf, size_t count, loff_ | |||
565 | struct mailbox mailbox; | 566 | struct mailbox mailbox; |
566 | 567 | ||
567 | /* Got a packet for us */ | 568 | /* Got a packet for us */ |
569 | memset(&st_loc, 0, sizeof(st_loc)); | ||
568 | ret = do_ac_read(i, buf, &st_loc, &mailbox); | 570 | ret = do_ac_read(i, buf, &st_loc, &mailbox); |
569 | spin_unlock_irqrestore(&apbs[i].mutex, flags); | 571 | spin_unlock_irqrestore(&apbs[i].mutex, flags); |
570 | set_current_state(TASK_RUNNING); | 572 | set_current_state(TASK_RUNNING); |
@@ -689,7 +691,7 @@ static irqreturn_t ac_interrupt(int vec, void *dev_instance) | |||
689 | 691 | ||
690 | 692 | ||
691 | 693 | ||
692 | static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 694 | static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
693 | 695 | ||
694 | { /* @ ADG ou ATO selon le cas */ | 696 | { /* @ ADG ou ATO selon le cas */ |
695 | int i; | 697 | int i; |
@@ -703,15 +705,11 @@ static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un | |||
703 | /* In general, the device is only openable by root anyway, so we're not | 705 | /* In general, the device is only openable by root anyway, so we're not |
704 | particularly concerned that bogus ioctls can flood the console. */ | 706 | particularly concerned that bogus ioctls can flood the console. */ |
705 | 707 | ||
706 | adgl = kmalloc(sizeof(struct st_ram_io), GFP_KERNEL); | 708 | adgl = memdup_user(argp, sizeof(struct st_ram_io)); |
707 | if (!adgl) | 709 | if (IS_ERR(adgl)) |
708 | return -ENOMEM; | 710 | return PTR_ERR(adgl); |
709 | 711 | ||
710 | if (copy_from_user(adgl, argp, sizeof(struct st_ram_io))) { | 712 | mutex_lock(&ac_mutex); |
711 | kfree(adgl); | ||
712 | return -EFAULT; | ||
713 | } | ||
714 | |||
715 | IndexCard = adgl->num_card-1; | 713 | IndexCard = adgl->num_card-1; |
716 | 714 | ||
717 | if(cmd != 6 && ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) { | 715 | if(cmd != 6 && ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) { |
@@ -721,6 +719,7 @@ static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un | |||
721 | warncount--; | 719 | warncount--; |
722 | } | 720 | } |
723 | kfree(adgl); | 721 | kfree(adgl); |
722 | mutex_unlock(&ac_mutex); | ||
724 | return -EINVAL; | 723 | return -EINVAL; |
725 | } | 724 | } |
726 | 725 | ||
@@ -838,6 +837,7 @@ static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un | |||
838 | } | 837 | } |
839 | Dummy = readb(apbs[IndexCard].RamIO + VERS); | 838 | Dummy = readb(apbs[IndexCard].RamIO + VERS); |
840 | kfree(adgl); | 839 | kfree(adgl); |
840 | mutex_unlock(&ac_mutex); | ||
841 | return 0; | 841 | return 0; |
842 | } | 842 | } |
843 | 843 | ||
diff --git a/drivers/char/bfin-otp.c b/drivers/char/bfin-otp.c index 836d4f0a876f..44660f1c4849 100644 --- a/drivers/char/bfin-otp.c +++ b/drivers/char/bfin-otp.c | |||
@@ -222,6 +222,7 @@ static const struct file_operations bfin_otp_fops = { | |||
222 | .unlocked_ioctl = bfin_otp_ioctl, | 222 | .unlocked_ioctl = bfin_otp_ioctl, |
223 | .read = bfin_otp_read, | 223 | .read = bfin_otp_read, |
224 | .write = bfin_otp_write, | 224 | .write = bfin_otp_write, |
225 | .llseek = default_llseek, | ||
225 | }; | 226 | }; |
226 | 227 | ||
227 | static struct miscdevice bfin_otp_misc_device = { | 228 | static struct miscdevice bfin_otp_misc_device = { |
diff --git a/drivers/char/bfin_jtag_comm.c b/drivers/char/bfin_jtag_comm.c index 2628c7415ea8..e397df3ad98e 100644 --- a/drivers/char/bfin_jtag_comm.c +++ b/drivers/char/bfin_jtag_comm.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
23 | #include <linux/sched.h> | 23 | #include <linux/sched.h> |
24 | #include <linux/slab.h> | ||
24 | #include <linux/tty.h> | 25 | #include <linux/tty.h> |
25 | #include <linux/tty_driver.h> | 26 | #include <linux/tty_driver.h> |
26 | #include <linux/tty_flip.h> | 27 | #include <linux/tty_flip.h> |
diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c index d8cff909001c..f6718f05dad4 100644 --- a/drivers/char/briq_panel.c +++ b/drivers/char/briq_panel.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/wait.h> | 15 | #include <linux/wait.h> |
16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
17 | #include <linux/slab.h> | ||
18 | #include <linux/ioport.h> | 17 | #include <linux/ioport.h> |
19 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
20 | #include <linux/miscdevice.h> | 19 | #include <linux/miscdevice.h> |
@@ -68,15 +67,15 @@ static void set_led(char state) | |||
68 | 67 | ||
69 | static int briq_panel_open(struct inode *ino, struct file *filep) | 68 | static int briq_panel_open(struct inode *ino, struct file *filep) |
70 | { | 69 | { |
71 | lock_kernel(); | 70 | tty_lock(); |
72 | /* enforce single access, vfd_is_open is protected by BKL */ | 71 | /* enforce single access, vfd_is_open is protected by BKL */ |
73 | if (vfd_is_open) { | 72 | if (vfd_is_open) { |
74 | unlock_kernel(); | 73 | tty_unlock(); |
75 | return -EBUSY; | 74 | return -EBUSY; |
76 | } | 75 | } |
77 | vfd_is_open = 1; | 76 | vfd_is_open = 1; |
78 | 77 | ||
79 | unlock_kernel(); | 78 | tty_unlock(); |
80 | return 0; | 79 | return 0; |
81 | } | 80 | } |
82 | 81 | ||
@@ -187,6 +186,7 @@ static const struct file_operations briq_panel_fops = { | |||
187 | .write = briq_panel_write, | 186 | .write = briq_panel_write, |
188 | .open = briq_panel_open, | 187 | .open = briq_panel_open, |
189 | .release = briq_panel_release, | 188 | .release = briq_panel_release, |
189 | .llseek = noop_llseek, | ||
190 | }; | 190 | }; |
191 | 191 | ||
192 | static struct miscdevice briq_panel_miscdev = { | 192 | static struct miscdevice briq_panel_miscdev = { |
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c index c02db01f736e..a4a6c2f044b5 100644 --- a/drivers/char/bsr.c +++ b/drivers/char/bsr.c | |||
@@ -23,10 +23,12 @@ | |||
23 | #include <linux/of.h> | 23 | #include <linux/of.h> |
24 | #include <linux/of_device.h> | 24 | #include <linux/of_device.h> |
25 | #include <linux/of_platform.h> | 25 | #include <linux/of_platform.h> |
26 | #include <linux/fs.h> | ||
26 | #include <linux/module.h> | 27 | #include <linux/module.h> |
27 | #include <linux/cdev.h> | 28 | #include <linux/cdev.h> |
28 | #include <linux/list.h> | 29 | #include <linux/list.h> |
29 | #include <linux/mm.h> | 30 | #include <linux/mm.h> |
31 | #include <linux/slab.h> | ||
30 | #include <asm/pgtable.h> | 32 | #include <asm/pgtable.h> |
31 | #include <asm/io.h> | 33 | #include <asm/io.h> |
32 | 34 | ||
@@ -153,6 +155,7 @@ static const struct file_operations bsr_fops = { | |||
153 | .owner = THIS_MODULE, | 155 | .owner = THIS_MODULE, |
154 | .mmap = bsr_mmap, | 156 | .mmap = bsr_mmap, |
155 | .open = bsr_open, | 157 | .open = bsr_open, |
158 | .llseek = noop_llseek, | ||
156 | }; | 159 | }; |
157 | 160 | ||
158 | static void bsr_cleanup_devs(void) | 161 | static void bsr_cleanup_devs(void) |
@@ -252,7 +255,7 @@ static int bsr_add_node(struct device_node *bn) | |||
252 | 255 | ||
253 | cur->bsr_device = device_create(bsr_class, NULL, cur->bsr_dev, | 256 | cur->bsr_device = device_create(bsr_class, NULL, cur->bsr_dev, |
254 | cur, cur->bsr_name); | 257 | cur, cur->bsr_name); |
255 | if (!cur->bsr_device) { | 258 | if (IS_ERR(cur->bsr_device)) { |
256 | printk(KERN_ERR "device_create failed for %s\n", | 259 | printk(KERN_ERR "device_create failed for %s\n", |
257 | cur->bsr_name); | 260 | cur->bsr_name); |
258 | cdev_del(&cur->bsr_cdev); | 261 | cdev_del(&cur->bsr_cdev); |
diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c index 4d830dc482ef..0cf1e5fad9ab 100644 --- a/drivers/char/cs5535_gpio.c +++ b/drivers/char/cs5535_gpio.c | |||
@@ -169,7 +169,8 @@ static const struct file_operations cs5535_gpio_fops = { | |||
169 | .owner = THIS_MODULE, | 169 | .owner = THIS_MODULE, |
170 | .write = cs5535_gpio_write, | 170 | .write = cs5535_gpio_write, |
171 | .read = cs5535_gpio_read, | 171 | .read = cs5535_gpio_read, |
172 | .open = cs5535_gpio_open | 172 | .open = cs5535_gpio_open, |
173 | .llseek = no_llseek, | ||
173 | }; | 174 | }; |
174 | 175 | ||
175 | static int __init cs5535_gpio_init(void) | 176 | static int __init cs5535_gpio_init(void) |
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 4254457d3911..4f152c28f40e 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -65,7 +65,6 @@ | |||
65 | #include <linux/tty.h> | 65 | #include <linux/tty.h> |
66 | #include <linux/tty_flip.h> | 66 | #include <linux/tty_flip.h> |
67 | #include <linux/serial.h> | 67 | #include <linux/serial.h> |
68 | #include <linux/smp_lock.h> | ||
69 | #include <linux/major.h> | 68 | #include <linux/major.h> |
70 | #include <linux/string.h> | 69 | #include <linux/string.h> |
71 | #include <linux/fcntl.h> | 70 | #include <linux/fcntl.h> |
@@ -79,6 +78,7 @@ | |||
79 | #include <linux/bitops.h> | 78 | #include <linux/bitops.h> |
80 | #include <linux/firmware.h> | 79 | #include <linux/firmware.h> |
81 | #include <linux/device.h> | 80 | #include <linux/device.h> |
81 | #include <linux/slab.h> | ||
82 | 82 | ||
83 | #include <linux/io.h> | 83 | #include <linux/io.h> |
84 | #include <linux/uaccess.h> | 84 | #include <linux/uaccess.h> |
@@ -158,13 +158,11 @@ static unsigned int cy_isa_addresses[] = { | |||
158 | 158 | ||
159 | #define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses) | 159 | #define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses) |
160 | 160 | ||
161 | #ifdef MODULE | ||
162 | static long maddr[NR_CARDS]; | 161 | static long maddr[NR_CARDS]; |
163 | static int irq[NR_CARDS]; | 162 | static int irq[NR_CARDS]; |
164 | 163 | ||
165 | module_param_array(maddr, long, NULL, 0); | 164 | module_param_array(maddr, long, NULL, 0); |
166 | module_param_array(irq, int, NULL, 0); | 165 | module_param_array(irq, int, NULL, 0); |
167 | #endif | ||
168 | 166 | ||
169 | #endif /* CONFIG_ISA */ | 167 | #endif /* CONFIG_ISA */ |
170 | 168 | ||
@@ -598,12 +596,6 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip, | |||
598 | save_car = readb(base_addr + (CyCAR << index)); | 596 | save_car = readb(base_addr + (CyCAR << index)); |
599 | cy_writeb(base_addr + (CyCAR << index), save_xir); | 597 | cy_writeb(base_addr + (CyCAR << index), save_xir); |
600 | 598 | ||
601 | /* validate the port# (as configured and open) */ | ||
602 | if (channel + chip * 4 >= cinfo->nports) { | ||
603 | cy_writeb(base_addr + (CySRER << index), | ||
604 | readb(base_addr + (CySRER << index)) & ~CyTxRdy); | ||
605 | goto end; | ||
606 | } | ||
607 | info = &cinfo->ports[channel + chip * 4]; | 599 | info = &cinfo->ports[channel + chip * 4]; |
608 | tty = tty_port_tty_get(&info->port); | 600 | tty = tty_port_tty_get(&info->port); |
609 | if (tty == NULL) { | 601 | if (tty == NULL) { |
@@ -1615,7 +1607,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
1615 | * If the port is the middle of closing, bail out now | 1607 | * If the port is the middle of closing, bail out now |
1616 | */ | 1608 | */ |
1617 | if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { | 1609 | if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { |
1618 | wait_event_interruptible(info->port.close_wait, | 1610 | wait_event_interruptible_tty(info->port.close_wait, |
1619 | !(info->port.flags & ASYNC_CLOSING)); | 1611 | !(info->port.flags & ASYNC_CLOSING)); |
1620 | return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; | 1612 | return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; |
1621 | } | 1613 | } |
@@ -1662,7 +1654,6 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1662 | return; /* Just in case.... */ | 1654 | return; /* Just in case.... */ |
1663 | 1655 | ||
1664 | orig_jiffies = jiffies; | 1656 | orig_jiffies = jiffies; |
1665 | lock_kernel(); | ||
1666 | /* | 1657 | /* |
1667 | * Set the check interval to be 1/5 of the estimated time to | 1658 | * Set the check interval to be 1/5 of the estimated time to |
1668 | * send a single character, and make it at least 1. The check | 1659 | * send a single character, and make it at least 1. The check |
@@ -1709,7 +1700,6 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1709 | } | 1700 | } |
1710 | /* Run one more char cycle */ | 1701 | /* Run one more char cycle */ |
1711 | msleep_interruptible(jiffies_to_msecs(char_time * 5)); | 1702 | msleep_interruptible(jiffies_to_msecs(char_time * 5)); |
1712 | unlock_kernel(); | ||
1713 | #ifdef CY_DEBUG_WAIT_UNTIL_SENT | 1703 | #ifdef CY_DEBUG_WAIT_UNTIL_SENT |
1714 | printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies); | 1704 | printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies); |
1715 | #endif | 1705 | #endif |
@@ -1966,7 +1956,6 @@ static int cy_chars_in_buffer(struct tty_struct *tty) | |||
1966 | int char_count; | 1956 | int char_count; |
1967 | __u32 tx_put, tx_get, tx_bufsize; | 1957 | __u32 tx_put, tx_get, tx_bufsize; |
1968 | 1958 | ||
1969 | lock_kernel(); | ||
1970 | tx_get = readl(&buf_ctrl->tx_get); | 1959 | tx_get = readl(&buf_ctrl->tx_get); |
1971 | tx_put = readl(&buf_ctrl->tx_put); | 1960 | tx_put = readl(&buf_ctrl->tx_put); |
1972 | tx_bufsize = readl(&buf_ctrl->tx_bufsize); | 1961 | tx_bufsize = readl(&buf_ctrl->tx_bufsize); |
@@ -1978,7 +1967,6 @@ static int cy_chars_in_buffer(struct tty_struct *tty) | |||
1978 | printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", | 1967 | printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", |
1979 | info->line, info->xmit_cnt + char_count); | 1968 | info->line, info->xmit_cnt + char_count); |
1980 | #endif | 1969 | #endif |
1981 | unlock_kernel(); | ||
1982 | return info->xmit_cnt + char_count; | 1970 | return info->xmit_cnt + char_count; |
1983 | } | 1971 | } |
1984 | #endif /* Z_EXT_CHARS_IN_BUFFER */ | 1972 | #endif /* Z_EXT_CHARS_IN_BUFFER */ |
@@ -2366,17 +2354,22 @@ cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty, | |||
2366 | struct serial_struct __user *new_info) | 2354 | struct serial_struct __user *new_info) |
2367 | { | 2355 | { |
2368 | struct serial_struct new_serial; | 2356 | struct serial_struct new_serial; |
2357 | int ret; | ||
2369 | 2358 | ||
2370 | if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) | 2359 | if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) |
2371 | return -EFAULT; | 2360 | return -EFAULT; |
2372 | 2361 | ||
2362 | mutex_lock(&info->port.mutex); | ||
2373 | if (!capable(CAP_SYS_ADMIN)) { | 2363 | if (!capable(CAP_SYS_ADMIN)) { |
2374 | if (new_serial.close_delay != info->port.close_delay || | 2364 | if (new_serial.close_delay != info->port.close_delay || |
2375 | new_serial.baud_base != info->baud || | 2365 | new_serial.baud_base != info->baud || |
2376 | (new_serial.flags & ASYNC_FLAGS & | 2366 | (new_serial.flags & ASYNC_FLAGS & |
2377 | ~ASYNC_USR_MASK) != | 2367 | ~ASYNC_USR_MASK) != |
2378 | (info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)) | 2368 | (info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)) |
2369 | { | ||
2370 | mutex_unlock(&info->port.mutex); | ||
2379 | return -EPERM; | 2371 | return -EPERM; |
2372 | } | ||
2380 | info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) | | 2373 | info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) | |
2381 | (new_serial.flags & ASYNC_USR_MASK); | 2374 | (new_serial.flags & ASYNC_USR_MASK); |
2382 | info->baud = new_serial.baud_base; | 2375 | info->baud = new_serial.baud_base; |
@@ -2399,10 +2392,12 @@ cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty, | |||
2399 | check_and_exit: | 2392 | check_and_exit: |
2400 | if (info->port.flags & ASYNC_INITIALIZED) { | 2393 | if (info->port.flags & ASYNC_INITIALIZED) { |
2401 | cy_set_line_char(info, tty); | 2394 | cy_set_line_char(info, tty); |
2402 | return 0; | 2395 | ret = 0; |
2403 | } else { | 2396 | } else { |
2404 | return cy_startup(info, tty); | 2397 | ret = cy_startup(info, tty); |
2405 | } | 2398 | } |
2399 | mutex_unlock(&info->port.mutex); | ||
2400 | return ret; | ||
2406 | } /* set_serial_info */ | 2401 | } /* set_serial_info */ |
2407 | 2402 | ||
2408 | /* | 2403 | /* |
@@ -2445,7 +2440,6 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) | |||
2445 | 2440 | ||
2446 | card = info->card; | 2441 | card = info->card; |
2447 | 2442 | ||
2448 | lock_kernel(); | ||
2449 | if (!cy_is_Z(card)) { | 2443 | if (!cy_is_Z(card)) { |
2450 | unsigned long flags; | 2444 | unsigned long flags; |
2451 | int channel = info->line - card->first_line; | 2445 | int channel = info->line - card->first_line; |
@@ -2485,7 +2479,6 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) | |||
2485 | ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0); | 2479 | ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0); |
2486 | } | 2480 | } |
2487 | end: | 2481 | end: |
2488 | unlock_kernel(); | ||
2489 | return result; | 2482 | return result; |
2490 | } /* cy_tiomget */ | 2483 | } /* cy_tiomget */ |
2491 | 2484 | ||
@@ -2703,7 +2696,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
2703 | printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", | 2696 | printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", |
2704 | info->line, cmd, arg); | 2697 | info->line, cmd, arg); |
2705 | #endif | 2698 | #endif |
2706 | lock_kernel(); | ||
2707 | 2699 | ||
2708 | switch (cmd) { | 2700 | switch (cmd) { |
2709 | case CYGETMON: | 2701 | case CYGETMON: |
@@ -2798,33 +2790,9 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
2798 | * NB: both 1->0 and 0->1 transitions are counted except for | 2790 | * NB: both 1->0 and 0->1 transitions are counted except for |
2799 | * RI where only 0->1 is counted. | 2791 | * RI where only 0->1 is counted. |
2800 | */ | 2792 | */ |
2801 | case TIOCGICOUNT: { | ||
2802 | struct serial_icounter_struct sic = { }; | ||
2803 | |||
2804 | spin_lock_irqsave(&info->card->card_lock, flags); | ||
2805 | cnow = info->icount; | ||
2806 | spin_unlock_irqrestore(&info->card->card_lock, flags); | ||
2807 | |||
2808 | sic.cts = cnow.cts; | ||
2809 | sic.dsr = cnow.dsr; | ||
2810 | sic.rng = cnow.rng; | ||
2811 | sic.dcd = cnow.dcd; | ||
2812 | sic.rx = cnow.rx; | ||
2813 | sic.tx = cnow.tx; | ||
2814 | sic.frame = cnow.frame; | ||
2815 | sic.overrun = cnow.overrun; | ||
2816 | sic.parity = cnow.parity; | ||
2817 | sic.brk = cnow.brk; | ||
2818 | sic.buf_overrun = cnow.buf_overrun; | ||
2819 | |||
2820 | if (copy_to_user(argp, &sic, sizeof(sic))) | ||
2821 | ret_val = -EFAULT; | ||
2822 | break; | ||
2823 | } | ||
2824 | default: | 2793 | default: |
2825 | ret_val = -ENOIOCTLCMD; | 2794 | ret_val = -ENOIOCTLCMD; |
2826 | } | 2795 | } |
2827 | unlock_kernel(); | ||
2828 | 2796 | ||
2829 | #ifdef CY_DEBUG_OTHER | 2797 | #ifdef CY_DEBUG_OTHER |
2830 | printk(KERN_DEBUG "cyc:cy_ioctl done\n"); | 2798 | printk(KERN_DEBUG "cyc:cy_ioctl done\n"); |
@@ -2832,6 +2800,31 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
2832 | return ret_val; | 2800 | return ret_val; |
2833 | } /* cy_ioctl */ | 2801 | } /* cy_ioctl */ |
2834 | 2802 | ||
2803 | static int cy_get_icount(struct tty_struct *tty, | ||
2804 | struct serial_icounter_struct *sic) | ||
2805 | { | ||
2806 | struct cyclades_port *info = tty->driver_data; | ||
2807 | struct cyclades_icount cnow; /* Used to snapshot */ | ||
2808 | unsigned long flags; | ||
2809 | |||
2810 | spin_lock_irqsave(&info->card->card_lock, flags); | ||
2811 | cnow = info->icount; | ||
2812 | spin_unlock_irqrestore(&info->card->card_lock, flags); | ||
2813 | |||
2814 | sic->cts = cnow.cts; | ||
2815 | sic->dsr = cnow.dsr; | ||
2816 | sic->rng = cnow.rng; | ||
2817 | sic->dcd = cnow.dcd; | ||
2818 | sic->rx = cnow.rx; | ||
2819 | sic->tx = cnow.tx; | ||
2820 | sic->frame = cnow.frame; | ||
2821 | sic->overrun = cnow.overrun; | ||
2822 | sic->parity = cnow.parity; | ||
2823 | sic->brk = cnow.brk; | ||
2824 | sic->buf_overrun = cnow.buf_overrun; | ||
2825 | return 0; | ||
2826 | } | ||
2827 | |||
2835 | /* | 2828 | /* |
2836 | * This routine allows the tty driver to be notified when | 2829 | * This routine allows the tty driver to be notified when |
2837 | * device's termios settings have changed. Note that a | 2830 | * device's termios settings have changed. Note that a |
@@ -3316,13 +3309,10 @@ static int __init cy_detect_isa(void) | |||
3316 | unsigned short cy_isa_irq, nboard; | 3309 | unsigned short cy_isa_irq, nboard; |
3317 | void __iomem *cy_isa_address; | 3310 | void __iomem *cy_isa_address; |
3318 | unsigned short i, j, cy_isa_nchan; | 3311 | unsigned short i, j, cy_isa_nchan; |
3319 | #ifdef MODULE | ||
3320 | int isparam = 0; | 3312 | int isparam = 0; |
3321 | #endif | ||
3322 | 3313 | ||
3323 | nboard = 0; | 3314 | nboard = 0; |
3324 | 3315 | ||
3325 | #ifdef MODULE | ||
3326 | /* Check for module parameters */ | 3316 | /* Check for module parameters */ |
3327 | for (i = 0; i < NR_CARDS; i++) { | 3317 | for (i = 0; i < NR_CARDS; i++) { |
3328 | if (maddr[i] || i) { | 3318 | if (maddr[i] || i) { |
@@ -3332,7 +3322,6 @@ static int __init cy_detect_isa(void) | |||
3332 | if (!maddr[i]) | 3322 | if (!maddr[i]) |
3333 | break; | 3323 | break; |
3334 | } | 3324 | } |
3335 | #endif | ||
3336 | 3325 | ||
3337 | /* scan the address table probing for Cyclom-Y/ISA boards */ | 3326 | /* scan the address table probing for Cyclom-Y/ISA boards */ |
3338 | for (i = 0; i < NR_ISA_ADDRS; i++) { | 3327 | for (i = 0; i < NR_ISA_ADDRS; i++) { |
@@ -3353,11 +3342,10 @@ static int __init cy_detect_isa(void) | |||
3353 | iounmap(cy_isa_address); | 3342 | iounmap(cy_isa_address); |
3354 | continue; | 3343 | continue; |
3355 | } | 3344 | } |
3356 | #ifdef MODULE | 3345 | |
3357 | if (isparam && i < NR_CARDS && irq[i]) | 3346 | if (isparam && i < NR_CARDS && irq[i]) |
3358 | cy_isa_irq = irq[i]; | 3347 | cy_isa_irq = irq[i]; |
3359 | else | 3348 | else |
3360 | #endif | ||
3361 | /* find out the board's irq by probing */ | 3349 | /* find out the board's irq by probing */ |
3362 | cy_isa_irq = detect_isa_irq(cy_isa_address); | 3350 | cy_isa_irq = detect_isa_irq(cy_isa_address); |
3363 | if (cy_isa_irq == 0) { | 3351 | if (cy_isa_irq == 0) { |
@@ -4098,6 +4086,7 @@ static const struct tty_operations cy_ops = { | |||
4098 | .wait_until_sent = cy_wait_until_sent, | 4086 | .wait_until_sent = cy_wait_until_sent, |
4099 | .tiocmget = cy_tiocmget, | 4087 | .tiocmget = cy_tiocmget, |
4100 | .tiocmset = cy_tiocmset, | 4088 | .tiocmset = cy_tiocmset, |
4089 | .get_icount = cy_get_icount, | ||
4101 | .proc_fops = &cyclades_proc_fops, | 4090 | .proc_fops = &cyclades_proc_fops, |
4102 | }; | 4091 | }; |
4103 | 4092 | ||
@@ -4208,3 +4197,4 @@ module_exit(cy_cleanup_module); | |||
4208 | MODULE_LICENSE("GPL"); | 4197 | MODULE_LICENSE("GPL"); |
4209 | MODULE_VERSION(CY_VERSION); | 4198 | MODULE_VERSION(CY_VERSION); |
4210 | MODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR); | 4199 | MODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR); |
4200 | MODULE_FIRMWARE("cyzfirm.bin"); | ||
diff --git a/drivers/char/ds1302.c b/drivers/char/ds1302.c index 170693c93c73..ed8303f9890c 100644 --- a/drivers/char/ds1302.c +++ b/drivers/char/ds1302.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <linux/miscdevice.h> | 20 | #include <linux/miscdevice.h> |
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/bcd.h> | 22 | #include <linux/bcd.h> |
23 | #include <linux/smp_lock.h> | 23 | #include <linux/mutex.h> |
24 | #include <linux/uaccess.h> | 24 | #include <linux/uaccess.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | 26 | ||
@@ -32,6 +32,7 @@ | |||
32 | 32 | ||
33 | #define RTC_MAJOR_NR 121 /* local major, change later */ | 33 | #define RTC_MAJOR_NR 121 /* local major, change later */ |
34 | 34 | ||
35 | static DEFINE_MUTEX(rtc_mutex); | ||
35 | static const char ds1302_name[] = "ds1302"; | 36 | static const char ds1302_name[] = "ds1302"; |
36 | 37 | ||
37 | /* Send 8 bits. */ | 38 | /* Send 8 bits. */ |
@@ -164,9 +165,9 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
164 | struct rtc_time rtc_tm; | 165 | struct rtc_time rtc_tm; |
165 | 166 | ||
166 | memset(&rtc_tm, 0, sizeof (struct rtc_time)); | 167 | memset(&rtc_tm, 0, sizeof (struct rtc_time)); |
167 | lock_kernel(); | 168 | mutex_lock(&rtc_mutex); |
168 | get_rtc_time(&rtc_tm); | 169 | get_rtc_time(&rtc_tm); |
169 | unlock_kernel(); | 170 | mutex_unlock(&rtc_mutex); |
170 | if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time))) | 171 | if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time))) |
171 | return -EFAULT; | 172 | return -EFAULT; |
172 | return 0; | 173 | return 0; |
@@ -218,7 +219,7 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
218 | mon = bin2bcd(mon); | 219 | mon = bin2bcd(mon); |
219 | yrs = bin2bcd(yrs); | 220 | yrs = bin2bcd(yrs); |
220 | 221 | ||
221 | lock_kernel(); | 222 | mutex_lock(&rtc_mutex); |
222 | local_irq_save(flags); | 223 | local_irq_save(flags); |
223 | CMOS_WRITE(yrs, RTC_YEAR); | 224 | CMOS_WRITE(yrs, RTC_YEAR); |
224 | CMOS_WRITE(mon, RTC_MONTH); | 225 | CMOS_WRITE(mon, RTC_MONTH); |
@@ -227,7 +228,7 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
227 | CMOS_WRITE(min, RTC_MINUTES); | 228 | CMOS_WRITE(min, RTC_MINUTES); |
228 | CMOS_WRITE(sec, RTC_SECONDS); | 229 | CMOS_WRITE(sec, RTC_SECONDS); |
229 | local_irq_restore(flags); | 230 | local_irq_restore(flags); |
230 | unlock_kernel(); | 231 | mutex_unlock(&rtc_mutex); |
231 | 232 | ||
232 | /* Notice that at this point, the RTC is updated but | 233 | /* Notice that at this point, the RTC is updated but |
233 | * the kernel is still running with the old time. | 234 | * the kernel is still running with the old time. |
@@ -247,10 +248,10 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
247 | if(copy_from_user(&tcs_val, (int*)arg, sizeof(int))) | 248 | if(copy_from_user(&tcs_val, (int*)arg, sizeof(int))) |
248 | return -EFAULT; | 249 | return -EFAULT; |
249 | 250 | ||
250 | lock_kernel(); | 251 | mutex_lock(&rtc_mutex); |
251 | tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F); | 252 | tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F); |
252 | ds1302_writereg(RTC_TRICKLECHARGER, tcs_val); | 253 | ds1302_writereg(RTC_TRICKLECHARGER, tcs_val); |
253 | unlock_kernel(); | 254 | mutex_unlock(&rtc_mutex); |
254 | return 0; | 255 | return 0; |
255 | } | 256 | } |
256 | default: | 257 | default: |
@@ -288,6 +289,7 @@ get_rtc_status(char *buf) | |||
288 | static const struct file_operations rtc_fops = { | 289 | static const struct file_operations rtc_fops = { |
289 | .owner = THIS_MODULE, | 290 | .owner = THIS_MODULE, |
290 | .unlocked_ioctl = rtc_ioctl, | 291 | .unlocked_ioctl = rtc_ioctl, |
292 | .llseek = noop_llseek, | ||
291 | }; | 293 | }; |
292 | 294 | ||
293 | /* Probe for the chip by writing something to its RAM and try reading it back. */ | 295 | /* Probe for the chip by writing something to its RAM and try reading it back. */ |
diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c index 61f0146e215d..aab9605f0b43 100644 --- a/drivers/char/ds1620.c +++ b/drivers/char/ds1620.c | |||
@@ -8,7 +8,7 @@ | |||
8 | #include <linux/proc_fs.h> | 8 | #include <linux/proc_fs.h> |
9 | #include <linux/capability.h> | 9 | #include <linux/capability.h> |
10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | #include <linux/smp_lock.h> | 11 | #include <linux/mutex.h> |
12 | 12 | ||
13 | #include <mach/hardware.h> | 13 | #include <mach/hardware.h> |
14 | #include <asm/mach-types.h> | 14 | #include <asm/mach-types.h> |
@@ -34,6 +34,7 @@ | |||
34 | #define CFG_CPU 2 | 34 | #define CFG_CPU 2 |
35 | #define CFG_1SHOT 1 | 35 | #define CFG_1SHOT 1 |
36 | 36 | ||
37 | static DEFINE_MUTEX(ds1620_mutex); | ||
37 | static const char *fan_state[] = { "off", "on", "on (hardwired)" }; | 38 | static const char *fan_state[] = { "off", "on", "on (hardwired)" }; |
38 | 39 | ||
39 | /* | 40 | /* |
@@ -210,7 +211,6 @@ static void ds1620_read_state(struct therm *therm) | |||
210 | 211 | ||
211 | static int ds1620_open(struct inode *inode, struct file *file) | 212 | static int ds1620_open(struct inode *inode, struct file *file) |
212 | { | 213 | { |
213 | cycle_kernel_lock(); | ||
214 | return nonseekable_open(inode, file); | 214 | return nonseekable_open(inode, file); |
215 | } | 215 | } |
216 | 216 | ||
@@ -232,7 +232,7 @@ ds1620_read(struct file *file, char __user *buf, size_t count, loff_t *ptr) | |||
232 | } | 232 | } |
233 | 233 | ||
234 | static int | 234 | static int |
235 | ds1620_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 235 | ds1620_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
236 | { | 236 | { |
237 | struct therm therm; | 237 | struct therm therm; |
238 | union { | 238 | union { |
@@ -316,6 +316,18 @@ ds1620_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned | |||
316 | return 0; | 316 | return 0; |
317 | } | 317 | } |
318 | 318 | ||
319 | static long | ||
320 | ds1620_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
321 | { | ||
322 | int ret; | ||
323 | |||
324 | mutex_lock(&ds1620_mutex); | ||
325 | ret = ds1620_ioctl(file, cmd, arg); | ||
326 | mutex_unlock(&ds1620_mutex); | ||
327 | |||
328 | return ret; | ||
329 | } | ||
330 | |||
319 | #ifdef THERM_USE_PROC | 331 | #ifdef THERM_USE_PROC |
320 | static int | 332 | static int |
321 | proc_therm_ds1620_read(char *buf, char **start, off_t offset, | 333 | proc_therm_ds1620_read(char *buf, char **start, off_t offset, |
@@ -344,7 +356,8 @@ static const struct file_operations ds1620_fops = { | |||
344 | .owner = THIS_MODULE, | 356 | .owner = THIS_MODULE, |
345 | .open = ds1620_open, | 357 | .open = ds1620_open, |
346 | .read = ds1620_read, | 358 | .read = ds1620_read, |
347 | .ioctl = ds1620_ioctl, | 359 | .unlocked_ioctl = ds1620_unlocked_ioctl, |
360 | .llseek = no_llseek, | ||
348 | }; | 361 | }; |
349 | 362 | ||
350 | static struct miscdevice ds1620_miscdev = { | 363 | static struct miscdevice ds1620_miscdev = { |
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index 85832ab924e6..052797b32bd3 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c | |||
@@ -24,7 +24,6 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/slab.h> /* for kmalloc() and kfree() */ | ||
28 | #include <linux/major.h> | 27 | #include <linux/major.h> |
29 | #include <linux/types.h> | 28 | #include <linux/types.h> |
30 | #include <linux/errno.h> | 29 | #include <linux/errno.h> |
@@ -33,7 +32,7 @@ | |||
33 | #include <linux/mm.h> | 32 | #include <linux/mm.h> |
34 | #include <linux/init.h> | 33 | #include <linux/init.h> |
35 | #include <linux/device.h> | 34 | #include <linux/device.h> |
36 | #include <linux/smp_lock.h> | 35 | #include <linux/mutex.h> |
37 | #include <linux/firmware.h> | 36 | #include <linux/firmware.h> |
38 | #include <linux/platform_device.h> | 37 | #include <linux/platform_device.h> |
39 | #include <linux/uaccess.h> /* For put_user and get_user */ | 38 | #include <linux/uaccess.h> /* For put_user and get_user */ |
@@ -95,6 +94,7 @@ | |||
95 | } \ | 94 | } \ |
96 | } | 95 | } |
97 | 96 | ||
97 | static DEFINE_MUTEX(dsp56k_mutex); | ||
98 | static struct dsp56k_device { | 98 | static struct dsp56k_device { |
99 | unsigned long in_use; | 99 | unsigned long in_use; |
100 | long maxio, timeout; | 100 | long maxio, timeout; |
@@ -331,9 +331,9 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd, | |||
331 | if (len > DSP56K_MAX_BINARY_LENGTH) { | 331 | if (len > DSP56K_MAX_BINARY_LENGTH) { |
332 | return -EINVAL; | 332 | return -EINVAL; |
333 | } | 333 | } |
334 | lock_kernel(); | 334 | mutex_lock(&dsp56k_mutex); |
335 | r = dsp56k_upload(bin, len); | 335 | r = dsp56k_upload(bin, len); |
336 | unlock_kernel(); | 336 | mutex_unlock(&dsp56k_mutex); |
337 | if (r < 0) { | 337 | if (r < 0) { |
338 | return r; | 338 | return r; |
339 | } | 339 | } |
@@ -343,16 +343,16 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd, | |||
343 | case DSP56K_SET_TX_WSIZE: | 343 | case DSP56K_SET_TX_WSIZE: |
344 | if (arg > 4 || arg < 1) | 344 | if (arg > 4 || arg < 1) |
345 | return -EINVAL; | 345 | return -EINVAL; |
346 | lock_kernel(); | 346 | mutex_lock(&dsp56k_mutex); |
347 | dsp56k.tx_wsize = (int) arg; | 347 | dsp56k.tx_wsize = (int) arg; |
348 | unlock_kernel(); | 348 | mutex_unlock(&dsp56k_mutex); |
349 | break; | 349 | break; |
350 | case DSP56K_SET_RX_WSIZE: | 350 | case DSP56K_SET_RX_WSIZE: |
351 | if (arg > 4 || arg < 1) | 351 | if (arg > 4 || arg < 1) |
352 | return -EINVAL; | 352 | return -EINVAL; |
353 | lock_kernel(); | 353 | mutex_lock(&dsp56k_mutex); |
354 | dsp56k.rx_wsize = (int) arg; | 354 | dsp56k.rx_wsize = (int) arg; |
355 | unlock_kernel(); | 355 | mutex_unlock(&dsp56k_mutex); |
356 | break; | 356 | break; |
357 | case DSP56K_HOST_FLAGS: | 357 | case DSP56K_HOST_FLAGS: |
358 | { | 358 | { |
@@ -364,7 +364,7 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd, | |||
364 | if(get_user(out, &hf->out) < 0) | 364 | if(get_user(out, &hf->out) < 0) |
365 | return -EFAULT; | 365 | return -EFAULT; |
366 | 366 | ||
367 | lock_kernel(); | 367 | mutex_lock(&dsp56k_mutex); |
368 | if ((dir & 0x1) && (out & 0x1)) | 368 | if ((dir & 0x1) && (out & 0x1)) |
369 | dsp56k_host_interface.icr |= DSP56K_ICR_HF0; | 369 | dsp56k_host_interface.icr |= DSP56K_ICR_HF0; |
370 | else if (dir & 0x1) | 370 | else if (dir & 0x1) |
@@ -379,16 +379,16 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd, | |||
379 | if (dsp56k_host_interface.icr & DSP56K_ICR_HF1) status |= 0x2; | 379 | if (dsp56k_host_interface.icr & DSP56K_ICR_HF1) status |= 0x2; |
380 | if (dsp56k_host_interface.isr & DSP56K_ISR_HF2) status |= 0x4; | 380 | if (dsp56k_host_interface.isr & DSP56K_ISR_HF2) status |= 0x4; |
381 | if (dsp56k_host_interface.isr & DSP56K_ISR_HF3) status |= 0x8; | 381 | if (dsp56k_host_interface.isr & DSP56K_ISR_HF3) status |= 0x8; |
382 | unlock_kernel(); | 382 | mutex_unlock(&dsp56k_mutex); |
383 | return put_user(status, &hf->status); | 383 | return put_user(status, &hf->status); |
384 | } | 384 | } |
385 | case DSP56K_HOST_CMD: | 385 | case DSP56K_HOST_CMD: |
386 | if (arg > 31 || arg < 0) | 386 | if (arg > 31 || arg < 0) |
387 | return -EINVAL; | 387 | return -EINVAL; |
388 | lock_kernel(); | 388 | mutex_lock(&dsp56k_mutex); |
389 | dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) | | 389 | dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) | |
390 | DSP56K_CVR_HC); | 390 | DSP56K_CVR_HC); |
391 | unlock_kernel(); | 391 | mutex_unlock(&dsp56k_mutex); |
392 | break; | 392 | break; |
393 | default: | 393 | default: |
394 | return -EINVAL; | 394 | return -EINVAL; |
@@ -428,7 +428,7 @@ static int dsp56k_open(struct inode *inode, struct file *file) | |||
428 | int dev = iminor(inode) & 0x0f; | 428 | int dev = iminor(inode) & 0x0f; |
429 | int ret = 0; | 429 | int ret = 0; |
430 | 430 | ||
431 | lock_kernel(); | 431 | mutex_lock(&dsp56k_mutex); |
432 | switch(dev) | 432 | switch(dev) |
433 | { | 433 | { |
434 | case DSP56K_DEV_56001: | 434 | case DSP56K_DEV_56001: |
@@ -455,7 +455,7 @@ static int dsp56k_open(struct inode *inode, struct file *file) | |||
455 | ret = -ENODEV; | 455 | ret = -ENODEV; |
456 | } | 456 | } |
457 | out: | 457 | out: |
458 | unlock_kernel(); | 458 | mutex_unlock(&dsp56k_mutex); |
459 | return ret; | 459 | return ret; |
460 | } | 460 | } |
461 | 461 | ||
@@ -483,6 +483,7 @@ static const struct file_operations dsp56k_fops = { | |||
483 | .unlocked_ioctl = dsp56k_ioctl, | 483 | .unlocked_ioctl = dsp56k_ioctl, |
484 | .open = dsp56k_open, | 484 | .open = dsp56k_open, |
485 | .release = dsp56k_release, | 485 | .release = dsp56k_release, |
486 | .llseek = noop_llseek, | ||
486 | }; | 487 | }; |
487 | 488 | ||
488 | 489 | ||
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c index 045c930e6320..85156dd0caee 100644 --- a/drivers/char/dtlk.c +++ b/drivers/char/dtlk.c | |||
@@ -57,7 +57,7 @@ | |||
57 | #include <linux/ioport.h> /* for request_region */ | 57 | #include <linux/ioport.h> /* for request_region */ |
58 | #include <linux/delay.h> /* for loops_per_jiffy */ | 58 | #include <linux/delay.h> /* for loops_per_jiffy */ |
59 | #include <linux/sched.h> | 59 | #include <linux/sched.h> |
60 | #include <linux/smp_lock.h> /* cycle_kernel_lock() */ | 60 | #include <linux/mutex.h> |
61 | #include <asm/io.h> /* for inb_p, outb_p, inb, outb, etc. */ | 61 | #include <asm/io.h> /* for inb_p, outb_p, inb, outb, etc. */ |
62 | #include <asm/uaccess.h> /* for get_user, etc. */ | 62 | #include <asm/uaccess.h> /* for get_user, etc. */ |
63 | #include <linux/wait.h> /* for wait_queue */ | 63 | #include <linux/wait.h> /* for wait_queue */ |
@@ -73,6 +73,7 @@ | |||
73 | #define TRACE_RET ((void) 0) | 73 | #define TRACE_RET ((void) 0) |
74 | #endif /* TRACING */ | 74 | #endif /* TRACING */ |
75 | 75 | ||
76 | static DEFINE_MUTEX(dtlk_mutex); | ||
76 | static void dtlk_timer_tick(unsigned long data); | 77 | static void dtlk_timer_tick(unsigned long data); |
77 | 78 | ||
78 | static int dtlk_major; | 79 | static int dtlk_major; |
@@ -93,8 +94,8 @@ static ssize_t dtlk_write(struct file *, const char __user *, | |||
93 | static unsigned int dtlk_poll(struct file *, poll_table *); | 94 | static unsigned int dtlk_poll(struct file *, poll_table *); |
94 | static int dtlk_open(struct inode *, struct file *); | 95 | static int dtlk_open(struct inode *, struct file *); |
95 | static int dtlk_release(struct inode *, struct file *); | 96 | static int dtlk_release(struct inode *, struct file *); |
96 | static int dtlk_ioctl(struct inode *inode, struct file *file, | 97 | static long dtlk_ioctl(struct file *file, |
97 | unsigned int cmd, unsigned long arg); | 98 | unsigned int cmd, unsigned long arg); |
98 | 99 | ||
99 | static const struct file_operations dtlk_fops = | 100 | static const struct file_operations dtlk_fops = |
100 | { | 101 | { |
@@ -102,9 +103,10 @@ static const struct file_operations dtlk_fops = | |||
102 | .read = dtlk_read, | 103 | .read = dtlk_read, |
103 | .write = dtlk_write, | 104 | .write = dtlk_write, |
104 | .poll = dtlk_poll, | 105 | .poll = dtlk_poll, |
105 | .ioctl = dtlk_ioctl, | 106 | .unlocked_ioctl = dtlk_ioctl, |
106 | .open = dtlk_open, | 107 | .open = dtlk_open, |
107 | .release = dtlk_release, | 108 | .release = dtlk_release, |
109 | .llseek = no_llseek, | ||
108 | }; | 110 | }; |
109 | 111 | ||
110 | /* local prototypes */ | 112 | /* local prototypes */ |
@@ -263,10 +265,9 @@ static void dtlk_timer_tick(unsigned long data) | |||
263 | wake_up_interruptible(&dtlk_process_list); | 265 | wake_up_interruptible(&dtlk_process_list); |
264 | } | 266 | } |
265 | 267 | ||
266 | static int dtlk_ioctl(struct inode *inode, | 268 | static long dtlk_ioctl(struct file *file, |
267 | struct file *file, | 269 | unsigned int cmd, |
268 | unsigned int cmd, | 270 | unsigned long arg) |
269 | unsigned long arg) | ||
270 | { | 271 | { |
271 | char __user *argp = (char __user *)arg; | 272 | char __user *argp = (char __user *)arg; |
272 | struct dtlk_settings *sp; | 273 | struct dtlk_settings *sp; |
@@ -276,7 +277,9 @@ static int dtlk_ioctl(struct inode *inode, | |||
276 | switch (cmd) { | 277 | switch (cmd) { |
277 | 278 | ||
278 | case DTLK_INTERROGATE: | 279 | case DTLK_INTERROGATE: |
280 | mutex_lock(&dtlk_mutex); | ||
279 | sp = dtlk_interrogate(); | 281 | sp = dtlk_interrogate(); |
282 | mutex_unlock(&dtlk_mutex); | ||
280 | if (copy_to_user(argp, sp, sizeof(struct dtlk_settings))) | 283 | if (copy_to_user(argp, sp, sizeof(struct dtlk_settings))) |
281 | return -EINVAL; | 284 | return -EINVAL; |
282 | return 0; | 285 | return 0; |
@@ -295,7 +298,6 @@ static int dtlk_open(struct inode *inode, struct file *file) | |||
295 | { | 298 | { |
296 | TRACE_TEXT("(dtlk_open"); | 299 | TRACE_TEXT("(dtlk_open"); |
297 | 300 | ||
298 | cycle_kernel_lock(); | ||
299 | nonseekable_open(inode, file); | 301 | nonseekable_open(inode, file); |
300 | switch (iminor(inode)) { | 302 | switch (iminor(inode)) { |
301 | case DTLK_MINOR: | 303 | case DTLK_MINOR: |
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 17b044a71e02..d9df46aa0fba 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/tty.h> | 37 | #include <linux/tty.h> |
38 | #include <linux/tty_flip.h> | 38 | #include <linux/tty_flip.h> |
39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
40 | #include <linux/smp_lock.h> | ||
41 | #include <linux/ioport.h> | 40 | #include <linux/ioport.h> |
42 | #include <linux/interrupt.h> | 41 | #include <linux/interrupt.h> |
43 | #include <linux/uaccess.h> | 42 | #include <linux/uaccess.h> |
@@ -2106,7 +2105,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file, | |||
2106 | break; | 2105 | break; |
2107 | case DIGI_SETAW: | 2106 | case DIGI_SETAW: |
2108 | case DIGI_SETAF: | 2107 | case DIGI_SETAF: |
2109 | lock_kernel(); | ||
2110 | if (cmd == DIGI_SETAW) { | 2108 | if (cmd == DIGI_SETAW) { |
2111 | /* Setup an event to indicate when the transmit | 2109 | /* Setup an event to indicate when the transmit |
2112 | buffer empties */ | 2110 | buffer empties */ |
@@ -2119,7 +2117,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file, | |||
2119 | if (tty->ldisc->ops->flush_buffer) | 2117 | if (tty->ldisc->ops->flush_buffer) |
2120 | tty->ldisc->ops->flush_buffer(tty); | 2118 | tty->ldisc->ops->flush_buffer(tty); |
2121 | } | 2119 | } |
2122 | unlock_kernel(); | ||
2123 | /* Fall Thru */ | 2120 | /* Fall Thru */ |
2124 | case DIGI_SETA: | 2121 | case DIGI_SETA: |
2125 | if (copy_from_user(&ch->digiext, argp, sizeof(digi_t))) | 2122 | if (copy_from_user(&ch->digiext, argp, sizeof(digi_t))) |
diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c index fda4181b5e67..0e941b57482e 100644 --- a/drivers/char/generic_nvram.c +++ b/drivers/char/generic_nvram.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/miscdevice.h> | 19 | #include <linux/miscdevice.h> |
20 | #include <linux/fcntl.h> | 20 | #include <linux/fcntl.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/mutex.h> | ||
22 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
23 | #include <asm/nvram.h> | 24 | #include <asm/nvram.h> |
24 | #ifdef CONFIG_PPC_PMAC | 25 | #ifdef CONFIG_PPC_PMAC |
@@ -27,6 +28,7 @@ | |||
27 | 28 | ||
28 | #define NVRAM_SIZE 8192 | 29 | #define NVRAM_SIZE 8192 |
29 | 30 | ||
31 | static DEFINE_MUTEX(nvram_mutex); | ||
30 | static ssize_t nvram_len; | 32 | static ssize_t nvram_len; |
31 | 33 | ||
32 | static loff_t nvram_llseek(struct file *file, loff_t offset, int origin) | 34 | static loff_t nvram_llseek(struct file *file, loff_t offset, int origin) |
@@ -84,8 +86,7 @@ static ssize_t write_nvram(struct file *file, const char __user *buf, | |||
84 | return p - buf; | 86 | return p - buf; |
85 | } | 87 | } |
86 | 88 | ||
87 | static int nvram_ioctl(struct inode *inode, struct file *file, | 89 | static int nvram_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
88 | unsigned int cmd, unsigned long arg) | ||
89 | { | 90 | { |
90 | switch(cmd) { | 91 | switch(cmd) { |
91 | #ifdef CONFIG_PPC_PMAC | 92 | #ifdef CONFIG_PPC_PMAC |
@@ -116,12 +117,23 @@ static int nvram_ioctl(struct inode *inode, struct file *file, | |||
116 | return 0; | 117 | return 0; |
117 | } | 118 | } |
118 | 119 | ||
120 | static long nvram_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
121 | { | ||
122 | int ret; | ||
123 | |||
124 | mutex_lock(&nvram_mutex); | ||
125 | ret = nvram_ioctl(file, cmd, arg); | ||
126 | mutex_unlock(&nvram_mutex); | ||
127 | |||
128 | return ret; | ||
129 | } | ||
130 | |||
119 | const struct file_operations nvram_fops = { | 131 | const struct file_operations nvram_fops = { |
120 | .owner = THIS_MODULE, | 132 | .owner = THIS_MODULE, |
121 | .llseek = nvram_llseek, | 133 | .llseek = nvram_llseek, |
122 | .read = read_nvram, | 134 | .read = read_nvram, |
123 | .write = write_nvram, | 135 | .write = write_nvram, |
124 | .ioctl = nvram_ioctl, | 136 | .unlocked_ioctl = nvram_unlocked_ioctl, |
125 | }; | 137 | }; |
126 | 138 | ||
127 | static struct miscdevice nvram_dev = { | 139 | static struct miscdevice nvram_dev = { |
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index d400cbd280f2..5954ee1dc953 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | #include <linux/tty_flip.h> | 30 | #include <linux/tty_flip.h> |
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/gfp.h> | ||
32 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
33 | 34 | ||
34 | #define DEBUG | 35 | #define DEBUG |
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c index 31e7c91c2d9d..f773a9dd14f3 100644 --- a/drivers/char/genrtc.c +++ b/drivers/char/genrtc.c | |||
@@ -52,7 +52,7 @@ | |||
52 | #include <linux/init.h> | 52 | #include <linux/init.h> |
53 | #include <linux/poll.h> | 53 | #include <linux/poll.h> |
54 | #include <linux/proc_fs.h> | 54 | #include <linux/proc_fs.h> |
55 | #include <linux/smp_lock.h> | 55 | #include <linux/mutex.h> |
56 | #include <linux/workqueue.h> | 56 | #include <linux/workqueue.h> |
57 | 57 | ||
58 | #include <asm/uaccess.h> | 58 | #include <asm/uaccess.h> |
@@ -66,6 +66,7 @@ | |||
66 | * ioctls. | 66 | * ioctls. |
67 | */ | 67 | */ |
68 | 68 | ||
69 | static DEFINE_MUTEX(gen_rtc_mutex); | ||
69 | static DECLARE_WAIT_QUEUE_HEAD(gen_rtc_wait); | 70 | static DECLARE_WAIT_QUEUE_HEAD(gen_rtc_wait); |
70 | 71 | ||
71 | /* | 72 | /* |
@@ -262,7 +263,7 @@ static inline int gen_set_rtc_irq_bit(unsigned char bit) | |||
262 | #endif | 263 | #endif |
263 | } | 264 | } |
264 | 265 | ||
265 | static int gen_rtc_ioctl(struct inode *inode, struct file *file, | 266 | static int gen_rtc_ioctl(struct file *file, |
266 | unsigned int cmd, unsigned long arg) | 267 | unsigned int cmd, unsigned long arg) |
267 | { | 268 | { |
268 | struct rtc_time wtime; | 269 | struct rtc_time wtime; |
@@ -332,6 +333,18 @@ static int gen_rtc_ioctl(struct inode *inode, struct file *file, | |||
332 | return -EINVAL; | 333 | return -EINVAL; |
333 | } | 334 | } |
334 | 335 | ||
336 | static long gen_rtc_unlocked_ioctl(struct file *file, unsigned int cmd, | ||
337 | unsigned long arg) | ||
338 | { | ||
339 | int ret; | ||
340 | |||
341 | mutex_lock(&gen_rtc_mutex); | ||
342 | ret = gen_rtc_ioctl(file, cmd, arg); | ||
343 | mutex_unlock(&gen_rtc_mutex); | ||
344 | |||
345 | return ret; | ||
346 | } | ||
347 | |||
335 | /* | 348 | /* |
336 | * We enforce only one user at a time here with the open/close. | 349 | * We enforce only one user at a time here with the open/close. |
337 | * Also clear the previous interrupt data on an open, and clean | 350 | * Also clear the previous interrupt data on an open, and clean |
@@ -340,16 +353,16 @@ static int gen_rtc_ioctl(struct inode *inode, struct file *file, | |||
340 | 353 | ||
341 | static int gen_rtc_open(struct inode *inode, struct file *file) | 354 | static int gen_rtc_open(struct inode *inode, struct file *file) |
342 | { | 355 | { |
343 | lock_kernel(); | 356 | mutex_lock(&gen_rtc_mutex); |
344 | if (gen_rtc_status & RTC_IS_OPEN) { | 357 | if (gen_rtc_status & RTC_IS_OPEN) { |
345 | unlock_kernel(); | 358 | mutex_unlock(&gen_rtc_mutex); |
346 | return -EBUSY; | 359 | return -EBUSY; |
347 | } | 360 | } |
348 | 361 | ||
349 | gen_rtc_status |= RTC_IS_OPEN; | 362 | gen_rtc_status |= RTC_IS_OPEN; |
350 | gen_rtc_irq_data = 0; | 363 | gen_rtc_irq_data = 0; |
351 | irq_active = 0; | 364 | irq_active = 0; |
352 | unlock_kernel(); | 365 | mutex_unlock(&gen_rtc_mutex); |
353 | 366 | ||
354 | return 0; | 367 | return 0; |
355 | } | 368 | } |
@@ -482,9 +495,10 @@ static const struct file_operations gen_rtc_fops = { | |||
482 | .read = gen_rtc_read, | 495 | .read = gen_rtc_read, |
483 | .poll = gen_rtc_poll, | 496 | .poll = gen_rtc_poll, |
484 | #endif | 497 | #endif |
485 | .ioctl = gen_rtc_ioctl, | 498 | .unlocked_ioctl = gen_rtc_unlocked_ioctl, |
486 | .open = gen_rtc_open, | 499 | .open = gen_rtc_open, |
487 | .release = gen_rtc_release, | 500 | .release = gen_rtc_release, |
501 | .llseek = noop_llseek, | ||
488 | }; | 502 | }; |
489 | 503 | ||
490 | static struct miscdevice rtc_gen_dev = | 504 | static struct miscdevice rtc_gen_dev = |
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c index 712d9f271aa6..f953c96efc86 100644 --- a/drivers/char/hangcheck-timer.c +++ b/drivers/char/hangcheck-timer.c | |||
@@ -49,8 +49,9 @@ | |||
49 | #include <asm/uaccess.h> | 49 | #include <asm/uaccess.h> |
50 | #include <linux/sysrq.h> | 50 | #include <linux/sysrq.h> |
51 | #include <linux/timer.h> | 51 | #include <linux/timer.h> |
52 | #include <linux/time.h> | ||
52 | 53 | ||
53 | #define VERSION_STR "0.9.0" | 54 | #define VERSION_STR "0.9.1" |
54 | 55 | ||
55 | #define DEFAULT_IOFENCE_MARGIN 60 /* Default fudge factor, in seconds */ | 56 | #define DEFAULT_IOFENCE_MARGIN 60 /* Default fudge factor, in seconds */ |
56 | #define DEFAULT_IOFENCE_TICK 180 /* Default timer timeout, in seconds */ | 57 | #define DEFAULT_IOFENCE_TICK 180 /* Default timer timeout, in seconds */ |
@@ -119,10 +120,8 @@ __setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks); | |||
119 | #if defined(CONFIG_S390) | 120 | #if defined(CONFIG_S390) |
120 | # define HAVE_MONOTONIC | 121 | # define HAVE_MONOTONIC |
121 | # define TIMER_FREQ 1000000000ULL | 122 | # define TIMER_FREQ 1000000000ULL |
122 | #elif defined(CONFIG_IA64) | ||
123 | # define TIMER_FREQ ((unsigned long long)local_cpu_data->itc_freq) | ||
124 | #else | 123 | #else |
125 | # define TIMER_FREQ (HZ*loops_per_jiffy) | 124 | # define TIMER_FREQ 1000000000ULL |
126 | #endif | 125 | #endif |
127 | 126 | ||
128 | #ifdef HAVE_MONOTONIC | 127 | #ifdef HAVE_MONOTONIC |
@@ -130,7 +129,9 @@ extern unsigned long long monotonic_clock(void); | |||
130 | #else | 129 | #else |
131 | static inline unsigned long long monotonic_clock(void) | 130 | static inline unsigned long long monotonic_clock(void) |
132 | { | 131 | { |
133 | return get_cycles(); | 132 | struct timespec ts; |
133 | getrawmonotonic(&ts); | ||
134 | return timespec_to_ns(&ts); | ||
134 | } | 135 | } |
135 | #endif /* HAVE_MONOTONIC */ | 136 | #endif /* HAVE_MONOTONIC */ |
136 | 137 | ||
@@ -158,7 +159,7 @@ static void hangcheck_fire(unsigned long data) | |||
158 | if (hangcheck_dump_tasks) { | 159 | if (hangcheck_dump_tasks) { |
159 | printk(KERN_CRIT "Hangcheck: Task state:\n"); | 160 | printk(KERN_CRIT "Hangcheck: Task state:\n"); |
160 | #ifdef CONFIG_MAGIC_SYSRQ | 161 | #ifdef CONFIG_MAGIC_SYSRQ |
161 | handle_sysrq('t', NULL); | 162 | handle_sysrq('t'); |
162 | #endif /* CONFIG_MAGIC_SYSRQ */ | 163 | #endif /* CONFIG_MAGIC_SYSRQ */ |
163 | } | 164 | } |
164 | if (hangcheck_reboot) { | 165 | if (hangcheck_reboot) { |
@@ -168,6 +169,13 @@ static void hangcheck_fire(unsigned long data) | |||
168 | printk(KERN_CRIT "Hangcheck: hangcheck value past margin!\n"); | 169 | printk(KERN_CRIT "Hangcheck: hangcheck value past margin!\n"); |
169 | } | 170 | } |
170 | } | 171 | } |
172 | #if 0 | ||
173 | /* | ||
174 | * Enable to investigate delays in detail | ||
175 | */ | ||
176 | printk("Hangcheck: called %Ld ns since last time (%Ld ns overshoot)\n", | ||
177 | tsc_diff, tsc_diff - hangcheck_tick*TIMER_FREQ); | ||
178 | #endif | ||
171 | mod_timer(&hangcheck_ticktock, jiffies + (hangcheck_tick*HZ)); | 179 | mod_timer(&hangcheck_ticktock, jiffies + (hangcheck_tick*HZ)); |
172 | hangcheck_tsc = monotonic_clock(); | 180 | hangcheck_tsc = monotonic_clock(); |
173 | } | 181 | } |
@@ -180,7 +188,7 @@ static int __init hangcheck_init(void) | |||
180 | #if defined (HAVE_MONOTONIC) | 188 | #if defined (HAVE_MONOTONIC) |
181 | printk("Hangcheck: Using monotonic_clock().\n"); | 189 | printk("Hangcheck: Using monotonic_clock().\n"); |
182 | #else | 190 | #else |
183 | printk("Hangcheck: Using get_cycles().\n"); | 191 | printk("Hangcheck: Using getrawmonotonic().\n"); |
184 | #endif /* HAVE_MONOTONIC */ | 192 | #endif /* HAVE_MONOTONIC */ |
185 | hangcheck_tsc_margin = | 193 | hangcheck_tsc_margin = |
186 | (unsigned long long)(hangcheck_margin + hangcheck_tick); | 194 | (unsigned long long)(hangcheck_margin + hangcheck_tick); |
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index e481c5938bad..55b8667f739f 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c | |||
@@ -30,12 +30,14 @@ | |||
30 | #include <linux/bcd.h> | 30 | #include <linux/bcd.h> |
31 | #include <linux/seq_file.h> | 31 | #include <linux/seq_file.h> |
32 | #include <linux/bitops.h> | 32 | #include <linux/bitops.h> |
33 | #include <linux/compat.h> | ||
33 | #include <linux/clocksource.h> | 34 | #include <linux/clocksource.h> |
35 | #include <linux/uaccess.h> | ||
36 | #include <linux/slab.h> | ||
37 | #include <linux/io.h> | ||
34 | 38 | ||
35 | #include <asm/current.h> | 39 | #include <asm/current.h> |
36 | #include <asm/uaccess.h> | ||
37 | #include <asm/system.h> | 40 | #include <asm/system.h> |
38 | #include <asm/io.h> | ||
39 | #include <asm/irq.h> | 41 | #include <asm/irq.h> |
40 | #include <asm/div64.h> | 42 | #include <asm/div64.h> |
41 | 43 | ||
@@ -66,6 +68,7 @@ | |||
66 | #define read_counter(MC) readl(MC) | 68 | #define read_counter(MC) readl(MC) |
67 | #endif | 69 | #endif |
68 | 70 | ||
71 | static DEFINE_MUTEX(hpet_mutex); /* replaces BKL */ | ||
69 | static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; | 72 | static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; |
70 | 73 | ||
71 | /* This clocksource driver currently only works on ia64 */ | 74 | /* This clocksource driver currently only works on ia64 */ |
@@ -78,13 +81,13 @@ static cycle_t read_hpet(struct clocksource *cs) | |||
78 | } | 81 | } |
79 | 82 | ||
80 | static struct clocksource clocksource_hpet = { | 83 | static struct clocksource clocksource_hpet = { |
81 | .name = "hpet", | 84 | .name = "hpet", |
82 | .rating = 250, | 85 | .rating = 250, |
83 | .read = read_hpet, | 86 | .read = read_hpet, |
84 | .mask = CLOCKSOURCE_MASK(64), | 87 | .mask = CLOCKSOURCE_MASK(64), |
85 | .mult = 0, /* to be calculated */ | 88 | .mult = 0, /* to be calculated */ |
86 | .shift = 10, | 89 | .shift = 10, |
87 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 90 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
88 | }; | 91 | }; |
89 | static struct clocksource *hpet_clocksource; | 92 | static struct clocksource *hpet_clocksource; |
90 | #endif | 93 | #endif |
@@ -215,9 +218,7 @@ static void hpet_timer_set_irq(struct hpet_dev *devp) | |||
215 | else | 218 | else |
216 | v &= ~0xffff; | 219 | v &= ~0xffff; |
217 | 220 | ||
218 | for (irq = find_first_bit(&v, HPET_MAX_IRQ); irq < HPET_MAX_IRQ; | 221 | for_each_set_bit(irq, &v, HPET_MAX_IRQ) { |
219 | irq = find_next_bit(&v, HPET_MAX_IRQ, 1 + irq)) { | ||
220 | |||
221 | if (irq >= nr_irqs) { | 222 | if (irq >= nr_irqs) { |
222 | irq = HPET_MAX_IRQ; | 223 | irq = HPET_MAX_IRQ; |
223 | break; | 224 | break; |
@@ -251,7 +252,7 @@ static int hpet_open(struct inode *inode, struct file *file) | |||
251 | if (file->f_mode & FMODE_WRITE) | 252 | if (file->f_mode & FMODE_WRITE) |
252 | return -EINVAL; | 253 | return -EINVAL; |
253 | 254 | ||
254 | lock_kernel(); | 255 | mutex_lock(&hpet_mutex); |
255 | spin_lock_irq(&hpet_lock); | 256 | spin_lock_irq(&hpet_lock); |
256 | 257 | ||
257 | for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next) | 258 | for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next) |
@@ -265,7 +266,7 @@ static int hpet_open(struct inode *inode, struct file *file) | |||
265 | 266 | ||
266 | if (!devp) { | 267 | if (!devp) { |
267 | spin_unlock_irq(&hpet_lock); | 268 | spin_unlock_irq(&hpet_lock); |
268 | unlock_kernel(); | 269 | mutex_unlock(&hpet_mutex); |
269 | return -EBUSY; | 270 | return -EBUSY; |
270 | } | 271 | } |
271 | 272 | ||
@@ -273,7 +274,7 @@ static int hpet_open(struct inode *inode, struct file *file) | |||
273 | devp->hd_irqdata = 0; | 274 | devp->hd_irqdata = 0; |
274 | devp->hd_flags |= HPET_OPEN; | 275 | devp->hd_flags |= HPET_OPEN; |
275 | spin_unlock_irq(&hpet_lock); | 276 | spin_unlock_irq(&hpet_lock); |
276 | unlock_kernel(); | 277 | mutex_unlock(&hpet_mutex); |
277 | 278 | ||
278 | hpet_timer_set_irq(devp); | 279 | hpet_timer_set_irq(devp); |
279 | 280 | ||
@@ -430,18 +431,6 @@ static int hpet_release(struct inode *inode, struct file *file) | |||
430 | return 0; | 431 | return 0; |
431 | } | 432 | } |
432 | 433 | ||
433 | static int hpet_ioctl_common(struct hpet_dev *, int, unsigned long, int); | ||
434 | |||
435 | static int | ||
436 | hpet_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
437 | unsigned long arg) | ||
438 | { | ||
439 | struct hpet_dev *devp; | ||
440 | |||
441 | devp = file->private_data; | ||
442 | return hpet_ioctl_common(devp, cmd, arg, 0); | ||
443 | } | ||
444 | |||
445 | static int hpet_ioctl_ieon(struct hpet_dev *devp) | 434 | static int hpet_ioctl_ieon(struct hpet_dev *devp) |
446 | { | 435 | { |
447 | struct hpet_timer __iomem *timer; | 436 | struct hpet_timer __iomem *timer; |
@@ -476,6 +465,21 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp) | |||
476 | if (irq) { | 465 | if (irq) { |
477 | unsigned long irq_flags; | 466 | unsigned long irq_flags; |
478 | 467 | ||
468 | if (devp->hd_flags & HPET_SHARED_IRQ) { | ||
469 | /* | ||
470 | * To prevent the interrupt handler from seeing an | ||
471 | * unwanted interrupt status bit, program the timer | ||
472 | * so that it will not fire in the near future ... | ||
473 | */ | ||
474 | writel(readl(&timer->hpet_config) & ~Tn_TYPE_CNF_MASK, | ||
475 | &timer->hpet_config); | ||
476 | write_counter(read_counter(&hpet->hpet_mc), | ||
477 | &timer->hpet_compare); | ||
478 | /* ... and clear any left-over status. */ | ||
479 | isr = 1 << (devp - devp->hd_hpets->hp_dev); | ||
480 | writel(isr, &hpet->hpet_isr); | ||
481 | } | ||
482 | |||
479 | sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev)); | 483 | sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev)); |
480 | irq_flags = devp->hd_flags & HPET_SHARED_IRQ | 484 | irq_flags = devp->hd_flags & HPET_SHARED_IRQ |
481 | ? IRQF_SHARED : IRQF_DISABLED; | 485 | ? IRQF_SHARED : IRQF_DISABLED; |
@@ -550,7 +554,8 @@ static inline unsigned long hpet_time_div(struct hpets *hpets, | |||
550 | } | 554 | } |
551 | 555 | ||
552 | static int | 556 | static int |
553 | hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel) | 557 | hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, |
558 | struct hpet_info *info) | ||
554 | { | 559 | { |
555 | struct hpet_timer __iomem *timer; | 560 | struct hpet_timer __iomem *timer; |
556 | struct hpet __iomem *hpet; | 561 | struct hpet __iomem *hpet; |
@@ -591,23 +596,14 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel) | |||
591 | break; | 596 | break; |
592 | case HPET_INFO: | 597 | case HPET_INFO: |
593 | { | 598 | { |
594 | struct hpet_info info; | 599 | memset(info, 0, sizeof(*info)); |
595 | |||
596 | if (devp->hd_ireqfreq) | 600 | if (devp->hd_ireqfreq) |
597 | info.hi_ireqfreq = | 601 | info->hi_ireqfreq = |
598 | hpet_time_div(hpetp, devp->hd_ireqfreq); | 602 | hpet_time_div(hpetp, devp->hd_ireqfreq); |
599 | else | 603 | info->hi_flags = |
600 | info.hi_ireqfreq = 0; | ||
601 | info.hi_flags = | ||
602 | readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK; | 604 | readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK; |
603 | info.hi_hpet = hpetp->hp_which; | 605 | info->hi_hpet = hpetp->hp_which; |
604 | info.hi_timer = devp - hpetp->hp_dev; | 606 | info->hi_timer = devp - hpetp->hp_dev; |
605 | if (kernel) | ||
606 | memcpy((void *)arg, &info, sizeof(info)); | ||
607 | else | ||
608 | if (copy_to_user((void __user *)arg, &info, | ||
609 | sizeof(info))) | ||
610 | err = -EFAULT; | ||
611 | break; | 607 | break; |
612 | } | 608 | } |
613 | case HPET_EPI: | 609 | case HPET_EPI: |
@@ -633,7 +629,7 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel) | |||
633 | devp->hd_flags &= ~HPET_PERIODIC; | 629 | devp->hd_flags &= ~HPET_PERIODIC; |
634 | break; | 630 | break; |
635 | case HPET_IRQFREQ: | 631 | case HPET_IRQFREQ: |
636 | if (!kernel && (arg > hpet_max_freq) && | 632 | if ((arg > hpet_max_freq) && |
637 | !capable(CAP_SYS_RESOURCE)) { | 633 | !capable(CAP_SYS_RESOURCE)) { |
638 | err = -EACCES; | 634 | err = -EACCES; |
639 | break; | 635 | break; |
@@ -650,12 +646,63 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel) | |||
650 | return err; | 646 | return err; |
651 | } | 647 | } |
652 | 648 | ||
649 | static long | ||
650 | hpet_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
651 | { | ||
652 | struct hpet_info info; | ||
653 | int err; | ||
654 | |||
655 | mutex_lock(&hpet_mutex); | ||
656 | err = hpet_ioctl_common(file->private_data, cmd, arg, &info); | ||
657 | mutex_unlock(&hpet_mutex); | ||
658 | |||
659 | if ((cmd == HPET_INFO) && !err && | ||
660 | (copy_to_user((void __user *)arg, &info, sizeof(info)))) | ||
661 | err = -EFAULT; | ||
662 | |||
663 | return err; | ||
664 | } | ||
665 | |||
666 | #ifdef CONFIG_COMPAT | ||
667 | struct compat_hpet_info { | ||
668 | compat_ulong_t hi_ireqfreq; /* Hz */ | ||
669 | compat_ulong_t hi_flags; /* information */ | ||
670 | unsigned short hi_hpet; | ||
671 | unsigned short hi_timer; | ||
672 | }; | ||
673 | |||
674 | static long | ||
675 | hpet_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
676 | { | ||
677 | struct hpet_info info; | ||
678 | int err; | ||
679 | |||
680 | mutex_lock(&hpet_mutex); | ||
681 | err = hpet_ioctl_common(file->private_data, cmd, arg, &info); | ||
682 | mutex_unlock(&hpet_mutex); | ||
683 | |||
684 | if ((cmd == HPET_INFO) && !err) { | ||
685 | struct compat_hpet_info __user *u = compat_ptr(arg); | ||
686 | if (put_user(info.hi_ireqfreq, &u->hi_ireqfreq) || | ||
687 | put_user(info.hi_flags, &u->hi_flags) || | ||
688 | put_user(info.hi_hpet, &u->hi_hpet) || | ||
689 | put_user(info.hi_timer, &u->hi_timer)) | ||
690 | err = -EFAULT; | ||
691 | } | ||
692 | |||
693 | return err; | ||
694 | } | ||
695 | #endif | ||
696 | |||
653 | static const struct file_operations hpet_fops = { | 697 | static const struct file_operations hpet_fops = { |
654 | .owner = THIS_MODULE, | 698 | .owner = THIS_MODULE, |
655 | .llseek = no_llseek, | 699 | .llseek = no_llseek, |
656 | .read = hpet_read, | 700 | .read = hpet_read, |
657 | .poll = hpet_poll, | 701 | .poll = hpet_poll, |
658 | .ioctl = hpet_ioctl, | 702 | .unlocked_ioctl = hpet_ioctl, |
703 | #ifdef CONFIG_COMPAT | ||
704 | .compat_ioctl = hpet_compat_ioctl, | ||
705 | #endif | ||
659 | .open = hpet_open, | 706 | .open = hpet_open, |
660 | .release = hpet_release, | 707 | .release = hpet_release, |
661 | .fasync = hpet_fasync, | 708 | .fasync = hpet_fasync, |
@@ -778,7 +825,7 @@ int hpet_alloc(struct hpet_data *hdp) | |||
778 | struct hpets *hpetp; | 825 | struct hpets *hpetp; |
779 | size_t siz; | 826 | size_t siz; |
780 | struct hpet __iomem *hpet; | 827 | struct hpet __iomem *hpet; |
781 | static struct hpets *last = NULL; | 828 | static struct hpets *last; |
782 | unsigned long period; | 829 | unsigned long period; |
783 | unsigned long long temp; | 830 | unsigned long long temp; |
784 | u32 remainder; | 831 | u32 remainder; |
@@ -967,6 +1014,8 @@ static int hpet_acpi_add(struct acpi_device *device) | |||
967 | return -ENODEV; | 1014 | return -ENODEV; |
968 | 1015 | ||
969 | if (!data.hd_address || !data.hd_nirqs) { | 1016 | if (!data.hd_address || !data.hd_nirqs) { |
1017 | if (data.hd_address) | ||
1018 | iounmap(data.hd_address); | ||
970 | printk("%s: no address or irqs in _CRS\n", __func__); | 1019 | printk("%s: no address or irqs in _CRS\n", __func__); |
971 | return -ENODEV; | 1020 | return -ENODEV; |
972 | } | 1021 | } |
diff --git a/drivers/char/hvc_beat.c b/drivers/char/hvc_beat.c index 0afc8b82212e..5fe4631e2a61 100644 --- a/drivers/char/hvc_beat.c +++ b/drivers/char/hvc_beat.c | |||
@@ -84,7 +84,7 @@ static int hvc_beat_put_chars(uint32_t vtermno, const char *buf, int cnt) | |||
84 | return cnt; | 84 | return cnt; |
85 | } | 85 | } |
86 | 86 | ||
87 | static struct hv_ops hvc_beat_get_put_ops = { | 87 | static const struct hv_ops hvc_beat_get_put_ops = { |
88 | .get_chars = hvc_beat_get_chars, | 88 | .get_chars = hvc_beat_get_chars, |
89 | .put_chars = hvc_beat_put_chars, | 89 | .put_chars = hvc_beat_put_chars, |
90 | }; | 90 | }; |
@@ -99,7 +99,7 @@ static int hvc_beat_config(char *p) | |||
99 | 99 | ||
100 | static int __init hvc_beat_console_init(void) | 100 | static int __init hvc_beat_console_init(void) |
101 | { | 101 | { |
102 | if (hvc_beat_useit && machine_is_compatible("Beat")) { | 102 | if (hvc_beat_useit && of_machine_is_compatible("Beat")) { |
103 | hvc_instantiate(0, 0, &hvc_beat_get_put_ops); | 103 | hvc_instantiate(0, 0, &hvc_beat_get_put_ops); |
104 | } | 104 | } |
105 | return 0; | 105 | return 0; |
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 416d3423150d..e9cba13ee800 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/spinlock.h> | 38 | #include <linux/spinlock.h> |
39 | #include <linux/delay.h> | 39 | #include <linux/delay.h> |
40 | #include <linux/freezer.h> | 40 | #include <linux/freezer.h> |
41 | #include <linux/slab.h> | ||
41 | 42 | ||
42 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
43 | 44 | ||
@@ -125,7 +126,7 @@ static struct hvc_struct *hvc_get_by_index(int index) | |||
125 | * console interfaces but can still be used as a tty device. This has to be | 126 | * console interfaces but can still be used as a tty device. This has to be |
126 | * static because kmalloc will not work during early console init. | 127 | * static because kmalloc will not work during early console init. |
127 | */ | 128 | */ |
128 | static struct hv_ops *cons_ops[MAX_NR_HVC_CONSOLES]; | 129 | static const struct hv_ops *cons_ops[MAX_NR_HVC_CONSOLES]; |
129 | static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] = | 130 | static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] = |
130 | {[0 ... MAX_NR_HVC_CONSOLES - 1] = -1}; | 131 | {[0 ... MAX_NR_HVC_CONSOLES - 1] = -1}; |
131 | 132 | ||
@@ -146,7 +147,7 @@ static void hvc_console_print(struct console *co, const char *b, | |||
146 | return; | 147 | return; |
147 | 148 | ||
148 | /* This console adapter was removed so it is not usable. */ | 149 | /* This console adapter was removed so it is not usable. */ |
149 | if (vtermnos[index] < 0) | 150 | if (vtermnos[index] == -1) |
150 | return; | 151 | return; |
151 | 152 | ||
152 | while (count > 0 || i > 0) { | 153 | while (count > 0 || i > 0) { |
@@ -193,7 +194,7 @@ static int __init hvc_console_setup(struct console *co, char *options) | |||
193 | return 0; | 194 | return 0; |
194 | } | 195 | } |
195 | 196 | ||
196 | static struct console hvc_con_driver = { | 197 | static struct console hvc_console = { |
197 | .name = "hvc", | 198 | .name = "hvc", |
198 | .write = hvc_console_print, | 199 | .write = hvc_console_print, |
199 | .device = hvc_console_device, | 200 | .device = hvc_console_device, |
@@ -219,7 +220,7 @@ static struct console hvc_con_driver = { | |||
219 | */ | 220 | */ |
220 | static int __init hvc_console_init(void) | 221 | static int __init hvc_console_init(void) |
221 | { | 222 | { |
222 | register_console(&hvc_con_driver); | 223 | register_console(&hvc_console); |
223 | return 0; | 224 | return 0; |
224 | } | 225 | } |
225 | console_initcall(hvc_console_init); | 226 | console_initcall(hvc_console_init); |
@@ -247,7 +248,7 @@ static void destroy_hvc_struct(struct kref *kref) | |||
247 | * vty adapters do NOT get an hvc_instantiate() callback since they | 248 | * vty adapters do NOT get an hvc_instantiate() callback since they |
248 | * appear after early console init. | 249 | * appear after early console init. |
249 | */ | 250 | */ |
250 | int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops) | 251 | int hvc_instantiate(uint32_t vtermno, int index, const struct hv_ops *ops) |
251 | { | 252 | { |
252 | struct hvc_struct *hp; | 253 | struct hvc_struct *hp; |
253 | 254 | ||
@@ -275,8 +276,8 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops) | |||
275 | * now (setup won't fail at this point). It's ok to just | 276 | * now (setup won't fail at this point). It's ok to just |
276 | * call register again if previously .setup failed. | 277 | * call register again if previously .setup failed. |
277 | */ | 278 | */ |
278 | if (index == hvc_con_driver.index) | 279 | if (index == hvc_console.index) |
279 | register_console(&hvc_con_driver); | 280 | register_console(&hvc_console); |
280 | 281 | ||
281 | return 0; | 282 | return 0; |
282 | } | 283 | } |
@@ -312,6 +313,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) | |||
312 | spin_lock_irqsave(&hp->lock, flags); | 313 | spin_lock_irqsave(&hp->lock, flags); |
313 | /* Check and then increment for fast path open. */ | 314 | /* Check and then increment for fast path open. */ |
314 | if (hp->count++ > 0) { | 315 | if (hp->count++ > 0) { |
316 | tty_kref_get(tty); | ||
315 | spin_unlock_irqrestore(&hp->lock, flags); | 317 | spin_unlock_irqrestore(&hp->lock, flags); |
316 | hvc_kick(); | 318 | hvc_kick(); |
317 | return 0; | 319 | return 0; |
@@ -319,7 +321,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) | |||
319 | 321 | ||
320 | tty->driver_data = hp; | 322 | tty->driver_data = hp; |
321 | 323 | ||
322 | hp->tty = tty; | 324 | hp->tty = tty_kref_get(tty); |
323 | 325 | ||
324 | spin_unlock_irqrestore(&hp->lock, flags); | 326 | spin_unlock_irqrestore(&hp->lock, flags); |
325 | 327 | ||
@@ -336,6 +338,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) | |||
336 | spin_lock_irqsave(&hp->lock, flags); | 338 | spin_lock_irqsave(&hp->lock, flags); |
337 | hp->tty = NULL; | 339 | hp->tty = NULL; |
338 | spin_unlock_irqrestore(&hp->lock, flags); | 340 | spin_unlock_irqrestore(&hp->lock, flags); |
341 | tty_kref_put(tty); | ||
339 | tty->driver_data = NULL; | 342 | tty->driver_data = NULL; |
340 | kref_put(&hp->kref, destroy_hvc_struct); | 343 | kref_put(&hp->kref, destroy_hvc_struct); |
341 | printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc); | 344 | printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc); |
@@ -363,6 +366,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) | |||
363 | return; | 366 | return; |
364 | 367 | ||
365 | hp = tty->driver_data; | 368 | hp = tty->driver_data; |
369 | |||
366 | spin_lock_irqsave(&hp->lock, flags); | 370 | spin_lock_irqsave(&hp->lock, flags); |
367 | 371 | ||
368 | if (--hp->count == 0) { | 372 | if (--hp->count == 0) { |
@@ -389,6 +393,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) | |||
389 | spin_unlock_irqrestore(&hp->lock, flags); | 393 | spin_unlock_irqrestore(&hp->lock, flags); |
390 | } | 394 | } |
391 | 395 | ||
396 | tty_kref_put(tty); | ||
392 | kref_put(&hp->kref, destroy_hvc_struct); | 397 | kref_put(&hp->kref, destroy_hvc_struct); |
393 | } | 398 | } |
394 | 399 | ||
@@ -424,10 +429,11 @@ static void hvc_hangup(struct tty_struct *tty) | |||
424 | spin_unlock_irqrestore(&hp->lock, flags); | 429 | spin_unlock_irqrestore(&hp->lock, flags); |
425 | 430 | ||
426 | if (hp->ops->notifier_hangup) | 431 | if (hp->ops->notifier_hangup) |
427 | hp->ops->notifier_hangup(hp, hp->data); | 432 | hp->ops->notifier_hangup(hp, hp->data); |
428 | 433 | ||
429 | while(temp_open_count) { | 434 | while(temp_open_count) { |
430 | --temp_open_count; | 435 | --temp_open_count; |
436 | tty_kref_put(tty); | ||
431 | kref_put(&hp->kref, destroy_hvc_struct); | 437 | kref_put(&hp->kref, destroy_hvc_struct); |
432 | } | 438 | } |
433 | } | 439 | } |
@@ -592,7 +598,7 @@ int hvc_poll(struct hvc_struct *hp) | |||
592 | } | 598 | } |
593 | 599 | ||
594 | /* No tty attached, just skip */ | 600 | /* No tty attached, just skip */ |
595 | tty = hp->tty; | 601 | tty = tty_kref_get(hp->tty); |
596 | if (tty == NULL) | 602 | if (tty == NULL) |
597 | goto bail; | 603 | goto bail; |
598 | 604 | ||
@@ -635,7 +641,7 @@ int hvc_poll(struct hvc_struct *hp) | |||
635 | } | 641 | } |
636 | for (i = 0; i < n; ++i) { | 642 | for (i = 0; i < n; ++i) { |
637 | #ifdef CONFIG_MAGIC_SYSRQ | 643 | #ifdef CONFIG_MAGIC_SYSRQ |
638 | if (hp->index == hvc_con_driver.index) { | 644 | if (hp->index == hvc_console.index) { |
639 | /* Handle the SysRq Hack */ | 645 | /* Handle the SysRq Hack */ |
640 | /* XXX should support a sequence */ | 646 | /* XXX should support a sequence */ |
641 | if (buf[i] == '\x0f') { /* ^O */ | 647 | if (buf[i] == '\x0f') { /* ^O */ |
@@ -645,7 +651,7 @@ int hvc_poll(struct hvc_struct *hp) | |||
645 | if (sysrq_pressed) | 651 | if (sysrq_pressed) |
646 | continue; | 652 | continue; |
647 | } else if (sysrq_pressed) { | 653 | } else if (sysrq_pressed) { |
648 | handle_sysrq(buf[i], tty); | 654 | handle_sysrq(buf[i]); |
649 | sysrq_pressed = 0; | 655 | sysrq_pressed = 0; |
650 | continue; | 656 | continue; |
651 | } | 657 | } |
@@ -672,6 +678,8 @@ int hvc_poll(struct hvc_struct *hp) | |||
672 | 678 | ||
673 | tty_flip_buffer_push(tty); | 679 | tty_flip_buffer_push(tty); |
674 | } | 680 | } |
681 | if (tty) | ||
682 | tty_kref_put(tty); | ||
675 | 683 | ||
676 | return poll_mask; | 684 | return poll_mask; |
677 | } | 685 | } |
@@ -705,7 +713,6 @@ static int khvcd(void *unused) | |||
705 | struct hvc_struct *hp; | 713 | struct hvc_struct *hp; |
706 | 714 | ||
707 | set_freezable(); | 715 | set_freezable(); |
708 | __set_current_state(TASK_RUNNING); | ||
709 | do { | 716 | do { |
710 | poll_mask = 0; | 717 | poll_mask = 0; |
711 | hvc_kicked = 0; | 718 | hvc_kicked = 0; |
@@ -748,8 +755,9 @@ static const struct tty_operations hvc_ops = { | |||
748 | .chars_in_buffer = hvc_chars_in_buffer, | 755 | .chars_in_buffer = hvc_chars_in_buffer, |
749 | }; | 756 | }; |
750 | 757 | ||
751 | struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int data, | 758 | struct hvc_struct *hvc_alloc(uint32_t vtermno, int data, |
752 | struct hv_ops *ops, int outbuf_size) | 759 | const struct hv_ops *ops, |
760 | int outbuf_size) | ||
753 | { | 761 | { |
754 | struct hvc_struct *hp; | 762 | struct hvc_struct *hp; |
755 | int i; | 763 | int i; |
@@ -806,7 +814,7 @@ int hvc_remove(struct hvc_struct *hp) | |||
806 | struct tty_struct *tty; | 814 | struct tty_struct *tty; |
807 | 815 | ||
808 | spin_lock_irqsave(&hp->lock, flags); | 816 | spin_lock_irqsave(&hp->lock, flags); |
809 | tty = hp->tty; | 817 | tty = tty_kref_get(hp->tty); |
810 | 818 | ||
811 | if (hp->index < MAX_NR_HVC_CONSOLES) | 819 | if (hp->index < MAX_NR_HVC_CONSOLES) |
812 | vtermnos[hp->index] = -1; | 820 | vtermnos[hp->index] = -1; |
@@ -818,18 +826,18 @@ int hvc_remove(struct hvc_struct *hp) | |||
818 | /* | 826 | /* |
819 | * We 'put' the instance that was grabbed when the kref instance | 827 | * We 'put' the instance that was grabbed when the kref instance |
820 | * was initialized using kref_init(). Let the last holder of this | 828 | * was initialized using kref_init(). Let the last holder of this |
821 | * kref cause it to be removed, which will probably be the tty_hangup | 829 | * kref cause it to be removed, which will probably be the tty_vhangup |
822 | * below. | 830 | * below. |
823 | */ | 831 | */ |
824 | kref_put(&hp->kref, destroy_hvc_struct); | 832 | kref_put(&hp->kref, destroy_hvc_struct); |
825 | 833 | ||
826 | /* | 834 | /* |
827 | * This function call will auto chain call hvc_hangup. The tty should | 835 | * This function call will auto chain call hvc_hangup. |
828 | * always be valid at this time unless a simultaneous tty close already | ||
829 | * cleaned up the hvc_struct. | ||
830 | */ | 836 | */ |
831 | if (tty) | 837 | if (tty) { |
832 | tty_hangup(tty); | 838 | tty_vhangup(tty); |
839 | tty_kref_put(tty); | ||
840 | } | ||
833 | return 0; | 841 | return 0; |
834 | } | 842 | } |
835 | EXPORT_SYMBOL_GPL(hvc_remove); | 843 | EXPORT_SYMBOL_GPL(hvc_remove); |
@@ -900,7 +908,7 @@ static void __exit hvc_exit(void) | |||
900 | tty_unregister_driver(hvc_driver); | 908 | tty_unregister_driver(hvc_driver); |
901 | /* return tty_struct instances allocated in hvc_init(). */ | 909 | /* return tty_struct instances allocated in hvc_init(). */ |
902 | put_tty_driver(hvc_driver); | 910 | put_tty_driver(hvc_driver); |
903 | unregister_console(&hvc_con_driver); | 911 | unregister_console(&hvc_console); |
904 | } | 912 | } |
905 | } | 913 | } |
906 | module_exit(hvc_exit); | 914 | module_exit(hvc_exit); |
diff --git a/drivers/char/hvc_console.h b/drivers/char/hvc_console.h index 10950ca706d8..54381eba4e4a 100644 --- a/drivers/char/hvc_console.h +++ b/drivers/char/hvc_console.h | |||
@@ -55,7 +55,7 @@ struct hvc_struct { | |||
55 | int outbuf_size; | 55 | int outbuf_size; |
56 | int n_outbuf; | 56 | int n_outbuf; |
57 | uint32_t vtermno; | 57 | uint32_t vtermno; |
58 | struct hv_ops *ops; | 58 | const struct hv_ops *ops; |
59 | int irq_requested; | 59 | int irq_requested; |
60 | int data; | 60 | int data; |
61 | struct winsize ws; | 61 | struct winsize ws; |
@@ -76,11 +76,12 @@ struct hv_ops { | |||
76 | }; | 76 | }; |
77 | 77 | ||
78 | /* Register a vterm and a slot index for use as a console (console_init) */ | 78 | /* Register a vterm and a slot index for use as a console (console_init) */ |
79 | extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops); | 79 | extern int hvc_instantiate(uint32_t vtermno, int index, |
80 | const struct hv_ops *ops); | ||
80 | 81 | ||
81 | /* register a vterm for hvc tty operation (module_init or hotplug add) */ | 82 | /* register a vterm for hvc tty operation (module_init or hotplug add) */ |
82 | extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int data, | 83 | extern struct hvc_struct * hvc_alloc(uint32_t vtermno, int data, |
83 | struct hv_ops *ops, int outbuf_size); | 84 | const struct hv_ops *ops, int outbuf_size); |
84 | /* remove a vterm from hvc tty operation (module_exit or hotplug remove) */ | 85 | /* remove a vterm from hvc tty operation (module_exit or hotplug remove) */ |
85 | extern int hvc_remove(struct hvc_struct *hp); | 86 | extern int hvc_remove(struct hvc_struct *hp); |
86 | 87 | ||
diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c index 936d05bf37fa..21c54955084e 100644 --- a/drivers/char/hvc_iseries.c +++ b/drivers/char/hvc_iseries.c | |||
@@ -197,7 +197,7 @@ done: | |||
197 | return sent; | 197 | return sent; |
198 | } | 198 | } |
199 | 199 | ||
200 | static struct hv_ops hvc_get_put_ops = { | 200 | static const struct hv_ops hvc_get_put_ops = { |
201 | .get_chars = get_chars, | 201 | .get_chars = get_chars, |
202 | .put_chars = put_chars, | 202 | .put_chars = put_chars, |
203 | .notifier_add = notifier_add_irq, | 203 | .notifier_add = notifier_add_irq, |
@@ -353,7 +353,7 @@ static void hvc_close_event(struct HvLpEvent *event) | |||
353 | 353 | ||
354 | if (!hvlpevent_is_int(event)) { | 354 | if (!hvlpevent_is_int(event)) { |
355 | printk(KERN_WARNING | 355 | printk(KERN_WARNING |
356 | "hvc: got unexpected close acknowlegement\n"); | 356 | "hvc: got unexpected close acknowledgement\n"); |
357 | return; | 357 | return; |
358 | } | 358 | } |
359 | 359 | ||
diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c index fe62bd0e17b7..c3425bb3a1f6 100644 --- a/drivers/char/hvc_iucv.c +++ b/drivers/char/hvc_iucv.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 12 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
13 | 13 | ||
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <linux/slab.h> | ||
15 | #include <asm/ebcdic.h> | 16 | #include <asm/ebcdic.h> |
16 | #include <linux/ctype.h> | 17 | #include <linux/ctype.h> |
17 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
@@ -139,6 +140,8 @@ struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num) | |||
139 | * | 140 | * |
140 | * This function allocates a new struct iucv_tty_buffer element and, optionally, | 141 | * This function allocates a new struct iucv_tty_buffer element and, optionally, |
141 | * allocates an internal data buffer with the specified size @size. | 142 | * allocates an internal data buffer with the specified size @size. |
143 | * The internal data buffer is always allocated with GFP_DMA which is | ||
144 | * required for receiving and sending data with IUCV. | ||
142 | * Note: The total message size arises from the internal buffer size and the | 145 | * Note: The total message size arises from the internal buffer size and the |
143 | * members of the iucv_tty_msg structure. | 146 | * members of the iucv_tty_msg structure. |
144 | * The function returns NULL if memory allocation has failed. | 147 | * The function returns NULL if memory allocation has failed. |
@@ -154,7 +157,7 @@ static struct iucv_tty_buffer *alloc_tty_buffer(size_t size, gfp_t flags) | |||
154 | 157 | ||
155 | if (size > 0) { | 158 | if (size > 0) { |
156 | bufp->msg.length = MSG_SIZE(size); | 159 | bufp->msg.length = MSG_SIZE(size); |
157 | bufp->mbuf = kmalloc(bufp->msg.length, flags); | 160 | bufp->mbuf = kmalloc(bufp->msg.length, flags | GFP_DMA); |
158 | if (!bufp->mbuf) { | 161 | if (!bufp->mbuf) { |
159 | mempool_free(bufp, hvc_iucv_mempool); | 162 | mempool_free(bufp, hvc_iucv_mempool); |
160 | return NULL; | 163 | return NULL; |
@@ -237,7 +240,7 @@ static int hvc_iucv_write(struct hvc_iucv_private *priv, | |||
237 | if (!rb->mbuf) { /* message not yet received ... */ | 240 | if (!rb->mbuf) { /* message not yet received ... */ |
238 | /* allocate mem to store msg data; if no memory is available | 241 | /* allocate mem to store msg data; if no memory is available |
239 | * then leave the buffer on the list and re-try later */ | 242 | * then leave the buffer on the list and re-try later */ |
240 | rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC); | 243 | rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC | GFP_DMA); |
241 | if (!rb->mbuf) | 244 | if (!rb->mbuf) |
242 | return -ENOMEM; | 245 | return -ENOMEM; |
243 | 246 | ||
@@ -922,7 +925,7 @@ static int hvc_iucv_pm_restore_thaw(struct device *dev) | |||
922 | 925 | ||
923 | 926 | ||
924 | /* HVC operations */ | 927 | /* HVC operations */ |
925 | static struct hv_ops hvc_iucv_ops = { | 928 | static const struct hv_ops hvc_iucv_ops = { |
926 | .get_chars = hvc_iucv_get_chars, | 929 | .get_chars = hvc_iucv_get_chars, |
927 | .put_chars = hvc_iucv_put_chars, | 930 | .put_chars = hvc_iucv_put_chars, |
928 | .notifier_add = hvc_iucv_notifier_add, | 931 | .notifier_add = hvc_iucv_notifier_add, |
@@ -1146,7 +1149,7 @@ out_err: | |||
1146 | * Note: If it is called early in the boot process, @val is stored and | 1149 | * Note: If it is called early in the boot process, @val is stored and |
1147 | * parsed later in hvc_iucv_init(). | 1150 | * parsed later in hvc_iucv_init(). |
1148 | */ | 1151 | */ |
1149 | static int param_set_vmidfilter(const char *val, struct kernel_param *kp) | 1152 | static int param_set_vmidfilter(const char *val, const struct kernel_param *kp) |
1150 | { | 1153 | { |
1151 | int rc; | 1154 | int rc; |
1152 | 1155 | ||
@@ -1173,7 +1176,7 @@ static int param_set_vmidfilter(const char *val, struct kernel_param *kp) | |||
1173 | * The function stores the filter as a comma-separated list of z/VM user IDs | 1176 | * The function stores the filter as a comma-separated list of z/VM user IDs |
1174 | * in @buffer. Typically, sysfs routines call this function for attr show. | 1177 | * in @buffer. Typically, sysfs routines call this function for attr show. |
1175 | */ | 1178 | */ |
1176 | static int param_get_vmidfilter(char *buffer, struct kernel_param *kp) | 1179 | static int param_get_vmidfilter(char *buffer, const struct kernel_param *kp) |
1177 | { | 1180 | { |
1178 | int rc; | 1181 | int rc; |
1179 | size_t index, len; | 1182 | size_t index, len; |
@@ -1200,6 +1203,11 @@ static int param_get_vmidfilter(char *buffer, struct kernel_param *kp) | |||
1200 | 1203 | ||
1201 | #define param_check_vmidfilter(name, p) __param_check(name, p, void) | 1204 | #define param_check_vmidfilter(name, p) __param_check(name, p, void) |
1202 | 1205 | ||
1206 | static struct kernel_param_ops param_ops_vmidfilter = { | ||
1207 | .set = param_set_vmidfilter, | ||
1208 | .get = param_get_vmidfilter, | ||
1209 | }; | ||
1210 | |||
1203 | /** | 1211 | /** |
1204 | * hvc_iucv_init() - z/VM IUCV HVC device driver initialization | 1212 | * hvc_iucv_init() - z/VM IUCV HVC device driver initialization |
1205 | */ | 1213 | */ |
@@ -1295,13 +1303,11 @@ static int __init hvc_iucv_init(void) | |||
1295 | if (rc) { | 1303 | if (rc) { |
1296 | pr_err("Registering IUCV handlers failed with error code=%d\n", | 1304 | pr_err("Registering IUCV handlers failed with error code=%d\n", |
1297 | rc); | 1305 | rc); |
1298 | goto out_error_iucv; | 1306 | goto out_error_hvc; |
1299 | } | 1307 | } |
1300 | 1308 | ||
1301 | return 0; | 1309 | return 0; |
1302 | 1310 | ||
1303 | out_error_iucv: | ||
1304 | iucv_unregister(&hvc_iucv_handler, 0); | ||
1305 | out_error_hvc: | 1311 | out_error_hvc: |
1306 | for (i = 0; i < hvc_iucv_devices; i++) | 1312 | for (i = 0; i < hvc_iucv_devices; i++) |
1307 | if (hvc_iucv_table[i]) | 1313 | if (hvc_iucv_table[i]) |
diff --git a/drivers/char/hvc_rtas.c b/drivers/char/hvc_rtas.c index 88590d040046..61c4a61558d9 100644 --- a/drivers/char/hvc_rtas.c +++ b/drivers/char/hvc_rtas.c | |||
@@ -71,7 +71,7 @@ static int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count) | |||
71 | return i; | 71 | return i; |
72 | } | 72 | } |
73 | 73 | ||
74 | static struct hv_ops hvc_rtas_get_put_ops = { | 74 | static const struct hv_ops hvc_rtas_get_put_ops = { |
75 | .get_chars = hvc_rtas_read_console, | 75 | .get_chars = hvc_rtas_read_console, |
76 | .put_chars = hvc_rtas_write_console, | 76 | .put_chars = hvc_rtas_write_console, |
77 | }; | 77 | }; |
diff --git a/drivers/char/hvc_tile.c b/drivers/char/hvc_tile.c new file mode 100644 index 000000000000..7a84a0595477 --- /dev/null +++ b/drivers/char/hvc_tile.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Tilera Corporation. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation, version 2. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
11 | * NON INFRINGEMENT. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * Tilera TILE Processor hypervisor console | ||
15 | */ | ||
16 | |||
17 | #include <linux/console.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/moduleparam.h> | ||
22 | #include <linux/types.h> | ||
23 | |||
24 | #include <hv/hypervisor.h> | ||
25 | |||
26 | #include "hvc_console.h" | ||
27 | |||
28 | static int hvc_tile_put_chars(uint32_t vt, const char *buf, int count) | ||
29 | { | ||
30 | return hv_console_write((HV_VirtAddr)buf, count); | ||
31 | } | ||
32 | |||
33 | static int hvc_tile_get_chars(uint32_t vt, char *buf, int count) | ||
34 | { | ||
35 | int i, c; | ||
36 | |||
37 | for (i = 0; i < count; ++i) { | ||
38 | c = hv_console_read_if_ready(); | ||
39 | if (c < 0) | ||
40 | break; | ||
41 | buf[i] = c; | ||
42 | } | ||
43 | |||
44 | return i; | ||
45 | } | ||
46 | |||
47 | static const struct hv_ops hvc_tile_get_put_ops = { | ||
48 | .get_chars = hvc_tile_get_chars, | ||
49 | .put_chars = hvc_tile_put_chars, | ||
50 | }; | ||
51 | |||
52 | static int __init hvc_tile_console_init(void) | ||
53 | { | ||
54 | extern void disable_early_printk(void); | ||
55 | hvc_instantiate(0, 0, &hvc_tile_get_put_ops); | ||
56 | add_preferred_console("hvc", 0, NULL); | ||
57 | disable_early_printk(); | ||
58 | return 0; | ||
59 | } | ||
60 | console_initcall(hvc_tile_console_init); | ||
61 | |||
62 | static int __init hvc_tile_init(void) | ||
63 | { | ||
64 | struct hvc_struct *s; | ||
65 | s = hvc_alloc(0, 0, &hvc_tile_get_put_ops, 128); | ||
66 | return IS_ERR(s) ? PTR_ERR(s) : 0; | ||
67 | } | ||
68 | device_initcall(hvc_tile_init); | ||
diff --git a/drivers/char/hvc_udbg.c b/drivers/char/hvc_udbg.c index bd63ba878a56..b0957e61a7be 100644 --- a/drivers/char/hvc_udbg.c +++ b/drivers/char/hvc_udbg.c | |||
@@ -58,7 +58,7 @@ static int hvc_udbg_get(uint32_t vtermno, char *buf, int count) | |||
58 | return i; | 58 | return i; |
59 | } | 59 | } |
60 | 60 | ||
61 | static struct hv_ops hvc_udbg_ops = { | 61 | static const struct hv_ops hvc_udbg_ops = { |
62 | .get_chars = hvc_udbg_get, | 62 | .get_chars = hvc_udbg_get, |
63 | .put_chars = hvc_udbg_put, | 63 | .put_chars = hvc_udbg_put, |
64 | }; | 64 | }; |
diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c index 10be343d6ae7..27370e99c66f 100644 --- a/drivers/char/hvc_vio.c +++ b/drivers/char/hvc_vio.c | |||
@@ -77,7 +77,7 @@ static int filtered_get_chars(uint32_t vtermno, char *buf, int count) | |||
77 | return got; | 77 | return got; |
78 | } | 78 | } |
79 | 79 | ||
80 | static struct hv_ops hvc_get_put_ops = { | 80 | static const struct hv_ops hvc_get_put_ops = { |
81 | .get_chars = filtered_get_chars, | 81 | .get_chars = filtered_get_chars, |
82 | .put_chars = hvc_put_chars, | 82 | .put_chars = hvc_put_chars, |
83 | .notifier_add = notifier_add_irq, | 83 | .notifier_add = notifier_add_irq, |
diff --git a/drivers/char/hvc_xen.c b/drivers/char/hvc_xen.c index b1a71638c772..6b8e6d18a8e6 100644 --- a/drivers/char/hvc_xen.c +++ b/drivers/char/hvc_xen.c | |||
@@ -74,7 +74,8 @@ static int __write_console(const char *data, int len) | |||
74 | wmb(); /* write ring before updating pointer */ | 74 | wmb(); /* write ring before updating pointer */ |
75 | intf->out_prod = prod; | 75 | intf->out_prod = prod; |
76 | 76 | ||
77 | notify_daemon(); | 77 | if (sent) |
78 | notify_daemon(); | ||
78 | return sent; | 79 | return sent; |
79 | } | 80 | } |
80 | 81 | ||
@@ -122,7 +123,7 @@ static int read_console(uint32_t vtermno, char *buf, int len) | |||
122 | return recv; | 123 | return recv; |
123 | } | 124 | } |
124 | 125 | ||
125 | static struct hv_ops hvc_ops = { | 126 | static const struct hv_ops hvc_ops = { |
126 | .get_chars = read_console, | 127 | .get_chars = read_console, |
127 | .put_chars = write_console, | 128 | .put_chars = write_console, |
128 | .notifier_add = notifier_add_irq, | 129 | .notifier_add = notifier_add_irq, |
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 266b858b8f85..bedc6c1b6fa5 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c | |||
@@ -74,6 +74,7 @@ | |||
74 | #include <linux/module.h> | 74 | #include <linux/module.h> |
75 | #include <linux/moduleparam.h> | 75 | #include <linux/moduleparam.h> |
76 | #include <linux/sched.h> | 76 | #include <linux/sched.h> |
77 | #include <linux/slab.h> | ||
77 | #include <linux/spinlock.h> | 78 | #include <linux/spinlock.h> |
78 | #include <linux/stat.h> | 79 | #include <linux/stat.h> |
79 | #include <linux/tty.h> | 80 | #include <linux/tty.h> |
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index 793b236c9266..a2bc885ce60a 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c | |||
@@ -194,10 +194,8 @@ static inline void print_state(struct hvsi_struct *hp) | |||
194 | "HVSI_WAIT_FOR_MCTRL_RESPONSE", | 194 | "HVSI_WAIT_FOR_MCTRL_RESPONSE", |
195 | "HVSI_FSP_DIED", | 195 | "HVSI_FSP_DIED", |
196 | }; | 196 | }; |
197 | const char *name = state_names[hp->state]; | 197 | const char *name = (hp->state < ARRAY_SIZE(state_names)) |
198 | 198 | ? state_names[hp->state] : "UNKNOWN"; | |
199 | if (hp->state > ARRAY_SIZE(state_names)) | ||
200 | name = "UNKNOWN"; | ||
201 | 199 | ||
202 | pr_debug("hvsi%i: state = %s\n", hp->index, name); | 200 | pr_debug("hvsi%i: state = %s\n", hp->index, name); |
203 | #endif /* DEBUG */ | 201 | #endif /* DEBUG */ |
@@ -405,7 +403,7 @@ static void hvsi_insert_chars(struct hvsi_struct *hp, const char *buf, int len) | |||
405 | hp->sysrq = 1; | 403 | hp->sysrq = 1; |
406 | continue; | 404 | continue; |
407 | } else if (hp->sysrq) { | 405 | } else if (hp->sysrq) { |
408 | handle_sysrq(c, hp->tty); | 406 | handle_sysrq(c); |
409 | hp->sysrq = 0; | 407 | hp->sysrq = 0; |
410 | continue; | 408 | continue; |
411 | } | 409 | } |
@@ -1257,7 +1255,7 @@ static int __init hvsi_console_setup(struct console *console, char *options) | |||
1257 | return 0; | 1255 | return 0; |
1258 | } | 1256 | } |
1259 | 1257 | ||
1260 | static struct console hvsi_con_driver = { | 1258 | static struct console hvsi_console = { |
1261 | .name = "hvsi", | 1259 | .name = "hvsi", |
1262 | .write = hvsi_console_print, | 1260 | .write = hvsi_console_print, |
1263 | .device = hvsi_console_device, | 1261 | .device = hvsi_console_device, |
@@ -1310,7 +1308,7 @@ static int __init hvsi_console_init(void) | |||
1310 | } | 1308 | } |
1311 | 1309 | ||
1312 | if (hvsi_count) | 1310 | if (hvsi_count) |
1313 | register_console(&hvsi_con_driver); | 1311 | register_console(&hvsi_console); |
1314 | return 0; | 1312 | return 0; |
1315 | } | 1313 | } |
1316 | console_initcall(hvsi_console_init); | 1314 | console_initcall(hvsi_console_init); |
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 87060266ef91..d31483c54883 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig | |||
@@ -114,7 +114,7 @@ config HW_RANDOM_IXP4XX | |||
114 | 114 | ||
115 | config HW_RANDOM_OMAP | 115 | config HW_RANDOM_OMAP |
116 | tristate "OMAP Random Number Generator support" | 116 | tristate "OMAP Random Number Generator support" |
117 | depends on HW_RANDOM && (ARCH_OMAP16XX || ARCH_OMAP24XX) | 117 | depends on HW_RANDOM && (ARCH_OMAP16XX || ARCH_OMAP2) |
118 | default HW_RANDOM | 118 | default HW_RANDOM |
119 | ---help--- | 119 | ---help--- |
120 | This driver provides kernel-side support for the Random Number | 120 | This driver provides kernel-side support for the Random Number |
@@ -186,3 +186,15 @@ config HW_RANDOM_MXC_RNGA | |||
186 | module will be called mxc-rnga. | 186 | module will be called mxc-rnga. |
187 | 187 | ||
188 | If unsure, say Y. | 188 | If unsure, say Y. |
189 | |||
190 | config HW_RANDOM_NOMADIK | ||
191 | tristate "ST-Ericsson Nomadik Random Number Generator support" | ||
192 | depends on HW_RANDOM && PLAT_NOMADIK | ||
193 | ---help--- | ||
194 | This driver provides kernel-side support for the Random Number | ||
195 | Generator hardware found on ST-Ericsson SoCs (8815 and 8500). | ||
196 | |||
197 | To compile this driver as a module, choose M here: the | ||
198 | module will be called nomadik-rng. | ||
199 | |||
200 | If unsure, say Y. | ||
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index 5eeb1303f0d0..4273308aa1e3 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile | |||
@@ -18,3 +18,4 @@ obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o | |||
18 | obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o | 18 | obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o |
19 | obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o | 19 | obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o |
20 | obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o | 20 | obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o |
21 | obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o | ||
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 3d9c61e5acbf..788da05190cc 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c | |||
@@ -170,6 +170,7 @@ static const struct file_operations rng_chrdev_ops = { | |||
170 | .owner = THIS_MODULE, | 170 | .owner = THIS_MODULE, |
171 | .open = rng_dev_open, | 171 | .open = rng_dev_open, |
172 | .read = rng_dev_read, | 172 | .read = rng_dev_read, |
173 | .llseek = noop_llseek, | ||
173 | }; | 174 | }; |
174 | 175 | ||
175 | static struct miscdevice rng_miscdev = { | 176 | static struct miscdevice rng_miscdev = { |
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index 91b53eb1c053..86fe45c19968 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/pci.h> | 30 | #include <linux/pci.h> |
31 | #include <linux/stop_machine.h> | 31 | #include <linux/stop_machine.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/slab.h> | ||
33 | #include <asm/io.h> | 34 | #include <asm/io.h> |
34 | 35 | ||
35 | 36 | ||
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index 9b3e09cd41f9..a3f5e381e746 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c | |||
@@ -71,7 +71,7 @@ MODULE_VERSION(DRV_MODULE_VERSION); | |||
71 | * x22 + x21 + x17 + x15 + x13 + x12 + x11 + x7 + x5 + x + 1 | 71 | * x22 + x21 + x17 + x15 + x13 + x12 + x11 + x7 + x5 + x + 1 |
72 | * | 72 | * |
73 | * The RNG_CTL_VCO value of each noise cell must be programmed | 73 | * The RNG_CTL_VCO value of each noise cell must be programmed |
74 | * seperately. This is why 4 control register values must be provided | 74 | * separately. This is why 4 control register values must be provided |
75 | * to the hypervisor. During a write, the hypervisor writes them all, | 75 | * to the hypervisor. During a write, the hypervisor writes them all, |
76 | * one at a time, to the actual RNG_CTL register. The first three | 76 | * one at a time, to the actual RNG_CTL register. The first three |
77 | * values are used to setup the desired RNG_CTL_VCO for each entropy | 77 | * values are used to setup the desired RNG_CTL_VCO for each entropy |
@@ -619,7 +619,7 @@ static void __devinit n2rng_driver_version(void) | |||
619 | pr_info("%s", version); | 619 | pr_info("%s", version); |
620 | } | 620 | } |
621 | 621 | ||
622 | static int __devinit n2rng_probe(struct of_device *op, | 622 | static int __devinit n2rng_probe(struct platform_device *op, |
623 | const struct of_device_id *match) | 623 | const struct of_device_id *match) |
624 | { | 624 | { |
625 | int victoria_falls = (match->data != NULL); | 625 | int victoria_falls = (match->data != NULL); |
@@ -660,7 +660,7 @@ static int __devinit n2rng_probe(struct of_device *op, | |||
660 | np->hvapi_major); | 660 | np->hvapi_major); |
661 | goto out_hvapi_unregister; | 661 | goto out_hvapi_unregister; |
662 | } | 662 | } |
663 | np->num_units = of_getintprop_default(op->node, | 663 | np->num_units = of_getintprop_default(op->dev.of_node, |
664 | "rng-#units", 0); | 664 | "rng-#units", 0); |
665 | if (!np->num_units) { | 665 | if (!np->num_units) { |
666 | dev_err(&op->dev, "VF RNG lacks rng-#units property\n"); | 666 | dev_err(&op->dev, "VF RNG lacks rng-#units property\n"); |
@@ -714,7 +714,7 @@ out: | |||
714 | return err; | 714 | return err; |
715 | } | 715 | } |
716 | 716 | ||
717 | static int __devexit n2rng_remove(struct of_device *op) | 717 | static int __devexit n2rng_remove(struct platform_device *op) |
718 | { | 718 | { |
719 | struct n2rng *np = dev_get_drvdata(&op->dev); | 719 | struct n2rng *np = dev_get_drvdata(&op->dev); |
720 | 720 | ||
@@ -751,20 +751,23 @@ static const struct of_device_id n2rng_match[] = { | |||
751 | MODULE_DEVICE_TABLE(of, n2rng_match); | 751 | MODULE_DEVICE_TABLE(of, n2rng_match); |
752 | 752 | ||
753 | static struct of_platform_driver n2rng_driver = { | 753 | static struct of_platform_driver n2rng_driver = { |
754 | .name = "n2rng", | 754 | .driver = { |
755 | .match_table = n2rng_match, | 755 | .name = "n2rng", |
756 | .owner = THIS_MODULE, | ||
757 | .of_match_table = n2rng_match, | ||
758 | }, | ||
756 | .probe = n2rng_probe, | 759 | .probe = n2rng_probe, |
757 | .remove = __devexit_p(n2rng_remove), | 760 | .remove = __devexit_p(n2rng_remove), |
758 | }; | 761 | }; |
759 | 762 | ||
760 | static int __init n2rng_init(void) | 763 | static int __init n2rng_init(void) |
761 | { | 764 | { |
762 | return of_register_driver(&n2rng_driver, &of_bus_type); | 765 | return of_register_platform_driver(&n2rng_driver); |
763 | } | 766 | } |
764 | 767 | ||
765 | static void __exit n2rng_exit(void) | 768 | static void __exit n2rng_exit(void) |
766 | { | 769 | { |
767 | of_unregister_driver(&n2rng_driver); | 770 | of_unregister_platform_driver(&n2rng_driver); |
768 | } | 771 | } |
769 | 772 | ||
770 | module_init(n2rng_init); | 773 | module_init(n2rng_init); |
diff --git a/drivers/char/hw_random/n2rng.h b/drivers/char/hw_random/n2rng.h index a2b81e7bfc18..4bea07f30978 100644 --- a/drivers/char/hw_random/n2rng.h +++ b/drivers/char/hw_random/n2rng.h | |||
@@ -65,7 +65,7 @@ struct n2rng_unit { | |||
65 | }; | 65 | }; |
66 | 66 | ||
67 | struct n2rng { | 67 | struct n2rng { |
68 | struct of_device *op; | 68 | struct platform_device *op; |
69 | 69 | ||
70 | unsigned long flags; | 70 | unsigned long flags; |
71 | #define N2RNG_FLAG_VF 0x00000001 /* Victoria Falls RNG, else N2 */ | 71 | #define N2RNG_FLAG_VF 0x00000001 /* Victoria Falls RNG, else N2 */ |
diff --git a/drivers/char/hw_random/nomadik-rng.c b/drivers/char/hw_random/nomadik-rng.c new file mode 100644 index 000000000000..a348c7e9aa0b --- /dev/null +++ b/drivers/char/hw_random/nomadik-rng.c | |||
@@ -0,0 +1,120 @@ | |||
1 | /* | ||
2 | * Nomadik RNG support | ||
3 | * Copyright 2009 Alessandro Rubini | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/amba/bus.h> | ||
16 | #include <linux/hw_random.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/err.h> | ||
20 | |||
21 | static struct clk *rng_clk; | ||
22 | |||
23 | static int nmk_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) | ||
24 | { | ||
25 | void __iomem *base = (void __iomem *)rng->priv; | ||
26 | |||
27 | /* | ||
28 | * The register is 32 bits and gives 16 random bits (low half). | ||
29 | * A subsequent read will delay the core for 400ns, so we just read | ||
30 | * once and accept the very unlikely very small delay, even if wait==0. | ||
31 | */ | ||
32 | *(u16 *)data = __raw_readl(base + 8) & 0xffff; | ||
33 | return 2; | ||
34 | } | ||
35 | |||
36 | /* we have at most one RNG per machine, granted */ | ||
37 | static struct hwrng nmk_rng = { | ||
38 | .name = "nomadik", | ||
39 | .read = nmk_rng_read, | ||
40 | }; | ||
41 | |||
42 | static int nmk_rng_probe(struct amba_device *dev, struct amba_id *id) | ||
43 | { | ||
44 | void __iomem *base; | ||
45 | int ret; | ||
46 | |||
47 | rng_clk = clk_get(&dev->dev, NULL); | ||
48 | if (IS_ERR(rng_clk)) { | ||
49 | dev_err(&dev->dev, "could not get rng clock\n"); | ||
50 | ret = PTR_ERR(rng_clk); | ||
51 | return ret; | ||
52 | } | ||
53 | |||
54 | clk_enable(rng_clk); | ||
55 | |||
56 | ret = amba_request_regions(dev, dev->dev.init_name); | ||
57 | if (ret) | ||
58 | return ret; | ||
59 | ret = -ENOMEM; | ||
60 | base = ioremap(dev->res.start, resource_size(&dev->res)); | ||
61 | if (!base) | ||
62 | goto out_release; | ||
63 | nmk_rng.priv = (unsigned long)base; | ||
64 | ret = hwrng_register(&nmk_rng); | ||
65 | if (ret) | ||
66 | goto out_unmap; | ||
67 | return 0; | ||
68 | |||
69 | out_unmap: | ||
70 | iounmap(base); | ||
71 | out_release: | ||
72 | amba_release_regions(dev); | ||
73 | clk_disable(rng_clk); | ||
74 | clk_put(rng_clk); | ||
75 | return ret; | ||
76 | } | ||
77 | |||
78 | static int nmk_rng_remove(struct amba_device *dev) | ||
79 | { | ||
80 | void __iomem *base = (void __iomem *)nmk_rng.priv; | ||
81 | hwrng_unregister(&nmk_rng); | ||
82 | iounmap(base); | ||
83 | amba_release_regions(dev); | ||
84 | clk_disable(rng_clk); | ||
85 | clk_put(rng_clk); | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static struct amba_id nmk_rng_ids[] = { | ||
90 | { | ||
91 | .id = 0x000805e1, | ||
92 | .mask = 0x000fffff, /* top bits are rev and cfg: accept all */ | ||
93 | }, | ||
94 | {0, 0}, | ||
95 | }; | ||
96 | |||
97 | static struct amba_driver nmk_rng_driver = { | ||
98 | .drv = { | ||
99 | .owner = THIS_MODULE, | ||
100 | .name = "rng", | ||
101 | }, | ||
102 | .probe = nmk_rng_probe, | ||
103 | .remove = nmk_rng_remove, | ||
104 | .id_table = nmk_rng_ids, | ||
105 | }; | ||
106 | |||
107 | static int __init nmk_rng_init(void) | ||
108 | { | ||
109 | return amba_driver_register(&nmk_rng_driver); | ||
110 | } | ||
111 | |||
112 | static void __devexit nmk_rng_exit(void) | ||
113 | { | ||
114 | amba_driver_unregister(&nmk_rng_driver); | ||
115 | } | ||
116 | |||
117 | module_init(nmk_rng_init); | ||
118 | module_exit(nmk_rng_exit); | ||
119 | |||
120 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/char/hw_random/octeon-rng.c b/drivers/char/hw_random/octeon-rng.c index 54b0d9ba65cf..9cd0feca318c 100644 --- a/drivers/char/hw_random/octeon-rng.c +++ b/drivers/char/hw_random/octeon-rng.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/device.h> | 15 | #include <linux/device.h> |
16 | #include <linux/hw_random.h> | 16 | #include <linux/hw_random.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/gfp.h> | ||
18 | 19 | ||
19 | #include <asm/octeon/octeon.h> | 20 | #include <asm/octeon/octeon.h> |
20 | #include <asm/octeon/cvmx-rnm-defs.h> | 21 | #include <asm/octeon/cvmx-rnm-defs.h> |
diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c index 7fa61dd1d9d9..a31c830ca8cd 100644 --- a/drivers/char/hw_random/pasemi-rng.c +++ b/drivers/char/hw_random/pasemi-rng.c | |||
@@ -94,11 +94,11 @@ static struct hwrng pasemi_rng = { | |||
94 | .data_read = pasemi_rng_data_read, | 94 | .data_read = pasemi_rng_data_read, |
95 | }; | 95 | }; |
96 | 96 | ||
97 | static int __devinit rng_probe(struct of_device *ofdev, | 97 | static int __devinit rng_probe(struct platform_device *ofdev, |
98 | const struct of_device_id *match) | 98 | const struct of_device_id *match) |
99 | { | 99 | { |
100 | void __iomem *rng_regs; | 100 | void __iomem *rng_regs; |
101 | struct device_node *rng_np = ofdev->node; | 101 | struct device_node *rng_np = ofdev->dev.of_node; |
102 | struct resource res; | 102 | struct resource res; |
103 | int err = 0; | 103 | int err = 0; |
104 | 104 | ||
@@ -123,7 +123,7 @@ static int __devinit rng_probe(struct of_device *ofdev, | |||
123 | return err; | 123 | return err; |
124 | } | 124 | } |
125 | 125 | ||
126 | static int __devexit rng_remove(struct of_device *dev) | 126 | static int __devexit rng_remove(struct platform_device *dev) |
127 | { | 127 | { |
128 | void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv; | 128 | void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv; |
129 | 129 | ||
@@ -140,8 +140,11 @@ static struct of_device_id rng_match[] = { | |||
140 | }; | 140 | }; |
141 | 141 | ||
142 | static struct of_platform_driver rng_driver = { | 142 | static struct of_platform_driver rng_driver = { |
143 | .name = "pasemi-rng", | 143 | .driver = { |
144 | .match_table = rng_match, | 144 | .name = "pasemi-rng", |
145 | .owner = THIS_MODULE, | ||
146 | .of_match_table = rng_match, | ||
147 | }, | ||
145 | .probe = rng_probe, | 148 | .probe = rng_probe, |
146 | .remove = rng_remove, | 149 | .remove = rng_remove, |
147 | }; | 150 | }; |
diff --git a/drivers/char/hw_random/tx4939-rng.c b/drivers/char/hw_random/tx4939-rng.c index 544d9085a8e8..0bc0cb70210b 100644 --- a/drivers/char/hw_random/tx4939-rng.c +++ b/drivers/char/hw_random/tx4939-rng.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
15 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
16 | #include <linux/hw_random.h> | 16 | #include <linux/hw_random.h> |
17 | #include <linux/gfp.h> | ||
17 | 18 | ||
18 | #define TX4939_RNG_RCSR 0x00000000 | 19 | #define TX4939_RNG_RCSR 0x00000000 |
19 | #define TX4939_RNG_ROR(n) (0x00000018 + (n) * 8) | 20 | #define TX4939_RNG_ROR(n) (0x00000018 + (n) * 8) |
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index 64fe0a793efd..75f1cbd61c17 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c | |||
@@ -32,7 +32,7 @@ static bool busy; | |||
32 | static void random_recv_done(struct virtqueue *vq) | 32 | static void random_recv_done(struct virtqueue *vq) |
33 | { | 33 | { |
34 | /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */ | 34 | /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */ |
35 | if (!vq->vq_ops->get_buf(vq, &data_avail)) | 35 | if (!virtqueue_get_buf(vq, &data_avail)) |
36 | return; | 36 | return; |
37 | 37 | ||
38 | complete(&have_data); | 38 | complete(&have_data); |
@@ -46,10 +46,10 @@ static void register_buffer(u8 *buf, size_t size) | |||
46 | sg_init_one(&sg, buf, size); | 46 | sg_init_one(&sg, buf, size); |
47 | 47 | ||
48 | /* There should always be room for one buffer. */ | 48 | /* There should always be room for one buffer. */ |
49 | if (vq->vq_ops->add_buf(vq, &sg, 0, 1, buf) < 0) | 49 | if (virtqueue_add_buf(vq, &sg, 0, 1, buf) < 0) |
50 | BUG(); | 50 | BUG(); |
51 | 51 | ||
52 | vq->vq_ops->kick(vq); | 52 | virtqueue_kick(vq); |
53 | } | 53 | } |
54 | 54 | ||
55 | static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) | 55 | static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) |
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index fc8cf7ac7f2b..3bc0eef88717 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/seq_file.h> | 23 | #include <linux/seq_file.h> |
24 | #include <linux/dmi.h> | 24 | #include <linux/dmi.h> |
25 | #include <linux/capability.h> | 25 | #include <linux/capability.h> |
26 | #include <linux/mutex.h> | ||
26 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
27 | #include <asm/io.h> | 28 | #include <asm/io.h> |
28 | 29 | ||
@@ -55,6 +56,7 @@ | |||
55 | 56 | ||
56 | #define I8K_TEMPERATURE_BUG 1 | 57 | #define I8K_TEMPERATURE_BUG 1 |
57 | 58 | ||
59 | static DEFINE_MUTEX(i8k_mutex); | ||
58 | static char bios_version[4]; | 60 | static char bios_version[4]; |
59 | 61 | ||
60 | MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)"); | 62 | MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)"); |
@@ -82,8 +84,7 @@ module_param(fan_mult, int, 0); | |||
82 | MODULE_PARM_DESC(fan_mult, "Factor to multiply fan speed with"); | 84 | MODULE_PARM_DESC(fan_mult, "Factor to multiply fan speed with"); |
83 | 85 | ||
84 | static int i8k_open_fs(struct inode *inode, struct file *file); | 86 | static int i8k_open_fs(struct inode *inode, struct file *file); |
85 | static int i8k_ioctl(struct inode *, struct file *, unsigned int, | 87 | static long i8k_ioctl(struct file *, unsigned int, unsigned long); |
86 | unsigned long); | ||
87 | 88 | ||
88 | static const struct file_operations i8k_fops = { | 89 | static const struct file_operations i8k_fops = { |
89 | .owner = THIS_MODULE, | 90 | .owner = THIS_MODULE, |
@@ -91,7 +92,7 @@ static const struct file_operations i8k_fops = { | |||
91 | .read = seq_read, | 92 | .read = seq_read, |
92 | .llseek = seq_lseek, | 93 | .llseek = seq_lseek, |
93 | .release = single_release, | 94 | .release = single_release, |
94 | .ioctl = i8k_ioctl, | 95 | .unlocked_ioctl = i8k_ioctl, |
95 | }; | 96 | }; |
96 | 97 | ||
97 | struct smm_regs { | 98 | struct smm_regs { |
@@ -307,8 +308,8 @@ static int i8k_get_dell_signature(int req_fn) | |||
307 | return regs.eax == 1145651527 && regs.edx == 1145392204 ? 0 : -1; | 308 | return regs.eax == 1145651527 && regs.edx == 1145392204 ? 0 : -1; |
308 | } | 309 | } |
309 | 310 | ||
310 | static int i8k_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, | 311 | static int |
311 | unsigned long arg) | 312 | i8k_ioctl_unlocked(struct file *fp, unsigned int cmd, unsigned long arg) |
312 | { | 313 | { |
313 | int val = 0; | 314 | int val = 0; |
314 | int speed; | 315 | int speed; |
@@ -395,6 +396,17 @@ static int i8k_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, | |||
395 | return 0; | 396 | return 0; |
396 | } | 397 | } |
397 | 398 | ||
399 | static long i8k_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) | ||
400 | { | ||
401 | long ret; | ||
402 | |||
403 | mutex_lock(&i8k_mutex); | ||
404 | ret = i8k_ioctl_unlocked(fp, cmd, arg); | ||
405 | mutex_unlock(&i8k_mutex); | ||
406 | |||
407 | return ret; | ||
408 | } | ||
409 | |||
398 | /* | 410 | /* |
399 | * Print the information for /proc/i8k. | 411 | * Print the information for /proc/i8k. |
400 | */ | 412 | */ |
diff --git a/drivers/char/ip2/Makefile b/drivers/char/ip2/Makefile index bc397d92b499..7b78e0dfc5b0 100644 --- a/drivers/char/ip2/Makefile +++ b/drivers/char/ip2/Makefile | |||
@@ -4,5 +4,5 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_COMPUTONE) += ip2.o | 5 | obj-$(CONFIG_COMPUTONE) += ip2.o |
6 | 6 | ||
7 | ip2-objs := ip2main.o | 7 | ip2-y := ip2main.o |
8 | 8 | ||
diff --git a/drivers/char/ip2/i2hw.h b/drivers/char/ip2/i2hw.h index 8aa6e7ab8d5b..c0ba6c05f0cd 100644 --- a/drivers/char/ip2/i2hw.h +++ b/drivers/char/ip2/i2hw.h | |||
@@ -559,7 +559,7 @@ Loadware may be sent to the board in two ways: | |||
559 | 559 | ||
560 | 2) It may be hard-coded into your source by including a .h file (typically | 560 | 2) It may be hard-coded into your source by including a .h file (typically |
561 | supplied by Computone), which declares a data array and initializes every | 561 | supplied by Computone), which declares a data array and initializes every |
562 | element. This acheives the same result as if an entire loadware file had | 562 | element. This achieves the same result as if an entire loadware file had |
563 | been read into the array. | 563 | been read into the array. |
564 | 564 | ||
565 | This requires more data space in your program, but access to the file system | 565 | This requires more data space in your program, but access to the file system |
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 517271c762e6..fcd02baa7d65 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c | |||
@@ -98,7 +98,7 @@ | |||
98 | #include <linux/major.h> | 98 | #include <linux/major.h> |
99 | #include <linux/wait.h> | 99 | #include <linux/wait.h> |
100 | #include <linux/device.h> | 100 | #include <linux/device.h> |
101 | #include <linux/smp_lock.h> | 101 | #include <linux/mutex.h> |
102 | #include <linux/firmware.h> | 102 | #include <linux/firmware.h> |
103 | #include <linux/platform_device.h> | 103 | #include <linux/platform_device.h> |
104 | 104 | ||
@@ -138,6 +138,7 @@ | |||
138 | #include <linux/proc_fs.h> | 138 | #include <linux/proc_fs.h> |
139 | #include <linux/seq_file.h> | 139 | #include <linux/seq_file.h> |
140 | 140 | ||
141 | static DEFINE_MUTEX(ip2_mutex); | ||
141 | static const struct file_operations ip2mem_proc_fops; | 142 | static const struct file_operations ip2mem_proc_fops; |
142 | static const struct file_operations ip2_proc_fops; | 143 | static const struct file_operations ip2_proc_fops; |
143 | 144 | ||
@@ -183,6 +184,8 @@ static void ip2_hangup(PTTY); | |||
183 | static int ip2_tiocmget(struct tty_struct *tty, struct file *file); | 184 | static int ip2_tiocmget(struct tty_struct *tty, struct file *file); |
184 | static int ip2_tiocmset(struct tty_struct *tty, struct file *file, | 185 | static int ip2_tiocmset(struct tty_struct *tty, struct file *file, |
185 | unsigned int set, unsigned int clear); | 186 | unsigned int set, unsigned int clear); |
187 | static int ip2_get_icount(struct tty_struct *tty, | ||
188 | struct serial_icounter_struct *icount); | ||
186 | 189 | ||
187 | static void set_irq(int, int); | 190 | static void set_irq(int, int); |
188 | static void ip2_interrupt_bh(struct work_struct *work); | 191 | static void ip2_interrupt_bh(struct work_struct *work); |
@@ -208,6 +211,7 @@ static int DumpFifoBuffer( char __user *, int); | |||
208 | 211 | ||
209 | static void ip2_init_board(int, const struct firmware *); | 212 | static void ip2_init_board(int, const struct firmware *); |
210 | static unsigned short find_eisa_board(int); | 213 | static unsigned short find_eisa_board(int); |
214 | static int ip2_setup(char *str); | ||
211 | 215 | ||
212 | /***************/ | 216 | /***************/ |
213 | /* Static Data */ | 217 | /* Static Data */ |
@@ -235,6 +239,7 @@ static const struct file_operations ip2_ipl = { | |||
235 | .write = ip2_ipl_write, | 239 | .write = ip2_ipl_write, |
236 | .unlocked_ioctl = ip2_ipl_ioctl, | 240 | .unlocked_ioctl = ip2_ipl_ioctl, |
237 | .open = ip2_ipl_open, | 241 | .open = ip2_ipl_open, |
242 | .llseek = noop_llseek, | ||
238 | }; | 243 | }; |
239 | 244 | ||
240 | static unsigned long irq_counter; | 245 | static unsigned long irq_counter; |
@@ -263,7 +268,7 @@ static int tracewrap; | |||
263 | /* Macros */ | 268 | /* Macros */ |
264 | /**********/ | 269 | /**********/ |
265 | 270 | ||
266 | #if defined(MODULE) && defined(IP2DEBUG_OPEN) | 271 | #ifdef IP2DEBUG_OPEN |
267 | #define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \ | 272 | #define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \ |
268 | tty->name,(pCh->flags), \ | 273 | tty->name,(pCh->flags), \ |
269 | tty->count,/*GET_USE_COUNT(module)*/0,s) | 274 | tty->count,/*GET_USE_COUNT(module)*/0,s) |
@@ -285,7 +290,10 @@ MODULE_AUTHOR("Doug McNash"); | |||
285 | MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); | 290 | MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); |
286 | MODULE_LICENSE("GPL"); | 291 | MODULE_LICENSE("GPL"); |
287 | 292 | ||
293 | #define MAX_CMD_STR 50 | ||
294 | |||
288 | static int poll_only; | 295 | static int poll_only; |
296 | static char cmd[MAX_CMD_STR]; | ||
289 | 297 | ||
290 | static int Eisa_irq; | 298 | static int Eisa_irq; |
291 | static int Eisa_slot; | 299 | static int Eisa_slot; |
@@ -309,6 +317,8 @@ module_param_array(io, int, NULL, 0); | |||
309 | MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards"); | 317 | MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards"); |
310 | module_param(poll_only, bool, 0); | 318 | module_param(poll_only, bool, 0); |
311 | MODULE_PARM_DESC(poll_only, "Do not use card interrupts"); | 319 | MODULE_PARM_DESC(poll_only, "Do not use card interrupts"); |
320 | module_param_string(ip2, cmd, MAX_CMD_STR, 0); | ||
321 | MODULE_PARM_DESC(ip2, "Contains module parameter passed with 'ip2='"); | ||
312 | 322 | ||
313 | /* for sysfs class support */ | 323 | /* for sysfs class support */ |
314 | static struct class *ip2_class; | 324 | static struct class *ip2_class; |
@@ -448,6 +458,7 @@ static const struct tty_operations ip2_ops = { | |||
448 | .hangup = ip2_hangup, | 458 | .hangup = ip2_hangup, |
449 | .tiocmget = ip2_tiocmget, | 459 | .tiocmget = ip2_tiocmget, |
450 | .tiocmset = ip2_tiocmset, | 460 | .tiocmset = ip2_tiocmset, |
461 | .get_icount = ip2_get_icount, | ||
451 | .proc_fops = &ip2_proc_fops, | 462 | .proc_fops = &ip2_proc_fops, |
452 | }; | 463 | }; |
453 | 464 | ||
@@ -487,7 +498,6 @@ static const struct firmware *ip2_request_firmware(void) | |||
487 | return fw; | 498 | return fw; |
488 | } | 499 | } |
489 | 500 | ||
490 | #ifndef MODULE | ||
491 | /****************************************************************************** | 501 | /****************************************************************************** |
492 | * ip2_setup: | 502 | * ip2_setup: |
493 | * str: kernel command line string | 503 | * str: kernel command line string |
@@ -531,7 +541,6 @@ static int __init ip2_setup(char *str) | |||
531 | return 1; | 541 | return 1; |
532 | } | 542 | } |
533 | __setup("ip2=", ip2_setup); | 543 | __setup("ip2=", ip2_setup); |
534 | #endif /* !MODULE */ | ||
535 | 544 | ||
536 | static int __init ip2_loadmain(void) | 545 | static int __init ip2_loadmain(void) |
537 | { | 546 | { |
@@ -539,14 +548,20 @@ static int __init ip2_loadmain(void) | |||
539 | int err = 0; | 548 | int err = 0; |
540 | i2eBordStrPtr pB = NULL; | 549 | i2eBordStrPtr pB = NULL; |
541 | int rc = -1; | 550 | int rc = -1; |
542 | struct pci_dev *pdev = NULL; | ||
543 | const struct firmware *fw = NULL; | 551 | const struct firmware *fw = NULL; |
552 | char *str; | ||
553 | |||
554 | str = cmd; | ||
544 | 555 | ||
545 | if (poll_only) { | 556 | if (poll_only) { |
546 | /* Hard lock the interrupts to zero */ | 557 | /* Hard lock the interrupts to zero */ |
547 | irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0; | 558 | irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0; |
548 | } | 559 | } |
549 | 560 | ||
561 | /* Check module parameter with 'ip2=' has been passed or not */ | ||
562 | if (!poll_only && (!strncmp(str, "ip2=", 4))) | ||
563 | ip2_setup(str); | ||
564 | |||
550 | ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0); | 565 | ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0); |
551 | 566 | ||
552 | /* process command line arguments to modprobe or | 567 | /* process command line arguments to modprobe or |
@@ -612,6 +627,7 @@ static int __init ip2_loadmain(void) | |||
612 | case PCI: | 627 | case PCI: |
613 | #ifdef CONFIG_PCI | 628 | #ifdef CONFIG_PCI |
614 | { | 629 | { |
630 | struct pci_dev *pdev = NULL; | ||
615 | u32 addr; | 631 | u32 addr; |
616 | int status; | 632 | int status; |
617 | 633 | ||
@@ -626,7 +642,7 @@ static int __init ip2_loadmain(void) | |||
626 | 642 | ||
627 | if (pci_enable_device(pdev)) { | 643 | if (pci_enable_device(pdev)) { |
628 | dev_err(&pdev->dev, "can't enable device\n"); | 644 | dev_err(&pdev->dev, "can't enable device\n"); |
629 | break; | 645 | goto out; |
630 | } | 646 | } |
631 | ip2config.type[i] = PCI; | 647 | ip2config.type[i] = PCI; |
632 | ip2config.pci_dev[i] = pci_dev_get(pdev); | 648 | ip2config.pci_dev[i] = pci_dev_get(pdev); |
@@ -638,6 +654,8 @@ static int __init ip2_loadmain(void) | |||
638 | dev_err(&pdev->dev, "I/O address error\n"); | 654 | dev_err(&pdev->dev, "I/O address error\n"); |
639 | 655 | ||
640 | ip2config.irq[i] = pdev->irq; | 656 | ip2config.irq[i] = pdev->irq; |
657 | out: | ||
658 | pci_dev_put(pdev); | ||
641 | } | 659 | } |
642 | #else | 660 | #else |
643 | printk(KERN_ERR "IP2: PCI card specified but PCI " | 661 | printk(KERN_ERR "IP2: PCI card specified but PCI " |
@@ -656,7 +674,6 @@ static int __init ip2_loadmain(void) | |||
656 | break; | 674 | break; |
657 | } /* switch */ | 675 | } /* switch */ |
658 | } /* for */ | 676 | } /* for */ |
659 | pci_dev_put(pdev); | ||
660 | 677 | ||
661 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { | 678 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { |
662 | if (ip2config.addr[i]) { | 679 | if (ip2config.addr[i]) { |
@@ -1474,7 +1491,9 @@ ip2_open( PTTY tty, struct file *pFile ) | |||
1474 | 1491 | ||
1475 | if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) { | 1492 | if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) { |
1476 | if ( pCh->flags & ASYNC_CLOSING ) { | 1493 | if ( pCh->flags & ASYNC_CLOSING ) { |
1494 | tty_unlock(); | ||
1477 | schedule(); | 1495 | schedule(); |
1496 | tty_lock(); | ||
1478 | } | 1497 | } |
1479 | if ( tty_hung_up_p(pFile) ) { | 1498 | if ( tty_hung_up_p(pFile) ) { |
1480 | set_current_state( TASK_RUNNING ); | 1499 | set_current_state( TASK_RUNNING ); |
@@ -1536,7 +1555,9 @@ ip2_open( PTTY tty, struct file *pFile ) | |||
1536 | rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS); | 1555 | rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS); |
1537 | break; | 1556 | break; |
1538 | } | 1557 | } |
1558 | tty_unlock(); | ||
1539 | schedule(); | 1559 | schedule(); |
1560 | tty_lock(); | ||
1540 | } | 1561 | } |
1541 | set_current_state( TASK_RUNNING ); | 1562 | set_current_state( TASK_RUNNING ); |
1542 | remove_wait_queue(&pCh->open_wait, &wait); | 1563 | remove_wait_queue(&pCh->open_wait, &wait); |
@@ -1634,7 +1655,7 @@ ip2_close( PTTY tty, struct file *pFile ) | |||
1634 | /* disable DSS reporting */ | 1655 | /* disable DSS reporting */ |
1635 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 4, | 1656 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 4, |
1636 | CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); | 1657 | CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); |
1637 | if ( !tty || (tty->termios->c_cflag & HUPCL) ) { | 1658 | if (tty->termios->c_cflag & HUPCL) { |
1638 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN); | 1659 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN); |
1639 | pCh->dataSetOut &= ~(I2_DTR | I2_RTS); | 1660 | pCh->dataSetOut &= ~(I2_DTR | I2_RTS); |
1640 | i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); | 1661 | i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); |
@@ -2112,7 +2133,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg ) | |||
2112 | i2ChanStrPtr pCh = DevTable[tty->index]; | 2133 | i2ChanStrPtr pCh = DevTable[tty->index]; |
2113 | i2eBordStrPtr pB; | 2134 | i2eBordStrPtr pB; |
2114 | struct async_icount cprev, cnow; /* kernel counter temps */ | 2135 | struct async_icount cprev, cnow; /* kernel counter temps */ |
2115 | struct serial_icounter_struct __user *p_cuser; | ||
2116 | int rc = 0; | 2136 | int rc = 0; |
2117 | unsigned long flags; | 2137 | unsigned long flags; |
2118 | void __user *argp = (void __user *)arg; | 2138 | void __user *argp = (void __user *)arg; |
@@ -2281,34 +2301,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg ) | |||
2281 | break; | 2301 | break; |
2282 | 2302 | ||
2283 | /* | 2303 | /* |
2284 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) | ||
2285 | * Return: write counters to the user passed counter struct | ||
2286 | * NB: both 1->0 and 0->1 transitions are counted except for RI where | ||
2287 | * only 0->1 is counted. The controller is quite capable of counting | ||
2288 | * both, but this done to preserve compatibility with the standard | ||
2289 | * serial driver. | ||
2290 | */ | ||
2291 | case TIOCGICOUNT: | ||
2292 | ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc ); | ||
2293 | |||
2294 | write_lock_irqsave(&pB->read_fifo_spinlock, flags); | ||
2295 | cnow = pCh->icount; | ||
2296 | write_unlock_irqrestore(&pB->read_fifo_spinlock, flags); | ||
2297 | p_cuser = argp; | ||
2298 | rc = put_user(cnow.cts, &p_cuser->cts); | ||
2299 | rc = put_user(cnow.dsr, &p_cuser->dsr); | ||
2300 | rc = put_user(cnow.rng, &p_cuser->rng); | ||
2301 | rc = put_user(cnow.dcd, &p_cuser->dcd); | ||
2302 | rc = put_user(cnow.rx, &p_cuser->rx); | ||
2303 | rc = put_user(cnow.tx, &p_cuser->tx); | ||
2304 | rc = put_user(cnow.frame, &p_cuser->frame); | ||
2305 | rc = put_user(cnow.overrun, &p_cuser->overrun); | ||
2306 | rc = put_user(cnow.parity, &p_cuser->parity); | ||
2307 | rc = put_user(cnow.brk, &p_cuser->brk); | ||
2308 | rc = put_user(cnow.buf_overrun, &p_cuser->buf_overrun); | ||
2309 | break; | ||
2310 | |||
2311 | /* | ||
2312 | * The rest are not supported by this driver. By returning -ENOIOCTLCMD they | 2304 | * The rest are not supported by this driver. By returning -ENOIOCTLCMD they |
2313 | * will be passed to the line discipline for it to handle. | 2305 | * will be passed to the line discipline for it to handle. |
2314 | */ | 2306 | */ |
@@ -2332,6 +2324,46 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg ) | |||
2332 | return rc; | 2324 | return rc; |
2333 | } | 2325 | } |
2334 | 2326 | ||
2327 | static int ip2_get_icount(struct tty_struct *tty, | ||
2328 | struct serial_icounter_struct *icount) | ||
2329 | { | ||
2330 | i2ChanStrPtr pCh = DevTable[tty->index]; | ||
2331 | i2eBordStrPtr pB; | ||
2332 | struct async_icount cnow; /* kernel counter temp */ | ||
2333 | unsigned long flags; | ||
2334 | |||
2335 | if ( pCh == NULL ) | ||
2336 | return -ENODEV; | ||
2337 | |||
2338 | pB = pCh->pMyBord; | ||
2339 | |||
2340 | /* | ||
2341 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) | ||
2342 | * Return: write counters to the user passed counter struct | ||
2343 | * NB: both 1->0 and 0->1 transitions are counted except for RI where | ||
2344 | * only 0->1 is counted. The controller is quite capable of counting | ||
2345 | * both, but this done to preserve compatibility with the standard | ||
2346 | * serial driver. | ||
2347 | */ | ||
2348 | |||
2349 | write_lock_irqsave(&pB->read_fifo_spinlock, flags); | ||
2350 | cnow = pCh->icount; | ||
2351 | write_unlock_irqrestore(&pB->read_fifo_spinlock, flags); | ||
2352 | |||
2353 | icount->cts = cnow.cts; | ||
2354 | icount->dsr = cnow.dsr; | ||
2355 | icount->rng = cnow.rng; | ||
2356 | icount->dcd = cnow.dcd; | ||
2357 | icount->rx = cnow.rx; | ||
2358 | icount->tx = cnow.tx; | ||
2359 | icount->frame = cnow.frame; | ||
2360 | icount->overrun = cnow.overrun; | ||
2361 | icount->parity = cnow.parity; | ||
2362 | icount->brk = cnow.brk; | ||
2363 | icount->buf_overrun = cnow.buf_overrun; | ||
2364 | return 0; | ||
2365 | } | ||
2366 | |||
2335 | /******************************************************************************/ | 2367 | /******************************************************************************/ |
2336 | /* Function: GetSerialInfo() */ | 2368 | /* Function: GetSerialInfo() */ |
2337 | /* Parameters: Pointer to channel structure */ | 2369 | /* Parameters: Pointer to channel structure */ |
@@ -2881,7 +2913,7 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg ) | |||
2881 | printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg ); | 2913 | printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg ); |
2882 | #endif | 2914 | #endif |
2883 | 2915 | ||
2884 | lock_kernel(); | 2916 | mutex_lock(&ip2_mutex); |
2885 | 2917 | ||
2886 | switch ( iplminor ) { | 2918 | switch ( iplminor ) { |
2887 | case 0: // IPL device | 2919 | case 0: // IPL device |
@@ -2914,6 +2946,8 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg ) | |||
2914 | if ( pCh ) | 2946 | if ( pCh ) |
2915 | { | 2947 | { |
2916 | rc = copy_to_user(argp, pCh, sizeof(i2ChanStr)); | 2948 | rc = copy_to_user(argp, pCh, sizeof(i2ChanStr)); |
2949 | if (rc) | ||
2950 | rc = -EFAULT; | ||
2917 | } else { | 2951 | } else { |
2918 | rc = -ENODEV; | 2952 | rc = -ENODEV; |
2919 | } | 2953 | } |
@@ -2943,7 +2977,7 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg ) | |||
2943 | rc = -ENODEV; | 2977 | rc = -ENODEV; |
2944 | break; | 2978 | break; |
2945 | } | 2979 | } |
2946 | unlock_kernel(); | 2980 | mutex_unlock(&ip2_mutex); |
2947 | return rc; | 2981 | return rc; |
2948 | } | 2982 | } |
2949 | 2983 | ||
@@ -2964,7 +2998,6 @@ ip2_ipl_open( struct inode *pInode, struct file *pFile ) | |||
2964 | #ifdef IP2DEBUG_IPL | 2998 | #ifdef IP2DEBUG_IPL |
2965 | printk (KERN_DEBUG "IP2IPL: open\n" ); | 2999 | printk (KERN_DEBUG "IP2IPL: open\n" ); |
2966 | #endif | 3000 | #endif |
2967 | cycle_kernel_lock(); | ||
2968 | return 0; | 3001 | return 0; |
2969 | } | 3002 | } |
2970 | 3003 | ||
@@ -3197,3 +3230,5 @@ static struct pci_device_id ip2main_pci_tbl[] __devinitdata = { | |||
3197 | }; | 3230 | }; |
3198 | 3231 | ||
3199 | MODULE_DEVICE_TABLE(pci, ip2main_pci_tbl); | 3232 | MODULE_DEVICE_TABLE(pci, ip2main_pci_tbl); |
3233 | |||
3234 | MODULE_FIRMWARE("intelliport2.bin"); | ||
diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile index eb8a1a8c188e..16a93648d54e 100644 --- a/drivers/char/ipmi/Makefile +++ b/drivers/char/ipmi/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for the ipmi drivers. | 2 | # Makefile for the ipmi drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | ipmi_si-objs := ipmi_si_intf.o ipmi_kcs_sm.o ipmi_smic_sm.o ipmi_bt_sm.o | 5 | ipmi_si-y := ipmi_si_intf.o ipmi_kcs_sm.o ipmi_smic_sm.o ipmi_bt_sm.o |
6 | 6 | ||
7 | obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o | 7 | obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o |
8 | obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o | 8 | obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o |
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c index 7b98c067190a..3ed20e8abc0d 100644 --- a/drivers/char/ipmi/ipmi_bt_sm.c +++ b/drivers/char/ipmi/ipmi_bt_sm.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * ipmi_bt_sm.c | 2 | * ipmi_bt_sm.c |
3 | * | 3 | * |
4 | * The state machine for an Open IPMI BT sub-driver under ipmi_si.c, part | 4 | * The state machine for an Open IPMI BT sub-driver under ipmi_si.c, part |
5 | * of the driver architecture at http://sourceforge.net/project/openipmi | 5 | * of the driver architecture at http://sourceforge.net/projects/openipmi |
6 | * | 6 | * |
7 | * Author: Rocky Craig <first.last@hp.com> | 7 | * Author: Rocky Craig <first.last@hp.com> |
8 | * | 8 | * |
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 65545de3dbf4..2aa3977aae5e 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c | |||
@@ -44,7 +44,6 @@ | |||
44 | #include <linux/init.h> | 44 | #include <linux/init.h> |
45 | #include <linux/device.h> | 45 | #include <linux/device.h> |
46 | #include <linux/compat.h> | 46 | #include <linux/compat.h> |
47 | #include <linux/smp_lock.h> | ||
48 | 47 | ||
49 | struct ipmi_file_private | 48 | struct ipmi_file_private |
50 | { | 49 | { |
@@ -59,6 +58,7 @@ struct ipmi_file_private | |||
59 | unsigned int default_retry_time_ms; | 58 | unsigned int default_retry_time_ms; |
60 | }; | 59 | }; |
61 | 60 | ||
61 | static DEFINE_MUTEX(ipmi_mutex); | ||
62 | static void file_receive_handler(struct ipmi_recv_msg *msg, | 62 | static void file_receive_handler(struct ipmi_recv_msg *msg, |
63 | void *handler_data) | 63 | void *handler_data) |
64 | { | 64 | { |
@@ -102,9 +102,9 @@ static int ipmi_fasync(int fd, struct file *file, int on) | |||
102 | struct ipmi_file_private *priv = file->private_data; | 102 | struct ipmi_file_private *priv = file->private_data; |
103 | int result; | 103 | int result; |
104 | 104 | ||
105 | lock_kernel(); /* could race against open() otherwise */ | 105 | mutex_lock(&ipmi_mutex); /* could race against open() otherwise */ |
106 | result = fasync_helper(fd, file, on, &priv->fasync_queue); | 106 | result = fasync_helper(fd, file, on, &priv->fasync_queue); |
107 | unlock_kernel(); | 107 | mutex_unlock(&ipmi_mutex); |
108 | 108 | ||
109 | return (result); | 109 | return (result); |
110 | } | 110 | } |
@@ -125,7 +125,7 @@ static int ipmi_open(struct inode *inode, struct file *file) | |||
125 | if (!priv) | 125 | if (!priv) |
126 | return -ENOMEM; | 126 | return -ENOMEM; |
127 | 127 | ||
128 | lock_kernel(); | 128 | mutex_lock(&ipmi_mutex); |
129 | priv->file = file; | 129 | priv->file = file; |
130 | 130 | ||
131 | rv = ipmi_create_user(if_num, | 131 | rv = ipmi_create_user(if_num, |
@@ -150,7 +150,7 @@ static int ipmi_open(struct inode *inode, struct file *file) | |||
150 | priv->default_retry_time_ms = 0; | 150 | priv->default_retry_time_ms = 0; |
151 | 151 | ||
152 | out: | 152 | out: |
153 | unlock_kernel(); | 153 | mutex_unlock(&ipmi_mutex); |
154 | return rv; | 154 | return rv; |
155 | } | 155 | } |
156 | 156 | ||
@@ -228,8 +228,7 @@ static int handle_send_req(ipmi_user_t user, | |||
228 | return rv; | 228 | return rv; |
229 | } | 229 | } |
230 | 230 | ||
231 | static int ipmi_ioctl(struct inode *inode, | 231 | static int ipmi_ioctl(struct file *file, |
232 | struct file *file, | ||
233 | unsigned int cmd, | 232 | unsigned int cmd, |
234 | unsigned long data) | 233 | unsigned long data) |
235 | { | 234 | { |
@@ -630,6 +629,23 @@ static int ipmi_ioctl(struct inode *inode, | |||
630 | return rv; | 629 | return rv; |
631 | } | 630 | } |
632 | 631 | ||
632 | /* | ||
633 | * Note: it doesn't make sense to take the BKL here but | ||
634 | * not in compat_ipmi_ioctl. -arnd | ||
635 | */ | ||
636 | static long ipmi_unlocked_ioctl(struct file *file, | ||
637 | unsigned int cmd, | ||
638 | unsigned long data) | ||
639 | { | ||
640 | int ret; | ||
641 | |||
642 | mutex_lock(&ipmi_mutex); | ||
643 | ret = ipmi_ioctl(file, cmd, data); | ||
644 | mutex_unlock(&ipmi_mutex); | ||
645 | |||
646 | return ret; | ||
647 | } | ||
648 | |||
633 | #ifdef CONFIG_COMPAT | 649 | #ifdef CONFIG_COMPAT |
634 | 650 | ||
635 | /* | 651 | /* |
@@ -802,7 +818,7 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd, | |||
802 | if (copy_to_user(precv64, &recv64, sizeof(recv64))) | 818 | if (copy_to_user(precv64, &recv64, sizeof(recv64))) |
803 | return -EFAULT; | 819 | return -EFAULT; |
804 | 820 | ||
805 | rc = ipmi_ioctl(filep->f_path.dentry->d_inode, filep, | 821 | rc = ipmi_ioctl(filep, |
806 | ((cmd == COMPAT_IPMICTL_RECEIVE_MSG) | 822 | ((cmd == COMPAT_IPMICTL_RECEIVE_MSG) |
807 | ? IPMICTL_RECEIVE_MSG | 823 | ? IPMICTL_RECEIVE_MSG |
808 | : IPMICTL_RECEIVE_MSG_TRUNC), | 824 | : IPMICTL_RECEIVE_MSG_TRUNC), |
@@ -819,14 +835,14 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd, | |||
819 | return rc; | 835 | return rc; |
820 | } | 836 | } |
821 | default: | 837 | default: |
822 | return ipmi_ioctl(filep->f_path.dentry->d_inode, filep, cmd, arg); | 838 | return ipmi_ioctl(filep, cmd, arg); |
823 | } | 839 | } |
824 | } | 840 | } |
825 | #endif | 841 | #endif |
826 | 842 | ||
827 | static const struct file_operations ipmi_fops = { | 843 | static const struct file_operations ipmi_fops = { |
828 | .owner = THIS_MODULE, | 844 | .owner = THIS_MODULE, |
829 | .ioctl = ipmi_ioctl, | 845 | .unlocked_ioctl = ipmi_unlocked_ioctl, |
830 | #ifdef CONFIG_COMPAT | 846 | #ifdef CONFIG_COMPAT |
831 | .compat_ioctl = compat_ipmi_ioctl, | 847 | .compat_ioctl = compat_ipmi_ioctl, |
832 | #endif | 848 | #endif |
@@ -834,6 +850,7 @@ static const struct file_operations ipmi_fops = { | |||
834 | .release = ipmi_release, | 850 | .release = ipmi_release, |
835 | .fasync = ipmi_fasync, | 851 | .fasync = ipmi_fasync, |
836 | .poll = ipmi_poll, | 852 | .poll = ipmi_poll, |
853 | .llseek = noop_llseek, | ||
837 | }; | 854 | }; |
838 | 855 | ||
839 | #define DEVICE_NAME "ipmidev" | 856 | #define DEVICE_NAME "ipmidev" |
@@ -899,7 +916,7 @@ static struct ipmi_smi_watcher smi_watcher = | |||
899 | .smi_gone = ipmi_smi_gone, | 916 | .smi_gone = ipmi_smi_gone, |
900 | }; | 917 | }; |
901 | 918 | ||
902 | static __init int init_ipmi_devintf(void) | 919 | static int __init init_ipmi_devintf(void) |
903 | { | 920 | { |
904 | int rv; | 921 | int rv; |
905 | 922 | ||
@@ -937,7 +954,7 @@ static __init int init_ipmi_devintf(void) | |||
937 | } | 954 | } |
938 | module_init(init_ipmi_devintf); | 955 | module_init(init_ipmi_devintf); |
939 | 956 | ||
940 | static __exit void cleanup_ipmi(void) | 957 | static void __exit cleanup_ipmi(void) |
941 | { | 958 | { |
942 | struct ipmi_reg_list *entry, *entry2; | 959 | struct ipmi_reg_list *entry, *entry2; |
943 | mutex_lock(®_list_mutex); | 960 | mutex_lock(®_list_mutex); |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index ec5e3f8df648..2fe72f8edf44 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -2272,42 +2272,52 @@ static int create_files(struct bmc_device *bmc) | |||
2272 | bmc->device_id_attr.attr.name = "device_id"; | 2272 | bmc->device_id_attr.attr.name = "device_id"; |
2273 | bmc->device_id_attr.attr.mode = S_IRUGO; | 2273 | bmc->device_id_attr.attr.mode = S_IRUGO; |
2274 | bmc->device_id_attr.show = device_id_show; | 2274 | bmc->device_id_attr.show = device_id_show; |
2275 | sysfs_attr_init(&bmc->device_id_attr.attr); | ||
2275 | 2276 | ||
2276 | bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs"; | 2277 | bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs"; |
2277 | bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO; | 2278 | bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO; |
2278 | bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show; | 2279 | bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show; |
2280 | sysfs_attr_init(&bmc->provides_dev_sdrs_attr.attr); | ||
2279 | 2281 | ||
2280 | bmc->revision_attr.attr.name = "revision"; | 2282 | bmc->revision_attr.attr.name = "revision"; |
2281 | bmc->revision_attr.attr.mode = S_IRUGO; | 2283 | bmc->revision_attr.attr.mode = S_IRUGO; |
2282 | bmc->revision_attr.show = revision_show; | 2284 | bmc->revision_attr.show = revision_show; |
2285 | sysfs_attr_init(&bmc->revision_attr.attr); | ||
2283 | 2286 | ||
2284 | bmc->firmware_rev_attr.attr.name = "firmware_revision"; | 2287 | bmc->firmware_rev_attr.attr.name = "firmware_revision"; |
2285 | bmc->firmware_rev_attr.attr.mode = S_IRUGO; | 2288 | bmc->firmware_rev_attr.attr.mode = S_IRUGO; |
2286 | bmc->firmware_rev_attr.show = firmware_rev_show; | 2289 | bmc->firmware_rev_attr.show = firmware_rev_show; |
2290 | sysfs_attr_init(&bmc->firmware_rev_attr.attr); | ||
2287 | 2291 | ||
2288 | bmc->version_attr.attr.name = "ipmi_version"; | 2292 | bmc->version_attr.attr.name = "ipmi_version"; |
2289 | bmc->version_attr.attr.mode = S_IRUGO; | 2293 | bmc->version_attr.attr.mode = S_IRUGO; |
2290 | bmc->version_attr.show = ipmi_version_show; | 2294 | bmc->version_attr.show = ipmi_version_show; |
2295 | sysfs_attr_init(&bmc->version_attr.attr); | ||
2291 | 2296 | ||
2292 | bmc->add_dev_support_attr.attr.name = "additional_device_support"; | 2297 | bmc->add_dev_support_attr.attr.name = "additional_device_support"; |
2293 | bmc->add_dev_support_attr.attr.mode = S_IRUGO; | 2298 | bmc->add_dev_support_attr.attr.mode = S_IRUGO; |
2294 | bmc->add_dev_support_attr.show = add_dev_support_show; | 2299 | bmc->add_dev_support_attr.show = add_dev_support_show; |
2300 | sysfs_attr_init(&bmc->add_dev_support_attr.attr); | ||
2295 | 2301 | ||
2296 | bmc->manufacturer_id_attr.attr.name = "manufacturer_id"; | 2302 | bmc->manufacturer_id_attr.attr.name = "manufacturer_id"; |
2297 | bmc->manufacturer_id_attr.attr.mode = S_IRUGO; | 2303 | bmc->manufacturer_id_attr.attr.mode = S_IRUGO; |
2298 | bmc->manufacturer_id_attr.show = manufacturer_id_show; | 2304 | bmc->manufacturer_id_attr.show = manufacturer_id_show; |
2305 | sysfs_attr_init(&bmc->manufacturer_id_attr.attr); | ||
2299 | 2306 | ||
2300 | bmc->product_id_attr.attr.name = "product_id"; | 2307 | bmc->product_id_attr.attr.name = "product_id"; |
2301 | bmc->product_id_attr.attr.mode = S_IRUGO; | 2308 | bmc->product_id_attr.attr.mode = S_IRUGO; |
2302 | bmc->product_id_attr.show = product_id_show; | 2309 | bmc->product_id_attr.show = product_id_show; |
2310 | sysfs_attr_init(&bmc->product_id_attr.attr); | ||
2303 | 2311 | ||
2304 | bmc->guid_attr.attr.name = "guid"; | 2312 | bmc->guid_attr.attr.name = "guid"; |
2305 | bmc->guid_attr.attr.mode = S_IRUGO; | 2313 | bmc->guid_attr.attr.mode = S_IRUGO; |
2306 | bmc->guid_attr.show = guid_show; | 2314 | bmc->guid_attr.show = guid_show; |
2315 | sysfs_attr_init(&bmc->guid_attr.attr); | ||
2307 | 2316 | ||
2308 | bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision"; | 2317 | bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision"; |
2309 | bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO; | 2318 | bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO; |
2310 | bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show; | 2319 | bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show; |
2320 | sysfs_attr_init(&bmc->aux_firmware_rev_attr.attr); | ||
2311 | 2321 | ||
2312 | err = device_create_file(&bmc->dev->dev, | 2322 | err = device_create_file(&bmc->dev->dev, |
2313 | &bmc->device_id_attr); | 2323 | &bmc->device_id_attr); |
@@ -2495,12 +2505,11 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, | |||
2495 | return rv; | 2505 | return rv; |
2496 | } | 2506 | } |
2497 | 2507 | ||
2498 | printk(KERN_INFO | 2508 | dev_info(intf->si_dev, "Found new BMC (man_id: 0x%6.6x, " |
2499 | "ipmi: Found new BMC (man_id: 0x%6.6x, " | 2509 | "prod_id: 0x%4.4x, dev_id: 0x%2.2x)\n", |
2500 | " prod_id: 0x%4.4x, dev_id: 0x%2.2x)\n", | 2510 | bmc->id.manufacturer_id, |
2501 | bmc->id.manufacturer_id, | 2511 | bmc->id.product_id, |
2502 | bmc->id.product_id, | 2512 | bmc->id.device_id); |
2503 | bmc->id.device_id); | ||
2504 | } | 2513 | } |
2505 | 2514 | ||
2506 | /* | 2515 | /* |
@@ -4027,8 +4036,8 @@ static void ipmi_request_event(void) | |||
4027 | 4036 | ||
4028 | static struct timer_list ipmi_timer; | 4037 | static struct timer_list ipmi_timer; |
4029 | 4038 | ||
4030 | /* Call every ~100 ms. */ | 4039 | /* Call every ~1000 ms. */ |
4031 | #define IPMI_TIMEOUT_TIME 100 | 4040 | #define IPMI_TIMEOUT_TIME 1000 |
4032 | 4041 | ||
4033 | /* How many jiffies does it take to get to the timeout time. */ | 4042 | /* How many jiffies does it take to get to the timeout time. */ |
4034 | #define IPMI_TIMEOUT_JIFFIES ((IPMI_TIMEOUT_TIME * HZ) / 1000) | 4043 | #define IPMI_TIMEOUT_JIFFIES ((IPMI_TIMEOUT_TIME * HZ) / 1000) |
@@ -4433,13 +4442,13 @@ static int ipmi_init_msghandler(void) | |||
4433 | return 0; | 4442 | return 0; |
4434 | } | 4443 | } |
4435 | 4444 | ||
4436 | static __init int ipmi_init_msghandler_mod(void) | 4445 | static int __init ipmi_init_msghandler_mod(void) |
4437 | { | 4446 | { |
4438 | ipmi_init_msghandler(); | 4447 | ipmi_init_msghandler(); |
4439 | return 0; | 4448 | return 0; |
4440 | } | 4449 | } |
4441 | 4450 | ||
4442 | static __exit void cleanup_ipmi(void) | 4451 | static void __exit cleanup_ipmi(void) |
4443 | { | 4452 | { |
4444 | int count; | 4453 | int count; |
4445 | 4454 | ||
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 176f1751237f..035da9e64a17 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -107,6 +107,14 @@ enum si_type { | |||
107 | }; | 107 | }; |
108 | static char *si_to_str[] = { "kcs", "smic", "bt" }; | 108 | static char *si_to_str[] = { "kcs", "smic", "bt" }; |
109 | 109 | ||
110 | enum ipmi_addr_src { | ||
111 | SI_INVALID = 0, SI_HOTMOD, SI_HARDCODED, SI_SPMI, SI_ACPI, SI_SMBIOS, | ||
112 | SI_PCI, SI_DEVICETREE, SI_DEFAULT | ||
113 | }; | ||
114 | static char *ipmi_addr_src_to_str[] = { NULL, "hotmod", "hardcoded", "SPMI", | ||
115 | "ACPI", "SMBIOS", "PCI", | ||
116 | "device-tree", "default" }; | ||
117 | |||
110 | #define DEVICE_NAME "ipmi_si" | 118 | #define DEVICE_NAME "ipmi_si" |
111 | 119 | ||
112 | static struct platform_driver ipmi_driver = { | 120 | static struct platform_driver ipmi_driver = { |
@@ -188,7 +196,7 @@ struct smi_info { | |||
188 | int (*irq_setup)(struct smi_info *info); | 196 | int (*irq_setup)(struct smi_info *info); |
189 | void (*irq_cleanup)(struct smi_info *info); | 197 | void (*irq_cleanup)(struct smi_info *info); |
190 | unsigned int io_size; | 198 | unsigned int io_size; |
191 | char *addr_source; /* ACPI, PCI, SMBIOS, hardcode, default. */ | 199 | enum ipmi_addr_src addr_source; /* ACPI, PCI, SMBIOS, hardcode, etc. */ |
192 | void (*addr_source_cleanup)(struct smi_info *info); | 200 | void (*addr_source_cleanup)(struct smi_info *info); |
193 | void *addr_source_data; | 201 | void *addr_source_data; |
194 | 202 | ||
@@ -294,9 +302,22 @@ struct smi_info { | |||
294 | 302 | ||
295 | static int force_kipmid[SI_MAX_PARMS]; | 303 | static int force_kipmid[SI_MAX_PARMS]; |
296 | static int num_force_kipmid; | 304 | static int num_force_kipmid; |
305 | #ifdef CONFIG_PCI | ||
306 | static int pci_registered; | ||
307 | #endif | ||
308 | #ifdef CONFIG_ACPI | ||
309 | static int pnp_registered; | ||
310 | #endif | ||
311 | #ifdef CONFIG_PPC_OF | ||
312 | static int of_registered; | ||
313 | #endif | ||
314 | |||
315 | static unsigned int kipmid_max_busy_us[SI_MAX_PARMS]; | ||
316 | static int num_max_busy_us; | ||
297 | 317 | ||
298 | static int unload_when_empty = 1; | 318 | static int unload_when_empty = 1; |
299 | 319 | ||
320 | static int add_smi(struct smi_info *smi); | ||
300 | static int try_smi_init(struct smi_info *smi); | 321 | static int try_smi_init(struct smi_info *smi); |
301 | static void cleanup_one_si(struct smi_info *to_clean); | 322 | static void cleanup_one_si(struct smi_info *to_clean); |
302 | 323 | ||
@@ -311,9 +332,14 @@ static void deliver_recv_msg(struct smi_info *smi_info, | |||
311 | { | 332 | { |
312 | /* Deliver the message to the upper layer with the lock | 333 | /* Deliver the message to the upper layer with the lock |
313 | released. */ | 334 | released. */ |
314 | spin_unlock(&(smi_info->si_lock)); | 335 | |
315 | ipmi_smi_msg_received(smi_info->intf, msg); | 336 | if (smi_info->run_to_completion) { |
316 | spin_lock(&(smi_info->si_lock)); | 337 | ipmi_smi_msg_received(smi_info->intf, msg); |
338 | } else { | ||
339 | spin_unlock(&(smi_info->si_lock)); | ||
340 | ipmi_smi_msg_received(smi_info->intf, msg); | ||
341 | spin_lock(&(smi_info->si_lock)); | ||
342 | } | ||
317 | } | 343 | } |
318 | 344 | ||
319 | static void return_hosed_msg(struct smi_info *smi_info, int cCode) | 345 | static void return_hosed_msg(struct smi_info *smi_info, int cCode) |
@@ -442,6 +468,9 @@ static inline void disable_si_irq(struct smi_info *smi_info) | |||
442 | if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { | 468 | if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { |
443 | start_disable_irq(smi_info); | 469 | start_disable_irq(smi_info); |
444 | smi_info->interrupt_disabled = 1; | 470 | smi_info->interrupt_disabled = 1; |
471 | if (!atomic_read(&smi_info->stop_operation)) | ||
472 | mod_timer(&smi_info->si_timer, | ||
473 | jiffies + SI_TIMEOUT_JIFFIES); | ||
445 | } | 474 | } |
446 | } | 475 | } |
447 | 476 | ||
@@ -573,9 +602,8 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
573 | smi_info->handlers->get_result(smi_info->si_sm, msg, 3); | 602 | smi_info->handlers->get_result(smi_info->si_sm, msg, 3); |
574 | if (msg[2] != 0) { | 603 | if (msg[2] != 0) { |
575 | /* Error clearing flags */ | 604 | /* Error clearing flags */ |
576 | printk(KERN_WARNING | 605 | dev_warn(smi_info->dev, |
577 | "ipmi_si: Error clearing flags: %2.2x\n", | 606 | "Error clearing flags: %2.2x\n", msg[2]); |
578 | msg[2]); | ||
579 | } | 607 | } |
580 | if (smi_info->si_state == SI_CLEARING_FLAGS_THEN_SET_IRQ) | 608 | if (smi_info->si_state == SI_CLEARING_FLAGS_THEN_SET_IRQ) |
581 | start_enable_irq(smi_info); | 609 | start_enable_irq(smi_info); |
@@ -667,9 +695,8 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
667 | /* We got the flags from the SMI, now handle them. */ | 695 | /* We got the flags from the SMI, now handle them. */ |
668 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); | 696 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); |
669 | if (msg[2] != 0) { | 697 | if (msg[2] != 0) { |
670 | printk(KERN_WARNING | 698 | dev_warn(smi_info->dev, "Could not enable interrupts" |
671 | "ipmi_si: Could not enable interrupts" | 699 | ", failed get, using polled mode.\n"); |
672 | ", failed get, using polled mode.\n"); | ||
673 | smi_info->si_state = SI_NORMAL; | 700 | smi_info->si_state = SI_NORMAL; |
674 | } else { | 701 | } else { |
675 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); | 702 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); |
@@ -690,11 +717,11 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
690 | 717 | ||
691 | /* We got the flags from the SMI, now handle them. */ | 718 | /* We got the flags from the SMI, now handle them. */ |
692 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); | 719 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); |
693 | if (msg[2] != 0) { | 720 | if (msg[2] != 0) |
694 | printk(KERN_WARNING | 721 | dev_warn(smi_info->dev, "Could not enable interrupts" |
695 | "ipmi_si: Could not enable interrupts" | 722 | ", failed set, using polled mode.\n"); |
696 | ", failed set, using polled mode.\n"); | 723 | else |
697 | } | 724 | smi_info->interrupt_disabled = 0; |
698 | smi_info->si_state = SI_NORMAL; | 725 | smi_info->si_state = SI_NORMAL; |
699 | break; | 726 | break; |
700 | } | 727 | } |
@@ -706,9 +733,8 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
706 | /* We got the flags from the SMI, now handle them. */ | 733 | /* We got the flags from the SMI, now handle them. */ |
707 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); | 734 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); |
708 | if (msg[2] != 0) { | 735 | if (msg[2] != 0) { |
709 | printk(KERN_WARNING | 736 | dev_warn(smi_info->dev, "Could not disable interrupts" |
710 | "ipmi_si: Could not disable interrupts" | 737 | ", failed get.\n"); |
711 | ", failed get.\n"); | ||
712 | smi_info->si_state = SI_NORMAL; | 738 | smi_info->si_state = SI_NORMAL; |
713 | } else { | 739 | } else { |
714 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); | 740 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); |
@@ -730,9 +756,8 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
730 | /* We got the flags from the SMI, now handle them. */ | 756 | /* We got the flags from the SMI, now handle them. */ |
731 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); | 757 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); |
732 | if (msg[2] != 0) { | 758 | if (msg[2] != 0) { |
733 | printk(KERN_WARNING | 759 | dev_warn(smi_info->dev, "Could not disable interrupts" |
734 | "ipmi_si: Could not disable interrupts" | 760 | ", failed set.\n"); |
735 | ", failed set.\n"); | ||
736 | } | 761 | } |
737 | smi_info->si_state = SI_NORMAL; | 762 | smi_info->si_state = SI_NORMAL; |
738 | break; | 763 | break; |
@@ -874,6 +899,11 @@ static void sender(void *send_info, | |||
874 | printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec); | 899 | printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec); |
875 | #endif | 900 | #endif |
876 | 901 | ||
902 | mod_timer(&smi_info->si_timer, jiffies + SI_TIMEOUT_JIFFIES); | ||
903 | |||
904 | if (smi_info->thread) | ||
905 | wake_up_process(smi_info->thread); | ||
906 | |||
877 | if (smi_info->run_to_completion) { | 907 | if (smi_info->run_to_completion) { |
878 | /* | 908 | /* |
879 | * If we are running to completion, then throw it in | 909 | * If we are running to completion, then throw it in |
@@ -925,21 +955,77 @@ static void set_run_to_completion(void *send_info, int i_run_to_completion) | |||
925 | } | 955 | } |
926 | } | 956 | } |
927 | 957 | ||
958 | /* | ||
959 | * Use -1 in the nsec value of the busy waiting timespec to tell that | ||
960 | * we are spinning in kipmid looking for something and not delaying | ||
961 | * between checks | ||
962 | */ | ||
963 | static inline void ipmi_si_set_not_busy(struct timespec *ts) | ||
964 | { | ||
965 | ts->tv_nsec = -1; | ||
966 | } | ||
967 | static inline int ipmi_si_is_busy(struct timespec *ts) | ||
968 | { | ||
969 | return ts->tv_nsec != -1; | ||
970 | } | ||
971 | |||
972 | static int ipmi_thread_busy_wait(enum si_sm_result smi_result, | ||
973 | const struct smi_info *smi_info, | ||
974 | struct timespec *busy_until) | ||
975 | { | ||
976 | unsigned int max_busy_us = 0; | ||
977 | |||
978 | if (smi_info->intf_num < num_max_busy_us) | ||
979 | max_busy_us = kipmid_max_busy_us[smi_info->intf_num]; | ||
980 | if (max_busy_us == 0 || smi_result != SI_SM_CALL_WITH_DELAY) | ||
981 | ipmi_si_set_not_busy(busy_until); | ||
982 | else if (!ipmi_si_is_busy(busy_until)) { | ||
983 | getnstimeofday(busy_until); | ||
984 | timespec_add_ns(busy_until, max_busy_us*NSEC_PER_USEC); | ||
985 | } else { | ||
986 | struct timespec now; | ||
987 | getnstimeofday(&now); | ||
988 | if (unlikely(timespec_compare(&now, busy_until) > 0)) { | ||
989 | ipmi_si_set_not_busy(busy_until); | ||
990 | return 0; | ||
991 | } | ||
992 | } | ||
993 | return 1; | ||
994 | } | ||
995 | |||
996 | |||
997 | /* | ||
998 | * A busy-waiting loop for speeding up IPMI operation. | ||
999 | * | ||
1000 | * Lousy hardware makes this hard. This is only enabled for systems | ||
1001 | * that are not BT and do not have interrupts. It starts spinning | ||
1002 | * when an operation is complete or until max_busy tells it to stop | ||
1003 | * (if that is enabled). See the paragraph on kimid_max_busy_us in | ||
1004 | * Documentation/IPMI.txt for details. | ||
1005 | */ | ||
928 | static int ipmi_thread(void *data) | 1006 | static int ipmi_thread(void *data) |
929 | { | 1007 | { |
930 | struct smi_info *smi_info = data; | 1008 | struct smi_info *smi_info = data; |
931 | unsigned long flags; | 1009 | unsigned long flags; |
932 | enum si_sm_result smi_result; | 1010 | enum si_sm_result smi_result; |
1011 | struct timespec busy_until; | ||
933 | 1012 | ||
1013 | ipmi_si_set_not_busy(&busy_until); | ||
934 | set_user_nice(current, 19); | 1014 | set_user_nice(current, 19); |
935 | while (!kthread_should_stop()) { | 1015 | while (!kthread_should_stop()) { |
1016 | int busy_wait; | ||
1017 | |||
936 | spin_lock_irqsave(&(smi_info->si_lock), flags); | 1018 | spin_lock_irqsave(&(smi_info->si_lock), flags); |
937 | smi_result = smi_event_handler(smi_info, 0); | 1019 | smi_result = smi_event_handler(smi_info, 0); |
938 | spin_unlock_irqrestore(&(smi_info->si_lock), flags); | 1020 | spin_unlock_irqrestore(&(smi_info->si_lock), flags); |
1021 | busy_wait = ipmi_thread_busy_wait(smi_result, smi_info, | ||
1022 | &busy_until); | ||
939 | if (smi_result == SI_SM_CALL_WITHOUT_DELAY) | 1023 | if (smi_result == SI_SM_CALL_WITHOUT_DELAY) |
940 | ; /* do nothing */ | 1024 | ; /* do nothing */ |
941 | else if (smi_result == SI_SM_CALL_WITH_DELAY) | 1025 | else if (smi_result == SI_SM_CALL_WITH_DELAY && busy_wait) |
942 | schedule(); | 1026 | schedule(); |
1027 | else if (smi_result == SI_SM_IDLE) | ||
1028 | schedule_timeout_interruptible(100); | ||
943 | else | 1029 | else |
944 | schedule_timeout_interruptible(1); | 1030 | schedule_timeout_interruptible(1); |
945 | } | 1031 | } |
@@ -982,6 +1068,7 @@ static void smi_timeout(unsigned long data) | |||
982 | unsigned long flags; | 1068 | unsigned long flags; |
983 | unsigned long jiffies_now; | 1069 | unsigned long jiffies_now; |
984 | long time_diff; | 1070 | long time_diff; |
1071 | long timeout; | ||
985 | #ifdef DEBUG_TIMING | 1072 | #ifdef DEBUG_TIMING |
986 | struct timeval t; | 1073 | struct timeval t; |
987 | #endif | 1074 | #endif |
@@ -1002,9 +1089,9 @@ static void smi_timeout(unsigned long data) | |||
1002 | 1089 | ||
1003 | if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { | 1090 | if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { |
1004 | /* Running with interrupts, only do long timeouts. */ | 1091 | /* Running with interrupts, only do long timeouts. */ |
1005 | smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; | 1092 | timeout = jiffies + SI_TIMEOUT_JIFFIES; |
1006 | smi_inc_stat(smi_info, long_timeouts); | 1093 | smi_inc_stat(smi_info, long_timeouts); |
1007 | goto do_add_timer; | 1094 | goto do_mod_timer; |
1008 | } | 1095 | } |
1009 | 1096 | ||
1010 | /* | 1097 | /* |
@@ -1013,14 +1100,15 @@ static void smi_timeout(unsigned long data) | |||
1013 | */ | 1100 | */ |
1014 | if (smi_result == SI_SM_CALL_WITH_DELAY) { | 1101 | if (smi_result == SI_SM_CALL_WITH_DELAY) { |
1015 | smi_inc_stat(smi_info, short_timeouts); | 1102 | smi_inc_stat(smi_info, short_timeouts); |
1016 | smi_info->si_timer.expires = jiffies + 1; | 1103 | timeout = jiffies + 1; |
1017 | } else { | 1104 | } else { |
1018 | smi_inc_stat(smi_info, long_timeouts); | 1105 | smi_inc_stat(smi_info, long_timeouts); |
1019 | smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; | 1106 | timeout = jiffies + SI_TIMEOUT_JIFFIES; |
1020 | } | 1107 | } |
1021 | 1108 | ||
1022 | do_add_timer: | 1109 | do_mod_timer: |
1023 | add_timer(&(smi_info->si_timer)); | 1110 | if (smi_result != SI_SM_IDLE) |
1111 | mod_timer(&(smi_info->si_timer), timeout); | ||
1024 | } | 1112 | } |
1025 | 1113 | ||
1026 | static irqreturn_t si_irq_handler(int irq, void *data) | 1114 | static irqreturn_t si_irq_handler(int irq, void *data) |
@@ -1087,10 +1175,10 @@ static int smi_start_processing(void *send_info, | |||
1087 | new_smi->thread = kthread_run(ipmi_thread, new_smi, | 1175 | new_smi->thread = kthread_run(ipmi_thread, new_smi, |
1088 | "kipmi%d", new_smi->intf_num); | 1176 | "kipmi%d", new_smi->intf_num); |
1089 | if (IS_ERR(new_smi->thread)) { | 1177 | if (IS_ERR(new_smi->thread)) { |
1090 | printk(KERN_NOTICE "ipmi_si_intf: Could not start" | 1178 | dev_notice(new_smi->dev, "Could not start" |
1091 | " kernel thread due to error %ld, only using" | 1179 | " kernel thread due to error %ld, only using" |
1092 | " timers to drive the interface\n", | 1180 | " timers to drive the interface\n", |
1093 | PTR_ERR(new_smi->thread)); | 1181 | PTR_ERR(new_smi->thread)); |
1094 | new_smi->thread = NULL; | 1182 | new_smi->thread = NULL; |
1095 | } | 1183 | } |
1096 | } | 1184 | } |
@@ -1144,7 +1232,7 @@ static int regsizes[SI_MAX_PARMS]; | |||
1144 | static unsigned int num_regsizes; | 1232 | static unsigned int num_regsizes; |
1145 | static int regshifts[SI_MAX_PARMS]; | 1233 | static int regshifts[SI_MAX_PARMS]; |
1146 | static unsigned int num_regshifts; | 1234 | static unsigned int num_regshifts; |
1147 | static int slave_addrs[SI_MAX_PARMS]; | 1235 | static int slave_addrs[SI_MAX_PARMS]; /* Leaving 0 chooses the default value */ |
1148 | static unsigned int num_slave_addrs; | 1236 | static unsigned int num_slave_addrs; |
1149 | 1237 | ||
1150 | #define IPMI_IO_ADDR_SPACE 0 | 1238 | #define IPMI_IO_ADDR_SPACE 0 |
@@ -1212,6 +1300,11 @@ module_param(unload_when_empty, int, 0); | |||
1212 | MODULE_PARM_DESC(unload_when_empty, "Unload the module if no interfaces are" | 1300 | MODULE_PARM_DESC(unload_when_empty, "Unload the module if no interfaces are" |
1213 | " specified or found, default is 1. Setting to 0" | 1301 | " specified or found, default is 1. Setting to 0" |
1214 | " is useful for hot add of devices using hotmod."); | 1302 | " is useful for hot add of devices using hotmod."); |
1303 | module_param_array(kipmid_max_busy_us, uint, &num_max_busy_us, 0644); | ||
1304 | MODULE_PARM_DESC(kipmid_max_busy_us, | ||
1305 | "Max time (in microseconds) to busy-wait for IPMI data before" | ||
1306 | " sleeping. 0 (default) means to wait forever. Set to 100-500" | ||
1307 | " if kipmid is using up a lot of CPU time."); | ||
1215 | 1308 | ||
1216 | 1309 | ||
1217 | static void std_irq_cleanup(struct smi_info *info) | 1310 | static void std_irq_cleanup(struct smi_info *info) |
@@ -1246,14 +1339,13 @@ static int std_irq_setup(struct smi_info *info) | |||
1246 | DEVICE_NAME, | 1339 | DEVICE_NAME, |
1247 | info); | 1340 | info); |
1248 | if (rv) { | 1341 | if (rv) { |
1249 | printk(KERN_WARNING | 1342 | dev_warn(info->dev, "%s unable to claim interrupt %d," |
1250 | "ipmi_si: %s unable to claim interrupt %d," | 1343 | " running polled\n", |
1251 | " running polled\n", | 1344 | DEVICE_NAME, info->irq); |
1252 | DEVICE_NAME, info->irq); | ||
1253 | info->irq = 0; | 1345 | info->irq = 0; |
1254 | } else { | 1346 | } else { |
1255 | info->irq_cleanup = std_irq_cleanup; | 1347 | info->irq_cleanup = std_irq_cleanup; |
1256 | printk(" Using irq %d\n", info->irq); | 1348 | dev_info(info->dev, "Using irq %d\n", info->irq); |
1257 | } | 1349 | } |
1258 | 1350 | ||
1259 | return rv; | 1351 | return rv; |
@@ -1344,8 +1436,8 @@ static int port_setup(struct smi_info *info) | |||
1344 | info->io.outputb = port_outl; | 1436 | info->io.outputb = port_outl; |
1345 | break; | 1437 | break; |
1346 | default: | 1438 | default: |
1347 | printk(KERN_WARNING "ipmi_si: Invalid register size: %d\n", | 1439 | dev_warn(info->dev, "Invalid register size: %d\n", |
1348 | info->io.regsize); | 1440 | info->io.regsize); |
1349 | return -EINVAL; | 1441 | return -EINVAL; |
1350 | } | 1442 | } |
1351 | 1443 | ||
@@ -1467,8 +1559,8 @@ static int mem_setup(struct smi_info *info) | |||
1467 | break; | 1559 | break; |
1468 | #endif | 1560 | #endif |
1469 | default: | 1561 | default: |
1470 | printk(KERN_WARNING "ipmi_si: Invalid register size: %d\n", | 1562 | dev_warn(info->dev, "Invalid register size: %d\n", |
1471 | info->io.regsize); | 1563 | info->io.regsize); |
1472 | return -EINVAL; | 1564 | return -EINVAL; |
1473 | } | 1565 | } |
1474 | 1566 | ||
@@ -1573,6 +1665,17 @@ static int check_hotmod_int_op(const char *curr, const char *option, | |||
1573 | return 0; | 1665 | return 0; |
1574 | } | 1666 | } |
1575 | 1667 | ||
1668 | static struct smi_info *smi_info_alloc(void) | ||
1669 | { | ||
1670 | struct smi_info *info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
1671 | |||
1672 | if (info) { | ||
1673 | spin_lock_init(&info->si_lock); | ||
1674 | spin_lock_init(&info->msg_lock); | ||
1675 | } | ||
1676 | return info; | ||
1677 | } | ||
1678 | |||
1576 | static int hotmod_handler(const char *val, struct kernel_param *kp) | 1679 | static int hotmod_handler(const char *val, struct kernel_param *kp) |
1577 | { | 1680 | { |
1578 | char *str = kstrdup(val, GFP_KERNEL); | 1681 | char *str = kstrdup(val, GFP_KERNEL); |
@@ -1607,7 +1710,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) | |||
1607 | regsize = 1; | 1710 | regsize = 1; |
1608 | regshift = 0; | 1711 | regshift = 0; |
1609 | irq = 0; | 1712 | irq = 0; |
1610 | ipmb = 0x20; | 1713 | ipmb = 0; /* Choose the default if not specified */ |
1611 | 1714 | ||
1612 | next = strchr(curr, ':'); | 1715 | next = strchr(curr, ':'); |
1613 | if (next) { | 1716 | if (next) { |
@@ -1687,13 +1790,13 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) | |||
1687 | } | 1790 | } |
1688 | 1791 | ||
1689 | if (op == HM_ADD) { | 1792 | if (op == HM_ADD) { |
1690 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 1793 | info = smi_info_alloc(); |
1691 | if (!info) { | 1794 | if (!info) { |
1692 | rv = -ENOMEM; | 1795 | rv = -ENOMEM; |
1693 | goto out; | 1796 | goto out; |
1694 | } | 1797 | } |
1695 | 1798 | ||
1696 | info->addr_source = "hotmod"; | 1799 | info->addr_source = SI_HOTMOD; |
1697 | info->si_type = si_type; | 1800 | info->si_type = si_type; |
1698 | info->io.addr_data = addr; | 1801 | info->io.addr_data = addr; |
1699 | info->io.addr_type = addr_space; | 1802 | info->io.addr_type = addr_space; |
@@ -1715,7 +1818,12 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) | |||
1715 | info->irq_setup = std_irq_setup; | 1818 | info->irq_setup = std_irq_setup; |
1716 | info->slave_addr = ipmb; | 1819 | info->slave_addr = ipmb; |
1717 | 1820 | ||
1718 | try_smi_init(info); | 1821 | if (!add_smi(info)) { |
1822 | if (try_smi_init(info)) | ||
1823 | cleanup_one_si(info); | ||
1824 | } else { | ||
1825 | kfree(info); | ||
1826 | } | ||
1719 | } else { | 1827 | } else { |
1720 | /* remove */ | 1828 | /* remove */ |
1721 | struct smi_info *e, *tmp_e; | 1829 | struct smi_info *e, *tmp_e; |
@@ -1738,7 +1846,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) | |||
1738 | return rv; | 1846 | return rv; |
1739 | } | 1847 | } |
1740 | 1848 | ||
1741 | static __devinit void hardcode_find_bmc(void) | 1849 | static void __devinit hardcode_find_bmc(void) |
1742 | { | 1850 | { |
1743 | int i; | 1851 | int i; |
1744 | struct smi_info *info; | 1852 | struct smi_info *info; |
@@ -1747,11 +1855,12 @@ static __devinit void hardcode_find_bmc(void) | |||
1747 | if (!ports[i] && !addrs[i]) | 1855 | if (!ports[i] && !addrs[i]) |
1748 | continue; | 1856 | continue; |
1749 | 1857 | ||
1750 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 1858 | info = smi_info_alloc(); |
1751 | if (!info) | 1859 | if (!info) |
1752 | return; | 1860 | return; |
1753 | 1861 | ||
1754 | info->addr_source = "hardcoded"; | 1862 | info->addr_source = SI_HARDCODED; |
1863 | printk(KERN_INFO PFX "probing via hardcoded address\n"); | ||
1755 | 1864 | ||
1756 | if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) { | 1865 | if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) { |
1757 | info->si_type = SI_KCS; | 1866 | info->si_type = SI_KCS; |
@@ -1760,8 +1869,7 @@ static __devinit void hardcode_find_bmc(void) | |||
1760 | } else if (strcmp(si_type[i], "bt") == 0) { | 1869 | } else if (strcmp(si_type[i], "bt") == 0) { |
1761 | info->si_type = SI_BT; | 1870 | info->si_type = SI_BT; |
1762 | } else { | 1871 | } else { |
1763 | printk(KERN_WARNING | 1872 | printk(KERN_WARNING PFX "Interface type specified " |
1764 | "ipmi_si: Interface type specified " | ||
1765 | "for interface %d, was invalid: %s\n", | 1873 | "for interface %d, was invalid: %s\n", |
1766 | i, si_type[i]); | 1874 | i, si_type[i]); |
1767 | kfree(info); | 1875 | kfree(info); |
@@ -1779,11 +1887,9 @@ static __devinit void hardcode_find_bmc(void) | |||
1779 | info->io.addr_data = addrs[i]; | 1887 | info->io.addr_data = addrs[i]; |
1780 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; | 1888 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; |
1781 | } else { | 1889 | } else { |
1782 | printk(KERN_WARNING | 1890 | printk(KERN_WARNING PFX "Interface type specified " |
1783 | "ipmi_si: Interface type specified " | 1891 | "for interface %d, but port and address were " |
1784 | "for interface %d, " | 1892 | "not set or set to zero.\n", i); |
1785 | "but port and address were not set or " | ||
1786 | "set to zero.\n", i); | ||
1787 | kfree(info); | 1893 | kfree(info); |
1788 | continue; | 1894 | continue; |
1789 | } | 1895 | } |
@@ -1799,8 +1905,14 @@ static __devinit void hardcode_find_bmc(void) | |||
1799 | info->irq = irqs[i]; | 1905 | info->irq = irqs[i]; |
1800 | if (info->irq) | 1906 | if (info->irq) |
1801 | info->irq_setup = std_irq_setup; | 1907 | info->irq_setup = std_irq_setup; |
1908 | info->slave_addr = slave_addrs[i]; | ||
1802 | 1909 | ||
1803 | try_smi_init(info); | 1910 | if (!add_smi(info)) { |
1911 | if (try_smi_init(info)) | ||
1912 | cleanup_one_si(info); | ||
1913 | } else { | ||
1914 | kfree(info); | ||
1915 | } | ||
1804 | } | 1916 | } |
1805 | } | 1917 | } |
1806 | 1918 | ||
@@ -1860,23 +1972,20 @@ static int acpi_gpe_irq_setup(struct smi_info *info) | |||
1860 | &ipmi_acpi_gpe, | 1972 | &ipmi_acpi_gpe, |
1861 | info); | 1973 | info); |
1862 | if (status != AE_OK) { | 1974 | if (status != AE_OK) { |
1863 | printk(KERN_WARNING | 1975 | dev_warn(info->dev, "%s unable to claim ACPI GPE %d," |
1864 | "ipmi_si: %s unable to claim ACPI GPE %d," | 1976 | " running polled\n", DEVICE_NAME, info->irq); |
1865 | " running polled\n", | ||
1866 | DEVICE_NAME, info->irq); | ||
1867 | info->irq = 0; | 1977 | info->irq = 0; |
1868 | return -EINVAL; | 1978 | return -EINVAL; |
1869 | } else { | 1979 | } else { |
1870 | info->irq_cleanup = acpi_gpe_irq_cleanup; | 1980 | info->irq_cleanup = acpi_gpe_irq_cleanup; |
1871 | printk(" Using ACPI GPE %d\n", info->irq); | 1981 | dev_info(info->dev, "Using ACPI GPE %d\n", info->irq); |
1872 | return 0; | 1982 | return 0; |
1873 | } | 1983 | } |
1874 | } | 1984 | } |
1875 | 1985 | ||
1876 | /* | 1986 | /* |
1877 | * Defined at | 1987 | * Defined at |
1878 | * http://h21007.www2.hp.com/dspp/files/unprotected/devresource/ | 1988 | * http://h21007.www2.hp.com/portal/download/files/unprot/hpspmi.pdf |
1879 | * Docs/TechPapers/IA64/hpspmi.pdf | ||
1880 | */ | 1989 | */ |
1881 | struct SPMITable { | 1990 | struct SPMITable { |
1882 | s8 Signature[4]; | 1991 | s8 Signature[4]; |
@@ -1920,28 +2029,23 @@ struct SPMITable { | |||
1920 | s8 spmi_id[1]; /* A '\0' terminated array starts here. */ | 2029 | s8 spmi_id[1]; /* A '\0' terminated array starts here. */ |
1921 | }; | 2030 | }; |
1922 | 2031 | ||
1923 | static __devinit int try_init_spmi(struct SPMITable *spmi) | 2032 | static int __devinit try_init_spmi(struct SPMITable *spmi) |
1924 | { | 2033 | { |
1925 | struct smi_info *info; | 2034 | struct smi_info *info; |
1926 | u8 addr_space; | ||
1927 | 2035 | ||
1928 | if (spmi->IPMIlegacy != 1) { | 2036 | if (spmi->IPMIlegacy != 1) { |
1929 | printk(KERN_INFO "IPMI: Bad SPMI legacy %d\n", spmi->IPMIlegacy); | 2037 | printk(KERN_INFO PFX "Bad SPMI legacy %d\n", spmi->IPMIlegacy); |
1930 | return -ENODEV; | 2038 | return -ENODEV; |
1931 | } | 2039 | } |
1932 | 2040 | ||
1933 | if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) | 2041 | info = smi_info_alloc(); |
1934 | addr_space = IPMI_MEM_ADDR_SPACE; | ||
1935 | else | ||
1936 | addr_space = IPMI_IO_ADDR_SPACE; | ||
1937 | |||
1938 | info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
1939 | if (!info) { | 2042 | if (!info) { |
1940 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n"); | 2043 | printk(KERN_ERR PFX "Could not allocate SI data (3)\n"); |
1941 | return -ENOMEM; | 2044 | return -ENOMEM; |
1942 | } | 2045 | } |
1943 | 2046 | ||
1944 | info->addr_source = "SPMI"; | 2047 | info->addr_source = SI_SPMI; |
2048 | printk(KERN_INFO PFX "probing via SPMI\n"); | ||
1945 | 2049 | ||
1946 | /* Figure out the interface type. */ | 2050 | /* Figure out the interface type. */ |
1947 | switch (spmi->InterfaceType) { | 2051 | switch (spmi->InterfaceType) { |
@@ -1955,8 +2059,8 @@ static __devinit int try_init_spmi(struct SPMITable *spmi) | |||
1955 | info->si_type = SI_BT; | 2059 | info->si_type = SI_BT; |
1956 | break; | 2060 | break; |
1957 | default: | 2061 | default: |
1958 | printk(KERN_INFO "ipmi_si: Unknown ACPI/SPMI SI type %d\n", | 2062 | printk(KERN_INFO PFX "Unknown ACPI/SPMI SI type %d\n", |
1959 | spmi->InterfaceType); | 2063 | spmi->InterfaceType); |
1960 | kfree(info); | 2064 | kfree(info); |
1961 | return -EIO; | 2065 | return -EIO; |
1962 | } | 2066 | } |
@@ -1992,18 +2096,23 @@ static __devinit int try_init_spmi(struct SPMITable *spmi) | |||
1992 | info->io.addr_type = IPMI_IO_ADDR_SPACE; | 2096 | info->io.addr_type = IPMI_IO_ADDR_SPACE; |
1993 | } else { | 2097 | } else { |
1994 | kfree(info); | 2098 | kfree(info); |
1995 | printk(KERN_WARNING | 2099 | printk(KERN_WARNING PFX "Unknown ACPI I/O Address type\n"); |
1996 | "ipmi_si: Unknown ACPI I/O Address type\n"); | ||
1997 | return -EIO; | 2100 | return -EIO; |
1998 | } | 2101 | } |
1999 | info->io.addr_data = spmi->addr.address; | 2102 | info->io.addr_data = spmi->addr.address; |
2000 | 2103 | ||
2001 | try_smi_init(info); | 2104 | pr_info("ipmi_si: SPMI: %s %#lx regsize %d spacing %d irq %d\n", |
2105 | (info->io.addr_type == IPMI_IO_ADDR_SPACE) ? "io" : "mem", | ||
2106 | info->io.addr_data, info->io.regsize, info->io.regspacing, | ||
2107 | info->irq); | ||
2108 | |||
2109 | if (add_smi(info)) | ||
2110 | kfree(info); | ||
2002 | 2111 | ||
2003 | return 0; | 2112 | return 0; |
2004 | } | 2113 | } |
2005 | 2114 | ||
2006 | static __devinit void spmi_find_bmc(void) | 2115 | static void __devinit spmi_find_bmc(void) |
2007 | { | 2116 | { |
2008 | acpi_status status; | 2117 | acpi_status status; |
2009 | struct SPMITable *spmi; | 2118 | struct SPMITable *spmi; |
@@ -2030,6 +2139,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, | |||
2030 | { | 2139 | { |
2031 | struct acpi_device *acpi_dev; | 2140 | struct acpi_device *acpi_dev; |
2032 | struct smi_info *info; | 2141 | struct smi_info *info; |
2142 | struct resource *res, *res_second; | ||
2033 | acpi_handle handle; | 2143 | acpi_handle handle; |
2034 | acpi_status status; | 2144 | acpi_status status; |
2035 | unsigned long long tmp; | 2145 | unsigned long long tmp; |
@@ -2038,11 +2148,12 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, | |||
2038 | if (!acpi_dev) | 2148 | if (!acpi_dev) |
2039 | return -ENODEV; | 2149 | return -ENODEV; |
2040 | 2150 | ||
2041 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2151 | info = smi_info_alloc(); |
2042 | if (!info) | 2152 | if (!info) |
2043 | return -ENOMEM; | 2153 | return -ENOMEM; |
2044 | 2154 | ||
2045 | info->addr_source = "ACPI"; | 2155 | info->addr_source = SI_ACPI; |
2156 | printk(KERN_INFO PFX "probing via ACPI\n"); | ||
2046 | 2157 | ||
2047 | handle = acpi_dev->handle; | 2158 | handle = acpi_dev->handle; |
2048 | 2159 | ||
@@ -2062,24 +2173,36 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, | |||
2062 | info->si_type = SI_BT; | 2173 | info->si_type = SI_BT; |
2063 | break; | 2174 | break; |
2064 | default: | 2175 | default: |
2065 | dev_info(&dev->dev, "unknown interface type %lld\n", tmp); | 2176 | dev_info(&dev->dev, "unknown IPMI type %lld\n", tmp); |
2066 | goto err_free; | 2177 | goto err_free; |
2067 | } | 2178 | } |
2068 | 2179 | ||
2069 | if (pnp_port_valid(dev, 0)) { | 2180 | res = pnp_get_resource(dev, IORESOURCE_IO, 0); |
2181 | if (res) { | ||
2070 | info->io_setup = port_setup; | 2182 | info->io_setup = port_setup; |
2071 | info->io.addr_type = IPMI_IO_ADDR_SPACE; | 2183 | info->io.addr_type = IPMI_IO_ADDR_SPACE; |
2072 | info->io.addr_data = pnp_port_start(dev, 0); | ||
2073 | } else if (pnp_mem_valid(dev, 0)) { | ||
2074 | info->io_setup = mem_setup; | ||
2075 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; | ||
2076 | info->io.addr_data = pnp_mem_start(dev, 0); | ||
2077 | } else { | 2184 | } else { |
2185 | res = pnp_get_resource(dev, IORESOURCE_MEM, 0); | ||
2186 | if (res) { | ||
2187 | info->io_setup = mem_setup; | ||
2188 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; | ||
2189 | } | ||
2190 | } | ||
2191 | if (!res) { | ||
2078 | dev_err(&dev->dev, "no I/O or memory address\n"); | 2192 | dev_err(&dev->dev, "no I/O or memory address\n"); |
2079 | goto err_free; | 2193 | goto err_free; |
2080 | } | 2194 | } |
2195 | info->io.addr_data = res->start; | ||
2081 | 2196 | ||
2082 | info->io.regspacing = DEFAULT_REGSPACING; | 2197 | info->io.regspacing = DEFAULT_REGSPACING; |
2198 | res_second = pnp_get_resource(dev, | ||
2199 | (info->io.addr_type == IPMI_IO_ADDR_SPACE) ? | ||
2200 | IORESOURCE_IO : IORESOURCE_MEM, | ||
2201 | 1); | ||
2202 | if (res_second) { | ||
2203 | if (res_second->start > info->io.addr_data) | ||
2204 | info->io.regspacing = res_second->start - info->io.addr_data; | ||
2205 | } | ||
2083 | info->io.regsize = DEFAULT_REGSPACING; | 2206 | info->io.regsize = DEFAULT_REGSPACING; |
2084 | info->io.regshift = 0; | 2207 | info->io.regshift = 0; |
2085 | 2208 | ||
@@ -2093,10 +2216,17 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, | |||
2093 | info->irq_setup = std_irq_setup; | 2216 | info->irq_setup = std_irq_setup; |
2094 | } | 2217 | } |
2095 | 2218 | ||
2096 | info->dev = &acpi_dev->dev; | 2219 | info->dev = &dev->dev; |
2097 | pnp_set_drvdata(dev, info); | 2220 | pnp_set_drvdata(dev, info); |
2098 | 2221 | ||
2099 | return try_smi_init(info); | 2222 | dev_info(info->dev, "%pR regsize %d spacing %d irq %d\n", |
2223 | res, info->io.regsize, info->io.regspacing, | ||
2224 | info->irq); | ||
2225 | |||
2226 | if (add_smi(info)) | ||
2227 | goto err_free; | ||
2228 | |||
2229 | return 0; | ||
2100 | 2230 | ||
2101 | err_free: | 2231 | err_free: |
2102 | kfree(info); | 2232 | kfree(info); |
@@ -2195,18 +2325,18 @@ static int __devinit decode_dmi(const struct dmi_header *dm, | |||
2195 | return 0; | 2325 | return 0; |
2196 | } | 2326 | } |
2197 | 2327 | ||
2198 | static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data) | 2328 | static void __devinit try_init_dmi(struct dmi_ipmi_data *ipmi_data) |
2199 | { | 2329 | { |
2200 | struct smi_info *info; | 2330 | struct smi_info *info; |
2201 | 2331 | ||
2202 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2332 | info = smi_info_alloc(); |
2203 | if (!info) { | 2333 | if (!info) { |
2204 | printk(KERN_ERR | 2334 | printk(KERN_ERR PFX "Could not allocate SI data\n"); |
2205 | "ipmi_si: Could not allocate SI data\n"); | ||
2206 | return; | 2335 | return; |
2207 | } | 2336 | } |
2208 | 2337 | ||
2209 | info->addr_source = "SMBIOS"; | 2338 | info->addr_source = SI_SMBIOS; |
2339 | printk(KERN_INFO PFX "probing via SMBIOS\n"); | ||
2210 | 2340 | ||
2211 | switch (ipmi_data->type) { | 2341 | switch (ipmi_data->type) { |
2212 | case 0x01: /* KCS */ | 2342 | case 0x01: /* KCS */ |
@@ -2236,8 +2366,7 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data) | |||
2236 | 2366 | ||
2237 | default: | 2367 | default: |
2238 | kfree(info); | 2368 | kfree(info); |
2239 | printk(KERN_WARNING | 2369 | printk(KERN_WARNING PFX "Unknown SMBIOS I/O Address type: %d\n", |
2240 | "ipmi_si: Unknown SMBIOS I/O Address type: %d.\n", | ||
2241 | ipmi_data->addr_space); | 2370 | ipmi_data->addr_space); |
2242 | return; | 2371 | return; |
2243 | } | 2372 | } |
@@ -2255,7 +2384,13 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data) | |||
2255 | if (info->irq) | 2384 | if (info->irq) |
2256 | info->irq_setup = std_irq_setup; | 2385 | info->irq_setup = std_irq_setup; |
2257 | 2386 | ||
2258 | try_smi_init(info); | 2387 | pr_info("ipmi_si: SMBIOS: %s %#lx regsize %d spacing %d irq %d\n", |
2388 | (info->io.addr_type == IPMI_IO_ADDR_SPACE) ? "io" : "mem", | ||
2389 | info->io.addr_data, info->io.regsize, info->io.regspacing, | ||
2390 | info->irq); | ||
2391 | |||
2392 | if (add_smi(info)) | ||
2393 | kfree(info); | ||
2259 | } | 2394 | } |
2260 | 2395 | ||
2261 | static void __devinit dmi_find_bmc(void) | 2396 | static void __devinit dmi_find_bmc(void) |
@@ -2301,11 +2436,12 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, | |||
2301 | int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK; | 2436 | int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK; |
2302 | struct smi_info *info; | 2437 | struct smi_info *info; |
2303 | 2438 | ||
2304 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2439 | info = smi_info_alloc(); |
2305 | if (!info) | 2440 | if (!info) |
2306 | return -ENOMEM; | 2441 | return -ENOMEM; |
2307 | 2442 | ||
2308 | info->addr_source = "PCI"; | 2443 | info->addr_source = SI_PCI; |
2444 | dev_info(&pdev->dev, "probing via PCI"); | ||
2309 | 2445 | ||
2310 | switch (class_type) { | 2446 | switch (class_type) { |
2311 | case PCI_ERMC_CLASSCODE_TYPE_SMIC: | 2447 | case PCI_ERMC_CLASSCODE_TYPE_SMIC: |
@@ -2322,15 +2458,13 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, | |||
2322 | 2458 | ||
2323 | default: | 2459 | default: |
2324 | kfree(info); | 2460 | kfree(info); |
2325 | printk(KERN_INFO "ipmi_si: %s: Unknown IPMI type: %d\n", | 2461 | dev_info(&pdev->dev, "Unknown IPMI type: %d\n", class_type); |
2326 | pci_name(pdev), class_type); | ||
2327 | return -ENOMEM; | 2462 | return -ENOMEM; |
2328 | } | 2463 | } |
2329 | 2464 | ||
2330 | rv = pci_enable_device(pdev); | 2465 | rv = pci_enable_device(pdev); |
2331 | if (rv) { | 2466 | if (rv) { |
2332 | printk(KERN_ERR "ipmi_si: %s: couldn't enable PCI device\n", | 2467 | dev_err(&pdev->dev, "couldn't enable PCI device\n"); |
2333 | pci_name(pdev)); | ||
2334 | kfree(info); | 2468 | kfree(info); |
2335 | return rv; | 2469 | return rv; |
2336 | } | 2470 | } |
@@ -2358,7 +2492,14 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, | |||
2358 | info->dev = &pdev->dev; | 2492 | info->dev = &pdev->dev; |
2359 | pci_set_drvdata(pdev, info); | 2493 | pci_set_drvdata(pdev, info); |
2360 | 2494 | ||
2361 | return try_smi_init(info); | 2495 | dev_info(&pdev->dev, "%pR regsize %d spacing %d irq %d\n", |
2496 | &pdev->resource[0], info->io.regsize, info->io.regspacing, | ||
2497 | info->irq); | ||
2498 | |||
2499 | if (add_smi(info)) | ||
2500 | kfree(info); | ||
2501 | |||
2502 | return 0; | ||
2362 | } | 2503 | } |
2363 | 2504 | ||
2364 | static void __devexit ipmi_pci_remove(struct pci_dev *pdev) | 2505 | static void __devexit ipmi_pci_remove(struct pci_dev *pdev) |
@@ -2400,17 +2541,17 @@ static struct pci_driver ipmi_pci_driver = { | |||
2400 | 2541 | ||
2401 | 2542 | ||
2402 | #ifdef CONFIG_PPC_OF | 2543 | #ifdef CONFIG_PPC_OF |
2403 | static int __devinit ipmi_of_probe(struct of_device *dev, | 2544 | static int __devinit ipmi_of_probe(struct platform_device *dev, |
2404 | const struct of_device_id *match) | 2545 | const struct of_device_id *match) |
2405 | { | 2546 | { |
2406 | struct smi_info *info; | 2547 | struct smi_info *info; |
2407 | struct resource resource; | 2548 | struct resource resource; |
2408 | const int *regsize, *regspacing, *regshift; | 2549 | const int *regsize, *regspacing, *regshift; |
2409 | struct device_node *np = dev->node; | 2550 | struct device_node *np = dev->dev.of_node; |
2410 | int ret; | 2551 | int ret; |
2411 | int proplen; | 2552 | int proplen; |
2412 | 2553 | ||
2413 | dev_info(&dev->dev, PFX "probing via device tree\n"); | 2554 | dev_info(&dev->dev, "probing via device tree\n"); |
2414 | 2555 | ||
2415 | ret = of_address_to_resource(np, 0, &resource); | 2556 | ret = of_address_to_resource(np, 0, &resource); |
2416 | if (ret) { | 2557 | if (ret) { |
@@ -2436,16 +2577,16 @@ static int __devinit ipmi_of_probe(struct of_device *dev, | |||
2436 | return -EINVAL; | 2577 | return -EINVAL; |
2437 | } | 2578 | } |
2438 | 2579 | ||
2439 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2580 | info = smi_info_alloc(); |
2440 | 2581 | ||
2441 | if (!info) { | 2582 | if (!info) { |
2442 | dev_err(&dev->dev, | 2583 | dev_err(&dev->dev, |
2443 | PFX "could not allocate memory for OF probe\n"); | 2584 | "could not allocate memory for OF probe\n"); |
2444 | return -ENOMEM; | 2585 | return -ENOMEM; |
2445 | } | 2586 | } |
2446 | 2587 | ||
2447 | info->si_type = (enum si_type) match->data; | 2588 | info->si_type = (enum si_type) match->data; |
2448 | info->addr_source = "device-tree"; | 2589 | info->addr_source = SI_DEVICETREE; |
2449 | info->irq_setup = std_irq_setup; | 2590 | info->irq_setup = std_irq_setup; |
2450 | 2591 | ||
2451 | if (resource.flags & IORESOURCE_IO) { | 2592 | if (resource.flags & IORESOURCE_IO) { |
@@ -2462,19 +2603,24 @@ static int __devinit ipmi_of_probe(struct of_device *dev, | |||
2462 | info->io.regspacing = regspacing ? *regspacing : DEFAULT_REGSPACING; | 2603 | info->io.regspacing = regspacing ? *regspacing : DEFAULT_REGSPACING; |
2463 | info->io.regshift = regshift ? *regshift : 0; | 2604 | info->io.regshift = regshift ? *regshift : 0; |
2464 | 2605 | ||
2465 | info->irq = irq_of_parse_and_map(dev->node, 0); | 2606 | info->irq = irq_of_parse_and_map(dev->dev.of_node, 0); |
2466 | info->dev = &dev->dev; | 2607 | info->dev = &dev->dev; |
2467 | 2608 | ||
2468 | dev_dbg(&dev->dev, "addr 0x%lx regsize %d spacing %d irq %x\n", | 2609 | dev_dbg(&dev->dev, "addr 0x%lx regsize %d spacing %d irq %d\n", |
2469 | info->io.addr_data, info->io.regsize, info->io.regspacing, | 2610 | info->io.addr_data, info->io.regsize, info->io.regspacing, |
2470 | info->irq); | 2611 | info->irq); |
2471 | 2612 | ||
2472 | dev_set_drvdata(&dev->dev, info); | 2613 | dev_set_drvdata(&dev->dev, info); |
2473 | 2614 | ||
2474 | return try_smi_init(info); | 2615 | if (add_smi(info)) { |
2616 | kfree(info); | ||
2617 | return -EBUSY; | ||
2618 | } | ||
2619 | |||
2620 | return 0; | ||
2475 | } | 2621 | } |
2476 | 2622 | ||
2477 | static int __devexit ipmi_of_remove(struct of_device *dev) | 2623 | static int __devexit ipmi_of_remove(struct platform_device *dev) |
2478 | { | 2624 | { |
2479 | cleanup_one_si(dev_get_drvdata(&dev->dev)); | 2625 | cleanup_one_si(dev_get_drvdata(&dev->dev)); |
2480 | return 0; | 2626 | return 0; |
@@ -2492,8 +2638,11 @@ static struct of_device_id ipmi_match[] = | |||
2492 | }; | 2638 | }; |
2493 | 2639 | ||
2494 | static struct of_platform_driver ipmi_of_platform_driver = { | 2640 | static struct of_platform_driver ipmi_of_platform_driver = { |
2495 | .name = "ipmi", | 2641 | .driver = { |
2496 | .match_table = ipmi_match, | 2642 | .name = "ipmi", |
2643 | .owner = THIS_MODULE, | ||
2644 | .of_match_table = ipmi_match, | ||
2645 | }, | ||
2497 | .probe = ipmi_of_probe, | 2646 | .probe = ipmi_of_probe, |
2498 | .remove = __devexit_p(ipmi_of_remove), | 2647 | .remove = __devexit_p(ipmi_of_remove), |
2499 | }; | 2648 | }; |
@@ -2577,9 +2726,8 @@ static int try_enable_event_buffer(struct smi_info *smi_info) | |||
2577 | 2726 | ||
2578 | rv = wait_for_msg_done(smi_info); | 2727 | rv = wait_for_msg_done(smi_info); |
2579 | if (rv) { | 2728 | if (rv) { |
2580 | printk(KERN_WARNING | 2729 | printk(KERN_WARNING PFX "Error getting response from get" |
2581 | "ipmi_si: Error getting response from get global," | 2730 | " global enables command, the event buffer is not" |
2582 | " enables command, the event buffer is not" | ||
2583 | " enabled.\n"); | 2731 | " enabled.\n"); |
2584 | goto out; | 2732 | goto out; |
2585 | } | 2733 | } |
@@ -2591,10 +2739,8 @@ static int try_enable_event_buffer(struct smi_info *smi_info) | |||
2591 | resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || | 2739 | resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || |
2592 | resp[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD || | 2740 | resp[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD || |
2593 | resp[2] != 0) { | 2741 | resp[2] != 0) { |
2594 | printk(KERN_WARNING | 2742 | printk(KERN_WARNING PFX "Invalid return from get global" |
2595 | "ipmi_si: Invalid return from get global" | 2743 | " enables command, cannot enable the event buffer.\n"); |
2596 | " enables command, cannot enable the event" | ||
2597 | " buffer.\n"); | ||
2598 | rv = -EINVAL; | 2744 | rv = -EINVAL; |
2599 | goto out; | 2745 | goto out; |
2600 | } | 2746 | } |
@@ -2610,9 +2756,8 @@ static int try_enable_event_buffer(struct smi_info *smi_info) | |||
2610 | 2756 | ||
2611 | rv = wait_for_msg_done(smi_info); | 2757 | rv = wait_for_msg_done(smi_info); |
2612 | if (rv) { | 2758 | if (rv) { |
2613 | printk(KERN_WARNING | 2759 | printk(KERN_WARNING PFX "Error getting response from set" |
2614 | "ipmi_si: Error getting response from set global," | 2760 | " global, enables command, the event buffer is not" |
2615 | " enables command, the event buffer is not" | ||
2616 | " enabled.\n"); | 2761 | " enabled.\n"); |
2617 | goto out; | 2762 | goto out; |
2618 | } | 2763 | } |
@@ -2623,10 +2768,8 @@ static int try_enable_event_buffer(struct smi_info *smi_info) | |||
2623 | if (resp_len < 3 || | 2768 | if (resp_len < 3 || |
2624 | resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || | 2769 | resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || |
2625 | resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) { | 2770 | resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) { |
2626 | printk(KERN_WARNING | 2771 | printk(KERN_WARNING PFX "Invalid return from get global," |
2627 | "ipmi_si: Invalid return from get global," | 2772 | "enables command, not enable the event buffer.\n"); |
2628 | "enables command, not enable the event" | ||
2629 | " buffer.\n"); | ||
2630 | rv = -EINVAL; | 2773 | rv = -EINVAL; |
2631 | goto out; | 2774 | goto out; |
2632 | } | 2775 | } |
@@ -2869,7 +3012,7 @@ static __devinitdata struct ipmi_default_vals | |||
2869 | { .port = 0 } | 3012 | { .port = 0 } |
2870 | }; | 3013 | }; |
2871 | 3014 | ||
2872 | static __devinit void default_find_bmc(void) | 3015 | static void __devinit default_find_bmc(void) |
2873 | { | 3016 | { |
2874 | struct smi_info *info; | 3017 | struct smi_info *info; |
2875 | int i; | 3018 | int i; |
@@ -2881,11 +3024,11 @@ static __devinit void default_find_bmc(void) | |||
2881 | if (check_legacy_ioport(ipmi_defaults[i].port)) | 3024 | if (check_legacy_ioport(ipmi_defaults[i].port)) |
2882 | continue; | 3025 | continue; |
2883 | #endif | 3026 | #endif |
2884 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 3027 | info = smi_info_alloc(); |
2885 | if (!info) | 3028 | if (!info) |
2886 | return; | 3029 | return; |
2887 | 3030 | ||
2888 | info->addr_source = NULL; | 3031 | info->addr_source = SI_DEFAULT; |
2889 | 3032 | ||
2890 | info->si_type = ipmi_defaults[i].type; | 3033 | info->si_type = ipmi_defaults[i].type; |
2891 | info->io_setup = port_setup; | 3034 | info->io_setup = port_setup; |
@@ -2897,14 +3040,18 @@ static __devinit void default_find_bmc(void) | |||
2897 | info->io.regsize = DEFAULT_REGSPACING; | 3040 | info->io.regsize = DEFAULT_REGSPACING; |
2898 | info->io.regshift = 0; | 3041 | info->io.regshift = 0; |
2899 | 3042 | ||
2900 | if (try_smi_init(info) == 0) { | 3043 | if (add_smi(info) == 0) { |
2901 | /* Found one... */ | 3044 | if ((try_smi_init(info)) == 0) { |
2902 | printk(KERN_INFO "ipmi_si: Found default %s state" | 3045 | /* Found one... */ |
2903 | " machine at %s address 0x%lx\n", | 3046 | printk(KERN_INFO PFX "Found default %s" |
2904 | si_to_str[info->si_type], | 3047 | " state machine at %s address 0x%lx\n", |
2905 | addr_space_to_str[info->io.addr_type], | 3048 | si_to_str[info->si_type], |
2906 | info->io.addr_data); | 3049 | addr_space_to_str[info->io.addr_type], |
2907 | return; | 3050 | info->io.addr_data); |
3051 | } else | ||
3052 | cleanup_one_si(info); | ||
3053 | } else { | ||
3054 | kfree(info); | ||
2908 | } | 3055 | } |
2909 | } | 3056 | } |
2910 | } | 3057 | } |
@@ -2923,34 +3070,48 @@ static int is_new_interface(struct smi_info *info) | |||
2923 | return 1; | 3070 | return 1; |
2924 | } | 3071 | } |
2925 | 3072 | ||
2926 | static int try_smi_init(struct smi_info *new_smi) | 3073 | static int add_smi(struct smi_info *new_smi) |
2927 | { | 3074 | { |
2928 | int rv; | 3075 | int rv = 0; |
2929 | int i; | ||
2930 | |||
2931 | if (new_smi->addr_source) { | ||
2932 | printk(KERN_INFO "ipmi_si: Trying %s-specified %s state" | ||
2933 | " machine at %s address 0x%lx, slave address 0x%x," | ||
2934 | " irq %d\n", | ||
2935 | new_smi->addr_source, | ||
2936 | si_to_str[new_smi->si_type], | ||
2937 | addr_space_to_str[new_smi->io.addr_type], | ||
2938 | new_smi->io.addr_data, | ||
2939 | new_smi->slave_addr, new_smi->irq); | ||
2940 | } | ||
2941 | 3076 | ||
3077 | printk(KERN_INFO PFX "Adding %s-specified %s state machine", | ||
3078 | ipmi_addr_src_to_str[new_smi->addr_source], | ||
3079 | si_to_str[new_smi->si_type]); | ||
2942 | mutex_lock(&smi_infos_lock); | 3080 | mutex_lock(&smi_infos_lock); |
2943 | if (!is_new_interface(new_smi)) { | 3081 | if (!is_new_interface(new_smi)) { |
2944 | printk(KERN_WARNING "ipmi_si: duplicate interface\n"); | 3082 | printk(KERN_CONT " duplicate interface\n"); |
2945 | rv = -EBUSY; | 3083 | rv = -EBUSY; |
2946 | goto out_err; | 3084 | goto out_err; |
2947 | } | 3085 | } |
2948 | 3086 | ||
3087 | printk(KERN_CONT "\n"); | ||
3088 | |||
2949 | /* So we know not to free it unless we have allocated one. */ | 3089 | /* So we know not to free it unless we have allocated one. */ |
2950 | new_smi->intf = NULL; | 3090 | new_smi->intf = NULL; |
2951 | new_smi->si_sm = NULL; | 3091 | new_smi->si_sm = NULL; |
2952 | new_smi->handlers = NULL; | 3092 | new_smi->handlers = NULL; |
2953 | 3093 | ||
3094 | list_add_tail(&new_smi->link, &smi_infos); | ||
3095 | |||
3096 | out_err: | ||
3097 | mutex_unlock(&smi_infos_lock); | ||
3098 | return rv; | ||
3099 | } | ||
3100 | |||
3101 | static int try_smi_init(struct smi_info *new_smi) | ||
3102 | { | ||
3103 | int rv = 0; | ||
3104 | int i; | ||
3105 | |||
3106 | printk(KERN_INFO PFX "Trying %s-specified %s state" | ||
3107 | " machine at %s address 0x%lx, slave address 0x%x," | ||
3108 | " irq %d\n", | ||
3109 | ipmi_addr_src_to_str[new_smi->addr_source], | ||
3110 | si_to_str[new_smi->si_type], | ||
3111 | addr_space_to_str[new_smi->io.addr_type], | ||
3112 | new_smi->io.addr_data, | ||
3113 | new_smi->slave_addr, new_smi->irq); | ||
3114 | |||
2954 | switch (new_smi->si_type) { | 3115 | switch (new_smi->si_type) { |
2955 | case SI_KCS: | 3116 | case SI_KCS: |
2956 | new_smi->handlers = &kcs_smi_handlers; | 3117 | new_smi->handlers = &kcs_smi_handlers; |
@@ -2973,7 +3134,8 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2973 | /* Allocate the state machine's data and initialize it. */ | 3134 | /* Allocate the state machine's data and initialize it. */ |
2974 | new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL); | 3135 | new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL); |
2975 | if (!new_smi->si_sm) { | 3136 | if (!new_smi->si_sm) { |
2976 | printk(KERN_ERR "Could not allocate state machine memory\n"); | 3137 | printk(KERN_ERR PFX |
3138 | "Could not allocate state machine memory\n"); | ||
2977 | rv = -ENOMEM; | 3139 | rv = -ENOMEM; |
2978 | goto out_err; | 3140 | goto out_err; |
2979 | } | 3141 | } |
@@ -2983,18 +3145,14 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2983 | /* Now that we know the I/O size, we can set up the I/O. */ | 3145 | /* Now that we know the I/O size, we can set up the I/O. */ |
2984 | rv = new_smi->io_setup(new_smi); | 3146 | rv = new_smi->io_setup(new_smi); |
2985 | if (rv) { | 3147 | if (rv) { |
2986 | printk(KERN_ERR "Could not set up I/O space\n"); | 3148 | printk(KERN_ERR PFX "Could not set up I/O space\n"); |
2987 | goto out_err; | 3149 | goto out_err; |
2988 | } | 3150 | } |
2989 | 3151 | ||
2990 | spin_lock_init(&(new_smi->si_lock)); | ||
2991 | spin_lock_init(&(new_smi->msg_lock)); | ||
2992 | |||
2993 | /* Do low-level detection first. */ | 3152 | /* Do low-level detection first. */ |
2994 | if (new_smi->handlers->detect(new_smi->si_sm)) { | 3153 | if (new_smi->handlers->detect(new_smi->si_sm)) { |
2995 | if (new_smi->addr_source) | 3154 | if (new_smi->addr_source) |
2996 | printk(KERN_INFO "ipmi_si: Interface detection" | 3155 | printk(KERN_INFO PFX "Interface detection failed\n"); |
2997 | " failed\n"); | ||
2998 | rv = -ENODEV; | 3156 | rv = -ENODEV; |
2999 | goto out_err; | 3157 | goto out_err; |
3000 | } | 3158 | } |
@@ -3006,7 +3164,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3006 | rv = try_get_dev_id(new_smi); | 3164 | rv = try_get_dev_id(new_smi); |
3007 | if (rv) { | 3165 | if (rv) { |
3008 | if (new_smi->addr_source) | 3166 | if (new_smi->addr_source) |
3009 | printk(KERN_INFO "ipmi_si: There appears to be no BMC" | 3167 | printk(KERN_INFO PFX "There appears to be no BMC" |
3010 | " at this location\n"); | 3168 | " at this location\n"); |
3011 | goto out_err; | 3169 | goto out_err; |
3012 | } | 3170 | } |
@@ -3022,7 +3180,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3022 | for (i = 0; i < SI_NUM_STATS; i++) | 3180 | for (i = 0; i < SI_NUM_STATS; i++) |
3023 | atomic_set(&new_smi->stats[i], 0); | 3181 | atomic_set(&new_smi->stats[i], 0); |
3024 | 3182 | ||
3025 | new_smi->interrupt_disabled = 0; | 3183 | new_smi->interrupt_disabled = 1; |
3026 | atomic_set(&new_smi->stop_operation, 0); | 3184 | atomic_set(&new_smi->stop_operation, 0); |
3027 | new_smi->intf_num = smi_num; | 3185 | new_smi->intf_num = smi_num; |
3028 | smi_num++; | 3186 | smi_num++; |
@@ -3048,9 +3206,8 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3048 | new_smi->pdev = platform_device_alloc("ipmi_si", | 3206 | new_smi->pdev = platform_device_alloc("ipmi_si", |
3049 | new_smi->intf_num); | 3207 | new_smi->intf_num); |
3050 | if (!new_smi->pdev) { | 3208 | if (!new_smi->pdev) { |
3051 | printk(KERN_ERR | 3209 | printk(KERN_ERR PFX |
3052 | "ipmi_si_intf:" | 3210 | "Unable to allocate platform device\n"); |
3053 | " Unable to allocate platform device\n"); | ||
3054 | goto out_err; | 3211 | goto out_err; |
3055 | } | 3212 | } |
3056 | new_smi->dev = &new_smi->pdev->dev; | 3213 | new_smi->dev = &new_smi->pdev->dev; |
@@ -3058,9 +3215,8 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3058 | 3215 | ||
3059 | rv = platform_device_add(new_smi->pdev); | 3216 | rv = platform_device_add(new_smi->pdev); |
3060 | if (rv) { | 3217 | if (rv) { |
3061 | printk(KERN_ERR | 3218 | printk(KERN_ERR PFX |
3062 | "ipmi_si_intf:" | 3219 | "Unable to register system interface device:" |
3063 | " Unable to register system interface device:" | ||
3064 | " %d\n", | 3220 | " %d\n", |
3065 | rv); | 3221 | rv); |
3066 | goto out_err; | 3222 | goto out_err; |
@@ -3075,9 +3231,8 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3075 | "bmc", | 3231 | "bmc", |
3076 | new_smi->slave_addr); | 3232 | new_smi->slave_addr); |
3077 | if (rv) { | 3233 | if (rv) { |
3078 | printk(KERN_ERR | 3234 | dev_err(new_smi->dev, "Unable to register device: error %d\n", |
3079 | "ipmi_si: Unable to register device: error %d\n", | 3235 | rv); |
3080 | rv); | ||
3081 | goto out_err_stop_timer; | 3236 | goto out_err_stop_timer; |
3082 | } | 3237 | } |
3083 | 3238 | ||
@@ -3085,9 +3240,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3085 | type_file_read_proc, | 3240 | type_file_read_proc, |
3086 | new_smi); | 3241 | new_smi); |
3087 | if (rv) { | 3242 | if (rv) { |
3088 | printk(KERN_ERR | 3243 | dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); |
3089 | "ipmi_si: Unable to create proc entry: %d\n", | ||
3090 | rv); | ||
3091 | goto out_err_stop_timer; | 3244 | goto out_err_stop_timer; |
3092 | } | 3245 | } |
3093 | 3246 | ||
@@ -3095,9 +3248,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3095 | stat_file_read_proc, | 3248 | stat_file_read_proc, |
3096 | new_smi); | 3249 | new_smi); |
3097 | if (rv) { | 3250 | if (rv) { |
3098 | printk(KERN_ERR | 3251 | dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); |
3099 | "ipmi_si: Unable to create proc entry: %d\n", | ||
3100 | rv); | ||
3101 | goto out_err_stop_timer; | 3252 | goto out_err_stop_timer; |
3102 | } | 3253 | } |
3103 | 3254 | ||
@@ -3105,18 +3256,12 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3105 | param_read_proc, | 3256 | param_read_proc, |
3106 | new_smi); | 3257 | new_smi); |
3107 | if (rv) { | 3258 | if (rv) { |
3108 | printk(KERN_ERR | 3259 | dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); |
3109 | "ipmi_si: Unable to create proc entry: %d\n", | ||
3110 | rv); | ||
3111 | goto out_err_stop_timer; | 3260 | goto out_err_stop_timer; |
3112 | } | 3261 | } |
3113 | 3262 | ||
3114 | list_add_tail(&new_smi->link, &smi_infos); | 3263 | dev_info(new_smi->dev, "IPMI %s interface initialized\n", |
3115 | 3264 | si_to_str[new_smi->si_type]); | |
3116 | mutex_unlock(&smi_infos_lock); | ||
3117 | |||
3118 | printk(KERN_INFO "IPMI %s interface initialized\n", | ||
3119 | si_to_str[new_smi->si_type]); | ||
3120 | 3265 | ||
3121 | return 0; | 3266 | return 0; |
3122 | 3267 | ||
@@ -3125,11 +3270,17 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3125 | wait_for_timer_and_thread(new_smi); | 3270 | wait_for_timer_and_thread(new_smi); |
3126 | 3271 | ||
3127 | out_err: | 3272 | out_err: |
3128 | if (new_smi->intf) | 3273 | new_smi->interrupt_disabled = 1; |
3274 | |||
3275 | if (new_smi->intf) { | ||
3129 | ipmi_unregister_smi(new_smi->intf); | 3276 | ipmi_unregister_smi(new_smi->intf); |
3277 | new_smi->intf = NULL; | ||
3278 | } | ||
3130 | 3279 | ||
3131 | if (new_smi->irq_cleanup) | 3280 | if (new_smi->irq_cleanup) { |
3132 | new_smi->irq_cleanup(new_smi); | 3281 | new_smi->irq_cleanup(new_smi); |
3282 | new_smi->irq_cleanup = NULL; | ||
3283 | } | ||
3133 | 3284 | ||
3134 | /* | 3285 | /* |
3135 | * Wait until we know that we are out of any interrupt | 3286 | * Wait until we know that we are out of any interrupt |
@@ -3142,27 +3293,32 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3142 | if (new_smi->handlers) | 3293 | if (new_smi->handlers) |
3143 | new_smi->handlers->cleanup(new_smi->si_sm); | 3294 | new_smi->handlers->cleanup(new_smi->si_sm); |
3144 | kfree(new_smi->si_sm); | 3295 | kfree(new_smi->si_sm); |
3296 | new_smi->si_sm = NULL; | ||
3145 | } | 3297 | } |
3146 | if (new_smi->addr_source_cleanup) | 3298 | if (new_smi->addr_source_cleanup) { |
3147 | new_smi->addr_source_cleanup(new_smi); | 3299 | new_smi->addr_source_cleanup(new_smi); |
3148 | if (new_smi->io_cleanup) | 3300 | new_smi->addr_source_cleanup = NULL; |
3301 | } | ||
3302 | if (new_smi->io_cleanup) { | ||
3149 | new_smi->io_cleanup(new_smi); | 3303 | new_smi->io_cleanup(new_smi); |
3304 | new_smi->io_cleanup = NULL; | ||
3305 | } | ||
3150 | 3306 | ||
3151 | if (new_smi->dev_registered) | 3307 | if (new_smi->dev_registered) { |
3152 | platform_device_unregister(new_smi->pdev); | 3308 | platform_device_unregister(new_smi->pdev); |
3153 | 3309 | new_smi->dev_registered = 0; | |
3154 | kfree(new_smi); | 3310 | } |
3155 | |||
3156 | mutex_unlock(&smi_infos_lock); | ||
3157 | 3311 | ||
3158 | return rv; | 3312 | return rv; |
3159 | } | 3313 | } |
3160 | 3314 | ||
3161 | static __devinit int init_ipmi_si(void) | 3315 | static int __devinit init_ipmi_si(void) |
3162 | { | 3316 | { |
3163 | int i; | 3317 | int i; |
3164 | char *str; | 3318 | char *str; |
3165 | int rv; | 3319 | int rv; |
3320 | struct smi_info *e; | ||
3321 | enum ipmi_addr_src type = SI_INVALID; | ||
3166 | 3322 | ||
3167 | if (initialized) | 3323 | if (initialized) |
3168 | return 0; | 3324 | return 0; |
@@ -3171,9 +3327,7 @@ static __devinit int init_ipmi_si(void) | |||
3171 | /* Register the device drivers. */ | 3327 | /* Register the device drivers. */ |
3172 | rv = driver_register(&ipmi_driver.driver); | 3328 | rv = driver_register(&ipmi_driver.driver); |
3173 | if (rv) { | 3329 | if (rv) { |
3174 | printk(KERN_ERR | 3330 | printk(KERN_ERR PFX "Unable to register driver: %d\n", rv); |
3175 | "init_ipmi_si: Unable to register driver: %d\n", | ||
3176 | rv); | ||
3177 | return rv; | 3331 | return rv; |
3178 | } | 3332 | } |
3179 | 3333 | ||
@@ -3197,53 +3351,102 @@ static __devinit int init_ipmi_si(void) | |||
3197 | 3351 | ||
3198 | hardcode_find_bmc(); | 3352 | hardcode_find_bmc(); |
3199 | 3353 | ||
3200 | #ifdef CONFIG_DMI | 3354 | /* If the user gave us a device, they presumably want us to use it */ |
3201 | dmi_find_bmc(); | 3355 | mutex_lock(&smi_infos_lock); |
3202 | #endif | 3356 | if (!list_empty(&smi_infos)) { |
3357 | mutex_unlock(&smi_infos_lock); | ||
3358 | return 0; | ||
3359 | } | ||
3360 | mutex_unlock(&smi_infos_lock); | ||
3203 | 3361 | ||
3204 | #ifdef CONFIG_ACPI | 3362 | #ifdef CONFIG_PCI |
3205 | spmi_find_bmc(); | 3363 | rv = pci_register_driver(&ipmi_pci_driver); |
3364 | if (rv) | ||
3365 | printk(KERN_ERR PFX "Unable to register PCI driver: %d\n", rv); | ||
3366 | else | ||
3367 | pci_registered = 1; | ||
3206 | #endif | 3368 | #endif |
3369 | |||
3207 | #ifdef CONFIG_ACPI | 3370 | #ifdef CONFIG_ACPI |
3208 | pnp_register_driver(&ipmi_pnp_driver); | 3371 | pnp_register_driver(&ipmi_pnp_driver); |
3372 | pnp_registered = 1; | ||
3209 | #endif | 3373 | #endif |
3210 | 3374 | ||
3211 | #ifdef CONFIG_PCI | 3375 | #ifdef CONFIG_DMI |
3212 | rv = pci_register_driver(&ipmi_pci_driver); | 3376 | dmi_find_bmc(); |
3213 | if (rv) | 3377 | #endif |
3214 | printk(KERN_ERR | 3378 | |
3215 | "init_ipmi_si: Unable to register PCI driver: %d\n", | 3379 | #ifdef CONFIG_ACPI |
3216 | rv); | 3380 | spmi_find_bmc(); |
3217 | #endif | 3381 | #endif |
3218 | 3382 | ||
3219 | #ifdef CONFIG_PPC_OF | 3383 | #ifdef CONFIG_PPC_OF |
3220 | of_register_platform_driver(&ipmi_of_platform_driver); | 3384 | of_register_platform_driver(&ipmi_of_platform_driver); |
3385 | of_registered = 1; | ||
3221 | #endif | 3386 | #endif |
3222 | 3387 | ||
3388 | /* We prefer devices with interrupts, but in the case of a machine | ||
3389 | with multiple BMCs we assume that there will be several instances | ||
3390 | of a given type so if we succeed in registering a type then also | ||
3391 | try to register everything else of the same type */ | ||
3392 | |||
3393 | mutex_lock(&smi_infos_lock); | ||
3394 | list_for_each_entry(e, &smi_infos, link) { | ||
3395 | /* Try to register a device if it has an IRQ and we either | ||
3396 | haven't successfully registered a device yet or this | ||
3397 | device has the same type as one we successfully registered */ | ||
3398 | if (e->irq && (!type || e->addr_source == type)) { | ||
3399 | if (!try_smi_init(e)) { | ||
3400 | type = e->addr_source; | ||
3401 | } | ||
3402 | } | ||
3403 | } | ||
3404 | |||
3405 | /* type will only have been set if we successfully registered an si */ | ||
3406 | if (type) { | ||
3407 | mutex_unlock(&smi_infos_lock); | ||
3408 | return 0; | ||
3409 | } | ||
3410 | |||
3411 | /* Fall back to the preferred device */ | ||
3412 | |||
3413 | list_for_each_entry(e, &smi_infos, link) { | ||
3414 | if (!e->irq && (!type || e->addr_source == type)) { | ||
3415 | if (!try_smi_init(e)) { | ||
3416 | type = e->addr_source; | ||
3417 | } | ||
3418 | } | ||
3419 | } | ||
3420 | mutex_unlock(&smi_infos_lock); | ||
3421 | |||
3422 | if (type) | ||
3423 | return 0; | ||
3424 | |||
3223 | if (si_trydefaults) { | 3425 | if (si_trydefaults) { |
3224 | mutex_lock(&smi_infos_lock); | 3426 | mutex_lock(&smi_infos_lock); |
3225 | if (list_empty(&smi_infos)) { | 3427 | if (list_empty(&smi_infos)) { |
3226 | /* No BMC was found, try defaults. */ | 3428 | /* No BMC was found, try defaults. */ |
3227 | mutex_unlock(&smi_infos_lock); | 3429 | mutex_unlock(&smi_infos_lock); |
3228 | default_find_bmc(); | 3430 | default_find_bmc(); |
3229 | } else { | 3431 | } else |
3230 | mutex_unlock(&smi_infos_lock); | 3432 | mutex_unlock(&smi_infos_lock); |
3231 | } | ||
3232 | } | 3433 | } |
3233 | 3434 | ||
3234 | mutex_lock(&smi_infos_lock); | 3435 | mutex_lock(&smi_infos_lock); |
3235 | if (unload_when_empty && list_empty(&smi_infos)) { | 3436 | if (unload_when_empty && list_empty(&smi_infos)) { |
3236 | mutex_unlock(&smi_infos_lock); | 3437 | mutex_unlock(&smi_infos_lock); |
3237 | #ifdef CONFIG_PCI | 3438 | #ifdef CONFIG_PCI |
3238 | pci_unregister_driver(&ipmi_pci_driver); | 3439 | if (pci_registered) |
3440 | pci_unregister_driver(&ipmi_pci_driver); | ||
3239 | #endif | 3441 | #endif |
3240 | 3442 | ||
3241 | #ifdef CONFIG_PPC_OF | 3443 | #ifdef CONFIG_PPC_OF |
3242 | of_unregister_platform_driver(&ipmi_of_platform_driver); | 3444 | if (of_registered) |
3445 | of_unregister_platform_driver(&ipmi_of_platform_driver); | ||
3243 | #endif | 3446 | #endif |
3244 | driver_unregister(&ipmi_driver.driver); | 3447 | driver_unregister(&ipmi_driver.driver); |
3245 | printk(KERN_WARNING | 3448 | printk(KERN_WARNING PFX |
3246 | "ipmi_si: Unable to find any System Interface(s)\n"); | 3449 | "Unable to find any System Interface(s)\n"); |
3247 | return -ENODEV; | 3450 | return -ENODEV; |
3248 | } else { | 3451 | } else { |
3249 | mutex_unlock(&smi_infos_lock); | 3452 | mutex_unlock(&smi_infos_lock); |
@@ -3254,7 +3457,7 @@ module_init(init_ipmi_si); | |||
3254 | 3457 | ||
3255 | static void cleanup_one_si(struct smi_info *to_clean) | 3458 | static void cleanup_one_si(struct smi_info *to_clean) |
3256 | { | 3459 | { |
3257 | int rv; | 3460 | int rv = 0; |
3258 | unsigned long flags; | 3461 | unsigned long flags; |
3259 | 3462 | ||
3260 | if (!to_clean) | 3463 | if (!to_clean) |
@@ -3298,14 +3501,16 @@ static void cleanup_one_si(struct smi_info *to_clean) | |||
3298 | schedule_timeout_uninterruptible(1); | 3501 | schedule_timeout_uninterruptible(1); |
3299 | } | 3502 | } |
3300 | 3503 | ||
3301 | rv = ipmi_unregister_smi(to_clean->intf); | 3504 | if (to_clean->intf) |
3505 | rv = ipmi_unregister_smi(to_clean->intf); | ||
3506 | |||
3302 | if (rv) { | 3507 | if (rv) { |
3303 | printk(KERN_ERR | 3508 | printk(KERN_ERR PFX "Unable to unregister device: errno=%d\n", |
3304 | "ipmi_si: Unable to unregister device: errno=%d\n", | ||
3305 | rv); | 3509 | rv); |
3306 | } | 3510 | } |
3307 | 3511 | ||
3308 | to_clean->handlers->cleanup(to_clean->si_sm); | 3512 | if (to_clean->handlers) |
3513 | to_clean->handlers->cleanup(to_clean->si_sm); | ||
3309 | 3514 | ||
3310 | kfree(to_clean->si_sm); | 3515 | kfree(to_clean->si_sm); |
3311 | 3516 | ||
@@ -3320,7 +3525,7 @@ static void cleanup_one_si(struct smi_info *to_clean) | |||
3320 | kfree(to_clean); | 3525 | kfree(to_clean); |
3321 | } | 3526 | } |
3322 | 3527 | ||
3323 | static __exit void cleanup_ipmi_si(void) | 3528 | static void __exit cleanup_ipmi_si(void) |
3324 | { | 3529 | { |
3325 | struct smi_info *e, *tmp_e; | 3530 | struct smi_info *e, *tmp_e; |
3326 | 3531 | ||
@@ -3328,14 +3533,17 @@ static __exit void cleanup_ipmi_si(void) | |||
3328 | return; | 3533 | return; |
3329 | 3534 | ||
3330 | #ifdef CONFIG_PCI | 3535 | #ifdef CONFIG_PCI |
3331 | pci_unregister_driver(&ipmi_pci_driver); | 3536 | if (pci_registered) |
3537 | pci_unregister_driver(&ipmi_pci_driver); | ||
3332 | #endif | 3538 | #endif |
3333 | #ifdef CONFIG_ACPI | 3539 | #ifdef CONFIG_ACPI |
3334 | pnp_unregister_driver(&ipmi_pnp_driver); | 3540 | if (pnp_registered) |
3541 | pnp_unregister_driver(&ipmi_pnp_driver); | ||
3335 | #endif | 3542 | #endif |
3336 | 3543 | ||
3337 | #ifdef CONFIG_PPC_OF | 3544 | #ifdef CONFIG_PPC_OF |
3338 | of_unregister_platform_driver(&ipmi_of_platform_driver); | 3545 | if (of_registered) |
3546 | of_unregister_platform_driver(&ipmi_of_platform_driver); | ||
3339 | #endif | 3547 | #endif |
3340 | 3548 | ||
3341 | mutex_lock(&smi_infos_lock); | 3549 | mutex_lock(&smi_infos_lock); |
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index a4d57e31f713..f4d334f2536e 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #include <linux/moduleparam.h> | 35 | #include <linux/moduleparam.h> |
36 | #include <linux/ipmi.h> | 36 | #include <linux/ipmi.h> |
37 | #include <linux/ipmi_smi.h> | 37 | #include <linux/ipmi_smi.h> |
38 | #include <linux/smp_lock.h> | 38 | #include <linux/mutex.h> |
39 | #include <linux/watchdog.h> | 39 | #include <linux/watchdog.h> |
40 | #include <linux/miscdevice.h> | 40 | #include <linux/miscdevice.h> |
41 | #include <linux/init.h> | 41 | #include <linux/init.h> |
@@ -149,6 +149,7 @@ | |||
149 | #define WDIOC_GET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 22, int) | 149 | #define WDIOC_GET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 22, int) |
150 | #endif | 150 | #endif |
151 | 151 | ||
152 | static DEFINE_MUTEX(ipmi_watchdog_mutex); | ||
152 | static int nowayout = WATCHDOG_NOWAYOUT; | 153 | static int nowayout = WATCHDOG_NOWAYOUT; |
153 | 154 | ||
154 | static ipmi_user_t watchdog_user; | 155 | static ipmi_user_t watchdog_user; |
@@ -196,7 +197,7 @@ static void ipmi_unregister_watchdog(int ipmi_intf); | |||
196 | */ | 197 | */ |
197 | static int start_now; | 198 | static int start_now; |
198 | 199 | ||
199 | static int set_param_int(const char *val, struct kernel_param *kp) | 200 | static int set_param_timeout(const char *val, const struct kernel_param *kp) |
200 | { | 201 | { |
201 | char *endp; | 202 | char *endp; |
202 | int l; | 203 | int l; |
@@ -215,10 +216,11 @@ static int set_param_int(const char *val, struct kernel_param *kp) | |||
215 | return rv; | 216 | return rv; |
216 | } | 217 | } |
217 | 218 | ||
218 | static int get_param_int(char *buffer, struct kernel_param *kp) | 219 | static struct kernel_param_ops param_ops_timeout = { |
219 | { | 220 | .set = set_param_timeout, |
220 | return sprintf(buffer, "%i", *((int *)kp->arg)); | 221 | .get = param_get_int, |
221 | } | 222 | }; |
223 | #define param_check_timeout param_check_int | ||
222 | 224 | ||
223 | typedef int (*action_fn)(const char *intval, char *outval); | 225 | typedef int (*action_fn)(const char *intval, char *outval); |
224 | 226 | ||
@@ -227,7 +229,7 @@ static int preaction_op(const char *inval, char *outval); | |||
227 | static int preop_op(const char *inval, char *outval); | 229 | static int preop_op(const char *inval, char *outval); |
228 | static void check_parms(void); | 230 | static void check_parms(void); |
229 | 231 | ||
230 | static int set_param_str(const char *val, struct kernel_param *kp) | 232 | static int set_param_str(const char *val, const struct kernel_param *kp) |
231 | { | 233 | { |
232 | action_fn fn = (action_fn) kp->arg; | 234 | action_fn fn = (action_fn) kp->arg; |
233 | int rv = 0; | 235 | int rv = 0; |
@@ -251,7 +253,7 @@ static int set_param_str(const char *val, struct kernel_param *kp) | |||
251 | return rv; | 253 | return rv; |
252 | } | 254 | } |
253 | 255 | ||
254 | static int get_param_str(char *buffer, struct kernel_param *kp) | 256 | static int get_param_str(char *buffer, const struct kernel_param *kp) |
255 | { | 257 | { |
256 | action_fn fn = (action_fn) kp->arg; | 258 | action_fn fn = (action_fn) kp->arg; |
257 | int rv; | 259 | int rv; |
@@ -263,7 +265,7 @@ static int get_param_str(char *buffer, struct kernel_param *kp) | |||
263 | } | 265 | } |
264 | 266 | ||
265 | 267 | ||
266 | static int set_param_wdog_ifnum(const char *val, struct kernel_param *kp) | 268 | static int set_param_wdog_ifnum(const char *val, const struct kernel_param *kp) |
267 | { | 269 | { |
268 | int rv = param_set_int(val, kp); | 270 | int rv = param_set_int(val, kp); |
269 | if (rv) | 271 | if (rv) |
@@ -276,27 +278,38 @@ static int set_param_wdog_ifnum(const char *val, struct kernel_param *kp) | |||
276 | return 0; | 278 | return 0; |
277 | } | 279 | } |
278 | 280 | ||
279 | module_param_call(ifnum_to_use, set_param_wdog_ifnum, get_param_int, | 281 | static struct kernel_param_ops param_ops_wdog_ifnum = { |
280 | &ifnum_to_use, 0644); | 282 | .set = set_param_wdog_ifnum, |
283 | .get = param_get_int, | ||
284 | }; | ||
285 | |||
286 | #define param_check_wdog_ifnum param_check_int | ||
287 | |||
288 | static struct kernel_param_ops param_ops_str = { | ||
289 | .set = set_param_str, | ||
290 | .get = get_param_str, | ||
291 | }; | ||
292 | |||
293 | module_param(ifnum_to_use, wdog_ifnum, 0644); | ||
281 | MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog " | 294 | MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog " |
282 | "timer. Setting to -1 defaults to the first registered " | 295 | "timer. Setting to -1 defaults to the first registered " |
283 | "interface"); | 296 | "interface"); |
284 | 297 | ||
285 | module_param_call(timeout, set_param_int, get_param_int, &timeout, 0644); | 298 | module_param(timeout, timeout, 0644); |
286 | MODULE_PARM_DESC(timeout, "Timeout value in seconds."); | 299 | MODULE_PARM_DESC(timeout, "Timeout value in seconds."); |
287 | 300 | ||
288 | module_param_call(pretimeout, set_param_int, get_param_int, &pretimeout, 0644); | 301 | module_param(pretimeout, timeout, 0644); |
289 | MODULE_PARM_DESC(pretimeout, "Pretimeout value in seconds."); | 302 | MODULE_PARM_DESC(pretimeout, "Pretimeout value in seconds."); |
290 | 303 | ||
291 | module_param_call(action, set_param_str, get_param_str, action_op, 0644); | 304 | module_param_cb(action, ¶m_ops_str, action_op, 0644); |
292 | MODULE_PARM_DESC(action, "Timeout action. One of: " | 305 | MODULE_PARM_DESC(action, "Timeout action. One of: " |
293 | "reset, none, power_cycle, power_off."); | 306 | "reset, none, power_cycle, power_off."); |
294 | 307 | ||
295 | module_param_call(preaction, set_param_str, get_param_str, preaction_op, 0644); | 308 | module_param_cb(preaction, ¶m_ops_str, preaction_op, 0644); |
296 | MODULE_PARM_DESC(preaction, "Pretimeout action. One of: " | 309 | MODULE_PARM_DESC(preaction, "Pretimeout action. One of: " |
297 | "pre_none, pre_smi, pre_nmi, pre_int."); | 310 | "pre_none, pre_smi, pre_nmi, pre_int."); |
298 | 311 | ||
299 | module_param_call(preop, set_param_str, get_param_str, preop_op, 0644); | 312 | module_param_cb(preop, ¶m_ops_str, preop_op, 0644); |
300 | MODULE_PARM_DESC(preop, "Pretimeout driver operation. One of: " | 313 | MODULE_PARM_DESC(preop, "Pretimeout driver operation. One of: " |
301 | "preop_none, preop_panic, preop_give_data."); | 314 | "preop_none, preop_panic, preop_give_data."); |
302 | 315 | ||
@@ -659,7 +672,7 @@ static struct watchdog_info ident = { | |||
659 | .identity = "IPMI" | 672 | .identity = "IPMI" |
660 | }; | 673 | }; |
661 | 674 | ||
662 | static int ipmi_ioctl(struct inode *inode, struct file *file, | 675 | static int ipmi_ioctl(struct file *file, |
663 | unsigned int cmd, unsigned long arg) | 676 | unsigned int cmd, unsigned long arg) |
664 | { | 677 | { |
665 | void __user *argp = (void __user *)arg; | 678 | void __user *argp = (void __user *)arg; |
@@ -730,6 +743,19 @@ static int ipmi_ioctl(struct inode *inode, struct file *file, | |||
730 | } | 743 | } |
731 | } | 744 | } |
732 | 745 | ||
746 | static long ipmi_unlocked_ioctl(struct file *file, | ||
747 | unsigned int cmd, | ||
748 | unsigned long arg) | ||
749 | { | ||
750 | int ret; | ||
751 | |||
752 | mutex_lock(&ipmi_watchdog_mutex); | ||
753 | ret = ipmi_ioctl(file, cmd, arg); | ||
754 | mutex_unlock(&ipmi_watchdog_mutex); | ||
755 | |||
756 | return ret; | ||
757 | } | ||
758 | |||
733 | static ssize_t ipmi_write(struct file *file, | 759 | static ssize_t ipmi_write(struct file *file, |
734 | const char __user *buf, | 760 | const char __user *buf, |
735 | size_t len, | 761 | size_t len, |
@@ -819,7 +845,6 @@ static int ipmi_open(struct inode *ino, struct file *filep) | |||
819 | if (test_and_set_bit(0, &ipmi_wdog_open)) | 845 | if (test_and_set_bit(0, &ipmi_wdog_open)) |
820 | return -EBUSY; | 846 | return -EBUSY; |
821 | 847 | ||
822 | cycle_kernel_lock(); | ||
823 | 848 | ||
824 | /* | 849 | /* |
825 | * Don't start the timer now, let it start on the | 850 | * Don't start the timer now, let it start on the |
@@ -880,10 +905,11 @@ static const struct file_operations ipmi_wdog_fops = { | |||
880 | .read = ipmi_read, | 905 | .read = ipmi_read, |
881 | .poll = ipmi_poll, | 906 | .poll = ipmi_poll, |
882 | .write = ipmi_write, | 907 | .write = ipmi_write, |
883 | .ioctl = ipmi_ioctl, | 908 | .unlocked_ioctl = ipmi_unlocked_ioctl, |
884 | .open = ipmi_open, | 909 | .open = ipmi_open, |
885 | .release = ipmi_close, | 910 | .release = ipmi_close, |
886 | .fasync = ipmi_fasync, | 911 | .fasync = ipmi_fasync, |
912 | .llseek = no_llseek, | ||
887 | }; | 913 | }; |
888 | 914 | ||
889 | static struct miscdevice ipmi_wdog_miscdev = { | 915 | static struct miscdevice ipmi_wdog_miscdev = { |
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 300d5bd6cd06..c27e9d21fea9 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -113,6 +113,8 @@ | |||
113 | * 64-bit verification | 113 | * 64-bit verification |
114 | */ | 114 | */ |
115 | 115 | ||
116 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
117 | |||
116 | #include <linux/module.h> | 118 | #include <linux/module.h> |
117 | #include <linux/firmware.h> | 119 | #include <linux/firmware.h> |
118 | #include <linux/kernel.h> | 120 | #include <linux/kernel.h> |
@@ -122,12 +124,12 @@ | |||
122 | #include <linux/fs.h> | 124 | #include <linux/fs.h> |
123 | #include <linux/sched.h> | 125 | #include <linux/sched.h> |
124 | #include <linux/serial.h> | 126 | #include <linux/serial.h> |
125 | #include <linux/smp_lock.h> | ||
126 | #include <linux/mm.h> | 127 | #include <linux/mm.h> |
127 | #include <linux/interrupt.h> | 128 | #include <linux/interrupt.h> |
128 | #include <linux/timer.h> | 129 | #include <linux/timer.h> |
129 | #include <linux/delay.h> | 130 | #include <linux/delay.h> |
130 | #include <linux/ioport.h> | 131 | #include <linux/ioport.h> |
132 | #include <linux/slab.h> | ||
131 | 133 | ||
132 | #include <linux/uaccess.h> | 134 | #include <linux/uaccess.h> |
133 | #include <linux/io.h> | 135 | #include <linux/io.h> |
@@ -140,7 +142,6 @@ | |||
140 | #define InterruptTheCard(base) outw(0, (base) + 0xc) | 142 | #define InterruptTheCard(base) outw(0, (base) + 0xc) |
141 | #define ClearInterrupt(base) inw((base) + 0x0a) | 143 | #define ClearInterrupt(base) inw((base) + 0x0a) |
142 | 144 | ||
143 | #define pr_dbg(str...) pr_debug("ISICOM: " str) | ||
144 | #ifdef DEBUG | 145 | #ifdef DEBUG |
145 | #define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c)) | 146 | #define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c)) |
146 | #else | 147 | #else |
@@ -249,8 +250,7 @@ static int lock_card(struct isi_board *card) | |||
249 | spin_unlock_irqrestore(&card->card_lock, card->flags); | 250 | spin_unlock_irqrestore(&card->card_lock, card->flags); |
250 | msleep(10); | 251 | msleep(10); |
251 | } | 252 | } |
252 | printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n", | 253 | pr_warning("Failed to lock Card (0x%lx)\n", card->base); |
253 | card->base); | ||
254 | 254 | ||
255 | return 0; /* Failed to acquire the card! */ | 255 | return 0; /* Failed to acquire the card! */ |
256 | } | 256 | } |
@@ -379,13 +379,13 @@ static inline int __isicom_paranoia_check(struct isi_port const *port, | |||
379 | char *name, const char *routine) | 379 | char *name, const char *routine) |
380 | { | 380 | { |
381 | if (!port) { | 381 | if (!port) { |
382 | printk(KERN_WARNING "ISICOM: Warning: bad isicom magic for " | 382 | pr_warning("Warning: bad isicom magic for dev %s in %s.\n", |
383 | "dev %s in %s.\n", name, routine); | 383 | name, routine); |
384 | return 1; | 384 | return 1; |
385 | } | 385 | } |
386 | if (port->magic != ISICOM_MAGIC) { | 386 | if (port->magic != ISICOM_MAGIC) { |
387 | printk(KERN_WARNING "ISICOM: Warning: NULL isicom port for " | 387 | pr_warning("Warning: NULL isicom port for dev %s in %s.\n", |
388 | "dev %s in %s.\n", name, routine); | 388 | name, routine); |
389 | return 1; | 389 | return 1; |
390 | } | 390 | } |
391 | 391 | ||
@@ -450,8 +450,8 @@ static void isicom_tx(unsigned long _data) | |||
450 | if (!(inw(base + 0x02) & (1 << port->channel))) | 450 | if (!(inw(base + 0x02) & (1 << port->channel))) |
451 | continue; | 451 | continue; |
452 | 452 | ||
453 | pr_dbg("txing %d bytes, port%d.\n", txcount, | 453 | pr_debug("txing %d bytes, port%d.\n", |
454 | port->channel + 1); | 454 | txcount, port->channel + 1); |
455 | outw((port->channel << isi_card[card].shift_count) | txcount, | 455 | outw((port->channel << isi_card[card].shift_count) | txcount, |
456 | base); | 456 | base); |
457 | residue = NO; | 457 | residue = NO; |
@@ -547,8 +547,8 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
547 | byte_count = header & 0xff; | 547 | byte_count = header & 0xff; |
548 | 548 | ||
549 | if (channel + 1 > card->port_count) { | 549 | if (channel + 1 > card->port_count) { |
550 | printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%lx): " | 550 | pr_warning("%s(0x%lx): %d(channel) > port_count.\n", |
551 | "%d(channel) > port_count.\n", base, channel+1); | 551 | __func__, base, channel+1); |
552 | outw(0x0000, base+0x04); /* enable interrupts */ | 552 | outw(0x0000, base+0x04); /* enable interrupts */ |
553 | spin_unlock(&card->card_lock); | 553 | spin_unlock(&card->card_lock); |
554 | return IRQ_HANDLED; | 554 | return IRQ_HANDLED; |
@@ -582,14 +582,15 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
582 | if (port->status & ISI_DCD) { | 582 | if (port->status & ISI_DCD) { |
583 | if (!(header & ISI_DCD)) { | 583 | if (!(header & ISI_DCD)) { |
584 | /* Carrier has been lost */ | 584 | /* Carrier has been lost */ |
585 | pr_dbg("interrupt: DCD->low.\n" | 585 | pr_debug("%s: DCD->low.\n", |
586 | ); | 586 | __func__); |
587 | port->status &= ~ISI_DCD; | 587 | port->status &= ~ISI_DCD; |
588 | tty_hangup(tty); | 588 | tty_hangup(tty); |
589 | } | 589 | } |
590 | } else if (header & ISI_DCD) { | 590 | } else if (header & ISI_DCD) { |
591 | /* Carrier has been detected */ | 591 | /* Carrier has been detected */ |
592 | pr_dbg("interrupt: DCD->high.\n"); | 592 | pr_debug("%s: DCD->high.\n", |
593 | __func__); | ||
593 | port->status |= ISI_DCD; | 594 | port->status |= ISI_DCD; |
594 | wake_up_interruptible(&port->port.open_wait); | 595 | wake_up_interruptible(&port->port.open_wait); |
595 | } | 596 | } |
@@ -641,17 +642,19 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
641 | break; | 642 | break; |
642 | 643 | ||
643 | case 2: /* Statistics */ | 644 | case 2: /* Statistics */ |
644 | pr_dbg("isicom_interrupt: stats!!!.\n"); | 645 | pr_debug("%s: stats!!!\n", __func__); |
645 | break; | 646 | break; |
646 | 647 | ||
647 | default: | 648 | default: |
648 | pr_dbg("Intr: Unknown code in status packet.\n"); | 649 | pr_debug("%s: Unknown code in status packet.\n", |
650 | __func__); | ||
649 | break; | 651 | break; |
650 | } | 652 | } |
651 | } else { /* Data Packet */ | 653 | } else { /* Data Packet */ |
652 | 654 | ||
653 | count = tty_prepare_flip_string(tty, &rp, byte_count & ~1); | 655 | count = tty_prepare_flip_string(tty, &rp, byte_count & ~1); |
654 | pr_dbg("Intr: Can rx %d of %d bytes.\n", count, byte_count); | 656 | pr_debug("%s: Can rx %d of %d bytes.\n", |
657 | __func__, count, byte_count); | ||
655 | word_count = count >> 1; | 658 | word_count = count >> 1; |
656 | insw(base, rp, word_count); | 659 | insw(base, rp, word_count); |
657 | byte_count -= (word_count << 1); | 660 | byte_count -= (word_count << 1); |
@@ -661,8 +664,8 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
661 | byte_count -= 2; | 664 | byte_count -= 2; |
662 | } | 665 | } |
663 | if (byte_count > 0) { | 666 | if (byte_count > 0) { |
664 | pr_dbg("Intr(0x%lx:%d): Flip buffer overflow! dropping " | 667 | pr_debug("%s(0x%lx:%d): Flip buffer overflow! dropping bytes...\n", |
665 | "bytes...\n", base, channel + 1); | 668 | __func__, base, channel + 1); |
666 | /* drain out unread xtra data */ | 669 | /* drain out unread xtra data */ |
667 | while (byte_count > 0) { | 670 | while (byte_count > 0) { |
668 | inw(base); | 671 | inw(base); |
@@ -868,15 +871,14 @@ static struct tty_port *isicom_find_port(struct tty_struct *tty) | |||
868 | static int isicom_open(struct tty_struct *tty, struct file *filp) | 871 | static int isicom_open(struct tty_struct *tty, struct file *filp) |
869 | { | 872 | { |
870 | struct isi_port *port; | 873 | struct isi_port *port; |
871 | struct isi_board *card; | ||
872 | struct tty_port *tport; | 874 | struct tty_port *tport; |
873 | 875 | ||
874 | tport = isicom_find_port(tty); | 876 | tport = isicom_find_port(tty); |
875 | if (tport == NULL) | 877 | if (tport == NULL) |
876 | return -ENODEV; | 878 | return -ENODEV; |
877 | port = container_of(tport, struct isi_port, port); | 879 | port = container_of(tport, struct isi_port, port); |
878 | card = &isi_card[BOARD(tty->index)]; | ||
879 | 880 | ||
881 | tty->driver_data = port; | ||
880 | return tty_port_open(tport, tty, filp); | 882 | return tty_port_open(tport, tty, filp); |
881 | } | 883 | } |
882 | 884 | ||
@@ -888,8 +890,8 @@ static void isicom_shutdown_port(struct isi_port *port) | |||
888 | struct isi_board *card = port->card; | 890 | struct isi_board *card = port->card; |
889 | 891 | ||
890 | if (--card->count < 0) { | 892 | if (--card->count < 0) { |
891 | pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n", | 893 | pr_debug("%s: bad board(0x%lx) count %d.\n", |
892 | card->base, card->count); | 894 | __func__, card->base, card->count); |
893 | card->count = 0; | 895 | card->count = 0; |
894 | } | 896 | } |
895 | /* last port was closed, shutdown that board too */ | 897 | /* last port was closed, shutdown that board too */ |
@@ -932,7 +934,12 @@ static void isicom_shutdown(struct tty_port *port) | |||
932 | static void isicom_close(struct tty_struct *tty, struct file *filp) | 934 | static void isicom_close(struct tty_struct *tty, struct file *filp) |
933 | { | 935 | { |
934 | struct isi_port *ip = tty->driver_data; | 936 | struct isi_port *ip = tty->driver_data; |
935 | struct tty_port *port = &ip->port; | 937 | struct tty_port *port; |
938 | |||
939 | if (ip == NULL) | ||
940 | return; | ||
941 | |||
942 | port = &ip->port; | ||
936 | if (isicom_paranoia_check(ip, tty->name, "isicom_close")) | 943 | if (isicom_paranoia_check(ip, tty->name, "isicom_close")) |
937 | return; | 944 | return; |
938 | tty_port_close(port, tty, filp); | 945 | tty_port_close(port, tty, filp); |
@@ -1109,8 +1116,7 @@ static int isicom_set_serial_info(struct tty_struct *tty, | |||
1109 | if (copy_from_user(&newinfo, info, sizeof(newinfo))) | 1116 | if (copy_from_user(&newinfo, info, sizeof(newinfo))) |
1110 | return -EFAULT; | 1117 | return -EFAULT; |
1111 | 1118 | ||
1112 | lock_kernel(); | 1119 | mutex_lock(&port->port.mutex); |
1113 | |||
1114 | reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) != | 1120 | reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) != |
1115 | (newinfo.flags & ASYNC_SPD_MASK)); | 1121 | (newinfo.flags & ASYNC_SPD_MASK)); |
1116 | 1122 | ||
@@ -1119,7 +1125,7 @@ static int isicom_set_serial_info(struct tty_struct *tty, | |||
1119 | (newinfo.closing_wait != port->port.closing_wait) || | 1125 | (newinfo.closing_wait != port->port.closing_wait) || |
1120 | ((newinfo.flags & ~ASYNC_USR_MASK) != | 1126 | ((newinfo.flags & ~ASYNC_USR_MASK) != |
1121 | (port->port.flags & ~ASYNC_USR_MASK))) { | 1127 | (port->port.flags & ~ASYNC_USR_MASK))) { |
1122 | unlock_kernel(); | 1128 | mutex_unlock(&port->port.mutex); |
1123 | return -EPERM; | 1129 | return -EPERM; |
1124 | } | 1130 | } |
1125 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | | 1131 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | |
@@ -1136,7 +1142,7 @@ static int isicom_set_serial_info(struct tty_struct *tty, | |||
1136 | isicom_config_port(tty); | 1142 | isicom_config_port(tty); |
1137 | spin_unlock_irqrestore(&port->card->card_lock, flags); | 1143 | spin_unlock_irqrestore(&port->card->card_lock, flags); |
1138 | } | 1144 | } |
1139 | unlock_kernel(); | 1145 | mutex_unlock(&port->port.mutex); |
1140 | return 0; | 1146 | return 0; |
1141 | } | 1147 | } |
1142 | 1148 | ||
@@ -1145,7 +1151,7 @@ static int isicom_get_serial_info(struct isi_port *port, | |||
1145 | { | 1151 | { |
1146 | struct serial_struct out_info; | 1152 | struct serial_struct out_info; |
1147 | 1153 | ||
1148 | lock_kernel(); | 1154 | mutex_lock(&port->port.mutex); |
1149 | memset(&out_info, 0, sizeof(out_info)); | 1155 | memset(&out_info, 0, sizeof(out_info)); |
1150 | /* out_info.type = ? */ | 1156 | /* out_info.type = ? */ |
1151 | out_info.line = port - isi_ports; | 1157 | out_info.line = port - isi_ports; |
@@ -1155,7 +1161,7 @@ static int isicom_get_serial_info(struct isi_port *port, | |||
1155 | /* out_info.baud_base = ? */ | 1161 | /* out_info.baud_base = ? */ |
1156 | out_info.close_delay = port->port.close_delay; | 1162 | out_info.close_delay = port->port.close_delay; |
1157 | out_info.closing_wait = port->port.closing_wait; | 1163 | out_info.closing_wait = port->port.closing_wait; |
1158 | unlock_kernel(); | 1164 | mutex_unlock(&port->port.mutex); |
1159 | if (copy_to_user(info, &out_info, sizeof(out_info))) | 1165 | if (copy_to_user(info, &out_info, sizeof(out_info))) |
1160 | return -EFAULT; | 1166 | return -EFAULT; |
1161 | return 0; | 1167 | return 0; |
@@ -1564,11 +1570,16 @@ static int __devinit isicom_probe(struct pci_dev *pdev, | |||
1564 | dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device); | 1570 | dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device); |
1565 | 1571 | ||
1566 | /* allot the first empty slot in the array */ | 1572 | /* allot the first empty slot in the array */ |
1567 | for (index = 0; index < BOARD_COUNT; index++) | 1573 | for (index = 0; index < BOARD_COUNT; index++) { |
1568 | if (isi_card[index].base == 0) { | 1574 | if (isi_card[index].base == 0) { |
1569 | board = &isi_card[index]; | 1575 | board = &isi_card[index]; |
1570 | break; | 1576 | break; |
1571 | } | 1577 | } |
1578 | } | ||
1579 | if (index == BOARD_COUNT) { | ||
1580 | retval = -ENODEV; | ||
1581 | goto err_disable; | ||
1582 | } | ||
1572 | 1583 | ||
1573 | board->index = index; | 1584 | board->index = index; |
1574 | board->base = pci_resource_start(pdev, 3); | 1585 | board->base = pci_resource_start(pdev, 3); |
@@ -1615,6 +1626,7 @@ errunrr: | |||
1615 | errdec: | 1626 | errdec: |
1616 | board->base = 0; | 1627 | board->base = 0; |
1617 | card_count--; | 1628 | card_count--; |
1629 | err_disable: | ||
1618 | pci_disable_device(pdev); | 1630 | pci_disable_device(pdev); |
1619 | err: | 1631 | err: |
1620 | return retval; | 1632 | return retval; |
@@ -1681,13 +1693,13 @@ static int __init isicom_init(void) | |||
1681 | 1693 | ||
1682 | retval = tty_register_driver(isicom_normal); | 1694 | retval = tty_register_driver(isicom_normal); |
1683 | if (retval) { | 1695 | if (retval) { |
1684 | pr_dbg("Couldn't register the dialin driver\n"); | 1696 | pr_debug("Couldn't register the dialin driver\n"); |
1685 | goto err_puttty; | 1697 | goto err_puttty; |
1686 | } | 1698 | } |
1687 | 1699 | ||
1688 | retval = pci_register_driver(&isicom_driver); | 1700 | retval = pci_register_driver(&isicom_driver); |
1689 | if (retval < 0) { | 1701 | if (retval < 0) { |
1690 | printk(KERN_ERR "ISICOM: Unable to register pci driver.\n"); | 1702 | pr_err("Unable to register pci driver.\n"); |
1691 | goto err_unrtty; | 1703 | goto err_unrtty; |
1692 | } | 1704 | } |
1693 | 1705 | ||
@@ -1717,3 +1729,8 @@ module_exit(isicom_exit); | |||
1717 | MODULE_AUTHOR("MultiTech"); | 1729 | MODULE_AUTHOR("MultiTech"); |
1718 | MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech"); | 1730 | MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech"); |
1719 | MODULE_LICENSE("GPL"); | 1731 | MODULE_LICENSE("GPL"); |
1732 | MODULE_FIRMWARE("isi608.bin"); | ||
1733 | MODULE_FIRMWARE("isi608em.bin"); | ||
1734 | MODULE_FIRMWARE("isi616em.bin"); | ||
1735 | MODULE_FIRMWARE("isi4608.bin"); | ||
1736 | MODULE_FIRMWARE("isi4616.bin"); | ||
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 4cd6c527ee41..667abd23ad6a 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -203,9 +203,9 @@ static int stli_shared; | |||
203 | * the board has been detected, and whether it is actually running a slave | 203 | * the board has been detected, and whether it is actually running a slave |
204 | * or not. | 204 | * or not. |
205 | */ | 205 | */ |
206 | #define BST_FOUND 0x1 | 206 | #define BST_FOUND 0 |
207 | #define BST_STARTED 0x2 | 207 | #define BST_STARTED 1 |
208 | #define BST_PROBED 0x4 | 208 | #define BST_PROBED 2 |
209 | 209 | ||
210 | /* | 210 | /* |
211 | * Define the set of port state flags. These are marked for internal | 211 | * Define the set of port state flags. These are marked for internal |
@@ -704,6 +704,7 @@ static const struct file_operations stli_fsiomem = { | |||
704 | .read = stli_memread, | 704 | .read = stli_memread, |
705 | .write = stli_memwrite, | 705 | .write = stli_memwrite, |
706 | .unlocked_ioctl = stli_memioctl, | 706 | .unlocked_ioctl = stli_memioctl, |
707 | .llseek = default_llseek, | ||
707 | }; | 708 | }; |
708 | 709 | ||
709 | /*****************************************************************************/ | 710 | /*****************************************************************************/ |
@@ -816,7 +817,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp) | |||
816 | brdp = stli_brds[brdnr]; | 817 | brdp = stli_brds[brdnr]; |
817 | if (brdp == NULL) | 818 | if (brdp == NULL) |
818 | return -ENODEV; | 819 | return -ENODEV; |
819 | if ((brdp->state & BST_STARTED) == 0) | 820 | if (!test_bit(BST_STARTED, &brdp->state)) |
820 | return -ENODEV; | 821 | return -ENODEV; |
821 | portnr = MINOR2PORT(minordev); | 822 | portnr = MINOR2PORT(minordev); |
822 | if (portnr > brdp->nrports) | 823 | if (portnr > brdp->nrports) |
@@ -827,6 +828,8 @@ static int stli_open(struct tty_struct *tty, struct file *filp) | |||
827 | return -ENODEV; | 828 | return -ENODEV; |
828 | if (portp->devnr < 1) | 829 | if (portp->devnr < 1) |
829 | return -ENODEV; | 830 | return -ENODEV; |
831 | |||
832 | tty->driver_data = portp; | ||
830 | return tty_port_open(&portp->port, tty, filp); | 833 | return tty_port_open(&portp->port, tty, filp); |
831 | } | 834 | } |
832 | 835 | ||
@@ -952,7 +955,7 @@ static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned l | |||
952 | * order of opens and closes may not be preserved across shared | 955 | * order of opens and closes may not be preserved across shared |
953 | * memory, so we must wait until it is complete. | 956 | * memory, so we must wait until it is complete. |
954 | */ | 957 | */ |
955 | wait_event_interruptible(portp->raw_wait, | 958 | wait_event_interruptible_tty(portp->raw_wait, |
956 | !test_bit(ST_CLOSING, &portp->state)); | 959 | !test_bit(ST_CLOSING, &portp->state)); |
957 | if (signal_pending(current)) { | 960 | if (signal_pending(current)) { |
958 | return -ERESTARTSYS; | 961 | return -ERESTARTSYS; |
@@ -987,7 +990,7 @@ static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned l | |||
987 | set_bit(ST_OPENING, &portp->state); | 990 | set_bit(ST_OPENING, &portp->state); |
988 | spin_unlock_irqrestore(&brd_lock, flags); | 991 | spin_unlock_irqrestore(&brd_lock, flags); |
989 | 992 | ||
990 | wait_event_interruptible(portp->raw_wait, | 993 | wait_event_interruptible_tty(portp->raw_wait, |
991 | !test_bit(ST_OPENING, &portp->state)); | 994 | !test_bit(ST_OPENING, &portp->state)); |
992 | if (signal_pending(current)) | 995 | if (signal_pending(current)) |
993 | rc = -ERESTARTSYS; | 996 | rc = -ERESTARTSYS; |
@@ -1018,7 +1021,7 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned | |||
1018 | * occurs on this port. | 1021 | * occurs on this port. |
1019 | */ | 1022 | */ |
1020 | if (wait) { | 1023 | if (wait) { |
1021 | wait_event_interruptible(portp->raw_wait, | 1024 | wait_event_interruptible_tty(portp->raw_wait, |
1022 | !test_bit(ST_CLOSING, &portp->state)); | 1025 | !test_bit(ST_CLOSING, &portp->state)); |
1023 | if (signal_pending(current)) { | 1026 | if (signal_pending(current)) { |
1024 | return -ERESTARTSYS; | 1027 | return -ERESTARTSYS; |
@@ -1050,7 +1053,7 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned | |||
1050 | * to come back. | 1053 | * to come back. |
1051 | */ | 1054 | */ |
1052 | rc = 0; | 1055 | rc = 0; |
1053 | wait_event_interruptible(portp->raw_wait, | 1056 | wait_event_interruptible_tty(portp->raw_wait, |
1054 | !test_bit(ST_CLOSING, &portp->state)); | 1057 | !test_bit(ST_CLOSING, &portp->state)); |
1055 | if (signal_pending(current)) | 1058 | if (signal_pending(current)) |
1056 | rc = -ERESTARTSYS; | 1059 | rc = -ERESTARTSYS; |
@@ -1071,6 +1074,10 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned | |||
1071 | 1074 | ||
1072 | static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) | 1075 | static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) |
1073 | { | 1076 | { |
1077 | /* | ||
1078 | * no need for wait_event_tty because clearing ST_CMDING cannot block | ||
1079 | * on BTM | ||
1080 | */ | ||
1074 | wait_event_interruptible(portp->raw_wait, | 1081 | wait_event_interruptible(portp->raw_wait, |
1075 | !test_bit(ST_CMDING, &portp->state)); | 1082 | !test_bit(ST_CMDING, &portp->state)); |
1076 | if (signal_pending(current)) | 1083 | if (signal_pending(current)) |
@@ -1844,7 +1851,7 @@ static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stlip | |||
1844 | rc = stli_portcmdstats(NULL, portp); | 1851 | rc = stli_portcmdstats(NULL, portp); |
1845 | 1852 | ||
1846 | uart = "UNKNOWN"; | 1853 | uart = "UNKNOWN"; |
1847 | if (brdp->state & BST_STARTED) { | 1854 | if (test_bit(BST_STARTED, &brdp->state)) { |
1848 | switch (stli_comstats.hwid) { | 1855 | switch (stli_comstats.hwid) { |
1849 | case 0: uart = "2681"; break; | 1856 | case 0: uart = "2681"; break; |
1850 | case 1: uart = "SC26198"; break; | 1857 | case 1: uart = "SC26198"; break; |
@@ -1853,7 +1860,7 @@ static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stlip | |||
1853 | } | 1860 | } |
1854 | seq_printf(m, "%d: uart:%s ", portnr, uart); | 1861 | seq_printf(m, "%d: uart:%s ", portnr, uart); |
1855 | 1862 | ||
1856 | if ((brdp->state & BST_STARTED) && (rc >= 0)) { | 1863 | if (test_bit(BST_STARTED, &brdp->state) && rc >= 0) { |
1857 | char sep; | 1864 | char sep; |
1858 | 1865 | ||
1859 | seq_printf(m, "tx:%d rx:%d", (int) stli_comstats.txtotal, | 1866 | seq_printf(m, "tx:%d rx:%d", (int) stli_comstats.txtotal, |
@@ -2353,7 +2360,7 @@ static void stli_poll(unsigned long arg) | |||
2353 | brdp = stli_brds[brdnr]; | 2360 | brdp = stli_brds[brdnr]; |
2354 | if (brdp == NULL) | 2361 | if (brdp == NULL) |
2355 | continue; | 2362 | continue; |
2356 | if ((brdp->state & BST_STARTED) == 0) | 2363 | if (!test_bit(BST_STARTED, &brdp->state)) |
2357 | continue; | 2364 | continue; |
2358 | 2365 | ||
2359 | spin_lock(&brd_lock); | 2366 | spin_lock(&brd_lock); |
@@ -3138,7 +3145,7 @@ static int stli_initecp(struct stlibrd *brdp) | |||
3138 | } | 3145 | } |
3139 | 3146 | ||
3140 | 3147 | ||
3141 | brdp->state |= BST_FOUND; | 3148 | set_bit(BST_FOUND, &brdp->state); |
3142 | return 0; | 3149 | return 0; |
3143 | err_unmap: | 3150 | err_unmap: |
3144 | iounmap(brdp->membase); | 3151 | iounmap(brdp->membase); |
@@ -3295,7 +3302,7 @@ static int stli_initonb(struct stlibrd *brdp) | |||
3295 | brdp->panels[0] = brdp->nrports; | 3302 | brdp->panels[0] = brdp->nrports; |
3296 | 3303 | ||
3297 | 3304 | ||
3298 | brdp->state |= BST_FOUND; | 3305 | set_bit(BST_FOUND, &brdp->state); |
3299 | return 0; | 3306 | return 0; |
3300 | err_unmap: | 3307 | err_unmap: |
3301 | iounmap(brdp->membase); | 3308 | iounmap(brdp->membase); |
@@ -3405,7 +3412,7 @@ stli_donestartup: | |||
3405 | spin_unlock_irqrestore(&brd_lock, flags); | 3412 | spin_unlock_irqrestore(&brd_lock, flags); |
3406 | 3413 | ||
3407 | if (rc == 0) | 3414 | if (rc == 0) |
3408 | brdp->state |= BST_STARTED; | 3415 | set_bit(BST_STARTED, &brdp->state); |
3409 | 3416 | ||
3410 | if (! stli_timeron) { | 3417 | if (! stli_timeron) { |
3411 | stli_timeron++; | 3418 | stli_timeron++; |
@@ -3708,7 +3715,7 @@ static int __devinit stli_pciprobe(struct pci_dev *pdev, | |||
3708 | if (retval) | 3715 | if (retval) |
3709 | goto err_null; | 3716 | goto err_null; |
3710 | 3717 | ||
3711 | brdp->state |= BST_PROBED; | 3718 | set_bit(BST_PROBED, &brdp->state); |
3712 | pci_set_drvdata(pdev, brdp); | 3719 | pci_set_drvdata(pdev, brdp); |
3713 | 3720 | ||
3714 | EBRDENABLE(brdp); | 3721 | EBRDENABLE(brdp); |
@@ -3839,7 +3846,7 @@ static int __init stli_initbrds(void) | |||
3839 | brdp = stli_brds[i]; | 3846 | brdp = stli_brds[i]; |
3840 | if (brdp == NULL) | 3847 | if (brdp == NULL) |
3841 | continue; | 3848 | continue; |
3842 | if (brdp->state & BST_FOUND) { | 3849 | if (test_bit(BST_FOUND, &brdp->state)) { |
3843 | EBRDENABLE(brdp); | 3850 | EBRDENABLE(brdp); |
3844 | brdp->enable = NULL; | 3851 | brdp->enable = NULL; |
3845 | brdp->disable = NULL; | 3852 | brdp->disable = NULL; |
@@ -4009,6 +4016,7 @@ static int stli_getbrdstats(combrd_t __user *bp) | |||
4009 | return -ENODEV; | 4016 | return -ENODEV; |
4010 | 4017 | ||
4011 | memset(&stli_brdstats, 0, sizeof(combrd_t)); | 4018 | memset(&stli_brdstats, 0, sizeof(combrd_t)); |
4019 | |||
4012 | stli_brdstats.brd = brdp->brdnr; | 4020 | stli_brdstats.brd = brdp->brdnr; |
4013 | stli_brdstats.type = brdp->brdtype; | 4021 | stli_brdstats.type = brdp->brdtype; |
4014 | stli_brdstats.hwid = 0; | 4022 | stli_brdstats.hwid = 0; |
@@ -4074,10 +4082,13 @@ static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp) | |||
4074 | if (brdp == NULL) | 4082 | if (brdp == NULL) |
4075 | return -ENODEV; | 4083 | return -ENODEV; |
4076 | 4084 | ||
4077 | if (brdp->state & BST_STARTED) { | 4085 | mutex_lock(&portp->port.mutex); |
4086 | if (test_bit(BST_STARTED, &brdp->state)) { | ||
4078 | if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS, | 4087 | if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS, |
4079 | &stli_cdkstats, sizeof(asystats_t), 1)) < 0) | 4088 | &stli_cdkstats, sizeof(asystats_t), 1)) < 0) { |
4089 | mutex_unlock(&portp->port.mutex); | ||
4080 | return rc; | 4090 | return rc; |
4091 | } | ||
4081 | } else { | 4092 | } else { |
4082 | memset(&stli_cdkstats, 0, sizeof(asystats_t)); | 4093 | memset(&stli_cdkstats, 0, sizeof(asystats_t)); |
4083 | } | 4094 | } |
@@ -4122,6 +4133,7 @@ static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp) | |||
4122 | stli_comstats.modem = stli_cdkstats.dcdcnt; | 4133 | stli_comstats.modem = stli_cdkstats.dcdcnt; |
4123 | stli_comstats.hwid = stli_cdkstats.hwid; | 4134 | stli_comstats.hwid = stli_cdkstats.hwid; |
4124 | stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals); | 4135 | stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals); |
4136 | mutex_unlock(&portp->port.mutex); | ||
4125 | 4137 | ||
4126 | return 0; | 4138 | return 0; |
4127 | } | 4139 | } |
@@ -4184,15 +4196,20 @@ static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp) | |||
4184 | if (!brdp) | 4196 | if (!brdp) |
4185 | return -ENODEV; | 4197 | return -ENODEV; |
4186 | 4198 | ||
4187 | if (brdp->state & BST_STARTED) { | 4199 | mutex_lock(&portp->port.mutex); |
4188 | if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0) | 4200 | |
4201 | if (test_bit(BST_STARTED, &brdp->state)) { | ||
4202 | if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0) { | ||
4203 | mutex_unlock(&portp->port.mutex); | ||
4189 | return rc; | 4204 | return rc; |
4205 | } | ||
4190 | } | 4206 | } |
4191 | 4207 | ||
4192 | memset(&stli_comstats, 0, sizeof(comstats_t)); | 4208 | memset(&stli_comstats, 0, sizeof(comstats_t)); |
4193 | stli_comstats.brd = portp->brdnr; | 4209 | stli_comstats.brd = portp->brdnr; |
4194 | stli_comstats.panel = portp->panelnr; | 4210 | stli_comstats.panel = portp->panelnr; |
4195 | stli_comstats.port = portp->portnr; | 4211 | stli_comstats.port = portp->portnr; |
4212 | mutex_unlock(&portp->port.mutex); | ||
4196 | 4213 | ||
4197 | if (copy_to_user(cp, &stli_comstats, sizeof(comstats_t))) | 4214 | if (copy_to_user(cp, &stli_comstats, sizeof(comstats_t))) |
4198 | return -EFAULT; | 4215 | return -EFAULT; |
@@ -4264,8 +4281,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
4264 | done = 0; | 4281 | done = 0; |
4265 | rc = 0; | 4282 | rc = 0; |
4266 | 4283 | ||
4267 | lock_kernel(); | ||
4268 | |||
4269 | switch (cmd) { | 4284 | switch (cmd) { |
4270 | case COM_GETPORTSTATS: | 4285 | case COM_GETPORTSTATS: |
4271 | rc = stli_getportstats(NULL, NULL, argp); | 4286 | rc = stli_getportstats(NULL, NULL, argp); |
@@ -4288,8 +4303,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
4288 | done++; | 4303 | done++; |
4289 | break; | 4304 | break; |
4290 | } | 4305 | } |
4291 | unlock_kernel(); | ||
4292 | |||
4293 | if (done) | 4306 | if (done) |
4294 | return rc; | 4307 | return rc; |
4295 | 4308 | ||
@@ -4306,8 +4319,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
4306 | if (brdp->state == 0) | 4319 | if (brdp->state == 0) |
4307 | return -ENODEV; | 4320 | return -ENODEV; |
4308 | 4321 | ||
4309 | lock_kernel(); | ||
4310 | |||
4311 | switch (cmd) { | 4322 | switch (cmd) { |
4312 | case STL_BINTR: | 4323 | case STL_BINTR: |
4313 | EBRDINTR(brdp); | 4324 | EBRDINTR(brdp); |
@@ -4316,10 +4327,10 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
4316 | rc = stli_startbrd(brdp); | 4327 | rc = stli_startbrd(brdp); |
4317 | break; | 4328 | break; |
4318 | case STL_BSTOP: | 4329 | case STL_BSTOP: |
4319 | brdp->state &= ~BST_STARTED; | 4330 | clear_bit(BST_STARTED, &brdp->state); |
4320 | break; | 4331 | break; |
4321 | case STL_BRESET: | 4332 | case STL_BRESET: |
4322 | brdp->state &= ~BST_STARTED; | 4333 | clear_bit(BST_STARTED, &brdp->state); |
4323 | EBRDRESET(brdp); | 4334 | EBRDRESET(brdp); |
4324 | if (stli_shared == 0) { | 4335 | if (stli_shared == 0) { |
4325 | if (brdp->reenable != NULL) | 4336 | if (brdp->reenable != NULL) |
@@ -4330,7 +4341,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
4330 | rc = -ENOIOCTLCMD; | 4341 | rc = -ENOIOCTLCMD; |
4331 | break; | 4342 | break; |
4332 | } | 4343 | } |
4333 | unlock_kernel(); | ||
4334 | return rc; | 4344 | return rc; |
4335 | } | 4345 | } |
4336 | 4346 | ||
@@ -4376,7 +4386,8 @@ static void istallion_cleanup_isa(void) | |||
4376 | unsigned int j; | 4386 | unsigned int j; |
4377 | 4387 | ||
4378 | for (j = 0; (j < stli_nrbrds); j++) { | 4388 | for (j = 0; (j < stli_nrbrds); j++) { |
4379 | if ((brdp = stli_brds[j]) == NULL || (brdp->state & BST_PROBED)) | 4389 | if ((brdp = stli_brds[j]) == NULL || |
4390 | test_bit(BST_PROBED, &brdp->state)) | ||
4380 | continue; | 4391 | continue; |
4381 | 4392 | ||
4382 | stli_cleanup_ports(brdp); | 4393 | stli_cleanup_ports(brdp); |
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index f706b1dffdb3..e95d7876ca6b 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
@@ -24,6 +24,8 @@ | |||
24 | * 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik) | 24 | * 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik) |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
28 | |||
27 | #include <linux/consolemap.h> | 29 | #include <linux/consolemap.h> |
28 | #include <linux/module.h> | 30 | #include <linux/module.h> |
29 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
@@ -38,7 +40,6 @@ | |||
38 | #include <linux/kbd_kern.h> | 40 | #include <linux/kbd_kern.h> |
39 | #include <linux/kbd_diacr.h> | 41 | #include <linux/kbd_diacr.h> |
40 | #include <linux/vt_kern.h> | 42 | #include <linux/vt_kern.h> |
41 | #include <linux/sysrq.h> | ||
42 | #include <linux/input.h> | 43 | #include <linux/input.h> |
43 | #include <linux/reboot.h> | 44 | #include <linux/reboot.h> |
44 | #include <linux/notifier.h> | 45 | #include <linux/notifier.h> |
@@ -82,8 +83,7 @@ void compute_shiftstate(void); | |||
82 | typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value, | 83 | typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value, |
83 | char up_flag); | 84 | char up_flag); |
84 | static k_handler_fn K_HANDLERS; | 85 | static k_handler_fn K_HANDLERS; |
85 | k_handler_fn *k_handler[16] = { K_HANDLERS }; | 86 | static k_handler_fn *k_handler[16] = { K_HANDLERS }; |
86 | EXPORT_SYMBOL_GPL(k_handler); | ||
87 | 87 | ||
88 | #define FN_HANDLERS\ | 88 | #define FN_HANDLERS\ |
89 | fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\ | 89 | fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\ |
@@ -133,7 +133,7 @@ static struct input_handler kbd_handler; | |||
133 | static DEFINE_SPINLOCK(kbd_event_lock); | 133 | static DEFINE_SPINLOCK(kbd_event_lock); |
134 | static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)]; /* keyboard key bitmap */ | 134 | static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)]; /* keyboard key bitmap */ |
135 | static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */ | 135 | static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */ |
136 | static int dead_key_next; | 136 | static bool dead_key_next; |
137 | static int npadch = -1; /* -1 or number assembled on pad */ | 137 | static int npadch = -1; /* -1 or number assembled on pad */ |
138 | static unsigned int diacr; | 138 | static unsigned int diacr; |
139 | static char rep; /* flag telling character repeat */ | 139 | static char rep; /* flag telling character repeat */ |
@@ -147,22 +147,6 @@ static struct ledptr { | |||
147 | unsigned char valid:1; | 147 | unsigned char valid:1; |
148 | } ledptrs[3]; | 148 | } ledptrs[3]; |
149 | 149 | ||
150 | /* Simple translation table for the SysRq keys */ | ||
151 | |||
152 | #ifdef CONFIG_MAGIC_SYSRQ | ||
153 | unsigned char kbd_sysrq_xlate[KEY_MAX + 1] = | ||
154 | "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ | ||
155 | "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ | ||
156 | "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ | ||
157 | "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ | ||
158 | "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ | ||
159 | "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ | ||
160 | "\r\000/"; /* 0x60 - 0x6f */ | ||
161 | static int sysrq_down; | ||
162 | static int sysrq_alt_use; | ||
163 | #endif | ||
164 | static int sysrq_alt; | ||
165 | |||
166 | /* | 150 | /* |
167 | * Notifier list for console keyboard events | 151 | * Notifier list for console keyboard events |
168 | */ | 152 | */ |
@@ -191,8 +175,7 @@ EXPORT_SYMBOL_GPL(unregister_keyboard_notifier); | |||
191 | */ | 175 | */ |
192 | 176 | ||
193 | struct getset_keycode_data { | 177 | struct getset_keycode_data { |
194 | unsigned int scancode; | 178 | struct input_keymap_entry ke; |
195 | unsigned int keycode; | ||
196 | int error; | 179 | int error; |
197 | }; | 180 | }; |
198 | 181 | ||
@@ -200,32 +183,50 @@ static int getkeycode_helper(struct input_handle *handle, void *data) | |||
200 | { | 183 | { |
201 | struct getset_keycode_data *d = data; | 184 | struct getset_keycode_data *d = data; |
202 | 185 | ||
203 | d->error = input_get_keycode(handle->dev, d->scancode, &d->keycode); | 186 | d->error = input_get_keycode(handle->dev, &d->ke); |
204 | 187 | ||
205 | return d->error == 0; /* stop as soon as we successfully get one */ | 188 | return d->error == 0; /* stop as soon as we successfully get one */ |
206 | } | 189 | } |
207 | 190 | ||
208 | int getkeycode(unsigned int scancode) | 191 | int getkeycode(unsigned int scancode) |
209 | { | 192 | { |
210 | struct getset_keycode_data d = { scancode, 0, -ENODEV }; | 193 | struct getset_keycode_data d = { |
194 | .ke = { | ||
195 | .flags = 0, | ||
196 | .len = sizeof(scancode), | ||
197 | .keycode = 0, | ||
198 | }, | ||
199 | .error = -ENODEV, | ||
200 | }; | ||
201 | |||
202 | memcpy(d.ke.scancode, &scancode, sizeof(scancode)); | ||
211 | 203 | ||
212 | input_handler_for_each_handle(&kbd_handler, &d, getkeycode_helper); | 204 | input_handler_for_each_handle(&kbd_handler, &d, getkeycode_helper); |
213 | 205 | ||
214 | return d.error ?: d.keycode; | 206 | return d.error ?: d.ke.keycode; |
215 | } | 207 | } |
216 | 208 | ||
217 | static int setkeycode_helper(struct input_handle *handle, void *data) | 209 | static int setkeycode_helper(struct input_handle *handle, void *data) |
218 | { | 210 | { |
219 | struct getset_keycode_data *d = data; | 211 | struct getset_keycode_data *d = data; |
220 | 212 | ||
221 | d->error = input_set_keycode(handle->dev, d->scancode, d->keycode); | 213 | d->error = input_set_keycode(handle->dev, &d->ke); |
222 | 214 | ||
223 | return d->error == 0; /* stop as soon as we successfully set one */ | 215 | return d->error == 0; /* stop as soon as we successfully set one */ |
224 | } | 216 | } |
225 | 217 | ||
226 | int setkeycode(unsigned int scancode, unsigned int keycode) | 218 | int setkeycode(unsigned int scancode, unsigned int keycode) |
227 | { | 219 | { |
228 | struct getset_keycode_data d = { scancode, keycode, -ENODEV }; | 220 | struct getset_keycode_data d = { |
221 | .ke = { | ||
222 | .flags = 0, | ||
223 | .len = sizeof(scancode), | ||
224 | .keycode = keycode, | ||
225 | }, | ||
226 | .error = -ENODEV, | ||
227 | }; | ||
228 | |||
229 | memcpy(d.ke.scancode, &scancode, sizeof(scancode)); | ||
229 | 230 | ||
230 | input_handler_for_each_handle(&kbd_handler, &d, setkeycode_helper); | 231 | input_handler_for_each_handle(&kbd_handler, &d, setkeycode_helper); |
231 | 232 | ||
@@ -315,7 +316,7 @@ int kbd_rate(struct kbd_repeat *rep) | |||
315 | */ | 316 | */ |
316 | static void put_queue(struct vc_data *vc, int ch) | 317 | static void put_queue(struct vc_data *vc, int ch) |
317 | { | 318 | { |
318 | struct tty_struct *tty = vc->vc_tty; | 319 | struct tty_struct *tty = vc->port.tty; |
319 | 320 | ||
320 | if (tty) { | 321 | if (tty) { |
321 | tty_insert_flip_char(tty, ch, 0); | 322 | tty_insert_flip_char(tty, ch, 0); |
@@ -325,7 +326,7 @@ static void put_queue(struct vc_data *vc, int ch) | |||
325 | 326 | ||
326 | static void puts_queue(struct vc_data *vc, char *cp) | 327 | static void puts_queue(struct vc_data *vc, char *cp) |
327 | { | 328 | { |
328 | struct tty_struct *tty = vc->vc_tty; | 329 | struct tty_struct *tty = vc->port.tty; |
329 | 330 | ||
330 | if (!tty) | 331 | if (!tty) |
331 | return; | 332 | return; |
@@ -361,8 +362,8 @@ static void to_utf8(struct vc_data *vc, uint c) | |||
361 | /* 110***** 10****** */ | 362 | /* 110***** 10****** */ |
362 | put_queue(vc, 0xc0 | (c >> 6)); | 363 | put_queue(vc, 0xc0 | (c >> 6)); |
363 | put_queue(vc, 0x80 | (c & 0x3f)); | 364 | put_queue(vc, 0x80 | (c & 0x3f)); |
364 | } else if (c < 0x10000) { | 365 | } else if (c < 0x10000) { |
365 | if (c >= 0xD800 && c < 0xE000) | 366 | if (c >= 0xD800 && c < 0xE000) |
366 | return; | 367 | return; |
367 | if (c == 0xFFFF) | 368 | if (c == 0xFFFF) |
368 | return; | 369 | return; |
@@ -370,7 +371,7 @@ static void to_utf8(struct vc_data *vc, uint c) | |||
370 | put_queue(vc, 0xe0 | (c >> 12)); | 371 | put_queue(vc, 0xe0 | (c >> 12)); |
371 | put_queue(vc, 0x80 | ((c >> 6) & 0x3f)); | 372 | put_queue(vc, 0x80 | ((c >> 6) & 0x3f)); |
372 | put_queue(vc, 0x80 | (c & 0x3f)); | 373 | put_queue(vc, 0x80 | (c & 0x3f)); |
373 | } else if (c < 0x110000) { | 374 | } else if (c < 0x110000) { |
374 | /* 11110*** 10****** 10****** 10****** */ | 375 | /* 11110*** 10****** 10****** 10****** */ |
375 | put_queue(vc, 0xf0 | (c >> 18)); | 376 | put_queue(vc, 0xf0 | (c >> 18)); |
376 | put_queue(vc, 0x80 | ((c >> 12) & 0x3f)); | 377 | put_queue(vc, 0x80 | ((c >> 12) & 0x3f)); |
@@ -469,6 +470,7 @@ static void fn_enter(struct vc_data *vc) | |||
469 | } | 470 | } |
470 | diacr = 0; | 471 | diacr = 0; |
471 | } | 472 | } |
473 | |||
472 | put_queue(vc, 13); | 474 | put_queue(vc, 13); |
473 | if (vc_kbd_mode(kbd, VC_CRLF)) | 475 | if (vc_kbd_mode(kbd, VC_CRLF)) |
474 | put_queue(vc, 10); | 476 | put_queue(vc, 10); |
@@ -478,6 +480,7 @@ static void fn_caps_toggle(struct vc_data *vc) | |||
478 | { | 480 | { |
479 | if (rep) | 481 | if (rep) |
480 | return; | 482 | return; |
483 | |||
481 | chg_vc_kbd_led(kbd, VC_CAPSLOCK); | 484 | chg_vc_kbd_led(kbd, VC_CAPSLOCK); |
482 | } | 485 | } |
483 | 486 | ||
@@ -485,19 +488,21 @@ static void fn_caps_on(struct vc_data *vc) | |||
485 | { | 488 | { |
486 | if (rep) | 489 | if (rep) |
487 | return; | 490 | return; |
491 | |||
488 | set_vc_kbd_led(kbd, VC_CAPSLOCK); | 492 | set_vc_kbd_led(kbd, VC_CAPSLOCK); |
489 | } | 493 | } |
490 | 494 | ||
491 | static void fn_show_ptregs(struct vc_data *vc) | 495 | static void fn_show_ptregs(struct vc_data *vc) |
492 | { | 496 | { |
493 | struct pt_regs *regs = get_irq_regs(); | 497 | struct pt_regs *regs = get_irq_regs(); |
498 | |||
494 | if (regs) | 499 | if (regs) |
495 | show_regs(regs); | 500 | show_regs(regs); |
496 | } | 501 | } |
497 | 502 | ||
498 | static void fn_hold(struct vc_data *vc) | 503 | static void fn_hold(struct vc_data *vc) |
499 | { | 504 | { |
500 | struct tty_struct *tty = vc->vc_tty; | 505 | struct tty_struct *tty = vc->port.tty; |
501 | 506 | ||
502 | if (rep || !tty) | 507 | if (rep || !tty) |
503 | return; | 508 | return; |
@@ -515,7 +520,7 @@ static void fn_hold(struct vc_data *vc) | |||
515 | 520 | ||
516 | static void fn_num(struct vc_data *vc) | 521 | static void fn_num(struct vc_data *vc) |
517 | { | 522 | { |
518 | if (vc_kbd_mode(kbd,VC_APPLIC)) | 523 | if (vc_kbd_mode(kbd, VC_APPLIC)) |
519 | applkey(vc, 'P', 1); | 524 | applkey(vc, 'P', 1); |
520 | else | 525 | else |
521 | fn_bare_num(vc); | 526 | fn_bare_num(vc); |
@@ -575,7 +580,7 @@ static void fn_inc_console(struct vc_data *vc) | |||
575 | 580 | ||
576 | static void fn_send_intr(struct vc_data *vc) | 581 | static void fn_send_intr(struct vc_data *vc) |
577 | { | 582 | { |
578 | struct tty_struct *tty = vc->vc_tty; | 583 | struct tty_struct *tty = vc->port.tty; |
579 | 584 | ||
580 | if (!tty) | 585 | if (!tty) |
581 | return; | 586 | return; |
@@ -610,7 +615,7 @@ static void fn_boot_it(struct vc_data *vc) | |||
610 | 615 | ||
611 | static void fn_compose(struct vc_data *vc) | 616 | static void fn_compose(struct vc_data *vc) |
612 | { | 617 | { |
613 | dead_key_next = 1; | 618 | dead_key_next = true; |
614 | } | 619 | } |
615 | 620 | ||
616 | static void fn_spawn_con(struct vc_data *vc) | 621 | static void fn_spawn_con(struct vc_data *vc) |
@@ -657,7 +662,7 @@ static void k_spec(struct vc_data *vc, unsigned char value, char up_flag) | |||
657 | 662 | ||
658 | static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag) | 663 | static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag) |
659 | { | 664 | { |
660 | printk(KERN_ERR "keyboard.c: k_lowercase was called - impossible\n"); | 665 | pr_err("k_lowercase was called - impossible\n"); |
661 | } | 666 | } |
662 | 667 | ||
663 | static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag) | 668 | static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag) |
@@ -669,7 +674,7 @@ static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag) | |||
669 | value = handle_diacr(vc, value); | 674 | value = handle_diacr(vc, value); |
670 | 675 | ||
671 | if (dead_key_next) { | 676 | if (dead_key_next) { |
672 | dead_key_next = 0; | 677 | dead_key_next = false; |
673 | diacr = value; | 678 | diacr = value; |
674 | return; | 679 | return; |
675 | } | 680 | } |
@@ -691,6 +696,7 @@ static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag) | |||
691 | { | 696 | { |
692 | if (up_flag) | 697 | if (up_flag) |
693 | return; | 698 | return; |
699 | |||
694 | diacr = (diacr ? handle_diacr(vc, value) : value); | 700 | diacr = (diacr ? handle_diacr(vc, value) : value); |
695 | } | 701 | } |
696 | 702 | ||
@@ -710,29 +716,28 @@ static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag) | |||
710 | static void k_dead(struct vc_data *vc, unsigned char value, char up_flag) | 716 | static void k_dead(struct vc_data *vc, unsigned char value, char up_flag) |
711 | { | 717 | { |
712 | static const unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' }; | 718 | static const unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' }; |
713 | value = ret_diacr[value]; | 719 | |
714 | k_deadunicode(vc, value, up_flag); | 720 | k_deadunicode(vc, ret_diacr[value], up_flag); |
715 | } | 721 | } |
716 | 722 | ||
717 | static void k_cons(struct vc_data *vc, unsigned char value, char up_flag) | 723 | static void k_cons(struct vc_data *vc, unsigned char value, char up_flag) |
718 | { | 724 | { |
719 | if (up_flag) | 725 | if (up_flag) |
720 | return; | 726 | return; |
727 | |||
721 | set_console(value); | 728 | set_console(value); |
722 | } | 729 | } |
723 | 730 | ||
724 | static void k_fn(struct vc_data *vc, unsigned char value, char up_flag) | 731 | static void k_fn(struct vc_data *vc, unsigned char value, char up_flag) |
725 | { | 732 | { |
726 | unsigned v; | ||
727 | |||
728 | if (up_flag) | 733 | if (up_flag) |
729 | return; | 734 | return; |
730 | v = value; | 735 | |
731 | if (v < ARRAY_SIZE(func_table)) { | 736 | if ((unsigned)value < ARRAY_SIZE(func_table)) { |
732 | if (func_table[value]) | 737 | if (func_table[value]) |
733 | puts_queue(vc, func_table[value]); | 738 | puts_queue(vc, func_table[value]); |
734 | } else | 739 | } else |
735 | printk(KERN_ERR "k_fn called with value=%d\n", value); | 740 | pr_err("k_fn called with value=%d\n", value); |
736 | } | 741 | } |
737 | 742 | ||
738 | static void k_cur(struct vc_data *vc, unsigned char value, char up_flag) | 743 | static void k_cur(struct vc_data *vc, unsigned char value, char up_flag) |
@@ -741,6 +746,7 @@ static void k_cur(struct vc_data *vc, unsigned char value, char up_flag) | |||
741 | 746 | ||
742 | if (up_flag) | 747 | if (up_flag) |
743 | return; | 748 | return; |
749 | |||
744 | applkey(vc, cur_chars[value], vc_kbd_mode(kbd, VC_CKMODE)); | 750 | applkey(vc, cur_chars[value], vc_kbd_mode(kbd, VC_CKMODE)); |
745 | } | 751 | } |
746 | 752 | ||
@@ -758,43 +764,45 @@ static void k_pad(struct vc_data *vc, unsigned char value, char up_flag) | |||
758 | return; | 764 | return; |
759 | } | 765 | } |
760 | 766 | ||
761 | if (!vc_kbd_led(kbd, VC_NUMLOCK)) | 767 | if (!vc_kbd_led(kbd, VC_NUMLOCK)) { |
768 | |||
762 | switch (value) { | 769 | switch (value) { |
763 | case KVAL(K_PCOMMA): | 770 | case KVAL(K_PCOMMA): |
764 | case KVAL(K_PDOT): | 771 | case KVAL(K_PDOT): |
765 | k_fn(vc, KVAL(K_REMOVE), 0); | 772 | k_fn(vc, KVAL(K_REMOVE), 0); |
766 | return; | 773 | return; |
767 | case KVAL(K_P0): | 774 | case KVAL(K_P0): |
768 | k_fn(vc, KVAL(K_INSERT), 0); | 775 | k_fn(vc, KVAL(K_INSERT), 0); |
769 | return; | 776 | return; |
770 | case KVAL(K_P1): | 777 | case KVAL(K_P1): |
771 | k_fn(vc, KVAL(K_SELECT), 0); | 778 | k_fn(vc, KVAL(K_SELECT), 0); |
772 | return; | 779 | return; |
773 | case KVAL(K_P2): | 780 | case KVAL(K_P2): |
774 | k_cur(vc, KVAL(K_DOWN), 0); | 781 | k_cur(vc, KVAL(K_DOWN), 0); |
775 | return; | 782 | return; |
776 | case KVAL(K_P3): | 783 | case KVAL(K_P3): |
777 | k_fn(vc, KVAL(K_PGDN), 0); | 784 | k_fn(vc, KVAL(K_PGDN), 0); |
778 | return; | 785 | return; |
779 | case KVAL(K_P4): | 786 | case KVAL(K_P4): |
780 | k_cur(vc, KVAL(K_LEFT), 0); | 787 | k_cur(vc, KVAL(K_LEFT), 0); |
781 | return; | 788 | return; |
782 | case KVAL(K_P6): | 789 | case KVAL(K_P6): |
783 | k_cur(vc, KVAL(K_RIGHT), 0); | 790 | k_cur(vc, KVAL(K_RIGHT), 0); |
784 | return; | 791 | return; |
785 | case KVAL(K_P7): | 792 | case KVAL(K_P7): |
786 | k_fn(vc, KVAL(K_FIND), 0); | 793 | k_fn(vc, KVAL(K_FIND), 0); |
787 | return; | 794 | return; |
788 | case KVAL(K_P8): | 795 | case KVAL(K_P8): |
789 | k_cur(vc, KVAL(K_UP), 0); | 796 | k_cur(vc, KVAL(K_UP), 0); |
790 | return; | 797 | return; |
791 | case KVAL(K_P9): | 798 | case KVAL(K_P9): |
792 | k_fn(vc, KVAL(K_PGUP), 0); | 799 | k_fn(vc, KVAL(K_PGUP), 0); |
793 | return; | 800 | return; |
794 | case KVAL(K_P5): | 801 | case KVAL(K_P5): |
795 | applkey(vc, 'G', vc_kbd_mode(kbd, VC_APPLIC)); | 802 | applkey(vc, 'G', vc_kbd_mode(kbd, VC_APPLIC)); |
796 | return; | 803 | return; |
797 | } | 804 | } |
805 | } | ||
798 | 806 | ||
799 | put_queue(vc, pad_chars[value]); | 807 | put_queue(vc, pad_chars[value]); |
800 | if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF)) | 808 | if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF)) |
@@ -880,6 +888,7 @@ static void k_lock(struct vc_data *vc, unsigned char value, char up_flag) | |||
880 | { | 888 | { |
881 | if (up_flag || rep) | 889 | if (up_flag || rep) |
882 | return; | 890 | return; |
891 | |||
883 | chg_vc_kbd_lock(kbd, value); | 892 | chg_vc_kbd_lock(kbd, value); |
884 | } | 893 | } |
885 | 894 | ||
@@ -888,6 +897,7 @@ static void k_slock(struct vc_data *vc, unsigned char value, char up_flag) | |||
888 | k_shift(vc, value, up_flag); | 897 | k_shift(vc, value, up_flag); |
889 | if (up_flag || rep) | 898 | if (up_flag || rep) |
890 | return; | 899 | return; |
900 | |||
891 | chg_vc_kbd_slock(kbd, value); | 901 | chg_vc_kbd_slock(kbd, value); |
892 | /* try to make Alt, oops, AltGr and such work */ | 902 | /* try to make Alt, oops, AltGr and such work */ |
893 | if (!key_maps[kbd->lockstate ^ kbd->slockstate]) { | 903 | if (!key_maps[kbd->lockstate ^ kbd->slockstate]) { |
@@ -925,12 +935,12 @@ static void k_brlcommit(struct vc_data *vc, unsigned int pattern, char up_flag) | |||
925 | 935 | ||
926 | static void k_brl(struct vc_data *vc, unsigned char value, char up_flag) | 936 | static void k_brl(struct vc_data *vc, unsigned char value, char up_flag) |
927 | { | 937 | { |
928 | static unsigned pressed,committing; | 938 | static unsigned pressed, committing; |
929 | static unsigned long releasestart; | 939 | static unsigned long releasestart; |
930 | 940 | ||
931 | if (kbd->kbdmode != VC_UNICODE) { | 941 | if (kbd->kbdmode != VC_UNICODE) { |
932 | if (!up_flag) | 942 | if (!up_flag) |
933 | printk("keyboard mode must be unicode for braille patterns\n"); | 943 | pr_warning("keyboard mode must be unicode for braille patterns\n"); |
934 | return; | 944 | return; |
935 | } | 945 | } |
936 | 946 | ||
@@ -942,32 +952,28 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag) | |||
942 | if (value > 8) | 952 | if (value > 8) |
943 | return; | 953 | return; |
944 | 954 | ||
945 | if (up_flag) { | 955 | if (!up_flag) { |
946 | if (brl_timeout) { | ||
947 | if (!committing || | ||
948 | time_after(jiffies, | ||
949 | releasestart + msecs_to_jiffies(brl_timeout))) { | ||
950 | committing = pressed; | ||
951 | releasestart = jiffies; | ||
952 | } | ||
953 | pressed &= ~(1 << (value - 1)); | ||
954 | if (!pressed) { | ||
955 | if (committing) { | ||
956 | k_brlcommit(vc, committing, 0); | ||
957 | committing = 0; | ||
958 | } | ||
959 | } | ||
960 | } else { | ||
961 | if (committing) { | ||
962 | k_brlcommit(vc, committing, 0); | ||
963 | committing = 0; | ||
964 | } | ||
965 | pressed &= ~(1 << (value - 1)); | ||
966 | } | ||
967 | } else { | ||
968 | pressed |= 1 << (value - 1); | 956 | pressed |= 1 << (value - 1); |
969 | if (!brl_timeout) | 957 | if (!brl_timeout) |
970 | committing = pressed; | 958 | committing = pressed; |
959 | } else if (brl_timeout) { | ||
960 | if (!committing || | ||
961 | time_after(jiffies, | ||
962 | releasestart + msecs_to_jiffies(brl_timeout))) { | ||
963 | committing = pressed; | ||
964 | releasestart = jiffies; | ||
965 | } | ||
966 | pressed &= ~(1 << (value - 1)); | ||
967 | if (!pressed && committing) { | ||
968 | k_brlcommit(vc, committing, 0); | ||
969 | committing = 0; | ||
970 | } | ||
971 | } else { | ||
972 | if (committing) { | ||
973 | k_brlcommit(vc, committing, 0); | ||
974 | committing = 0; | ||
975 | } | ||
976 | pressed &= ~(1 << (value - 1)); | ||
971 | } | 977 | } |
972 | } | 978 | } |
973 | 979 | ||
@@ -988,6 +994,7 @@ void setledstate(struct kbd_struct *kbd, unsigned int led) | |||
988 | kbd->ledmode = LED_SHOW_IOCTL; | 994 | kbd->ledmode = LED_SHOW_IOCTL; |
989 | } else | 995 | } else |
990 | kbd->ledmode = LED_SHOW_FLAGS; | 996 | kbd->ledmode = LED_SHOW_FLAGS; |
997 | |||
991 | set_leds(); | 998 | set_leds(); |
992 | } | 999 | } |
993 | 1000 | ||
@@ -1075,7 +1082,7 @@ static const unsigned short x86_keycodes[256] = | |||
1075 | 332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 }; | 1082 | 332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 }; |
1076 | 1083 | ||
1077 | #ifdef CONFIG_SPARC | 1084 | #ifdef CONFIG_SPARC |
1078 | static int sparc_l1_a_state = 0; | 1085 | static int sparc_l1_a_state; |
1079 | extern void sun_do_break(void); | 1086 | extern void sun_do_break(void); |
1080 | #endif | 1087 | #endif |
1081 | 1088 | ||
@@ -1085,52 +1092,54 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode, | |||
1085 | int code; | 1092 | int code; |
1086 | 1093 | ||
1087 | switch (keycode) { | 1094 | switch (keycode) { |
1088 | case KEY_PAUSE: | ||
1089 | put_queue(vc, 0xe1); | ||
1090 | put_queue(vc, 0x1d | up_flag); | ||
1091 | put_queue(vc, 0x45 | up_flag); | ||
1092 | break; | ||
1093 | 1095 | ||
1094 | case KEY_HANGEUL: | 1096 | case KEY_PAUSE: |
1095 | if (!up_flag) | 1097 | put_queue(vc, 0xe1); |
1096 | put_queue(vc, 0xf2); | 1098 | put_queue(vc, 0x1d | up_flag); |
1097 | break; | 1099 | put_queue(vc, 0x45 | up_flag); |
1100 | break; | ||
1098 | 1101 | ||
1099 | case KEY_HANJA: | 1102 | case KEY_HANGEUL: |
1100 | if (!up_flag) | 1103 | if (!up_flag) |
1101 | put_queue(vc, 0xf1); | 1104 | put_queue(vc, 0xf2); |
1102 | break; | 1105 | break; |
1103 | 1106 | ||
1104 | case KEY_SYSRQ: | 1107 | case KEY_HANJA: |
1105 | /* | 1108 | if (!up_flag) |
1106 | * Real AT keyboards (that's what we're trying | 1109 | put_queue(vc, 0xf1); |
1107 | * to emulate here emit 0xe0 0x2a 0xe0 0x37 when | 1110 | break; |
1108 | * pressing PrtSc/SysRq alone, but simply 0x54 | 1111 | |
1109 | * when pressing Alt+PrtSc/SysRq. | 1112 | case KEY_SYSRQ: |
1110 | */ | 1113 | /* |
1111 | if (sysrq_alt) { | 1114 | * Real AT keyboards (that's what we're trying |
1112 | put_queue(vc, 0x54 | up_flag); | 1115 | * to emulate here emit 0xe0 0x2a 0xe0 0x37 when |
1113 | } else { | 1116 | * pressing PrtSc/SysRq alone, but simply 0x54 |
1114 | put_queue(vc, 0xe0); | 1117 | * when pressing Alt+PrtSc/SysRq. |
1115 | put_queue(vc, 0x2a | up_flag); | 1118 | */ |
1116 | put_queue(vc, 0xe0); | 1119 | if (test_bit(KEY_LEFTALT, key_down) || |
1117 | put_queue(vc, 0x37 | up_flag); | 1120 | test_bit(KEY_RIGHTALT, key_down)) { |
1118 | } | 1121 | put_queue(vc, 0x54 | up_flag); |
1119 | break; | 1122 | } else { |
1123 | put_queue(vc, 0xe0); | ||
1124 | put_queue(vc, 0x2a | up_flag); | ||
1125 | put_queue(vc, 0xe0); | ||
1126 | put_queue(vc, 0x37 | up_flag); | ||
1127 | } | ||
1128 | break; | ||
1120 | 1129 | ||
1121 | default: | 1130 | default: |
1122 | if (keycode > 255) | 1131 | if (keycode > 255) |
1123 | return -1; | 1132 | return -1; |
1124 | 1133 | ||
1125 | code = x86_keycodes[keycode]; | 1134 | code = x86_keycodes[keycode]; |
1126 | if (!code) | 1135 | if (!code) |
1127 | return -1; | 1136 | return -1; |
1128 | 1137 | ||
1129 | if (code & 0x100) | 1138 | if (code & 0x100) |
1130 | put_queue(vc, 0xe0); | 1139 | put_queue(vc, 0xe0); |
1131 | put_queue(vc, (code & 0x7f) | up_flag); | 1140 | put_queue(vc, (code & 0x7f) | up_flag); |
1132 | 1141 | ||
1133 | break; | 1142 | break; |
1134 | } | 1143 | } |
1135 | 1144 | ||
1136 | return 0; | 1145 | return 0; |
@@ -1153,6 +1162,7 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char u | |||
1153 | static void kbd_rawcode(unsigned char data) | 1162 | static void kbd_rawcode(unsigned char data) |
1154 | { | 1163 | { |
1155 | struct vc_data *vc = vc_cons[fg_console].d; | 1164 | struct vc_data *vc = vc_cons[fg_console].d; |
1165 | |||
1156 | kbd = kbd_table + vc->vc_num; | 1166 | kbd = kbd_table + vc->vc_num; |
1157 | if (kbd->kbdmode == VC_RAW) | 1167 | if (kbd->kbdmode == VC_RAW) |
1158 | put_queue(vc, data); | 1168 | put_queue(vc, data); |
@@ -1162,12 +1172,14 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) | |||
1162 | { | 1172 | { |
1163 | struct vc_data *vc = vc_cons[fg_console].d; | 1173 | struct vc_data *vc = vc_cons[fg_console].d; |
1164 | unsigned short keysym, *key_map; | 1174 | unsigned short keysym, *key_map; |
1165 | unsigned char type, raw_mode; | 1175 | unsigned char type; |
1176 | bool raw_mode; | ||
1166 | struct tty_struct *tty; | 1177 | struct tty_struct *tty; |
1167 | int shift_final; | 1178 | int shift_final; |
1168 | struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down }; | 1179 | struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down }; |
1180 | int rc; | ||
1169 | 1181 | ||
1170 | tty = vc->vc_tty; | 1182 | tty = vc->port.tty; |
1171 | 1183 | ||
1172 | if (tty && (!tty->driver_data)) { | 1184 | if (tty && (!tty->driver_data)) { |
1173 | /* No driver data? Strange. Okay we fix it then. */ | 1185 | /* No driver data? Strange. Okay we fix it then. */ |
@@ -1176,8 +1188,6 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) | |||
1176 | 1188 | ||
1177 | kbd = kbd_table + vc->vc_num; | 1189 | kbd = kbd_table + vc->vc_num; |
1178 | 1190 | ||
1179 | if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT) | ||
1180 | sysrq_alt = down ? keycode : 0; | ||
1181 | #ifdef CONFIG_SPARC | 1191 | #ifdef CONFIG_SPARC |
1182 | if (keycode == KEY_STOP) | 1192 | if (keycode == KEY_STOP) |
1183 | sparc_l1_a_state = down; | 1193 | sparc_l1_a_state = down; |
@@ -1185,34 +1195,16 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) | |||
1185 | 1195 | ||
1186 | rep = (down == 2); | 1196 | rep = (down == 2); |
1187 | 1197 | ||
1188 | #ifdef CONFIG_MAC_EMUMOUSEBTN | 1198 | raw_mode = (kbd->kbdmode == VC_RAW); |
1189 | if (mac_hid_mouse_emulate_buttons(1, keycode, down)) | 1199 | if (raw_mode && !hw_raw) |
1190 | return; | ||
1191 | #endif /* CONFIG_MAC_EMUMOUSEBTN */ | ||
1192 | |||
1193 | if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw) | ||
1194 | if (emulate_raw(vc, keycode, !down << 7)) | 1200 | if (emulate_raw(vc, keycode, !down << 7)) |
1195 | if (keycode < BTN_MISC && printk_ratelimit()) | 1201 | if (keycode < BTN_MISC && printk_ratelimit()) |
1196 | printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode); | 1202 | pr_warning("can't emulate rawmode for keycode %d\n", |
1203 | keycode); | ||
1197 | 1204 | ||
1198 | #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ | ||
1199 | if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) { | ||
1200 | if (!sysrq_down) { | ||
1201 | sysrq_down = down; | ||
1202 | sysrq_alt_use = sysrq_alt; | ||
1203 | } | ||
1204 | return; | ||
1205 | } | ||
1206 | if (sysrq_down && !down && keycode == sysrq_alt_use) | ||
1207 | sysrq_down = 0; | ||
1208 | if (sysrq_down && down && !rep) { | ||
1209 | handle_sysrq(kbd_sysrq_xlate[keycode], tty); | ||
1210 | return; | ||
1211 | } | ||
1212 | #endif | ||
1213 | #ifdef CONFIG_SPARC | 1205 | #ifdef CONFIG_SPARC |
1214 | if (keycode == KEY_A && sparc_l1_a_state) { | 1206 | if (keycode == KEY_A && sparc_l1_a_state) { |
1215 | sparc_l1_a_state = 0; | 1207 | sparc_l1_a_state = false; |
1216 | sun_do_break(); | 1208 | sun_do_break(); |
1217 | } | 1209 | } |
1218 | #endif | 1210 | #endif |
@@ -1234,7 +1226,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) | |||
1234 | put_queue(vc, (keycode >> 7) | 0x80); | 1226 | put_queue(vc, (keycode >> 7) | 0x80); |
1235 | put_queue(vc, keycode | 0x80); | 1227 | put_queue(vc, keycode | 0x80); |
1236 | } | 1228 | } |
1237 | raw_mode = 1; | 1229 | raw_mode = true; |
1238 | } | 1230 | } |
1239 | 1231 | ||
1240 | if (down) | 1232 | if (down) |
@@ -1257,29 +1249,32 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) | |||
1257 | param.ledstate = kbd->ledflagstate; | 1249 | param.ledstate = kbd->ledflagstate; |
1258 | key_map = key_maps[shift_final]; | 1250 | key_map = key_maps[shift_final]; |
1259 | 1251 | ||
1260 | if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYCODE, ¶m) == NOTIFY_STOP || !key_map) { | 1252 | rc = atomic_notifier_call_chain(&keyboard_notifier_list, |
1261 | atomic_notifier_call_chain(&keyboard_notifier_list, KBD_UNBOUND_KEYCODE, ¶m); | 1253 | KBD_KEYCODE, ¶m); |
1254 | if (rc == NOTIFY_STOP || !key_map) { | ||
1255 | atomic_notifier_call_chain(&keyboard_notifier_list, | ||
1256 | KBD_UNBOUND_KEYCODE, ¶m); | ||
1262 | compute_shiftstate(); | 1257 | compute_shiftstate(); |
1263 | kbd->slockstate = 0; | 1258 | kbd->slockstate = 0; |
1264 | return; | 1259 | return; |
1265 | } | 1260 | } |
1266 | 1261 | ||
1267 | if (keycode >= NR_KEYS) | 1262 | if (keycode < NR_KEYS) |
1268 | if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8) | ||
1269 | keysym = U(K(KT_BRL, keycode - KEY_BRL_DOT1 + 1)); | ||
1270 | else | ||
1271 | return; | ||
1272 | else | ||
1273 | keysym = key_map[keycode]; | 1263 | keysym = key_map[keycode]; |
1264 | else if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8) | ||
1265 | keysym = U(K(KT_BRL, keycode - KEY_BRL_DOT1 + 1)); | ||
1266 | else | ||
1267 | return; | ||
1274 | 1268 | ||
1275 | type = KTYP(keysym); | 1269 | type = KTYP(keysym); |
1276 | 1270 | ||
1277 | if (type < 0xf0) { | 1271 | if (type < 0xf0) { |
1278 | param.value = keysym; | 1272 | param.value = keysym; |
1279 | if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_UNICODE, ¶m) == NOTIFY_STOP) | 1273 | rc = atomic_notifier_call_chain(&keyboard_notifier_list, |
1280 | return; | 1274 | KBD_UNICODE, ¶m); |
1281 | if (down && !raw_mode) | 1275 | if (rc != NOTIFY_STOP) |
1282 | to_utf8(vc, keysym); | 1276 | if (down && !raw_mode) |
1277 | to_utf8(vc, keysym); | ||
1283 | return; | 1278 | return; |
1284 | } | 1279 | } |
1285 | 1280 | ||
@@ -1293,9 +1288,11 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) | |||
1293 | keysym = key_map[keycode]; | 1288 | keysym = key_map[keycode]; |
1294 | } | 1289 | } |
1295 | } | 1290 | } |
1296 | param.value = keysym; | ||
1297 | 1291 | ||
1298 | if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYSYM, ¶m) == NOTIFY_STOP) | 1292 | param.value = keysym; |
1293 | rc = atomic_notifier_call_chain(&keyboard_notifier_list, | ||
1294 | KBD_KEYSYM, ¶m); | ||
1295 | if (rc == NOTIFY_STOP) | ||
1299 | return; | 1296 | return; |
1300 | 1297 | ||
1301 | if (raw_mode && type != KT_SPEC && type != KT_SHIFT) | 1298 | if (raw_mode && type != KT_SPEC && type != KT_SHIFT) |
@@ -1328,6 +1325,25 @@ static void kbd_event(struct input_handle *handle, unsigned int event_type, | |||
1328 | schedule_console_callback(); | 1325 | schedule_console_callback(); |
1329 | } | 1326 | } |
1330 | 1327 | ||
1328 | static bool kbd_match(struct input_handler *handler, struct input_dev *dev) | ||
1329 | { | ||
1330 | int i; | ||
1331 | |||
1332 | if (test_bit(EV_SND, dev->evbit)) | ||
1333 | return true; | ||
1334 | |||
1335 | if (test_bit(EV_KEY, dev->evbit)) { | ||
1336 | for (i = KEY_RESERVED; i < BTN_MISC; i++) | ||
1337 | if (test_bit(i, dev->keybit)) | ||
1338 | return true; | ||
1339 | for (i = KEY_BRL_DOT1; i <= KEY_BRL_DOT10; i++) | ||
1340 | if (test_bit(i, dev->keybit)) | ||
1341 | return true; | ||
1342 | } | ||
1343 | |||
1344 | return false; | ||
1345 | } | ||
1346 | |||
1331 | /* | 1347 | /* |
1332 | * When a keyboard (or other input device) is found, the kbd_connect | 1348 | * When a keyboard (or other input device) is found, the kbd_connect |
1333 | * function is called. The function then looks at the device, and if it | 1349 | * function is called. The function then looks at the device, and if it |
@@ -1339,14 +1355,6 @@ static int kbd_connect(struct input_handler *handler, struct input_dev *dev, | |||
1339 | { | 1355 | { |
1340 | struct input_handle *handle; | 1356 | struct input_handle *handle; |
1341 | int error; | 1357 | int error; |
1342 | int i; | ||
1343 | |||
1344 | for (i = KEY_RESERVED; i < BTN_MISC; i++) | ||
1345 | if (test_bit(i, dev->keybit)) | ||
1346 | break; | ||
1347 | |||
1348 | if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit)) | ||
1349 | return -ENODEV; | ||
1350 | 1358 | ||
1351 | handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); | 1359 | handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); |
1352 | if (!handle) | 1360 | if (!handle) |
@@ -1412,6 +1420,7 @@ MODULE_DEVICE_TABLE(input, kbd_ids); | |||
1412 | 1420 | ||
1413 | static struct input_handler kbd_handler = { | 1421 | static struct input_handler kbd_handler = { |
1414 | .event = kbd_event, | 1422 | .event = kbd_event, |
1423 | .match = kbd_match, | ||
1415 | .connect = kbd_connect, | 1424 | .connect = kbd_connect, |
1416 | .disconnect = kbd_disconnect, | 1425 | .disconnect = kbd_disconnect, |
1417 | .start = kbd_start, | 1426 | .start = kbd_start, |
diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 938a3a273886..97c3edb95ae7 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c | |||
@@ -126,7 +126,7 @@ | |||
126 | #include <linux/device.h> | 126 | #include <linux/device.h> |
127 | #include <linux/wait.h> | 127 | #include <linux/wait.h> |
128 | #include <linux/jiffies.h> | 128 | #include <linux/jiffies.h> |
129 | #include <linux/smp_lock.h> | 129 | #include <linux/mutex.h> |
130 | #include <linux/compat.h> | 130 | #include <linux/compat.h> |
131 | 131 | ||
132 | #include <linux/parport.h> | 132 | #include <linux/parport.h> |
@@ -140,6 +140,7 @@ | |||
140 | /* if you have more than 8 printers, remember to increase LP_NO */ | 140 | /* if you have more than 8 printers, remember to increase LP_NO */ |
141 | #define LP_NO 8 | 141 | #define LP_NO 8 |
142 | 142 | ||
143 | static DEFINE_MUTEX(lp_mutex); | ||
143 | static struct lp_struct lp_table[LP_NO]; | 144 | static struct lp_struct lp_table[LP_NO]; |
144 | 145 | ||
145 | static unsigned int lp_count = 0; | 146 | static unsigned int lp_count = 0; |
@@ -493,7 +494,7 @@ static int lp_open(struct inode * inode, struct file * file) | |||
493 | unsigned int minor = iminor(inode); | 494 | unsigned int minor = iminor(inode); |
494 | int ret = 0; | 495 | int ret = 0; |
495 | 496 | ||
496 | lock_kernel(); | 497 | mutex_lock(&lp_mutex); |
497 | if (minor >= LP_NO) { | 498 | if (minor >= LP_NO) { |
498 | ret = -ENXIO; | 499 | ret = -ENXIO; |
499 | goto out; | 500 | goto out; |
@@ -554,7 +555,7 @@ static int lp_open(struct inode * inode, struct file * file) | |||
554 | lp_release_parport (&lp_table[minor]); | 555 | lp_release_parport (&lp_table[minor]); |
555 | lp_table[minor].current_mode = IEEE1284_MODE_COMPAT; | 556 | lp_table[minor].current_mode = IEEE1284_MODE_COMPAT; |
556 | out: | 557 | out: |
557 | unlock_kernel(); | 558 | mutex_unlock(&lp_mutex); |
558 | return ret; | 559 | return ret; |
559 | } | 560 | } |
560 | 561 | ||
@@ -680,7 +681,7 @@ static long lp_ioctl(struct file *file, unsigned int cmd, | |||
680 | int ret; | 681 | int ret; |
681 | 682 | ||
682 | minor = iminor(file->f_path.dentry->d_inode); | 683 | minor = iminor(file->f_path.dentry->d_inode); |
683 | lock_kernel(); | 684 | mutex_lock(&lp_mutex); |
684 | switch (cmd) { | 685 | switch (cmd) { |
685 | case LPSETTIMEOUT: | 686 | case LPSETTIMEOUT: |
686 | if (copy_from_user(&par_timeout, (void __user *)arg, | 687 | if (copy_from_user(&par_timeout, (void __user *)arg, |
@@ -694,7 +695,7 @@ static long lp_ioctl(struct file *file, unsigned int cmd, | |||
694 | ret = lp_do_ioctl(minor, cmd, arg, (void __user *)arg); | 695 | ret = lp_do_ioctl(minor, cmd, arg, (void __user *)arg); |
695 | break; | 696 | break; |
696 | } | 697 | } |
697 | unlock_kernel(); | 698 | mutex_unlock(&lp_mutex); |
698 | 699 | ||
699 | return ret; | 700 | return ret; |
700 | } | 701 | } |
@@ -709,7 +710,7 @@ static long lp_compat_ioctl(struct file *file, unsigned int cmd, | |||
709 | int ret; | 710 | int ret; |
710 | 711 | ||
711 | minor = iminor(file->f_path.dentry->d_inode); | 712 | minor = iminor(file->f_path.dentry->d_inode); |
712 | lock_kernel(); | 713 | mutex_lock(&lp_mutex); |
713 | switch (cmd) { | 714 | switch (cmd) { |
714 | case LPSETTIMEOUT: | 715 | case LPSETTIMEOUT: |
715 | tc = compat_ptr(arg); | 716 | tc = compat_ptr(arg); |
@@ -730,7 +731,7 @@ static long lp_compat_ioctl(struct file *file, unsigned int cmd, | |||
730 | ret = lp_do_ioctl(minor, cmd, arg, compat_ptr(arg)); | 731 | ret = lp_do_ioctl(minor, cmd, arg, compat_ptr(arg)); |
731 | break; | 732 | break; |
732 | } | 733 | } |
733 | unlock_kernel(); | 734 | mutex_unlock(&lp_mutex); |
734 | 735 | ||
735 | return ret; | 736 | return ret; |
736 | } | 737 | } |
@@ -748,6 +749,7 @@ static const struct file_operations lp_fops = { | |||
748 | #ifdef CONFIG_PARPORT_1284 | 749 | #ifdef CONFIG_PARPORT_1284 |
749 | .read = lp_read, | 750 | .read = lp_read, |
750 | #endif | 751 | #endif |
752 | .llseek = noop_llseek, | ||
751 | }; | 753 | }; |
752 | 754 | ||
753 | /* --- support for console on the line printer ----------------- */ | 755 | /* --- support for console on the line printer ----------------- */ |
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c index 87c67b42bc08..1aeaaba680d2 100644 --- a/drivers/char/mbcs.c +++ b/drivers/char/mbcs.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/mm.h> | 25 | #include <linux/mm.h> |
26 | #include <linux/uio.h> | 26 | #include <linux/uio.h> |
27 | #include <linux/mutex.h> | 27 | #include <linux/mutex.h> |
28 | #include <linux/smp_lock.h> | 28 | #include <linux/slab.h> |
29 | #include <asm/io.h> | 29 | #include <asm/io.h> |
30 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
31 | #include <asm/system.h> | 31 | #include <asm/system.h> |
@@ -41,6 +41,7 @@ | |||
41 | #else | 41 | #else |
42 | #define DBG(fmt...) | 42 | #define DBG(fmt...) |
43 | #endif | 43 | #endif |
44 | static DEFINE_MUTEX(mbcs_mutex); | ||
44 | static int mbcs_major; | 45 | static int mbcs_major; |
45 | 46 | ||
46 | static LIST_HEAD(soft_list); | 47 | static LIST_HEAD(soft_list); |
@@ -384,19 +385,19 @@ static int mbcs_open(struct inode *ip, struct file *fp) | |||
384 | struct mbcs_soft *soft; | 385 | struct mbcs_soft *soft; |
385 | int minor; | 386 | int minor; |
386 | 387 | ||
387 | lock_kernel(); | 388 | mutex_lock(&mbcs_mutex); |
388 | minor = iminor(ip); | 389 | minor = iminor(ip); |
389 | 390 | ||
390 | /* Nothing protects access to this list... */ | 391 | /* Nothing protects access to this list... */ |
391 | list_for_each_entry(soft, &soft_list, list) { | 392 | list_for_each_entry(soft, &soft_list, list) { |
392 | if (soft->nasid == minor) { | 393 | if (soft->nasid == minor) { |
393 | fp->private_data = soft->cxdev; | 394 | fp->private_data = soft->cxdev; |
394 | unlock_kernel(); | 395 | mutex_unlock(&mbcs_mutex); |
395 | return 0; | 396 | return 0; |
396 | } | 397 | } |
397 | } | 398 | } |
398 | 399 | ||
399 | unlock_kernel(); | 400 | mutex_unlock(&mbcs_mutex); |
400 | return -ENODEV; | 401 | return -ENODEV; |
401 | } | 402 | } |
402 | 403 | ||
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index be832b6f8279..1256454b2d43 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 1991, 1992 Linus Torvalds | 4 | * Copyright (C) 1991, 1992 Linus Torvalds |
5 | * | 5 | * |
6 | * Added devfs support. | 6 | * Added devfs support. |
7 | * Jan-11-1998, C. Scott Ananian <cananian@alumni.princeton.edu> | 7 | * Jan-11-1998, C. Scott Ananian <cananian@alumni.princeton.edu> |
8 | * Shared /dev/zero mmapping support, Feb 2000, Kanoj Sarcar <kanoj@sgi.com> | 8 | * Shared /dev/zero mmapping support, Feb 2000, Kanoj Sarcar <kanoj@sgi.com> |
9 | */ | 9 | */ |
@@ -44,36 +44,6 @@ static inline unsigned long size_inside_page(unsigned long start, | |||
44 | return min(sz, size); | 44 | return min(sz, size); |
45 | } | 45 | } |
46 | 46 | ||
47 | /* | ||
48 | * Architectures vary in how they handle caching for addresses | ||
49 | * outside of main memory. | ||
50 | * | ||
51 | */ | ||
52 | static inline int uncached_access(struct file *file, unsigned long addr) | ||
53 | { | ||
54 | #if defined(CONFIG_IA64) | ||
55 | /* | ||
56 | * On ia64, we ignore O_DSYNC because we cannot tolerate memory attribute aliases. | ||
57 | */ | ||
58 | return !(efi_mem_attributes(addr) & EFI_MEMORY_WB); | ||
59 | #elif defined(CONFIG_MIPS) | ||
60 | { | ||
61 | extern int __uncached_access(struct file *file, | ||
62 | unsigned long addr); | ||
63 | |||
64 | return __uncached_access(file, addr); | ||
65 | } | ||
66 | #else | ||
67 | /* | ||
68 | * Accessing memory above the top the kernel knows about or through a file pointer | ||
69 | * that was marked O_DSYNC will be done non-cached. | ||
70 | */ | ||
71 | if (file->f_flags & O_DSYNC) | ||
72 | return 1; | ||
73 | return addr >= __pa(high_memory); | ||
74 | #endif | ||
75 | } | ||
76 | |||
77 | #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE | 47 | #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE |
78 | static inline int valid_phys_addr_range(unsigned long addr, size_t count) | 48 | static inline int valid_phys_addr_range(unsigned long addr, size_t count) |
79 | { | 49 | { |
@@ -115,15 +85,15 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size) | |||
115 | } | 85 | } |
116 | #endif | 86 | #endif |
117 | 87 | ||
118 | void __attribute__((weak)) unxlate_dev_mem_ptr(unsigned long phys, void *addr) | 88 | void __weak unxlate_dev_mem_ptr(unsigned long phys, void *addr) |
119 | { | 89 | { |
120 | } | 90 | } |
121 | 91 | ||
122 | /* | 92 | /* |
123 | * This funcion reads the *physical* memory. The f_pos points directly to the | 93 | * This funcion reads the *physical* memory. The f_pos points directly to the |
124 | * memory location. | 94 | * memory location. |
125 | */ | 95 | */ |
126 | static ssize_t read_mem(struct file * file, char __user * buf, | 96 | static ssize_t read_mem(struct file *file, char __user *buf, |
127 | size_t count, loff_t *ppos) | 97 | size_t count, loff_t *ppos) |
128 | { | 98 | { |
129 | unsigned long p = *ppos; | 99 | unsigned long p = *ppos; |
@@ -140,10 +110,10 @@ static ssize_t read_mem(struct file * file, char __user * buf, | |||
140 | if (sz > 0) { | 110 | if (sz > 0) { |
141 | if (clear_user(buf, sz)) | 111 | if (clear_user(buf, sz)) |
142 | return -EFAULT; | 112 | return -EFAULT; |
143 | buf += sz; | 113 | buf += sz; |
144 | p += sz; | 114 | p += sz; |
145 | count -= sz; | 115 | count -= sz; |
146 | read += sz; | 116 | read += sz; |
147 | } | 117 | } |
148 | } | 118 | } |
149 | #endif | 119 | #endif |
@@ -157,9 +127,9 @@ static ssize_t read_mem(struct file * file, char __user * buf, | |||
157 | return -EPERM; | 127 | return -EPERM; |
158 | 128 | ||
159 | /* | 129 | /* |
160 | * On ia64 if a page has been mapped somewhere as | 130 | * On ia64 if a page has been mapped somewhere as uncached, then |
161 | * uncached, then it must also be accessed uncached | 131 | * it must also be accessed uncached by the kernel or data |
162 | * by the kernel or data corruption may occur | 132 | * corruption may occur. |
163 | */ | 133 | */ |
164 | ptr = xlate_dev_mem_ptr(p); | 134 | ptr = xlate_dev_mem_ptr(p); |
165 | if (!ptr) | 135 | if (!ptr) |
@@ -180,7 +150,7 @@ static ssize_t read_mem(struct file * file, char __user * buf, | |||
180 | return read; | 150 | return read; |
181 | } | 151 | } |
182 | 152 | ||
183 | static ssize_t write_mem(struct file * file, const char __user * buf, | 153 | static ssize_t write_mem(struct file *file, const char __user *buf, |
184 | size_t count, loff_t *ppos) | 154 | size_t count, loff_t *ppos) |
185 | { | 155 | { |
186 | unsigned long p = *ppos; | 156 | unsigned long p = *ppos; |
@@ -212,9 +182,9 @@ static ssize_t write_mem(struct file * file, const char __user * buf, | |||
212 | return -EPERM; | 182 | return -EPERM; |
213 | 183 | ||
214 | /* | 184 | /* |
215 | * On ia64 if a page has been mapped somewhere as | 185 | * On ia64 if a page has been mapped somewhere as uncached, then |
216 | * uncached, then it must also be accessed uncached | 186 | * it must also be accessed uncached by the kernel or data |
217 | * by the kernel or data corruption may occur | 187 | * corruption may occur. |
218 | */ | 188 | */ |
219 | ptr = xlate_dev_mem_ptr(p); | 189 | ptr = xlate_dev_mem_ptr(p); |
220 | if (!ptr) { | 190 | if (!ptr) { |
@@ -242,13 +212,48 @@ static ssize_t write_mem(struct file * file, const char __user * buf, | |||
242 | return written; | 212 | return written; |
243 | } | 213 | } |
244 | 214 | ||
245 | int __attribute__((weak)) phys_mem_access_prot_allowed(struct file *file, | 215 | int __weak phys_mem_access_prot_allowed(struct file *file, |
246 | unsigned long pfn, unsigned long size, pgprot_t *vma_prot) | 216 | unsigned long pfn, unsigned long size, pgprot_t *vma_prot) |
247 | { | 217 | { |
248 | return 1; | 218 | return 1; |
249 | } | 219 | } |
250 | 220 | ||
251 | #ifndef __HAVE_PHYS_MEM_ACCESS_PROT | 221 | #ifndef __HAVE_PHYS_MEM_ACCESS_PROT |
222 | |||
223 | /* | ||
224 | * Architectures vary in how they handle caching for addresses | ||
225 | * outside of main memory. | ||
226 | * | ||
227 | */ | ||
228 | #ifdef pgprot_noncached | ||
229 | static int uncached_access(struct file *file, unsigned long addr) | ||
230 | { | ||
231 | #if defined(CONFIG_IA64) | ||
232 | /* | ||
233 | * On ia64, we ignore O_DSYNC because we cannot tolerate memory | ||
234 | * attribute aliases. | ||
235 | */ | ||
236 | return !(efi_mem_attributes(addr) & EFI_MEMORY_WB); | ||
237 | #elif defined(CONFIG_MIPS) | ||
238 | { | ||
239 | extern int __uncached_access(struct file *file, | ||
240 | unsigned long addr); | ||
241 | |||
242 | return __uncached_access(file, addr); | ||
243 | } | ||
244 | #else | ||
245 | /* | ||
246 | * Accessing memory above the top the kernel knows about or through a | ||
247 | * file pointer | ||
248 | * that was marked O_DSYNC will be done non-cached. | ||
249 | */ | ||
250 | if (file->f_flags & O_DSYNC) | ||
251 | return 1; | ||
252 | return addr >= __pa(high_memory); | ||
253 | #endif | ||
254 | } | ||
255 | #endif | ||
256 | |||
252 | static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | 257 | static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, |
253 | unsigned long size, pgprot_t vma_prot) | 258 | unsigned long size, pgprot_t vma_prot) |
254 | { | 259 | { |
@@ -294,7 +299,7 @@ static const struct vm_operations_struct mmap_mem_ops = { | |||
294 | #endif | 299 | #endif |
295 | }; | 300 | }; |
296 | 301 | ||
297 | static int mmap_mem(struct file * file, struct vm_area_struct * vma) | 302 | static int mmap_mem(struct file *file, struct vm_area_struct *vma) |
298 | { | 303 | { |
299 | size_t size = vma->vm_end - vma->vm_start; | 304 | size_t size = vma->vm_end - vma->vm_start; |
300 | 305 | ||
@@ -329,7 +334,7 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma) | |||
329 | } | 334 | } |
330 | 335 | ||
331 | #ifdef CONFIG_DEVKMEM | 336 | #ifdef CONFIG_DEVKMEM |
332 | static int mmap_kmem(struct file * file, struct vm_area_struct * vma) | 337 | static int mmap_kmem(struct file *file, struct vm_area_struct *vma) |
333 | { | 338 | { |
334 | unsigned long pfn; | 339 | unsigned long pfn; |
335 | 340 | ||
@@ -337,9 +342,9 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma) | |||
337 | pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT; | 342 | pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT; |
338 | 343 | ||
339 | /* | 344 | /* |
340 | * RED-PEN: on some architectures there is more mapped memory | 345 | * RED-PEN: on some architectures there is more mapped memory than |
341 | * than available in mem_map which pfn_valid checks | 346 | * available in mem_map which pfn_valid checks for. Perhaps should add a |
342 | * for. Perhaps should add a new macro here. | 347 | * new macro here. |
343 | * | 348 | * |
344 | * RED-PEN: vmalloc is not supported right now. | 349 | * RED-PEN: vmalloc is not supported right now. |
345 | */ | 350 | */ |
@@ -389,18 +394,19 @@ static ssize_t read_oldmem(struct file *file, char __user *buf, | |||
389 | /* | 394 | /* |
390 | * This function reads the *virtual* memory as seen by the kernel. | 395 | * This function reads the *virtual* memory as seen by the kernel. |
391 | */ | 396 | */ |
392 | static ssize_t read_kmem(struct file *file, char __user *buf, | 397 | static ssize_t read_kmem(struct file *file, char __user *buf, |
393 | size_t count, loff_t *ppos) | 398 | size_t count, loff_t *ppos) |
394 | { | 399 | { |
395 | unsigned long p = *ppos; | 400 | unsigned long p = *ppos; |
396 | ssize_t low_count, read, sz; | 401 | ssize_t low_count, read, sz; |
397 | char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */ | 402 | char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */ |
403 | int err = 0; | ||
398 | 404 | ||
399 | read = 0; | 405 | read = 0; |
400 | if (p < (unsigned long) high_memory) { | 406 | if (p < (unsigned long) high_memory) { |
401 | low_count = count; | 407 | low_count = count; |
402 | if (count > (unsigned long) high_memory - p) | 408 | if (count > (unsigned long)high_memory - p) |
403 | low_count = (unsigned long) high_memory - p; | 409 | low_count = (unsigned long)high_memory - p; |
404 | 410 | ||
405 | #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED | 411 | #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED |
406 | /* we don't have page 0 mapped on sparc and m68k.. */ | 412 | /* we don't have page 0 mapped on sparc and m68k.. */ |
@@ -441,12 +447,16 @@ static ssize_t read_kmem(struct file *file, char __user *buf, | |||
441 | return -ENOMEM; | 447 | return -ENOMEM; |
442 | while (count > 0) { | 448 | while (count > 0) { |
443 | sz = size_inside_page(p, count); | 449 | sz = size_inside_page(p, count); |
450 | if (!is_vmalloc_or_module_addr((void *)p)) { | ||
451 | err = -ENXIO; | ||
452 | break; | ||
453 | } | ||
444 | sz = vread(kbuf, (char *)p, sz); | 454 | sz = vread(kbuf, (char *)p, sz); |
445 | if (!sz) | 455 | if (!sz) |
446 | break; | 456 | break; |
447 | if (copy_to_user(buf, kbuf, sz)) { | 457 | if (copy_to_user(buf, kbuf, sz)) { |
448 | free_page((unsigned long)kbuf); | 458 | err = -EFAULT; |
449 | return -EFAULT; | 459 | break; |
450 | } | 460 | } |
451 | count -= sz; | 461 | count -= sz; |
452 | buf += sz; | 462 | buf += sz; |
@@ -455,14 +465,13 @@ static ssize_t read_kmem(struct file *file, char __user *buf, | |||
455 | } | 465 | } |
456 | free_page((unsigned long)kbuf); | 466 | free_page((unsigned long)kbuf); |
457 | } | 467 | } |
458 | *ppos = p; | 468 | *ppos = p; |
459 | return read; | 469 | return read ? read : err; |
460 | } | 470 | } |
461 | 471 | ||
462 | 472 | ||
463 | static inline ssize_t | 473 | static ssize_t do_write_kmem(unsigned long p, const char __user *buf, |
464 | do_write_kmem(unsigned long p, const char __user *buf, | 474 | size_t count, loff_t *ppos) |
465 | size_t count, loff_t *ppos) | ||
466 | { | 475 | { |
467 | ssize_t written, sz; | 476 | ssize_t written, sz; |
468 | unsigned long copied; | 477 | unsigned long copied; |
@@ -486,9 +495,9 @@ do_write_kmem(unsigned long p, const char __user *buf, | |||
486 | sz = size_inside_page(p, count); | 495 | sz = size_inside_page(p, count); |
487 | 496 | ||
488 | /* | 497 | /* |
489 | * On ia64 if a page has been mapped somewhere as | 498 | * On ia64 if a page has been mapped somewhere as uncached, then |
490 | * uncached, then it must also be accessed uncached | 499 | * it must also be accessed uncached by the kernel or data |
491 | * by the kernel or data corruption may occur | 500 | * corruption may occur. |
492 | */ | 501 | */ |
493 | ptr = xlate_dev_kmem_ptr((char *)p); | 502 | ptr = xlate_dev_kmem_ptr((char *)p); |
494 | 503 | ||
@@ -509,17 +518,17 @@ do_write_kmem(unsigned long p, const char __user *buf, | |||
509 | return written; | 518 | return written; |
510 | } | 519 | } |
511 | 520 | ||
512 | |||
513 | /* | 521 | /* |
514 | * This function writes to the *virtual* memory as seen by the kernel. | 522 | * This function writes to the *virtual* memory as seen by the kernel. |
515 | */ | 523 | */ |
516 | static ssize_t write_kmem(struct file * file, const char __user * buf, | 524 | static ssize_t write_kmem(struct file *file, const char __user *buf, |
517 | size_t count, loff_t *ppos) | 525 | size_t count, loff_t *ppos) |
518 | { | 526 | { |
519 | unsigned long p = *ppos; | 527 | unsigned long p = *ppos; |
520 | ssize_t wrote = 0; | 528 | ssize_t wrote = 0; |
521 | ssize_t virtr = 0; | 529 | ssize_t virtr = 0; |
522 | char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ | 530 | char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ |
531 | int err = 0; | ||
523 | 532 | ||
524 | if (p < (unsigned long) high_memory) { | 533 | if (p < (unsigned long) high_memory) { |
525 | unsigned long to_write = min_t(unsigned long, count, | 534 | unsigned long to_write = min_t(unsigned long, count, |
@@ -540,14 +549,16 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, | |||
540 | unsigned long sz = size_inside_page(p, count); | 549 | unsigned long sz = size_inside_page(p, count); |
541 | unsigned long n; | 550 | unsigned long n; |
542 | 551 | ||
552 | if (!is_vmalloc_or_module_addr((void *)p)) { | ||
553 | err = -ENXIO; | ||
554 | break; | ||
555 | } | ||
543 | n = copy_from_user(kbuf, buf, sz); | 556 | n = copy_from_user(kbuf, buf, sz); |
544 | if (n) { | 557 | if (n) { |
545 | if (wrote + virtr) | 558 | err = -EFAULT; |
546 | break; | 559 | break; |
547 | free_page((unsigned long)kbuf); | ||
548 | return -EFAULT; | ||
549 | } | 560 | } |
550 | sz = vwrite(kbuf, (char *)p, sz); | 561 | vwrite(kbuf, (char *)p, sz); |
551 | count -= sz; | 562 | count -= sz; |
552 | buf += sz; | 563 | buf += sz; |
553 | virtr += sz; | 564 | virtr += sz; |
@@ -556,23 +567,23 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, | |||
556 | free_page((unsigned long)kbuf); | 567 | free_page((unsigned long)kbuf); |
557 | } | 568 | } |
558 | 569 | ||
559 | *ppos = p; | 570 | *ppos = p; |
560 | return virtr + wrote; | 571 | return virtr + wrote ? : err; |
561 | } | 572 | } |
562 | #endif | 573 | #endif |
563 | 574 | ||
564 | #ifdef CONFIG_DEVPORT | 575 | #ifdef CONFIG_DEVPORT |
565 | static ssize_t read_port(struct file * file, char __user * buf, | 576 | static ssize_t read_port(struct file *file, char __user *buf, |
566 | size_t count, loff_t *ppos) | 577 | size_t count, loff_t *ppos) |
567 | { | 578 | { |
568 | unsigned long i = *ppos; | 579 | unsigned long i = *ppos; |
569 | char __user *tmp = buf; | 580 | char __user *tmp = buf; |
570 | 581 | ||
571 | if (!access_ok(VERIFY_WRITE, buf, count)) | 582 | if (!access_ok(VERIFY_WRITE, buf, count)) |
572 | return -EFAULT; | 583 | return -EFAULT; |
573 | while (count-- > 0 && i < 65536) { | 584 | while (count-- > 0 && i < 65536) { |
574 | if (__put_user(inb(i),tmp) < 0) | 585 | if (__put_user(inb(i), tmp) < 0) |
575 | return -EFAULT; | 586 | return -EFAULT; |
576 | i++; | 587 | i++; |
577 | tmp++; | 588 | tmp++; |
578 | } | 589 | } |
@@ -580,22 +591,22 @@ static ssize_t read_port(struct file * file, char __user * buf, | |||
580 | return tmp-buf; | 591 | return tmp-buf; |
581 | } | 592 | } |
582 | 593 | ||
583 | static ssize_t write_port(struct file * file, const char __user * buf, | 594 | static ssize_t write_port(struct file *file, const char __user *buf, |
584 | size_t count, loff_t *ppos) | 595 | size_t count, loff_t *ppos) |
585 | { | 596 | { |
586 | unsigned long i = *ppos; | 597 | unsigned long i = *ppos; |
587 | const char __user * tmp = buf; | 598 | const char __user * tmp = buf; |
588 | 599 | ||
589 | if (!access_ok(VERIFY_READ,buf,count)) | 600 | if (!access_ok(VERIFY_READ, buf, count)) |
590 | return -EFAULT; | 601 | return -EFAULT; |
591 | while (count-- > 0 && i < 65536) { | 602 | while (count-- > 0 && i < 65536) { |
592 | char c; | 603 | char c; |
593 | if (__get_user(c, tmp)) { | 604 | if (__get_user(c, tmp)) { |
594 | if (tmp > buf) | 605 | if (tmp > buf) |
595 | break; | 606 | break; |
596 | return -EFAULT; | 607 | return -EFAULT; |
597 | } | 608 | } |
598 | outb(c,i); | 609 | outb(c, i); |
599 | i++; | 610 | i++; |
600 | tmp++; | 611 | tmp++; |
601 | } | 612 | } |
@@ -604,13 +615,13 @@ static ssize_t write_port(struct file * file, const char __user * buf, | |||
604 | } | 615 | } |
605 | #endif | 616 | #endif |
606 | 617 | ||
607 | static ssize_t read_null(struct file * file, char __user * buf, | 618 | static ssize_t read_null(struct file *file, char __user *buf, |
608 | size_t count, loff_t *ppos) | 619 | size_t count, loff_t *ppos) |
609 | { | 620 | { |
610 | return 0; | 621 | return 0; |
611 | } | 622 | } |
612 | 623 | ||
613 | static ssize_t write_null(struct file * file, const char __user * buf, | 624 | static ssize_t write_null(struct file *file, const char __user *buf, |
614 | size_t count, loff_t *ppos) | 625 | size_t count, loff_t *ppos) |
615 | { | 626 | { |
616 | return count; | 627 | return count; |
@@ -622,13 +633,13 @@ static int pipe_to_null(struct pipe_inode_info *info, struct pipe_buffer *buf, | |||
622 | return sd->len; | 633 | return sd->len; |
623 | } | 634 | } |
624 | 635 | ||
625 | static ssize_t splice_write_null(struct pipe_inode_info *pipe,struct file *out, | 636 | static ssize_t splice_write_null(struct pipe_inode_info *pipe, struct file *out, |
626 | loff_t *ppos, size_t len, unsigned int flags) | 637 | loff_t *ppos, size_t len, unsigned int flags) |
627 | { | 638 | { |
628 | return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_null); | 639 | return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_null); |
629 | } | 640 | } |
630 | 641 | ||
631 | static ssize_t read_zero(struct file * file, char __user * buf, | 642 | static ssize_t read_zero(struct file *file, char __user *buf, |
632 | size_t count, loff_t *ppos) | 643 | size_t count, loff_t *ppos) |
633 | { | 644 | { |
634 | size_t written; | 645 | size_t written; |
@@ -659,7 +670,7 @@ static ssize_t read_zero(struct file * file, char __user * buf, | |||
659 | return written ? written : -EFAULT; | 670 | return written ? written : -EFAULT; |
660 | } | 671 | } |
661 | 672 | ||
662 | static int mmap_zero(struct file * file, struct vm_area_struct * vma) | 673 | static int mmap_zero(struct file *file, struct vm_area_struct *vma) |
663 | { | 674 | { |
664 | #ifndef CONFIG_MMU | 675 | #ifndef CONFIG_MMU |
665 | return -ENOSYS; | 676 | return -ENOSYS; |
@@ -669,7 +680,7 @@ static int mmap_zero(struct file * file, struct vm_area_struct * vma) | |||
669 | return 0; | 680 | return 0; |
670 | } | 681 | } |
671 | 682 | ||
672 | static ssize_t write_full(struct file * file, const char __user * buf, | 683 | static ssize_t write_full(struct file *file, const char __user *buf, |
673 | size_t count, loff_t *ppos) | 684 | size_t count, loff_t *ppos) |
674 | { | 685 | { |
675 | return -ENOSPC; | 686 | return -ENOSPC; |
@@ -680,8 +691,7 @@ static ssize_t write_full(struct file * file, const char __user * buf, | |||
680 | * can fopen() both devices with "a" now. This was previously impossible. | 691 | * can fopen() both devices with "a" now. This was previously impossible. |
681 | * -- SRB. | 692 | * -- SRB. |
682 | */ | 693 | */ |
683 | 694 | static loff_t null_lseek(struct file *file, loff_t offset, int orig) | |
684 | static loff_t null_lseek(struct file * file, loff_t offset, int orig) | ||
685 | { | 695 | { |
686 | return file->f_pos = 0; | 696 | return file->f_pos = 0; |
687 | } | 697 | } |
@@ -694,24 +704,26 @@ static loff_t null_lseek(struct file * file, loff_t offset, int orig) | |||
694 | * also note that seeking relative to the "end of file" isn't supported: | 704 | * also note that seeking relative to the "end of file" isn't supported: |
695 | * it has no meaning, so it returns -EINVAL. | 705 | * it has no meaning, so it returns -EINVAL. |
696 | */ | 706 | */ |
697 | static loff_t memory_lseek(struct file * file, loff_t offset, int orig) | 707 | static loff_t memory_lseek(struct file *file, loff_t offset, int orig) |
698 | { | 708 | { |
699 | loff_t ret; | 709 | loff_t ret; |
700 | 710 | ||
701 | mutex_lock(&file->f_path.dentry->d_inode->i_mutex); | 711 | mutex_lock(&file->f_path.dentry->d_inode->i_mutex); |
702 | switch (orig) { | 712 | switch (orig) { |
703 | case 0: | 713 | case SEEK_CUR: |
704 | file->f_pos = offset; | 714 | offset += file->f_pos; |
705 | ret = file->f_pos; | 715 | case SEEK_SET: |
706 | force_successful_syscall_return(); | 716 | /* to avoid userland mistaking f_pos=-9 as -EBADF=-9 */ |
717 | if ((unsigned long long)offset >= ~0xFFFULL) { | ||
718 | ret = -EOVERFLOW; | ||
707 | break; | 719 | break; |
708 | case 1: | 720 | } |
709 | file->f_pos += offset; | 721 | file->f_pos = offset; |
710 | ret = file->f_pos; | 722 | ret = file->f_pos; |
711 | force_successful_syscall_return(); | 723 | force_successful_syscall_return(); |
712 | break; | 724 | break; |
713 | default: | 725 | default: |
714 | ret = -EINVAL; | 726 | ret = -EINVAL; |
715 | } | 727 | } |
716 | mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); | 728 | mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); |
717 | return ret; | 729 | return ret; |
@@ -776,10 +788,11 @@ static const struct file_operations zero_fops = { | |||
776 | /* | 788 | /* |
777 | * capabilities for /dev/zero | 789 | * capabilities for /dev/zero |
778 | * - permits private mappings, "copies" are taken of the source of zeros | 790 | * - permits private mappings, "copies" are taken of the source of zeros |
791 | * - no writeback happens | ||
779 | */ | 792 | */ |
780 | static struct backing_dev_info zero_bdi = { | 793 | static struct backing_dev_info zero_bdi = { |
781 | .name = "char/mem", | 794 | .name = "char/mem", |
782 | .capabilities = BDI_CAP_MAP_COPY, | 795 | .capabilities = BDI_CAP_MAP_COPY | BDI_CAP_NO_ACCT_AND_WRITEBACK, |
783 | }; | 796 | }; |
784 | 797 | ||
785 | static const struct file_operations full_fops = { | 798 | static const struct file_operations full_fops = { |
@@ -792,10 +805,11 @@ static const struct file_operations full_fops = { | |||
792 | static const struct file_operations oldmem_fops = { | 805 | static const struct file_operations oldmem_fops = { |
793 | .read = read_oldmem, | 806 | .read = read_oldmem, |
794 | .open = open_oldmem, | 807 | .open = open_oldmem, |
808 | .llseek = default_llseek, | ||
795 | }; | 809 | }; |
796 | #endif | 810 | #endif |
797 | 811 | ||
798 | static ssize_t kmsg_write(struct file * file, const char __user * buf, | 812 | static ssize_t kmsg_write(struct file *file, const char __user *buf, |
799 | size_t count, loff_t *ppos) | 813 | size_t count, loff_t *ppos) |
800 | { | 814 | { |
801 | char *tmp; | 815 | char *tmp; |
@@ -817,7 +831,8 @@ static ssize_t kmsg_write(struct file * file, const char __user * buf, | |||
817 | } | 831 | } |
818 | 832 | ||
819 | static const struct file_operations kmsg_fops = { | 833 | static const struct file_operations kmsg_fops = { |
820 | .write = kmsg_write, | 834 | .write = kmsg_write, |
835 | .llseek = noop_llseek, | ||
821 | }; | 836 | }; |
822 | 837 | ||
823 | static const struct memdev { | 838 | static const struct memdev { |
@@ -861,6 +876,10 @@ static int memory_open(struct inode *inode, struct file *filp) | |||
861 | if (dev->dev_info) | 876 | if (dev->dev_info) |
862 | filp->f_mapping->backing_dev_info = dev->dev_info; | 877 | filp->f_mapping->backing_dev_info = dev->dev_info; |
863 | 878 | ||
879 | /* Is /dev/mem or /dev/kmem ? */ | ||
880 | if (dev->dev_info == &directly_mappable_cdev_bdi) | ||
881 | filp->f_mode |= FMODE_UNSIGNED_OFFSET; | ||
882 | |||
864 | if (dev->fops->open) | 883 | if (dev->fops->open) |
865 | return dev->fops->open(inode, filp); | 884 | return dev->fops->open(inode, filp); |
866 | 885 | ||
@@ -868,7 +887,8 @@ static int memory_open(struct inode *inode, struct file *filp) | |||
868 | } | 887 | } |
869 | 888 | ||
870 | static const struct file_operations memory_fops = { | 889 | static const struct file_operations memory_fops = { |
871 | .open = memory_open, | 890 | .open = memory_open, |
891 | .llseek = noop_llseek, | ||
872 | }; | 892 | }; |
873 | 893 | ||
874 | static char *mem_devnode(struct device *dev, mode_t *mode) | 894 | static char *mem_devnode(struct device *dev, mode_t *mode) |
@@ -889,10 +909,13 @@ static int __init chr_dev_init(void) | |||
889 | if (err) | 909 | if (err) |
890 | return err; | 910 | return err; |
891 | 911 | ||
892 | if (register_chrdev(MEM_MAJOR,"mem",&memory_fops)) | 912 | if (register_chrdev(MEM_MAJOR, "mem", &memory_fops)) |
893 | printk("unable to get major %d for memory devs\n", MEM_MAJOR); | 913 | printk("unable to get major %d for memory devs\n", MEM_MAJOR); |
894 | 914 | ||
895 | mem_class = class_create(THIS_MODULE, "mem"); | 915 | mem_class = class_create(THIS_MODULE, "mem"); |
916 | if (IS_ERR(mem_class)) | ||
917 | return PTR_ERR(mem_class); | ||
918 | |||
896 | mem_class->devnode = mem_devnode; | 919 | mem_class->devnode = mem_devnode; |
897 | for (minor = 1; minor < ARRAY_SIZE(devlist); minor++) { | 920 | for (minor = 1; minor < ARRAY_SIZE(devlist); minor++) { |
898 | if (!devlist[minor].name) | 921 | if (!devlist[minor].name) |
@@ -901,7 +924,7 @@ static int __init chr_dev_init(void) | |||
901 | NULL, devlist[minor].name); | 924 | NULL, devlist[minor].name); |
902 | } | 925 | } |
903 | 926 | ||
904 | return 0; | 927 | return tty_init(); |
905 | } | 928 | } |
906 | 929 | ||
907 | fs_initcall(chr_dev_init); | 930 | fs_initcall(chr_dev_init); |
diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 94a136e96c06..778273c93242 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <linux/miscdevice.h> | 40 | #include <linux/miscdevice.h> |
41 | #include <linux/kernel.h> | 41 | #include <linux/kernel.h> |
42 | #include <linux/major.h> | 42 | #include <linux/major.h> |
43 | #include <linux/slab.h> | ||
44 | #include <linux/mutex.h> | 43 | #include <linux/mutex.h> |
45 | #include <linux/proc_fs.h> | 44 | #include <linux/proc_fs.h> |
46 | #include <linux/seq_file.h> | 45 | #include <linux/seq_file.h> |
@@ -49,6 +48,7 @@ | |||
49 | #include <linux/device.h> | 48 | #include <linux/device.h> |
50 | #include <linux/tty.h> | 49 | #include <linux/tty.h> |
51 | #include <linux/kmod.h> | 50 | #include <linux/kmod.h> |
51 | #include <linux/gfp.h> | ||
52 | 52 | ||
53 | /* | 53 | /* |
54 | * Head entry for the doubly linked miscdevice list | 54 | * Head entry for the doubly linked miscdevice list |
@@ -144,6 +144,7 @@ static int misc_open(struct inode * inode, struct file * file) | |||
144 | old_fops = file->f_op; | 144 | old_fops = file->f_op; |
145 | file->f_op = new_fops; | 145 | file->f_op = new_fops; |
146 | if (file->f_op->open) { | 146 | if (file->f_op->open) { |
147 | file->private_data = c; | ||
147 | err=file->f_op->open(inode,file); | 148 | err=file->f_op->open(inode,file); |
148 | if (err) { | 149 | if (err) { |
149 | fops_put(file->f_op); | 150 | fops_put(file->f_op); |
@@ -161,6 +162,7 @@ static struct class *misc_class; | |||
161 | static const struct file_operations misc_fops = { | 162 | static const struct file_operations misc_fops = { |
162 | .owner = THIS_MODULE, | 163 | .owner = THIS_MODULE, |
163 | .open = misc_open, | 164 | .open = misc_open, |
165 | .llseek = noop_llseek, | ||
164 | }; | 166 | }; |
165 | 167 | ||
166 | /** | 168 | /** |
@@ -241,7 +243,7 @@ int misc_deregister(struct miscdevice *misc) | |||
241 | { | 243 | { |
242 | int i = DYNAMIC_MINORS - misc->minor - 1; | 244 | int i = DYNAMIC_MINORS - misc->minor - 1; |
243 | 245 | ||
244 | if (list_empty(&misc->list)) | 246 | if (WARN_ON(list_empty(&misc->list))) |
245 | return -EINVAL; | 247 | return -EINVAL; |
246 | 248 | ||
247 | mutex_lock(&misc_mtx); | 249 | mutex_lock(&misc_mtx); |
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index 918711aa56f3..e6d75627c6c8 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c | |||
@@ -32,7 +32,8 @@ | |||
32 | #include <linux/interrupt.h> | 32 | #include <linux/interrupt.h> |
33 | #include <linux/time.h> | 33 | #include <linux/time.h> |
34 | #include <linux/math64.h> | 34 | #include <linux/math64.h> |
35 | #include <linux/smp_lock.h> | 35 | #include <linux/mutex.h> |
36 | #include <linux/slab.h> | ||
36 | 37 | ||
37 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
38 | #include <asm/sn/addrs.h> | 39 | #include <asm/sn/addrs.h> |
@@ -58,6 +59,7 @@ extern unsigned long sn_rtc_cycles_per_second; | |||
58 | 59 | ||
59 | #define rtc_time() (*RTC_COUNTER_ADDR) | 60 | #define rtc_time() (*RTC_COUNTER_ADDR) |
60 | 61 | ||
62 | static DEFINE_MUTEX(mmtimer_mutex); | ||
61 | static long mmtimer_ioctl(struct file *file, unsigned int cmd, | 63 | static long mmtimer_ioctl(struct file *file, unsigned int cmd, |
62 | unsigned long arg); | 64 | unsigned long arg); |
63 | static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma); | 65 | static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma); |
@@ -71,6 +73,7 @@ static const struct file_operations mmtimer_fops = { | |||
71 | .owner = THIS_MODULE, | 73 | .owner = THIS_MODULE, |
72 | .mmap = mmtimer_mmap, | 74 | .mmap = mmtimer_mmap, |
73 | .unlocked_ioctl = mmtimer_ioctl, | 75 | .unlocked_ioctl = mmtimer_ioctl, |
76 | .llseek = noop_llseek, | ||
74 | }; | 77 | }; |
75 | 78 | ||
76 | /* | 79 | /* |
@@ -173,9 +176,9 @@ static void mmtimer_setup_int_2(int cpu, u64 expires) | |||
173 | * in order to insure that the setup succeeds in a deterministic time frame. | 176 | * in order to insure that the setup succeeds in a deterministic time frame. |
174 | * It will check if the interrupt setup succeeded. | 177 | * It will check if the interrupt setup succeeded. |
175 | */ | 178 | */ |
176 | static int mmtimer_setup(int cpu, int comparator, unsigned long expires) | 179 | static int mmtimer_setup(int cpu, int comparator, unsigned long expires, |
180 | u64 *set_completion_time) | ||
177 | { | 181 | { |
178 | |||
179 | switch (comparator) { | 182 | switch (comparator) { |
180 | case 0: | 183 | case 0: |
181 | mmtimer_setup_int_0(cpu, expires); | 184 | mmtimer_setup_int_0(cpu, expires); |
@@ -188,7 +191,8 @@ static int mmtimer_setup(int cpu, int comparator, unsigned long expires) | |||
188 | break; | 191 | break; |
189 | } | 192 | } |
190 | /* We might've missed our expiration time */ | 193 | /* We might've missed our expiration time */ |
191 | if (rtc_time() <= expires) | 194 | *set_completion_time = rtc_time(); |
195 | if (*set_completion_time <= expires) | ||
192 | return 1; | 196 | return 1; |
193 | 197 | ||
194 | /* | 198 | /* |
@@ -224,6 +228,8 @@ static int mmtimer_disable_int(long nasid, int comparator) | |||
224 | #define TIMER_OFF 0xbadcabLL /* Timer is not setup */ | 228 | #define TIMER_OFF 0xbadcabLL /* Timer is not setup */ |
225 | #define TIMER_SET 0 /* Comparator is set for this timer */ | 229 | #define TIMER_SET 0 /* Comparator is set for this timer */ |
226 | 230 | ||
231 | #define MMTIMER_INTERVAL_RETRY_INCREMENT_DEFAULT 40 | ||
232 | |||
227 | /* There is one of these for each timer */ | 233 | /* There is one of these for each timer */ |
228 | struct mmtimer { | 234 | struct mmtimer { |
229 | struct rb_node list; | 235 | struct rb_node list; |
@@ -239,6 +245,11 @@ struct mmtimer_node { | |||
239 | }; | 245 | }; |
240 | static struct mmtimer_node *timers; | 246 | static struct mmtimer_node *timers; |
241 | 247 | ||
248 | static unsigned mmtimer_interval_retry_increment = | ||
249 | MMTIMER_INTERVAL_RETRY_INCREMENT_DEFAULT; | ||
250 | module_param(mmtimer_interval_retry_increment, uint, 0644); | ||
251 | MODULE_PARM_DESC(mmtimer_interval_retry_increment, | ||
252 | "RTC ticks to add to expiration on interval retry (default 40)"); | ||
242 | 253 | ||
243 | /* | 254 | /* |
244 | * Add a new mmtimer struct to the node's mmtimer list. | 255 | * Add a new mmtimer struct to the node's mmtimer list. |
@@ -286,7 +297,8 @@ static void mmtimer_set_next_timer(int nodeid) | |||
286 | struct mmtimer_node *n = &timers[nodeid]; | 297 | struct mmtimer_node *n = &timers[nodeid]; |
287 | struct mmtimer *x; | 298 | struct mmtimer *x; |
288 | struct k_itimer *t; | 299 | struct k_itimer *t; |
289 | int o; | 300 | u64 expires, exp, set_completion_time; |
301 | int i; | ||
290 | 302 | ||
291 | restart: | 303 | restart: |
292 | if (n->next == NULL) | 304 | if (n->next == NULL) |
@@ -297,7 +309,8 @@ restart: | |||
297 | if (!t->it.mmtimer.incr) { | 309 | if (!t->it.mmtimer.incr) { |
298 | /* Not an interval timer */ | 310 | /* Not an interval timer */ |
299 | if (!mmtimer_setup(x->cpu, COMPARATOR, | 311 | if (!mmtimer_setup(x->cpu, COMPARATOR, |
300 | t->it.mmtimer.expires)) { | 312 | t->it.mmtimer.expires, |
313 | &set_completion_time)) { | ||
301 | /* Late setup, fire now */ | 314 | /* Late setup, fire now */ |
302 | tasklet_schedule(&n->tasklet); | 315 | tasklet_schedule(&n->tasklet); |
303 | } | 316 | } |
@@ -305,14 +318,23 @@ restart: | |||
305 | } | 318 | } |
306 | 319 | ||
307 | /* Interval timer */ | 320 | /* Interval timer */ |
308 | o = 0; | 321 | i = 0; |
309 | while (!mmtimer_setup(x->cpu, COMPARATOR, t->it.mmtimer.expires)) { | 322 | expires = exp = t->it.mmtimer.expires; |
310 | unsigned long e, e1; | 323 | while (!mmtimer_setup(x->cpu, COMPARATOR, expires, |
311 | struct rb_node *next; | 324 | &set_completion_time)) { |
312 | t->it.mmtimer.expires += t->it.mmtimer.incr << o; | 325 | int to; |
313 | t->it_overrun += 1 << o; | 326 | |
314 | o++; | 327 | i++; |
315 | if (o > 20) { | 328 | expires = set_completion_time + |
329 | mmtimer_interval_retry_increment + (1 << i); | ||
330 | /* Calculate overruns as we go. */ | ||
331 | to = ((u64)(expires - exp) / t->it.mmtimer.incr); | ||
332 | if (to) { | ||
333 | t->it_overrun += to; | ||
334 | t->it.mmtimer.expires += t->it.mmtimer.incr * to; | ||
335 | exp = t->it.mmtimer.expires; | ||
336 | } | ||
337 | if (i > 20) { | ||
316 | printk(KERN_ALERT "mmtimer: cannot reschedule timer\n"); | 338 | printk(KERN_ALERT "mmtimer: cannot reschedule timer\n"); |
317 | t->it.mmtimer.clock = TIMER_OFF; | 339 | t->it.mmtimer.clock = TIMER_OFF; |
318 | n->next = rb_next(&x->list); | 340 | n->next = rb_next(&x->list); |
@@ -320,21 +342,6 @@ restart: | |||
320 | kfree(x); | 342 | kfree(x); |
321 | goto restart; | 343 | goto restart; |
322 | } | 344 | } |
323 | |||
324 | e = t->it.mmtimer.expires; | ||
325 | next = rb_next(&x->list); | ||
326 | |||
327 | if (next == NULL) | ||
328 | continue; | ||
329 | |||
330 | e1 = rb_entry(next, struct mmtimer, list)-> | ||
331 | timer->it.mmtimer.expires; | ||
332 | if (e > e1) { | ||
333 | n->next = next; | ||
334 | rb_erase(&x->list, &n->timer_head); | ||
335 | mmtimer_add_list(x); | ||
336 | goto restart; | ||
337 | } | ||
338 | } | 345 | } |
339 | } | 346 | } |
340 | 347 | ||
@@ -370,7 +377,7 @@ static long mmtimer_ioctl(struct file *file, unsigned int cmd, | |||
370 | { | 377 | { |
371 | int ret = 0; | 378 | int ret = 0; |
372 | 379 | ||
373 | lock_kernel(); | 380 | mutex_lock(&mmtimer_mutex); |
374 | 381 | ||
375 | switch (cmd) { | 382 | switch (cmd) { |
376 | case MMTIMER_GETOFFSET: /* offset of the counter */ | 383 | case MMTIMER_GETOFFSET: /* offset of the counter */ |
@@ -413,7 +420,7 @@ static long mmtimer_ioctl(struct file *file, unsigned int cmd, | |||
413 | ret = -ENOTTY; | 420 | ret = -ENOTTY; |
414 | break; | 421 | break; |
415 | } | 422 | } |
416 | unlock_kernel(); | 423 | mutex_unlock(&mmtimer_mutex); |
417 | return ret; | 424 | return ret; |
418 | } | 425 | } |
419 | 426 | ||
@@ -546,7 +553,7 @@ static void mmtimer_tasklet(unsigned long data) | |||
546 | { | 553 | { |
547 | int nodeid = data; | 554 | int nodeid = data; |
548 | struct mmtimer_node *mn = &timers[nodeid]; | 555 | struct mmtimer_node *mn = &timers[nodeid]; |
549 | struct mmtimer *x = rb_entry(mn->next, struct mmtimer, list); | 556 | struct mmtimer *x; |
550 | struct k_itimer *t; | 557 | struct k_itimer *t; |
551 | unsigned long flags; | 558 | unsigned long flags; |
552 | 559 | ||
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 63ee3bbc1ce4..107b0bd58d19 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/pci.h> | 43 | #include <linux/pci.h> |
44 | #include <linux/init.h> | 44 | #include <linux/init.h> |
45 | #include <linux/bitops.h> | 45 | #include <linux/bitops.h> |
46 | #include <linux/slab.h> | ||
46 | 47 | ||
47 | #include <asm/system.h> | 48 | #include <asm/system.h> |
48 | #include <asm/io.h> | 49 | #include <asm/io.h> |
@@ -164,24 +165,25 @@ static unsigned int moxaFuncTout = HZ / 2; | |||
164 | static unsigned int moxaLowWaterChk; | 165 | static unsigned int moxaLowWaterChk; |
165 | static DEFINE_MUTEX(moxa_openlock); | 166 | static DEFINE_MUTEX(moxa_openlock); |
166 | static DEFINE_SPINLOCK(moxa_lock); | 167 | static DEFINE_SPINLOCK(moxa_lock); |
167 | /* Variables for insmod */ | 168 | |
168 | #ifdef MODULE | ||
169 | static unsigned long baseaddr[MAX_BOARDS]; | 169 | static unsigned long baseaddr[MAX_BOARDS]; |
170 | static unsigned int type[MAX_BOARDS]; | 170 | static unsigned int type[MAX_BOARDS]; |
171 | static unsigned int numports[MAX_BOARDS]; | 171 | static unsigned int numports[MAX_BOARDS]; |
172 | #endif | ||
173 | 172 | ||
174 | MODULE_AUTHOR("William Chen"); | 173 | MODULE_AUTHOR("William Chen"); |
175 | MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver"); | 174 | MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver"); |
176 | MODULE_LICENSE("GPL"); | 175 | MODULE_LICENSE("GPL"); |
177 | #ifdef MODULE | 176 | MODULE_FIRMWARE("c218tunx.cod"); |
177 | MODULE_FIRMWARE("cp204unx.cod"); | ||
178 | MODULE_FIRMWARE("c320tunx.cod"); | ||
179 | |||
178 | module_param_array(type, uint, NULL, 0); | 180 | module_param_array(type, uint, NULL, 0); |
179 | MODULE_PARM_DESC(type, "card type: C218=2, C320=4"); | 181 | MODULE_PARM_DESC(type, "card type: C218=2, C320=4"); |
180 | module_param_array(baseaddr, ulong, NULL, 0); | 182 | module_param_array(baseaddr, ulong, NULL, 0); |
181 | MODULE_PARM_DESC(baseaddr, "base address"); | 183 | MODULE_PARM_DESC(baseaddr, "base address"); |
182 | module_param_array(numports, uint, NULL, 0); | 184 | module_param_array(numports, uint, NULL, 0); |
183 | MODULE_PARM_DESC(numports, "numports (ignored for C218)"); | 185 | MODULE_PARM_DESC(numports, "numports (ignored for C218)"); |
184 | #endif | 186 | |
185 | module_param(ttymajor, int, 0); | 187 | module_param(ttymajor, int, 0); |
186 | 188 | ||
187 | /* | 189 | /* |
@@ -1024,6 +1026,8 @@ static int __init moxa_init(void) | |||
1024 | { | 1026 | { |
1025 | unsigned int isabrds = 0; | 1027 | unsigned int isabrds = 0; |
1026 | int retval = 0; | 1028 | int retval = 0; |
1029 | struct moxa_board_conf *brd = moxa_boards; | ||
1030 | unsigned int i; | ||
1027 | 1031 | ||
1028 | printk(KERN_INFO "MOXA Intellio family driver version %s\n", | 1032 | printk(KERN_INFO "MOXA Intellio family driver version %s\n", |
1029 | MOXA_VERSION); | 1033 | MOXA_VERSION); |
@@ -1051,10 +1055,7 @@ static int __init moxa_init(void) | |||
1051 | } | 1055 | } |
1052 | 1056 | ||
1053 | /* Find the boards defined from module args. */ | 1057 | /* Find the boards defined from module args. */ |
1054 | #ifdef MODULE | 1058 | |
1055 | { | ||
1056 | struct moxa_board_conf *brd = moxa_boards; | ||
1057 | unsigned int i; | ||
1058 | for (i = 0; i < MAX_BOARDS; i++) { | 1059 | for (i = 0; i < MAX_BOARDS; i++) { |
1059 | if (!baseaddr[i]) | 1060 | if (!baseaddr[i]) |
1060 | break; | 1061 | break; |
@@ -1087,8 +1088,6 @@ static int __init moxa_init(void) | |||
1087 | isabrds++; | 1088 | isabrds++; |
1088 | } | 1089 | } |
1089 | } | 1090 | } |
1090 | } | ||
1091 | #endif | ||
1092 | 1091 | ||
1093 | #ifdef CONFIG_PCI | 1092 | #ifdef CONFIG_PCI |
1094 | retval = pci_register_driver(&moxa_pci_driver); | 1093 | retval = pci_register_driver(&moxa_pci_driver); |
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index ecb89d798e35..966a95bc974b 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c | |||
@@ -316,7 +316,8 @@ uncached_mmap(struct file *file, struct vm_area_struct *vma) | |||
316 | 316 | ||
317 | static const struct file_operations fetchop_fops = { | 317 | static const struct file_operations fetchop_fops = { |
318 | .owner = THIS_MODULE, | 318 | .owner = THIS_MODULE, |
319 | .mmap = fetchop_mmap | 319 | .mmap = fetchop_mmap, |
320 | .llseek = noop_llseek, | ||
320 | }; | 321 | }; |
321 | 322 | ||
322 | static struct miscdevice fetchop_miscdev = { | 323 | static struct miscdevice fetchop_miscdev = { |
@@ -327,7 +328,8 @@ static struct miscdevice fetchop_miscdev = { | |||
327 | 328 | ||
328 | static const struct file_operations cached_fops = { | 329 | static const struct file_operations cached_fops = { |
329 | .owner = THIS_MODULE, | 330 | .owner = THIS_MODULE, |
330 | .mmap = cached_mmap | 331 | .mmap = cached_mmap, |
332 | .llseek = noop_llseek, | ||
331 | }; | 333 | }; |
332 | 334 | ||
333 | static struct miscdevice cached_miscdev = { | 335 | static struct miscdevice cached_miscdev = { |
@@ -338,7 +340,8 @@ static struct miscdevice cached_miscdev = { | |||
338 | 340 | ||
339 | static const struct file_operations uncached_fops = { | 341 | static const struct file_operations uncached_fops = { |
340 | .owner = THIS_MODULE, | 342 | .owner = THIS_MODULE, |
341 | .mmap = uncached_mmap | 343 | .mmap = uncached_mmap, |
344 | .llseek = noop_llseek, | ||
342 | }; | 345 | }; |
343 | 346 | ||
344 | static struct miscdevice uncached_miscdev = { | 347 | static struct miscdevice uncached_miscdev = { |
diff --git a/drivers/char/mwave/Makefile b/drivers/char/mwave/Makefile index 754c9e2058ed..26b4fce217b6 100644 --- a/drivers/char/mwave/Makefile +++ b/drivers/char/mwave/Makefile | |||
@@ -6,10 +6,10 @@ | |||
6 | 6 | ||
7 | obj-$(CONFIG_MWAVE) += mwave.o | 7 | obj-$(CONFIG_MWAVE) += mwave.o |
8 | 8 | ||
9 | mwave-objs := mwavedd.o smapi.o tp3780i.o 3780i.o | 9 | mwave-y := mwavedd.o smapi.o tp3780i.o 3780i.o |
10 | 10 | ||
11 | # To have the mwave driver disable other uarts if necessary | 11 | # To have the mwave driver disable other uarts if necessary |
12 | # EXTRA_CFLAGS += -DMWAVE_FUTZ_WITH_OTHER_DEVICES | 12 | # EXTRA_CFLAGS += -DMWAVE_FUTZ_WITH_OTHER_DEVICES |
13 | 13 | ||
14 | # To compile in lots (~20 KiB) of run-time enablable printk()s for debugging: | 14 | # To compile in lots (~20 KiB) of run-time enablable printk()s for debugging: |
15 | EXTRA_CFLAGS += -DMW_TRACE | 15 | ccflags-y := -DMW_TRACE |
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c index a4ec50c95072..1d82d5838f0c 100644 --- a/drivers/char/mwave/mwavedd.c +++ b/drivers/char/mwave/mwavedd.c | |||
@@ -56,7 +56,7 @@ | |||
56 | #include <linux/serial.h> | 56 | #include <linux/serial.h> |
57 | #include <linux/sched.h> | 57 | #include <linux/sched.h> |
58 | #include <linux/spinlock.h> | 58 | #include <linux/spinlock.h> |
59 | #include <linux/smp_lock.h> | 59 | #include <linux/mutex.h> |
60 | #include <linux/delay.h> | 60 | #include <linux/delay.h> |
61 | #include <linux/serial_8250.h> | 61 | #include <linux/serial_8250.h> |
62 | #include "smapi.h" | 62 | #include "smapi.h" |
@@ -73,6 +73,7 @@ MODULE_LICENSE("GPL"); | |||
73 | * checks are made against other devices (ie. superio) for conflicts. | 73 | * checks are made against other devices (ie. superio) for conflicts. |
74 | * We'll depend on users using the tpctl utility to do that for now | 74 | * We'll depend on users using the tpctl utility to do that for now |
75 | */ | 75 | */ |
76 | static DEFINE_MUTEX(mwave_mutex); | ||
76 | int mwave_debug = 0; | 77 | int mwave_debug = 0; |
77 | int mwave_3780i_irq = 0; | 78 | int mwave_3780i_irq = 0; |
78 | int mwave_3780i_io = 0; | 79 | int mwave_3780i_io = 0; |
@@ -101,7 +102,6 @@ static int mwave_open(struct inode *inode, struct file *file) | |||
101 | PRINTK_2(TRACE_MWAVE, | 102 | PRINTK_2(TRACE_MWAVE, |
102 | "mwavedd::mwave_open, exit return retval %x\n", retval); | 103 | "mwavedd::mwave_open, exit return retval %x\n", retval); |
103 | 104 | ||
104 | cycle_kernel_lock(); | ||
105 | return retval; | 105 | return retval; |
106 | } | 106 | } |
107 | 107 | ||
@@ -136,9 +136,9 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd, | |||
136 | PRINTK_1(TRACE_MWAVE, | 136 | PRINTK_1(TRACE_MWAVE, |
137 | "mwavedd::mwave_ioctl, IOCTL_MW_RESET" | 137 | "mwavedd::mwave_ioctl, IOCTL_MW_RESET" |
138 | " calling tp3780I_ResetDSP\n"); | 138 | " calling tp3780I_ResetDSP\n"); |
139 | lock_kernel(); | 139 | mutex_lock(&mwave_mutex); |
140 | retval = tp3780I_ResetDSP(&pDrvData->rBDData); | 140 | retval = tp3780I_ResetDSP(&pDrvData->rBDData); |
141 | unlock_kernel(); | 141 | mutex_unlock(&mwave_mutex); |
142 | PRINTK_2(TRACE_MWAVE, | 142 | PRINTK_2(TRACE_MWAVE, |
143 | "mwavedd::mwave_ioctl, IOCTL_MW_RESET" | 143 | "mwavedd::mwave_ioctl, IOCTL_MW_RESET" |
144 | " retval %x from tp3780I_ResetDSP\n", | 144 | " retval %x from tp3780I_ResetDSP\n", |
@@ -149,9 +149,9 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd, | |||
149 | PRINTK_1(TRACE_MWAVE, | 149 | PRINTK_1(TRACE_MWAVE, |
150 | "mwavedd::mwave_ioctl, IOCTL_MW_RUN" | 150 | "mwavedd::mwave_ioctl, IOCTL_MW_RUN" |
151 | " calling tp3780I_StartDSP\n"); | 151 | " calling tp3780I_StartDSP\n"); |
152 | lock_kernel(); | 152 | mutex_lock(&mwave_mutex); |
153 | retval = tp3780I_StartDSP(&pDrvData->rBDData); | 153 | retval = tp3780I_StartDSP(&pDrvData->rBDData); |
154 | unlock_kernel(); | 154 | mutex_unlock(&mwave_mutex); |
155 | PRINTK_2(TRACE_MWAVE, | 155 | PRINTK_2(TRACE_MWAVE, |
156 | "mwavedd::mwave_ioctl, IOCTL_MW_RUN" | 156 | "mwavedd::mwave_ioctl, IOCTL_MW_RUN" |
157 | " retval %x from tp3780I_StartDSP\n", | 157 | " retval %x from tp3780I_StartDSP\n", |
@@ -165,10 +165,10 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd, | |||
165 | "mwavedd::mwave_ioctl," | 165 | "mwavedd::mwave_ioctl," |
166 | " IOCTL_MW_DSP_ABILITIES calling" | 166 | " IOCTL_MW_DSP_ABILITIES calling" |
167 | " tp3780I_QueryAbilities\n"); | 167 | " tp3780I_QueryAbilities\n"); |
168 | lock_kernel(); | 168 | mutex_lock(&mwave_mutex); |
169 | retval = tp3780I_QueryAbilities(&pDrvData->rBDData, | 169 | retval = tp3780I_QueryAbilities(&pDrvData->rBDData, |
170 | &rAbilities); | 170 | &rAbilities); |
171 | unlock_kernel(); | 171 | mutex_unlock(&mwave_mutex); |
172 | PRINTK_2(TRACE_MWAVE, | 172 | PRINTK_2(TRACE_MWAVE, |
173 | "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES" | 173 | "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES" |
174 | " retval %x from tp3780I_QueryAbilities\n", | 174 | " retval %x from tp3780I_QueryAbilities\n", |
@@ -199,13 +199,13 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd, | |||
199 | "mwavedd::mwave_ioctl IOCTL_MW_READ_DATA," | 199 | "mwavedd::mwave_ioctl IOCTL_MW_READ_DATA," |
200 | " size %lx, ioarg %lx pusBuffer %p\n", | 200 | " size %lx, ioarg %lx pusBuffer %p\n", |
201 | rReadData.ulDataLength, ioarg, pusBuffer); | 201 | rReadData.ulDataLength, ioarg, pusBuffer); |
202 | lock_kernel(); | 202 | mutex_lock(&mwave_mutex); |
203 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, | 203 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, |
204 | iocmd, | 204 | iocmd, |
205 | pusBuffer, | 205 | pusBuffer, |
206 | rReadData.ulDataLength, | 206 | rReadData.ulDataLength, |
207 | rReadData.usDspAddress); | 207 | rReadData.usDspAddress); |
208 | unlock_kernel(); | 208 | mutex_unlock(&mwave_mutex); |
209 | } | 209 | } |
210 | break; | 210 | break; |
211 | 211 | ||
@@ -223,12 +223,12 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd, | |||
223 | " size %lx, ioarg %lx pusBuffer %p\n", | 223 | " size %lx, ioarg %lx pusBuffer %p\n", |
224 | rReadData.ulDataLength / 2, ioarg, | 224 | rReadData.ulDataLength / 2, ioarg, |
225 | pusBuffer); | 225 | pusBuffer); |
226 | lock_kernel(); | 226 | mutex_lock(&mwave_mutex); |
227 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, | 227 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, |
228 | iocmd, pusBuffer, | 228 | iocmd, pusBuffer, |
229 | rReadData.ulDataLength / 2, | 229 | rReadData.ulDataLength / 2, |
230 | rReadData.usDspAddress); | 230 | rReadData.usDspAddress); |
231 | unlock_kernel(); | 231 | mutex_unlock(&mwave_mutex); |
232 | } | 232 | } |
233 | break; | 233 | break; |
234 | 234 | ||
@@ -246,12 +246,12 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd, | |||
246 | " size %lx, ioarg %lx pusBuffer %p\n", | 246 | " size %lx, ioarg %lx pusBuffer %p\n", |
247 | rWriteData.ulDataLength, ioarg, | 247 | rWriteData.ulDataLength, ioarg, |
248 | pusBuffer); | 248 | pusBuffer); |
249 | lock_kernel(); | 249 | mutex_lock(&mwave_mutex); |
250 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, | 250 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, |
251 | iocmd, pusBuffer, | 251 | iocmd, pusBuffer, |
252 | rWriteData.ulDataLength, | 252 | rWriteData.ulDataLength, |
253 | rWriteData.usDspAddress); | 253 | rWriteData.usDspAddress); |
254 | unlock_kernel(); | 254 | mutex_unlock(&mwave_mutex); |
255 | } | 255 | } |
256 | break; | 256 | break; |
257 | 257 | ||
@@ -269,12 +269,12 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd, | |||
269 | " size %lx, ioarg %lx pusBuffer %p\n", | 269 | " size %lx, ioarg %lx pusBuffer %p\n", |
270 | rWriteData.ulDataLength, ioarg, | 270 | rWriteData.ulDataLength, ioarg, |
271 | pusBuffer); | 271 | pusBuffer); |
272 | lock_kernel(); | 272 | mutex_lock(&mwave_mutex); |
273 | retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData, | 273 | retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData, |
274 | iocmd, pusBuffer, | 274 | iocmd, pusBuffer, |
275 | rWriteData.ulDataLength, | 275 | rWriteData.ulDataLength, |
276 | rWriteData.usDspAddress); | 276 | rWriteData.usDspAddress); |
277 | unlock_kernel(); | 277 | mutex_unlock(&mwave_mutex); |
278 | } | 278 | } |
279 | break; | 279 | break; |
280 | 280 | ||
@@ -295,10 +295,10 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd, | |||
295 | ipcnum, | 295 | ipcnum, |
296 | pDrvData->IPCs[ipcnum].usIntCount); | 296 | pDrvData->IPCs[ipcnum].usIntCount); |
297 | 297 | ||
298 | lock_kernel(); | 298 | mutex_lock(&mwave_mutex); |
299 | pDrvData->IPCs[ipcnum].bIsHere = FALSE; | 299 | pDrvData->IPCs[ipcnum].bIsHere = FALSE; |
300 | pDrvData->IPCs[ipcnum].bIsEnabled = TRUE; | 300 | pDrvData->IPCs[ipcnum].bIsEnabled = TRUE; |
301 | unlock_kernel(); | 301 | mutex_unlock(&mwave_mutex); |
302 | 302 | ||
303 | PRINTK_2(TRACE_MWAVE, | 303 | PRINTK_2(TRACE_MWAVE, |
304 | "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC" | 304 | "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC" |
@@ -323,7 +323,7 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd, | |||
323 | ipcnum, | 323 | ipcnum, |
324 | pDrvData->IPCs[ipcnum].usIntCount); | 324 | pDrvData->IPCs[ipcnum].usIntCount); |
325 | 325 | ||
326 | lock_kernel(); | 326 | mutex_lock(&mwave_mutex); |
327 | if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { | 327 | if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { |
328 | DECLARE_WAITQUEUE(wait, current); | 328 | DECLARE_WAITQUEUE(wait, current); |
329 | 329 | ||
@@ -364,7 +364,7 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd, | |||
364 | " processing\n", | 364 | " processing\n", |
365 | ipcnum); | 365 | ipcnum); |
366 | } | 366 | } |
367 | unlock_kernel(); | 367 | mutex_unlock(&mwave_mutex); |
368 | } | 368 | } |
369 | break; | 369 | break; |
370 | 370 | ||
@@ -383,14 +383,14 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd, | |||
383 | ipcnum); | 383 | ipcnum); |
384 | return -EINVAL; | 384 | return -EINVAL; |
385 | } | 385 | } |
386 | lock_kernel(); | 386 | mutex_lock(&mwave_mutex); |
387 | if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { | 387 | if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { |
388 | pDrvData->IPCs[ipcnum].bIsEnabled = FALSE; | 388 | pDrvData->IPCs[ipcnum].bIsEnabled = FALSE; |
389 | if (pDrvData->IPCs[ipcnum].bIsHere == TRUE) { | 389 | if (pDrvData->IPCs[ipcnum].bIsHere == TRUE) { |
390 | wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue); | 390 | wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue); |
391 | } | 391 | } |
392 | } | 392 | } |
393 | unlock_kernel(); | 393 | mutex_unlock(&mwave_mutex); |
394 | } | 394 | } |
395 | break; | 395 | break; |
396 | 396 | ||
@@ -479,7 +479,8 @@ static const struct file_operations mwave_fops = { | |||
479 | .write = mwave_write, | 479 | .write = mwave_write, |
480 | .unlocked_ioctl = mwave_ioctl, | 480 | .unlocked_ioctl = mwave_ioctl, |
481 | .open = mwave_open, | 481 | .open = mwave_open, |
482 | .release = mwave_close | 482 | .release = mwave_close, |
483 | .llseek = default_llseek, | ||
483 | }; | 484 | }; |
484 | 485 | ||
485 | 486 | ||
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 3d923065d9a2..dd9d75351cd6 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -33,12 +33,12 @@ | |||
33 | #include <linux/string.h> | 33 | #include <linux/string.h> |
34 | #include <linux/fcntl.h> | 34 | #include <linux/fcntl.h> |
35 | #include <linux/ptrace.h> | 35 | #include <linux/ptrace.h> |
36 | #include <linux/gfp.h> | ||
37 | #include <linux/ioport.h> | 36 | #include <linux/ioport.h> |
38 | #include <linux/mm.h> | 37 | #include <linux/mm.h> |
39 | #include <linux/delay.h> | 38 | #include <linux/delay.h> |
40 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
41 | #include <linux/bitops.h> | 40 | #include <linux/bitops.h> |
41 | #include <linux/slab.h> | ||
42 | 42 | ||
43 | #include <asm/system.h> | 43 | #include <asm/system.h> |
44 | #include <asm/io.h> | 44 | #include <asm/io.h> |
@@ -303,6 +303,7 @@ static void mxser_enable_must_enchance_mode(unsigned long baseio) | |||
303 | outb(oldlcr, baseio + UART_LCR); | 303 | outb(oldlcr, baseio + UART_LCR); |
304 | } | 304 | } |
305 | 305 | ||
306 | #ifdef CONFIG_PCI | ||
306 | static void mxser_disable_must_enchance_mode(unsigned long baseio) | 307 | static void mxser_disable_must_enchance_mode(unsigned long baseio) |
307 | { | 308 | { |
308 | u8 oldlcr; | 309 | u8 oldlcr; |
@@ -317,6 +318,7 @@ static void mxser_disable_must_enchance_mode(unsigned long baseio) | |||
317 | outb(efr, baseio + MOXA_MUST_EFR_REGISTER); | 318 | outb(efr, baseio + MOXA_MUST_EFR_REGISTER); |
318 | outb(oldlcr, baseio + UART_LCR); | 319 | outb(oldlcr, baseio + UART_LCR); |
319 | } | 320 | } |
321 | #endif | ||
320 | 322 | ||
321 | static void mxser_set_must_xon1_value(unsigned long baseio, u8 value) | 323 | static void mxser_set_must_xon1_value(unsigned long baseio, u8 value) |
322 | { | 324 | { |
@@ -388,6 +390,7 @@ static void mxser_set_must_enum_value(unsigned long baseio, u8 value) | |||
388 | outb(oldlcr, baseio + UART_LCR); | 390 | outb(oldlcr, baseio + UART_LCR); |
389 | } | 391 | } |
390 | 392 | ||
393 | #ifdef CONFIG_PCI | ||
391 | static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId) | 394 | static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId) |
392 | { | 395 | { |
393 | u8 oldlcr; | 396 | u8 oldlcr; |
@@ -404,6 +407,7 @@ static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId) | |||
404 | *pId = inb(baseio + MOXA_MUST_HWID_REGISTER); | 407 | *pId = inb(baseio + MOXA_MUST_HWID_REGISTER); |
405 | outb(oldlcr, baseio + UART_LCR); | 408 | outb(oldlcr, baseio + UART_LCR); |
406 | } | 409 | } |
410 | #endif | ||
407 | 411 | ||
408 | static void SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(unsigned long baseio) | 412 | static void SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(unsigned long baseio) |
409 | { | 413 | { |
@@ -895,8 +899,7 @@ static int mxser_activate(struct tty_port *port, struct tty_struct *tty) | |||
895 | if (inb(info->ioaddr + UART_LSR) == 0xff) { | 899 | if (inb(info->ioaddr + UART_LSR) == 0xff) { |
896 | spin_unlock_irqrestore(&info->slock, flags); | 900 | spin_unlock_irqrestore(&info->slock, flags); |
897 | if (capable(CAP_SYS_ADMIN)) { | 901 | if (capable(CAP_SYS_ADMIN)) { |
898 | if (tty) | 902 | set_bit(TTY_IO_ERROR, &tty->flags); |
899 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
900 | return 0; | 903 | return 0; |
901 | } else | 904 | } else |
902 | return -ENODEV; | 905 | return -ENODEV; |
@@ -1012,6 +1015,7 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) | |||
1012 | if (!info->ioaddr) | 1015 | if (!info->ioaddr) |
1013 | return -ENODEV; | 1016 | return -ENODEV; |
1014 | 1017 | ||
1018 | tty->driver_data = info; | ||
1015 | return tty_port_open(&info->port, tty, filp); | 1019 | return tty_port_open(&info->port, tty, filp); |
1016 | } | 1020 | } |
1017 | 1021 | ||
@@ -1075,7 +1079,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) | |||
1075 | struct mxser_port *info = tty->driver_data; | 1079 | struct mxser_port *info = tty->driver_data; |
1076 | struct tty_port *port = &info->port; | 1080 | struct tty_port *port = &info->port; |
1077 | 1081 | ||
1078 | if (tty->index == MXSER_PORTS) | 1082 | if (tty->index == MXSER_PORTS || info == NULL) |
1079 | return; | 1083 | return; |
1080 | if (tty_port_close_start(port, tty, filp) == 0) | 1084 | if (tty_port_close_start(port, tty, filp) == 0) |
1081 | return; | 1085 | return; |
@@ -1700,7 +1704,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1700 | return 0; | 1704 | return 0; |
1701 | } | 1705 | } |
1702 | 1706 | ||
1703 | if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT && | 1707 | if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && |
1704 | test_bit(TTY_IO_ERROR, &tty->flags)) | 1708 | test_bit(TTY_IO_ERROR, &tty->flags)) |
1705 | return -EIO; | 1709 | return -EIO; |
1706 | 1710 | ||
@@ -1730,32 +1734,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1730 | 1734 | ||
1731 | return wait_event_interruptible(info->port.delta_msr_wait, | 1735 | return wait_event_interruptible(info->port.delta_msr_wait, |
1732 | mxser_cflags_changed(info, arg, &cnow)); | 1736 | mxser_cflags_changed(info, arg, &cnow)); |
1733 | /* | ||
1734 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) | ||
1735 | * Return: write counters to the user passed counter struct | ||
1736 | * NB: both 1->0 and 0->1 transitions are counted except for | ||
1737 | * RI where only 0->1 is counted. | ||
1738 | */ | ||
1739 | case TIOCGICOUNT: { | ||
1740 | struct serial_icounter_struct icnt = { 0 }; | ||
1741 | spin_lock_irqsave(&info->slock, flags); | ||
1742 | cnow = info->icount; | ||
1743 | spin_unlock_irqrestore(&info->slock, flags); | ||
1744 | |||
1745 | icnt.frame = cnow.frame; | ||
1746 | icnt.brk = cnow.brk; | ||
1747 | icnt.overrun = cnow.overrun; | ||
1748 | icnt.buf_overrun = cnow.buf_overrun; | ||
1749 | icnt.parity = cnow.parity; | ||
1750 | icnt.rx = cnow.rx; | ||
1751 | icnt.tx = cnow.tx; | ||
1752 | icnt.cts = cnow.cts; | ||
1753 | icnt.dsr = cnow.dsr; | ||
1754 | icnt.rng = cnow.rng; | ||
1755 | icnt.dcd = cnow.dcd; | ||
1756 | |||
1757 | return copy_to_user(argp, &icnt, sizeof(icnt)) ? -EFAULT : 0; | ||
1758 | } | ||
1759 | case MOXA_HighSpeedOn: | 1737 | case MOXA_HighSpeedOn: |
1760 | return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); | 1738 | return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); |
1761 | case MOXA_SDS_RSTICOUNTER: | 1739 | case MOXA_SDS_RSTICOUNTER: |
@@ -1769,7 +1747,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1769 | int len, lsr; | 1747 | int len, lsr; |
1770 | 1748 | ||
1771 | len = mxser_chars_in_buffer(tty); | 1749 | len = mxser_chars_in_buffer(tty); |
1772 | spin_lock(&info->slock); | 1750 | spin_lock_irq(&info->slock); |
1773 | lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE; | 1751 | lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE; |
1774 | spin_unlock_irq(&info->slock); | 1752 | spin_unlock_irq(&info->slock); |
1775 | len += (lsr ? 0 : 1); | 1753 | len += (lsr ? 0 : 1); |
@@ -1779,12 +1757,12 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1779 | case MOXA_ASPP_MON: { | 1757 | case MOXA_ASPP_MON: { |
1780 | int mcr, status; | 1758 | int mcr, status; |
1781 | 1759 | ||
1782 | spin_lock(&info->slock); | 1760 | spin_lock_irq(&info->slock); |
1783 | status = mxser_get_msr(info->ioaddr, 1, tty->index); | 1761 | status = mxser_get_msr(info->ioaddr, 1, tty->index); |
1784 | mxser_check_modem_status(tty, info, status); | 1762 | mxser_check_modem_status(tty, info, status); |
1785 | 1763 | ||
1786 | mcr = inb(info->ioaddr + UART_MCR); | 1764 | mcr = inb(info->ioaddr + UART_MCR); |
1787 | spin_unlock(&info->slock); | 1765 | spin_unlock_irq(&info->slock); |
1788 | 1766 | ||
1789 | if (mcr & MOXA_MUST_MCR_XON_FLAG) | 1767 | if (mcr & MOXA_MUST_MCR_XON_FLAG) |
1790 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; | 1768 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; |
@@ -1828,6 +1806,39 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1828 | return 0; | 1806 | return 0; |
1829 | } | 1807 | } |
1830 | 1808 | ||
1809 | /* | ||
1810 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) | ||
1811 | * Return: write counters to the user passed counter struct | ||
1812 | * NB: both 1->0 and 0->1 transitions are counted except for | ||
1813 | * RI where only 0->1 is counted. | ||
1814 | */ | ||
1815 | |||
1816 | static int mxser_get_icount(struct tty_struct *tty, | ||
1817 | struct serial_icounter_struct *icount) | ||
1818 | |||
1819 | { | ||
1820 | struct mxser_port *info = tty->driver_data; | ||
1821 | struct async_icount cnow; | ||
1822 | unsigned long flags; | ||
1823 | |||
1824 | spin_lock_irqsave(&info->slock, flags); | ||
1825 | cnow = info->icount; | ||
1826 | spin_unlock_irqrestore(&info->slock, flags); | ||
1827 | |||
1828 | icount->frame = cnow.frame; | ||
1829 | icount->brk = cnow.brk; | ||
1830 | icount->overrun = cnow.overrun; | ||
1831 | icount->buf_overrun = cnow.buf_overrun; | ||
1832 | icount->parity = cnow.parity; | ||
1833 | icount->rx = cnow.rx; | ||
1834 | icount->tx = cnow.tx; | ||
1835 | icount->cts = cnow.cts; | ||
1836 | icount->dsr = cnow.dsr; | ||
1837 | icount->rng = cnow.rng; | ||
1838 | icount->dcd = cnow.dcd; | ||
1839 | return 0; | ||
1840 | } | ||
1841 | |||
1831 | static void mxser_stoprx(struct tty_struct *tty) | 1842 | static void mxser_stoprx(struct tty_struct *tty) |
1832 | { | 1843 | { |
1833 | struct mxser_port *info = tty->driver_data; | 1844 | struct mxser_port *info = tty->driver_data; |
@@ -2193,7 +2204,7 @@ static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port | |||
2193 | port->mon_data.up_txcnt += (cnt - port->xmit_cnt); | 2204 | port->mon_data.up_txcnt += (cnt - port->xmit_cnt); |
2194 | port->icount.tx += (cnt - port->xmit_cnt); | 2205 | port->icount.tx += (cnt - port->xmit_cnt); |
2195 | 2206 | ||
2196 | if (port->xmit_cnt < WAKEUP_CHARS && tty) | 2207 | if (port->xmit_cnt < WAKEUP_CHARS) |
2197 | tty_wakeup(tty); | 2208 | tty_wakeup(tty); |
2198 | 2209 | ||
2199 | if (port->xmit_cnt <= 0) { | 2210 | if (port->xmit_cnt <= 0) { |
@@ -2326,6 +2337,7 @@ static const struct tty_operations mxser_ops = { | |||
2326 | .wait_until_sent = mxser_wait_until_sent, | 2337 | .wait_until_sent = mxser_wait_until_sent, |
2327 | .tiocmget = mxser_tiocmget, | 2338 | .tiocmget = mxser_tiocmget, |
2328 | .tiocmset = mxser_tiocmset, | 2339 | .tiocmset = mxser_tiocmset, |
2340 | .get_icount = mxser_get_icount, | ||
2329 | }; | 2341 | }; |
2330 | 2342 | ||
2331 | struct tty_port_operations mxser_port_ops = { | 2343 | struct tty_port_operations mxser_port_ops = { |
@@ -2339,20 +2351,11 @@ struct tty_port_operations mxser_port_ops = { | |||
2339 | * The MOXA Smartio/Industio serial driver boot-time initialization code! | 2351 | * The MOXA Smartio/Industio serial driver boot-time initialization code! |
2340 | */ | 2352 | */ |
2341 | 2353 | ||
2342 | static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev, | 2354 | static void mxser_release_ISA_res(struct mxser_board *brd) |
2343 | unsigned int irq) | ||
2344 | { | 2355 | { |
2345 | if (irq) | 2356 | free_irq(brd->irq, brd); |
2346 | free_irq(brd->irq, brd); | 2357 | release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); |
2347 | if (pdev != NULL) { /* PCI */ | 2358 | release_region(brd->vector, 1); |
2348 | #ifdef CONFIG_PCI | ||
2349 | pci_release_region(pdev, 2); | ||
2350 | pci_release_region(pdev, 3); | ||
2351 | #endif | ||
2352 | } else { | ||
2353 | release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); | ||
2354 | release_region(brd->vector, 1); | ||
2355 | } | ||
2356 | } | 2359 | } |
2357 | 2360 | ||
2358 | static int __devinit mxser_initbrd(struct mxser_board *brd, | 2361 | static int __devinit mxser_initbrd(struct mxser_board *brd, |
@@ -2397,13 +2400,11 @@ static int __devinit mxser_initbrd(struct mxser_board *brd, | |||
2397 | 2400 | ||
2398 | retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser", | 2401 | retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser", |
2399 | brd); | 2402 | brd); |
2400 | if (retval) { | 2403 | if (retval) |
2401 | printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may " | 2404 | printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may " |
2402 | "conflict with another device.\n", | 2405 | "conflict with another device.\n", |
2403 | brd->info->name, brd->irq); | 2406 | brd->info->name, brd->irq); |
2404 | /* We hold resources, we need to release them. */ | 2407 | |
2405 | mxser_release_res(brd, pdev, 0); | ||
2406 | } | ||
2407 | return retval; | 2408 | return retval; |
2408 | } | 2409 | } |
2409 | 2410 | ||
@@ -2555,7 +2556,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev, | |||
2555 | ioaddress = pci_resource_start(pdev, 2); | 2556 | ioaddress = pci_resource_start(pdev, 2); |
2556 | retval = pci_request_region(pdev, 2, "mxser(IO)"); | 2557 | retval = pci_request_region(pdev, 2, "mxser(IO)"); |
2557 | if (retval) | 2558 | if (retval) |
2558 | goto err; | 2559 | goto err_dis; |
2559 | 2560 | ||
2560 | brd->info = &mxser_cards[ent->driver_data]; | 2561 | brd->info = &mxser_cards[ent->driver_data]; |
2561 | for (i = 0; i < brd->info->nports; i++) | 2562 | for (i = 0; i < brd->info->nports; i++) |
@@ -2565,7 +2566,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev, | |||
2565 | ioaddress = pci_resource_start(pdev, 3); | 2566 | ioaddress = pci_resource_start(pdev, 3); |
2566 | retval = pci_request_region(pdev, 3, "mxser(vector)"); | 2567 | retval = pci_request_region(pdev, 3, "mxser(vector)"); |
2567 | if (retval) | 2568 | if (retval) |
2568 | goto err_relio; | 2569 | goto err_zero; |
2569 | brd->vector = ioaddress; | 2570 | brd->vector = ioaddress; |
2570 | 2571 | ||
2571 | /* irq */ | 2572 | /* irq */ |
@@ -2608,7 +2609,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev, | |||
2608 | /* mxser_initbrd will hook ISR. */ | 2609 | /* mxser_initbrd will hook ISR. */ |
2609 | retval = mxser_initbrd(brd, pdev); | 2610 | retval = mxser_initbrd(brd, pdev); |
2610 | if (retval) | 2611 | if (retval) |
2611 | goto err_null; | 2612 | goto err_rel3; |
2612 | 2613 | ||
2613 | for (i = 0; i < brd->info->nports; i++) | 2614 | for (i = 0; i < brd->info->nports; i++) |
2614 | tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev); | 2615 | tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev); |
@@ -2616,10 +2617,13 @@ static int __devinit mxser_probe(struct pci_dev *pdev, | |||
2616 | pci_set_drvdata(pdev, brd); | 2617 | pci_set_drvdata(pdev, brd); |
2617 | 2618 | ||
2618 | return 0; | 2619 | return 0; |
2619 | err_relio: | 2620 | err_rel3: |
2620 | pci_release_region(pdev, 2); | 2621 | pci_release_region(pdev, 3); |
2621 | err_null: | 2622 | err_zero: |
2622 | brd->info = NULL; | 2623 | brd->info = NULL; |
2624 | pci_release_region(pdev, 2); | ||
2625 | err_dis: | ||
2626 | pci_disable_device(pdev); | ||
2623 | err: | 2627 | err: |
2624 | return retval; | 2628 | return retval; |
2625 | #else | 2629 | #else |
@@ -2629,14 +2633,19 @@ err: | |||
2629 | 2633 | ||
2630 | static void __devexit mxser_remove(struct pci_dev *pdev) | 2634 | static void __devexit mxser_remove(struct pci_dev *pdev) |
2631 | { | 2635 | { |
2636 | #ifdef CONFIG_PCI | ||
2632 | struct mxser_board *brd = pci_get_drvdata(pdev); | 2637 | struct mxser_board *brd = pci_get_drvdata(pdev); |
2633 | unsigned int i; | 2638 | unsigned int i; |
2634 | 2639 | ||
2635 | for (i = 0; i < brd->info->nports; i++) | 2640 | for (i = 0; i < brd->info->nports; i++) |
2636 | tty_unregister_device(mxvar_sdriver, brd->idx + i); | 2641 | tty_unregister_device(mxvar_sdriver, brd->idx + i); |
2637 | 2642 | ||
2638 | mxser_release_res(brd, pdev, 1); | 2643 | free_irq(pdev->irq, brd); |
2644 | pci_release_region(pdev, 2); | ||
2645 | pci_release_region(pdev, 3); | ||
2646 | pci_disable_device(pdev); | ||
2639 | brd->info = NULL; | 2647 | brd->info = NULL; |
2648 | #endif | ||
2640 | } | 2649 | } |
2641 | 2650 | ||
2642 | static struct pci_driver mxser_driver = { | 2651 | static struct pci_driver mxser_driver = { |
@@ -2741,7 +2750,7 @@ static void __exit mxser_module_exit(void) | |||
2741 | 2750 | ||
2742 | for (i = 0; i < MXSER_BOARDS; i++) | 2751 | for (i = 0; i < MXSER_BOARDS; i++) |
2743 | if (mxser_boards[i].info != NULL) | 2752 | if (mxser_boards[i].info != NULL) |
2744 | mxser_release_res(&mxser_boards[i], NULL, 1); | 2753 | mxser_release_ISA_res(&mxser_boards[i]); |
2745 | } | 2754 | } |
2746 | 2755 | ||
2747 | module_init(mxser_module_init); | 2756 | module_init(mxser_module_init); |
diff --git a/drivers/char/n_gsm.c b/drivers/char/n_gsm.c new file mode 100644 index 000000000000..04ef3ef0a422 --- /dev/null +++ b/drivers/char/n_gsm.c | |||
@@ -0,0 +1,2763 @@ | |||
1 | /* | ||
2 | * n_gsm.c GSM 0710 tty multiplexor | ||
3 | * Copyright (c) 2009/10 Intel Corporation | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | * | ||
18 | * * THIS IS A DEVELOPMENT SNAPSHOT IT IS NOT A FINAL RELEASE * | ||
19 | * | ||
20 | * TO DO: | ||
21 | * Mostly done: ioctls for setting modes/timing | ||
22 | * Partly done: hooks so you can pull off frames to non tty devs | ||
23 | * Restart DLCI 0 when it closes ? | ||
24 | * Test basic encoding | ||
25 | * Improve the tx engine | ||
26 | * Resolve tx side locking by adding a queue_head and routing | ||
27 | * all control traffic via it | ||
28 | * General tidy/document | ||
29 | * Review the locking/move to refcounts more (mux now moved to an | ||
30 | * alloc/free model ready) | ||
31 | * Use newest tty open/close port helpers and install hooks | ||
32 | * What to do about power functions ? | ||
33 | * Termios setting and negotiation | ||
34 | * Do we need a 'which mux are you' ioctl to correlate mux and tty sets | ||
35 | * | ||
36 | */ | ||
37 | |||
38 | #include <linux/types.h> | ||
39 | #include <linux/major.h> | ||
40 | #include <linux/errno.h> | ||
41 | #include <linux/signal.h> | ||
42 | #include <linux/fcntl.h> | ||
43 | #include <linux/sched.h> | ||
44 | #include <linux/interrupt.h> | ||
45 | #include <linux/tty.h> | ||
46 | #include <linux/ctype.h> | ||
47 | #include <linux/mm.h> | ||
48 | #include <linux/string.h> | ||
49 | #include <linux/slab.h> | ||
50 | #include <linux/poll.h> | ||
51 | #include <linux/bitops.h> | ||
52 | #include <linux/file.h> | ||
53 | #include <linux/uaccess.h> | ||
54 | #include <linux/module.h> | ||
55 | #include <linux/timer.h> | ||
56 | #include <linux/tty_flip.h> | ||
57 | #include <linux/tty_driver.h> | ||
58 | #include <linux/serial.h> | ||
59 | #include <linux/kfifo.h> | ||
60 | #include <linux/skbuff.h> | ||
61 | #include <linux/gsmmux.h> | ||
62 | |||
63 | static int debug; | ||
64 | module_param(debug, int, 0600); | ||
65 | |||
66 | #define T1 (HZ/10) | ||
67 | #define T2 (HZ/3) | ||
68 | #define N2 3 | ||
69 | |||
70 | /* Use long timers for testing at low speed with debug on */ | ||
71 | #ifdef DEBUG_TIMING | ||
72 | #define T1 HZ | ||
73 | #define T2 (2 * HZ) | ||
74 | #endif | ||
75 | |||
76 | /* Semi-arbitary buffer size limits. 0710 is normally run with 32-64 byte | ||
77 | limits so this is plenty */ | ||
78 | #define MAX_MRU 512 | ||
79 | #define MAX_MTU 512 | ||
80 | |||
81 | /* | ||
82 | * Each block of data we have queued to go out is in the form of | ||
83 | * a gsm_msg which holds everything we need in a link layer independant | ||
84 | * format | ||
85 | */ | ||
86 | |||
87 | struct gsm_msg { | ||
88 | struct gsm_msg *next; | ||
89 | u8 addr; /* DLCI address + flags */ | ||
90 | u8 ctrl; /* Control byte + flags */ | ||
91 | unsigned int len; /* Length of data block (can be zero) */ | ||
92 | unsigned char *data; /* Points into buffer but not at the start */ | ||
93 | unsigned char buffer[0]; | ||
94 | }; | ||
95 | |||
96 | /* | ||
97 | * Each active data link has a gsm_dlci structure associated which ties | ||
98 | * the link layer to an optional tty (if the tty side is open). To avoid | ||
99 | * complexity right now these are only ever freed up when the mux is | ||
100 | * shut down. | ||
101 | * | ||
102 | * At the moment we don't free DLCI objects until the mux is torn down | ||
103 | * this avoid object life time issues but might be worth review later. | ||
104 | */ | ||
105 | |||
106 | struct gsm_dlci { | ||
107 | struct gsm_mux *gsm; | ||
108 | int addr; | ||
109 | int state; | ||
110 | #define DLCI_CLOSED 0 | ||
111 | #define DLCI_OPENING 1 /* Sending SABM not seen UA */ | ||
112 | #define DLCI_OPEN 2 /* SABM/UA complete */ | ||
113 | #define DLCI_CLOSING 3 /* Sending DISC not seen UA/DM */ | ||
114 | |||
115 | /* Link layer */ | ||
116 | spinlock_t lock; /* Protects the internal state */ | ||
117 | struct timer_list t1; /* Retransmit timer for SABM and UA */ | ||
118 | int retries; | ||
119 | /* Uplink tty if active */ | ||
120 | struct tty_port port; /* The tty bound to this DLCI if there is one */ | ||
121 | struct kfifo *fifo; /* Queue fifo for the DLCI */ | ||
122 | struct kfifo _fifo; /* For new fifo API porting only */ | ||
123 | int adaption; /* Adaption layer in use */ | ||
124 | u32 modem_rx; /* Our incoming virtual modem lines */ | ||
125 | u32 modem_tx; /* Our outgoing modem lines */ | ||
126 | int dead; /* Refuse re-open */ | ||
127 | /* Flow control */ | ||
128 | int throttled; /* Private copy of throttle state */ | ||
129 | int constipated; /* Throttle status for outgoing */ | ||
130 | /* Packetised I/O */ | ||
131 | struct sk_buff *skb; /* Frame being sent */ | ||
132 | struct sk_buff_head skb_list; /* Queued frames */ | ||
133 | /* Data handling callback */ | ||
134 | void (*data)(struct gsm_dlci *dlci, u8 *data, int len); | ||
135 | }; | ||
136 | |||
137 | /* DLCI 0, 62/63 are special or reseved see gsmtty_open */ | ||
138 | |||
139 | #define NUM_DLCI 64 | ||
140 | |||
141 | /* | ||
142 | * DLCI 0 is used to pass control blocks out of band of the data | ||
143 | * flow (and with a higher link priority). One command can be outstanding | ||
144 | * at a time and we use this structure to manage them. They are created | ||
145 | * and destroyed by the user context, and updated by the receive paths | ||
146 | * and timers | ||
147 | */ | ||
148 | |||
149 | struct gsm_control { | ||
150 | u8 cmd; /* Command we are issuing */ | ||
151 | u8 *data; /* Data for the command in case we retransmit */ | ||
152 | int len; /* Length of block for retransmission */ | ||
153 | int done; /* Done flag */ | ||
154 | int error; /* Error if any */ | ||
155 | }; | ||
156 | |||
157 | /* | ||
158 | * Each GSM mux we have is represented by this structure. If we are | ||
159 | * operating as an ldisc then we use this structure as our ldisc | ||
160 | * state. We need to sort out lifetimes and locking with respect | ||
161 | * to the gsm mux array. For now we don't free DLCI objects that | ||
162 | * have been instantiated until the mux itself is terminated. | ||
163 | * | ||
164 | * To consider further: tty open versus mux shutdown. | ||
165 | */ | ||
166 | |||
167 | struct gsm_mux { | ||
168 | struct tty_struct *tty; /* The tty our ldisc is bound to */ | ||
169 | spinlock_t lock; | ||
170 | |||
171 | /* Events on the GSM channel */ | ||
172 | wait_queue_head_t event; | ||
173 | |||
174 | /* Bits for GSM mode decoding */ | ||
175 | |||
176 | /* Framing Layer */ | ||
177 | unsigned char *buf; | ||
178 | int state; | ||
179 | #define GSM_SEARCH 0 | ||
180 | #define GSM_START 1 | ||
181 | #define GSM_ADDRESS 2 | ||
182 | #define GSM_CONTROL 3 | ||
183 | #define GSM_LEN 4 | ||
184 | #define GSM_DATA 5 | ||
185 | #define GSM_FCS 6 | ||
186 | #define GSM_OVERRUN 7 | ||
187 | unsigned int len; | ||
188 | unsigned int address; | ||
189 | unsigned int count; | ||
190 | int escape; | ||
191 | int encoding; | ||
192 | u8 control; | ||
193 | u8 fcs; | ||
194 | u8 *txframe; /* TX framing buffer */ | ||
195 | |||
196 | /* Methods for the receiver side */ | ||
197 | void (*receive)(struct gsm_mux *gsm, u8 ch); | ||
198 | void (*error)(struct gsm_mux *gsm, u8 ch, u8 flag); | ||
199 | /* And transmit side */ | ||
200 | int (*output)(struct gsm_mux *mux, u8 *data, int len); | ||
201 | |||
202 | /* Link Layer */ | ||
203 | unsigned int mru; | ||
204 | unsigned int mtu; | ||
205 | int initiator; /* Did we initiate connection */ | ||
206 | int dead; /* Has the mux been shut down */ | ||
207 | struct gsm_dlci *dlci[NUM_DLCI]; | ||
208 | int constipated; /* Asked by remote to shut up */ | ||
209 | |||
210 | spinlock_t tx_lock; | ||
211 | unsigned int tx_bytes; /* TX data outstanding */ | ||
212 | #define TX_THRESH_HI 8192 | ||
213 | #define TX_THRESH_LO 2048 | ||
214 | struct gsm_msg *tx_head; /* Pending data packets */ | ||
215 | struct gsm_msg *tx_tail; | ||
216 | |||
217 | /* Control messages */ | ||
218 | struct timer_list t2_timer; /* Retransmit timer for commands */ | ||
219 | int cretries; /* Command retry counter */ | ||
220 | struct gsm_control *pending_cmd;/* Our current pending command */ | ||
221 | spinlock_t control_lock; /* Protects the pending command */ | ||
222 | |||
223 | /* Configuration */ | ||
224 | int adaption; /* 1 or 2 supported */ | ||
225 | u8 ftype; /* UI or UIH */ | ||
226 | int t1, t2; /* Timers in 1/100th of a sec */ | ||
227 | int n2; /* Retry count */ | ||
228 | |||
229 | /* Statistics (not currently exposed) */ | ||
230 | unsigned long bad_fcs; | ||
231 | unsigned long malformed; | ||
232 | unsigned long io_error; | ||
233 | unsigned long bad_size; | ||
234 | unsigned long unsupported; | ||
235 | }; | ||
236 | |||
237 | |||
238 | /* | ||
239 | * Mux objects - needed so that we can translate a tty index into the | ||
240 | * relevant mux and DLCI. | ||
241 | */ | ||
242 | |||
243 | #define MAX_MUX 4 /* 256 minors */ | ||
244 | static struct gsm_mux *gsm_mux[MAX_MUX]; /* GSM muxes */ | ||
245 | static spinlock_t gsm_mux_lock; | ||
246 | |||
247 | /* | ||
248 | * This section of the driver logic implements the GSM encodings | ||
249 | * both the basic and the 'advanced'. Reliable transport is not | ||
250 | * supported. | ||
251 | */ | ||
252 | |||
253 | #define CR 0x02 | ||
254 | #define EA 0x01 | ||
255 | #define PF 0x10 | ||
256 | |||
257 | /* I is special: the rest are ..*/ | ||
258 | #define RR 0x01 | ||
259 | #define UI 0x03 | ||
260 | #define RNR 0x05 | ||
261 | #define REJ 0x09 | ||
262 | #define DM 0x0F | ||
263 | #define SABM 0x2F | ||
264 | #define DISC 0x43 | ||
265 | #define UA 0x63 | ||
266 | #define UIH 0xEF | ||
267 | |||
268 | /* Channel commands */ | ||
269 | #define CMD_NSC 0x09 | ||
270 | #define CMD_TEST 0x11 | ||
271 | #define CMD_PSC 0x21 | ||
272 | #define CMD_RLS 0x29 | ||
273 | #define CMD_FCOFF 0x31 | ||
274 | #define CMD_PN 0x41 | ||
275 | #define CMD_RPN 0x49 | ||
276 | #define CMD_FCON 0x51 | ||
277 | #define CMD_CLD 0x61 | ||
278 | #define CMD_SNC 0x69 | ||
279 | #define CMD_MSC 0x71 | ||
280 | |||
281 | /* Virtual modem bits */ | ||
282 | #define MDM_FC 0x01 | ||
283 | #define MDM_RTC 0x02 | ||
284 | #define MDM_RTR 0x04 | ||
285 | #define MDM_IC 0x20 | ||
286 | #define MDM_DV 0x40 | ||
287 | |||
288 | #define GSM0_SOF 0xF9 | ||
289 | #define GSM1_SOF 0x7E | ||
290 | #define GSM1_ESCAPE 0x7D | ||
291 | #define GSM1_ESCAPE_BITS 0x20 | ||
292 | #define XON 0x11 | ||
293 | #define XOFF 0x13 | ||
294 | |||
295 | static const struct tty_port_operations gsm_port_ops; | ||
296 | |||
297 | /* | ||
298 | * CRC table for GSM 0710 | ||
299 | */ | ||
300 | |||
301 | static const u8 gsm_fcs8[256] = { | ||
302 | 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, | ||
303 | 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B, | ||
304 | 0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, | ||
305 | 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67, | ||
306 | 0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, | ||
307 | 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43, | ||
308 | 0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, | ||
309 | 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F, | ||
310 | 0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, | ||
311 | 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B, | ||
312 | 0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, | ||
313 | 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17, | ||
314 | 0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, | ||
315 | 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33, | ||
316 | 0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, | ||
317 | 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F, | ||
318 | 0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, | ||
319 | 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B, | ||
320 | 0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, | ||
321 | 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87, | ||
322 | 0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, | ||
323 | 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3, | ||
324 | 0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, | ||
325 | 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF, | ||
326 | 0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, | ||
327 | 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB, | ||
328 | 0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, | ||
329 | 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7, | ||
330 | 0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, | ||
331 | 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3, | ||
332 | 0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, | ||
333 | 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF | ||
334 | }; | ||
335 | |||
336 | #define INIT_FCS 0xFF | ||
337 | #define GOOD_FCS 0xCF | ||
338 | |||
339 | /** | ||
340 | * gsm_fcs_add - update FCS | ||
341 | * @fcs: Current FCS | ||
342 | * @c: Next data | ||
343 | * | ||
344 | * Update the FCS to include c. Uses the algorithm in the specification | ||
345 | * notes. | ||
346 | */ | ||
347 | |||
348 | static inline u8 gsm_fcs_add(u8 fcs, u8 c) | ||
349 | { | ||
350 | return gsm_fcs8[fcs ^ c]; | ||
351 | } | ||
352 | |||
353 | /** | ||
354 | * gsm_fcs_add_block - update FCS for a block | ||
355 | * @fcs: Current FCS | ||
356 | * @c: buffer of data | ||
357 | * @len: length of buffer | ||
358 | * | ||
359 | * Update the FCS to include c. Uses the algorithm in the specification | ||
360 | * notes. | ||
361 | */ | ||
362 | |||
363 | static inline u8 gsm_fcs_add_block(u8 fcs, u8 *c, int len) | ||
364 | { | ||
365 | while (len--) | ||
366 | fcs = gsm_fcs8[fcs ^ *c++]; | ||
367 | return fcs; | ||
368 | } | ||
369 | |||
370 | /** | ||
371 | * gsm_read_ea - read a byte into an EA | ||
372 | * @val: variable holding value | ||
373 | * c: byte going into the EA | ||
374 | * | ||
375 | * Processes one byte of an EA. Updates the passed variable | ||
376 | * and returns 1 if the EA is now completely read | ||
377 | */ | ||
378 | |||
379 | static int gsm_read_ea(unsigned int *val, u8 c) | ||
380 | { | ||
381 | /* Add the next 7 bits into the value */ | ||
382 | *val <<= 7; | ||
383 | *val |= c >> 1; | ||
384 | /* Was this the last byte of the EA 1 = yes*/ | ||
385 | return c & EA; | ||
386 | } | ||
387 | |||
388 | /** | ||
389 | * gsm_encode_modem - encode modem data bits | ||
390 | * @dlci: DLCI to encode from | ||
391 | * | ||
392 | * Returns the correct GSM encoded modem status bits (6 bit field) for | ||
393 | * the current status of the DLCI and attached tty object | ||
394 | */ | ||
395 | |||
396 | static u8 gsm_encode_modem(const struct gsm_dlci *dlci) | ||
397 | { | ||
398 | u8 modembits = 0; | ||
399 | /* FC is true flow control not modem bits */ | ||
400 | if (dlci->throttled) | ||
401 | modembits |= MDM_FC; | ||
402 | if (dlci->modem_tx & TIOCM_DTR) | ||
403 | modembits |= MDM_RTC; | ||
404 | if (dlci->modem_tx & TIOCM_RTS) | ||
405 | modembits |= MDM_RTR; | ||
406 | if (dlci->modem_tx & TIOCM_RI) | ||
407 | modembits |= MDM_IC; | ||
408 | if (dlci->modem_tx & TIOCM_CD) | ||
409 | modembits |= MDM_DV; | ||
410 | return modembits; | ||
411 | } | ||
412 | |||
413 | /** | ||
414 | * gsm_print_packet - display a frame for debug | ||
415 | * @hdr: header to print before decode | ||
416 | * @addr: address EA from the frame | ||
417 | * @cr: C/R bit from the frame | ||
418 | * @control: control including PF bit | ||
419 | * @data: following data bytes | ||
420 | * @dlen: length of data | ||
421 | * | ||
422 | * Displays a packet in human readable format for debugging purposes. The | ||
423 | * style is based on amateur radio LAP-B dump display. | ||
424 | */ | ||
425 | |||
426 | static void gsm_print_packet(const char *hdr, int addr, int cr, | ||
427 | u8 control, const u8 *data, int dlen) | ||
428 | { | ||
429 | if (!(debug & 1)) | ||
430 | return; | ||
431 | |||
432 | printk(KERN_INFO "%s %d) %c: ", hdr, addr, "RC"[cr]); | ||
433 | |||
434 | switch (control & ~PF) { | ||
435 | case SABM: | ||
436 | printk(KERN_CONT "SABM"); | ||
437 | break; | ||
438 | case UA: | ||
439 | printk(KERN_CONT "UA"); | ||
440 | break; | ||
441 | case DISC: | ||
442 | printk(KERN_CONT "DISC"); | ||
443 | break; | ||
444 | case DM: | ||
445 | printk(KERN_CONT "DM"); | ||
446 | break; | ||
447 | case UI: | ||
448 | printk(KERN_CONT "UI"); | ||
449 | break; | ||
450 | case UIH: | ||
451 | printk(KERN_CONT "UIH"); | ||
452 | break; | ||
453 | default: | ||
454 | if (!(control & 0x01)) { | ||
455 | printk(KERN_CONT "I N(S)%d N(R)%d", | ||
456 | (control & 0x0E) >> 1, (control & 0xE)>> 5); | ||
457 | } else switch (control & 0x0F) { | ||
458 | case RR: | ||
459 | printk("RR(%d)", (control & 0xE0) >> 5); | ||
460 | break; | ||
461 | case RNR: | ||
462 | printk("RNR(%d)", (control & 0xE0) >> 5); | ||
463 | break; | ||
464 | case REJ: | ||
465 | printk("REJ(%d)", (control & 0xE0) >> 5); | ||
466 | break; | ||
467 | default: | ||
468 | printk(KERN_CONT "[%02X]", control); | ||
469 | } | ||
470 | } | ||
471 | |||
472 | if (control & PF) | ||
473 | printk(KERN_CONT "(P)"); | ||
474 | else | ||
475 | printk(KERN_CONT "(F)"); | ||
476 | |||
477 | if (dlen) { | ||
478 | int ct = 0; | ||
479 | while (dlen--) { | ||
480 | if (ct % 8 == 0) | ||
481 | printk(KERN_CONT "\n "); | ||
482 | printk(KERN_CONT "%02X ", *data++); | ||
483 | ct++; | ||
484 | } | ||
485 | } | ||
486 | printk(KERN_CONT "\n"); | ||
487 | } | ||
488 | |||
489 | |||
490 | /* | ||
491 | * Link level transmission side | ||
492 | */ | ||
493 | |||
494 | /** | ||
495 | * gsm_stuff_packet - bytestuff a packet | ||
496 | * @ibuf: input | ||
497 | * @obuf: output | ||
498 | * @len: length of input | ||
499 | * | ||
500 | * Expand a buffer by bytestuffing it. The worst case size change | ||
501 | * is doubling and the caller is responsible for handing out | ||
502 | * suitable sized buffers. | ||
503 | */ | ||
504 | |||
505 | static int gsm_stuff_frame(const u8 *input, u8 *output, int len) | ||
506 | { | ||
507 | int olen = 0; | ||
508 | while (len--) { | ||
509 | if (*input == GSM1_SOF || *input == GSM1_ESCAPE | ||
510 | || *input == XON || *input == XOFF) { | ||
511 | *output++ = GSM1_ESCAPE; | ||
512 | *output++ = *input++ ^ GSM1_ESCAPE_BITS; | ||
513 | olen++; | ||
514 | } else | ||
515 | *output++ = *input++; | ||
516 | olen++; | ||
517 | } | ||
518 | return olen; | ||
519 | } | ||
520 | |||
521 | static void hex_packet(const unsigned char *p, int len) | ||
522 | { | ||
523 | int i; | ||
524 | for (i = 0; i < len; i++) { | ||
525 | if (i && (i % 16) == 0) | ||
526 | printk("\n"); | ||
527 | printk("%02X ", *p++); | ||
528 | } | ||
529 | printk("\n"); | ||
530 | } | ||
531 | |||
532 | /** | ||
533 | * gsm_send - send a control frame | ||
534 | * @gsm: our GSM mux | ||
535 | * @addr: address for control frame | ||
536 | * @cr: command/response bit | ||
537 | * @control: control byte including PF bit | ||
538 | * | ||
539 | * Format up and transmit a control frame. These do not go via the | ||
540 | * queueing logic as they should be transmitted ahead of data when | ||
541 | * they are needed. | ||
542 | * | ||
543 | * FIXME: Lock versus data TX path | ||
544 | */ | ||
545 | |||
546 | static void gsm_send(struct gsm_mux *gsm, int addr, int cr, int control) | ||
547 | { | ||
548 | int len; | ||
549 | u8 cbuf[10]; | ||
550 | u8 ibuf[3]; | ||
551 | |||
552 | switch (gsm->encoding) { | ||
553 | case 0: | ||
554 | cbuf[0] = GSM0_SOF; | ||
555 | cbuf[1] = (addr << 2) | (cr << 1) | EA; | ||
556 | cbuf[2] = control; | ||
557 | cbuf[3] = EA; /* Length of data = 0 */ | ||
558 | cbuf[4] = 0xFF - gsm_fcs_add_block(INIT_FCS, cbuf + 1, 3); | ||
559 | cbuf[5] = GSM0_SOF; | ||
560 | len = 6; | ||
561 | break; | ||
562 | case 1: | ||
563 | case 2: | ||
564 | /* Control frame + packing (but not frame stuffing) in mode 1 */ | ||
565 | ibuf[0] = (addr << 2) | (cr << 1) | EA; | ||
566 | ibuf[1] = control; | ||
567 | ibuf[2] = 0xFF - gsm_fcs_add_block(INIT_FCS, ibuf, 2); | ||
568 | /* Stuffing may double the size worst case */ | ||
569 | len = gsm_stuff_frame(ibuf, cbuf + 1, 3); | ||
570 | /* Now add the SOF markers */ | ||
571 | cbuf[0] = GSM1_SOF; | ||
572 | cbuf[len + 1] = GSM1_SOF; | ||
573 | /* FIXME: we can omit the lead one in many cases */ | ||
574 | len += 2; | ||
575 | break; | ||
576 | default: | ||
577 | WARN_ON(1); | ||
578 | return; | ||
579 | } | ||
580 | gsm->output(gsm, cbuf, len); | ||
581 | gsm_print_packet("-->", addr, cr, control, NULL, 0); | ||
582 | } | ||
583 | |||
584 | /** | ||
585 | * gsm_response - send a control response | ||
586 | * @gsm: our GSM mux | ||
587 | * @addr: address for control frame | ||
588 | * @control: control byte including PF bit | ||
589 | * | ||
590 | * Format up and transmit a link level response frame. | ||
591 | */ | ||
592 | |||
593 | static inline void gsm_response(struct gsm_mux *gsm, int addr, int control) | ||
594 | { | ||
595 | gsm_send(gsm, addr, 0, control); | ||
596 | } | ||
597 | |||
598 | /** | ||
599 | * gsm_command - send a control command | ||
600 | * @gsm: our GSM mux | ||
601 | * @addr: address for control frame | ||
602 | * @control: control byte including PF bit | ||
603 | * | ||
604 | * Format up and transmit a link level command frame. | ||
605 | */ | ||
606 | |||
607 | static inline void gsm_command(struct gsm_mux *gsm, int addr, int control) | ||
608 | { | ||
609 | gsm_send(gsm, addr, 1, control); | ||
610 | } | ||
611 | |||
612 | /* Data transmission */ | ||
613 | |||
614 | #define HDR_LEN 6 /* ADDR CTRL [LEN.2] DATA FCS */ | ||
615 | |||
616 | /** | ||
617 | * gsm_data_alloc - allocate data frame | ||
618 | * @gsm: GSM mux | ||
619 | * @addr: DLCI address | ||
620 | * @len: length excluding header and FCS | ||
621 | * @ctrl: control byte | ||
622 | * | ||
623 | * Allocate a new data buffer for sending frames with data. Space is left | ||
624 | * at the front for header bytes but that is treated as an implementation | ||
625 | * detail and not for the high level code to use | ||
626 | */ | ||
627 | |||
628 | static struct gsm_msg *gsm_data_alloc(struct gsm_mux *gsm, u8 addr, int len, | ||
629 | u8 ctrl) | ||
630 | { | ||
631 | struct gsm_msg *m = kmalloc(sizeof(struct gsm_msg) + len + HDR_LEN, | ||
632 | GFP_ATOMIC); | ||
633 | if (m == NULL) | ||
634 | return NULL; | ||
635 | m->data = m->buffer + HDR_LEN - 1; /* Allow for FCS */ | ||
636 | m->len = len; | ||
637 | m->addr = addr; | ||
638 | m->ctrl = ctrl; | ||
639 | m->next = NULL; | ||
640 | return m; | ||
641 | } | ||
642 | |||
643 | /** | ||
644 | * gsm_data_kick - poke the queue | ||
645 | * @gsm: GSM Mux | ||
646 | * | ||
647 | * The tty device has called us to indicate that room has appeared in | ||
648 | * the transmit queue. Ram more data into the pipe if we have any | ||
649 | * | ||
650 | * FIXME: lock against link layer control transmissions | ||
651 | */ | ||
652 | |||
653 | static void gsm_data_kick(struct gsm_mux *gsm) | ||
654 | { | ||
655 | struct gsm_msg *msg = gsm->tx_head; | ||
656 | int len; | ||
657 | int skip_sof = 0; | ||
658 | |||
659 | /* FIXME: We need to apply this solely to data messages */ | ||
660 | if (gsm->constipated) | ||
661 | return; | ||
662 | |||
663 | while (gsm->tx_head != NULL) { | ||
664 | msg = gsm->tx_head; | ||
665 | if (gsm->encoding != 0) { | ||
666 | gsm->txframe[0] = GSM1_SOF; | ||
667 | len = gsm_stuff_frame(msg->data, | ||
668 | gsm->txframe + 1, msg->len); | ||
669 | gsm->txframe[len + 1] = GSM1_SOF; | ||
670 | len += 2; | ||
671 | } else { | ||
672 | gsm->txframe[0] = GSM0_SOF; | ||
673 | memcpy(gsm->txframe + 1 , msg->data, msg->len); | ||
674 | gsm->txframe[msg->len + 1] = GSM0_SOF; | ||
675 | len = msg->len + 2; | ||
676 | } | ||
677 | |||
678 | if (debug & 4) { | ||
679 | printk("gsm_data_kick: \n"); | ||
680 | hex_packet(gsm->txframe, len); | ||
681 | } | ||
682 | |||
683 | if (gsm->output(gsm, gsm->txframe + skip_sof, | ||
684 | len - skip_sof) < 0) | ||
685 | break; | ||
686 | /* FIXME: Can eliminate one SOF in many more cases */ | ||
687 | gsm->tx_head = msg->next; | ||
688 | if (gsm->tx_head == NULL) | ||
689 | gsm->tx_tail = NULL; | ||
690 | gsm->tx_bytes -= msg->len; | ||
691 | kfree(msg); | ||
692 | /* For a burst of frames skip the extra SOF within the | ||
693 | burst */ | ||
694 | skip_sof = 1; | ||
695 | } | ||
696 | } | ||
697 | |||
698 | /** | ||
699 | * __gsm_data_queue - queue a UI or UIH frame | ||
700 | * @dlci: DLCI sending the data | ||
701 | * @msg: message queued | ||
702 | * | ||
703 | * Add data to the transmit queue and try and get stuff moving | ||
704 | * out of the mux tty if not already doing so. The Caller must hold | ||
705 | * the gsm tx lock. | ||
706 | */ | ||
707 | |||
708 | static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg) | ||
709 | { | ||
710 | struct gsm_mux *gsm = dlci->gsm; | ||
711 | u8 *dp = msg->data; | ||
712 | u8 *fcs = dp + msg->len; | ||
713 | |||
714 | /* Fill in the header */ | ||
715 | if (gsm->encoding == 0) { | ||
716 | if (msg->len < 128) | ||
717 | *--dp = (msg->len << 1) | EA; | ||
718 | else { | ||
719 | *--dp = (msg->len >> 6) | EA; | ||
720 | *--dp = (msg->len & 127) << 1; | ||
721 | } | ||
722 | } | ||
723 | |||
724 | *--dp = msg->ctrl; | ||
725 | if (gsm->initiator) | ||
726 | *--dp = (msg->addr << 2) | 2 | EA; | ||
727 | else | ||
728 | *--dp = (msg->addr << 2) | EA; | ||
729 | *fcs = gsm_fcs_add_block(INIT_FCS, dp , msg->data - dp); | ||
730 | /* Ugly protocol layering violation */ | ||
731 | if (msg->ctrl == UI || msg->ctrl == (UI|PF)) | ||
732 | *fcs = gsm_fcs_add_block(*fcs, msg->data, msg->len); | ||
733 | *fcs = 0xFF - *fcs; | ||
734 | |||
735 | gsm_print_packet("Q> ", msg->addr, gsm->initiator, msg->ctrl, | ||
736 | msg->data, msg->len); | ||
737 | |||
738 | /* Move the header back and adjust the length, also allow for the FCS | ||
739 | now tacked on the end */ | ||
740 | msg->len += (msg->data - dp) + 1; | ||
741 | msg->data = dp; | ||
742 | |||
743 | /* Add to the actual output queue */ | ||
744 | if (gsm->tx_tail) | ||
745 | gsm->tx_tail->next = msg; | ||
746 | else | ||
747 | gsm->tx_head = msg; | ||
748 | gsm->tx_tail = msg; | ||
749 | gsm->tx_bytes += msg->len; | ||
750 | gsm_data_kick(gsm); | ||
751 | } | ||
752 | |||
753 | /** | ||
754 | * gsm_data_queue - queue a UI or UIH frame | ||
755 | * @dlci: DLCI sending the data | ||
756 | * @msg: message queued | ||
757 | * | ||
758 | * Add data to the transmit queue and try and get stuff moving | ||
759 | * out of the mux tty if not already doing so. Take the | ||
760 | * the gsm tx lock and dlci lock. | ||
761 | */ | ||
762 | |||
763 | static void gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg) | ||
764 | { | ||
765 | unsigned long flags; | ||
766 | spin_lock_irqsave(&dlci->gsm->tx_lock, flags); | ||
767 | __gsm_data_queue(dlci, msg); | ||
768 | spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags); | ||
769 | } | ||
770 | |||
771 | /** | ||
772 | * gsm_dlci_data_output - try and push data out of a DLCI | ||
773 | * @gsm: mux | ||
774 | * @dlci: the DLCI to pull data from | ||
775 | * | ||
776 | * Pull data from a DLCI and send it into the transmit queue if there | ||
777 | * is data. Keep to the MRU of the mux. This path handles the usual tty | ||
778 | * interface which is a byte stream with optional modem data. | ||
779 | * | ||
780 | * Caller must hold the tx_lock of the mux. | ||
781 | */ | ||
782 | |||
783 | static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci) | ||
784 | { | ||
785 | struct gsm_msg *msg; | ||
786 | u8 *dp; | ||
787 | int len, size; | ||
788 | int h = dlci->adaption - 1; | ||
789 | |||
790 | len = kfifo_len(dlci->fifo); | ||
791 | if (len == 0) | ||
792 | return 0; | ||
793 | |||
794 | /* MTU/MRU count only the data bits */ | ||
795 | if (len > gsm->mtu) | ||
796 | len = gsm->mtu; | ||
797 | |||
798 | size = len + h; | ||
799 | |||
800 | msg = gsm_data_alloc(gsm, dlci->addr, size, gsm->ftype); | ||
801 | /* FIXME: need a timer or something to kick this so it can't | ||
802 | get stuck with no work outstanding and no buffer free */ | ||
803 | if (msg == NULL) | ||
804 | return -ENOMEM; | ||
805 | dp = msg->data; | ||
806 | switch (dlci->adaption) { | ||
807 | case 1: /* Unstructured */ | ||
808 | break; | ||
809 | case 2: /* Unstructed with modem bits. Always one byte as we never | ||
810 | send inline break data */ | ||
811 | *dp += gsm_encode_modem(dlci); | ||
812 | len--; | ||
813 | break; | ||
814 | } | ||
815 | WARN_ON(kfifo_out_locked(dlci->fifo, dp , len, &dlci->lock) != len); | ||
816 | __gsm_data_queue(dlci, msg); | ||
817 | /* Bytes of data we used up */ | ||
818 | return size; | ||
819 | } | ||
820 | |||
821 | /** | ||
822 | * gsm_dlci_data_output_framed - try and push data out of a DLCI | ||
823 | * @gsm: mux | ||
824 | * @dlci: the DLCI to pull data from | ||
825 | * | ||
826 | * Pull data from a DLCI and send it into the transmit queue if there | ||
827 | * is data. Keep to the MRU of the mux. This path handles framed data | ||
828 | * queued as skbuffs to the DLCI. | ||
829 | * | ||
830 | * Caller must hold the tx_lock of the mux. | ||
831 | */ | ||
832 | |||
833 | static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, | ||
834 | struct gsm_dlci *dlci) | ||
835 | { | ||
836 | struct gsm_msg *msg; | ||
837 | u8 *dp; | ||
838 | int len, size; | ||
839 | int last = 0, first = 0; | ||
840 | int overhead = 0; | ||
841 | |||
842 | /* One byte per frame is used for B/F flags */ | ||
843 | if (dlci->adaption == 4) | ||
844 | overhead = 1; | ||
845 | |||
846 | /* dlci->skb is locked by tx_lock */ | ||
847 | if (dlci->skb == NULL) { | ||
848 | dlci->skb = skb_dequeue(&dlci->skb_list); | ||
849 | if (dlci->skb == NULL) | ||
850 | return 0; | ||
851 | first = 1; | ||
852 | } | ||
853 | len = dlci->skb->len + overhead; | ||
854 | |||
855 | /* MTU/MRU count only the data bits */ | ||
856 | if (len > gsm->mtu) { | ||
857 | if (dlci->adaption == 3) { | ||
858 | /* Over long frame, bin it */ | ||
859 | kfree_skb(dlci->skb); | ||
860 | dlci->skb = NULL; | ||
861 | return 0; | ||
862 | } | ||
863 | len = gsm->mtu; | ||
864 | } else | ||
865 | last = 1; | ||
866 | |||
867 | size = len + overhead; | ||
868 | msg = gsm_data_alloc(gsm, dlci->addr, size, gsm->ftype); | ||
869 | |||
870 | /* FIXME: need a timer or something to kick this so it can't | ||
871 | get stuck with no work outstanding and no buffer free */ | ||
872 | if (msg == NULL) | ||
873 | return -ENOMEM; | ||
874 | dp = msg->data; | ||
875 | |||
876 | if (dlci->adaption == 4) { /* Interruptible framed (Packetised Data) */ | ||
877 | /* Flag byte to carry the start/end info */ | ||
878 | *dp++ = last << 7 | first << 6 | 1; /* EA */ | ||
879 | len--; | ||
880 | } | ||
881 | memcpy(dp, skb_pull(dlci->skb, len), len); | ||
882 | __gsm_data_queue(dlci, msg); | ||
883 | if (last) | ||
884 | dlci->skb = NULL; | ||
885 | return size; | ||
886 | } | ||
887 | |||
888 | /** | ||
889 | * gsm_dlci_data_sweep - look for data to send | ||
890 | * @gsm: the GSM mux | ||
891 | * | ||
892 | * Sweep the GSM mux channels in priority order looking for ones with | ||
893 | * data to send. We could do with optimising this scan a bit. We aim | ||
894 | * to fill the queue totally or up to TX_THRESH_HI bytes. Once we hit | ||
895 | * TX_THRESH_LO we get called again | ||
896 | * | ||
897 | * FIXME: We should round robin between groups and in theory you can | ||
898 | * renegotiate DLCI priorities with optional stuff. Needs optimising. | ||
899 | */ | ||
900 | |||
901 | static void gsm_dlci_data_sweep(struct gsm_mux *gsm) | ||
902 | { | ||
903 | int len; | ||
904 | /* Priority ordering: We should do priority with RR of the groups */ | ||
905 | int i = 1; | ||
906 | |||
907 | while (i < NUM_DLCI) { | ||
908 | struct gsm_dlci *dlci; | ||
909 | |||
910 | if (gsm->tx_bytes > TX_THRESH_HI) | ||
911 | break; | ||
912 | dlci = gsm->dlci[i]; | ||
913 | if (dlci == NULL || dlci->constipated) { | ||
914 | i++; | ||
915 | continue; | ||
916 | } | ||
917 | if (dlci->adaption < 3) | ||
918 | len = gsm_dlci_data_output(gsm, dlci); | ||
919 | else | ||
920 | len = gsm_dlci_data_output_framed(gsm, dlci); | ||
921 | if (len < 0) | ||
922 | break; | ||
923 | /* DLCI empty - try the next */ | ||
924 | if (len == 0) | ||
925 | i++; | ||
926 | } | ||
927 | } | ||
928 | |||
929 | /** | ||
930 | * gsm_dlci_data_kick - transmit if possible | ||
931 | * @dlci: DLCI to kick | ||
932 | * | ||
933 | * Transmit data from this DLCI if the queue is empty. We can't rely on | ||
934 | * a tty wakeup except when we filled the pipe so we need to fire off | ||
935 | * new data ourselves in other cases. | ||
936 | */ | ||
937 | |||
938 | static void gsm_dlci_data_kick(struct gsm_dlci *dlci) | ||
939 | { | ||
940 | unsigned long flags; | ||
941 | |||
942 | spin_lock_irqsave(&dlci->gsm->tx_lock, flags); | ||
943 | /* If we have nothing running then we need to fire up */ | ||
944 | if (dlci->gsm->tx_bytes == 0) | ||
945 | gsm_dlci_data_output(dlci->gsm, dlci); | ||
946 | else if (dlci->gsm->tx_bytes < TX_THRESH_LO) | ||
947 | gsm_dlci_data_sweep(dlci->gsm); | ||
948 | spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags); | ||
949 | } | ||
950 | |||
951 | /* | ||
952 | * Control message processing | ||
953 | */ | ||
954 | |||
955 | |||
956 | /** | ||
957 | * gsm_control_reply - send a response frame to a control | ||
958 | * @gsm: gsm channel | ||
959 | * @cmd: the command to use | ||
960 | * @data: data to follow encoded info | ||
961 | * @dlen: length of data | ||
962 | * | ||
963 | * Encode up and queue a UI/UIH frame containing our response. | ||
964 | */ | ||
965 | |||
966 | static void gsm_control_reply(struct gsm_mux *gsm, int cmd, u8 *data, | ||
967 | int dlen) | ||
968 | { | ||
969 | struct gsm_msg *msg; | ||
970 | msg = gsm_data_alloc(gsm, 0, dlen + 2, gsm->ftype); | ||
971 | msg->data[0] = (cmd & 0xFE) << 1 | EA; /* Clear C/R */ | ||
972 | msg->data[1] = (dlen << 1) | EA; | ||
973 | memcpy(msg->data + 2, data, dlen); | ||
974 | gsm_data_queue(gsm->dlci[0], msg); | ||
975 | } | ||
976 | |||
977 | /** | ||
978 | * gsm_process_modem - process received modem status | ||
979 | * @tty: virtual tty bound to the DLCI | ||
980 | * @dlci: DLCI to affect | ||
981 | * @modem: modem bits (full EA) | ||
982 | * | ||
983 | * Used when a modem control message or line state inline in adaption | ||
984 | * layer 2 is processed. Sort out the local modem state and throttles | ||
985 | */ | ||
986 | |||
987 | static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci, | ||
988 | u32 modem) | ||
989 | { | ||
990 | int mlines = 0; | ||
991 | u8 brk = modem >> 6; | ||
992 | |||
993 | /* Flow control/ready to communicate */ | ||
994 | if (modem & MDM_FC) { | ||
995 | /* Need to throttle our output on this device */ | ||
996 | dlci->constipated = 1; | ||
997 | } | ||
998 | if (modem & MDM_RTC) { | ||
999 | mlines |= TIOCM_DSR | TIOCM_DTR; | ||
1000 | dlci->constipated = 0; | ||
1001 | gsm_dlci_data_kick(dlci); | ||
1002 | } | ||
1003 | /* Map modem bits */ | ||
1004 | if (modem & MDM_RTR) | ||
1005 | mlines |= TIOCM_RTS | TIOCM_CTS; | ||
1006 | if (modem & MDM_IC) | ||
1007 | mlines |= TIOCM_RI; | ||
1008 | if (modem & MDM_DV) | ||
1009 | mlines |= TIOCM_CD; | ||
1010 | |||
1011 | /* Carrier drop -> hangup */ | ||
1012 | if (tty) { | ||
1013 | if ((mlines & TIOCM_CD) == 0 && (dlci->modem_rx & TIOCM_CD)) | ||
1014 | if (!(tty->termios->c_cflag & CLOCAL)) | ||
1015 | tty_hangup(tty); | ||
1016 | if (brk & 0x01) | ||
1017 | tty_insert_flip_char(tty, 0, TTY_BREAK); | ||
1018 | } | ||
1019 | dlci->modem_rx = mlines; | ||
1020 | } | ||
1021 | |||
1022 | /** | ||
1023 | * gsm_control_modem - modem status received | ||
1024 | * @gsm: GSM channel | ||
1025 | * @data: data following command | ||
1026 | * @clen: command length | ||
1027 | * | ||
1028 | * We have received a modem status control message. This is used by | ||
1029 | * the GSM mux protocol to pass virtual modem line status and optionally | ||
1030 | * to indicate break signals. Unpack it, convert to Linux representation | ||
1031 | * and if need be stuff a break message down the tty. | ||
1032 | */ | ||
1033 | |||
1034 | static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen) | ||
1035 | { | ||
1036 | unsigned int addr = 0; | ||
1037 | unsigned int modem = 0; | ||
1038 | struct gsm_dlci *dlci; | ||
1039 | int len = clen; | ||
1040 | u8 *dp = data; | ||
1041 | struct tty_struct *tty; | ||
1042 | |||
1043 | while (gsm_read_ea(&addr, *dp++) == 0) { | ||
1044 | len--; | ||
1045 | if (len == 0) | ||
1046 | return; | ||
1047 | } | ||
1048 | /* Must be at least one byte following the EA */ | ||
1049 | len--; | ||
1050 | if (len <= 0) | ||
1051 | return; | ||
1052 | |||
1053 | addr >>= 1; | ||
1054 | /* Closed port, or invalid ? */ | ||
1055 | if (addr == 0 || addr >= NUM_DLCI || gsm->dlci[addr] == NULL) | ||
1056 | return; | ||
1057 | dlci = gsm->dlci[addr]; | ||
1058 | |||
1059 | while (gsm_read_ea(&modem, *dp++) == 0) { | ||
1060 | len--; | ||
1061 | if (len == 0) | ||
1062 | return; | ||
1063 | } | ||
1064 | tty = tty_port_tty_get(&dlci->port); | ||
1065 | gsm_process_modem(tty, dlci, modem); | ||
1066 | if (tty) { | ||
1067 | tty_wakeup(tty); | ||
1068 | tty_kref_put(tty); | ||
1069 | } | ||
1070 | gsm_control_reply(gsm, CMD_MSC, data, clen); | ||
1071 | } | ||
1072 | |||
1073 | /** | ||
1074 | * gsm_control_rls - remote line status | ||
1075 | * @gsm: GSM channel | ||
1076 | * @data: data bytes | ||
1077 | * @clen: data length | ||
1078 | * | ||
1079 | * The modem sends us a two byte message on the control channel whenever | ||
1080 | * it wishes to send us an error state from the virtual link. Stuff | ||
1081 | * this into the uplink tty if present | ||
1082 | */ | ||
1083 | |||
1084 | static void gsm_control_rls(struct gsm_mux *gsm, u8 *data, int clen) | ||
1085 | { | ||
1086 | struct tty_struct *tty; | ||
1087 | unsigned int addr = 0 ; | ||
1088 | u8 bits; | ||
1089 | int len = clen; | ||
1090 | u8 *dp = data; | ||
1091 | |||
1092 | while (gsm_read_ea(&addr, *dp++) == 0) { | ||
1093 | len--; | ||
1094 | if (len == 0) | ||
1095 | return; | ||
1096 | } | ||
1097 | /* Must be at least one byte following ea */ | ||
1098 | len--; | ||
1099 | if (len <= 0) | ||
1100 | return; | ||
1101 | addr >>= 1; | ||
1102 | /* Closed port, or invalid ? */ | ||
1103 | if (addr == 0 || addr >= NUM_DLCI || gsm->dlci[addr] == NULL) | ||
1104 | return; | ||
1105 | /* No error ? */ | ||
1106 | bits = *dp; | ||
1107 | if ((bits & 1) == 0) | ||
1108 | return; | ||
1109 | /* See if we have an uplink tty */ | ||
1110 | tty = tty_port_tty_get(&gsm->dlci[addr]->port); | ||
1111 | |||
1112 | if (tty) { | ||
1113 | if (bits & 2) | ||
1114 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
1115 | if (bits & 4) | ||
1116 | tty_insert_flip_char(tty, 0, TTY_PARITY); | ||
1117 | if (bits & 8) | ||
1118 | tty_insert_flip_char(tty, 0, TTY_FRAME); | ||
1119 | tty_flip_buffer_push(tty); | ||
1120 | tty_kref_put(tty); | ||
1121 | } | ||
1122 | gsm_control_reply(gsm, CMD_RLS, data, clen); | ||
1123 | } | ||
1124 | |||
1125 | static void gsm_dlci_begin_close(struct gsm_dlci *dlci); | ||
1126 | |||
1127 | /** | ||
1128 | * gsm_control_message - DLCI 0 control processing | ||
1129 | * @gsm: our GSM mux | ||
1130 | * @command: the command EA | ||
1131 | * @data: data beyond the command/length EAs | ||
1132 | * @clen: length | ||
1133 | * | ||
1134 | * Input processor for control messages from the other end of the link. | ||
1135 | * Processes the incoming request and queues a response frame or an | ||
1136 | * NSC response if not supported | ||
1137 | */ | ||
1138 | |||
1139 | static void gsm_control_message(struct gsm_mux *gsm, unsigned int command, | ||
1140 | u8 *data, int clen) | ||
1141 | { | ||
1142 | u8 buf[1]; | ||
1143 | switch (command) { | ||
1144 | case CMD_CLD: { | ||
1145 | struct gsm_dlci *dlci = gsm->dlci[0]; | ||
1146 | /* Modem wishes to close down */ | ||
1147 | if (dlci) { | ||
1148 | dlci->dead = 1; | ||
1149 | gsm->dead = 1; | ||
1150 | gsm_dlci_begin_close(dlci); | ||
1151 | } | ||
1152 | } | ||
1153 | break; | ||
1154 | case CMD_TEST: | ||
1155 | /* Modem wishes to test, reply with the data */ | ||
1156 | gsm_control_reply(gsm, CMD_TEST, data, clen); | ||
1157 | break; | ||
1158 | case CMD_FCON: | ||
1159 | /* Modem wants us to STFU */ | ||
1160 | gsm->constipated = 1; | ||
1161 | gsm_control_reply(gsm, CMD_FCON, NULL, 0); | ||
1162 | break; | ||
1163 | case CMD_FCOFF: | ||
1164 | /* Modem can accept data again */ | ||
1165 | gsm->constipated = 0; | ||
1166 | gsm_control_reply(gsm, CMD_FCOFF, NULL, 0); | ||
1167 | /* Kick the link in case it is idling */ | ||
1168 | gsm_data_kick(gsm); | ||
1169 | break; | ||
1170 | case CMD_MSC: | ||
1171 | /* Out of band modem line change indicator for a DLCI */ | ||
1172 | gsm_control_modem(gsm, data, clen); | ||
1173 | break; | ||
1174 | case CMD_RLS: | ||
1175 | /* Out of band error reception for a DLCI */ | ||
1176 | gsm_control_rls(gsm, data, clen); | ||
1177 | break; | ||
1178 | case CMD_PSC: | ||
1179 | /* Modem wishes to enter power saving state */ | ||
1180 | gsm_control_reply(gsm, CMD_PSC, NULL, 0); | ||
1181 | break; | ||
1182 | /* Optional unsupported commands */ | ||
1183 | case CMD_PN: /* Parameter negotiation */ | ||
1184 | case CMD_RPN: /* Remote port negotation */ | ||
1185 | case CMD_SNC: /* Service negotation command */ | ||
1186 | default: | ||
1187 | /* Reply to bad commands with an NSC */ | ||
1188 | buf[0] = command; | ||
1189 | gsm_control_reply(gsm, CMD_NSC, buf, 1); | ||
1190 | break; | ||
1191 | } | ||
1192 | } | ||
1193 | |||
1194 | /** | ||
1195 | * gsm_control_response - process a response to our control | ||
1196 | * @gsm: our GSM mux | ||
1197 | * @command: the command (response) EA | ||
1198 | * @data: data beyond the command/length EA | ||
1199 | * @clen: length | ||
1200 | * | ||
1201 | * Process a response to an outstanding command. We only allow a single | ||
1202 | * control message in flight so this is fairly easy. All the clean up | ||
1203 | * is done by the caller, we just update the fields, flag it as done | ||
1204 | * and return | ||
1205 | */ | ||
1206 | |||
1207 | static void gsm_control_response(struct gsm_mux *gsm, unsigned int command, | ||
1208 | u8 *data, int clen) | ||
1209 | { | ||
1210 | struct gsm_control *ctrl; | ||
1211 | unsigned long flags; | ||
1212 | |||
1213 | spin_lock_irqsave(&gsm->control_lock, flags); | ||
1214 | |||
1215 | ctrl = gsm->pending_cmd; | ||
1216 | /* Does the reply match our command */ | ||
1217 | command |= 1; | ||
1218 | if (ctrl != NULL && (command == ctrl->cmd || command == CMD_NSC)) { | ||
1219 | /* Our command was replied to, kill the retry timer */ | ||
1220 | del_timer(&gsm->t2_timer); | ||
1221 | gsm->pending_cmd = NULL; | ||
1222 | /* Rejected by the other end */ | ||
1223 | if (command == CMD_NSC) | ||
1224 | ctrl->error = -EOPNOTSUPP; | ||
1225 | ctrl->done = 1; | ||
1226 | wake_up(&gsm->event); | ||
1227 | } | ||
1228 | spin_unlock_irqrestore(&gsm->control_lock, flags); | ||
1229 | } | ||
1230 | |||
1231 | /** | ||
1232 | * gsm_control_transmit - send control packet | ||
1233 | * @gsm: gsm mux | ||
1234 | * @ctrl: frame to send | ||
1235 | * | ||
1236 | * Send out a pending control command (called under control lock) | ||
1237 | */ | ||
1238 | |||
1239 | static void gsm_control_transmit(struct gsm_mux *gsm, struct gsm_control *ctrl) | ||
1240 | { | ||
1241 | struct gsm_msg *msg = gsm_data_alloc(gsm, 0, ctrl->len + 1, | ||
1242 | gsm->ftype|PF); | ||
1243 | if (msg == NULL) | ||
1244 | return; | ||
1245 | msg->data[0] = (ctrl->cmd << 1) | 2 | EA; /* command */ | ||
1246 | memcpy(msg->data + 1, ctrl->data, ctrl->len); | ||
1247 | gsm_data_queue(gsm->dlci[0], msg); | ||
1248 | } | ||
1249 | |||
1250 | /** | ||
1251 | * gsm_control_retransmit - retransmit a control frame | ||
1252 | * @data: pointer to our gsm object | ||
1253 | * | ||
1254 | * Called off the T2 timer expiry in order to retransmit control frames | ||
1255 | * that have been lost in the system somewhere. The control_lock protects | ||
1256 | * us from colliding with another sender or a receive completion event. | ||
1257 | * In that situation the timer may still occur in a small window but | ||
1258 | * gsm->pending_cmd will be NULL and we just let the timer expire. | ||
1259 | */ | ||
1260 | |||
1261 | static void gsm_control_retransmit(unsigned long data) | ||
1262 | { | ||
1263 | struct gsm_mux *gsm = (struct gsm_mux *)data; | ||
1264 | struct gsm_control *ctrl; | ||
1265 | unsigned long flags; | ||
1266 | spin_lock_irqsave(&gsm->control_lock, flags); | ||
1267 | ctrl = gsm->pending_cmd; | ||
1268 | if (ctrl) { | ||
1269 | gsm->cretries--; | ||
1270 | if (gsm->cretries == 0) { | ||
1271 | gsm->pending_cmd = NULL; | ||
1272 | ctrl->error = -ETIMEDOUT; | ||
1273 | ctrl->done = 1; | ||
1274 | spin_unlock_irqrestore(&gsm->control_lock, flags); | ||
1275 | wake_up(&gsm->event); | ||
1276 | return; | ||
1277 | } | ||
1278 | gsm_control_transmit(gsm, ctrl); | ||
1279 | mod_timer(&gsm->t2_timer, jiffies + gsm->t2 * HZ / 100); | ||
1280 | } | ||
1281 | spin_unlock_irqrestore(&gsm->control_lock, flags); | ||
1282 | } | ||
1283 | |||
1284 | /** | ||
1285 | * gsm_control_send - send a control frame on DLCI 0 | ||
1286 | * @gsm: the GSM channel | ||
1287 | * @command: command to send including CR bit | ||
1288 | * @data: bytes of data (must be kmalloced) | ||
1289 | * @len: length of the block to send | ||
1290 | * | ||
1291 | * Queue and dispatch a control command. Only one command can be | ||
1292 | * active at a time. In theory more can be outstanding but the matching | ||
1293 | * gets really complicated so for now stick to one outstanding. | ||
1294 | */ | ||
1295 | |||
1296 | static struct gsm_control *gsm_control_send(struct gsm_mux *gsm, | ||
1297 | unsigned int command, u8 *data, int clen) | ||
1298 | { | ||
1299 | struct gsm_control *ctrl = kzalloc(sizeof(struct gsm_control), | ||
1300 | GFP_KERNEL); | ||
1301 | unsigned long flags; | ||
1302 | if (ctrl == NULL) | ||
1303 | return NULL; | ||
1304 | retry: | ||
1305 | wait_event(gsm->event, gsm->pending_cmd == NULL); | ||
1306 | spin_lock_irqsave(&gsm->control_lock, flags); | ||
1307 | if (gsm->pending_cmd != NULL) { | ||
1308 | spin_unlock_irqrestore(&gsm->control_lock, flags); | ||
1309 | goto retry; | ||
1310 | } | ||
1311 | ctrl->cmd = command; | ||
1312 | ctrl->data = data; | ||
1313 | ctrl->len = clen; | ||
1314 | gsm->pending_cmd = ctrl; | ||
1315 | gsm->cretries = gsm->n2; | ||
1316 | mod_timer(&gsm->t2_timer, jiffies + gsm->t2 * HZ / 100); | ||
1317 | gsm_control_transmit(gsm, ctrl); | ||
1318 | spin_unlock_irqrestore(&gsm->control_lock, flags); | ||
1319 | return ctrl; | ||
1320 | } | ||
1321 | |||
1322 | /** | ||
1323 | * gsm_control_wait - wait for a control to finish | ||
1324 | * @gsm: GSM mux | ||
1325 | * @control: control we are waiting on | ||
1326 | * | ||
1327 | * Waits for the control to complete or time out. Frees any used | ||
1328 | * resources and returns 0 for success, or an error if the remote | ||
1329 | * rejected or ignored the request. | ||
1330 | */ | ||
1331 | |||
1332 | static int gsm_control_wait(struct gsm_mux *gsm, struct gsm_control *control) | ||
1333 | { | ||
1334 | int err; | ||
1335 | wait_event(gsm->event, control->done == 1); | ||
1336 | err = control->error; | ||
1337 | kfree(control); | ||
1338 | return err; | ||
1339 | } | ||
1340 | |||
1341 | |||
1342 | /* | ||
1343 | * DLCI level handling: Needs krefs | ||
1344 | */ | ||
1345 | |||
1346 | /* | ||
1347 | * State transitions and timers | ||
1348 | */ | ||
1349 | |||
1350 | /** | ||
1351 | * gsm_dlci_close - a DLCI has closed | ||
1352 | * @dlci: DLCI that closed | ||
1353 | * | ||
1354 | * Perform processing when moving a DLCI into closed state. If there | ||
1355 | * is an attached tty this is hung up | ||
1356 | */ | ||
1357 | |||
1358 | static void gsm_dlci_close(struct gsm_dlci *dlci) | ||
1359 | { | ||
1360 | del_timer(&dlci->t1); | ||
1361 | if (debug & 8) | ||
1362 | printk("DLCI %d goes closed.\n", dlci->addr); | ||
1363 | dlci->state = DLCI_CLOSED; | ||
1364 | if (dlci->addr != 0) { | ||
1365 | struct tty_struct *tty = tty_port_tty_get(&dlci->port); | ||
1366 | if (tty) { | ||
1367 | tty_hangup(tty); | ||
1368 | tty_kref_put(tty); | ||
1369 | } | ||
1370 | kfifo_reset(dlci->fifo); | ||
1371 | } else | ||
1372 | dlci->gsm->dead = 1; | ||
1373 | wake_up(&dlci->gsm->event); | ||
1374 | /* A DLCI 0 close is a MUX termination so we need to kick that | ||
1375 | back to userspace somehow */ | ||
1376 | } | ||
1377 | |||
1378 | /** | ||
1379 | * gsm_dlci_open - a DLCI has opened | ||
1380 | * @dlci: DLCI that opened | ||
1381 | * | ||
1382 | * Perform processing when moving a DLCI into open state. | ||
1383 | */ | ||
1384 | |||
1385 | static void gsm_dlci_open(struct gsm_dlci *dlci) | ||
1386 | { | ||
1387 | /* Note that SABM UA .. SABM UA first UA lost can mean that we go | ||
1388 | open -> open */ | ||
1389 | del_timer(&dlci->t1); | ||
1390 | /* This will let a tty open continue */ | ||
1391 | dlci->state = DLCI_OPEN; | ||
1392 | if (debug & 8) | ||
1393 | printk("DLCI %d goes open.\n", dlci->addr); | ||
1394 | wake_up(&dlci->gsm->event); | ||
1395 | } | ||
1396 | |||
1397 | /** | ||
1398 | * gsm_dlci_t1 - T1 timer expiry | ||
1399 | * @dlci: DLCI that opened | ||
1400 | * | ||
1401 | * The T1 timer handles retransmits of control frames (essentially of | ||
1402 | * SABM and DISC). We resend the command until the retry count runs out | ||
1403 | * in which case an opening port goes back to closed and a closing port | ||
1404 | * is simply put into closed state (any further frames from the other | ||
1405 | * end will get a DM response) | ||
1406 | */ | ||
1407 | |||
1408 | static void gsm_dlci_t1(unsigned long data) | ||
1409 | { | ||
1410 | struct gsm_dlci *dlci = (struct gsm_dlci *)data; | ||
1411 | struct gsm_mux *gsm = dlci->gsm; | ||
1412 | |||
1413 | switch (dlci->state) { | ||
1414 | case DLCI_OPENING: | ||
1415 | dlci->retries--; | ||
1416 | if (dlci->retries) { | ||
1417 | gsm_command(dlci->gsm, dlci->addr, SABM|PF); | ||
1418 | mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100); | ||
1419 | } else | ||
1420 | gsm_dlci_close(dlci); | ||
1421 | break; | ||
1422 | case DLCI_CLOSING: | ||
1423 | dlci->retries--; | ||
1424 | if (dlci->retries) { | ||
1425 | gsm_command(dlci->gsm, dlci->addr, DISC|PF); | ||
1426 | mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100); | ||
1427 | } else | ||
1428 | gsm_dlci_close(dlci); | ||
1429 | break; | ||
1430 | } | ||
1431 | } | ||
1432 | |||
1433 | /** | ||
1434 | * gsm_dlci_begin_open - start channel open procedure | ||
1435 | * @dlci: DLCI to open | ||
1436 | * | ||
1437 | * Commence opening a DLCI from the Linux side. We issue SABM messages | ||
1438 | * to the modem which should then reply with a UA, at which point we | ||
1439 | * will move into open state. Opening is done asynchronously with retry | ||
1440 | * running off timers and the responses. | ||
1441 | */ | ||
1442 | |||
1443 | static void gsm_dlci_begin_open(struct gsm_dlci *dlci) | ||
1444 | { | ||
1445 | struct gsm_mux *gsm = dlci->gsm; | ||
1446 | if (dlci->state == DLCI_OPEN || dlci->state == DLCI_OPENING) | ||
1447 | return; | ||
1448 | dlci->retries = gsm->n2; | ||
1449 | dlci->state = DLCI_OPENING; | ||
1450 | gsm_command(dlci->gsm, dlci->addr, SABM|PF); | ||
1451 | mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100); | ||
1452 | } | ||
1453 | |||
1454 | /** | ||
1455 | * gsm_dlci_begin_close - start channel open procedure | ||
1456 | * @dlci: DLCI to open | ||
1457 | * | ||
1458 | * Commence closing a DLCI from the Linux side. We issue DISC messages | ||
1459 | * to the modem which should then reply with a UA, at which point we | ||
1460 | * will move into closed state. Closing is done asynchronously with retry | ||
1461 | * off timers. We may also receive a DM reply from the other end which | ||
1462 | * indicates the channel was already closed. | ||
1463 | */ | ||
1464 | |||
1465 | static void gsm_dlci_begin_close(struct gsm_dlci *dlci) | ||
1466 | { | ||
1467 | struct gsm_mux *gsm = dlci->gsm; | ||
1468 | if (dlci->state == DLCI_CLOSED || dlci->state == DLCI_CLOSING) | ||
1469 | return; | ||
1470 | dlci->retries = gsm->n2; | ||
1471 | dlci->state = DLCI_CLOSING; | ||
1472 | gsm_command(dlci->gsm, dlci->addr, DISC|PF); | ||
1473 | mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100); | ||
1474 | } | ||
1475 | |||
1476 | /** | ||
1477 | * gsm_dlci_data - data arrived | ||
1478 | * @dlci: channel | ||
1479 | * @data: block of bytes received | ||
1480 | * @len: length of received block | ||
1481 | * | ||
1482 | * A UI or UIH frame has arrived which contains data for a channel | ||
1483 | * other than the control channel. If the relevant virtual tty is | ||
1484 | * open we shovel the bits down it, if not we drop them. | ||
1485 | */ | ||
1486 | |||
1487 | static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int len) | ||
1488 | { | ||
1489 | /* krefs .. */ | ||
1490 | struct tty_port *port = &dlci->port; | ||
1491 | struct tty_struct *tty = tty_port_tty_get(port); | ||
1492 | unsigned int modem = 0; | ||
1493 | |||
1494 | if (debug & 16) | ||
1495 | printk("%d bytes for tty %p\n", len, tty); | ||
1496 | if (tty) { | ||
1497 | switch (dlci->adaption) { | ||
1498 | /* Unsupported types */ | ||
1499 | /* Packetised interruptible data */ | ||
1500 | case 4: | ||
1501 | break; | ||
1502 | /* Packetised uininterruptible voice/data */ | ||
1503 | case 3: | ||
1504 | break; | ||
1505 | /* Asynchronous serial with line state in each frame */ | ||
1506 | case 2: | ||
1507 | while (gsm_read_ea(&modem, *data++) == 0) { | ||
1508 | len--; | ||
1509 | if (len == 0) | ||
1510 | return; | ||
1511 | } | ||
1512 | gsm_process_modem(tty, dlci, modem); | ||
1513 | /* Line state will go via DLCI 0 controls only */ | ||
1514 | case 1: | ||
1515 | default: | ||
1516 | tty_insert_flip_string(tty, data, len); | ||
1517 | tty_flip_buffer_push(tty); | ||
1518 | } | ||
1519 | tty_kref_put(tty); | ||
1520 | } | ||
1521 | } | ||
1522 | |||
1523 | /** | ||
1524 | * gsm_dlci_control - data arrived on control channel | ||
1525 | * @dlci: channel | ||
1526 | * @data: block of bytes received | ||
1527 | * @len: length of received block | ||
1528 | * | ||
1529 | * A UI or UIH frame has arrived which contains data for DLCI 0 the | ||
1530 | * control channel. This should contain a command EA followed by | ||
1531 | * control data bytes. The command EA contains a command/response bit | ||
1532 | * and we divide up the work accordingly. | ||
1533 | */ | ||
1534 | |||
1535 | static void gsm_dlci_command(struct gsm_dlci *dlci, u8 *data, int len) | ||
1536 | { | ||
1537 | /* See what command is involved */ | ||
1538 | unsigned int command = 0; | ||
1539 | while (len-- > 0) { | ||
1540 | if (gsm_read_ea(&command, *data++) == 1) { | ||
1541 | int clen = *data++; | ||
1542 | len--; | ||
1543 | /* FIXME: this is properly an EA */ | ||
1544 | clen >>= 1; | ||
1545 | /* Malformed command ? */ | ||
1546 | if (clen > len) | ||
1547 | return; | ||
1548 | if (command & 1) | ||
1549 | gsm_control_message(dlci->gsm, command, | ||
1550 | data, clen); | ||
1551 | else | ||
1552 | gsm_control_response(dlci->gsm, command, | ||
1553 | data, clen); | ||
1554 | return; | ||
1555 | } | ||
1556 | } | ||
1557 | } | ||
1558 | |||
1559 | /* | ||
1560 | * Allocate/Free DLCI channels | ||
1561 | */ | ||
1562 | |||
1563 | /** | ||
1564 | * gsm_dlci_alloc - allocate a DLCI | ||
1565 | * @gsm: GSM mux | ||
1566 | * @addr: address of the DLCI | ||
1567 | * | ||
1568 | * Allocate and install a new DLCI object into the GSM mux. | ||
1569 | * | ||
1570 | * FIXME: review locking races | ||
1571 | */ | ||
1572 | |||
1573 | static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr) | ||
1574 | { | ||
1575 | struct gsm_dlci *dlci = kzalloc(sizeof(struct gsm_dlci), GFP_ATOMIC); | ||
1576 | if (dlci == NULL) | ||
1577 | return NULL; | ||
1578 | spin_lock_init(&dlci->lock); | ||
1579 | dlci->fifo = &dlci->_fifo; | ||
1580 | if (kfifo_alloc(&dlci->_fifo, 4096, GFP_KERNEL) < 0) { | ||
1581 | kfree(dlci); | ||
1582 | return NULL; | ||
1583 | } | ||
1584 | |||
1585 | skb_queue_head_init(&dlci->skb_list); | ||
1586 | init_timer(&dlci->t1); | ||
1587 | dlci->t1.function = gsm_dlci_t1; | ||
1588 | dlci->t1.data = (unsigned long)dlci; | ||
1589 | tty_port_init(&dlci->port); | ||
1590 | dlci->port.ops = &gsm_port_ops; | ||
1591 | dlci->gsm = gsm; | ||
1592 | dlci->addr = addr; | ||
1593 | dlci->adaption = gsm->adaption; | ||
1594 | dlci->state = DLCI_CLOSED; | ||
1595 | if (addr) | ||
1596 | dlci->data = gsm_dlci_data; | ||
1597 | else | ||
1598 | dlci->data = gsm_dlci_command; | ||
1599 | gsm->dlci[addr] = dlci; | ||
1600 | return dlci; | ||
1601 | } | ||
1602 | |||
1603 | /** | ||
1604 | * gsm_dlci_free - release DLCI | ||
1605 | * @dlci: DLCI to destroy | ||
1606 | * | ||
1607 | * Free up a DLCI. Currently to keep the lifetime rules sane we only | ||
1608 | * clean up DLCI objects when the MUX closes rather than as the port | ||
1609 | * is closed down on both the tty and mux levels. | ||
1610 | * | ||
1611 | * Can sleep. | ||
1612 | */ | ||
1613 | static void gsm_dlci_free(struct gsm_dlci *dlci) | ||
1614 | { | ||
1615 | struct tty_struct *tty = tty_port_tty_get(&dlci->port); | ||
1616 | if (tty) { | ||
1617 | tty_vhangup(tty); | ||
1618 | tty_kref_put(tty); | ||
1619 | } | ||
1620 | del_timer_sync(&dlci->t1); | ||
1621 | dlci->gsm->dlci[dlci->addr] = NULL; | ||
1622 | kfifo_free(dlci->fifo); | ||
1623 | kfree(dlci); | ||
1624 | } | ||
1625 | |||
1626 | |||
1627 | /* | ||
1628 | * LAPBish link layer logic | ||
1629 | */ | ||
1630 | |||
1631 | /** | ||
1632 | * gsm_queue - a GSM frame is ready to process | ||
1633 | * @gsm: pointer to our gsm mux | ||
1634 | * | ||
1635 | * At this point in time a frame has arrived and been demangled from | ||
1636 | * the line encoding. All the differences between the encodings have | ||
1637 | * been handled below us and the frame is unpacked into the structures. | ||
1638 | * The fcs holds the header FCS but any data FCS must be added here. | ||
1639 | */ | ||
1640 | |||
1641 | static void gsm_queue(struct gsm_mux *gsm) | ||
1642 | { | ||
1643 | struct gsm_dlci *dlci; | ||
1644 | u8 cr; | ||
1645 | int address; | ||
1646 | /* We have to sneak a look at the packet body to do the FCS. | ||
1647 | A somewhat layering violation in the spec */ | ||
1648 | |||
1649 | if ((gsm->control & ~PF) == UI) | ||
1650 | gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, gsm->len); | ||
1651 | if (gsm->fcs != GOOD_FCS) { | ||
1652 | gsm->bad_fcs++; | ||
1653 | if (debug & 4) | ||
1654 | printk("BAD FCS %02x\n", gsm->fcs); | ||
1655 | return; | ||
1656 | } | ||
1657 | address = gsm->address >> 1; | ||
1658 | if (address >= NUM_DLCI) | ||
1659 | goto invalid; | ||
1660 | |||
1661 | cr = gsm->address & 1; /* C/R bit */ | ||
1662 | |||
1663 | gsm_print_packet("<--", address, cr, gsm->control, gsm->buf, gsm->len); | ||
1664 | |||
1665 | cr ^= 1 - gsm->initiator; /* Flip so 1 always means command */ | ||
1666 | dlci = gsm->dlci[address]; | ||
1667 | |||
1668 | switch (gsm->control) { | ||
1669 | case SABM|PF: | ||
1670 | if (cr == 0) | ||
1671 | goto invalid; | ||
1672 | if (dlci == NULL) | ||
1673 | dlci = gsm_dlci_alloc(gsm, address); | ||
1674 | if (dlci == NULL) | ||
1675 | return; | ||
1676 | if (dlci->dead) | ||
1677 | gsm_response(gsm, address, DM); | ||
1678 | else { | ||
1679 | gsm_response(gsm, address, UA); | ||
1680 | gsm_dlci_open(dlci); | ||
1681 | } | ||
1682 | break; | ||
1683 | case DISC|PF: | ||
1684 | if (cr == 0) | ||
1685 | goto invalid; | ||
1686 | if (dlci == NULL || dlci->state == DLCI_CLOSED) { | ||
1687 | gsm_response(gsm, address, DM); | ||
1688 | return; | ||
1689 | } | ||
1690 | /* Real close complete */ | ||
1691 | gsm_response(gsm, address, UA); | ||
1692 | gsm_dlci_close(dlci); | ||
1693 | break; | ||
1694 | case UA: | ||
1695 | case UA|PF: | ||
1696 | if (cr == 0 || dlci == NULL) | ||
1697 | break; | ||
1698 | switch (dlci->state) { | ||
1699 | case DLCI_CLOSING: | ||
1700 | gsm_dlci_close(dlci); | ||
1701 | break; | ||
1702 | case DLCI_OPENING: | ||
1703 | gsm_dlci_open(dlci); | ||
1704 | break; | ||
1705 | } | ||
1706 | break; | ||
1707 | case DM: /* DM can be valid unsolicited */ | ||
1708 | case DM|PF: | ||
1709 | if (cr) | ||
1710 | goto invalid; | ||
1711 | if (dlci == NULL) | ||
1712 | return; | ||
1713 | gsm_dlci_close(dlci); | ||
1714 | break; | ||
1715 | case UI: | ||
1716 | case UI|PF: | ||
1717 | case UIH: | ||
1718 | case UIH|PF: | ||
1719 | #if 0 | ||
1720 | if (cr) | ||
1721 | goto invalid; | ||
1722 | #endif | ||
1723 | if (dlci == NULL || dlci->state != DLCI_OPEN) { | ||
1724 | gsm_command(gsm, address, DM|PF); | ||
1725 | return; | ||
1726 | } | ||
1727 | dlci->data(dlci, gsm->buf, gsm->len); | ||
1728 | break; | ||
1729 | default: | ||
1730 | goto invalid; | ||
1731 | } | ||
1732 | return; | ||
1733 | invalid: | ||
1734 | gsm->malformed++; | ||
1735 | return; | ||
1736 | } | ||
1737 | |||
1738 | |||
1739 | /** | ||
1740 | * gsm0_receive - perform processing for non-transparency | ||
1741 | * @gsm: gsm data for this ldisc instance | ||
1742 | * @c: character | ||
1743 | * | ||
1744 | * Receive bytes in gsm mode 0 | ||
1745 | */ | ||
1746 | |||
1747 | static void gsm0_receive(struct gsm_mux *gsm, unsigned char c) | ||
1748 | { | ||
1749 | switch (gsm->state) { | ||
1750 | case GSM_SEARCH: /* SOF marker */ | ||
1751 | if (c == GSM0_SOF) { | ||
1752 | gsm->state = GSM_ADDRESS; | ||
1753 | gsm->address = 0; | ||
1754 | gsm->len = 0; | ||
1755 | gsm->fcs = INIT_FCS; | ||
1756 | } | ||
1757 | break; /* Address EA */ | ||
1758 | case GSM_ADDRESS: | ||
1759 | gsm->fcs = gsm_fcs_add(gsm->fcs, c); | ||
1760 | if (gsm_read_ea(&gsm->address, c)) | ||
1761 | gsm->state = GSM_CONTROL; | ||
1762 | break; | ||
1763 | case GSM_CONTROL: /* Control Byte */ | ||
1764 | gsm->fcs = gsm_fcs_add(gsm->fcs, c); | ||
1765 | gsm->control = c; | ||
1766 | gsm->state = GSM_LEN; | ||
1767 | break; | ||
1768 | case GSM_LEN: /* Length EA */ | ||
1769 | gsm->fcs = gsm_fcs_add(gsm->fcs, c); | ||
1770 | if (gsm_read_ea(&gsm->len, c)) { | ||
1771 | if (gsm->len > gsm->mru) { | ||
1772 | gsm->bad_size++; | ||
1773 | gsm->state = GSM_SEARCH; | ||
1774 | break; | ||
1775 | } | ||
1776 | gsm->count = 0; | ||
1777 | gsm->state = GSM_DATA; | ||
1778 | } | ||
1779 | break; | ||
1780 | case GSM_DATA: /* Data */ | ||
1781 | gsm->buf[gsm->count++] = c; | ||
1782 | if (gsm->count == gsm->len) | ||
1783 | gsm->state = GSM_FCS; | ||
1784 | break; | ||
1785 | case GSM_FCS: /* FCS follows the packet */ | ||
1786 | gsm->fcs = c; | ||
1787 | gsm_queue(gsm); | ||
1788 | /* And then back for the next frame */ | ||
1789 | gsm->state = GSM_SEARCH; | ||
1790 | break; | ||
1791 | } | ||
1792 | } | ||
1793 | |||
1794 | /** | ||
1795 | * gsm0_receive - perform processing for non-transparency | ||
1796 | * @gsm: gsm data for this ldisc instance | ||
1797 | * @c: character | ||
1798 | * | ||
1799 | * Receive bytes in mode 1 (Advanced option) | ||
1800 | */ | ||
1801 | |||
1802 | static void gsm1_receive(struct gsm_mux *gsm, unsigned char c) | ||
1803 | { | ||
1804 | if (c == GSM1_SOF) { | ||
1805 | /* EOF is only valid in frame if we have got to the data state | ||
1806 | and received at least one byte (the FCS) */ | ||
1807 | if (gsm->state == GSM_DATA && gsm->count) { | ||
1808 | /* Extract the FCS */ | ||
1809 | gsm->count--; | ||
1810 | gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->buf[gsm->count]); | ||
1811 | gsm->len = gsm->count; | ||
1812 | gsm_queue(gsm); | ||
1813 | gsm->state = GSM_START; | ||
1814 | return; | ||
1815 | } | ||
1816 | /* Any partial frame was a runt so go back to start */ | ||
1817 | if (gsm->state != GSM_START) { | ||
1818 | gsm->malformed++; | ||
1819 | gsm->state = GSM_START; | ||
1820 | } | ||
1821 | /* A SOF in GSM_START means we are still reading idling or | ||
1822 | framing bytes */ | ||
1823 | return; | ||
1824 | } | ||
1825 | |||
1826 | if (c == GSM1_ESCAPE) { | ||
1827 | gsm->escape = 1; | ||
1828 | return; | ||
1829 | } | ||
1830 | |||
1831 | /* Only an unescaped SOF gets us out of GSM search */ | ||
1832 | if (gsm->state == GSM_SEARCH) | ||
1833 | return; | ||
1834 | |||
1835 | if (gsm->escape) { | ||
1836 | c ^= GSM1_ESCAPE_BITS; | ||
1837 | gsm->escape = 0; | ||
1838 | } | ||
1839 | switch (gsm->state) { | ||
1840 | case GSM_START: /* First byte after SOF */ | ||
1841 | gsm->address = 0; | ||
1842 | gsm->state = GSM_ADDRESS; | ||
1843 | gsm->fcs = INIT_FCS; | ||
1844 | /* Drop through */ | ||
1845 | case GSM_ADDRESS: /* Address continuation */ | ||
1846 | gsm->fcs = gsm_fcs_add(gsm->fcs, c); | ||
1847 | if (gsm_read_ea(&gsm->address, c)) | ||
1848 | gsm->state = GSM_CONTROL; | ||
1849 | break; | ||
1850 | case GSM_CONTROL: /* Control Byte */ | ||
1851 | gsm->fcs = gsm_fcs_add(gsm->fcs, c); | ||
1852 | gsm->control = c; | ||
1853 | gsm->count = 0; | ||
1854 | gsm->state = GSM_DATA; | ||
1855 | break; | ||
1856 | case GSM_DATA: /* Data */ | ||
1857 | if (gsm->count > gsm->mru ) { /* Allow one for the FCS */ | ||
1858 | gsm->state = GSM_OVERRUN; | ||
1859 | gsm->bad_size++; | ||
1860 | } else | ||
1861 | gsm->buf[gsm->count++] = c; | ||
1862 | break; | ||
1863 | case GSM_OVERRUN: /* Over-long - eg a dropped SOF */ | ||
1864 | break; | ||
1865 | } | ||
1866 | } | ||
1867 | |||
1868 | /** | ||
1869 | * gsm_error - handle tty error | ||
1870 | * @gsm: ldisc data | ||
1871 | * @data: byte received (may be invalid) | ||
1872 | * @flag: error received | ||
1873 | * | ||
1874 | * Handle an error in the receipt of data for a frame. Currently we just | ||
1875 | * go back to hunting for a SOF. | ||
1876 | * | ||
1877 | * FIXME: better diagnostics ? | ||
1878 | */ | ||
1879 | |||
1880 | static void gsm_error(struct gsm_mux *gsm, | ||
1881 | unsigned char data, unsigned char flag) | ||
1882 | { | ||
1883 | gsm->state = GSM_SEARCH; | ||
1884 | gsm->io_error++; | ||
1885 | } | ||
1886 | |||
1887 | /** | ||
1888 | * gsm_cleanup_mux - generic GSM protocol cleanup | ||
1889 | * @gsm: our mux | ||
1890 | * | ||
1891 | * Clean up the bits of the mux which are the same for all framing | ||
1892 | * protocols. Remove the mux from the mux table, stop all the timers | ||
1893 | * and then shut down each device hanging up the channels as we go. | ||
1894 | */ | ||
1895 | |||
1896 | void gsm_cleanup_mux(struct gsm_mux *gsm) | ||
1897 | { | ||
1898 | int i; | ||
1899 | struct gsm_dlci *dlci = gsm->dlci[0]; | ||
1900 | struct gsm_msg *txq; | ||
1901 | |||
1902 | gsm->dead = 1; | ||
1903 | |||
1904 | spin_lock(&gsm_mux_lock); | ||
1905 | for (i = 0; i < MAX_MUX; i++) { | ||
1906 | if (gsm_mux[i] == gsm) { | ||
1907 | gsm_mux[i] = NULL; | ||
1908 | break; | ||
1909 | } | ||
1910 | } | ||
1911 | spin_unlock(&gsm_mux_lock); | ||
1912 | WARN_ON(i == MAX_MUX); | ||
1913 | |||
1914 | del_timer_sync(&gsm->t2_timer); | ||
1915 | /* Now we are sure T2 has stopped */ | ||
1916 | if (dlci) { | ||
1917 | dlci->dead = 1; | ||
1918 | gsm_dlci_begin_close(dlci); | ||
1919 | wait_event_interruptible(gsm->event, | ||
1920 | dlci->state == DLCI_CLOSED); | ||
1921 | } | ||
1922 | /* Free up any link layer users */ | ||
1923 | for (i = 0; i < NUM_DLCI; i++) | ||
1924 | if (gsm->dlci[i]) | ||
1925 | gsm_dlci_free(gsm->dlci[i]); | ||
1926 | /* Now wipe the queues */ | ||
1927 | for (txq = gsm->tx_head; txq != NULL; txq = gsm->tx_head) { | ||
1928 | gsm->tx_head = txq->next; | ||
1929 | kfree(txq); | ||
1930 | } | ||
1931 | gsm->tx_tail = NULL; | ||
1932 | } | ||
1933 | EXPORT_SYMBOL_GPL(gsm_cleanup_mux); | ||
1934 | |||
1935 | /** | ||
1936 | * gsm_activate_mux - generic GSM setup | ||
1937 | * @gsm: our mux | ||
1938 | * | ||
1939 | * Set up the bits of the mux which are the same for all framing | ||
1940 | * protocols. Add the mux to the mux table so it can be opened and | ||
1941 | * finally kick off connecting to DLCI 0 on the modem. | ||
1942 | */ | ||
1943 | |||
1944 | int gsm_activate_mux(struct gsm_mux *gsm) | ||
1945 | { | ||
1946 | struct gsm_dlci *dlci; | ||
1947 | int i = 0; | ||
1948 | |||
1949 | init_timer(&gsm->t2_timer); | ||
1950 | gsm->t2_timer.function = gsm_control_retransmit; | ||
1951 | gsm->t2_timer.data = (unsigned long)gsm; | ||
1952 | init_waitqueue_head(&gsm->event); | ||
1953 | spin_lock_init(&gsm->control_lock); | ||
1954 | spin_lock_init(&gsm->tx_lock); | ||
1955 | |||
1956 | if (gsm->encoding == 0) | ||
1957 | gsm->receive = gsm0_receive; | ||
1958 | else | ||
1959 | gsm->receive = gsm1_receive; | ||
1960 | gsm->error = gsm_error; | ||
1961 | |||
1962 | spin_lock(&gsm_mux_lock); | ||
1963 | for (i = 0; i < MAX_MUX; i++) { | ||
1964 | if (gsm_mux[i] == NULL) { | ||
1965 | gsm_mux[i] = gsm; | ||
1966 | break; | ||
1967 | } | ||
1968 | } | ||
1969 | spin_unlock(&gsm_mux_lock); | ||
1970 | if (i == MAX_MUX) | ||
1971 | return -EBUSY; | ||
1972 | |||
1973 | dlci = gsm_dlci_alloc(gsm, 0); | ||
1974 | if (dlci == NULL) | ||
1975 | return -ENOMEM; | ||
1976 | gsm->dead = 0; /* Tty opens are now permissible */ | ||
1977 | return 0; | ||
1978 | } | ||
1979 | EXPORT_SYMBOL_GPL(gsm_activate_mux); | ||
1980 | |||
1981 | /** | ||
1982 | * gsm_free_mux - free up a mux | ||
1983 | * @mux: mux to free | ||
1984 | * | ||
1985 | * Dispose of allocated resources for a dead mux. No refcounting | ||
1986 | * at present so the mux must be truely dead. | ||
1987 | */ | ||
1988 | void gsm_free_mux(struct gsm_mux *gsm) | ||
1989 | { | ||
1990 | kfree(gsm->txframe); | ||
1991 | kfree(gsm->buf); | ||
1992 | kfree(gsm); | ||
1993 | } | ||
1994 | EXPORT_SYMBOL_GPL(gsm_free_mux); | ||
1995 | |||
1996 | /** | ||
1997 | * gsm_alloc_mux - allocate a mux | ||
1998 | * | ||
1999 | * Creates a new mux ready for activation. | ||
2000 | */ | ||
2001 | |||
2002 | struct gsm_mux *gsm_alloc_mux(void) | ||
2003 | { | ||
2004 | struct gsm_mux *gsm = kzalloc(sizeof(struct gsm_mux), GFP_KERNEL); | ||
2005 | if (gsm == NULL) | ||
2006 | return NULL; | ||
2007 | gsm->buf = kmalloc(MAX_MRU + 1, GFP_KERNEL); | ||
2008 | if (gsm->buf == NULL) { | ||
2009 | kfree(gsm); | ||
2010 | return NULL; | ||
2011 | } | ||
2012 | gsm->txframe = kmalloc(2 * MAX_MRU + 2, GFP_KERNEL); | ||
2013 | if (gsm->txframe == NULL) { | ||
2014 | kfree(gsm->buf); | ||
2015 | kfree(gsm); | ||
2016 | return NULL; | ||
2017 | } | ||
2018 | spin_lock_init(&gsm->lock); | ||
2019 | |||
2020 | gsm->t1 = T1; | ||
2021 | gsm->t2 = T2; | ||
2022 | gsm->n2 = N2; | ||
2023 | gsm->ftype = UIH; | ||
2024 | gsm->initiator = 0; | ||
2025 | gsm->adaption = 1; | ||
2026 | gsm->encoding = 1; | ||
2027 | gsm->mru = 64; /* Default to encoding 1 so these should be 64 */ | ||
2028 | gsm->mtu = 64; | ||
2029 | gsm->dead = 1; /* Avoid early tty opens */ | ||
2030 | |||
2031 | return gsm; | ||
2032 | } | ||
2033 | EXPORT_SYMBOL_GPL(gsm_alloc_mux); | ||
2034 | |||
2035 | |||
2036 | |||
2037 | |||
2038 | /** | ||
2039 | * gsmld_output - write to link | ||
2040 | * @gsm: our mux | ||
2041 | * @data: bytes to output | ||
2042 | * @len: size | ||
2043 | * | ||
2044 | * Write a block of data from the GSM mux to the data channel. This | ||
2045 | * will eventually be serialized from above but at the moment isn't. | ||
2046 | */ | ||
2047 | |||
2048 | static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len) | ||
2049 | { | ||
2050 | if (tty_write_room(gsm->tty) < len) { | ||
2051 | set_bit(TTY_DO_WRITE_WAKEUP, &gsm->tty->flags); | ||
2052 | return -ENOSPC; | ||
2053 | } | ||
2054 | if (debug & 4) { | ||
2055 | printk("-->%d bytes out\n", len); | ||
2056 | hex_packet(data, len); | ||
2057 | } | ||
2058 | gsm->tty->ops->write(gsm->tty, data, len); | ||
2059 | return len; | ||
2060 | } | ||
2061 | |||
2062 | /** | ||
2063 | * gsmld_attach_gsm - mode set up | ||
2064 | * @tty: our tty structure | ||
2065 | * @gsm: our mux | ||
2066 | * | ||
2067 | * Set up the MUX for basic mode and commence connecting to the | ||
2068 | * modem. Currently called from the line discipline set up but | ||
2069 | * will need moving to an ioctl path. | ||
2070 | */ | ||
2071 | |||
2072 | static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) | ||
2073 | { | ||
2074 | int ret; | ||
2075 | |||
2076 | gsm->tty = tty_kref_get(tty); | ||
2077 | gsm->output = gsmld_output; | ||
2078 | ret = gsm_activate_mux(gsm); | ||
2079 | if (ret != 0) | ||
2080 | tty_kref_put(gsm->tty); | ||
2081 | return ret; | ||
2082 | } | ||
2083 | |||
2084 | |||
2085 | /** | ||
2086 | * gsmld_detach_gsm - stop doing 0710 mux | ||
2087 | * @tty: tty atttached to the mux | ||
2088 | * @gsm: mux | ||
2089 | * | ||
2090 | * Shutdown and then clean up the resources used by the line discipline | ||
2091 | */ | ||
2092 | |||
2093 | static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) | ||
2094 | { | ||
2095 | WARN_ON(tty != gsm->tty); | ||
2096 | gsm_cleanup_mux(gsm); | ||
2097 | tty_kref_put(gsm->tty); | ||
2098 | gsm->tty = NULL; | ||
2099 | } | ||
2100 | |||
2101 | static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, | ||
2102 | char *fp, int count) | ||
2103 | { | ||
2104 | struct gsm_mux *gsm = tty->disc_data; | ||
2105 | const unsigned char *dp; | ||
2106 | char *f; | ||
2107 | int i; | ||
2108 | char buf[64]; | ||
2109 | char flags; | ||
2110 | |||
2111 | if (debug & 4) { | ||
2112 | printk("Inbytes %dd\n", count); | ||
2113 | hex_packet(cp, count); | ||
2114 | } | ||
2115 | |||
2116 | for (i = count, dp = cp, f = fp; i; i--, dp++) { | ||
2117 | flags = *f++; | ||
2118 | switch (flags) { | ||
2119 | case TTY_NORMAL: | ||
2120 | gsm->receive(gsm, *dp); | ||
2121 | break; | ||
2122 | case TTY_OVERRUN: | ||
2123 | case TTY_BREAK: | ||
2124 | case TTY_PARITY: | ||
2125 | case TTY_FRAME: | ||
2126 | gsm->error(gsm, *dp, flags); | ||
2127 | break; | ||
2128 | default: | ||
2129 | printk(KERN_ERR "%s: unknown flag %d\n", | ||
2130 | tty_name(tty, buf), flags); | ||
2131 | break; | ||
2132 | } | ||
2133 | } | ||
2134 | /* FASYNC if needed ? */ | ||
2135 | /* If clogged call tty_throttle(tty); */ | ||
2136 | } | ||
2137 | |||
2138 | /** | ||
2139 | * gsmld_chars_in_buffer - report available bytes | ||
2140 | * @tty: tty device | ||
2141 | * | ||
2142 | * Report the number of characters buffered to be delivered to user | ||
2143 | * at this instant in time. | ||
2144 | * | ||
2145 | * Locking: gsm lock | ||
2146 | */ | ||
2147 | |||
2148 | static ssize_t gsmld_chars_in_buffer(struct tty_struct *tty) | ||
2149 | { | ||
2150 | return 0; | ||
2151 | } | ||
2152 | |||
2153 | /** | ||
2154 | * gsmld_flush_buffer - clean input queue | ||
2155 | * @tty: terminal device | ||
2156 | * | ||
2157 | * Flush the input buffer. Called when the line discipline is | ||
2158 | * being closed, when the tty layer wants the buffer flushed (eg | ||
2159 | * at hangup). | ||
2160 | */ | ||
2161 | |||
2162 | static void gsmld_flush_buffer(struct tty_struct *tty) | ||
2163 | { | ||
2164 | } | ||
2165 | |||
2166 | /** | ||
2167 | * gsmld_close - close the ldisc for this tty | ||
2168 | * @tty: device | ||
2169 | * | ||
2170 | * Called from the terminal layer when this line discipline is | ||
2171 | * being shut down, either because of a close or becsuse of a | ||
2172 | * discipline change. The function will not be called while other | ||
2173 | * ldisc methods are in progress. | ||
2174 | */ | ||
2175 | |||
2176 | static void gsmld_close(struct tty_struct *tty) | ||
2177 | { | ||
2178 | struct gsm_mux *gsm = tty->disc_data; | ||
2179 | |||
2180 | gsmld_detach_gsm(tty, gsm); | ||
2181 | |||
2182 | gsmld_flush_buffer(tty); | ||
2183 | /* Do other clean up here */ | ||
2184 | gsm_free_mux(gsm); | ||
2185 | } | ||
2186 | |||
2187 | /** | ||
2188 | * gsmld_open - open an ldisc | ||
2189 | * @tty: terminal to open | ||
2190 | * | ||
2191 | * Called when this line discipline is being attached to the | ||
2192 | * terminal device. Can sleep. Called serialized so that no | ||
2193 | * other events will occur in parallel. No further open will occur | ||
2194 | * until a close. | ||
2195 | */ | ||
2196 | |||
2197 | static int gsmld_open(struct tty_struct *tty) | ||
2198 | { | ||
2199 | struct gsm_mux *gsm; | ||
2200 | |||
2201 | if (tty->ops->write == NULL) | ||
2202 | return -EINVAL; | ||
2203 | |||
2204 | /* Attach our ldisc data */ | ||
2205 | gsm = gsm_alloc_mux(); | ||
2206 | if (gsm == NULL) | ||
2207 | return -ENOMEM; | ||
2208 | |||
2209 | tty->disc_data = gsm; | ||
2210 | tty->receive_room = 65536; | ||
2211 | |||
2212 | /* Attach the initial passive connection */ | ||
2213 | gsm->encoding = 1; | ||
2214 | return gsmld_attach_gsm(tty, gsm); | ||
2215 | } | ||
2216 | |||
2217 | /** | ||
2218 | * gsmld_write_wakeup - asynchronous I/O notifier | ||
2219 | * @tty: tty device | ||
2220 | * | ||
2221 | * Required for the ptys, serial driver etc. since processes | ||
2222 | * that attach themselves to the master and rely on ASYNC | ||
2223 | * IO must be woken up | ||
2224 | */ | ||
2225 | |||
2226 | static void gsmld_write_wakeup(struct tty_struct *tty) | ||
2227 | { | ||
2228 | struct gsm_mux *gsm = tty->disc_data; | ||
2229 | unsigned long flags; | ||
2230 | |||
2231 | /* Queue poll */ | ||
2232 | clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); | ||
2233 | gsm_data_kick(gsm); | ||
2234 | if (gsm->tx_bytes < TX_THRESH_LO) { | ||
2235 | spin_lock_irqsave(&gsm->tx_lock, flags); | ||
2236 | gsm_dlci_data_sweep(gsm); | ||
2237 | spin_unlock_irqrestore(&gsm->tx_lock, flags); | ||
2238 | } | ||
2239 | } | ||
2240 | |||
2241 | /** | ||
2242 | * gsmld_read - read function for tty | ||
2243 | * @tty: tty device | ||
2244 | * @file: file object | ||
2245 | * @buf: userspace buffer pointer | ||
2246 | * @nr: size of I/O | ||
2247 | * | ||
2248 | * Perform reads for the line discipline. We are guaranteed that the | ||
2249 | * line discipline will not be closed under us but we may get multiple | ||
2250 | * parallel readers and must handle this ourselves. We may also get | ||
2251 | * a hangup. Always called in user context, may sleep. | ||
2252 | * | ||
2253 | * This code must be sure never to sleep through a hangup. | ||
2254 | */ | ||
2255 | |||
2256 | static ssize_t gsmld_read(struct tty_struct *tty, struct file *file, | ||
2257 | unsigned char __user *buf, size_t nr) | ||
2258 | { | ||
2259 | return -EOPNOTSUPP; | ||
2260 | } | ||
2261 | |||
2262 | /** | ||
2263 | * gsmld_write - write function for tty | ||
2264 | * @tty: tty device | ||
2265 | * @file: file object | ||
2266 | * @buf: userspace buffer pointer | ||
2267 | * @nr: size of I/O | ||
2268 | * | ||
2269 | * Called when the owner of the device wants to send a frame | ||
2270 | * itself (or some other control data). The data is transferred | ||
2271 | * as-is and must be properly framed and checksummed as appropriate | ||
2272 | * by userspace. Frames are either sent whole or not at all as this | ||
2273 | * avoids pain user side. | ||
2274 | */ | ||
2275 | |||
2276 | static ssize_t gsmld_write(struct tty_struct *tty, struct file *file, | ||
2277 | const unsigned char *buf, size_t nr) | ||
2278 | { | ||
2279 | int space = tty_write_room(tty); | ||
2280 | if (space >= nr) | ||
2281 | return tty->ops->write(tty, buf, nr); | ||
2282 | set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); | ||
2283 | return -ENOBUFS; | ||
2284 | } | ||
2285 | |||
2286 | /** | ||
2287 | * gsmld_poll - poll method for N_GSM0710 | ||
2288 | * @tty: terminal device | ||
2289 | * @file: file accessing it | ||
2290 | * @wait: poll table | ||
2291 | * | ||
2292 | * Called when the line discipline is asked to poll() for data or | ||
2293 | * for special events. This code is not serialized with respect to | ||
2294 | * other events save open/close. | ||
2295 | * | ||
2296 | * This code must be sure never to sleep through a hangup. | ||
2297 | * Called without the kernel lock held - fine | ||
2298 | */ | ||
2299 | |||
2300 | static unsigned int gsmld_poll(struct tty_struct *tty, struct file *file, | ||
2301 | poll_table *wait) | ||
2302 | { | ||
2303 | unsigned int mask = 0; | ||
2304 | struct gsm_mux *gsm = tty->disc_data; | ||
2305 | |||
2306 | poll_wait(file, &tty->read_wait, wait); | ||
2307 | poll_wait(file, &tty->write_wait, wait); | ||
2308 | if (tty_hung_up_p(file)) | ||
2309 | mask |= POLLHUP; | ||
2310 | if (!tty_is_writelocked(tty) && tty_write_room(tty) > 0) | ||
2311 | mask |= POLLOUT | POLLWRNORM; | ||
2312 | if (gsm->dead) | ||
2313 | mask |= POLLHUP; | ||
2314 | return mask; | ||
2315 | } | ||
2316 | |||
2317 | static int gsmld_config(struct tty_struct *tty, struct gsm_mux *gsm, | ||
2318 | struct gsm_config *c) | ||
2319 | { | ||
2320 | int need_close = 0; | ||
2321 | int need_restart = 0; | ||
2322 | |||
2323 | /* Stuff we don't support yet - UI or I frame transport, windowing */ | ||
2324 | if ((c->adaption !=1 && c->adaption != 2) || c->k) | ||
2325 | return -EOPNOTSUPP; | ||
2326 | /* Check the MRU/MTU range looks sane */ | ||
2327 | if (c->mru > MAX_MRU || c->mtu > MAX_MTU || c->mru < 8 || c->mtu < 8) | ||
2328 | return -EINVAL; | ||
2329 | if (c->n2 < 3) | ||
2330 | return -EINVAL; | ||
2331 | if (c->encapsulation > 1) /* Basic, advanced, no I */ | ||
2332 | return -EINVAL; | ||
2333 | if (c->initiator > 1) | ||
2334 | return -EINVAL; | ||
2335 | if (c->i == 0 || c->i > 2) /* UIH and UI only */ | ||
2336 | return -EINVAL; | ||
2337 | /* | ||
2338 | * See what is needed for reconfiguration | ||
2339 | */ | ||
2340 | |||
2341 | /* Timing fields */ | ||
2342 | if (c->t1 != 0 && c->t1 != gsm->t1) | ||
2343 | need_restart = 1; | ||
2344 | if (c->t2 != 0 && c->t2 != gsm->t2) | ||
2345 | need_restart = 1; | ||
2346 | if (c->encapsulation != gsm->encoding) | ||
2347 | need_restart = 1; | ||
2348 | if (c->adaption != gsm->adaption) | ||
2349 | need_restart = 1; | ||
2350 | /* Requires care */ | ||
2351 | if (c->initiator != gsm->initiator) | ||
2352 | need_close = 1; | ||
2353 | if (c->mru != gsm->mru) | ||
2354 | need_restart = 1; | ||
2355 | if (c->mtu != gsm->mtu) | ||
2356 | need_restart = 1; | ||
2357 | |||
2358 | /* | ||
2359 | * Close down what is needed, restart and initiate the new | ||
2360 | * configuration | ||
2361 | */ | ||
2362 | |||
2363 | if (need_close || need_restart) { | ||
2364 | gsm_dlci_begin_close(gsm->dlci[0]); | ||
2365 | /* This will timeout if the link is down due to N2 expiring */ | ||
2366 | wait_event_interruptible(gsm->event, | ||
2367 | gsm->dlci[0]->state == DLCI_CLOSED); | ||
2368 | if (signal_pending(current)) | ||
2369 | return -EINTR; | ||
2370 | } | ||
2371 | if (need_restart) | ||
2372 | gsm_cleanup_mux(gsm); | ||
2373 | |||
2374 | gsm->initiator = c->initiator; | ||
2375 | gsm->mru = c->mru; | ||
2376 | gsm->encoding = c->encapsulation; | ||
2377 | gsm->adaption = c->adaption; | ||
2378 | |||
2379 | if (c->i == 1) | ||
2380 | gsm->ftype = UIH; | ||
2381 | else if (c->i == 2) | ||
2382 | gsm->ftype = UI; | ||
2383 | |||
2384 | if (c->t1) | ||
2385 | gsm->t1 = c->t1; | ||
2386 | if (c->t2) | ||
2387 | gsm->t2 = c->t2; | ||
2388 | |||
2389 | /* FIXME: We need to separate activation/deactivation from adding | ||
2390 | and removing from the mux array */ | ||
2391 | if (need_restart) | ||
2392 | gsm_activate_mux(gsm); | ||
2393 | if (gsm->initiator && need_close) | ||
2394 | gsm_dlci_begin_open(gsm->dlci[0]); | ||
2395 | return 0; | ||
2396 | } | ||
2397 | |||
2398 | static int gsmld_ioctl(struct tty_struct *tty, struct file *file, | ||
2399 | unsigned int cmd, unsigned long arg) | ||
2400 | { | ||
2401 | struct gsm_config c; | ||
2402 | struct gsm_mux *gsm = tty->disc_data; | ||
2403 | |||
2404 | switch (cmd) { | ||
2405 | case GSMIOC_GETCONF: | ||
2406 | memset(&c, 0, sizeof(c)); | ||
2407 | c.adaption = gsm->adaption; | ||
2408 | c.encapsulation = gsm->encoding; | ||
2409 | c.initiator = gsm->initiator; | ||
2410 | c.t1 = gsm->t1; | ||
2411 | c.t2 = gsm->t2; | ||
2412 | c.t3 = 0; /* Not supported */ | ||
2413 | c.n2 = gsm->n2; | ||
2414 | if (gsm->ftype == UIH) | ||
2415 | c.i = 1; | ||
2416 | else | ||
2417 | c.i = 2; | ||
2418 | printk("Ftype %d i %d\n", gsm->ftype, c.i); | ||
2419 | c.mru = gsm->mru; | ||
2420 | c.mtu = gsm->mtu; | ||
2421 | c.k = 0; | ||
2422 | if (copy_to_user((void *)arg, &c, sizeof(c))) | ||
2423 | return -EFAULT; | ||
2424 | return 0; | ||
2425 | case GSMIOC_SETCONF: | ||
2426 | if (copy_from_user(&c, (void *)arg, sizeof(c))) | ||
2427 | return -EFAULT; | ||
2428 | return gsmld_config(tty, gsm, &c); | ||
2429 | default: | ||
2430 | return n_tty_ioctl_helper(tty, file, cmd, arg); | ||
2431 | } | ||
2432 | } | ||
2433 | |||
2434 | |||
2435 | /* Line discipline for real tty */ | ||
2436 | struct tty_ldisc_ops tty_ldisc_packet = { | ||
2437 | .owner = THIS_MODULE, | ||
2438 | .magic = TTY_LDISC_MAGIC, | ||
2439 | .name = "n_gsm", | ||
2440 | .open = gsmld_open, | ||
2441 | .close = gsmld_close, | ||
2442 | .flush_buffer = gsmld_flush_buffer, | ||
2443 | .chars_in_buffer = gsmld_chars_in_buffer, | ||
2444 | .read = gsmld_read, | ||
2445 | .write = gsmld_write, | ||
2446 | .ioctl = gsmld_ioctl, | ||
2447 | .poll = gsmld_poll, | ||
2448 | .receive_buf = gsmld_receive_buf, | ||
2449 | .write_wakeup = gsmld_write_wakeup | ||
2450 | }; | ||
2451 | |||
2452 | /* | ||
2453 | * Virtual tty side | ||
2454 | */ | ||
2455 | |||
2456 | #define TX_SIZE 512 | ||
2457 | |||
2458 | static int gsmtty_modem_update(struct gsm_dlci *dlci, u8 brk) | ||
2459 | { | ||
2460 | u8 modembits[5]; | ||
2461 | struct gsm_control *ctrl; | ||
2462 | int len = 2; | ||
2463 | |||
2464 | if (brk) | ||
2465 | len++; | ||
2466 | |||
2467 | modembits[0] = len << 1 | EA; /* Data bytes */ | ||
2468 | modembits[1] = dlci->addr << 2 | 3; /* DLCI, EA, 1 */ | ||
2469 | modembits[2] = gsm_encode_modem(dlci) << 1 | EA; | ||
2470 | if (brk) | ||
2471 | modembits[3] = brk << 4 | 2 | EA; /* Valid, EA */ | ||
2472 | ctrl = gsm_control_send(dlci->gsm, CMD_MSC, modembits, len + 1); | ||
2473 | if (ctrl == NULL) | ||
2474 | return -ENOMEM; | ||
2475 | return gsm_control_wait(dlci->gsm, ctrl); | ||
2476 | } | ||
2477 | |||
2478 | static int gsm_carrier_raised(struct tty_port *port) | ||
2479 | { | ||
2480 | struct gsm_dlci *dlci = container_of(port, struct gsm_dlci, port); | ||
2481 | /* Not yet open so no carrier info */ | ||
2482 | if (dlci->state != DLCI_OPEN) | ||
2483 | return 0; | ||
2484 | if (debug & 2) | ||
2485 | return 1; | ||
2486 | return dlci->modem_rx & TIOCM_CD; | ||
2487 | } | ||
2488 | |||
2489 | static void gsm_dtr_rts(struct tty_port *port, int onoff) | ||
2490 | { | ||
2491 | struct gsm_dlci *dlci = container_of(port, struct gsm_dlci, port); | ||
2492 | unsigned int modem_tx = dlci->modem_tx; | ||
2493 | if (onoff) | ||
2494 | modem_tx |= TIOCM_DTR | TIOCM_RTS; | ||
2495 | else | ||
2496 | modem_tx &= ~(TIOCM_DTR | TIOCM_RTS); | ||
2497 | if (modem_tx != dlci->modem_tx) { | ||
2498 | dlci->modem_tx = modem_tx; | ||
2499 | gsmtty_modem_update(dlci, 0); | ||
2500 | } | ||
2501 | } | ||
2502 | |||
2503 | static const struct tty_port_operations gsm_port_ops = { | ||
2504 | .carrier_raised = gsm_carrier_raised, | ||
2505 | .dtr_rts = gsm_dtr_rts, | ||
2506 | }; | ||
2507 | |||
2508 | |||
2509 | static int gsmtty_open(struct tty_struct *tty, struct file *filp) | ||
2510 | { | ||
2511 | struct gsm_mux *gsm; | ||
2512 | struct gsm_dlci *dlci; | ||
2513 | struct tty_port *port; | ||
2514 | unsigned int line = tty->index; | ||
2515 | unsigned int mux = line >> 6; | ||
2516 | |||
2517 | line = line & 0x3F; | ||
2518 | |||
2519 | if (mux >= MAX_MUX) | ||
2520 | return -ENXIO; | ||
2521 | /* FIXME: we need to lock gsm_mux for lifetimes of ttys eventually */ | ||
2522 | if (gsm_mux[mux] == NULL) | ||
2523 | return -EUNATCH; | ||
2524 | if (line == 0 || line > 61) /* 62/63 reserved */ | ||
2525 | return -ECHRNG; | ||
2526 | gsm = gsm_mux[mux]; | ||
2527 | if (gsm->dead) | ||
2528 | return -EL2HLT; | ||
2529 | dlci = gsm->dlci[line]; | ||
2530 | if (dlci == NULL) | ||
2531 | dlci = gsm_dlci_alloc(gsm, line); | ||
2532 | if (dlci == NULL) | ||
2533 | return -ENOMEM; | ||
2534 | port = &dlci->port; | ||
2535 | port->count++; | ||
2536 | tty->driver_data = dlci; | ||
2537 | tty_port_tty_set(port, tty); | ||
2538 | |||
2539 | dlci->modem_rx = 0; | ||
2540 | /* We could in theory open and close before we wait - eg if we get | ||
2541 | a DM straight back. This is ok as that will have caused a hangup */ | ||
2542 | set_bit(ASYNCB_INITIALIZED, &port->flags); | ||
2543 | /* Start sending off SABM messages */ | ||
2544 | gsm_dlci_begin_open(dlci); | ||
2545 | /* And wait for virtual carrier */ | ||
2546 | return tty_port_block_til_ready(port, tty, filp); | ||
2547 | } | ||
2548 | |||
2549 | static void gsmtty_close(struct tty_struct *tty, struct file *filp) | ||
2550 | { | ||
2551 | struct gsm_dlci *dlci = tty->driver_data; | ||
2552 | if (dlci == NULL) | ||
2553 | return; | ||
2554 | if (tty_port_close_start(&dlci->port, tty, filp) == 0) | ||
2555 | return; | ||
2556 | gsm_dlci_begin_close(dlci); | ||
2557 | tty_port_close_end(&dlci->port, tty); | ||
2558 | tty_port_tty_set(&dlci->port, NULL); | ||
2559 | } | ||
2560 | |||
2561 | static void gsmtty_hangup(struct tty_struct *tty) | ||
2562 | { | ||
2563 | struct gsm_dlci *dlci = tty->driver_data; | ||
2564 | tty_port_hangup(&dlci->port); | ||
2565 | gsm_dlci_begin_close(dlci); | ||
2566 | } | ||
2567 | |||
2568 | static int gsmtty_write(struct tty_struct *tty, const unsigned char *buf, | ||
2569 | int len) | ||
2570 | { | ||
2571 | struct gsm_dlci *dlci = tty->driver_data; | ||
2572 | /* Stuff the bytes into the fifo queue */ | ||
2573 | int sent = kfifo_in_locked(dlci->fifo, buf, len, &dlci->lock); | ||
2574 | /* Need to kick the channel */ | ||
2575 | gsm_dlci_data_kick(dlci); | ||
2576 | return sent; | ||
2577 | } | ||
2578 | |||
2579 | static int gsmtty_write_room(struct tty_struct *tty) | ||
2580 | { | ||
2581 | struct gsm_dlci *dlci = tty->driver_data; | ||
2582 | return TX_SIZE - kfifo_len(dlci->fifo); | ||
2583 | } | ||
2584 | |||
2585 | static int gsmtty_chars_in_buffer(struct tty_struct *tty) | ||
2586 | { | ||
2587 | struct gsm_dlci *dlci = tty->driver_data; | ||
2588 | return kfifo_len(dlci->fifo); | ||
2589 | } | ||
2590 | |||
2591 | static void gsmtty_flush_buffer(struct tty_struct *tty) | ||
2592 | { | ||
2593 | struct gsm_dlci *dlci = tty->driver_data; | ||
2594 | /* Caution needed: If we implement reliable transport classes | ||
2595 | then the data being transmitted can't simply be junked once | ||
2596 | it has first hit the stack. Until then we can just blow it | ||
2597 | away */ | ||
2598 | kfifo_reset(dlci->fifo); | ||
2599 | /* Need to unhook this DLCI from the transmit queue logic */ | ||
2600 | } | ||
2601 | |||
2602 | static void gsmtty_wait_until_sent(struct tty_struct *tty, int timeout) | ||
2603 | { | ||
2604 | /* The FIFO handles the queue so the kernel will do the right | ||
2605 | thing waiting on chars_in_buffer before calling us. No work | ||
2606 | to do here */ | ||
2607 | } | ||
2608 | |||
2609 | static int gsmtty_tiocmget(struct tty_struct *tty, struct file *filp) | ||
2610 | { | ||
2611 | struct gsm_dlci *dlci = tty->driver_data; | ||
2612 | return dlci->modem_rx; | ||
2613 | } | ||
2614 | |||
2615 | static int gsmtty_tiocmset(struct tty_struct *tty, struct file *filp, | ||
2616 | unsigned int set, unsigned int clear) | ||
2617 | { | ||
2618 | struct gsm_dlci *dlci = tty->driver_data; | ||
2619 | unsigned int modem_tx = dlci->modem_tx; | ||
2620 | |||
2621 | modem_tx &= clear; | ||
2622 | modem_tx |= set; | ||
2623 | |||
2624 | if (modem_tx != dlci->modem_tx) { | ||
2625 | dlci->modem_tx = modem_tx; | ||
2626 | return gsmtty_modem_update(dlci, 0); | ||
2627 | } | ||
2628 | return 0; | ||
2629 | } | ||
2630 | |||
2631 | |||
2632 | static int gsmtty_ioctl(struct tty_struct *tty, struct file *filp, | ||
2633 | unsigned int cmd, unsigned long arg) | ||
2634 | { | ||
2635 | return -ENOIOCTLCMD; | ||
2636 | } | ||
2637 | |||
2638 | static void gsmtty_set_termios(struct tty_struct *tty, struct ktermios *old) | ||
2639 | { | ||
2640 | /* For the moment its fixed. In actual fact the speed information | ||
2641 | for the virtual channel can be propogated in both directions by | ||
2642 | the RPN control message. This however rapidly gets nasty as we | ||
2643 | then have to remap modem signals each way according to whether | ||
2644 | our virtual cable is null modem etc .. */ | ||
2645 | tty_termios_copy_hw(tty->termios, old); | ||
2646 | } | ||
2647 | |||
2648 | static void gsmtty_throttle(struct tty_struct *tty) | ||
2649 | { | ||
2650 | struct gsm_dlci *dlci = tty->driver_data; | ||
2651 | if (tty->termios->c_cflag & CRTSCTS) | ||
2652 | dlci->modem_tx &= ~TIOCM_DTR; | ||
2653 | dlci->throttled = 1; | ||
2654 | /* Send an MSC with DTR cleared */ | ||
2655 | gsmtty_modem_update(dlci, 0); | ||
2656 | } | ||
2657 | |||
2658 | static void gsmtty_unthrottle(struct tty_struct *tty) | ||
2659 | { | ||
2660 | struct gsm_dlci *dlci = tty->driver_data; | ||
2661 | if (tty->termios->c_cflag & CRTSCTS) | ||
2662 | dlci->modem_tx |= TIOCM_DTR; | ||
2663 | dlci->throttled = 0; | ||
2664 | /* Send an MSC with DTR set */ | ||
2665 | gsmtty_modem_update(dlci, 0); | ||
2666 | } | ||
2667 | |||
2668 | static int gsmtty_break_ctl(struct tty_struct *tty, int state) | ||
2669 | { | ||
2670 | struct gsm_dlci *dlci = tty->driver_data; | ||
2671 | int encode = 0; /* Off */ | ||
2672 | |||
2673 | if (state == -1) /* "On indefinitely" - we can't encode this | ||
2674 | properly */ | ||
2675 | encode = 0x0F; | ||
2676 | else if (state > 0) { | ||
2677 | encode = state / 200; /* mS to encoding */ | ||
2678 | if (encode > 0x0F) | ||
2679 | encode = 0x0F; /* Best effort */ | ||
2680 | } | ||
2681 | return gsmtty_modem_update(dlci, encode); | ||
2682 | } | ||
2683 | |||
2684 | static struct tty_driver *gsm_tty_driver; | ||
2685 | |||
2686 | /* Virtual ttys for the demux */ | ||
2687 | static const struct tty_operations gsmtty_ops = { | ||
2688 | .open = gsmtty_open, | ||
2689 | .close = gsmtty_close, | ||
2690 | .write = gsmtty_write, | ||
2691 | .write_room = gsmtty_write_room, | ||
2692 | .chars_in_buffer = gsmtty_chars_in_buffer, | ||
2693 | .flush_buffer = gsmtty_flush_buffer, | ||
2694 | .ioctl = gsmtty_ioctl, | ||
2695 | .throttle = gsmtty_throttle, | ||
2696 | .unthrottle = gsmtty_unthrottle, | ||
2697 | .set_termios = gsmtty_set_termios, | ||
2698 | .hangup = gsmtty_hangup, | ||
2699 | .wait_until_sent = gsmtty_wait_until_sent, | ||
2700 | .tiocmget = gsmtty_tiocmget, | ||
2701 | .tiocmset = gsmtty_tiocmset, | ||
2702 | .break_ctl = gsmtty_break_ctl, | ||
2703 | }; | ||
2704 | |||
2705 | |||
2706 | |||
2707 | static int __init gsm_init(void) | ||
2708 | { | ||
2709 | /* Fill in our line protocol discipline, and register it */ | ||
2710 | int status = tty_register_ldisc(N_GSM0710, &tty_ldisc_packet); | ||
2711 | if (status != 0) { | ||
2712 | printk(KERN_ERR "n_gsm: can't register line discipline (err = %d)\n", status); | ||
2713 | return status; | ||
2714 | } | ||
2715 | |||
2716 | gsm_tty_driver = alloc_tty_driver(256); | ||
2717 | if (!gsm_tty_driver) { | ||
2718 | tty_unregister_ldisc(N_GSM0710); | ||
2719 | printk(KERN_ERR "gsm_init: tty allocation failed.\n"); | ||
2720 | return -EINVAL; | ||
2721 | } | ||
2722 | gsm_tty_driver->owner = THIS_MODULE; | ||
2723 | gsm_tty_driver->driver_name = "gsmtty"; | ||
2724 | gsm_tty_driver->name = "gsmtty"; | ||
2725 | gsm_tty_driver->major = 0; /* Dynamic */ | ||
2726 | gsm_tty_driver->minor_start = 0; | ||
2727 | gsm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
2728 | gsm_tty_driver->subtype = SERIAL_TYPE_NORMAL; | ||
2729 | gsm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | ||
2730 | | TTY_DRIVER_HARDWARE_BREAK; | ||
2731 | gsm_tty_driver->init_termios = tty_std_termios; | ||
2732 | /* Fixme */ | ||
2733 | gsm_tty_driver->init_termios.c_lflag &= ~ECHO; | ||
2734 | tty_set_operations(gsm_tty_driver, &gsmtty_ops); | ||
2735 | |||
2736 | spin_lock_init(&gsm_mux_lock); | ||
2737 | |||
2738 | if (tty_register_driver(gsm_tty_driver)) { | ||
2739 | put_tty_driver(gsm_tty_driver); | ||
2740 | tty_unregister_ldisc(N_GSM0710); | ||
2741 | printk(KERN_ERR "gsm_init: tty registration failed.\n"); | ||
2742 | return -EBUSY; | ||
2743 | } | ||
2744 | printk(KERN_INFO "gsm_init: loaded as %d,%d.\n", gsm_tty_driver->major, gsm_tty_driver->minor_start); | ||
2745 | return 0; | ||
2746 | } | ||
2747 | |||
2748 | static void __exit gsm_exit(void) | ||
2749 | { | ||
2750 | int status = tty_unregister_ldisc(N_GSM0710); | ||
2751 | if (status != 0) | ||
2752 | printk(KERN_ERR "n_gsm: can't unregister line discipline (err = %d)\n", status); | ||
2753 | tty_unregister_driver(gsm_tty_driver); | ||
2754 | put_tty_driver(gsm_tty_driver); | ||
2755 | printk(KERN_INFO "gsm_init: unloaded.\n"); | ||
2756 | } | ||
2757 | |||
2758 | module_init(gsm_init); | ||
2759 | module_exit(gsm_exit); | ||
2760 | |||
2761 | |||
2762 | MODULE_LICENSE("GPL"); | ||
2763 | MODULE_ALIAS_LDISC(N_GSM0710); | ||
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index c68118efad84..47d32281032c 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c | |||
@@ -598,18 +598,18 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, | |||
598 | return -EFAULT; | 598 | return -EFAULT; |
599 | } | 599 | } |
600 | 600 | ||
601 | lock_kernel(); | 601 | tty_lock(); |
602 | 602 | ||
603 | for (;;) { | 603 | for (;;) { |
604 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { | 604 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { |
605 | unlock_kernel(); | 605 | tty_unlock(); |
606 | return -EIO; | 606 | return -EIO; |
607 | } | 607 | } |
608 | 608 | ||
609 | n_hdlc = tty2n_hdlc (tty); | 609 | n_hdlc = tty2n_hdlc (tty); |
610 | if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC || | 610 | if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC || |
611 | tty != n_hdlc->tty) { | 611 | tty != n_hdlc->tty) { |
612 | unlock_kernel(); | 612 | tty_unlock(); |
613 | return 0; | 613 | return 0; |
614 | } | 614 | } |
615 | 615 | ||
@@ -619,13 +619,13 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, | |||
619 | 619 | ||
620 | /* no data */ | 620 | /* no data */ |
621 | if (file->f_flags & O_NONBLOCK) { | 621 | if (file->f_flags & O_NONBLOCK) { |
622 | unlock_kernel(); | 622 | tty_unlock(); |
623 | return -EAGAIN; | 623 | return -EAGAIN; |
624 | } | 624 | } |
625 | 625 | ||
626 | interruptible_sleep_on (&tty->read_wait); | 626 | interruptible_sleep_on (&tty->read_wait); |
627 | if (signal_pending(current)) { | 627 | if (signal_pending(current)) { |
628 | unlock_kernel(); | 628 | tty_unlock(); |
629 | return -EINTR; | 629 | return -EINTR; |
630 | } | 630 | } |
631 | } | 631 | } |
@@ -648,7 +648,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, | |||
648 | kfree(rbuf); | 648 | kfree(rbuf); |
649 | else | 649 | else |
650 | n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf); | 650 | n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf); |
651 | unlock_kernel(); | 651 | tty_unlock(); |
652 | return ret; | 652 | return ret; |
653 | 653 | ||
654 | } /* end of n_hdlc_tty_read() */ | 654 | } /* end of n_hdlc_tty_read() */ |
@@ -691,7 +691,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, | |||
691 | count = maxframe; | 691 | count = maxframe; |
692 | } | 692 | } |
693 | 693 | ||
694 | lock_kernel(); | 694 | tty_lock(); |
695 | 695 | ||
696 | add_wait_queue(&tty->write_wait, &wait); | 696 | add_wait_queue(&tty->write_wait, &wait); |
697 | set_current_state(TASK_INTERRUPTIBLE); | 697 | set_current_state(TASK_INTERRUPTIBLE); |
@@ -731,7 +731,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, | |||
731 | n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf); | 731 | n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf); |
732 | n_hdlc_send_frames(n_hdlc,tty); | 732 | n_hdlc_send_frames(n_hdlc,tty); |
733 | } | 733 | } |
734 | unlock_kernel(); | 734 | tty_unlock(); |
735 | return error; | 735 | return error; |
736 | 736 | ||
737 | } /* end of n_hdlc_tty_write() */ | 737 | } /* end of n_hdlc_tty_write() */ |
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index c1d8b54c816d..88dda0c45ee0 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c | |||
@@ -4,7 +4,6 @@ | |||
4 | * Copyright by | 4 | * Copyright by |
5 | * Philips Automation Projects | 5 | * Philips Automation Projects |
6 | * Kassel (Germany) | 6 | * Kassel (Germany) |
7 | * http://www.pap-philips.de | ||
8 | * ----------------------------------------------------------- | 7 | * ----------------------------------------------------------- |
9 | * This software may be used and distributed according to the terms of | 8 | * This software may be used and distributed according to the terms of |
10 | * the GNU General Public License, incorporated herein by reference. | 9 | * the GNU General Public License, incorporated herein by reference. |
@@ -1067,7 +1066,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1067 | 1066 | ||
1068 | TRACE_L("read()"); | 1067 | TRACE_L("read()"); |
1069 | 1068 | ||
1070 | lock_kernel(); | 1069 | tty_lock(); |
1071 | 1070 | ||
1072 | pClient = findClient(pInfo, task_pid(current)); | 1071 | pClient = findClient(pInfo, task_pid(current)); |
1073 | if (pClient) { | 1072 | if (pClient) { |
@@ -1079,7 +1078,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1079 | goto unlock; | 1078 | goto unlock; |
1080 | } | 1079 | } |
1081 | /* block until there is a message: */ | 1080 | /* block until there is a message: */ |
1082 | wait_event_interruptible(pInfo->read_wait, | 1081 | wait_event_interruptible_tty(pInfo->read_wait, |
1083 | (pMsg = remove_msg(pInfo, pClient))); | 1082 | (pMsg = remove_msg(pInfo, pClient))); |
1084 | } | 1083 | } |
1085 | 1084 | ||
@@ -1109,7 +1108,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1109 | } | 1108 | } |
1110 | ret = -EPERM; | 1109 | ret = -EPERM; |
1111 | unlock: | 1110 | unlock: |
1112 | unlock_kernel(); | 1111 | tty_unlock(); |
1113 | return ret; | 1112 | return ret; |
1114 | } | 1113 | } |
1115 | 1114 | ||
@@ -1158,7 +1157,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, | |||
1158 | pHeader->locks = 0; | 1157 | pHeader->locks = 0; |
1159 | pHeader->owner = NULL; | 1158 | pHeader->owner = NULL; |
1160 | 1159 | ||
1161 | lock_kernel(); | 1160 | tty_lock(); |
1162 | 1161 | ||
1163 | pClient = findClient(pInfo, task_pid(current)); | 1162 | pClient = findClient(pInfo, task_pid(current)); |
1164 | if (pClient) { | 1163 | if (pClient) { |
@@ -1177,7 +1176,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, | |||
1177 | add_tx_queue(pInfo, pHeader); | 1176 | add_tx_queue(pInfo, pHeader); |
1178 | trigger_transmit(pInfo); | 1177 | trigger_transmit(pInfo); |
1179 | 1178 | ||
1180 | unlock_kernel(); | 1179 | tty_unlock(); |
1181 | 1180 | ||
1182 | return 0; | 1181 | return 0; |
1183 | } | 1182 | } |
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 2e50f4dfc79c..428f4fe0b5f7 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <linux/audit.h> | 48 | #include <linux/audit.h> |
49 | #include <linux/file.h> | 49 | #include <linux/file.h> |
50 | #include <linux/uaccess.h> | 50 | #include <linux/uaccess.h> |
51 | #include <linux/module.h> | ||
51 | 52 | ||
52 | #include <asm/system.h> | 53 | #include <asm/system.h> |
53 | 54 | ||
@@ -1101,6 +1102,11 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) | |||
1101 | if (I_IUCLC(tty) && L_IEXTEN(tty)) | 1102 | if (I_IUCLC(tty) && L_IEXTEN(tty)) |
1102 | c = tolower(c); | 1103 | c = tolower(c); |
1103 | 1104 | ||
1105 | if (L_EXTPROC(tty)) { | ||
1106 | put_tty_queue(c, tty); | ||
1107 | return; | ||
1108 | } | ||
1109 | |||
1104 | if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && | 1110 | if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && |
1105 | I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty) && | 1111 | I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty) && |
1106 | c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty)) { | 1112 | c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty)) { |
@@ -1408,7 +1414,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, | |||
1408 | 1414 | ||
1409 | n_tty_set_room(tty); | 1415 | n_tty_set_room(tty); |
1410 | 1416 | ||
1411 | if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) { | 1417 | if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) || |
1418 | L_EXTPROC(tty)) { | ||
1412 | kill_fasync(&tty->fasync, SIGIO, POLL_IN); | 1419 | kill_fasync(&tty->fasync, SIGIO, POLL_IN); |
1413 | if (waitqueue_active(&tty->read_wait)) | 1420 | if (waitqueue_active(&tty->read_wait)) |
1414 | wake_up_interruptible(&tty->read_wait); | 1421 | wake_up_interruptible(&tty->read_wait); |
@@ -1584,7 +1591,7 @@ static int n_tty_open(struct tty_struct *tty) | |||
1584 | static inline int input_available_p(struct tty_struct *tty, int amt) | 1591 | static inline int input_available_p(struct tty_struct *tty, int amt) |
1585 | { | 1592 | { |
1586 | tty_flush_to_ldisc(tty); | 1593 | tty_flush_to_ldisc(tty); |
1587 | if (tty->icanon) { | 1594 | if (tty->icanon && !L_EXTPROC(tty)) { |
1588 | if (tty->canon_data) | 1595 | if (tty->canon_data) |
1589 | return 1; | 1596 | return 1; |
1590 | } else if (tty->read_cnt >= (amt ? amt : 1)) | 1597 | } else if (tty->read_cnt >= (amt ? amt : 1)) |
@@ -1631,6 +1638,11 @@ static int copy_from_read_buf(struct tty_struct *tty, | |||
1631 | spin_lock_irqsave(&tty->read_lock, flags); | 1638 | spin_lock_irqsave(&tty->read_lock, flags); |
1632 | tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1); | 1639 | tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1); |
1633 | tty->read_cnt -= n; | 1640 | tty->read_cnt -= n; |
1641 | /* Turn single EOF into zero-length read */ | ||
1642 | if (L_EXTPROC(tty) && tty->icanon && n == 1) { | ||
1643 | if (!tty->read_cnt && (*b)[n-1] == EOF_CHAR(tty)) | ||
1644 | n--; | ||
1645 | } | ||
1634 | spin_unlock_irqrestore(&tty->read_lock, flags); | 1646 | spin_unlock_irqrestore(&tty->read_lock, flags); |
1635 | *b += n; | 1647 | *b += n; |
1636 | *nr -= n; | 1648 | *nr -= n; |
@@ -1811,7 +1823,7 @@ do_it_again: | |||
1811 | nr--; | 1823 | nr--; |
1812 | } | 1824 | } |
1813 | 1825 | ||
1814 | if (tty->icanon) { | 1826 | if (tty->icanon && !L_EXTPROC(tty)) { |
1815 | /* N.B. avoid overrun if nr == 0 */ | 1827 | /* N.B. avoid overrun if nr == 0 */ |
1816 | while (nr && tty->read_cnt) { | 1828 | while (nr && tty->read_cnt) { |
1817 | int eol; | 1829 | int eol; |
@@ -2091,3 +2103,19 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = { | |||
2091 | .receive_buf = n_tty_receive_buf, | 2103 | .receive_buf = n_tty_receive_buf, |
2092 | .write_wakeup = n_tty_write_wakeup | 2104 | .write_wakeup = n_tty_write_wakeup |
2093 | }; | 2105 | }; |
2106 | |||
2107 | /** | ||
2108 | * n_tty_inherit_ops - inherit N_TTY methods | ||
2109 | * @ops: struct tty_ldisc_ops where to save N_TTY methods | ||
2110 | * | ||
2111 | * Used by a generic struct tty_ldisc_ops to easily inherit N_TTY | ||
2112 | * methods. | ||
2113 | */ | ||
2114 | |||
2115 | void n_tty_inherit_ops(struct tty_ldisc_ops *ops) | ||
2116 | { | ||
2117 | *ops = tty_ldisc_N_TTY; | ||
2118 | ops->owner = NULL; | ||
2119 | ops->refcount = ops->flags = 0; | ||
2120 | } | ||
2121 | EXPORT_SYMBOL_GPL(n_tty_inherit_ops); | ||
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index 2ad7d37afbd0..dd3f9b1f11b4 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c | |||
@@ -55,6 +55,7 @@ | |||
55 | #include <linux/init.h> | 55 | #include <linux/init.h> |
56 | #include <linux/kfifo.h> | 56 | #include <linux/kfifo.h> |
57 | #include <linux/uaccess.h> | 57 | #include <linux/uaccess.h> |
58 | #include <linux/slab.h> | ||
58 | #include <asm/byteorder.h> | 59 | #include <asm/byteorder.h> |
59 | 60 | ||
60 | #include <linux/delay.h> | 61 | #include <linux/delay.h> |
@@ -136,10 +137,6 @@ static int debug; | |||
136 | #define RECEIVE_BUF_MAX 4 | 137 | #define RECEIVE_BUF_MAX 4 |
137 | 138 | ||
138 | 139 | ||
139 | /* Define all types of vendors and devices to support */ | ||
140 | #define VENDOR1 0x1931 /* Vendor Option */ | ||
141 | #define DEVICE1 0x000c /* HSDPA card */ | ||
142 | |||
143 | #define R_IIR 0x0000 /* Interrupt Identity Register */ | 140 | #define R_IIR 0x0000 /* Interrupt Identity Register */ |
144 | #define R_FCR 0x0000 /* Flow Control Register */ | 141 | #define R_FCR 0x0000 /* Flow Control Register */ |
145 | #define R_IER 0x0004 /* Interrupt Enable Register */ | 142 | #define R_IER 0x0004 /* Interrupt Enable Register */ |
@@ -371,6 +368,8 @@ struct port { | |||
371 | struct mutex tty_sem; | 368 | struct mutex tty_sem; |
372 | wait_queue_head_t tty_wait; | 369 | wait_queue_head_t tty_wait; |
373 | struct async_icount tty_icount; | 370 | struct async_icount tty_icount; |
371 | |||
372 | struct nozomi *dc; | ||
374 | }; | 373 | }; |
375 | 374 | ||
376 | /* Private data one for each card in the system */ | 375 | /* Private data one for each card in the system */ |
@@ -405,7 +404,7 @@ struct buffer { | |||
405 | 404 | ||
406 | /* Global variables */ | 405 | /* Global variables */ |
407 | static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = { | 406 | static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = { |
408 | {PCI_DEVICE(VENDOR1, DEVICE1)}, | 407 | {PCI_DEVICE(0x1931, 0x000c)}, /* Nozomi HSDPA */ |
409 | {}, | 408 | {}, |
410 | }; | 409 | }; |
411 | 410 | ||
@@ -414,6 +413,8 @@ MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl); | |||
414 | static struct nozomi *ndevs[NOZOMI_MAX_CARDS]; | 413 | static struct nozomi *ndevs[NOZOMI_MAX_CARDS]; |
415 | static struct tty_driver *ntty_driver; | 414 | static struct tty_driver *ntty_driver; |
416 | 415 | ||
416 | static const struct tty_port_operations noz_tty_port_ops; | ||
417 | |||
417 | /* | 418 | /* |
418 | * find card by tty_index | 419 | * find card by tty_index |
419 | */ | 420 | */ |
@@ -853,8 +854,6 @@ static int receive_data(enum port_type index, struct nozomi *dc) | |||
853 | goto put; | 854 | goto put; |
854 | } | 855 | } |
855 | 856 | ||
856 | tty_buffer_request_room(tty, size); | ||
857 | |||
858 | while (size > 0) { | 857 | while (size > 0) { |
859 | read_mem32((u32 *) buf, addr + offset, RECEIVE_BUF_MAX); | 858 | read_mem32((u32 *) buf, addr + offset, RECEIVE_BUF_MAX); |
860 | 859 | ||
@@ -1473,9 +1472,11 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, | |||
1473 | 1472 | ||
1474 | for (i = 0; i < MAX_PORT; i++) { | 1473 | for (i = 0; i < MAX_PORT; i++) { |
1475 | struct device *tty_dev; | 1474 | struct device *tty_dev; |
1476 | 1475 | struct port *port = &dc->port[i]; | |
1477 | mutex_init(&dc->port[i].tty_sem); | 1476 | port->dc = dc; |
1478 | tty_port_init(&dc->port[i].port); | 1477 | mutex_init(&port->tty_sem); |
1478 | tty_port_init(&port->port); | ||
1479 | port->port.ops = &noz_tty_port_ops; | ||
1479 | tty_dev = tty_register_device(ntty_driver, dc->index_start + i, | 1480 | tty_dev = tty_register_device(ntty_driver, dc->index_start + i, |
1480 | &pdev->dev); | 1481 | &pdev->dev); |
1481 | 1482 | ||
@@ -1600,67 +1601,76 @@ static void set_dtr(const struct tty_struct *tty, int dtr) | |||
1600 | * ---------------------------------------------------------------------------- | 1601 | * ---------------------------------------------------------------------------- |
1601 | */ | 1602 | */ |
1602 | 1603 | ||
1603 | /* Called when the userspace process opens the tty, /dev/noz*. */ | 1604 | static int ntty_install(struct tty_driver *driver, struct tty_struct *tty) |
1604 | static int ntty_open(struct tty_struct *tty, struct file *file) | ||
1605 | { | 1605 | { |
1606 | struct port *port = get_port_by_tty(tty); | 1606 | struct port *port = get_port_by_tty(tty); |
1607 | struct nozomi *dc = get_dc_by_tty(tty); | 1607 | struct nozomi *dc = get_dc_by_tty(tty); |
1608 | unsigned long flags; | 1608 | int ret; |
1609 | |||
1610 | if (!port || !dc || dc->state != NOZOMI_STATE_READY) | 1609 | if (!port || !dc || dc->state != NOZOMI_STATE_READY) |
1611 | return -ENODEV; | 1610 | return -ENODEV; |
1612 | 1611 | ret = tty_init_termios(tty); | |
1613 | if (mutex_lock_interruptible(&port->tty_sem)) | 1612 | if (ret == 0) { |
1614 | return -ERESTARTSYS; | 1613 | tty_driver_kref_get(driver); |
1615 | 1614 | tty->count++; | |
1616 | port->port.count++; | ||
1617 | dc->open_ttys++; | ||
1618 | |||
1619 | /* Enable interrupt downlink for channel */ | ||
1620 | if (port->port.count == 1) { | ||
1621 | tty->driver_data = port; | 1615 | tty->driver_data = port; |
1622 | tty_port_tty_set(&port->port, tty); | 1616 | driver->ttys[tty->index] = tty; |
1623 | DBG1("open: %d", port->token_dl); | ||
1624 | spin_lock_irqsave(&dc->spin_mutex, flags); | ||
1625 | dc->last_ier = dc->last_ier | port->token_dl; | ||
1626 | writew(dc->last_ier, dc->reg_ier); | ||
1627 | spin_unlock_irqrestore(&dc->spin_mutex, flags); | ||
1628 | } | 1617 | } |
1629 | mutex_unlock(&port->tty_sem); | 1618 | return ret; |
1630 | return 0; | ||
1631 | } | 1619 | } |
1632 | 1620 | ||
1633 | /* Called when the userspace process close the tty, /dev/noz*. Also | 1621 | static void ntty_cleanup(struct tty_struct *tty) |
1634 | called immediately if ntty_open fails in which case tty->driver_data | 1622 | { |
1635 | will be NULL an we exit by the first return */ | 1623 | tty->driver_data = NULL; |
1624 | } | ||
1636 | 1625 | ||
1637 | static void ntty_close(struct tty_struct *tty, struct file *file) | 1626 | static int ntty_activate(struct tty_port *tport, struct tty_struct *tty) |
1638 | { | 1627 | { |
1639 | struct nozomi *dc = get_dc_by_tty(tty); | 1628 | struct port *port = container_of(tport, struct port, port); |
1640 | struct port *nport = tty->driver_data; | 1629 | struct nozomi *dc = port->dc; |
1641 | struct tty_port *port = &nport->port; | ||
1642 | unsigned long flags; | 1630 | unsigned long flags; |
1643 | 1631 | ||
1644 | if (!dc || !nport) | 1632 | DBG1("open: %d", port->token_dl); |
1645 | return; | 1633 | spin_lock_irqsave(&dc->spin_mutex, flags); |
1634 | dc->last_ier = dc->last_ier | port->token_dl; | ||
1635 | writew(dc->last_ier, dc->reg_ier); | ||
1636 | dc->open_ttys++; | ||
1637 | spin_unlock_irqrestore(&dc->spin_mutex, flags); | ||
1638 | printk("noz: activated %d: %p\n", tty->index, tport); | ||
1639 | return 0; | ||
1640 | } | ||
1646 | 1641 | ||
1647 | /* Users cannot interrupt a close */ | 1642 | static int ntty_open(struct tty_struct *tty, struct file *filp) |
1648 | mutex_lock(&nport->tty_sem); | 1643 | { |
1644 | struct port *port = tty->driver_data; | ||
1645 | return tty_port_open(&port->port, tty, filp); | ||
1646 | } | ||
1649 | 1647 | ||
1650 | WARN_ON(!port->count); | 1648 | static void ntty_shutdown(struct tty_port *tport) |
1649 | { | ||
1650 | struct port *port = container_of(tport, struct port, port); | ||
1651 | struct nozomi *dc = port->dc; | ||
1652 | unsigned long flags; | ||
1651 | 1653 | ||
1654 | DBG1("close: %d", port->token_dl); | ||
1655 | spin_lock_irqsave(&dc->spin_mutex, flags); | ||
1656 | dc->last_ier &= ~(port->token_dl); | ||
1657 | writew(dc->last_ier, dc->reg_ier); | ||
1652 | dc->open_ttys--; | 1658 | dc->open_ttys--; |
1653 | port->count--; | 1659 | spin_unlock_irqrestore(&dc->spin_mutex, flags); |
1660 | printk("noz: shutdown %p\n", tport); | ||
1661 | } | ||
1654 | 1662 | ||
1655 | if (port->count == 0) { | 1663 | static void ntty_close(struct tty_struct *tty, struct file *filp) |
1656 | DBG1("close: %d", nport->token_dl); | 1664 | { |
1657 | tty_port_tty_set(port, NULL); | 1665 | struct port *port = tty->driver_data; |
1658 | spin_lock_irqsave(&dc->spin_mutex, flags); | 1666 | if (port) |
1659 | dc->last_ier &= ~(nport->token_dl); | 1667 | tty_port_close(&port->port, tty, filp); |
1660 | writew(dc->last_ier, dc->reg_ier); | 1668 | } |
1661 | spin_unlock_irqrestore(&dc->spin_mutex, flags); | 1669 | |
1662 | } | 1670 | static void ntty_hangup(struct tty_struct *tty) |
1663 | mutex_unlock(&nport->tty_sem); | 1671 | { |
1672 | struct port *port = tty->driver_data; | ||
1673 | tty_port_hangup(&port->port); | ||
1664 | } | 1674 | } |
1665 | 1675 | ||
1666 | /* | 1676 | /* |
@@ -1680,15 +1690,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, | |||
1680 | if (!dc || !port) | 1690 | if (!dc || !port) |
1681 | return -ENODEV; | 1691 | return -ENODEV; |
1682 | 1692 | ||
1683 | if (unlikely(!mutex_trylock(&port->tty_sem))) { | 1693 | mutex_lock(&port->tty_sem); |
1684 | /* | ||
1685 | * must test lock as tty layer wraps calls | ||
1686 | * to this function with BKL | ||
1687 | */ | ||
1688 | dev_err(&dc->pdev->dev, "Would have deadlocked - " | ||
1689 | "return EAGAIN\n"); | ||
1690 | return -EAGAIN; | ||
1691 | } | ||
1692 | 1694 | ||
1693 | if (unlikely(!port->port.count)) { | 1695 | if (unlikely(!port->port.count)) { |
1694 | DBG1(" "); | 1696 | DBG1(" "); |
@@ -1728,25 +1730,22 @@ exit: | |||
1728 | * This method is called by the upper tty layer. | 1730 | * This method is called by the upper tty layer. |
1729 | * #according to sources N_TTY.c it expects a value >= 0 and | 1731 | * #according to sources N_TTY.c it expects a value >= 0 and |
1730 | * does not check for negative values. | 1732 | * does not check for negative values. |
1733 | * | ||
1734 | * If the port is unplugged report lots of room and let the bits | ||
1735 | * dribble away so we don't block anything. | ||
1731 | */ | 1736 | */ |
1732 | static int ntty_write_room(struct tty_struct *tty) | 1737 | static int ntty_write_room(struct tty_struct *tty) |
1733 | { | 1738 | { |
1734 | struct port *port = tty->driver_data; | 1739 | struct port *port = tty->driver_data; |
1735 | int room = 0; | 1740 | int room = 4096; |
1736 | const struct nozomi *dc = get_dc_by_tty(tty); | 1741 | const struct nozomi *dc = get_dc_by_tty(tty); |
1737 | 1742 | ||
1738 | if (!dc || !port) | 1743 | if (dc) { |
1739 | return 0; | 1744 | mutex_lock(&port->tty_sem); |
1740 | if (!mutex_trylock(&port->tty_sem)) | 1745 | if (port->port.count) |
1741 | return 0; | 1746 | room = kfifo_avail(&port->fifo_ul); |
1742 | 1747 | mutex_unlock(&port->tty_sem); | |
1743 | if (!port->port.count) | 1748 | } |
1744 | goto exit; | ||
1745 | |||
1746 | room = port->fifo_ul.size - kfifo_len(&port->fifo_ul); | ||
1747 | |||
1748 | exit: | ||
1749 | mutex_unlock(&port->tty_sem); | ||
1750 | return room; | 1749 | return room; |
1751 | } | 1750 | } |
1752 | 1751 | ||
@@ -1805,24 +1804,24 @@ static int ntty_cflags_changed(struct port *port, unsigned long flags, | |||
1805 | return ret; | 1804 | return ret; |
1806 | } | 1805 | } |
1807 | 1806 | ||
1808 | static int ntty_ioctl_tiocgicount(struct port *port, void __user *argp) | 1807 | static int ntty_tiocgicount(struct tty_struct *tty, |
1808 | struct serial_icounter_struct *icount) | ||
1809 | { | 1809 | { |
1810 | struct port *port = tty->driver_data; | ||
1810 | const struct async_icount cnow = port->tty_icount; | 1811 | const struct async_icount cnow = port->tty_icount; |
1811 | struct serial_icounter_struct icount; | 1812 | |
1812 | 1813 | icount->cts = cnow.cts; | |
1813 | icount.cts = cnow.cts; | 1814 | icount->dsr = cnow.dsr; |
1814 | icount.dsr = cnow.dsr; | 1815 | icount->rng = cnow.rng; |
1815 | icount.rng = cnow.rng; | 1816 | icount->dcd = cnow.dcd; |
1816 | icount.dcd = cnow.dcd; | 1817 | icount->rx = cnow.rx; |
1817 | icount.rx = cnow.rx; | 1818 | icount->tx = cnow.tx; |
1818 | icount.tx = cnow.tx; | 1819 | icount->frame = cnow.frame; |
1819 | icount.frame = cnow.frame; | 1820 | icount->overrun = cnow.overrun; |
1820 | icount.overrun = cnow.overrun; | 1821 | icount->parity = cnow.parity; |
1821 | icount.parity = cnow.parity; | 1822 | icount->brk = cnow.brk; |
1822 | icount.brk = cnow.brk; | 1823 | icount->buf_overrun = cnow.buf_overrun; |
1823 | icount.buf_overrun = cnow.buf_overrun; | 1824 | return 0; |
1824 | |||
1825 | return copy_to_user(argp, &icount, sizeof(icount)) ? -EFAULT : 0; | ||
1826 | } | 1825 | } |
1827 | 1826 | ||
1828 | static int ntty_ioctl(struct tty_struct *tty, struct file *file, | 1827 | static int ntty_ioctl(struct tty_struct *tty, struct file *file, |
@@ -1841,9 +1840,7 @@ static int ntty_ioctl(struct tty_struct *tty, struct file *file, | |||
1841 | rval = wait_event_interruptible(port->tty_wait, | 1840 | rval = wait_event_interruptible(port->tty_wait, |
1842 | ntty_cflags_changed(port, arg, &cprev)); | 1841 | ntty_cflags_changed(port, arg, &cprev)); |
1843 | break; | 1842 | break; |
1844 | } case TIOCGICOUNT: | 1843 | } |
1845 | rval = ntty_ioctl_tiocgicount(port, argp); | ||
1846 | break; | ||
1847 | default: | 1844 | default: |
1848 | DBG1("ERR: 0x%08X, %d", cmd, cmd); | 1845 | DBG1("ERR: 0x%08X, %d", cmd, cmd); |
1849 | break; | 1846 | break; |
@@ -1906,10 +1903,16 @@ exit_in_buffer: | |||
1906 | return rval; | 1903 | return rval; |
1907 | } | 1904 | } |
1908 | 1905 | ||
1906 | static const struct tty_port_operations noz_tty_port_ops = { | ||
1907 | .activate = ntty_activate, | ||
1908 | .shutdown = ntty_shutdown, | ||
1909 | }; | ||
1910 | |||
1909 | static const struct tty_operations tty_ops = { | 1911 | static const struct tty_operations tty_ops = { |
1910 | .ioctl = ntty_ioctl, | 1912 | .ioctl = ntty_ioctl, |
1911 | .open = ntty_open, | 1913 | .open = ntty_open, |
1912 | .close = ntty_close, | 1914 | .close = ntty_close, |
1915 | .hangup = ntty_hangup, | ||
1913 | .write = ntty_write, | 1916 | .write = ntty_write, |
1914 | .write_room = ntty_write_room, | 1917 | .write_room = ntty_write_room, |
1915 | .unthrottle = ntty_unthrottle, | 1918 | .unthrottle = ntty_unthrottle, |
@@ -1917,6 +1920,9 @@ static const struct tty_operations tty_ops = { | |||
1917 | .chars_in_buffer = ntty_chars_in_buffer, | 1920 | .chars_in_buffer = ntty_chars_in_buffer, |
1918 | .tiocmget = ntty_tiocmget, | 1921 | .tiocmget = ntty_tiocmget, |
1919 | .tiocmset = ntty_tiocmset, | 1922 | .tiocmset = ntty_tiocmset, |
1923 | .get_icount = ntty_tiocgicount, | ||
1924 | .install = ntty_install, | ||
1925 | .cleanup = ntty_cleanup, | ||
1920 | }; | 1926 | }; |
1921 | 1927 | ||
1922 | /* Module initialization */ | 1928 | /* Module initialization */ |
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index fdbcc9fd6d31..166f1e7aaa7e 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c | |||
@@ -100,7 +100,6 @@ | |||
100 | #include <linux/types.h> | 100 | #include <linux/types.h> |
101 | #include <linux/errno.h> | 101 | #include <linux/errno.h> |
102 | #include <linux/miscdevice.h> | 102 | #include <linux/miscdevice.h> |
103 | #include <linux/slab.h> | ||
104 | #include <linux/ioport.h> | 103 | #include <linux/ioport.h> |
105 | #include <linux/fcntl.h> | 104 | #include <linux/fcntl.h> |
106 | #include <linux/mc146818rtc.h> | 105 | #include <linux/mc146818rtc.h> |
@@ -110,10 +109,11 @@ | |||
110 | #include <linux/spinlock.h> | 109 | #include <linux/spinlock.h> |
111 | #include <linux/io.h> | 110 | #include <linux/io.h> |
112 | #include <linux/uaccess.h> | 111 | #include <linux/uaccess.h> |
113 | #include <linux/smp_lock.h> | 112 | #include <linux/mutex.h> |
114 | 113 | ||
115 | #include <asm/system.h> | 114 | #include <asm/system.h> |
116 | 115 | ||
116 | static DEFINE_MUTEX(nvram_mutex); | ||
117 | static DEFINE_SPINLOCK(nvram_state_lock); | 117 | static DEFINE_SPINLOCK(nvram_state_lock); |
118 | static int nvram_open_cnt; /* #times opened */ | 118 | static int nvram_open_cnt; /* #times opened */ |
119 | static int nvram_open_mode; /* special open modes */ | 119 | static int nvram_open_mode; /* special open modes */ |
@@ -297,8 +297,8 @@ checksum_err: | |||
297 | return -EIO; | 297 | return -EIO; |
298 | } | 298 | } |
299 | 299 | ||
300 | static int nvram_ioctl(struct inode *inode, struct file *file, | 300 | static long nvram_ioctl(struct file *file, unsigned int cmd, |
301 | unsigned int cmd, unsigned long arg) | 301 | unsigned long arg) |
302 | { | 302 | { |
303 | int i; | 303 | int i; |
304 | 304 | ||
@@ -309,6 +309,7 @@ static int nvram_ioctl(struct inode *inode, struct file *file, | |||
309 | if (!capable(CAP_SYS_ADMIN)) | 309 | if (!capable(CAP_SYS_ADMIN)) |
310 | return -EACCES; | 310 | return -EACCES; |
311 | 311 | ||
312 | mutex_lock(&nvram_mutex); | ||
312 | spin_lock_irq(&rtc_lock); | 313 | spin_lock_irq(&rtc_lock); |
313 | 314 | ||
314 | for (i = 0; i < NVRAM_BYTES; ++i) | 315 | for (i = 0; i < NVRAM_BYTES; ++i) |
@@ -316,6 +317,7 @@ static int nvram_ioctl(struct inode *inode, struct file *file, | |||
316 | __nvram_set_checksum(); | 317 | __nvram_set_checksum(); |
317 | 318 | ||
318 | spin_unlock_irq(&rtc_lock); | 319 | spin_unlock_irq(&rtc_lock); |
320 | mutex_unlock(&nvram_mutex); | ||
319 | return 0; | 321 | return 0; |
320 | 322 | ||
321 | case NVRAM_SETCKS: | 323 | case NVRAM_SETCKS: |
@@ -324,9 +326,11 @@ static int nvram_ioctl(struct inode *inode, struct file *file, | |||
324 | if (!capable(CAP_SYS_ADMIN)) | 326 | if (!capable(CAP_SYS_ADMIN)) |
325 | return -EACCES; | 327 | return -EACCES; |
326 | 328 | ||
329 | mutex_lock(&nvram_mutex); | ||
327 | spin_lock_irq(&rtc_lock); | 330 | spin_lock_irq(&rtc_lock); |
328 | __nvram_set_checksum(); | 331 | __nvram_set_checksum(); |
329 | spin_unlock_irq(&rtc_lock); | 332 | spin_unlock_irq(&rtc_lock); |
333 | mutex_unlock(&nvram_mutex); | ||
330 | return 0; | 334 | return 0; |
331 | 335 | ||
332 | default: | 336 | default: |
@@ -336,14 +340,12 @@ static int nvram_ioctl(struct inode *inode, struct file *file, | |||
336 | 340 | ||
337 | static int nvram_open(struct inode *inode, struct file *file) | 341 | static int nvram_open(struct inode *inode, struct file *file) |
338 | { | 342 | { |
339 | lock_kernel(); | ||
340 | spin_lock(&nvram_state_lock); | 343 | spin_lock(&nvram_state_lock); |
341 | 344 | ||
342 | if ((nvram_open_cnt && (file->f_flags & O_EXCL)) || | 345 | if ((nvram_open_cnt && (file->f_flags & O_EXCL)) || |
343 | (nvram_open_mode & NVRAM_EXCL) || | 346 | (nvram_open_mode & NVRAM_EXCL) || |
344 | ((file->f_mode & FMODE_WRITE) && (nvram_open_mode & NVRAM_WRITE))) { | 347 | ((file->f_mode & FMODE_WRITE) && (nvram_open_mode & NVRAM_WRITE))) { |
345 | spin_unlock(&nvram_state_lock); | 348 | spin_unlock(&nvram_state_lock); |
346 | unlock_kernel(); | ||
347 | return -EBUSY; | 349 | return -EBUSY; |
348 | } | 350 | } |
349 | 351 | ||
@@ -354,7 +356,6 @@ static int nvram_open(struct inode *inode, struct file *file) | |||
354 | nvram_open_cnt++; | 356 | nvram_open_cnt++; |
355 | 357 | ||
356 | spin_unlock(&nvram_state_lock); | 358 | spin_unlock(&nvram_state_lock); |
357 | unlock_kernel(); | ||
358 | 359 | ||
359 | return 0; | 360 | return 0; |
360 | } | 361 | } |
@@ -426,7 +427,7 @@ static const struct file_operations nvram_fops = { | |||
426 | .llseek = nvram_llseek, | 427 | .llseek = nvram_llseek, |
427 | .read = nvram_read, | 428 | .read = nvram_read, |
428 | .write = nvram_write, | 429 | .write = nvram_write, |
429 | .ioctl = nvram_ioctl, | 430 | .unlocked_ioctl = nvram_ioctl, |
430 | .open = nvram_open, | 431 | .open = nvram_open, |
431 | .release = nvram_release, | 432 | .release = nvram_release, |
432 | }; | 433 | }; |
diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c index 2604246501e4..8994ce32e6c7 100644 --- a/drivers/char/nwbutton.c +++ b/drivers/char/nwbutton.c | |||
@@ -182,6 +182,7 @@ static int button_read (struct file *filp, char __user *buffer, | |||
182 | static const struct file_operations button_fops = { | 182 | static const struct file_operations button_fops = { |
183 | .owner = THIS_MODULE, | 183 | .owner = THIS_MODULE, |
184 | .read = button_read, | 184 | .read = button_read, |
185 | .llseek = noop_llseek, | ||
185 | }; | 186 | }; |
186 | 187 | ||
187 | /* | 188 | /* |
diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c index f80810901db6..a12f52400dbc 100644 --- a/drivers/char/nwflash.c +++ b/drivers/char/nwflash.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/spinlock.h> | 25 | #include <linux/spinlock.h> |
26 | #include <linux/rwsem.h> | 26 | #include <linux/rwsem.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/smp_lock.h> | ||
29 | #include <linux/mutex.h> | 28 | #include <linux/mutex.h> |
30 | #include <linux/jiffies.h> | 29 | #include <linux/jiffies.h> |
31 | 30 | ||
@@ -41,6 +40,7 @@ | |||
41 | 40 | ||
42 | #define NWFLASH_VERSION "6.4" | 41 | #define NWFLASH_VERSION "6.4" |
43 | 42 | ||
43 | static DEFINE_MUTEX(flash_mutex); | ||
44 | static void kick_open(void); | 44 | static void kick_open(void); |
45 | static int get_flash_id(void); | 45 | static int get_flash_id(void); |
46 | static int erase_block(int nBlock); | 46 | static int erase_block(int nBlock); |
@@ -94,8 +94,9 @@ static int get_flash_id(void) | |||
94 | return c2; | 94 | return c2; |
95 | } | 95 | } |
96 | 96 | ||
97 | static int flash_ioctl(struct inode *inodep, struct file *filep, unsigned int cmd, unsigned long arg) | 97 | static long flash_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) |
98 | { | 98 | { |
99 | mutex_lock(&flash_mutex); | ||
99 | switch (cmd) { | 100 | switch (cmd) { |
100 | case CMD_WRITE_DISABLE: | 101 | case CMD_WRITE_DISABLE: |
101 | gbWriteBase64Enable = 0; | 102 | gbWriteBase64Enable = 0; |
@@ -113,8 +114,10 @@ static int flash_ioctl(struct inode *inodep, struct file *filep, unsigned int cm | |||
113 | default: | 114 | default: |
114 | gbWriteBase64Enable = 0; | 115 | gbWriteBase64Enable = 0; |
115 | gbWriteEnable = 0; | 116 | gbWriteEnable = 0; |
117 | mutex_unlock(&flash_mutex); | ||
116 | return -EINVAL; | 118 | return -EINVAL; |
117 | } | 119 | } |
120 | mutex_unlock(&flash_mutex); | ||
118 | return 0; | 121 | return 0; |
119 | } | 122 | } |
120 | 123 | ||
@@ -279,7 +282,7 @@ static loff_t flash_llseek(struct file *file, loff_t offset, int orig) | |||
279 | { | 282 | { |
280 | loff_t ret; | 283 | loff_t ret; |
281 | 284 | ||
282 | lock_kernel(); | 285 | mutex_lock(&flash_mutex); |
283 | if (flashdebug) | 286 | if (flashdebug) |
284 | printk(KERN_DEBUG "flash_llseek: offset=0x%X, orig=0x%X.\n", | 287 | printk(KERN_DEBUG "flash_llseek: offset=0x%X, orig=0x%X.\n", |
285 | (unsigned int) offset, orig); | 288 | (unsigned int) offset, orig); |
@@ -314,7 +317,7 @@ static loff_t flash_llseek(struct file *file, loff_t offset, int orig) | |||
314 | default: | 317 | default: |
315 | ret = -EINVAL; | 318 | ret = -EINVAL; |
316 | } | 319 | } |
317 | unlock_kernel(); | 320 | mutex_unlock(&flash_mutex); |
318 | return ret; | 321 | return ret; |
319 | } | 322 | } |
320 | 323 | ||
@@ -631,7 +634,7 @@ static const struct file_operations flash_fops = | |||
631 | .llseek = flash_llseek, | 634 | .llseek = flash_llseek, |
632 | .read = flash_read, | 635 | .read = flash_read, |
633 | .write = flash_write, | 636 | .write = flash_write, |
634 | .ioctl = flash_ioctl, | 637 | .unlocked_ioctl = flash_ioctl, |
635 | }; | 638 | }; |
636 | 639 | ||
637 | static struct miscdevice flash_miscdev = | 640 | static struct miscdevice flash_miscdev = |
diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c index 8ecbcc174c15..b304ec052501 100644 --- a/drivers/char/pc8736x_gpio.c +++ b/drivers/char/pc8736x_gpio.c | |||
@@ -234,6 +234,7 @@ static const struct file_operations pc8736x_gpio_fileops = { | |||
234 | .open = pc8736x_gpio_open, | 234 | .open = pc8736x_gpio_open, |
235 | .write = nsc_gpio_write, | 235 | .write = nsc_gpio_write, |
236 | .read = nsc_gpio_read, | 236 | .read = nsc_gpio_read, |
237 | .llseek = no_llseek, | ||
237 | }; | 238 | }; |
238 | 239 | ||
239 | static void __init pc8736x_init_shadow(void) | 240 | static void __init pc8736x_init_shadow(void) |
diff --git a/drivers/char/pcmcia/Kconfig b/drivers/char/pcmcia/Kconfig index ffa0efce0aed..6614416a8623 100644 --- a/drivers/char/pcmcia/Kconfig +++ b/drivers/char/pcmcia/Kconfig | |||
@@ -28,7 +28,7 @@ config CARDMAN_4000 | |||
28 | 28 | ||
29 | This kernel driver requires additional userspace support, either | 29 | This kernel driver requires additional userspace support, either |
30 | by the vendor-provided PC/SC ifd_handler (http://www.omnikey.com/), | 30 | by the vendor-provided PC/SC ifd_handler (http://www.omnikey.com/), |
31 | or via the cm4000 backend of OpenCT (http://www.opensc.com/). | 31 | or via the cm4000 backend of OpenCT (http://www.opensc-project.org/opensc). |
32 | 32 | ||
33 | config CARDMAN_4040 | 33 | config CARDMAN_4040 |
34 | tristate "Omnikey CardMan 4040 support" | 34 | tristate "Omnikey CardMan 4040 support" |
@@ -41,7 +41,7 @@ config CARDMAN_4040 | |||
41 | in I/O space. To use the kernel driver, you will need either the | 41 | in I/O space. To use the kernel driver, you will need either the |
42 | PC/SC ifdhandler provided from the Omnikey homepage | 42 | PC/SC ifdhandler provided from the Omnikey homepage |
43 | (http://www.omnikey.com/), or a current development version of OpenCT | 43 | (http://www.omnikey.com/), or a current development version of OpenCT |
44 | (http://www.opensc.org/). | 44 | (http://www.opensc-project.org/opensc). |
45 | 45 | ||
46 | config IPWIRELESS | 46 | config IPWIRELESS |
47 | tristate "IPWireless 3G UMTS PCMCIA card support" | 47 | tristate "IPWireless 3G UMTS PCMCIA card support" |
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 2db4c0a29b05..d962f25dcc2a 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c | |||
@@ -30,12 +30,10 @@ | |||
30 | #include <linux/fs.h> | 30 | #include <linux/fs.h> |
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/bitrev.h> | 32 | #include <linux/bitrev.h> |
33 | #include <linux/smp_lock.h> | 33 | #include <linux/mutex.h> |
34 | #include <linux/uaccess.h> | 34 | #include <linux/uaccess.h> |
35 | #include <linux/io.h> | 35 | #include <linux/io.h> |
36 | 36 | ||
37 | #include <pcmcia/cs_types.h> | ||
38 | #include <pcmcia/cs.h> | ||
39 | #include <pcmcia/cistpl.h> | 37 | #include <pcmcia/cistpl.h> |
40 | #include <pcmcia/cisreg.h> | 38 | #include <pcmcia/cisreg.h> |
41 | #include <pcmcia/ciscode.h> | 39 | #include <pcmcia/ciscode.h> |
@@ -56,7 +54,7 @@ | |||
56 | __func__ , ## args); \ | 54 | __func__ , ## args); \ |
57 | } while (0) | 55 | } while (0) |
58 | 56 | ||
59 | static char *version = "cm4000_cs.c v2.4.0gm6 - All bugs added by Harald Welte"; | 57 | static DEFINE_MUTEX(cmm_mutex); |
60 | 58 | ||
61 | #define T_1SEC (HZ) | 59 | #define T_1SEC (HZ) |
62 | #define T_10MSEC msecs_to_jiffies(10) | 60 | #define T_10MSEC msecs_to_jiffies(10) |
@@ -106,7 +104,6 @@ static int major; /* major number we get from the kernel */ | |||
106 | 104 | ||
107 | struct cm4000_dev { | 105 | struct cm4000_dev { |
108 | struct pcmcia_device *p_dev; | 106 | struct pcmcia_device *p_dev; |
109 | dev_node_t node; /* OS node (major,minor) */ | ||
110 | 107 | ||
111 | unsigned char atr[MAX_ATR]; | 108 | unsigned char atr[MAX_ATR]; |
112 | unsigned char rbuf[512]; | 109 | unsigned char rbuf[512]; |
@@ -423,7 +420,7 @@ static struct card_fixup card_fixups[] = { | |||
423 | static void set_cardparameter(struct cm4000_dev *dev) | 420 | static void set_cardparameter(struct cm4000_dev *dev) |
424 | { | 421 | { |
425 | int i; | 422 | int i; |
426 | unsigned int iobase = dev->p_dev->io.BasePort1; | 423 | unsigned int iobase = dev->p_dev->resource[0]->start; |
427 | u_int8_t stopbits = 0x02; /* ISO default */ | 424 | u_int8_t stopbits = 0x02; /* ISO default */ |
428 | 425 | ||
429 | DEBUGP(3, dev, "-> set_cardparameter\n"); | 426 | DEBUGP(3, dev, "-> set_cardparameter\n"); |
@@ -456,7 +453,7 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq) | |||
456 | unsigned short num_bytes_read; | 453 | unsigned short num_bytes_read; |
457 | unsigned char pts_reply[4]; | 454 | unsigned char pts_reply[4]; |
458 | ssize_t rc; | 455 | ssize_t rc; |
459 | unsigned int iobase = dev->p_dev->io.BasePort1; | 456 | unsigned int iobase = dev->p_dev->resource[0]->start; |
460 | 457 | ||
461 | rc = 0; | 458 | rc = 0; |
462 | 459 | ||
@@ -665,7 +662,7 @@ static void terminate_monitor(struct cm4000_dev *dev) | |||
665 | static void monitor_card(unsigned long p) | 662 | static void monitor_card(unsigned long p) |
666 | { | 663 | { |
667 | struct cm4000_dev *dev = (struct cm4000_dev *) p; | 664 | struct cm4000_dev *dev = (struct cm4000_dev *) p; |
668 | unsigned int iobase = dev->p_dev->io.BasePort1; | 665 | unsigned int iobase = dev->p_dev->resource[0]->start; |
669 | unsigned short s; | 666 | unsigned short s; |
670 | struct ptsreq ptsreq; | 667 | struct ptsreq ptsreq; |
671 | int i, atrc; | 668 | int i, atrc; |
@@ -884,8 +881,7 @@ static void monitor_card(unsigned long p) | |||
884 | /* slow down warning, but prompt immediately after insertion */ | 881 | /* slow down warning, but prompt immediately after insertion */ |
885 | if (dev->cwarn == 0 || dev->cwarn == 10) { | 882 | if (dev->cwarn == 0 || dev->cwarn == 10) { |
886 | set_bit(IS_BAD_CARD, &dev->flags); | 883 | set_bit(IS_BAD_CARD, &dev->flags); |
887 | printk(KERN_WARNING MODULE_NAME ": device %s: ", | 884 | dev_warn(&dev->p_dev->dev, MODULE_NAME ": "); |
888 | dev->node.dev_name); | ||
889 | if (test_bit(IS_BAD_CSUM, &dev->flags)) { | 885 | if (test_bit(IS_BAD_CSUM, &dev->flags)) { |
890 | DEBUGP(4, dev, "ATR checksum (0x%.2x, should " | 886 | DEBUGP(4, dev, "ATR checksum (0x%.2x, should " |
891 | "be zero) failed\n", dev->atr_csum); | 887 | "be zero) failed\n", dev->atr_csum); |
@@ -927,7 +923,7 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count, | |||
927 | loff_t *ppos) | 923 | loff_t *ppos) |
928 | { | 924 | { |
929 | struct cm4000_dev *dev = filp->private_data; | 925 | struct cm4000_dev *dev = filp->private_data; |
930 | unsigned int iobase = dev->p_dev->io.BasePort1; | 926 | unsigned int iobase = dev->p_dev->resource[0]->start; |
931 | ssize_t rc; | 927 | ssize_t rc; |
932 | int i, j, k; | 928 | int i, j, k; |
933 | 929 | ||
@@ -1026,14 +1022,16 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count, | |||
1026 | 1022 | ||
1027 | xoutb(0, REG_FLAGS1(iobase)); /* clear detectCMM */ | 1023 | xoutb(0, REG_FLAGS1(iobase)); /* clear detectCMM */ |
1028 | /* last check before exit */ | 1024 | /* last check before exit */ |
1029 | if (!io_detect_cm4000(iobase, dev)) | 1025 | if (!io_detect_cm4000(iobase, dev)) { |
1030 | count = -ENODEV; | 1026 | rc = -ENODEV; |
1027 | goto release_io; | ||
1028 | } | ||
1031 | 1029 | ||
1032 | if (test_bit(IS_INVREV, &dev->flags) && count > 0) | 1030 | if (test_bit(IS_INVREV, &dev->flags) && count > 0) |
1033 | str_invert_revert(dev->rbuf, count); | 1031 | str_invert_revert(dev->rbuf, count); |
1034 | 1032 | ||
1035 | if (copy_to_user(buf, dev->rbuf, count)) | 1033 | if (copy_to_user(buf, dev->rbuf, count)) |
1036 | return -EFAULT; | 1034 | rc = -EFAULT; |
1037 | 1035 | ||
1038 | release_io: | 1036 | release_io: |
1039 | clear_bit(LOCK_IO, &dev->flags); | 1037 | clear_bit(LOCK_IO, &dev->flags); |
@@ -1047,8 +1045,8 @@ release_io: | |||
1047 | static ssize_t cmm_write(struct file *filp, const char __user *buf, | 1045 | static ssize_t cmm_write(struct file *filp, const char __user *buf, |
1048 | size_t count, loff_t *ppos) | 1046 | size_t count, loff_t *ppos) |
1049 | { | 1047 | { |
1050 | struct cm4000_dev *dev = (struct cm4000_dev *) filp->private_data; | 1048 | struct cm4000_dev *dev = filp->private_data; |
1051 | unsigned int iobase = dev->p_dev->io.BasePort1; | 1049 | unsigned int iobase = dev->p_dev->resource[0]->start; |
1052 | unsigned short s; | 1050 | unsigned short s; |
1053 | unsigned char tmp; | 1051 | unsigned char tmp; |
1054 | unsigned char infolen; | 1052 | unsigned char infolen; |
@@ -1401,7 +1399,7 @@ static void stop_monitor(struct cm4000_dev *dev) | |||
1401 | static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 1399 | static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
1402 | { | 1400 | { |
1403 | struct cm4000_dev *dev = filp->private_data; | 1401 | struct cm4000_dev *dev = filp->private_data; |
1404 | unsigned int iobase = dev->p_dev->io.BasePort1; | 1402 | unsigned int iobase = dev->p_dev->resource[0]->start; |
1405 | struct inode *inode = filp->f_path.dentry->d_inode; | 1403 | struct inode *inode = filp->f_path.dentry->d_inode; |
1406 | struct pcmcia_device *link; | 1404 | struct pcmcia_device *link; |
1407 | int size; | 1405 | int size; |
@@ -1419,7 +1417,7 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
1419 | iminor(inode), ioctl_names[_IOC_NR(cmd)]); | 1417 | iminor(inode), ioctl_names[_IOC_NR(cmd)]); |
1420 | #endif | 1418 | #endif |
1421 | 1419 | ||
1422 | lock_kernel(); | 1420 | mutex_lock(&cmm_mutex); |
1423 | rc = -ENODEV; | 1421 | rc = -ENODEV; |
1424 | link = dev_table[iminor(inode)]; | 1422 | link = dev_table[iminor(inode)]; |
1425 | if (!pcmcia_dev_present(link)) { | 1423 | if (!pcmcia_dev_present(link)) { |
@@ -1627,7 +1625,7 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
1627 | rc = -ENOTTY; | 1625 | rc = -ENOTTY; |
1628 | } | 1626 | } |
1629 | out: | 1627 | out: |
1630 | unlock_kernel(); | 1628 | mutex_unlock(&cmm_mutex); |
1631 | return rc; | 1629 | return rc; |
1632 | } | 1630 | } |
1633 | 1631 | ||
@@ -1641,7 +1639,7 @@ static int cmm_open(struct inode *inode, struct file *filp) | |||
1641 | if (minor >= CM4000_MAX_DEV) | 1639 | if (minor >= CM4000_MAX_DEV) |
1642 | return -ENODEV; | 1640 | return -ENODEV; |
1643 | 1641 | ||
1644 | lock_kernel(); | 1642 | mutex_lock(&cmm_mutex); |
1645 | link = dev_table[minor]; | 1643 | link = dev_table[minor]; |
1646 | if (link == NULL || !pcmcia_dev_present(link)) { | 1644 | if (link == NULL || !pcmcia_dev_present(link)) { |
1647 | ret = -ENODEV; | 1645 | ret = -ENODEV; |
@@ -1668,7 +1666,7 @@ static int cmm_open(struct inode *inode, struct file *filp) | |||
1668 | /* opening will always block since the | 1666 | /* opening will always block since the |
1669 | * monitor will be started by open, which | 1667 | * monitor will be started by open, which |
1670 | * means we have to wait for ATR becoming | 1668 | * means we have to wait for ATR becoming |
1671 | * vaild = block until valid (or card | 1669 | * valid = block until valid (or card |
1672 | * inserted) | 1670 | * inserted) |
1673 | */ | 1671 | */ |
1674 | if (filp->f_flags & O_NONBLOCK) { | 1672 | if (filp->f_flags & O_NONBLOCK) { |
@@ -1686,7 +1684,7 @@ static int cmm_open(struct inode *inode, struct file *filp) | |||
1686 | DEBUGP(2, dev, "<- cmm_open\n"); | 1684 | DEBUGP(2, dev, "<- cmm_open\n"); |
1687 | ret = nonseekable_open(inode, filp); | 1685 | ret = nonseekable_open(inode, filp); |
1688 | out: | 1686 | out: |
1689 | unlock_kernel(); | 1687 | mutex_unlock(&cmm_mutex); |
1690 | return ret; | 1688 | return ret; |
1691 | } | 1689 | } |
1692 | 1690 | ||
@@ -1743,47 +1741,25 @@ static void cmm_cm4000_release(struct pcmcia_device * link) | |||
1743 | 1741 | ||
1744 | /*==== Interface to PCMCIA Layer =======================================*/ | 1742 | /*==== Interface to PCMCIA Layer =======================================*/ |
1745 | 1743 | ||
1746 | static int cm4000_config_check(struct pcmcia_device *p_dev, | 1744 | static int cm4000_config_check(struct pcmcia_device *p_dev, void *priv_data) |
1747 | cistpl_cftable_entry_t *cfg, | ||
1748 | cistpl_cftable_entry_t *dflt, | ||
1749 | unsigned int vcc, | ||
1750 | void *priv_data) | ||
1751 | { | 1745 | { |
1752 | if (!cfg->io.nwin) | 1746 | return pcmcia_request_io(p_dev); |
1753 | return -ENODEV; | ||
1754 | |||
1755 | /* Get the IOaddr */ | ||
1756 | p_dev->io.BasePort1 = cfg->io.win[0].base; | ||
1757 | p_dev->io.NumPorts1 = cfg->io.win[0].len; | ||
1758 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
1759 | if (!(cfg->io.flags & CISTPL_IO_8BIT)) | ||
1760 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
1761 | if (!(cfg->io.flags & CISTPL_IO_16BIT)) | ||
1762 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
1763 | p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK; | ||
1764 | |||
1765 | return pcmcia_request_io(p_dev, &p_dev->io); | ||
1766 | } | 1747 | } |
1767 | 1748 | ||
1768 | static int cm4000_config(struct pcmcia_device * link, int devno) | 1749 | static int cm4000_config(struct pcmcia_device * link, int devno) |
1769 | { | 1750 | { |
1770 | struct cm4000_dev *dev; | 1751 | struct cm4000_dev *dev; |
1771 | 1752 | ||
1753 | link->config_flags |= CONF_AUTO_SET_IO; | ||
1754 | |||
1772 | /* read the config-tuples */ | 1755 | /* read the config-tuples */ |
1773 | if (pcmcia_loop_config(link, cm4000_config_check, NULL)) | 1756 | if (pcmcia_loop_config(link, cm4000_config_check, NULL)) |
1774 | goto cs_release; | 1757 | goto cs_release; |
1775 | 1758 | ||
1776 | link->conf.IntType = 00000002; | 1759 | if (pcmcia_enable_device(link)) |
1777 | |||
1778 | if (pcmcia_request_configuration(link, &link->conf)) | ||
1779 | goto cs_release; | 1760 | goto cs_release; |
1780 | 1761 | ||
1781 | dev = link->priv; | 1762 | dev = link->priv; |
1782 | sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno); | ||
1783 | dev->node.major = major; | ||
1784 | dev->node.minor = devno; | ||
1785 | dev->node.next = NULL; | ||
1786 | link->dev_node = &dev->node; | ||
1787 | 1763 | ||
1788 | return 0; | 1764 | return 0; |
1789 | 1765 | ||
@@ -1840,7 +1816,6 @@ static int cm4000_probe(struct pcmcia_device *link) | |||
1840 | 1816 | ||
1841 | dev->p_dev = link; | 1817 | dev->p_dev = link; |
1842 | link->priv = dev; | 1818 | link->priv = dev; |
1843 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
1844 | dev_table[i] = link; | 1819 | dev_table[i] = link; |
1845 | 1820 | ||
1846 | init_waitqueue_head(&dev->devq); | 1821 | init_waitqueue_head(&dev->devq); |
@@ -1891,6 +1866,7 @@ static const struct file_operations cm4000_fops = { | |||
1891 | .unlocked_ioctl = cmm_ioctl, | 1866 | .unlocked_ioctl = cmm_ioctl, |
1892 | .open = cmm_open, | 1867 | .open = cmm_open, |
1893 | .release= cmm_close, | 1868 | .release= cmm_close, |
1869 | .llseek = no_llseek, | ||
1894 | }; | 1870 | }; |
1895 | 1871 | ||
1896 | static struct pcmcia_device_id cm4000_ids[] = { | 1872 | static struct pcmcia_device_id cm4000_ids[] = { |
@@ -1902,9 +1878,7 @@ MODULE_DEVICE_TABLE(pcmcia, cm4000_ids); | |||
1902 | 1878 | ||
1903 | static struct pcmcia_driver cm4000_driver = { | 1879 | static struct pcmcia_driver cm4000_driver = { |
1904 | .owner = THIS_MODULE, | 1880 | .owner = THIS_MODULE, |
1905 | .drv = { | 1881 | .name = "cm4000_cs", |
1906 | .name = "cm4000_cs", | ||
1907 | }, | ||
1908 | .probe = cm4000_probe, | 1882 | .probe = cm4000_probe, |
1909 | .remove = cm4000_detach, | 1883 | .remove = cm4000_detach, |
1910 | .suspend = cm4000_suspend, | 1884 | .suspend = cm4000_suspend, |
@@ -1916,8 +1890,6 @@ static int __init cmm_init(void) | |||
1916 | { | 1890 | { |
1917 | int rc; | 1891 | int rc; |
1918 | 1892 | ||
1919 | printk(KERN_INFO "%s\n", version); | ||
1920 | |||
1921 | cmm_class = class_create(THIS_MODULE, "cardman_4000"); | 1893 | cmm_class = class_create(THIS_MODULE, "cardman_4000"); |
1922 | if (IS_ERR(cmm_class)) | 1894 | if (IS_ERR(cmm_class)) |
1923 | return PTR_ERR(cmm_class); | 1895 | return PTR_ERR(cmm_class); |
@@ -1942,7 +1914,6 @@ static int __init cmm_init(void) | |||
1942 | 1914 | ||
1943 | static void __exit cmm_exit(void) | 1915 | static void __exit cmm_exit(void) |
1944 | { | 1916 | { |
1945 | printk(KERN_INFO MODULE_NAME ": unloading\n"); | ||
1946 | pcmcia_unregister_driver(&cm4000_driver); | 1917 | pcmcia_unregister_driver(&cm4000_driver); |
1947 | unregister_chrdev(major, DEVICE_NAME); | 1918 | unregister_chrdev(major, DEVICE_NAME); |
1948 | class_destroy(cmm_class); | 1919 | class_destroy(cmm_class); |
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index a6a70e476bea..5d8d59e865f4 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c | |||
@@ -24,13 +24,11 @@ | |||
24 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/poll.h> | 26 | #include <linux/poll.h> |
27 | #include <linux/smp_lock.h> | 27 | #include <linux/mutex.h> |
28 | #include <linux/wait.h> | 28 | #include <linux/wait.h> |
29 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
30 | #include <asm/io.h> | 30 | #include <asm/io.h> |
31 | 31 | ||
32 | #include <pcmcia/cs_types.h> | ||
33 | #include <pcmcia/cs.h> | ||
34 | #include <pcmcia/cistpl.h> | 32 | #include <pcmcia/cistpl.h> |
35 | #include <pcmcia/cisreg.h> | 33 | #include <pcmcia/cisreg.h> |
36 | #include <pcmcia/ciscode.h> | 34 | #include <pcmcia/ciscode.h> |
@@ -50,8 +48,7 @@ | |||
50 | __func__ , ## args); \ | 48 | __func__ , ## args); \ |
51 | } while (0) | 49 | } while (0) |
52 | 50 | ||
53 | static char *version = | 51 | static DEFINE_MUTEX(cm4040_mutex); |
54 | "OMNIKEY CardMan 4040 v1.1.0gm5 - All bugs added by Harald Welte"; | ||
55 | 52 | ||
56 | #define CCID_DRIVER_BULK_DEFAULT_TIMEOUT (150*HZ) | 53 | #define CCID_DRIVER_BULK_DEFAULT_TIMEOUT (150*HZ) |
57 | #define CCID_DRIVER_ASYNC_POWERUP_TIMEOUT (35*HZ) | 54 | #define CCID_DRIVER_ASYNC_POWERUP_TIMEOUT (35*HZ) |
@@ -72,7 +69,6 @@ static struct class *cmx_class; | |||
72 | 69 | ||
73 | struct reader_dev { | 70 | struct reader_dev { |
74 | struct pcmcia_device *p_dev; | 71 | struct pcmcia_device *p_dev; |
75 | dev_node_t node; | ||
76 | wait_queue_head_t devq; | 72 | wait_queue_head_t devq; |
77 | wait_queue_head_t poll_wait; | 73 | wait_queue_head_t poll_wait; |
78 | wait_queue_head_t read_wait; | 74 | wait_queue_head_t read_wait; |
@@ -111,7 +107,7 @@ static inline unsigned char xinb(unsigned short port) | |||
111 | static void cm4040_do_poll(unsigned long dummy) | 107 | static void cm4040_do_poll(unsigned long dummy) |
112 | { | 108 | { |
113 | struct reader_dev *dev = (struct reader_dev *) dummy; | 109 | struct reader_dev *dev = (struct reader_dev *) dummy; |
114 | unsigned int obs = xinb(dev->p_dev->io.BasePort1 | 110 | unsigned int obs = xinb(dev->p_dev->resource[0]->start |
115 | + REG_OFFSET_BUFFER_STATUS); | 111 | + REG_OFFSET_BUFFER_STATUS); |
116 | 112 | ||
117 | if ((obs & BSR_BULK_IN_FULL)) { | 113 | if ((obs & BSR_BULK_IN_FULL)) { |
@@ -142,7 +138,7 @@ static void cm4040_stop_poll(struct reader_dev *dev) | |||
142 | static int wait_for_bulk_out_ready(struct reader_dev *dev) | 138 | static int wait_for_bulk_out_ready(struct reader_dev *dev) |
143 | { | 139 | { |
144 | int i, rc; | 140 | int i, rc; |
145 | int iobase = dev->p_dev->io.BasePort1; | 141 | int iobase = dev->p_dev->resource[0]->start; |
146 | 142 | ||
147 | for (i = 0; i < POLL_LOOP_COUNT; i++) { | 143 | for (i = 0; i < POLL_LOOP_COUNT; i++) { |
148 | if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS) | 144 | if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS) |
@@ -172,7 +168,7 @@ static int wait_for_bulk_out_ready(struct reader_dev *dev) | |||
172 | /* Write to Sync Control Register */ | 168 | /* Write to Sync Control Register */ |
173 | static int write_sync_reg(unsigned char val, struct reader_dev *dev) | 169 | static int write_sync_reg(unsigned char val, struct reader_dev *dev) |
174 | { | 170 | { |
175 | int iobase = dev->p_dev->io.BasePort1; | 171 | int iobase = dev->p_dev->resource[0]->start; |
176 | int rc; | 172 | int rc; |
177 | 173 | ||
178 | rc = wait_for_bulk_out_ready(dev); | 174 | rc = wait_for_bulk_out_ready(dev); |
@@ -190,7 +186,7 @@ static int write_sync_reg(unsigned char val, struct reader_dev *dev) | |||
190 | static int wait_for_bulk_in_ready(struct reader_dev *dev) | 186 | static int wait_for_bulk_in_ready(struct reader_dev *dev) |
191 | { | 187 | { |
192 | int i, rc; | 188 | int i, rc; |
193 | int iobase = dev->p_dev->io.BasePort1; | 189 | int iobase = dev->p_dev->resource[0]->start; |
194 | 190 | ||
195 | for (i = 0; i < POLL_LOOP_COUNT; i++) { | 191 | for (i = 0; i < POLL_LOOP_COUNT; i++) { |
196 | if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS) | 192 | if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS) |
@@ -220,7 +216,7 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf, | |||
220 | size_t count, loff_t *ppos) | 216 | size_t count, loff_t *ppos) |
221 | { | 217 | { |
222 | struct reader_dev *dev = filp->private_data; | 218 | struct reader_dev *dev = filp->private_data; |
223 | int iobase = dev->p_dev->io.BasePort1; | 219 | int iobase = dev->p_dev->resource[0]->start; |
224 | size_t bytes_to_read; | 220 | size_t bytes_to_read; |
225 | unsigned long i; | 221 | unsigned long i; |
226 | size_t min_bytes_to_read; | 222 | size_t min_bytes_to_read; |
@@ -322,7 +318,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf, | |||
322 | size_t count, loff_t *ppos) | 318 | size_t count, loff_t *ppos) |
323 | { | 319 | { |
324 | struct reader_dev *dev = filp->private_data; | 320 | struct reader_dev *dev = filp->private_data; |
325 | int iobase = dev->p_dev->io.BasePort1; | 321 | int iobase = dev->p_dev->resource[0]->start; |
326 | ssize_t rc; | 322 | ssize_t rc; |
327 | int i; | 323 | int i; |
328 | unsigned int bytes_to_write; | 324 | unsigned int bytes_to_write; |
@@ -446,7 +442,7 @@ static int cm4040_open(struct inode *inode, struct file *filp) | |||
446 | if (minor >= CM_MAX_DEV) | 442 | if (minor >= CM_MAX_DEV) |
447 | return -ENODEV; | 443 | return -ENODEV; |
448 | 444 | ||
449 | lock_kernel(); | 445 | mutex_lock(&cm4040_mutex); |
450 | link = dev_table[minor]; | 446 | link = dev_table[minor]; |
451 | if (link == NULL || !pcmcia_dev_present(link)) { | 447 | if (link == NULL || !pcmcia_dev_present(link)) { |
452 | ret = -ENODEV; | 448 | ret = -ENODEV; |
@@ -475,7 +471,7 @@ static int cm4040_open(struct inode *inode, struct file *filp) | |||
475 | DEBUGP(2, dev, "<- cm4040_open (successfully)\n"); | 471 | DEBUGP(2, dev, "<- cm4040_open (successfully)\n"); |
476 | ret = nonseekable_open(inode, filp); | 472 | ret = nonseekable_open(inode, filp); |
477 | out: | 473 | out: |
478 | unlock_kernel(); | 474 | mutex_unlock(&cm4040_mutex); |
479 | return ret; | 475 | return ret; |
480 | } | 476 | } |
481 | 477 | ||
@@ -518,30 +514,9 @@ static void cm4040_reader_release(struct pcmcia_device *link) | |||
518 | return; | 514 | return; |
519 | } | 515 | } |
520 | 516 | ||
521 | static int cm4040_config_check(struct pcmcia_device *p_dev, | 517 | static int cm4040_config_check(struct pcmcia_device *p_dev, void *priv_data) |
522 | cistpl_cftable_entry_t *cfg, | ||
523 | cistpl_cftable_entry_t *dflt, | ||
524 | unsigned int vcc, | ||
525 | void *priv_data) | ||
526 | { | 518 | { |
527 | int rc; | 519 | return pcmcia_request_io(p_dev); |
528 | if (!cfg->io.nwin) | ||
529 | return -ENODEV; | ||
530 | |||
531 | /* Get the IOaddr */ | ||
532 | p_dev->io.BasePort1 = cfg->io.win[0].base; | ||
533 | p_dev->io.NumPorts1 = cfg->io.win[0].len; | ||
534 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
535 | if (!(cfg->io.flags & CISTPL_IO_8BIT)) | ||
536 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
537 | if (!(cfg->io.flags & CISTPL_IO_16BIT)) | ||
538 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
539 | p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK; | ||
540 | |||
541 | rc = pcmcia_request_io(p_dev, &p_dev->io); | ||
542 | dev_printk(KERN_INFO, &p_dev->dev, | ||
543 | "pcmcia_request_io returned 0x%x\n", rc); | ||
544 | return rc; | ||
545 | } | 520 | } |
546 | 521 | ||
547 | 522 | ||
@@ -550,31 +525,23 @@ static int reader_config(struct pcmcia_device *link, int devno) | |||
550 | struct reader_dev *dev; | 525 | struct reader_dev *dev; |
551 | int fail_rc; | 526 | int fail_rc; |
552 | 527 | ||
553 | link->io.BasePort2 = 0; | 528 | link->config_flags |= CONF_AUTO_SET_IO; |
554 | link->io.NumPorts2 = 0; | ||
555 | link->io.Attributes2 = 0; | ||
556 | 529 | ||
557 | if (pcmcia_loop_config(link, cm4040_config_check, NULL)) | 530 | if (pcmcia_loop_config(link, cm4040_config_check, NULL)) |
558 | goto cs_release; | 531 | goto cs_release; |
559 | 532 | ||
560 | link->conf.IntType = 00000002; | 533 | fail_rc = pcmcia_enable_device(link); |
561 | |||
562 | fail_rc = pcmcia_request_configuration(link, &link->conf); | ||
563 | if (fail_rc != 0) { | 534 | if (fail_rc != 0) { |
564 | dev_printk(KERN_INFO, &link->dev, | 535 | dev_printk(KERN_INFO, &link->dev, |
565 | "pcmcia_request_configuration failed 0x%x\n", | 536 | "pcmcia_enable_device failed 0x%x\n", |
566 | fail_rc); | 537 | fail_rc); |
567 | goto cs_release; | 538 | goto cs_release; |
568 | } | 539 | } |
569 | 540 | ||
570 | dev = link->priv; | 541 | dev = link->priv; |
571 | sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno); | ||
572 | dev->node.major = major; | ||
573 | dev->node.minor = devno; | ||
574 | dev->node.next = &dev->node; | ||
575 | 542 | ||
576 | DEBUGP(2, dev, "device " DEVICE_NAME "%d at 0x%.4x-0x%.4x\n", devno, | 543 | DEBUGP(2, dev, "device " DEVICE_NAME "%d at %pR\n", devno, |
577 | link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1); | 544 | link->resource[0]); |
578 | DEBUGP(2, dev, "<- reader_config (succ)\n"); | 545 | DEBUGP(2, dev, "<- reader_config (succ)\n"); |
579 | 546 | ||
580 | return 0; | 547 | return 0; |
@@ -613,7 +580,6 @@ static int reader_probe(struct pcmcia_device *link) | |||
613 | link->priv = dev; | 580 | link->priv = dev; |
614 | dev->p_dev = link; | 581 | dev->p_dev = link; |
615 | 582 | ||
616 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
617 | dev_table[i] = link; | 583 | dev_table[i] = link; |
618 | 584 | ||
619 | init_waitqueue_head(&dev->devq); | 585 | init_waitqueue_head(&dev->devq); |
@@ -664,6 +630,7 @@ static const struct file_operations reader_fops = { | |||
664 | .open = cm4040_open, | 630 | .open = cm4040_open, |
665 | .release = cm4040_close, | 631 | .release = cm4040_close, |
666 | .poll = cm4040_poll, | 632 | .poll = cm4040_poll, |
633 | .llseek = no_llseek, | ||
667 | }; | 634 | }; |
668 | 635 | ||
669 | static struct pcmcia_device_id cm4040_ids[] = { | 636 | static struct pcmcia_device_id cm4040_ids[] = { |
@@ -676,9 +643,7 @@ MODULE_DEVICE_TABLE(pcmcia, cm4040_ids); | |||
676 | 643 | ||
677 | static struct pcmcia_driver reader_driver = { | 644 | static struct pcmcia_driver reader_driver = { |
678 | .owner = THIS_MODULE, | 645 | .owner = THIS_MODULE, |
679 | .drv = { | 646 | .name = "cm4040_cs", |
680 | .name = "cm4040_cs", | ||
681 | }, | ||
682 | .probe = reader_probe, | 647 | .probe = reader_probe, |
683 | .remove = reader_detach, | 648 | .remove = reader_detach, |
684 | .id_table = cm4040_ids, | 649 | .id_table = cm4040_ids, |
@@ -688,7 +653,6 @@ static int __init cm4040_init(void) | |||
688 | { | 653 | { |
689 | int rc; | 654 | int rc; |
690 | 655 | ||
691 | printk(KERN_INFO "%s\n", version); | ||
692 | cmx_class = class_create(THIS_MODULE, "cardman_4040"); | 656 | cmx_class = class_create(THIS_MODULE, "cardman_4040"); |
693 | if (IS_ERR(cmx_class)) | 657 | if (IS_ERR(cmx_class)) |
694 | return PTR_ERR(cmx_class); | 658 | return PTR_ERR(cmx_class); |
@@ -713,7 +677,6 @@ static int __init cm4040_init(void) | |||
713 | 677 | ||
714 | static void __exit cm4040_exit(void) | 678 | static void __exit cm4040_exit(void) |
715 | { | 679 | { |
716 | printk(KERN_INFO MODULE_NAME ": unloading\n"); | ||
717 | pcmcia_unregister_driver(&reader_driver); | 680 | pcmcia_unregister_driver(&reader_driver); |
718 | unregister_chrdev(major, DEVICE_NAME); | 681 | unregister_chrdev(major, DEVICE_NAME); |
719 | class_destroy(cmx_class); | 682 | class_destroy(cmx_class); |
diff --git a/drivers/char/pcmcia/ipwireless/Makefile b/drivers/char/pcmcia/ipwireless/Makefile index b71eb593643d..db80873d7f20 100644 --- a/drivers/char/pcmcia/ipwireless/Makefile +++ b/drivers/char/pcmcia/ipwireless/Makefile | |||
@@ -6,5 +6,5 @@ | |||
6 | 6 | ||
7 | obj-$(CONFIG_IPWIRELESS) += ipwireless.o | 7 | obj-$(CONFIG_IPWIRELESS) += ipwireless.o |
8 | 8 | ||
9 | ipwireless-objs := hardware.o main.o network.o tty.o | 9 | ipwireless-y := hardware.o main.o network.o tty.o |
10 | 10 | ||
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c index dff24dae1485..94b8eb4d691d 100644 --- a/drivers/char/pcmcia/ipwireless/main.c +++ b/drivers/char/pcmcia/ipwireless/main.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <pcmcia/device_id.h> | 32 | #include <pcmcia/device_id.h> |
33 | #include <pcmcia/ss.h> | 33 | #include <pcmcia/ss.h> |
34 | #include <pcmcia/ds.h> | 34 | #include <pcmcia/ds.h> |
35 | #include <pcmcia/cs.h> | ||
36 | 35 | ||
37 | static struct pcmcia_device_id ipw_ids[] = { | 36 | static struct pcmcia_device_id ipw_ids[] = { |
38 | PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100), | 37 | PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100), |
@@ -76,105 +75,72 @@ static void signalled_reboot_callback(void *callback_data) | |||
76 | schedule_work(&ipw->work_reboot); | 75 | schedule_work(&ipw->work_reboot); |
77 | } | 76 | } |
78 | 77 | ||
79 | static int ipwireless_probe(struct pcmcia_device *p_dev, | 78 | static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data) |
80 | cistpl_cftable_entry_t *cfg, | ||
81 | cistpl_cftable_entry_t *dflt, | ||
82 | unsigned int vcc, | ||
83 | void *priv_data) | ||
84 | { | 79 | { |
85 | struct ipw_dev *ipw = priv_data; | 80 | struct ipw_dev *ipw = priv_data; |
86 | struct resource *io_resource; | 81 | struct resource *io_resource; |
87 | memreq_t memreq_attr_memory; | ||
88 | memreq_t memreq_common_memory; | ||
89 | int ret; | 82 | int ret; |
90 | 83 | ||
91 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | 84 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
92 | p_dev->io.BasePort1 = cfg->io.win[0].base; | 85 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; |
93 | p_dev->io.NumPorts1 = cfg->io.win[0].len; | ||
94 | p_dev->io.IOAddrLines = 16; | ||
95 | 86 | ||
96 | /* 0x40 causes it to generate level mode interrupts. */ | 87 | /* 0x40 causes it to generate level mode interrupts. */ |
97 | /* 0x04 enables IREQ pin. */ | 88 | /* 0x04 enables IREQ pin. */ |
98 | p_dev->conf.ConfigIndex = cfg->index | 0x44; | 89 | p_dev->config_index |= 0x44; |
99 | ret = pcmcia_request_io(p_dev, &p_dev->io); | 90 | p_dev->io_lines = 16; |
91 | ret = pcmcia_request_io(p_dev); | ||
100 | if (ret) | 92 | if (ret) |
101 | return ret; | 93 | return ret; |
102 | 94 | ||
103 | io_resource = request_region(p_dev->io.BasePort1, p_dev->io.NumPorts1, | 95 | io_resource = request_region(p_dev->resource[0]->start, |
96 | resource_size(p_dev->resource[0]), | ||
104 | IPWIRELESS_PCCARD_NAME); | 97 | IPWIRELESS_PCCARD_NAME); |
105 | 98 | ||
106 | if (cfg->mem.nwin == 0) | 99 | p_dev->resource[2]->flags |= |
107 | return 0; | ||
108 | |||
109 | ipw->request_common_memory.Attributes = | ||
110 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; | 100 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; |
111 | ipw->request_common_memory.Base = cfg->mem.win[0].host_addr; | ||
112 | ipw->request_common_memory.Size = cfg->mem.win[0].len; | ||
113 | if (ipw->request_common_memory.Size < 0x1000) | ||
114 | ipw->request_common_memory.Size = 0x1000; | ||
115 | ipw->request_common_memory.AccessSpeed = 0; | ||
116 | |||
117 | ret = pcmcia_request_window(p_dev, &ipw->request_common_memory, | ||
118 | &ipw->handle_common_memory); | ||
119 | 101 | ||
102 | ret = pcmcia_request_window(p_dev, p_dev->resource[2], 0); | ||
120 | if (ret != 0) | 103 | if (ret != 0) |
121 | goto exit1; | 104 | goto exit1; |
122 | 105 | ||
123 | memreq_common_memory.CardOffset = cfg->mem.win[0].card_addr; | 106 | ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2], p_dev->card_addr); |
124 | memreq_common_memory.Page = 0; | ||
125 | |||
126 | ret = pcmcia_map_mem_page(p_dev, ipw->handle_common_memory, | ||
127 | &memreq_common_memory); | ||
128 | |||
129 | if (ret != 0) | 107 | if (ret != 0) |
130 | goto exit2; | 108 | goto exit2; |
131 | 109 | ||
132 | ipw->is_v2_card = cfg->mem.win[0].len == 0x100; | 110 | ipw->is_v2_card = resource_size(p_dev->resource[2]) == 0x100; |
133 | 111 | ||
134 | ipw->common_memory = ioremap(ipw->request_common_memory.Base, | 112 | ipw->attr_memory = ioremap(p_dev->resource[2]->start, |
135 | ipw->request_common_memory.Size); | 113 | resource_size(p_dev->resource[2])); |
136 | request_mem_region(ipw->request_common_memory.Base, | 114 | request_mem_region(p_dev->resource[2]->start, |
137 | ipw->request_common_memory.Size, | 115 | resource_size(p_dev->resource[2]), |
138 | IPWIRELESS_PCCARD_NAME); | 116 | IPWIRELESS_PCCARD_NAME); |
139 | 117 | ||
140 | ipw->request_attr_memory.Attributes = | 118 | p_dev->resource[3]->flags |= WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | |
141 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; | 119 | WIN_ENABLE; |
142 | ipw->request_attr_memory.Base = 0; | 120 | p_dev->resource[3]->end = 0; /* this used to be 0x1000 */ |
143 | ipw->request_attr_memory.Size = 0; /* this used to be 0x1000 */ | 121 | ret = pcmcia_request_window(p_dev, p_dev->resource[3], 0); |
144 | ipw->request_attr_memory.AccessSpeed = 0; | ||
145 | |||
146 | ret = pcmcia_request_window(p_dev, &ipw->request_attr_memory, | ||
147 | &ipw->handle_attr_memory); | ||
148 | |||
149 | if (ret != 0) | 122 | if (ret != 0) |
150 | goto exit2; | 123 | goto exit2; |
151 | 124 | ||
152 | memreq_attr_memory.CardOffset = 0; | 125 | ret = pcmcia_map_mem_page(p_dev, p_dev->resource[3], 0); |
153 | memreq_attr_memory.Page = 0; | ||
154 | |||
155 | ret = pcmcia_map_mem_page(p_dev, ipw->handle_attr_memory, | ||
156 | &memreq_attr_memory); | ||
157 | |||
158 | if (ret != 0) | 126 | if (ret != 0) |
159 | goto exit3; | 127 | goto exit3; |
160 | 128 | ||
161 | ipw->attr_memory = ioremap(ipw->request_attr_memory.Base, | 129 | ipw->attr_memory = ioremap(p_dev->resource[3]->start, |
162 | ipw->request_attr_memory.Size); | 130 | resource_size(p_dev->resource[3])); |
163 | request_mem_region(ipw->request_attr_memory.Base, | 131 | request_mem_region(p_dev->resource[3]->start, |
164 | ipw->request_attr_memory.Size, IPWIRELESS_PCCARD_NAME); | 132 | resource_size(p_dev->resource[3]), |
133 | IPWIRELESS_PCCARD_NAME); | ||
165 | 134 | ||
166 | return 0; | 135 | return 0; |
167 | 136 | ||
168 | exit3: | 137 | exit3: |
169 | pcmcia_release_window(p_dev, ipw->handle_attr_memory); | ||
170 | exit2: | 138 | exit2: |
171 | if (ipw->common_memory) { | 139 | if (ipw->common_memory) { |
172 | release_mem_region(ipw->request_common_memory.Base, | 140 | release_mem_region(p_dev->resource[2]->start, |
173 | ipw->request_common_memory.Size); | 141 | resource_size(p_dev->resource[2])); |
174 | iounmap(ipw->common_memory); | 142 | iounmap(ipw->common_memory); |
175 | pcmcia_release_window(p_dev, ipw->handle_common_memory); | 143 | } |
176 | } else | ||
177 | pcmcia_release_window(p_dev, ipw->handle_common_memory); | ||
178 | exit1: | 144 | exit1: |
179 | release_resource(io_resource); | 145 | release_resource(io_resource); |
180 | pcmcia_disable_device(p_dev); | 146 | pcmcia_disable_device(p_dev); |
@@ -187,53 +153,40 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
187 | int ret = 0; | 153 | int ret = 0; |
188 | 154 | ||
189 | ipw->is_v2_card = 0; | 155 | ipw->is_v2_card = 0; |
156 | link->config_flags |= CONF_AUTO_SET_IO | CONF_AUTO_SET_IOMEM | | ||
157 | CONF_ENABLE_IRQ; | ||
190 | 158 | ||
191 | ret = pcmcia_loop_config(link, ipwireless_probe, ipw); | 159 | ret = pcmcia_loop_config(link, ipwireless_probe, ipw); |
192 | if (ret != 0) | 160 | if (ret != 0) |
193 | return ret; | 161 | return ret; |
194 | 162 | ||
195 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
196 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
197 | |||
198 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; | ||
199 | link->irq.Handler = ipwireless_interrupt; | ||
200 | |||
201 | INIT_WORK(&ipw->work_reboot, signalled_reboot_work); | 163 | INIT_WORK(&ipw->work_reboot, signalled_reboot_work); |
202 | 164 | ||
203 | ipwireless_init_hardware_v1(ipw->hardware, link->io.BasePort1, | 165 | ipwireless_init_hardware_v1(ipw->hardware, link->resource[0]->start, |
204 | ipw->attr_memory, ipw->common_memory, | 166 | ipw->attr_memory, ipw->common_memory, |
205 | ipw->is_v2_card, signalled_reboot_callback, | 167 | ipw->is_v2_card, signalled_reboot_callback, |
206 | ipw); | 168 | ipw); |
207 | 169 | ||
208 | ret = pcmcia_request_irq(link, &link->irq); | 170 | ret = pcmcia_request_irq(link, ipwireless_interrupt); |
209 | |||
210 | if (ret != 0) | 171 | if (ret != 0) |
211 | goto exit; | 172 | goto exit; |
212 | 173 | ||
213 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n", | 174 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n", |
214 | ipw->is_v2_card ? "V2/V3" : "V1"); | 175 | ipw->is_v2_card ? "V2/V3" : "V1"); |
215 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME | 176 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME |
216 | ": I/O ports 0x%04x-0x%04x, irq %d\n", | 177 | ": I/O ports %pR, irq %d\n", link->resource[0], |
217 | (unsigned int) link->io.BasePort1, | 178 | (unsigned int) link->irq); |
218 | (unsigned int) (link->io.BasePort1 + | ||
219 | link->io.NumPorts1 - 1), | ||
220 | (unsigned int) link->irq.AssignedIRQ); | ||
221 | if (ipw->attr_memory && ipw->common_memory) | 179 | if (ipw->attr_memory && ipw->common_memory) |
222 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME | 180 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME |
223 | ": attr memory 0x%08lx-0x%08lx, common memory 0x%08lx-0x%08lx\n", | 181 | ": attr memory %pR, common memory %pR\n", |
224 | ipw->request_attr_memory.Base, | 182 | link->resource[3], |
225 | ipw->request_attr_memory.Base | 183 | link->resource[2]); |
226 | + ipw->request_attr_memory.Size - 1, | ||
227 | ipw->request_common_memory.Base, | ||
228 | ipw->request_common_memory.Base | ||
229 | + ipw->request_common_memory.Size - 1); | ||
230 | 184 | ||
231 | ipw->network = ipwireless_network_create(ipw->hardware); | 185 | ipw->network = ipwireless_network_create(ipw->hardware); |
232 | if (!ipw->network) | 186 | if (!ipw->network) |
233 | goto exit; | 187 | goto exit; |
234 | 188 | ||
235 | ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network, | 189 | ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network); |
236 | ipw->nodes); | ||
237 | if (!ipw->tty) | 190 | if (!ipw->tty) |
238 | goto exit; | 191 | goto exit; |
239 | 192 | ||
@@ -243,27 +196,22 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
243 | * Do the RequestConfiguration last, because it enables interrupts. | 196 | * Do the RequestConfiguration last, because it enables interrupts. |
244 | * Then we don't get any interrupts before we're ready for them. | 197 | * Then we don't get any interrupts before we're ready for them. |
245 | */ | 198 | */ |
246 | ret = pcmcia_request_configuration(link, &link->conf); | 199 | ret = pcmcia_enable_device(link); |
247 | |||
248 | if (ret != 0) | 200 | if (ret != 0) |
249 | goto exit; | 201 | goto exit; |
250 | 202 | ||
251 | link->dev_node = &ipw->nodes[0]; | ||
252 | |||
253 | return 0; | 203 | return 0; |
254 | 204 | ||
255 | exit: | 205 | exit: |
256 | if (ipw->attr_memory) { | ||
257 | release_mem_region(ipw->request_attr_memory.Base, | ||
258 | ipw->request_attr_memory.Size); | ||
259 | iounmap(ipw->attr_memory); | ||
260 | pcmcia_release_window(link, ipw->handle_attr_memory); | ||
261 | } | ||
262 | if (ipw->common_memory) { | 206 | if (ipw->common_memory) { |
263 | release_mem_region(ipw->request_common_memory.Base, | 207 | release_mem_region(link->resource[2]->start, |
264 | ipw->request_common_memory.Size); | 208 | resource_size(link->resource[2])); |
265 | iounmap(ipw->common_memory); | 209 | iounmap(ipw->common_memory); |
266 | pcmcia_release_window(link, ipw->handle_common_memory); | 210 | } |
211 | if (ipw->attr_memory) { | ||
212 | release_mem_region(link->resource[3]->start, | ||
213 | resource_size(link->resource[3])); | ||
214 | iounmap(ipw->attr_memory); | ||
267 | } | 215 | } |
268 | pcmcia_disable_device(link); | 216 | pcmcia_disable_device(link); |
269 | return -1; | 217 | return -1; |
@@ -271,24 +219,16 @@ exit: | |||
271 | 219 | ||
272 | static void release_ipwireless(struct ipw_dev *ipw) | 220 | static void release_ipwireless(struct ipw_dev *ipw) |
273 | { | 221 | { |
274 | pcmcia_disable_device(ipw->link); | ||
275 | |||
276 | if (ipw->common_memory) { | 222 | if (ipw->common_memory) { |
277 | release_mem_region(ipw->request_common_memory.Base, | 223 | release_mem_region(ipw->link->resource[2]->start, |
278 | ipw->request_common_memory.Size); | 224 | resource_size(ipw->link->resource[2])); |
279 | iounmap(ipw->common_memory); | 225 | iounmap(ipw->common_memory); |
280 | } | 226 | } |
281 | if (ipw->attr_memory) { | 227 | if (ipw->attr_memory) { |
282 | release_mem_region(ipw->request_attr_memory.Base, | 228 | release_mem_region(ipw->link->resource[3]->start, |
283 | ipw->request_attr_memory.Size); | 229 | resource_size(ipw->link->resource[3])); |
284 | iounmap(ipw->attr_memory); | 230 | iounmap(ipw->attr_memory); |
285 | } | 231 | } |
286 | if (ipw->common_memory) | ||
287 | pcmcia_release_window(ipw->link, ipw->handle_common_memory); | ||
288 | if (ipw->attr_memory) | ||
289 | pcmcia_release_window(ipw->link, ipw->handle_attr_memory); | ||
290 | |||
291 | /* Break the link with Card Services */ | ||
292 | pcmcia_disable_device(ipw->link); | 232 | pcmcia_disable_device(ipw->link); |
293 | } | 233 | } |
294 | 234 | ||
@@ -313,9 +253,6 @@ static int ipwireless_attach(struct pcmcia_device *link) | |||
313 | ipw->link = link; | 253 | ipw->link = link; |
314 | link->priv = ipw; | 254 | link->priv = ipw; |
315 | 255 | ||
316 | /* Link this device into our device list. */ | ||
317 | link->dev_node = &ipw->nodes[0]; | ||
318 | |||
319 | ipw->hardware = ipwireless_hardware_create(); | 256 | ipw->hardware = ipwireless_hardware_create(); |
320 | if (!ipw->hardware) { | 257 | if (!ipw->hardware) { |
321 | kfree(ipw); | 258 | kfree(ipw); |
@@ -358,7 +295,7 @@ static struct pcmcia_driver me = { | |||
358 | .owner = THIS_MODULE, | 295 | .owner = THIS_MODULE, |
359 | .probe = ipwireless_attach, | 296 | .probe = ipwireless_attach, |
360 | .remove = ipwireless_detach, | 297 | .remove = ipwireless_detach, |
361 | .drv = { .name = IPWIRELESS_PCCARD_NAME }, | 298 | .name = IPWIRELESS_PCCARD_NAME, |
362 | .id_table = ipw_ids | 299 | .id_table = ipw_ids |
363 | }; | 300 | }; |
364 | 301 | ||
@@ -370,9 +307,6 @@ static int __init init_ipwireless(void) | |||
370 | { | 307 | { |
371 | int ret; | 308 | int ret; |
372 | 309 | ||
373 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME " " | ||
374 | IPWIRELESS_PCMCIA_VERSION " by " IPWIRELESS_PCMCIA_AUTHOR "\n"); | ||
375 | |||
376 | ret = ipwireless_tty_init(); | 310 | ret = ipwireless_tty_init(); |
377 | if (ret != 0) | 311 | if (ret != 0) |
378 | return ret; | 312 | return ret; |
@@ -389,9 +323,6 @@ static int __init init_ipwireless(void) | |||
389 | */ | 323 | */ |
390 | static void __exit exit_ipwireless(void) | 324 | static void __exit exit_ipwireless(void) |
391 | { | 325 | { |
392 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME " " | ||
393 | IPWIRELESS_PCMCIA_VERSION " removed\n"); | ||
394 | |||
395 | pcmcia_unregister_driver(&me); | 326 | pcmcia_unregister_driver(&me); |
396 | ipwireless_tty_release(); | 327 | ipwireless_tty_release(); |
397 | } | 328 | } |
diff --git a/drivers/char/pcmcia/ipwireless/main.h b/drivers/char/pcmcia/ipwireless/main.h index 0e0363af9ab2..f2cbb116bccb 100644 --- a/drivers/char/pcmcia/ipwireless/main.h +++ b/drivers/char/pcmcia/ipwireless/main.h | |||
@@ -21,8 +21,6 @@ | |||
21 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
22 | #include <linux/types.h> | 22 | #include <linux/types.h> |
23 | 23 | ||
24 | #include <pcmcia/cs_types.h> | ||
25 | #include <pcmcia/cs.h> | ||
26 | #include <pcmcia/cistpl.h> | 24 | #include <pcmcia/cistpl.h> |
27 | #include <pcmcia/ds.h> | 25 | #include <pcmcia/ds.h> |
28 | 26 | ||
@@ -46,15 +44,10 @@ struct ipw_dev { | |||
46 | struct pcmcia_device *link; | 44 | struct pcmcia_device *link; |
47 | int is_v2_card; | 45 | int is_v2_card; |
48 | 46 | ||
49 | window_handle_t handle_attr_memory; | ||
50 | void __iomem *attr_memory; | 47 | void __iomem *attr_memory; |
51 | win_req_t request_attr_memory; | ||
52 | 48 | ||
53 | window_handle_t handle_common_memory; | ||
54 | void __iomem *common_memory; | 49 | void __iomem *common_memory; |
55 | win_req_t request_common_memory; | ||
56 | 50 | ||
57 | dev_node_t nodes[2]; | ||
58 | /* Reference to attribute memory, containing CIS data */ | 51 | /* Reference to attribute memory, containing CIS data */ |
59 | void *attribute_memory; | 52 | void *attribute_memory; |
60 | 53 | ||
diff --git a/drivers/char/pcmcia/ipwireless/network.c b/drivers/char/pcmcia/ipwireless/network.c index 590762a7f217..9fe538347932 100644 --- a/drivers/char/pcmcia/ipwireless/network.c +++ b/drivers/char/pcmcia/ipwireless/network.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/netdevice.h> | 21 | #include <linux/netdevice.h> |
22 | #include <linux/ppp_channel.h> | 22 | #include <linux/ppp_channel.h> |
23 | #include <linux/ppp_defs.h> | 23 | #include <linux/ppp_defs.h> |
24 | #include <linux/slab.h> | ||
24 | #include <linux/if_ppp.h> | 25 | #include <linux/if_ppp.h> |
25 | #include <linux/skbuff.h> | 26 | #include <linux/skbuff.h> |
26 | 27 | ||
@@ -238,7 +239,7 @@ static int ipwireless_ppp_ioctl(struct ppp_channel *ppp_channel, | |||
238 | return err; | 239 | return err; |
239 | } | 240 | } |
240 | 241 | ||
241 | static struct ppp_channel_ops ipwireless_ppp_channel_ops = { | 242 | static const struct ppp_channel_ops ipwireless_ppp_channel_ops = { |
242 | .start_xmit = ipwireless_ppp_start_xmit, | 243 | .start_xmit = ipwireless_ppp_start_xmit, |
243 | .ioctl = ipwireless_ppp_ioctl | 244 | .ioctl = ipwireless_ppp_ioctl |
244 | }; | 245 | }; |
diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c index 2bb7874a6899..1a2c2c3b068f 100644 --- a/drivers/char/pcmcia/ipwireless/tty.c +++ b/drivers/char/pcmcia/ipwireless/tty.c | |||
@@ -487,7 +487,7 @@ static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file, | |||
487 | return tty_mode_ioctl(linux_tty, file, cmd , arg); | 487 | return tty_mode_ioctl(linux_tty, file, cmd , arg); |
488 | } | 488 | } |
489 | 489 | ||
490 | static int add_tty(dev_node_t *nodesp, int j, | 490 | static int add_tty(int j, |
491 | struct ipw_hardware *hardware, | 491 | struct ipw_hardware *hardware, |
492 | struct ipw_network *network, int channel_idx, | 492 | struct ipw_network *network, int channel_idx, |
493 | int secondary_channel_idx, int tty_type) | 493 | int secondary_channel_idx, int tty_type) |
@@ -510,19 +510,13 @@ static int add_tty(dev_node_t *nodesp, int j, | |||
510 | ipwireless_associate_network_tty(network, | 510 | ipwireless_associate_network_tty(network, |
511 | secondary_channel_idx, | 511 | secondary_channel_idx, |
512 | ttys[j]); | 512 | ttys[j]); |
513 | if (nodesp != NULL) { | ||
514 | sprintf(nodesp->dev_name, "ttyIPWp%d", j); | ||
515 | nodesp->major = ipw_tty_driver->major; | ||
516 | nodesp->minor = j + ipw_tty_driver->minor_start; | ||
517 | } | ||
518 | if (get_tty(j + ipw_tty_driver->minor_start) == ttys[j]) | 513 | if (get_tty(j + ipw_tty_driver->minor_start) == ttys[j]) |
519 | report_registering(ttys[j]); | 514 | report_registering(ttys[j]); |
520 | return 0; | 515 | return 0; |
521 | } | 516 | } |
522 | 517 | ||
523 | struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hardware, | 518 | struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hardware, |
524 | struct ipw_network *network, | 519 | struct ipw_network *network) |
525 | dev_node_t *nodes) | ||
526 | { | 520 | { |
527 | int i, j; | 521 | int i, j; |
528 | 522 | ||
@@ -539,26 +533,23 @@ struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hardware, | |||
539 | if (allfree) { | 533 | if (allfree) { |
540 | j = i; | 534 | j = i; |
541 | 535 | ||
542 | if (add_tty(&nodes[0], j, hardware, network, | 536 | if (add_tty(j, hardware, network, |
543 | IPW_CHANNEL_DIALLER, IPW_CHANNEL_RAS, | 537 | IPW_CHANNEL_DIALLER, IPW_CHANNEL_RAS, |
544 | TTYTYPE_MODEM)) | 538 | TTYTYPE_MODEM)) |
545 | return NULL; | 539 | return NULL; |
546 | 540 | ||
547 | j += IPWIRELESS_PCMCIA_MINOR_RANGE; | 541 | j += IPWIRELESS_PCMCIA_MINOR_RANGE; |
548 | if (add_tty(&nodes[1], j, hardware, network, | 542 | if (add_tty(j, hardware, network, |
549 | IPW_CHANNEL_DIALLER, -1, | 543 | IPW_CHANNEL_DIALLER, -1, |
550 | TTYTYPE_MONITOR)) | 544 | TTYTYPE_MONITOR)) |
551 | return NULL; | 545 | return NULL; |
552 | 546 | ||
553 | j += IPWIRELESS_PCMCIA_MINOR_RANGE; | 547 | j += IPWIRELESS_PCMCIA_MINOR_RANGE; |
554 | if (add_tty(NULL, j, hardware, network, | 548 | if (add_tty(j, hardware, network, |
555 | IPW_CHANNEL_RAS, -1, | 549 | IPW_CHANNEL_RAS, -1, |
556 | TTYTYPE_RAS_RAW)) | 550 | TTYTYPE_RAS_RAW)) |
557 | return NULL; | 551 | return NULL; |
558 | 552 | ||
559 | nodes[0].next = &nodes[1]; | ||
560 | nodes[1].next = NULL; | ||
561 | |||
562 | return ttys[i]; | 553 | return ttys[i]; |
563 | } | 554 | } |
564 | } | 555 | } |
diff --git a/drivers/char/pcmcia/ipwireless/tty.h b/drivers/char/pcmcia/ipwireless/tty.h index b0deb9168b6b..747b2d637860 100644 --- a/drivers/char/pcmcia/ipwireless/tty.h +++ b/drivers/char/pcmcia/ipwireless/tty.h | |||
@@ -21,8 +21,6 @@ | |||
21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
22 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
23 | 23 | ||
24 | #include <pcmcia/cs_types.h> | ||
25 | #include <pcmcia/cs.h> | ||
26 | #include <pcmcia/cistpl.h> | 24 | #include <pcmcia/cistpl.h> |
27 | #include <pcmcia/ds.h> | 25 | #include <pcmcia/ds.h> |
28 | 26 | ||
@@ -34,8 +32,7 @@ int ipwireless_tty_init(void); | |||
34 | void ipwireless_tty_release(void); | 32 | void ipwireless_tty_release(void); |
35 | 33 | ||
36 | struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hw, | 34 | struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hw, |
37 | struct ipw_network *net, | 35 | struct ipw_network *net); |
38 | dev_node_t *nodes); | ||
39 | void ipwireless_tty_free(struct ipw_tty *tty); | 36 | void ipwireless_tty_free(struct ipw_tty *tty); |
40 | void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data, | 37 | void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data, |
41 | unsigned int length); | 38 | unsigned int length); |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index c31a0d913d37..bfc10f89d951 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -70,8 +70,6 @@ | |||
70 | #include <linux/workqueue.h> | 70 | #include <linux/workqueue.h> |
71 | #include <linux/hdlc.h> | 71 | #include <linux/hdlc.h> |
72 | 72 | ||
73 | #include <pcmcia/cs_types.h> | ||
74 | #include <pcmcia/cs.h> | ||
75 | #include <pcmcia/cistpl.h> | 73 | #include <pcmcia/cistpl.h> |
76 | #include <pcmcia/cisreg.h> | 74 | #include <pcmcia/cisreg.h> |
77 | #include <pcmcia/ds.h> | 75 | #include <pcmcia/ds.h> |
@@ -220,7 +218,6 @@ typedef struct _mgslpc_info { | |||
220 | 218 | ||
221 | /* PCMCIA support */ | 219 | /* PCMCIA support */ |
222 | struct pcmcia_device *p_dev; | 220 | struct pcmcia_device *p_dev; |
223 | dev_node_t node; | ||
224 | int stop; | 221 | int stop; |
225 | 222 | ||
226 | /* SPPP/Cisco HDLC device parts */ | 223 | /* SPPP/Cisco HDLC device parts */ |
@@ -552,13 +549,6 @@ static int mgslpc_probe(struct pcmcia_device *link) | |||
552 | 549 | ||
553 | /* Initialize the struct pcmcia_device structure */ | 550 | /* Initialize the struct pcmcia_device structure */ |
554 | 551 | ||
555 | /* Interrupt setup */ | ||
556 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; | ||
557 | link->irq.Handler = NULL; | ||
558 | |||
559 | link->conf.Attributes = 0; | ||
560 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
561 | |||
562 | ret = mgslpc_config(link); | 552 | ret = mgslpc_config(link); |
563 | if (ret) | 553 | if (ret) |
564 | return ret; | 554 | return ret; |
@@ -571,24 +561,9 @@ static int mgslpc_probe(struct pcmcia_device *link) | |||
571 | /* Card has been inserted. | 561 | /* Card has been inserted. |
572 | */ | 562 | */ |
573 | 563 | ||
574 | static int mgslpc_ioprobe(struct pcmcia_device *p_dev, | 564 | static int mgslpc_ioprobe(struct pcmcia_device *p_dev, void *priv_data) |
575 | cistpl_cftable_entry_t *cfg, | ||
576 | cistpl_cftable_entry_t *dflt, | ||
577 | unsigned int vcc, | ||
578 | void *priv_data) | ||
579 | { | 565 | { |
580 | if (cfg->io.nwin > 0) { | 566 | return pcmcia_request_io(p_dev); |
581 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
582 | if (!(cfg->io.flags & CISTPL_IO_8BIT)) | ||
583 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
584 | if (!(cfg->io.flags & CISTPL_IO_16BIT)) | ||
585 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
586 | p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK; | ||
587 | p_dev->io.BasePort1 = cfg->io.win[0].base; | ||
588 | p_dev->io.NumPorts1 = cfg->io.win[0].len; | ||
589 | return pcmcia_request_io(p_dev, &p_dev->io); | ||
590 | } | ||
591 | return -ENODEV; | ||
592 | } | 567 | } |
593 | 568 | ||
594 | static int mgslpc_config(struct pcmcia_device *link) | 569 | static int mgslpc_config(struct pcmcia_device *link) |
@@ -599,40 +574,24 @@ static int mgslpc_config(struct pcmcia_device *link) | |||
599 | if (debug_level >= DEBUG_LEVEL_INFO) | 574 | if (debug_level >= DEBUG_LEVEL_INFO) |
600 | printk("mgslpc_config(0x%p)\n", link); | 575 | printk("mgslpc_config(0x%p)\n", link); |
601 | 576 | ||
577 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; | ||
578 | |||
602 | ret = pcmcia_loop_config(link, mgslpc_ioprobe, NULL); | 579 | ret = pcmcia_loop_config(link, mgslpc_ioprobe, NULL); |
603 | if (ret != 0) | 580 | if (ret != 0) |
604 | goto failed; | 581 | goto failed; |
605 | 582 | ||
606 | link->conf.Attributes = CONF_ENABLE_IRQ; | 583 | link->config_index = 8; |
607 | link->conf.IntType = INT_MEMORY_AND_IO; | 584 | link->config_regs = PRESENT_OPTION; |
608 | link->conf.ConfigIndex = 8; | ||
609 | link->conf.Present = PRESENT_OPTION; | ||
610 | 585 | ||
611 | link->irq.Handler = mgslpc_isr; | 586 | ret = pcmcia_request_irq(link, mgslpc_isr); |
612 | |||
613 | ret = pcmcia_request_irq(link, &link->irq); | ||
614 | if (ret) | 587 | if (ret) |
615 | goto failed; | 588 | goto failed; |
616 | ret = pcmcia_request_configuration(link, &link->conf); | 589 | ret = pcmcia_enable_device(link); |
617 | if (ret) | 590 | if (ret) |
618 | goto failed; | 591 | goto failed; |
619 | 592 | ||
620 | info->io_base = link->io.BasePort1; | 593 | info->io_base = link->resource[0]->start; |
621 | info->irq_level = link->irq.AssignedIRQ; | 594 | info->irq_level = link->irq; |
622 | |||
623 | /* add to linked list of devices */ | ||
624 | sprintf(info->node.dev_name, "mgslpc0"); | ||
625 | info->node.major = info->node.minor = 0; | ||
626 | link->dev_node = &info->node; | ||
627 | |||
628 | printk(KERN_INFO "%s: index 0x%02x:", | ||
629 | info->node.dev_name, link->conf.ConfigIndex); | ||
630 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | ||
631 | printk(", irq %d", link->irq.AssignedIRQ); | ||
632 | if (link->io.NumPorts1) | ||
633 | printk(", io 0x%04x-0x%04x", link->io.BasePort1, | ||
634 | link->io.BasePort1+link->io.NumPorts1-1); | ||
635 | printk("\n"); | ||
636 | return 0; | 595 | return 0; |
637 | 596 | ||
638 | failed: | 597 | failed: |
@@ -2232,6 +2191,32 @@ static int mgslpc_break(struct tty_struct *tty, int break_state) | |||
2232 | return 0; | 2191 | return 0; |
2233 | } | 2192 | } |
2234 | 2193 | ||
2194 | static int mgslpc_get_icount(struct tty_struct *tty, | ||
2195 | struct serial_icounter_struct *icount) | ||
2196 | { | ||
2197 | MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; | ||
2198 | struct mgsl_icount cnow; /* kernel counter temps */ | ||
2199 | unsigned long flags; | ||
2200 | |||
2201 | spin_lock_irqsave(&info->lock,flags); | ||
2202 | cnow = info->icount; | ||
2203 | spin_unlock_irqrestore(&info->lock,flags); | ||
2204 | |||
2205 | icount->cts = cnow.cts; | ||
2206 | icount->dsr = cnow.dsr; | ||
2207 | icount->rng = cnow.rng; | ||
2208 | icount->dcd = cnow.dcd; | ||
2209 | icount->rx = cnow.rx; | ||
2210 | icount->tx = cnow.tx; | ||
2211 | icount->frame = cnow.frame; | ||
2212 | icount->overrun = cnow.overrun; | ||
2213 | icount->parity = cnow.parity; | ||
2214 | icount->brk = cnow.brk; | ||
2215 | icount->buf_overrun = cnow.buf_overrun; | ||
2216 | |||
2217 | return 0; | ||
2218 | } | ||
2219 | |||
2235 | /* Service an IOCTL request | 2220 | /* Service an IOCTL request |
2236 | * | 2221 | * |
2237 | * Arguments: | 2222 | * Arguments: |
@@ -2247,11 +2232,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file, | |||
2247 | unsigned int cmd, unsigned long arg) | 2232 | unsigned int cmd, unsigned long arg) |
2248 | { | 2233 | { |
2249 | MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; | 2234 | MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; |
2250 | int error; | ||
2251 | struct mgsl_icount cnow; /* kernel counter temps */ | ||
2252 | struct serial_icounter_struct __user *p_cuser; /* user space */ | ||
2253 | void __user *argp = (void __user *)arg; | 2235 | void __user *argp = (void __user *)arg; |
2254 | unsigned long flags; | ||
2255 | 2236 | ||
2256 | if (debug_level >= DEBUG_LEVEL_INFO) | 2237 | if (debug_level >= DEBUG_LEVEL_INFO) |
2257 | printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__, | 2238 | printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__, |
@@ -2261,7 +2242,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file, | |||
2261 | return -ENODEV; | 2242 | return -ENODEV; |
2262 | 2243 | ||
2263 | if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && | 2244 | if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && |
2264 | (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { | 2245 | (cmd != TIOCMIWAIT)) { |
2265 | if (tty->flags & (1 << TTY_IO_ERROR)) | 2246 | if (tty->flags & (1 << TTY_IO_ERROR)) |
2266 | return -EIO; | 2247 | return -EIO; |
2267 | } | 2248 | } |
@@ -2291,34 +2272,6 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file, | |||
2291 | return wait_events(info, argp); | 2272 | return wait_events(info, argp); |
2292 | case TIOCMIWAIT: | 2273 | case TIOCMIWAIT: |
2293 | return modem_input_wait(info,(int)arg); | 2274 | return modem_input_wait(info,(int)arg); |
2294 | case TIOCGICOUNT: | ||
2295 | spin_lock_irqsave(&info->lock,flags); | ||
2296 | cnow = info->icount; | ||
2297 | spin_unlock_irqrestore(&info->lock,flags); | ||
2298 | p_cuser = argp; | ||
2299 | PUT_USER(error,cnow.cts, &p_cuser->cts); | ||
2300 | if (error) return error; | ||
2301 | PUT_USER(error,cnow.dsr, &p_cuser->dsr); | ||
2302 | if (error) return error; | ||
2303 | PUT_USER(error,cnow.rng, &p_cuser->rng); | ||
2304 | if (error) return error; | ||
2305 | PUT_USER(error,cnow.dcd, &p_cuser->dcd); | ||
2306 | if (error) return error; | ||
2307 | PUT_USER(error,cnow.rx, &p_cuser->rx); | ||
2308 | if (error) return error; | ||
2309 | PUT_USER(error,cnow.tx, &p_cuser->tx); | ||
2310 | if (error) return error; | ||
2311 | PUT_USER(error,cnow.frame, &p_cuser->frame); | ||
2312 | if (error) return error; | ||
2313 | PUT_USER(error,cnow.overrun, &p_cuser->overrun); | ||
2314 | if (error) return error; | ||
2315 | PUT_USER(error,cnow.parity, &p_cuser->parity); | ||
2316 | if (error) return error; | ||
2317 | PUT_USER(error,cnow.brk, &p_cuser->brk); | ||
2318 | if (error) return error; | ||
2319 | PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun); | ||
2320 | if (error) return error; | ||
2321 | return 0; | ||
2322 | default: | 2275 | default: |
2323 | return -ENOIOCTLCMD; | 2276 | return -ENOIOCTLCMD; |
2324 | } | 2277 | } |
@@ -2814,9 +2767,7 @@ MODULE_DEVICE_TABLE(pcmcia, mgslpc_ids); | |||
2814 | 2767 | ||
2815 | static struct pcmcia_driver mgslpc_driver = { | 2768 | static struct pcmcia_driver mgslpc_driver = { |
2816 | .owner = THIS_MODULE, | 2769 | .owner = THIS_MODULE, |
2817 | .drv = { | 2770 | .name = "synclink_cs", |
2818 | .name = "synclink_cs", | ||
2819 | }, | ||
2820 | .probe = mgslpc_probe, | 2771 | .probe = mgslpc_probe, |
2821 | .remove = mgslpc_detach, | 2772 | .remove = mgslpc_detach, |
2822 | .id_table = mgslpc_ids, | 2773 | .id_table = mgslpc_ids, |
@@ -2852,8 +2803,6 @@ static void synclink_cs_cleanup(void) | |||
2852 | { | 2803 | { |
2853 | int rc; | 2804 | int rc; |
2854 | 2805 | ||
2855 | printk("Unloading %s: version %s\n", driver_name, driver_version); | ||
2856 | |||
2857 | while(mgslpc_device_list) | 2806 | while(mgslpc_device_list) |
2858 | mgslpc_remove_device(mgslpc_device_list); | 2807 | mgslpc_remove_device(mgslpc_device_list); |
2859 | 2808 | ||
@@ -2876,8 +2825,6 @@ static int __init synclink_cs_init(void) | |||
2876 | BREAKPOINT(); | 2825 | BREAKPOINT(); |
2877 | } | 2826 | } |
2878 | 2827 | ||
2879 | printk("%s %s\n", driver_name, driver_version); | ||
2880 | |||
2881 | if ((rc = pcmcia_register_driver(&mgslpc_driver)) < 0) | 2828 | if ((rc = pcmcia_register_driver(&mgslpc_driver)) < 0) |
2882 | return rc; | 2829 | return rc; |
2883 | 2830 | ||
@@ -4144,6 +4091,8 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
4144 | if (cmd != SIOCWANDEV) | 4091 | if (cmd != SIOCWANDEV) |
4145 | return hdlc_ioctl(dev, ifr, cmd); | 4092 | return hdlc_ioctl(dev, ifr, cmd); |
4146 | 4093 | ||
4094 | memset(&new_line, 0, size); | ||
4095 | |||
4147 | switch(ifr->ifr_settings.type) { | 4096 | switch(ifr->ifr_settings.type) { |
4148 | case IF_GET_IFACE: /* return current sync_serial_settings */ | 4097 | case IF_GET_IFACE: /* return current sync_serial_settings */ |
4149 | 4098 | ||
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 432655bcb04c..f176dbaeb15a 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c | |||
@@ -64,9 +64,10 @@ | |||
64 | #include <linux/parport.h> | 64 | #include <linux/parport.h> |
65 | #include <linux/ctype.h> | 65 | #include <linux/ctype.h> |
66 | #include <linux/poll.h> | 66 | #include <linux/poll.h> |
67 | #include <linux/slab.h> | ||
67 | #include <linux/major.h> | 68 | #include <linux/major.h> |
68 | #include <linux/ppdev.h> | 69 | #include <linux/ppdev.h> |
69 | #include <linux/smp_lock.h> | 70 | #include <linux/mutex.h> |
70 | #include <linux/uaccess.h> | 71 | #include <linux/uaccess.h> |
71 | 72 | ||
72 | #define PP_VERSION "ppdev: user-space parallel port driver" | 73 | #define PP_VERSION "ppdev: user-space parallel port driver" |
@@ -96,6 +97,7 @@ struct pp_struct { | |||
96 | /* ROUND_UP macro from fs/select.c */ | 97 | /* ROUND_UP macro from fs/select.c */ |
97 | #define ROUND_UP(x,y) (((x)+(y)-1)/(y)) | 98 | #define ROUND_UP(x,y) (((x)+(y)-1)/(y)) |
98 | 99 | ||
100 | static DEFINE_MUTEX(pp_do_mutex); | ||
99 | static inline void pp_enable_irq (struct pp_struct *pp) | 101 | static inline void pp_enable_irq (struct pp_struct *pp) |
100 | { | 102 | { |
101 | struct parport *port = pp->pdev->port; | 103 | struct parport *port = pp->pdev->port; |
@@ -286,12 +288,10 @@ static int register_device (int minor, struct pp_struct *pp) | |||
286 | char *name; | 288 | char *name; |
287 | int fl; | 289 | int fl; |
288 | 290 | ||
289 | name = kmalloc (strlen (CHRDEV) + 3, GFP_KERNEL); | 291 | name = kasprintf(GFP_KERNEL, CHRDEV "%x", minor); |
290 | if (name == NULL) | 292 | if (name == NULL) |
291 | return -ENOMEM; | 293 | return -ENOMEM; |
292 | 294 | ||
293 | sprintf (name, CHRDEV "%x", minor); | ||
294 | |||
295 | port = parport_find_number (minor); | 295 | port = parport_find_number (minor); |
296 | if (!port) { | 296 | if (!port) { |
297 | printk (KERN_WARNING "%s: no associated port!\n", name); | 297 | printk (KERN_WARNING "%s: no associated port!\n", name); |
@@ -613,6 +613,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
613 | 613 | ||
614 | case PPGETTIME: | 614 | case PPGETTIME: |
615 | to_jiffies = pp->pdev->timeout; | 615 | to_jiffies = pp->pdev->timeout; |
616 | memset(&par_timeout, 0, sizeof(par_timeout)); | ||
616 | par_timeout.tv_sec = to_jiffies / HZ; | 617 | par_timeout.tv_sec = to_jiffies / HZ; |
617 | par_timeout.tv_usec = (to_jiffies % (long)HZ) * (1000000/HZ); | 618 | par_timeout.tv_usec = (to_jiffies % (long)HZ) * (1000000/HZ); |
618 | if (copy_to_user (argp, &par_timeout, sizeof(struct timeval))) | 619 | if (copy_to_user (argp, &par_timeout, sizeof(struct timeval))) |
@@ -631,9 +632,9 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
631 | static long pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 632 | static long pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
632 | { | 633 | { |
633 | long ret; | 634 | long ret; |
634 | lock_kernel(); | 635 | mutex_lock(&pp_do_mutex); |
635 | ret = pp_do_ioctl(file, cmd, arg); | 636 | ret = pp_do_ioctl(file, cmd, arg); |
636 | unlock_kernel(); | 637 | mutex_unlock(&pp_do_mutex); |
637 | return ret; | 638 | return ret; |
638 | } | 639 | } |
639 | 640 | ||
@@ -642,7 +643,6 @@ static int pp_open (struct inode * inode, struct file * file) | |||
642 | unsigned int minor = iminor(inode); | 643 | unsigned int minor = iminor(inode); |
643 | struct pp_struct *pp; | 644 | struct pp_struct *pp; |
644 | 645 | ||
645 | cycle_kernel_lock(); | ||
646 | if (minor >= PARPORT_MAX) | 646 | if (minor >= PARPORT_MAX) |
647 | return -ENXIO; | 647 | return -ENXIO; |
648 | 648 | ||
diff --git a/drivers/char/ps3flash.c b/drivers/char/ps3flash.c index f424d394a286..85c004a518ee 100644 --- a/drivers/char/ps3flash.c +++ b/drivers/char/ps3flash.c | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
22 | #include <linux/miscdevice.h> | 22 | #include <linux/miscdevice.h> |
23 | #include <linux/slab.h> | ||
23 | #include <linux/uaccess.h> | 24 | #include <linux/uaccess.h> |
24 | 25 | ||
25 | #include <asm/lv1call.h> | 26 | #include <asm/lv1call.h> |
@@ -304,8 +305,7 @@ static int ps3flash_flush(struct file *file, fl_owner_t id) | |||
304 | return ps3flash_writeback(ps3flash_dev); | 305 | return ps3flash_writeback(ps3flash_dev); |
305 | } | 306 | } |
306 | 307 | ||
307 | static int ps3flash_fsync(struct file *file, struct dentry *dentry, | 308 | static int ps3flash_fsync(struct file *file, int datasync) |
308 | int datasync) | ||
309 | { | 309 | { |
310 | return ps3flash_writeback(ps3flash_dev); | 310 | return ps3flash_writeback(ps3flash_dev); |
311 | } | 311 | } |
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 385c44b3034f..923a48585501 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/uaccess.h> | 29 | #include <linux/uaccess.h> |
30 | #include <linux/bitops.h> | 30 | #include <linux/bitops.h> |
31 | #include <linux/devpts_fs.h> | 31 | #include <linux/devpts_fs.h> |
32 | #include <linux/slab.h> | ||
32 | 33 | ||
33 | #include <asm/system.h> | 34 | #include <asm/system.h> |
34 | 35 | ||
@@ -61,7 +62,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp) | |||
61 | if (tty->driver == ptm_driver) | 62 | if (tty->driver == ptm_driver) |
62 | devpts_pty_kill(tty->link); | 63 | devpts_pty_kill(tty->link); |
63 | #endif | 64 | #endif |
65 | tty_unlock(); | ||
64 | tty_vhangup(tty->link); | 66 | tty_vhangup(tty->link); |
67 | tty_lock(); | ||
65 | } | 68 | } |
66 | } | 69 | } |
67 | 70 | ||
@@ -170,6 +173,23 @@ static int pty_set_lock(struct tty_struct *tty, int __user *arg) | |||
170 | return 0; | 173 | return 0; |
171 | } | 174 | } |
172 | 175 | ||
176 | /* Send a signal to the slave */ | ||
177 | static int pty_signal(struct tty_struct *tty, int sig) | ||
178 | { | ||
179 | unsigned long flags; | ||
180 | struct pid *pgrp; | ||
181 | |||
182 | if (tty->link) { | ||
183 | spin_lock_irqsave(&tty->link->ctrl_lock, flags); | ||
184 | pgrp = get_pid(tty->link->pgrp); | ||
185 | spin_unlock_irqrestore(&tty->link->ctrl_lock, flags); | ||
186 | |||
187 | kill_pgrp(pgrp, sig, 1); | ||
188 | put_pid(pgrp); | ||
189 | } | ||
190 | return 0; | ||
191 | } | ||
192 | |||
173 | static void pty_flush_buffer(struct tty_struct *tty) | 193 | static void pty_flush_buffer(struct tty_struct *tty) |
174 | { | 194 | { |
175 | struct tty_struct *to = tty->link; | 195 | struct tty_struct *to = tty->link; |
@@ -220,7 +240,7 @@ static void pty_set_termios(struct tty_struct *tty, | |||
220 | * @tty: tty being resized | 240 | * @tty: tty being resized |
221 | * @ws: window size being set. | 241 | * @ws: window size being set. |
222 | * | 242 | * |
223 | * Update the termios variables and send the neccessary signals to | 243 | * Update the termios variables and send the necessary signals to |
224 | * peform a terminal resize correctly | 244 | * peform a terminal resize correctly |
225 | */ | 245 | */ |
226 | 246 | ||
@@ -320,6 +340,8 @@ static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file, | |||
320 | switch (cmd) { | 340 | switch (cmd) { |
321 | case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ | 341 | case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ |
322 | return pty_set_lock(tty, (int __user *) arg); | 342 | return pty_set_lock(tty, (int __user *) arg); |
343 | case TIOCSIG: /* Send signal to other side of pty */ | ||
344 | return pty_signal(tty, (int) arg); | ||
323 | } | 345 | } |
324 | return -ENOIOCTLCMD; | 346 | return -ENOIOCTLCMD; |
325 | } | 347 | } |
@@ -475,6 +497,8 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file, | |||
475 | return pty_set_lock(tty, (int __user *)arg); | 497 | return pty_set_lock(tty, (int __user *)arg); |
476 | case TIOCGPTN: /* Get PT Number */ | 498 | case TIOCGPTN: /* Get PT Number */ |
477 | return put_user(tty->index, (unsigned int __user *)arg); | 499 | return put_user(tty->index, (unsigned int __user *)arg); |
500 | case TIOCSIG: /* Send signal to other side of pty */ | ||
501 | return pty_signal(tty, (int) arg); | ||
478 | } | 502 | } |
479 | 503 | ||
480 | return -ENOIOCTLCMD; | 504 | return -ENOIOCTLCMD; |
@@ -625,7 +649,7 @@ static const struct tty_operations pty_unix98_ops = { | |||
625 | * allocated_ptys_lock handles the list of free pty numbers | 649 | * allocated_ptys_lock handles the list of free pty numbers |
626 | */ | 650 | */ |
627 | 651 | ||
628 | static int __ptmx_open(struct inode *inode, struct file *filp) | 652 | static int ptmx_open(struct inode *inode, struct file *filp) |
629 | { | 653 | { |
630 | struct tty_struct *tty; | 654 | struct tty_struct *tty; |
631 | int retval; | 655 | int retval; |
@@ -634,11 +658,14 @@ static int __ptmx_open(struct inode *inode, struct file *filp) | |||
634 | nonseekable_open(inode, filp); | 658 | nonseekable_open(inode, filp); |
635 | 659 | ||
636 | /* find a device that is not in use. */ | 660 | /* find a device that is not in use. */ |
661 | tty_lock(); | ||
637 | index = devpts_new_index(inode); | 662 | index = devpts_new_index(inode); |
663 | tty_unlock(); | ||
638 | if (index < 0) | 664 | if (index < 0) |
639 | return index; | 665 | return index; |
640 | 666 | ||
641 | mutex_lock(&tty_mutex); | 667 | mutex_lock(&tty_mutex); |
668 | tty_lock(); | ||
642 | tty = tty_init_dev(ptm_driver, index, 1); | 669 | tty = tty_init_dev(ptm_driver, index, 1); |
643 | mutex_unlock(&tty_mutex); | 670 | mutex_unlock(&tty_mutex); |
644 | 671 | ||
@@ -648,34 +675,31 @@ static int __ptmx_open(struct inode *inode, struct file *filp) | |||
648 | } | 675 | } |
649 | 676 | ||
650 | set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ | 677 | set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ |
651 | filp->private_data = tty; | 678 | |
652 | file_move(filp, &tty->tty_files); | 679 | retval = tty_add_file(tty, filp); |
680 | if (retval) | ||
681 | goto out; | ||
653 | 682 | ||
654 | retval = devpts_pty_new(inode, tty->link); | 683 | retval = devpts_pty_new(inode, tty->link); |
655 | if (retval) | 684 | if (retval) |
656 | goto out1; | 685 | goto out1; |
657 | 686 | ||
658 | retval = ptm_driver->ops->open(tty, filp); | 687 | retval = ptm_driver->ops->open(tty, filp); |
659 | if (!retval) | 688 | if (retval) |
660 | return 0; | 689 | goto out2; |
661 | out1: | 690 | out1: |
691 | tty_unlock(); | ||
692 | return retval; | ||
693 | out2: | ||
694 | tty_unlock(); | ||
662 | tty_release(inode, filp); | 695 | tty_release(inode, filp); |
663 | return retval; | 696 | return retval; |
664 | out: | 697 | out: |
665 | devpts_kill_index(inode, index); | 698 | devpts_kill_index(inode, index); |
699 | tty_unlock(); | ||
666 | return retval; | 700 | return retval; |
667 | } | 701 | } |
668 | 702 | ||
669 | static int ptmx_open(struct inode *inode, struct file *filp) | ||
670 | { | ||
671 | int ret; | ||
672 | |||
673 | lock_kernel(); | ||
674 | ret = __ptmx_open(inode, filp); | ||
675 | unlock_kernel(); | ||
676 | return ret; | ||
677 | } | ||
678 | |||
679 | static struct file_operations ptmx_fops; | 703 | static struct file_operations ptmx_fops; |
680 | 704 | ||
681 | static void __init unix98_pty_init(void) | 705 | static void __init unix98_pty_init(void) |
diff --git a/drivers/char/ramoops.c b/drivers/char/ramoops.c new file mode 100644 index 000000000000..73dcb0ee41fd --- /dev/null +++ b/drivers/char/ramoops.c | |||
@@ -0,0 +1,188 @@ | |||
1 | /* | ||
2 | * RAM Oops/Panic logger | ||
3 | * | ||
4 | * Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/kmsg_dump.h> | ||
25 | #include <linux/time.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/ioport.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | #include <linux/ramoops.h> | ||
30 | |||
31 | #define RAMOOPS_KERNMSG_HDR "====" | ||
32 | #define RAMOOPS_HEADER_SIZE (5 + sizeof(struct timeval)) | ||
33 | |||
34 | #define RECORD_SIZE 4096 | ||
35 | |||
36 | static ulong mem_address; | ||
37 | module_param(mem_address, ulong, 0400); | ||
38 | MODULE_PARM_DESC(mem_address, | ||
39 | "start of reserved RAM used to store oops/panic logs"); | ||
40 | |||
41 | static ulong mem_size; | ||
42 | module_param(mem_size, ulong, 0400); | ||
43 | MODULE_PARM_DESC(mem_size, | ||
44 | "size of reserved RAM used to store oops/panic logs"); | ||
45 | |||
46 | static int dump_oops = 1; | ||
47 | module_param(dump_oops, int, 0600); | ||
48 | MODULE_PARM_DESC(dump_oops, | ||
49 | "set to 1 to dump oopses, 0 to only dump panics (default 1)"); | ||
50 | |||
51 | static struct ramoops_context { | ||
52 | struct kmsg_dumper dump; | ||
53 | void *virt_addr; | ||
54 | phys_addr_t phys_addr; | ||
55 | unsigned long size; | ||
56 | int count; | ||
57 | int max_count; | ||
58 | } oops_cxt; | ||
59 | |||
60 | static void ramoops_do_dump(struct kmsg_dumper *dumper, | ||
61 | enum kmsg_dump_reason reason, const char *s1, unsigned long l1, | ||
62 | const char *s2, unsigned long l2) | ||
63 | { | ||
64 | struct ramoops_context *cxt = container_of(dumper, | ||
65 | struct ramoops_context, dump); | ||
66 | unsigned long s1_start, s2_start; | ||
67 | unsigned long l1_cpy, l2_cpy; | ||
68 | int res; | ||
69 | char *buf; | ||
70 | struct timeval timestamp; | ||
71 | |||
72 | /* Only dump oopses if dump_oops is set */ | ||
73 | if (reason == KMSG_DUMP_OOPS && !dump_oops) | ||
74 | return; | ||
75 | |||
76 | buf = (char *)(cxt->virt_addr + (cxt->count * RECORD_SIZE)); | ||
77 | memset(buf, '\0', RECORD_SIZE); | ||
78 | res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR); | ||
79 | buf += res; | ||
80 | do_gettimeofday(×tamp); | ||
81 | res = sprintf(buf, "%lu.%lu\n", (long)timestamp.tv_sec, (long)timestamp.tv_usec); | ||
82 | buf += res; | ||
83 | |||
84 | l2_cpy = min(l2, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE)); | ||
85 | l1_cpy = min(l1, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE) - l2_cpy); | ||
86 | |||
87 | s2_start = l2 - l2_cpy; | ||
88 | s1_start = l1 - l1_cpy; | ||
89 | |||
90 | memcpy(buf, s1 + s1_start, l1_cpy); | ||
91 | memcpy(buf + l1_cpy, s2 + s2_start, l2_cpy); | ||
92 | |||
93 | cxt->count = (cxt->count + 1) % cxt->max_count; | ||
94 | } | ||
95 | |||
96 | static int __init ramoops_probe(struct platform_device *pdev) | ||
97 | { | ||
98 | struct ramoops_platform_data *pdata = pdev->dev.platform_data; | ||
99 | struct ramoops_context *cxt = &oops_cxt; | ||
100 | int err = -EINVAL; | ||
101 | |||
102 | if (pdata) { | ||
103 | mem_size = pdata->mem_size; | ||
104 | mem_address = pdata->mem_address; | ||
105 | } | ||
106 | |||
107 | if (!mem_size) { | ||
108 | printk(KERN_ERR "ramoops: invalid size specification"); | ||
109 | goto fail3; | ||
110 | } | ||
111 | |||
112 | rounddown_pow_of_two(mem_size); | ||
113 | |||
114 | if (mem_size < RECORD_SIZE) { | ||
115 | printk(KERN_ERR "ramoops: size too small"); | ||
116 | goto fail3; | ||
117 | } | ||
118 | |||
119 | cxt->max_count = mem_size / RECORD_SIZE; | ||
120 | cxt->count = 0; | ||
121 | cxt->size = mem_size; | ||
122 | cxt->phys_addr = mem_address; | ||
123 | |||
124 | if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) { | ||
125 | printk(KERN_ERR "ramoops: request mem region failed"); | ||
126 | err = -EINVAL; | ||
127 | goto fail3; | ||
128 | } | ||
129 | |||
130 | cxt->virt_addr = ioremap(cxt->phys_addr, cxt->size); | ||
131 | if (!cxt->virt_addr) { | ||
132 | printk(KERN_ERR "ramoops: ioremap failed"); | ||
133 | goto fail2; | ||
134 | } | ||
135 | |||
136 | cxt->dump.dump = ramoops_do_dump; | ||
137 | err = kmsg_dump_register(&cxt->dump); | ||
138 | if (err) { | ||
139 | printk(KERN_ERR "ramoops: registering kmsg dumper failed"); | ||
140 | goto fail1; | ||
141 | } | ||
142 | |||
143 | return 0; | ||
144 | |||
145 | fail1: | ||
146 | iounmap(cxt->virt_addr); | ||
147 | fail2: | ||
148 | release_mem_region(cxt->phys_addr, cxt->size); | ||
149 | fail3: | ||
150 | return err; | ||
151 | } | ||
152 | |||
153 | static int __exit ramoops_remove(struct platform_device *pdev) | ||
154 | { | ||
155 | struct ramoops_context *cxt = &oops_cxt; | ||
156 | |||
157 | if (kmsg_dump_unregister(&cxt->dump) < 0) | ||
158 | printk(KERN_WARNING "ramoops: could not unregister kmsg_dumper"); | ||
159 | |||
160 | iounmap(cxt->virt_addr); | ||
161 | release_mem_region(cxt->phys_addr, cxt->size); | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static struct platform_driver ramoops_driver = { | ||
166 | .remove = __exit_p(ramoops_remove), | ||
167 | .driver = { | ||
168 | .name = "ramoops", | ||
169 | .owner = THIS_MODULE, | ||
170 | }, | ||
171 | }; | ||
172 | |||
173 | static int __init ramoops_init(void) | ||
174 | { | ||
175 | return platform_driver_probe(&ramoops_driver, ramoops_probe); | ||
176 | } | ||
177 | |||
178 | static void __exit ramoops_exit(void) | ||
179 | { | ||
180 | platform_driver_unregister(&ramoops_driver); | ||
181 | } | ||
182 | |||
183 | module_init(ramoops_init); | ||
184 | module_exit(ramoops_exit); | ||
185 | |||
186 | MODULE_LICENSE("GPL"); | ||
187 | MODULE_AUTHOR("Marco Stornelli <marco.stornelli@gmail.com>"); | ||
188 | MODULE_DESCRIPTION("RAM Oops/Panic logger/driver"); | ||
diff --git a/drivers/char/random.c b/drivers/char/random.c index 8258982b49ec..5a1aa64f4e76 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -257,6 +257,7 @@ | |||
257 | #define INPUT_POOL_WORDS 128 | 257 | #define INPUT_POOL_WORDS 128 |
258 | #define OUTPUT_POOL_WORDS 32 | 258 | #define OUTPUT_POOL_WORDS 32 |
259 | #define SEC_XFER_SIZE 512 | 259 | #define SEC_XFER_SIZE 512 |
260 | #define EXTRACT_SIZE 10 | ||
260 | 261 | ||
261 | /* | 262 | /* |
262 | * The minimum number of bits of entropy before we wake up a read on | 263 | * The minimum number of bits of entropy before we wake up a read on |
@@ -406,15 +407,15 @@ struct entropy_store { | |||
406 | struct poolinfo *poolinfo; | 407 | struct poolinfo *poolinfo; |
407 | __u32 *pool; | 408 | __u32 *pool; |
408 | const char *name; | 409 | const char *name; |
409 | int limit; | ||
410 | struct entropy_store *pull; | 410 | struct entropy_store *pull; |
411 | int limit; | ||
411 | 412 | ||
412 | /* read-write data: */ | 413 | /* read-write data: */ |
413 | spinlock_t lock; | 414 | spinlock_t lock; |
414 | unsigned add_ptr; | 415 | unsigned add_ptr; |
415 | int entropy_count; | 416 | int entropy_count; |
416 | int input_rotate; | 417 | int input_rotate; |
417 | __u8 *last_data; | 418 | __u8 last_data[EXTRACT_SIZE]; |
418 | }; | 419 | }; |
419 | 420 | ||
420 | static __u32 input_pool_data[INPUT_POOL_WORDS]; | 421 | static __u32 input_pool_data[INPUT_POOL_WORDS]; |
@@ -714,8 +715,6 @@ void add_disk_randomness(struct gendisk *disk) | |||
714 | } | 715 | } |
715 | #endif | 716 | #endif |
716 | 717 | ||
717 | #define EXTRACT_SIZE 10 | ||
718 | |||
719 | /********************************************************************* | 718 | /********************************************************************* |
720 | * | 719 | * |
721 | * Entropy extraction routines | 720 | * Entropy extraction routines |
@@ -862,7 +861,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, | |||
862 | while (nbytes) { | 861 | while (nbytes) { |
863 | extract_buf(r, tmp); | 862 | extract_buf(r, tmp); |
864 | 863 | ||
865 | if (r->last_data) { | 864 | if (fips_enabled) { |
866 | spin_lock_irqsave(&r->lock, flags); | 865 | spin_lock_irqsave(&r->lock, flags); |
867 | if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) | 866 | if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) |
868 | panic("Hardware RNG duplicated output!\n"); | 867 | panic("Hardware RNG duplicated output!\n"); |
@@ -951,9 +950,6 @@ static void init_std_data(struct entropy_store *r) | |||
951 | now = ktime_get_real(); | 950 | now = ktime_get_real(); |
952 | mix_pool_bytes(r, &now, sizeof(now)); | 951 | mix_pool_bytes(r, &now, sizeof(now)); |
953 | mix_pool_bytes(r, utsname(), sizeof(*(utsname()))); | 952 | mix_pool_bytes(r, utsname(), sizeof(*(utsname()))); |
954 | /* Enable continuous test in fips mode */ | ||
955 | if (fips_enabled) | ||
956 | r->last_data = kmalloc(EXTRACT_SIZE, GFP_KERNEL); | ||
957 | } | 953 | } |
958 | 954 | ||
959 | static int rand_initialize(void) | 955 | static int rand_initialize(void) |
@@ -1051,12 +1047,6 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) | |||
1051 | /* like a named pipe */ | 1047 | /* like a named pipe */ |
1052 | } | 1048 | } |
1053 | 1049 | ||
1054 | /* | ||
1055 | * If we gave the user some bytes, update the access time. | ||
1056 | */ | ||
1057 | if (count) | ||
1058 | file_accessed(file); | ||
1059 | |||
1060 | return (count ? count : retval); | 1050 | return (count ? count : retval); |
1061 | } | 1051 | } |
1062 | 1052 | ||
@@ -1107,7 +1097,6 @@ static ssize_t random_write(struct file *file, const char __user *buffer, | |||
1107 | size_t count, loff_t *ppos) | 1097 | size_t count, loff_t *ppos) |
1108 | { | 1098 | { |
1109 | size_t ret; | 1099 | size_t ret; |
1110 | struct inode *inode = file->f_path.dentry->d_inode; | ||
1111 | 1100 | ||
1112 | ret = write_pool(&blocking_pool, buffer, count); | 1101 | ret = write_pool(&blocking_pool, buffer, count); |
1113 | if (ret) | 1102 | if (ret) |
@@ -1116,8 +1105,6 @@ static ssize_t random_write(struct file *file, const char __user *buffer, | |||
1116 | if (ret) | 1105 | if (ret) |
1117 | return ret; | 1106 | return ret; |
1118 | 1107 | ||
1119 | inode->i_mtime = current_fs_time(inode->i_sb); | ||
1120 | mark_inode_dirty(inode); | ||
1121 | return (ssize_t)count; | 1108 | return (ssize_t)count; |
1122 | } | 1109 | } |
1123 | 1110 | ||
@@ -1178,6 +1165,7 @@ const struct file_operations random_fops = { | |||
1178 | .poll = random_poll, | 1165 | .poll = random_poll, |
1179 | .unlocked_ioctl = random_ioctl, | 1166 | .unlocked_ioctl = random_ioctl, |
1180 | .fasync = random_fasync, | 1167 | .fasync = random_fasync, |
1168 | .llseek = noop_llseek, | ||
1181 | }; | 1169 | }; |
1182 | 1170 | ||
1183 | const struct file_operations urandom_fops = { | 1171 | const struct file_operations urandom_fops = { |
@@ -1185,6 +1173,7 @@ const struct file_operations urandom_fops = { | |||
1185 | .write = random_write, | 1173 | .write = random_write, |
1186 | .unlocked_ioctl = random_ioctl, | 1174 | .unlocked_ioctl = random_ioctl, |
1187 | .fasync = random_fasync, | 1175 | .fasync = random_fasync, |
1176 | .llseek = noop_llseek, | ||
1188 | }; | 1177 | }; |
1189 | 1178 | ||
1190 | /*************************************************************** | 1179 | /*************************************************************** |
@@ -1200,7 +1189,7 @@ const struct file_operations urandom_fops = { | |||
1200 | void generate_random_uuid(unsigned char uuid_out[16]) | 1189 | void generate_random_uuid(unsigned char uuid_out[16]) |
1201 | { | 1190 | { |
1202 | get_random_bytes(uuid_out, 16); | 1191 | get_random_bytes(uuid_out, 16); |
1203 | /* Set UUID version to 4 --- truely random generation */ | 1192 | /* Set UUID version to 4 --- truly random generation */ |
1204 | uuid_out[6] = (uuid_out[6] & 0x0F) | 0x40; | 1193 | uuid_out[6] = (uuid_out[6] & 0x0F) | 0x40; |
1205 | /* Set the UUID variant to DCE */ | 1194 | /* Set the UUID variant to DCE */ |
1206 | uuid_out[8] = (uuid_out[8] & 0x3F) | 0x80; | 1195 | uuid_out[8] = (uuid_out[8] & 0x3F) | 0x80; |
diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 64acd05f71c8..bfe25ea9766b 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c | |||
@@ -19,7 +19,8 @@ | |||
19 | #include <linux/cdev.h> | 19 | #include <linux/cdev.h> |
20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
21 | #include <linux/mutex.h> | 21 | #include <linux/mutex.h> |
22 | #include <linux/smp_lock.h> | 22 | #include <linux/gfp.h> |
23 | #include <linux/compat.h> | ||
23 | 24 | ||
24 | #include <asm/uaccess.h> | 25 | #include <asm/uaccess.h> |
25 | 26 | ||
@@ -54,7 +55,6 @@ static int raw_open(struct inode *inode, struct file *filp) | |||
54 | return 0; | 55 | return 0; |
55 | } | 56 | } |
56 | 57 | ||
57 | lock_kernel(); | ||
58 | mutex_lock(&raw_mutex); | 58 | mutex_lock(&raw_mutex); |
59 | 59 | ||
60 | /* | 60 | /* |
@@ -81,7 +81,6 @@ static int raw_open(struct inode *inode, struct file *filp) | |||
81 | bdev->bd_inode->i_mapping; | 81 | bdev->bd_inode->i_mapping; |
82 | filp->private_data = bdev; | 82 | filp->private_data = bdev; |
83 | mutex_unlock(&raw_mutex); | 83 | mutex_unlock(&raw_mutex); |
84 | unlock_kernel(); | ||
85 | return 0; | 84 | return 0; |
86 | 85 | ||
87 | out2: | 86 | out2: |
@@ -90,7 +89,6 @@ out1: | |||
90 | blkdev_put(bdev, filp->f_mode); | 89 | blkdev_put(bdev, filp->f_mode); |
91 | out: | 90 | out: |
92 | mutex_unlock(&raw_mutex); | 91 | mutex_unlock(&raw_mutex); |
93 | unlock_kernel(); | ||
94 | return err; | 92 | return err; |
95 | } | 93 | } |
96 | 94 | ||
@@ -120,143 +118,192 @@ static int raw_release(struct inode *inode, struct file *filp) | |||
120 | /* | 118 | /* |
121 | * Forward ioctls to the underlying block device. | 119 | * Forward ioctls to the underlying block device. |
122 | */ | 120 | */ |
123 | static int | 121 | static long |
124 | raw_ioctl(struct inode *inode, struct file *filp, | 122 | raw_ioctl(struct file *filp, unsigned int command, unsigned long arg) |
125 | unsigned int command, unsigned long arg) | ||
126 | { | 123 | { |
127 | struct block_device *bdev = filp->private_data; | 124 | struct block_device *bdev = filp->private_data; |
128 | |||
129 | return blkdev_ioctl(bdev, 0, command, arg); | 125 | return blkdev_ioctl(bdev, 0, command, arg); |
130 | } | 126 | } |
131 | 127 | ||
132 | static void bind_device(struct raw_config_request *rq) | 128 | static int bind_set(int number, u64 major, u64 minor) |
133 | { | 129 | { |
134 | device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor)); | 130 | dev_t dev = MKDEV(major, minor); |
135 | device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor), NULL, | 131 | struct raw_device_data *rawdev; |
136 | "raw%d", rq->raw_minor); | 132 | int err = 0; |
133 | |||
134 | if (number <= 0 || number >= MAX_RAW_MINORS) | ||
135 | return -EINVAL; | ||
136 | |||
137 | if (MAJOR(dev) != major || MINOR(dev) != minor) | ||
138 | return -EINVAL; | ||
139 | |||
140 | rawdev = &raw_devices[number]; | ||
141 | |||
142 | /* | ||
143 | * This is like making block devices, so demand the | ||
144 | * same capability | ||
145 | */ | ||
146 | if (!capable(CAP_SYS_ADMIN)) | ||
147 | return -EPERM; | ||
148 | |||
149 | /* | ||
150 | * For now, we don't need to check that the underlying | ||
151 | * block device is present or not: we can do that when | ||
152 | * the raw device is opened. Just check that the | ||
153 | * major/minor numbers make sense. | ||
154 | */ | ||
155 | |||
156 | if (MAJOR(dev) == 0 && dev != 0) | ||
157 | return -EINVAL; | ||
158 | |||
159 | mutex_lock(&raw_mutex); | ||
160 | if (rawdev->inuse) { | ||
161 | mutex_unlock(&raw_mutex); | ||
162 | return -EBUSY; | ||
163 | } | ||
164 | if (rawdev->binding) { | ||
165 | bdput(rawdev->binding); | ||
166 | module_put(THIS_MODULE); | ||
167 | } | ||
168 | if (!dev) { | ||
169 | /* unbind */ | ||
170 | rawdev->binding = NULL; | ||
171 | device_destroy(raw_class, MKDEV(RAW_MAJOR, number)); | ||
172 | } else { | ||
173 | rawdev->binding = bdget(dev); | ||
174 | if (rawdev->binding == NULL) { | ||
175 | err = -ENOMEM; | ||
176 | } else { | ||
177 | dev_t raw = MKDEV(RAW_MAJOR, number); | ||
178 | __module_get(THIS_MODULE); | ||
179 | device_destroy(raw_class, raw); | ||
180 | device_create(raw_class, NULL, raw, NULL, | ||
181 | "raw%d", number); | ||
182 | } | ||
183 | } | ||
184 | mutex_unlock(&raw_mutex); | ||
185 | return err; | ||
186 | } | ||
187 | |||
188 | static int bind_get(int number, dev_t *dev) | ||
189 | { | ||
190 | struct raw_device_data *rawdev; | ||
191 | struct block_device *bdev; | ||
192 | |||
193 | if (number <= 0 || number >= MAX_RAW_MINORS) | ||
194 | return -EINVAL; | ||
195 | |||
196 | rawdev = &raw_devices[number]; | ||
197 | |||
198 | mutex_lock(&raw_mutex); | ||
199 | bdev = rawdev->binding; | ||
200 | *dev = bdev ? bdev->bd_dev : 0; | ||
201 | mutex_unlock(&raw_mutex); | ||
202 | return 0; | ||
137 | } | 203 | } |
138 | 204 | ||
139 | /* | 205 | /* |
140 | * Deal with ioctls against the raw-device control interface, to bind | 206 | * Deal with ioctls against the raw-device control interface, to bind |
141 | * and unbind other raw devices. | 207 | * and unbind other raw devices. |
142 | */ | 208 | */ |
143 | static int raw_ctl_ioctl(struct inode *inode, struct file *filp, | 209 | static long raw_ctl_ioctl(struct file *filp, unsigned int command, |
144 | unsigned int command, unsigned long arg) | 210 | unsigned long arg) |
145 | { | 211 | { |
146 | struct raw_config_request rq; | 212 | struct raw_config_request rq; |
147 | struct raw_device_data *rawdev; | 213 | dev_t dev; |
148 | int err = 0; | 214 | int err; |
149 | 215 | ||
150 | switch (command) { | 216 | switch (command) { |
151 | case RAW_SETBIND: | 217 | case RAW_SETBIND: |
218 | if (copy_from_user(&rq, (void __user *) arg, sizeof(rq))) | ||
219 | return -EFAULT; | ||
220 | |||
221 | return bind_set(rq.raw_minor, rq.block_major, rq.block_minor); | ||
222 | |||
152 | case RAW_GETBIND: | 223 | case RAW_GETBIND: |
224 | if (copy_from_user(&rq, (void __user *) arg, sizeof(rq))) | ||
225 | return -EFAULT; | ||
153 | 226 | ||
154 | /* First, find out which raw minor we want */ | 227 | err = bind_get(rq.raw_minor, &dev); |
228 | if (err) | ||
229 | return err; | ||
155 | 230 | ||
156 | if (copy_from_user(&rq, (void __user *) arg, sizeof(rq))) { | 231 | rq.block_major = MAJOR(dev); |
157 | err = -EFAULT; | 232 | rq.block_minor = MINOR(dev); |
158 | goto out; | ||
159 | } | ||
160 | 233 | ||
161 | if (rq.raw_minor <= 0 || rq.raw_minor >= MAX_RAW_MINORS) { | 234 | if (copy_to_user((void __user *)arg, &rq, sizeof(rq))) |
162 | err = -EINVAL; | 235 | return -EFAULT; |
163 | goto out; | 236 | |
164 | } | 237 | return 0; |
165 | rawdev = &raw_devices[rq.raw_minor]; | ||
166 | |||
167 | if (command == RAW_SETBIND) { | ||
168 | dev_t dev; | ||
169 | |||
170 | /* | ||
171 | * This is like making block devices, so demand the | ||
172 | * same capability | ||
173 | */ | ||
174 | if (!capable(CAP_SYS_ADMIN)) { | ||
175 | err = -EPERM; | ||
176 | goto out; | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * For now, we don't need to check that the underlying | ||
181 | * block device is present or not: we can do that when | ||
182 | * the raw device is opened. Just check that the | ||
183 | * major/minor numbers make sense. | ||
184 | */ | ||
185 | |||
186 | dev = MKDEV(rq.block_major, rq.block_minor); | ||
187 | if ((rq.block_major == 0 && rq.block_minor != 0) || | ||
188 | MAJOR(dev) != rq.block_major || | ||
189 | MINOR(dev) != rq.block_minor) { | ||
190 | err = -EINVAL; | ||
191 | goto out; | ||
192 | } | ||
193 | |||
194 | mutex_lock(&raw_mutex); | ||
195 | if (rawdev->inuse) { | ||
196 | mutex_unlock(&raw_mutex); | ||
197 | err = -EBUSY; | ||
198 | goto out; | ||
199 | } | ||
200 | if (rawdev->binding) { | ||
201 | bdput(rawdev->binding); | ||
202 | module_put(THIS_MODULE); | ||
203 | } | ||
204 | if (rq.block_major == 0 && rq.block_minor == 0) { | ||
205 | /* unbind */ | ||
206 | rawdev->binding = NULL; | ||
207 | device_destroy(raw_class, | ||
208 | MKDEV(RAW_MAJOR, rq.raw_minor)); | ||
209 | } else { | ||
210 | rawdev->binding = bdget(dev); | ||
211 | if (rawdev->binding == NULL) | ||
212 | err = -ENOMEM; | ||
213 | else { | ||
214 | __module_get(THIS_MODULE); | ||
215 | bind_device(&rq); | ||
216 | } | ||
217 | } | ||
218 | mutex_unlock(&raw_mutex); | ||
219 | } else { | ||
220 | struct block_device *bdev; | ||
221 | |||
222 | mutex_lock(&raw_mutex); | ||
223 | bdev = rawdev->binding; | ||
224 | if (bdev) { | ||
225 | rq.block_major = MAJOR(bdev->bd_dev); | ||
226 | rq.block_minor = MINOR(bdev->bd_dev); | ||
227 | } else { | ||
228 | rq.block_major = rq.block_minor = 0; | ||
229 | } | ||
230 | mutex_unlock(&raw_mutex); | ||
231 | if (copy_to_user((void __user *)arg, &rq, sizeof(rq))) { | ||
232 | err = -EFAULT; | ||
233 | goto out; | ||
234 | } | ||
235 | } | ||
236 | break; | ||
237 | default: | ||
238 | err = -EINVAL; | ||
239 | break; | ||
240 | } | 238 | } |
241 | out: | 239 | |
242 | return err; | 240 | return -EINVAL; |
241 | } | ||
242 | |||
243 | #ifdef CONFIG_COMPAT | ||
244 | struct raw32_config_request { | ||
245 | compat_int_t raw_minor; | ||
246 | compat_u64 block_major; | ||
247 | compat_u64 block_minor; | ||
248 | }; | ||
249 | |||
250 | static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd, | ||
251 | unsigned long arg) | ||
252 | { | ||
253 | struct raw32_config_request __user *user_req = compat_ptr(arg); | ||
254 | struct raw32_config_request rq; | ||
255 | dev_t dev; | ||
256 | int err = 0; | ||
257 | |||
258 | switch (cmd) { | ||
259 | case RAW_SETBIND: | ||
260 | if (copy_from_user(&rq, user_req, sizeof(rq))) | ||
261 | return -EFAULT; | ||
262 | |||
263 | return bind_set(rq.raw_minor, rq.block_major, rq.block_minor); | ||
264 | |||
265 | case RAW_GETBIND: | ||
266 | if (copy_from_user(&rq, user_req, sizeof(rq))) | ||
267 | return -EFAULT; | ||
268 | |||
269 | err = bind_get(rq.raw_minor, &dev); | ||
270 | if (err) | ||
271 | return err; | ||
272 | |||
273 | rq.block_major = MAJOR(dev); | ||
274 | rq.block_minor = MINOR(dev); | ||
275 | |||
276 | if (copy_to_user(user_req, &rq, sizeof(rq))) | ||
277 | return -EFAULT; | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | return -EINVAL; | ||
243 | } | 283 | } |
284 | #endif | ||
244 | 285 | ||
245 | static const struct file_operations raw_fops = { | 286 | static const struct file_operations raw_fops = { |
246 | .read = do_sync_read, | 287 | .read = do_sync_read, |
247 | .aio_read = generic_file_aio_read, | 288 | .aio_read = generic_file_aio_read, |
248 | .write = do_sync_write, | 289 | .write = do_sync_write, |
249 | .aio_write = blkdev_aio_write, | 290 | .aio_write = blkdev_aio_write, |
250 | .open = raw_open, | 291 | .fsync = blkdev_fsync, |
251 | .release= raw_release, | 292 | .open = raw_open, |
252 | .ioctl = raw_ioctl, | 293 | .release = raw_release, |
253 | .owner = THIS_MODULE, | 294 | .unlocked_ioctl = raw_ioctl, |
295 | .llseek = default_llseek, | ||
296 | .owner = THIS_MODULE, | ||
254 | }; | 297 | }; |
255 | 298 | ||
256 | static const struct file_operations raw_ctl_fops = { | 299 | static const struct file_operations raw_ctl_fops = { |
257 | .ioctl = raw_ctl_ioctl, | 300 | .unlocked_ioctl = raw_ctl_ioctl, |
258 | .open = raw_open, | 301 | #ifdef CONFIG_COMPAT |
259 | .owner = THIS_MODULE, | 302 | .compat_ioctl = raw_ctl_compat_ioctl, |
303 | #endif | ||
304 | .open = raw_open, | ||
305 | .owner = THIS_MODULE, | ||
306 | .llseek = noop_llseek, | ||
260 | }; | 307 | }; |
261 | 308 | ||
262 | static struct cdev raw_cdev; | 309 | static struct cdev raw_cdev; |
diff --git a/drivers/char/rio/Makefile b/drivers/char/rio/Makefile index 2d1c5a7cba7d..1661875883fb 100644 --- a/drivers/char/rio/Makefile +++ b/drivers/char/rio/Makefile | |||
@@ -8,5 +8,5 @@ | |||
8 | 8 | ||
9 | obj-$(CONFIG_RIO) += rio.o | 9 | obj-$(CONFIG_RIO) += rio.o |
10 | 10 | ||
11 | rio-objs := rio_linux.o rioinit.o rioboot.o riocmd.o rioctrl.o riointr.o \ | 11 | rio-y := rio_linux.o rioinit.o rioboot.o riocmd.o rioctrl.o riointr.o \ |
12 | rioparam.o rioroute.o riotable.o riotty.o | 12 | rioparam.o rioroute.o riotable.o riotty.o |
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index d58c2eb07f07..5e33293d24e3 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #include <linux/delay.h> | 44 | #include <linux/delay.h> |
45 | #include <linux/pci.h> | 45 | #include <linux/pci.h> |
46 | #include <linux/slab.h> | 46 | #include <linux/slab.h> |
47 | #include <linux/smp_lock.h> | 47 | #include <linux/mutex.h> |
48 | #include <linux/miscdevice.h> | 48 | #include <linux/miscdevice.h> |
49 | #include <linux/init.h> | 49 | #include <linux/init.h> |
50 | 50 | ||
@@ -122,6 +122,7 @@ more than 512 ports.... */ | |||
122 | 122 | ||
123 | 123 | ||
124 | /* These constants are derived from SCO Source */ | 124 | /* These constants are derived from SCO Source */ |
125 | static DEFINE_MUTEX(rio_fw_mutex); | ||
125 | static struct Conf | 126 | static struct Conf |
126 | RIOConf = { | 127 | RIOConf = { |
127 | /* locator */ "RIO Config here", | 128 | /* locator */ "RIO Config here", |
@@ -241,6 +242,7 @@ static struct real_driver rio_real_driver = { | |||
241 | static const struct file_operations rio_fw_fops = { | 242 | static const struct file_operations rio_fw_fops = { |
242 | .owner = THIS_MODULE, | 243 | .owner = THIS_MODULE, |
243 | .unlocked_ioctl = rio_fw_ioctl, | 244 | .unlocked_ioctl = rio_fw_ioctl, |
245 | .llseek = noop_llseek, | ||
244 | }; | 246 | }; |
245 | 247 | ||
246 | static struct miscdevice rio_fw_device = { | 248 | static struct miscdevice rio_fw_device = { |
@@ -566,9 +568,9 @@ static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
566 | func_enter(); | 568 | func_enter(); |
567 | 569 | ||
568 | /* The "dev" argument isn't used. */ | 570 | /* The "dev" argument isn't used. */ |
569 | lock_kernel(); | 571 | mutex_lock(&rio_fw_mutex); |
570 | rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN)); | 572 | rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN)); |
571 | unlock_kernel(); | 573 | mutex_unlock(&rio_fw_mutex); |
572 | 574 | ||
573 | func_exit(); | 575 | func_exit(); |
574 | return rc; | 576 | return rc; |
diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c index be0ba401966e..24a282bb89d4 100644 --- a/drivers/char/rio/rioinit.c +++ b/drivers/char/rio/rioinit.c | |||
@@ -31,7 +31,6 @@ | |||
31 | */ | 31 | */ |
32 | 32 | ||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/slab.h> | ||
35 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
36 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
37 | #include <asm/io.h> | 36 | #include <asm/io.h> |
diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c index 71f87600907c..2e71aecae206 100644 --- a/drivers/char/rio/riointr.c +++ b/drivers/char/rio/riointr.c | |||
@@ -31,7 +31,6 @@ | |||
31 | */ | 31 | */ |
32 | 32 | ||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/slab.h> | ||
35 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
36 | #include <linux/tty.h> | 35 | #include <linux/tty.h> |
37 | #include <linux/tty_flip.h> | 36 | #include <linux/tty_flip.h> |
diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c index d687c17be152..6415f3f32a72 100644 --- a/drivers/char/rio/rioparam.c +++ b/drivers/char/rio/rioparam.c | |||
@@ -31,7 +31,6 @@ | |||
31 | */ | 31 | */ |
32 | 32 | ||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/slab.h> | ||
35 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
36 | #include <linux/tty.h> | 35 | #include <linux/tty.h> |
37 | #include <asm/io.h> | 36 | #include <asm/io.h> |
diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c index 706c2a25f7aa..f9b936ac3394 100644 --- a/drivers/char/rio/rioroute.c +++ b/drivers/char/rio/rioroute.c | |||
@@ -31,7 +31,6 @@ | |||
31 | */ | 31 | */ |
32 | 32 | ||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/slab.h> | ||
35 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
36 | #include <asm/io.h> | 35 | #include <asm/io.h> |
37 | #include <asm/system.h> | 36 | #include <asm/system.h> |
diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c index 47fab7c33073..8a90393faf3c 100644 --- a/drivers/char/rio/riotty.c +++ b/drivers/char/rio/riotty.c | |||
@@ -34,7 +34,6 @@ | |||
34 | 34 | ||
35 | #include <linux/module.h> | 35 | #include <linux/module.h> |
36 | #include <linux/sched.h> | 36 | #include <linux/sched.h> |
37 | #include <linux/slab.h> | ||
38 | #include <linux/errno.h> | 37 | #include <linux/errno.h> |
39 | #include <linux/tty.h> | 38 | #include <linux/tty.h> |
40 | #include <linux/string.h> | 39 | #include <linux/string.h> |
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 0a8d1e56c993..af4de1fe8445 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
@@ -47,7 +47,6 @@ | |||
47 | #include <linux/init.h> | 47 | #include <linux/init.h> |
48 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
49 | #include <linux/tty_flip.h> | 49 | #include <linux/tty_flip.h> |
50 | #include <linux/smp_lock.h> | ||
51 | #include <linux/spinlock.h> | 50 | #include <linux/spinlock.h> |
52 | #include <linux/device.h> | 51 | #include <linux/device.h> |
53 | 52 | ||
@@ -909,6 +908,7 @@ static int rc_open(struct tty_struct *tty, struct file *filp) | |||
909 | if (error) | 908 | if (error) |
910 | return error; | 909 | return error; |
911 | 910 | ||
911 | tty->driver_data = port; | ||
912 | return tty_port_open(&port->port, tty, filp); | 912 | return tty_port_open(&port->port, tty, filp); |
913 | } | 913 | } |
914 | 914 | ||
@@ -1183,6 +1183,7 @@ static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port, | |||
1183 | if (copy_from_user(&tmp, newinfo, sizeof(tmp))) | 1183 | if (copy_from_user(&tmp, newinfo, sizeof(tmp))) |
1184 | return -EFAULT; | 1184 | return -EFAULT; |
1185 | 1185 | ||
1186 | mutex_lock(&port->port.mutex); | ||
1186 | change_speed = ((port->port.flags & ASYNC_SPD_MASK) != | 1187 | change_speed = ((port->port.flags & ASYNC_SPD_MASK) != |
1187 | (tmp.flags & ASYNC_SPD_MASK)); | 1188 | (tmp.flags & ASYNC_SPD_MASK)); |
1188 | 1189 | ||
@@ -1190,8 +1191,10 @@ static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port, | |||
1190 | if ((tmp.close_delay != port->port.close_delay) || | 1191 | if ((tmp.close_delay != port->port.close_delay) || |
1191 | (tmp.closing_wait != port->port.closing_wait) || | 1192 | (tmp.closing_wait != port->port.closing_wait) || |
1192 | ((tmp.flags & ~ASYNC_USR_MASK) != | 1193 | ((tmp.flags & ~ASYNC_USR_MASK) != |
1193 | (port->port.flags & ~ASYNC_USR_MASK))) | 1194 | (port->port.flags & ~ASYNC_USR_MASK))) { |
1195 | mutex_unlock(&port->port.mutex); | ||
1194 | return -EPERM; | 1196 | return -EPERM; |
1197 | } | ||
1195 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | | 1198 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | |
1196 | (tmp.flags & ASYNC_USR_MASK)); | 1199 | (tmp.flags & ASYNC_USR_MASK)); |
1197 | } else { | 1200 | } else { |
@@ -1207,6 +1210,7 @@ static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port, | |||
1207 | rc_change_speed(tty, bp, port); | 1210 | rc_change_speed(tty, bp, port); |
1208 | spin_unlock_irqrestore(&riscom_lock, flags); | 1211 | spin_unlock_irqrestore(&riscom_lock, flags); |
1209 | } | 1212 | } |
1213 | mutex_unlock(&port->port.mutex); | ||
1210 | return 0; | 1214 | return 0; |
1211 | } | 1215 | } |
1212 | 1216 | ||
@@ -1219,12 +1223,15 @@ static int rc_get_serial_info(struct riscom_port *port, | |||
1219 | memset(&tmp, 0, sizeof(tmp)); | 1223 | memset(&tmp, 0, sizeof(tmp)); |
1220 | tmp.type = PORT_CIRRUS; | 1224 | tmp.type = PORT_CIRRUS; |
1221 | tmp.line = port - rc_port; | 1225 | tmp.line = port - rc_port; |
1226 | |||
1227 | mutex_lock(&port->port.mutex); | ||
1222 | tmp.port = bp->base; | 1228 | tmp.port = bp->base; |
1223 | tmp.irq = bp->irq; | 1229 | tmp.irq = bp->irq; |
1224 | tmp.flags = port->port.flags; | 1230 | tmp.flags = port->port.flags; |
1225 | tmp.baud_base = (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC; | 1231 | tmp.baud_base = (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC; |
1226 | tmp.close_delay = port->port.close_delay * HZ/100; | 1232 | tmp.close_delay = port->port.close_delay * HZ/100; |
1227 | tmp.closing_wait = port->port.closing_wait * HZ/100; | 1233 | tmp.closing_wait = port->port.closing_wait * HZ/100; |
1234 | mutex_unlock(&port->port.mutex); | ||
1228 | tmp.xmit_fifo_size = CD180_NFIFO; | 1235 | tmp.xmit_fifo_size = CD180_NFIFO; |
1229 | return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0; | 1236 | return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0; |
1230 | } | 1237 | } |
@@ -1241,14 +1248,10 @@ static int rc_ioctl(struct tty_struct *tty, struct file *filp, | |||
1241 | 1248 | ||
1242 | switch (cmd) { | 1249 | switch (cmd) { |
1243 | case TIOCGSERIAL: | 1250 | case TIOCGSERIAL: |
1244 | lock_kernel(); | ||
1245 | retval = rc_get_serial_info(port, argp); | 1251 | retval = rc_get_serial_info(port, argp); |
1246 | unlock_kernel(); | ||
1247 | break; | 1252 | break; |
1248 | case TIOCSSERIAL: | 1253 | case TIOCSSERIAL: |
1249 | lock_kernel(); | ||
1250 | retval = rc_set_serial_info(tty, port, argp); | 1254 | retval = rc_set_serial_info(tty, port, argp); |
1251 | unlock_kernel(); | ||
1252 | break; | 1255 | break; |
1253 | default: | 1256 | default: |
1254 | retval = -ENOIOCTLCMD; | 1257 | retval = -ENOIOCTLCMD; |
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 0e29a23ec4c5..86308830ac42 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c | |||
@@ -73,7 +73,6 @@ | |||
73 | #include <linux/tty_driver.h> | 73 | #include <linux/tty_driver.h> |
74 | #include <linux/tty_flip.h> | 74 | #include <linux/tty_flip.h> |
75 | #include <linux/serial.h> | 75 | #include <linux/serial.h> |
76 | #include <linux/smp_lock.h> | ||
77 | #include <linux/string.h> | 76 | #include <linux/string.h> |
78 | #include <linux/fcntl.h> | 77 | #include <linux/fcntl.h> |
79 | #include <linux/ptrace.h> | 78 | #include <linux/ptrace.h> |
@@ -1017,6 +1016,7 @@ static void rp_close(struct tty_struct *tty, struct file *filp) | |||
1017 | if (tty_port_close_start(port, tty, filp) == 0) | 1016 | if (tty_port_close_start(port, tty, filp) == 0) |
1018 | return; | 1017 | return; |
1019 | 1018 | ||
1019 | mutex_lock(&port->mutex); | ||
1020 | cp = &info->channel; | 1020 | cp = &info->channel; |
1021 | /* | 1021 | /* |
1022 | * Before we drop DTR, make sure the UART transmitter | 1022 | * Before we drop DTR, make sure the UART transmitter |
@@ -1060,9 +1060,13 @@ static void rp_close(struct tty_struct *tty, struct file *filp) | |||
1060 | info->xmit_buf = NULL; | 1060 | info->xmit_buf = NULL; |
1061 | } | 1061 | } |
1062 | } | 1062 | } |
1063 | spin_lock_irq(&port->lock); | ||
1063 | info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE); | 1064 | info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE); |
1064 | tty->closing = 0; | 1065 | tty->closing = 0; |
1066 | spin_unlock_irq(&port->lock); | ||
1067 | mutex_unlock(&port->mutex); | ||
1065 | tty_port_tty_set(port, NULL); | 1068 | tty_port_tty_set(port, NULL); |
1069 | |||
1066 | wake_up_interruptible(&port->close_wait); | 1070 | wake_up_interruptible(&port->close_wait); |
1067 | complete_all(&info->close_wait); | 1071 | complete_all(&info->close_wait); |
1068 | atomic_dec(&rp_num_ports_open); | 1072 | atomic_dec(&rp_num_ports_open); |
@@ -1210,11 +1214,13 @@ static int get_config(struct r_port *info, struct rocket_config __user *retinfo) | |||
1210 | if (!retinfo) | 1214 | if (!retinfo) |
1211 | return -EFAULT; | 1215 | return -EFAULT; |
1212 | memset(&tmp, 0, sizeof (tmp)); | 1216 | memset(&tmp, 0, sizeof (tmp)); |
1217 | mutex_lock(&info->port.mutex); | ||
1213 | tmp.line = info->line; | 1218 | tmp.line = info->line; |
1214 | tmp.flags = info->flags; | 1219 | tmp.flags = info->flags; |
1215 | tmp.close_delay = info->port.close_delay; | 1220 | tmp.close_delay = info->port.close_delay; |
1216 | tmp.closing_wait = info->port.closing_wait; | 1221 | tmp.closing_wait = info->port.closing_wait; |
1217 | tmp.port = rcktpt_io_addr[(info->line >> 5) & 3]; | 1222 | tmp.port = rcktpt_io_addr[(info->line >> 5) & 3]; |
1223 | mutex_unlock(&info->port.mutex); | ||
1218 | 1224 | ||
1219 | if (copy_to_user(retinfo, &tmp, sizeof (*retinfo))) | 1225 | if (copy_to_user(retinfo, &tmp, sizeof (*retinfo))) |
1220 | return -EFAULT; | 1226 | return -EFAULT; |
@@ -1229,12 +1235,16 @@ static int set_config(struct tty_struct *tty, struct r_port *info, | |||
1229 | if (copy_from_user(&new_serial, new_info, sizeof (new_serial))) | 1235 | if (copy_from_user(&new_serial, new_info, sizeof (new_serial))) |
1230 | return -EFAULT; | 1236 | return -EFAULT; |
1231 | 1237 | ||
1238 | mutex_lock(&info->port.mutex); | ||
1232 | if (!capable(CAP_SYS_ADMIN)) | 1239 | if (!capable(CAP_SYS_ADMIN)) |
1233 | { | 1240 | { |
1234 | if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) | 1241 | if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) { |
1242 | mutex_unlock(&info->port.mutex); | ||
1235 | return -EPERM; | 1243 | return -EPERM; |
1244 | } | ||
1236 | info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK)); | 1245 | info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK)); |
1237 | configure_r_port(tty, info, NULL); | 1246 | configure_r_port(tty, info, NULL); |
1247 | mutex_unlock(&info->port.mutex); | ||
1238 | return 0; | 1248 | return 0; |
1239 | } | 1249 | } |
1240 | 1250 | ||
@@ -1250,6 +1260,7 @@ static int set_config(struct tty_struct *tty, struct r_port *info, | |||
1250 | tty->alt_speed = 230400; | 1260 | tty->alt_speed = 230400; |
1251 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) | 1261 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) |
1252 | tty->alt_speed = 460800; | 1262 | tty->alt_speed = 460800; |
1263 | mutex_unlock(&info->port.mutex); | ||
1253 | 1264 | ||
1254 | configure_r_port(tty, info, NULL); | 1265 | configure_r_port(tty, info, NULL); |
1255 | return 0; | 1266 | return 0; |
@@ -1325,8 +1336,6 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file, | |||
1325 | if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl")) | 1336 | if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl")) |
1326 | return -ENXIO; | 1337 | return -ENXIO; |
1327 | 1338 | ||
1328 | lock_kernel(); | ||
1329 | |||
1330 | switch (cmd) { | 1339 | switch (cmd) { |
1331 | case RCKP_GET_STRUCT: | 1340 | case RCKP_GET_STRUCT: |
1332 | if (copy_to_user(argp, info, sizeof (struct r_port))) | 1341 | if (copy_to_user(argp, info, sizeof (struct r_port))) |
@@ -1350,7 +1359,6 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file, | |||
1350 | default: | 1359 | default: |
1351 | ret = -ENOIOCTLCMD; | 1360 | ret = -ENOIOCTLCMD; |
1352 | } | 1361 | } |
1353 | unlock_kernel(); | ||
1354 | return ret; | 1362 | return ret; |
1355 | } | 1363 | } |
1356 | 1364 | ||
@@ -1471,7 +1479,6 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1471 | jiffies); | 1479 | jiffies); |
1472 | printk(KERN_INFO "cps=%d...\n", info->cps); | 1480 | printk(KERN_INFO "cps=%d...\n", info->cps); |
1473 | #endif | 1481 | #endif |
1474 | lock_kernel(); | ||
1475 | while (1) { | 1482 | while (1) { |
1476 | txcnt = sGetTxCnt(cp); | 1483 | txcnt = sGetTxCnt(cp); |
1477 | if (!txcnt) { | 1484 | if (!txcnt) { |
@@ -1499,7 +1506,6 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1499 | break; | 1506 | break; |
1500 | } | 1507 | } |
1501 | __set_current_state(TASK_RUNNING); | 1508 | __set_current_state(TASK_RUNNING); |
1502 | unlock_kernel(); | ||
1503 | #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT | 1509 | #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT |
1504 | printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies); | 1510 | printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies); |
1505 | #endif | 1511 | #endif |
@@ -1512,6 +1518,7 @@ static void rp_hangup(struct tty_struct *tty) | |||
1512 | { | 1518 | { |
1513 | CHANNEL_t *cp; | 1519 | CHANNEL_t *cp; |
1514 | struct r_port *info = tty->driver_data; | 1520 | struct r_port *info = tty->driver_data; |
1521 | unsigned long flags; | ||
1515 | 1522 | ||
1516 | if (rocket_paranoia_check(info, "rp_hangup")) | 1523 | if (rocket_paranoia_check(info, "rp_hangup")) |
1517 | return; | 1524 | return; |
@@ -1520,11 +1527,15 @@ static void rp_hangup(struct tty_struct *tty) | |||
1520 | printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line); | 1527 | printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line); |
1521 | #endif | 1528 | #endif |
1522 | rp_flush_buffer(tty); | 1529 | rp_flush_buffer(tty); |
1523 | if (info->port.flags & ASYNC_CLOSING) | 1530 | spin_lock_irqsave(&info->port.lock, flags); |
1531 | if (info->port.flags & ASYNC_CLOSING) { | ||
1532 | spin_unlock_irqrestore(&info->port.lock, flags); | ||
1524 | return; | 1533 | return; |
1534 | } | ||
1525 | if (info->port.count) | 1535 | if (info->port.count) |
1526 | atomic_dec(&rp_num_ports_open); | 1536 | atomic_dec(&rp_num_ports_open); |
1527 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); | 1537 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); |
1538 | spin_unlock_irqrestore(&info->port.lock, flags); | ||
1528 | 1539 | ||
1529 | tty_port_hangup(&info->port); | 1540 | tty_port_hangup(&info->port); |
1530 | 1541 | ||
@@ -1535,7 +1546,7 @@ static void rp_hangup(struct tty_struct *tty) | |||
1535 | sDisCTSFlowCtl(cp); | 1546 | sDisCTSFlowCtl(cp); |
1536 | sDisTxSoftFlowCtl(cp); | 1547 | sDisTxSoftFlowCtl(cp); |
1537 | sClrTxXOFF(cp); | 1548 | sClrTxXOFF(cp); |
1538 | info->port.flags &= ~ASYNC_INITIALIZED; | 1549 | clear_bit(ASYNCB_INITIALIZED, &info->port.flags); |
1539 | 1550 | ||
1540 | wake_up_interruptible(&info->port.open_wait); | 1551 | wake_up_interruptible(&info->port.open_wait); |
1541 | } | 1552 | } |
@@ -2334,7 +2345,7 @@ static int __init rp_init(void) | |||
2334 | ret = tty_register_driver(rocket_driver); | 2345 | ret = tty_register_driver(rocket_driver); |
2335 | if (ret < 0) { | 2346 | if (ret < 0) { |
2336 | printk(KERN_ERR "Couldn't install tty RocketPort driver\n"); | 2347 | printk(KERN_ERR "Couldn't install tty RocketPort driver\n"); |
2337 | goto err_tty; | 2348 | goto err_controller; |
2338 | } | 2349 | } |
2339 | 2350 | ||
2340 | #ifdef ROCKET_DEBUG_OPEN | 2351 | #ifdef ROCKET_DEBUG_OPEN |
@@ -2369,6 +2380,9 @@ static int __init rp_init(void) | |||
2369 | return 0; | 2380 | return 0; |
2370 | err_ttyu: | 2381 | err_ttyu: |
2371 | tty_unregister_driver(rocket_driver); | 2382 | tty_unregister_driver(rocket_driver); |
2383 | err_controller: | ||
2384 | if (controller) | ||
2385 | release_region(controller, 4); | ||
2372 | err_tty: | 2386 | err_tty: |
2373 | put_tty_driver(rocket_driver); | 2387 | put_tty_driver(rocket_driver); |
2374 | err: | 2388 | err: |
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 95acb8c880f4..dfa8b3062fda 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
@@ -961,7 +961,7 @@ static int __init rtc_init(void) | |||
961 | #endif | 961 | #endif |
962 | #ifdef CONFIG_SPARC32 | 962 | #ifdef CONFIG_SPARC32 |
963 | struct device_node *ebus_dp; | 963 | struct device_node *ebus_dp; |
964 | struct of_device *op; | 964 | struct platform_device *op; |
965 | #else | 965 | #else |
966 | void *r; | 966 | void *r; |
967 | #ifdef RTC_IRQ | 967 | #ifdef RTC_IRQ |
diff --git a/drivers/char/scx200_gpio.c b/drivers/char/scx200_gpio.c index 99e5272e3c53..0bc135b9b16f 100644 --- a/drivers/char/scx200_gpio.c +++ b/drivers/char/scx200_gpio.c | |||
@@ -67,6 +67,7 @@ static const struct file_operations scx200_gpio_fileops = { | |||
67 | .read = nsc_gpio_read, | 67 | .read = nsc_gpio_read, |
68 | .open = scx200_gpio_open, | 68 | .open = scx200_gpio_open, |
69 | .release = scx200_gpio_release, | 69 | .release = scx200_gpio_release, |
70 | .llseek = no_llseek, | ||
70 | }; | 71 | }; |
71 | 72 | ||
72 | static struct cdev scx200_gpio_cdev; /* use 1 cdev for all pins */ | 73 | static struct cdev scx200_gpio_cdev; /* use 1 cdev for all pins */ |
diff --git a/drivers/char/selection.c b/drivers/char/selection.c index f97b9e848064..ebae344ce910 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/selection.h> | 26 | #include <linux/selection.h> |
27 | #include <linux/tiocl.h> | 27 | #include <linux/tiocl.h> |
28 | #include <linux/console.h> | 28 | #include <linux/console.h> |
29 | #include <linux/smp_lock.h> | ||
29 | 30 | ||
30 | /* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */ | 31 | /* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */ |
31 | #define isspace(c) ((c) == ' ') | 32 | #define isspace(c) ((c) == ' ') |
@@ -312,12 +313,20 @@ int paste_selection(struct tty_struct *tty) | |||
312 | struct tty_ldisc *ld; | 313 | struct tty_ldisc *ld; |
313 | DECLARE_WAITQUEUE(wait, current); | 314 | DECLARE_WAITQUEUE(wait, current); |
314 | 315 | ||
316 | /* always called with BTM from vt_ioctl */ | ||
317 | WARN_ON(!tty_locked()); | ||
318 | |||
315 | acquire_console_sem(); | 319 | acquire_console_sem(); |
316 | poke_blanked_console(); | 320 | poke_blanked_console(); |
317 | release_console_sem(); | 321 | release_console_sem(); |
318 | 322 | ||
319 | ld = tty_ldisc_ref_wait(tty); | 323 | ld = tty_ldisc_ref(tty); |
320 | 324 | if (!ld) { | |
325 | tty_unlock(); | ||
326 | ld = tty_ldisc_ref_wait(tty); | ||
327 | tty_lock(); | ||
328 | } | ||
329 | |||
321 | add_wait_queue(&vc->paste_wait, &wait); | 330 | add_wait_queue(&vc->paste_wait, &wait); |
322 | while (sel_buffer && sel_buffer_lth > pasted) { | 331 | while (sel_buffer && sel_buffer_lth > pasted) { |
323 | set_current_state(TASK_INTERRUPTIBLE); | 332 | set_current_state(TASK_INTERRUPTIBLE); |
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 452370af95de..f646725bd567 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c | |||
@@ -64,6 +64,7 @@ | |||
64 | #include <linux/module.h> | 64 | #include <linux/module.h> |
65 | #include <linux/bitops.h> | 65 | #include <linux/bitops.h> |
66 | #include <linux/tty_flip.h> | 66 | #include <linux/tty_flip.h> |
67 | #include <linux/gfp.h> | ||
67 | 68 | ||
68 | #include <asm/system.h> | 69 | #include <asm/system.h> |
69 | #include <asm/io.h> | 70 | #include <asm/io.h> |
@@ -175,23 +176,6 @@ static void config_setup(struct cyclades_port *); | |||
175 | static void show_status(int); | 176 | static void show_status(int); |
176 | #endif | 177 | #endif |
177 | 178 | ||
178 | #ifdef CONFIG_REMOTE_DEBUG | ||
179 | static void debug_setup(void); | ||
180 | void queueDebugChar(int c); | ||
181 | int getDebugChar(void); | ||
182 | |||
183 | #define DEBUG_PORT 1 | ||
184 | #define DEBUG_LEN 256 | ||
185 | |||
186 | typedef struct { | ||
187 | int in; | ||
188 | int out; | ||
189 | unsigned char buf[DEBUG_LEN]; | ||
190 | } debugq; | ||
191 | |||
192 | debugq debugiq; | ||
193 | #endif | ||
194 | |||
195 | /* | 179 | /* |
196 | * I have my own version of udelay(), as it is needed when initialising | 180 | * I have my own version of udelay(), as it is needed when initialising |
197 | * the chip, before the delay loop has been calibrated. Should probably | 181 | * the chip, before the delay loop has been calibrated. Should probably |
@@ -514,11 +498,6 @@ static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id) | |||
514 | /* determine the channel and change to that context */ | 498 | /* determine the channel and change to that context */ |
515 | channel = (u_short) (base_addr[CyLICR] >> 2); | 499 | channel = (u_short) (base_addr[CyLICR] >> 2); |
516 | 500 | ||
517 | #ifdef CONFIG_REMOTE_DEBUG | ||
518 | if (channel == DEBUG_PORT) { | ||
519 | panic("TxInt on debug port!!!"); | ||
520 | } | ||
521 | #endif | ||
522 | /* validate the port number (as configured and open) */ | 501 | /* validate the port number (as configured and open) */ |
523 | if ((channel < 0) || (NR_PORTS <= channel)) { | 502 | if ((channel < 0) || (NR_PORTS <= channel)) { |
524 | base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); | 503 | base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); |
@@ -626,7 +605,6 @@ static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id) | |||
626 | char data; | 605 | char data; |
627 | int char_count; | 606 | int char_count; |
628 | int save_cnt; | 607 | int save_cnt; |
629 | int len; | ||
630 | 608 | ||
631 | /* determine the channel and change to that context */ | 609 | /* determine the channel and change to that context */ |
632 | channel = (u_short) (base_addr[CyLICR] >> 2); | 610 | channel = (u_short) (base_addr[CyLICR] >> 2); |
@@ -634,14 +612,6 @@ static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id) | |||
634 | info->last_active = jiffies; | 612 | info->last_active = jiffies; |
635 | save_cnt = char_count = base_addr[CyRFOC]; | 613 | save_cnt = char_count = base_addr[CyRFOC]; |
636 | 614 | ||
637 | #ifdef CONFIG_REMOTE_DEBUG | ||
638 | if (channel == DEBUG_PORT) { | ||
639 | while (char_count--) { | ||
640 | data = base_addr[CyRDR]; | ||
641 | queueDebugChar(data); | ||
642 | } | ||
643 | } else | ||
644 | #endif | ||
645 | /* if there is nowhere to put the data, discard it */ | 615 | /* if there is nowhere to put the data, discard it */ |
646 | if (info->tty == 0) { | 616 | if (info->tty == 0) { |
647 | while (char_count--) { | 617 | while (char_count--) { |
@@ -658,8 +628,7 @@ static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id) | |||
658 | info->mon.char_max = char_count; | 628 | info->mon.char_max = char_count; |
659 | info->mon.char_last = char_count; | 629 | info->mon.char_last = char_count; |
660 | #endif | 630 | #endif |
661 | len = tty_buffer_request_room(tty, char_count); | 631 | while (char_count--) { |
662 | while (len--) { | ||
663 | data = base_addr[CyRDR]; | 632 | data = base_addr[CyRDR]; |
664 | tty_insert_flip_char(tty, data, TTY_NORMAL); | 633 | tty_insert_flip_char(tty, data, TTY_NORMAL); |
665 | #ifdef CYCLOM_16Y_HACK | 634 | #ifdef CYCLOM_16Y_HACK |
@@ -1528,7 +1497,6 @@ static int | |||
1528 | cy_ioctl(struct tty_struct *tty, struct file *file, | 1497 | cy_ioctl(struct tty_struct *tty, struct file *file, |
1529 | unsigned int cmd, unsigned long arg) | 1498 | unsigned int cmd, unsigned long arg) |
1530 | { | 1499 | { |
1531 | unsigned long val; | ||
1532 | struct cyclades_port *info = tty->driver_data; | 1500 | struct cyclades_port *info = tty->driver_data; |
1533 | int ret_val = 0; | 1501 | int ret_val = 0; |
1534 | void __user *argp = (void __user *)arg; | 1502 | void __user *argp = (void __user *)arg; |
@@ -1537,7 +1505,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
1537 | printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */ | 1505 | printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */ |
1538 | #endif | 1506 | #endif |
1539 | 1507 | ||
1540 | lock_kernel(); | 1508 | tty_lock(); |
1541 | 1509 | ||
1542 | switch (cmd) { | 1510 | switch (cmd) { |
1543 | case CYGETMON: | 1511 | case CYGETMON: |
@@ -1593,7 +1561,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
1593 | default: | 1561 | default: |
1594 | ret_val = -ENOIOCTLCMD; | 1562 | ret_val = -ENOIOCTLCMD; |
1595 | } | 1563 | } |
1596 | unlock_kernel(); | 1564 | tty_unlock(); |
1597 | 1565 | ||
1598 | #ifdef SERIAL_DEBUG_OTHER | 1566 | #ifdef SERIAL_DEBUG_OTHER |
1599 | printk("cy_ioctl done\n"); | 1567 | printk("cy_ioctl done\n"); |
@@ -1818,7 +1786,9 @@ block_til_ready(struct tty_struct *tty, struct file *filp, | |||
1818 | tty->name, info->count); | 1786 | tty->name, info->count); |
1819 | /**/ | 1787 | /**/ |
1820 | #endif | 1788 | #endif |
1821 | schedule(); | 1789 | tty_unlock(); |
1790 | schedule(); | ||
1791 | tty_lock(); | ||
1822 | } | 1792 | } |
1823 | __set_current_state(TASK_RUNNING); | 1793 | __set_current_state(TASK_RUNNING); |
1824 | remove_wait_queue(&info->open_wait, &wait); | 1794 | remove_wait_queue(&info->open_wait, &wait); |
@@ -1990,7 +1960,7 @@ void mvme167_serial_console_setup(int cflag) | |||
1990 | /* | 1960 | /* |
1991 | * Attempt to set up all channels to something reasonable, and | 1961 | * Attempt to set up all channels to something reasonable, and |
1992 | * bang out a INIT_CHAN command. We should then be able to limit | 1962 | * bang out a INIT_CHAN command. We should then be able to limit |
1993 | * the ammount of fiddling we have to do in normal running. | 1963 | * the amount of fiddling we have to do in normal running. |
1994 | */ | 1964 | */ |
1995 | 1965 | ||
1996 | for (ch = 3; ch >= 0; ch--) { | 1966 | for (ch = 3; ch >= 0; ch--) { |
@@ -2197,9 +2167,7 @@ static int __init serial167_init(void) | |||
2197 | port_num++; | 2167 | port_num++; |
2198 | info++; | 2168 | info++; |
2199 | } | 2169 | } |
2200 | #ifdef CONFIG_REMOTE_DEBUG | 2170 | |
2201 | debug_setup(); | ||
2202 | #endif | ||
2203 | ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0, | 2171 | ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0, |
2204 | "cd2401_errors", cd2401_rxerr_interrupt); | 2172 | "cd2401_errors", cd2401_rxerr_interrupt); |
2205 | if (ret) { | 2173 | if (ret) { |
@@ -2520,193 +2488,4 @@ static int __init serial167_console_init(void) | |||
2520 | 2488 | ||
2521 | console_initcall(serial167_console_init); | 2489 | console_initcall(serial167_console_init); |
2522 | 2490 | ||
2523 | #ifdef CONFIG_REMOTE_DEBUG | ||
2524 | void putDebugChar(int c) | ||
2525 | { | ||
2526 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | ||
2527 | unsigned long flags; | ||
2528 | volatile u_char sink; | ||
2529 | u_char ier; | ||
2530 | int port; | ||
2531 | |||
2532 | local_irq_save(flags); | ||
2533 | |||
2534 | /* Ensure transmitter is enabled! */ | ||
2535 | |||
2536 | port = DEBUG_PORT; | ||
2537 | base_addr[CyCAR] = (u_char) port; | ||
2538 | while (base_addr[CyCCR]) | ||
2539 | ; | ||
2540 | base_addr[CyCCR] = CyENB_XMTR; | ||
2541 | |||
2542 | ier = base_addr[CyIER]; | ||
2543 | base_addr[CyIER] = CyTxMpty; | ||
2544 | |||
2545 | while (1) { | ||
2546 | if (pcc2chip[PccSCCTICR] & 0x20) { | ||
2547 | /* We have a Tx int. Acknowledge it */ | ||
2548 | sink = pcc2chip[PccTPIACKR]; | ||
2549 | if ((base_addr[CyLICR] >> 2) == port) { | ||
2550 | base_addr[CyTDR] = c; | ||
2551 | base_addr[CyTEOIR] = 0; | ||
2552 | break; | ||
2553 | } else | ||
2554 | base_addr[CyTEOIR] = CyNOTRANS; | ||
2555 | } | ||
2556 | } | ||
2557 | |||
2558 | base_addr[CyIER] = ier; | ||
2559 | |||
2560 | local_irq_restore(flags); | ||
2561 | } | ||
2562 | |||
2563 | int getDebugChar() | ||
2564 | { | ||
2565 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | ||
2566 | unsigned long flags; | ||
2567 | volatile u_char sink; | ||
2568 | u_char ier; | ||
2569 | int port; | ||
2570 | int i, c; | ||
2571 | |||
2572 | i = debugiq.out; | ||
2573 | if (i != debugiq.in) { | ||
2574 | c = debugiq.buf[i]; | ||
2575 | if (++i == DEBUG_LEN) | ||
2576 | i = 0; | ||
2577 | debugiq.out = i; | ||
2578 | return c; | ||
2579 | } | ||
2580 | /* OK, nothing in queue, wait in poll loop */ | ||
2581 | |||
2582 | local_irq_save(flags); | ||
2583 | |||
2584 | /* Ensure receiver is enabled! */ | ||
2585 | |||
2586 | port = DEBUG_PORT; | ||
2587 | base_addr[CyCAR] = (u_char) port; | ||
2588 | #if 0 | ||
2589 | while (base_addr[CyCCR]) | ||
2590 | ; | ||
2591 | base_addr[CyCCR] = CyENB_RCVR; | ||
2592 | #endif | ||
2593 | ier = base_addr[CyIER]; | ||
2594 | base_addr[CyIER] = CyRxData; | ||
2595 | |||
2596 | while (1) { | ||
2597 | if (pcc2chip[PccSCCRICR] & 0x20) { | ||
2598 | /* We have a Rx int. Acknowledge it */ | ||
2599 | sink = pcc2chip[PccRPIACKR]; | ||
2600 | if ((base_addr[CyLICR] >> 2) == port) { | ||
2601 | int cnt = base_addr[CyRFOC]; | ||
2602 | while (cnt-- > 0) { | ||
2603 | c = base_addr[CyRDR]; | ||
2604 | if (c == 0) | ||
2605 | printk | ||
2606 | ("!! debug char is null (cnt=%d) !!", | ||
2607 | cnt); | ||
2608 | else | ||
2609 | queueDebugChar(c); | ||
2610 | } | ||
2611 | base_addr[CyREOIR] = 0; | ||
2612 | i = debugiq.out; | ||
2613 | if (i == debugiq.in) | ||
2614 | panic("Debug input queue empty!"); | ||
2615 | c = debugiq.buf[i]; | ||
2616 | if (++i == DEBUG_LEN) | ||
2617 | i = 0; | ||
2618 | debugiq.out = i; | ||
2619 | break; | ||
2620 | } else | ||
2621 | base_addr[CyREOIR] = CyNOTRANS; | ||
2622 | } | ||
2623 | } | ||
2624 | |||
2625 | base_addr[CyIER] = ier; | ||
2626 | |||
2627 | local_irq_restore(flags); | ||
2628 | |||
2629 | return (c); | ||
2630 | } | ||
2631 | |||
2632 | void queueDebugChar(int c) | ||
2633 | { | ||
2634 | int i; | ||
2635 | |||
2636 | i = debugiq.in; | ||
2637 | debugiq.buf[i] = c; | ||
2638 | if (++i == DEBUG_LEN) | ||
2639 | i = 0; | ||
2640 | if (i != debugiq.out) | ||
2641 | debugiq.in = i; | ||
2642 | } | ||
2643 | |||
2644 | static void debug_setup() | ||
2645 | { | ||
2646 | unsigned long flags; | ||
2647 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | ||
2648 | int i, cflag; | ||
2649 | |||
2650 | cflag = B19200; | ||
2651 | |||
2652 | local_irq_save(flags); | ||
2653 | |||
2654 | for (i = 0; i < 4; i++) { | ||
2655 | base_addr[CyCAR] = i; | ||
2656 | base_addr[CyLICR] = i << 2; | ||
2657 | } | ||
2658 | |||
2659 | debugiq.in = debugiq.out = 0; | ||
2660 | |||
2661 | base_addr[CyCAR] = DEBUG_PORT; | ||
2662 | |||
2663 | /* baud rate */ | ||
2664 | i = cflag & CBAUD; | ||
2665 | |||
2666 | base_addr[CyIER] = 0; | ||
2667 | |||
2668 | base_addr[CyCMR] = CyASYNC; | ||
2669 | base_addr[CyLICR] = DEBUG_PORT << 2; | ||
2670 | base_addr[CyLIVR] = 0x5c; | ||
2671 | |||
2672 | /* tx and rx baud rate */ | ||
2673 | |||
2674 | base_addr[CyTCOR] = baud_co[i]; | ||
2675 | base_addr[CyTBPR] = baud_bpr[i]; | ||
2676 | base_addr[CyRCOR] = baud_co[i] >> 5; | ||
2677 | base_addr[CyRBPR] = baud_bpr[i]; | ||
2678 | |||
2679 | /* set line characteristics according configuration */ | ||
2680 | |||
2681 | base_addr[CySCHR1] = 0; | ||
2682 | base_addr[CySCHR2] = 0; | ||
2683 | base_addr[CySCRL] = 0; | ||
2684 | base_addr[CySCRH] = 0; | ||
2685 | base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE; | ||
2686 | base_addr[CyCOR2] = 0; | ||
2687 | base_addr[CyCOR3] = Cy_1_STOP; | ||
2688 | base_addr[CyCOR4] = baud_cor4[i]; | ||
2689 | base_addr[CyCOR5] = 0; | ||
2690 | base_addr[CyCOR6] = 0; | ||
2691 | base_addr[CyCOR7] = 0; | ||
2692 | |||
2693 | write_cy_cmd(base_addr, CyINIT_CHAN); | ||
2694 | write_cy_cmd(base_addr, CyENB_RCVR); | ||
2695 | |||
2696 | base_addr[CyCAR] = DEBUG_PORT; /* !!! Is this needed? */ | ||
2697 | |||
2698 | base_addr[CyRTPRL] = 2; | ||
2699 | base_addr[CyRTPRH] = 0; | ||
2700 | |||
2701 | base_addr[CyMSVR1] = CyRTS; | ||
2702 | base_addr[CyMSVR2] = CyDTR; | ||
2703 | |||
2704 | base_addr[CyIER] = CyRxData; | ||
2705 | |||
2706 | local_irq_restore(flags); | ||
2707 | |||
2708 | } /* debug_setup */ | ||
2709 | |||
2710 | #endif | ||
2711 | |||
2712 | MODULE_LICENSE("GPL"); | 2491 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c index 32b74de18f5f..5816b39ff5a9 100644 --- a/drivers/char/snsc.c +++ b/drivers/char/snsc.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <linux/poll.h> | 21 | #include <linux/poll.h> |
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/smp_lock.h> | 24 | #include <linux/mutex.h> |
25 | #include <asm/sn/io.h> | 25 | #include <asm/sn/io.h> |
26 | #include <asm/sn/sn_sal.h> | 26 | #include <asm/sn/sn_sal.h> |
27 | #include <asm/sn/module.h> | 27 | #include <asm/sn/module.h> |
@@ -34,6 +34,7 @@ | |||
34 | #define SCDRV_BUFSZ 2048 | 34 | #define SCDRV_BUFSZ 2048 |
35 | #define SCDRV_TIMEOUT 1000 | 35 | #define SCDRV_TIMEOUT 1000 |
36 | 36 | ||
37 | static DEFINE_MUTEX(scdrv_mutex); | ||
37 | static irqreturn_t | 38 | static irqreturn_t |
38 | scdrv_interrupt(int irq, void *subch_data) | 39 | scdrv_interrupt(int irq, void *subch_data) |
39 | { | 40 | { |
@@ -105,7 +106,7 @@ scdrv_open(struct inode *inode, struct file *file) | |||
105 | file->private_data = sd; | 106 | file->private_data = sd; |
106 | 107 | ||
107 | /* hook this subchannel up to the system controller interrupt */ | 108 | /* hook this subchannel up to the system controller interrupt */ |
108 | lock_kernel(); | 109 | mutex_lock(&scdrv_mutex); |
109 | rv = request_irq(SGI_UART_VECTOR, scdrv_interrupt, | 110 | rv = request_irq(SGI_UART_VECTOR, scdrv_interrupt, |
110 | IRQF_SHARED | IRQF_DISABLED, | 111 | IRQF_SHARED | IRQF_DISABLED, |
111 | SYSCTL_BASENAME, sd); | 112 | SYSCTL_BASENAME, sd); |
@@ -113,10 +114,10 @@ scdrv_open(struct inode *inode, struct file *file) | |||
113 | ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch); | 114 | ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch); |
114 | kfree(sd); | 115 | kfree(sd); |
115 | printk("%s: irq request failed (%d)\n", __func__, rv); | 116 | printk("%s: irq request failed (%d)\n", __func__, rv); |
116 | unlock_kernel(); | 117 | mutex_unlock(&scdrv_mutex); |
117 | return -EBUSY; | 118 | return -EBUSY; |
118 | } | 119 | } |
119 | unlock_kernel(); | 120 | mutex_unlock(&scdrv_mutex); |
120 | return 0; | 121 | return 0; |
121 | } | 122 | } |
122 | 123 | ||
@@ -357,6 +358,7 @@ static const struct file_operations scdrv_fops = { | |||
357 | .poll = scdrv_poll, | 358 | .poll = scdrv_poll, |
358 | .open = scdrv_open, | 359 | .open = scdrv_open, |
359 | .release = scdrv_release, | 360 | .release = scdrv_release, |
361 | .llseek = noop_llseek, | ||
360 | }; | 362 | }; |
361 | 363 | ||
362 | static struct class *snsc_class; | 364 | static struct class *snsc_class; |
diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c index 55a95892ccf9..ee156948b9f8 100644 --- a/drivers/char/snsc_event.c +++ b/drivers/char/snsc_event.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
20 | #include <linux/slab.h> | ||
20 | #include <asm/byteorder.h> | 21 | #include <asm/byteorder.h> |
21 | #include <asm/sn/sn_sal.h> | 22 | #include <asm/sn/sn_sal.h> |
22 | #include <asm/unaligned.h> | 23 | #include <asm/unaligned.h> |
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index bba727c3807e..73f66d03624d 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <linux/err.h> | 50 | #include <linux/err.h> |
51 | #include <linux/kfifo.h> | 51 | #include <linux/kfifo.h> |
52 | #include <linux/platform_device.h> | 52 | #include <linux/platform_device.h> |
53 | #include <linux/gfp.h> | ||
53 | 54 | ||
54 | #include <asm/uaccess.h> | 55 | #include <asm/uaccess.h> |
55 | #include <asm/io.h> | 56 | #include <asm/io.h> |
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 268e17f9ec3f..9f8495b4fc8f 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c | |||
@@ -94,6 +94,7 @@ | |||
94 | #include <linux/pci.h> | 94 | #include <linux/pci.h> |
95 | #include <linux/init.h> | 95 | #include <linux/init.h> |
96 | #include <linux/uaccess.h> | 96 | #include <linux/uaccess.h> |
97 | #include <linux/gfp.h> | ||
97 | 98 | ||
98 | #include "specialix_io8.h" | 99 | #include "specialix_io8.h" |
99 | #include "cd1865.h" | 100 | #include "cd1865.h" |
@@ -646,8 +647,6 @@ static void sx_receive(struct specialix_board *bp) | |||
646 | dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count); | 647 | dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count); |
647 | port->hits[count > 8 ? 9 : count]++; | 648 | port->hits[count > 8 ? 9 : count]++; |
648 | 649 | ||
649 | tty_buffer_request_room(tty, count); | ||
650 | |||
651 | while (count--) | 650 | while (count--) |
652 | tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL); | 651 | tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL); |
653 | tty_flip_buffer_push(tty); | 652 | tty_flip_buffer_push(tty); |
@@ -1366,7 +1365,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
1366 | retval = -ERESTARTSYS; | 1365 | retval = -ERESTARTSYS; |
1367 | break; | 1366 | break; |
1368 | } | 1367 | } |
1368 | tty_unlock(); | ||
1369 | schedule(); | 1369 | schedule(); |
1370 | tty_lock(); | ||
1370 | } | 1371 | } |
1371 | 1372 | ||
1372 | set_current_state(TASK_RUNNING); | 1373 | set_current_state(TASK_RUNNING); |
@@ -1864,8 +1865,7 @@ static int sx_set_serial_info(struct specialix_port *port, | |||
1864 | return -EFAULT; | 1865 | return -EFAULT; |
1865 | } | 1866 | } |
1866 | 1867 | ||
1867 | lock_kernel(); | 1868 | mutex_lock(&port->port.mutex); |
1868 | |||
1869 | change_speed = ((port->port.flags & ASYNC_SPD_MASK) != | 1869 | change_speed = ((port->port.flags & ASYNC_SPD_MASK) != |
1870 | (tmp.flags & ASYNC_SPD_MASK)); | 1870 | (tmp.flags & ASYNC_SPD_MASK)); |
1871 | change_speed |= (tmp.custom_divisor != port->custom_divisor); | 1871 | change_speed |= (tmp.custom_divisor != port->custom_divisor); |
@@ -1876,7 +1876,7 @@ static int sx_set_serial_info(struct specialix_port *port, | |||
1876 | ((tmp.flags & ~ASYNC_USR_MASK) != | 1876 | ((tmp.flags & ~ASYNC_USR_MASK) != |
1877 | (port->port.flags & ~ASYNC_USR_MASK))) { | 1877 | (port->port.flags & ~ASYNC_USR_MASK))) { |
1878 | func_exit(); | 1878 | func_exit(); |
1879 | unlock_kernel(); | 1879 | mutex_unlock(&port->port.mutex); |
1880 | return -EPERM; | 1880 | return -EPERM; |
1881 | } | 1881 | } |
1882 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | | 1882 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | |
@@ -1893,7 +1893,7 @@ static int sx_set_serial_info(struct specialix_port *port, | |||
1893 | sx_change_speed(bp, port); | 1893 | sx_change_speed(bp, port); |
1894 | 1894 | ||
1895 | func_exit(); | 1895 | func_exit(); |
1896 | unlock_kernel(); | 1896 | mutex_unlock(&port->port.mutex); |
1897 | return 0; | 1897 | return 0; |
1898 | } | 1898 | } |
1899 | 1899 | ||
@@ -1907,7 +1907,7 @@ static int sx_get_serial_info(struct specialix_port *port, | |||
1907 | func_enter(); | 1907 | func_enter(); |
1908 | 1908 | ||
1909 | memset(&tmp, 0, sizeof(tmp)); | 1909 | memset(&tmp, 0, sizeof(tmp)); |
1910 | lock_kernel(); | 1910 | mutex_lock(&port->port.mutex); |
1911 | tmp.type = PORT_CIRRUS; | 1911 | tmp.type = PORT_CIRRUS; |
1912 | tmp.line = port - sx_port; | 1912 | tmp.line = port - sx_port; |
1913 | tmp.port = bp->base; | 1913 | tmp.port = bp->base; |
@@ -1918,7 +1918,7 @@ static int sx_get_serial_info(struct specialix_port *port, | |||
1918 | tmp.closing_wait = port->port.closing_wait * HZ/100; | 1918 | tmp.closing_wait = port->port.closing_wait * HZ/100; |
1919 | tmp.custom_divisor = port->custom_divisor; | 1919 | tmp.custom_divisor = port->custom_divisor; |
1920 | tmp.xmit_fifo_size = CD186x_NFIFO; | 1920 | tmp.xmit_fifo_size = CD186x_NFIFO; |
1921 | unlock_kernel(); | 1921 | mutex_unlock(&port->port.mutex); |
1922 | if (copy_to_user(retinfo, &tmp, sizeof(tmp))) { | 1922 | if (copy_to_user(retinfo, &tmp, sizeof(tmp))) { |
1923 | func_exit(); | 1923 | func_exit(); |
1924 | return -EFAULT; | 1924 | return -EFAULT; |
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 0e511d61f544..4bef6ab83622 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
@@ -608,6 +608,7 @@ static unsigned int sc26198_baudtable[] = { | |||
608 | static const struct file_operations stl_fsiomem = { | 608 | static const struct file_operations stl_fsiomem = { |
609 | .owner = THIS_MODULE, | 609 | .owner = THIS_MODULE, |
610 | .unlocked_ioctl = stl_memioctl, | 610 | .unlocked_ioctl = stl_memioctl, |
611 | .llseek = noop_llseek, | ||
611 | }; | 612 | }; |
612 | 613 | ||
613 | static struct class *stallion_class; | 614 | static struct class *stallion_class; |
@@ -724,7 +725,6 @@ static int stl_open(struct tty_struct *tty, struct file *filp) | |||
724 | { | 725 | { |
725 | struct stlport *portp; | 726 | struct stlport *portp; |
726 | struct stlbrd *brdp; | 727 | struct stlbrd *brdp; |
727 | struct tty_port *port; | ||
728 | unsigned int minordev, brdnr, panelnr; | 728 | unsigned int minordev, brdnr, panelnr; |
729 | int portnr; | 729 | int portnr; |
730 | 730 | ||
@@ -754,7 +754,8 @@ static int stl_open(struct tty_struct *tty, struct file *filp) | |||
754 | portp = brdp->panels[panelnr]->ports[portnr]; | 754 | portp = brdp->panels[panelnr]->ports[portnr]; |
755 | if (portp == NULL) | 755 | if (portp == NULL) |
756 | return -ENODEV; | 756 | return -ENODEV; |
757 | port = &portp->port; | 757 | |
758 | tty->driver_data = portp; | ||
758 | return tty_port_open(&portp->port, tty, filp); | 759 | return tty_port_open(&portp->port, tty, filp); |
759 | 760 | ||
760 | } | 761 | } |
@@ -807,7 +808,6 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout) | |||
807 | timeout = HZ; | 808 | timeout = HZ; |
808 | tend = jiffies + timeout; | 809 | tend = jiffies + timeout; |
809 | 810 | ||
810 | lock_kernel(); | ||
811 | while (stl_datastate(portp)) { | 811 | while (stl_datastate(portp)) { |
812 | if (signal_pending(current)) | 812 | if (signal_pending(current)) |
813 | break; | 813 | break; |
@@ -815,7 +815,6 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout) | |||
815 | if (time_after_eq(jiffies, tend)) | 815 | if (time_after_eq(jiffies, tend)) |
816 | break; | 816 | break; |
817 | } | 817 | } |
818 | unlock_kernel(); | ||
819 | } | 818 | } |
820 | 819 | ||
821 | /*****************************************************************************/ | 820 | /*****************************************************************************/ |
@@ -841,7 +840,8 @@ static void stl_close(struct tty_struct *tty, struct file *filp) | |||
841 | pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); | 840 | pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); |
842 | 841 | ||
843 | portp = tty->driver_data; | 842 | portp = tty->driver_data; |
844 | BUG_ON(portp == NULL); | 843 | if(portp == NULL) |
844 | return; | ||
845 | tty_port_close(&portp->port, tty, filp); | 845 | tty_port_close(&portp->port, tty, filp); |
846 | } | 846 | } |
847 | 847 | ||
@@ -1028,6 +1028,8 @@ static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp) | |||
1028 | pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp); | 1028 | pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp); |
1029 | 1029 | ||
1030 | memset(&sio, 0, sizeof(struct serial_struct)); | 1030 | memset(&sio, 0, sizeof(struct serial_struct)); |
1031 | |||
1032 | mutex_lock(&portp->port.mutex); | ||
1031 | sio.line = portp->portnr; | 1033 | sio.line = portp->portnr; |
1032 | sio.port = portp->ioaddr; | 1034 | sio.port = portp->ioaddr; |
1033 | sio.flags = portp->port.flags; | 1035 | sio.flags = portp->port.flags; |
@@ -1047,6 +1049,7 @@ static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp) | |||
1047 | brdp = stl_brds[portp->brdnr]; | 1049 | brdp = stl_brds[portp->brdnr]; |
1048 | if (brdp != NULL) | 1050 | if (brdp != NULL) |
1049 | sio.irq = brdp->irq; | 1051 | sio.irq = brdp->irq; |
1052 | mutex_unlock(&portp->port.mutex); | ||
1050 | 1053 | ||
1051 | return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0; | 1054 | return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0; |
1052 | } | 1055 | } |
@@ -1068,12 +1071,15 @@ static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp | |||
1068 | 1071 | ||
1069 | if (copy_from_user(&sio, sp, sizeof(struct serial_struct))) | 1072 | if (copy_from_user(&sio, sp, sizeof(struct serial_struct))) |
1070 | return -EFAULT; | 1073 | return -EFAULT; |
1074 | mutex_lock(&portp->port.mutex); | ||
1071 | if (!capable(CAP_SYS_ADMIN)) { | 1075 | if (!capable(CAP_SYS_ADMIN)) { |
1072 | if ((sio.baud_base != portp->baud_base) || | 1076 | if ((sio.baud_base != portp->baud_base) || |
1073 | (sio.close_delay != portp->close_delay) || | 1077 | (sio.close_delay != portp->close_delay) || |
1074 | ((sio.flags & ~ASYNC_USR_MASK) != | 1078 | ((sio.flags & ~ASYNC_USR_MASK) != |
1075 | (portp->port.flags & ~ASYNC_USR_MASK))) | 1079 | (portp->port.flags & ~ASYNC_USR_MASK))) { |
1080 | mutex_unlock(&portp->port.mutex); | ||
1076 | return -EPERM; | 1081 | return -EPERM; |
1082 | } | ||
1077 | } | 1083 | } |
1078 | 1084 | ||
1079 | portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) | | 1085 | portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) | |
@@ -1082,6 +1088,7 @@ static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp | |||
1082 | portp->close_delay = sio.close_delay; | 1088 | portp->close_delay = sio.close_delay; |
1083 | portp->closing_wait = sio.closing_wait; | 1089 | portp->closing_wait = sio.closing_wait; |
1084 | portp->custom_divisor = sio.custom_divisor; | 1090 | portp->custom_divisor = sio.custom_divisor; |
1091 | mutex_unlock(&portp->port.mutex); | ||
1085 | stl_setport(portp, tty->termios); | 1092 | stl_setport(portp, tty->termios); |
1086 | return 0; | 1093 | return 0; |
1087 | } | 1094 | } |
@@ -1146,8 +1153,6 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd | |||
1146 | 1153 | ||
1147 | rc = 0; | 1154 | rc = 0; |
1148 | 1155 | ||
1149 | lock_kernel(); | ||
1150 | |||
1151 | switch (cmd) { | 1156 | switch (cmd) { |
1152 | case TIOCGSERIAL: | 1157 | case TIOCGSERIAL: |
1153 | rc = stl_getserial(portp, argp); | 1158 | rc = stl_getserial(portp, argp); |
@@ -1172,7 +1177,6 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd | |||
1172 | rc = -ENOIOCTLCMD; | 1177 | rc = -ENOIOCTLCMD; |
1173 | break; | 1178 | break; |
1174 | } | 1179 | } |
1175 | unlock_kernel(); | ||
1176 | return rc; | 1180 | return rc; |
1177 | } | 1181 | } |
1178 | 1182 | ||
@@ -2326,6 +2330,7 @@ static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comst | |||
2326 | return -ENODEV; | 2330 | return -ENODEV; |
2327 | } | 2331 | } |
2328 | 2332 | ||
2333 | mutex_lock(&portp->port.mutex); | ||
2329 | portp->stats.state = portp->istate; | 2334 | portp->stats.state = portp->istate; |
2330 | portp->stats.flags = portp->port.flags; | 2335 | portp->stats.flags = portp->port.flags; |
2331 | portp->stats.hwid = portp->hwid; | 2336 | portp->stats.hwid = portp->hwid; |
@@ -2357,6 +2362,7 @@ static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comst | |||
2357 | (STL_TXBUFSIZE - (tail - head)); | 2362 | (STL_TXBUFSIZE - (tail - head)); |
2358 | 2363 | ||
2359 | portp->stats.signals = (unsigned long) stl_getsignals(portp); | 2364 | portp->stats.signals = (unsigned long) stl_getsignals(portp); |
2365 | mutex_unlock(&portp->port.mutex); | ||
2360 | 2366 | ||
2361 | return copy_to_user(cp, &portp->stats, | 2367 | return copy_to_user(cp, &portp->stats, |
2362 | sizeof(comstats_t)) ? -EFAULT : 0; | 2368 | sizeof(comstats_t)) ? -EFAULT : 0; |
@@ -2381,10 +2387,12 @@ static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp) | |||
2381 | return -ENODEV; | 2387 | return -ENODEV; |
2382 | } | 2388 | } |
2383 | 2389 | ||
2390 | mutex_lock(&portp->port.mutex); | ||
2384 | memset(&portp->stats, 0, sizeof(comstats_t)); | 2391 | memset(&portp->stats, 0, sizeof(comstats_t)); |
2385 | portp->stats.brd = portp->brdnr; | 2392 | portp->stats.brd = portp->brdnr; |
2386 | portp->stats.panel = portp->panelnr; | 2393 | portp->stats.panel = portp->panelnr; |
2387 | portp->stats.port = portp->portnr; | 2394 | portp->stats.port = portp->portnr; |
2395 | mutex_unlock(&portp->port.mutex); | ||
2388 | return copy_to_user(cp, &portp->stats, | 2396 | return copy_to_user(cp, &portp->stats, |
2389 | sizeof(comstats_t)) ? -EFAULT : 0; | 2397 | sizeof(comstats_t)) ? -EFAULT : 0; |
2390 | } | 2398 | } |
@@ -2450,7 +2458,6 @@ static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
2450 | return -ENODEV; | 2458 | return -ENODEV; |
2451 | rc = 0; | 2459 | rc = 0; |
2452 | 2460 | ||
2453 | lock_kernel(); | ||
2454 | switch (cmd) { | 2461 | switch (cmd) { |
2455 | case COM_GETPORTSTATS: | 2462 | case COM_GETPORTSTATS: |
2456 | rc = stl_getportstats(NULL, NULL, argp); | 2463 | rc = stl_getportstats(NULL, NULL, argp); |
@@ -2471,7 +2478,6 @@ static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
2471 | rc = -ENOIOCTLCMD; | 2478 | rc = -ENOIOCTLCMD; |
2472 | break; | 2479 | break; |
2473 | } | 2480 | } |
2474 | unlock_kernel(); | ||
2475 | return rc; | 2481 | return rc; |
2476 | } | 2482 | } |
2477 | 2483 | ||
@@ -3175,7 +3181,7 @@ static void stl_cd1400flush(struct stlport *portp) | |||
3175 | 3181 | ||
3176 | /* | 3182 | /* |
3177 | * Return the current state of data flow on this port. This is only | 3183 | * Return the current state of data flow on this port. This is only |
3178 | * really interresting when determining if data has fully completed | 3184 | * really interesting when determining if data has fully completed |
3179 | * transmission or not... This is easy for the cd1400, it accurately | 3185 | * transmission or not... This is easy for the cd1400, it accurately |
3180 | * maintains the busy port flag. | 3186 | * maintains the busy port flag. |
3181 | */ | 3187 | */ |
@@ -4125,7 +4131,7 @@ static void stl_sc26198flush(struct stlport *portp) | |||
4125 | 4131 | ||
4126 | /* | 4132 | /* |
4127 | * Return the current state of data flow on this port. This is only | 4133 | * Return the current state of data flow on this port. This is only |
4128 | * really interresting when determining if data has fully completed | 4134 | * really interesting when determining if data has fully completed |
4129 | * transmission or not... The sc26198 interrupt scheme cannot | 4135 | * transmission or not... The sc26198 interrupt scheme cannot |
4130 | * determine when all data has actually drained, so we need to | 4136 | * determine when all data has actually drained, so we need to |
4131 | * check the port statusy register to be sure. | 4137 | * check the port statusy register to be sure. |
diff --git a/drivers/char/sx.c b/drivers/char/sx.c index a81ec4fcf6ff..e53f16865397 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c | |||
@@ -397,6 +397,7 @@ static struct real_driver sx_real_driver = { | |||
397 | static const struct file_operations sx_fw_fops = { | 397 | static const struct file_operations sx_fw_fops = { |
398 | .owner = THIS_MODULE, | 398 | .owner = THIS_MODULE, |
399 | .unlocked_ioctl = sx_fw_ioctl, | 399 | .unlocked_ioctl = sx_fw_ioctl, |
400 | .llseek = noop_llseek, | ||
400 | }; | 401 | }; |
401 | 402 | ||
402 | static struct miscdevice sx_fw_device = { | 403 | static struct miscdevice sx_fw_device = { |
@@ -1699,7 +1700,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd, | |||
1699 | if (!capable(CAP_SYS_RAWIO)) | 1700 | if (!capable(CAP_SYS_RAWIO)) |
1700 | return -EPERM; | 1701 | return -EPERM; |
1701 | 1702 | ||
1702 | lock_kernel(); | 1703 | tty_lock(); |
1703 | 1704 | ||
1704 | sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); | 1705 | sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); |
1705 | 1706 | ||
@@ -1848,7 +1849,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd, | |||
1848 | break; | 1849 | break; |
1849 | } | 1850 | } |
1850 | out: | 1851 | out: |
1851 | unlock_kernel(); | 1852 | tty_unlock(); |
1852 | func_exit(); | 1853 | func_exit(); |
1853 | return rc; | 1854 | return rc; |
1854 | } | 1855 | } |
@@ -1859,7 +1860,7 @@ static int sx_break(struct tty_struct *tty, int flag) | |||
1859 | int rv; | 1860 | int rv; |
1860 | 1861 | ||
1861 | func_enter(); | 1862 | func_enter(); |
1862 | lock_kernel(); | 1863 | tty_lock(); |
1863 | 1864 | ||
1864 | if (flag) | 1865 | if (flag) |
1865 | rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK); | 1866 | rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK); |
@@ -1868,7 +1869,7 @@ static int sx_break(struct tty_struct *tty, int flag) | |||
1868 | if (rv != 1) | 1869 | if (rv != 1) |
1869 | printk(KERN_ERR "sx: couldn't send break (%x).\n", | 1870 | printk(KERN_ERR "sx: couldn't send break (%x).\n", |
1870 | read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat))); | 1871 | read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat))); |
1871 | unlock_kernel(); | 1872 | tty_unlock(); |
1872 | func_exit(); | 1873 | func_exit(); |
1873 | return 0; | 1874 | return 0; |
1874 | } | 1875 | } |
@@ -1909,7 +1910,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp, | |||
1909 | /* func_enter2(); */ | 1910 | /* func_enter2(); */ |
1910 | 1911 | ||
1911 | rc = 0; | 1912 | rc = 0; |
1912 | lock_kernel(); | 1913 | tty_lock(); |
1913 | switch (cmd) { | 1914 | switch (cmd) { |
1914 | case TIOCGSERIAL: | 1915 | case TIOCGSERIAL: |
1915 | rc = gs_getserial(&port->gs, argp); | 1916 | rc = gs_getserial(&port->gs, argp); |
@@ -1921,7 +1922,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp, | |||
1921 | rc = -ENOIOCTLCMD; | 1922 | rc = -ENOIOCTLCMD; |
1922 | break; | 1923 | break; |
1923 | } | 1924 | } |
1924 | unlock_kernel(); | 1925 | tty_unlock(); |
1925 | 1926 | ||
1926 | /* func_exit(); */ | 1927 | /* func_exit(); */ |
1927 | return rc; | 1928 | return rc; |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 4846b73ef28d..3a6824f12be2 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -81,7 +81,6 @@ | |||
81 | #include <linux/mm.h> | 81 | #include <linux/mm.h> |
82 | #include <linux/seq_file.h> | 82 | #include <linux/seq_file.h> |
83 | #include <linux/slab.h> | 83 | #include <linux/slab.h> |
84 | #include <linux/smp_lock.h> | ||
85 | #include <linux/delay.h> | 84 | #include <linux/delay.h> |
86 | #include <linux/netdevice.h> | 85 | #include <linux/netdevice.h> |
87 | #include <linux/vmalloc.h> | 86 | #include <linux/vmalloc.h> |
@@ -2031,7 +2030,7 @@ static int mgsl_put_char(struct tty_struct *tty, unsigned char ch) | |||
2031 | if (mgsl_paranoia_check(info, tty->name, "mgsl_put_char")) | 2030 | if (mgsl_paranoia_check(info, tty->name, "mgsl_put_char")) |
2032 | return 0; | 2031 | return 0; |
2033 | 2032 | ||
2034 | if (!tty || !info->xmit_buf) | 2033 | if (!info->xmit_buf) |
2035 | return 0; | 2034 | return 0; |
2036 | 2035 | ||
2037 | spin_lock_irqsave(&info->irq_spinlock, flags); | 2036 | spin_lock_irqsave(&info->irq_spinlock, flags); |
@@ -2121,7 +2120,7 @@ static int mgsl_write(struct tty_struct * tty, | |||
2121 | if (mgsl_paranoia_check(info, tty->name, "mgsl_write")) | 2120 | if (mgsl_paranoia_check(info, tty->name, "mgsl_write")) |
2122 | goto cleanup; | 2121 | goto cleanup; |
2123 | 2122 | ||
2124 | if (!tty || !info->xmit_buf) | 2123 | if (!info->xmit_buf) |
2125 | goto cleanup; | 2124 | goto cleanup; |
2126 | 2125 | ||
2127 | if ( info->params.mode == MGSL_MODE_HDLC || | 2126 | if ( info->params.mode == MGSL_MODE_HDLC || |
@@ -2436,7 +2435,9 @@ static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount __user * | |||
2436 | if (!user_icount) { | 2435 | if (!user_icount) { |
2437 | memset(&info->icount, 0, sizeof(info->icount)); | 2436 | memset(&info->icount, 0, sizeof(info->icount)); |
2438 | } else { | 2437 | } else { |
2438 | mutex_lock(&info->port.mutex); | ||
2439 | COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount)); | 2439 | COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount)); |
2440 | mutex_unlock(&info->port.mutex); | ||
2440 | if (err) | 2441 | if (err) |
2441 | return -EFAULT; | 2442 | return -EFAULT; |
2442 | } | 2443 | } |
@@ -2461,7 +2462,9 @@ static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS __user *user_p | |||
2461 | printk("%s(%d):mgsl_get_params(%s)\n", | 2462 | printk("%s(%d):mgsl_get_params(%s)\n", |
2462 | __FILE__,__LINE__, info->device_name); | 2463 | __FILE__,__LINE__, info->device_name); |
2463 | 2464 | ||
2465 | mutex_lock(&info->port.mutex); | ||
2464 | COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS)); | 2466 | COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS)); |
2467 | mutex_unlock(&info->port.mutex); | ||
2465 | if (err) { | 2468 | if (err) { |
2466 | if ( debug_level >= DEBUG_LEVEL_INFO ) | 2469 | if ( debug_level >= DEBUG_LEVEL_INFO ) |
2467 | printk( "%s(%d):mgsl_get_params(%s) user buffer copy failed\n", | 2470 | printk( "%s(%d):mgsl_get_params(%s) user buffer copy failed\n", |
@@ -2501,11 +2504,13 @@ static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS __user *new_pa | |||
2501 | return -EFAULT; | 2504 | return -EFAULT; |
2502 | } | 2505 | } |
2503 | 2506 | ||
2507 | mutex_lock(&info->port.mutex); | ||
2504 | spin_lock_irqsave(&info->irq_spinlock,flags); | 2508 | spin_lock_irqsave(&info->irq_spinlock,flags); |
2505 | memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); | 2509 | memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); |
2506 | spin_unlock_irqrestore(&info->irq_spinlock,flags); | 2510 | spin_unlock_irqrestore(&info->irq_spinlock,flags); |
2507 | 2511 | ||
2508 | mgsl_change_params(info); | 2512 | mgsl_change_params(info); |
2513 | mutex_unlock(&info->port.mutex); | ||
2509 | 2514 | ||
2510 | return 0; | 2515 | return 0; |
2511 | 2516 | ||
@@ -2920,6 +2925,38 @@ static int mgsl_break(struct tty_struct *tty, int break_state) | |||
2920 | 2925 | ||
2921 | } /* end of mgsl_break() */ | 2926 | } /* end of mgsl_break() */ |
2922 | 2927 | ||
2928 | /* | ||
2929 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) | ||
2930 | * Return: write counters to the user passed counter struct | ||
2931 | * NB: both 1->0 and 0->1 transitions are counted except for | ||
2932 | * RI where only 0->1 is counted. | ||
2933 | */ | ||
2934 | static int msgl_get_icount(struct tty_struct *tty, | ||
2935 | struct serial_icounter_struct *icount) | ||
2936 | |||
2937 | { | ||
2938 | struct mgsl_struct * info = tty->driver_data; | ||
2939 | struct mgsl_icount cnow; /* kernel counter temps */ | ||
2940 | unsigned long flags; | ||
2941 | |||
2942 | spin_lock_irqsave(&info->irq_spinlock,flags); | ||
2943 | cnow = info->icount; | ||
2944 | spin_unlock_irqrestore(&info->irq_spinlock,flags); | ||
2945 | |||
2946 | icount->cts = cnow.cts; | ||
2947 | icount->dsr = cnow.dsr; | ||
2948 | icount->rng = cnow.rng; | ||
2949 | icount->dcd = cnow.dcd; | ||
2950 | icount->rx = cnow.rx; | ||
2951 | icount->tx = cnow.tx; | ||
2952 | icount->frame = cnow.frame; | ||
2953 | icount->overrun = cnow.overrun; | ||
2954 | icount->parity = cnow.parity; | ||
2955 | icount->brk = cnow.brk; | ||
2956 | icount->buf_overrun = cnow.buf_overrun; | ||
2957 | return 0; | ||
2958 | } | ||
2959 | |||
2923 | /* mgsl_ioctl() Service an IOCTL request | 2960 | /* mgsl_ioctl() Service an IOCTL request |
2924 | * | 2961 | * |
2925 | * Arguments: | 2962 | * Arguments: |
@@ -2935,7 +2972,6 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file, | |||
2935 | unsigned int cmd, unsigned long arg) | 2972 | unsigned int cmd, unsigned long arg) |
2936 | { | 2973 | { |
2937 | struct mgsl_struct * info = tty->driver_data; | 2974 | struct mgsl_struct * info = tty->driver_data; |
2938 | int ret; | ||
2939 | 2975 | ||
2940 | if (debug_level >= DEBUG_LEVEL_INFO) | 2976 | if (debug_level >= DEBUG_LEVEL_INFO) |
2941 | printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__, | 2977 | printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__, |
@@ -2945,24 +2981,17 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file, | |||
2945 | return -ENODEV; | 2981 | return -ENODEV; |
2946 | 2982 | ||
2947 | if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && | 2983 | if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && |
2948 | (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { | 2984 | (cmd != TIOCMIWAIT)) { |
2949 | if (tty->flags & (1 << TTY_IO_ERROR)) | 2985 | if (tty->flags & (1 << TTY_IO_ERROR)) |
2950 | return -EIO; | 2986 | return -EIO; |
2951 | } | 2987 | } |
2952 | 2988 | ||
2953 | lock_kernel(); | 2989 | return mgsl_ioctl_common(info, cmd, arg); |
2954 | ret = mgsl_ioctl_common(info, cmd, arg); | ||
2955 | unlock_kernel(); | ||
2956 | return ret; | ||
2957 | } | 2990 | } |
2958 | 2991 | ||
2959 | static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg) | 2992 | static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg) |
2960 | { | 2993 | { |
2961 | int error; | ||
2962 | struct mgsl_icount cnow; /* kernel counter temps */ | ||
2963 | void __user *argp = (void __user *)arg; | 2994 | void __user *argp = (void __user *)arg; |
2964 | struct serial_icounter_struct __user *p_cuser; /* user space */ | ||
2965 | unsigned long flags; | ||
2966 | 2995 | ||
2967 | switch (cmd) { | 2996 | switch (cmd) { |
2968 | case MGSL_IOCGPARAMS: | 2997 | case MGSL_IOCGPARAMS: |
@@ -2991,40 +3020,6 @@ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigne | |||
2991 | case TIOCMIWAIT: | 3020 | case TIOCMIWAIT: |
2992 | return modem_input_wait(info,(int)arg); | 3021 | return modem_input_wait(info,(int)arg); |
2993 | 3022 | ||
2994 | /* | ||
2995 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) | ||
2996 | * Return: write counters to the user passed counter struct | ||
2997 | * NB: both 1->0 and 0->1 transitions are counted except for | ||
2998 | * RI where only 0->1 is counted. | ||
2999 | */ | ||
3000 | case TIOCGICOUNT: | ||
3001 | spin_lock_irqsave(&info->irq_spinlock,flags); | ||
3002 | cnow = info->icount; | ||
3003 | spin_unlock_irqrestore(&info->irq_spinlock,flags); | ||
3004 | p_cuser = argp; | ||
3005 | PUT_USER(error,cnow.cts, &p_cuser->cts); | ||
3006 | if (error) return error; | ||
3007 | PUT_USER(error,cnow.dsr, &p_cuser->dsr); | ||
3008 | if (error) return error; | ||
3009 | PUT_USER(error,cnow.rng, &p_cuser->rng); | ||
3010 | if (error) return error; | ||
3011 | PUT_USER(error,cnow.dcd, &p_cuser->dcd); | ||
3012 | if (error) return error; | ||
3013 | PUT_USER(error,cnow.rx, &p_cuser->rx); | ||
3014 | if (error) return error; | ||
3015 | PUT_USER(error,cnow.tx, &p_cuser->tx); | ||
3016 | if (error) return error; | ||
3017 | PUT_USER(error,cnow.frame, &p_cuser->frame); | ||
3018 | if (error) return error; | ||
3019 | PUT_USER(error,cnow.overrun, &p_cuser->overrun); | ||
3020 | if (error) return error; | ||
3021 | PUT_USER(error,cnow.parity, &p_cuser->parity); | ||
3022 | if (error) return error; | ||
3023 | PUT_USER(error,cnow.brk, &p_cuser->brk); | ||
3024 | if (error) return error; | ||
3025 | PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun); | ||
3026 | if (error) return error; | ||
3027 | return 0; | ||
3028 | default: | 3023 | default: |
3029 | return -ENOIOCTLCMD; | 3024 | return -ENOIOCTLCMD; |
3030 | } | 3025 | } |
@@ -3109,12 +3104,14 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp) | |||
3109 | 3104 | ||
3110 | if (tty_port_close_start(&info->port, tty, filp) == 0) | 3105 | if (tty_port_close_start(&info->port, tty, filp) == 0) |
3111 | goto cleanup; | 3106 | goto cleanup; |
3112 | 3107 | ||
3108 | mutex_lock(&info->port.mutex); | ||
3113 | if (info->port.flags & ASYNC_INITIALIZED) | 3109 | if (info->port.flags & ASYNC_INITIALIZED) |
3114 | mgsl_wait_until_sent(tty, info->timeout); | 3110 | mgsl_wait_until_sent(tty, info->timeout); |
3115 | mgsl_flush_buffer(tty); | 3111 | mgsl_flush_buffer(tty); |
3116 | tty_ldisc_flush(tty); | 3112 | tty_ldisc_flush(tty); |
3117 | shutdown(info); | 3113 | shutdown(info); |
3114 | mutex_unlock(&info->port.mutex); | ||
3118 | 3115 | ||
3119 | tty_port_close_end(&info->port, tty); | 3116 | tty_port_close_end(&info->port, tty); |
3120 | info->port.tty = NULL; | 3117 | info->port.tty = NULL; |
@@ -3162,7 +3159,6 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout) | |||
3162 | * Note: use tight timings here to satisfy the NIST-PCTS. | 3159 | * Note: use tight timings here to satisfy the NIST-PCTS. |
3163 | */ | 3160 | */ |
3164 | 3161 | ||
3165 | lock_kernel(); | ||
3166 | if ( info->params.data_rate ) { | 3162 | if ( info->params.data_rate ) { |
3167 | char_time = info->timeout/(32 * 5); | 3163 | char_time = info->timeout/(32 * 5); |
3168 | if (!char_time) | 3164 | if (!char_time) |
@@ -3192,7 +3188,6 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout) | |||
3192 | break; | 3188 | break; |
3193 | } | 3189 | } |
3194 | } | 3190 | } |
3195 | unlock_kernel(); | ||
3196 | 3191 | ||
3197 | exit: | 3192 | exit: |
3198 | if (debug_level >= DEBUG_LEVEL_INFO) | 3193 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -3348,7 +3343,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
3348 | printk("%s(%d):block_til_ready blocking on %s count=%d\n", | 3343 | printk("%s(%d):block_til_ready blocking on %s count=%d\n", |
3349 | __FILE__,__LINE__, tty->driver->name, port->count ); | 3344 | __FILE__,__LINE__, tty->driver->name, port->count ); |
3350 | 3345 | ||
3346 | tty_unlock(); | ||
3351 | schedule(); | 3347 | schedule(); |
3348 | tty_lock(); | ||
3352 | } | 3349 | } |
3353 | 3350 | ||
3354 | set_current_state(TASK_RUNNING); | 3351 | set_current_state(TASK_RUNNING); |
@@ -4325,6 +4322,7 @@ static const struct tty_operations mgsl_ops = { | |||
4325 | .hangup = mgsl_hangup, | 4322 | .hangup = mgsl_hangup, |
4326 | .tiocmget = tiocmget, | 4323 | .tiocmget = tiocmget, |
4327 | .tiocmset = tiocmset, | 4324 | .tiocmset = tiocmset, |
4325 | .get_icount = msgl_get_icount, | ||
4328 | .proc_fops = &mgsl_proc_fops, | 4326 | .proc_fops = &mgsl_proc_fops, |
4329 | }; | 4327 | }; |
4330 | 4328 | ||
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 8678f0c8699d..d01fffeac951 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -40,8 +40,8 @@ | |||
40 | #define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt | 40 | #define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt |
41 | #define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt | 41 | #define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt |
42 | #define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label)) | 42 | #define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label)) |
43 | //#define DBGTBUF(info) dump_tbufs(info) | 43 | /*#define DBGTBUF(info) dump_tbufs(info)*/ |
44 | //#define DBGRBUF(info) dump_rbufs(info) | 44 | /*#define DBGRBUF(info) dump_rbufs(info)*/ |
45 | 45 | ||
46 | 46 | ||
47 | #include <linux/module.h> | 47 | #include <linux/module.h> |
@@ -62,7 +62,6 @@ | |||
62 | #include <linux/mm.h> | 62 | #include <linux/mm.h> |
63 | #include <linux/seq_file.h> | 63 | #include <linux/seq_file.h> |
64 | #include <linux/slab.h> | 64 | #include <linux/slab.h> |
65 | #include <linux/smp_lock.h> | ||
66 | #include <linux/netdevice.h> | 65 | #include <linux/netdevice.h> |
67 | #include <linux/vmalloc.h> | 66 | #include <linux/vmalloc.h> |
68 | #include <linux/init.h> | 67 | #include <linux/init.h> |
@@ -302,6 +301,8 @@ struct slgt_info { | |||
302 | unsigned int rx_pio; | 301 | unsigned int rx_pio; |
303 | unsigned int if_mode; | 302 | unsigned int if_mode; |
304 | unsigned int base_clock; | 303 | unsigned int base_clock; |
304 | unsigned int xsync; | ||
305 | unsigned int xctrl; | ||
305 | 306 | ||
306 | /* device status */ | 307 | /* device status */ |
307 | 308 | ||
@@ -406,6 +407,8 @@ static MGSL_PARAMS default_params = { | |||
406 | #define TDCSR 0x94 /* tx DMA control/status */ | 407 | #define TDCSR 0x94 /* tx DMA control/status */ |
407 | #define RDDAR 0x98 /* rx DMA descriptor address */ | 408 | #define RDDAR 0x98 /* rx DMA descriptor address */ |
408 | #define TDDAR 0x9c /* tx DMA descriptor address */ | 409 | #define TDDAR 0x9c /* tx DMA descriptor address */ |
410 | #define XSR 0x40 /* extended sync pattern */ | ||
411 | #define XCR 0x44 /* extended control */ | ||
409 | 412 | ||
410 | #define RXIDLE BIT14 | 413 | #define RXIDLE BIT14 |
411 | #define RXBREAK BIT14 | 414 | #define RXBREAK BIT14 |
@@ -468,7 +471,7 @@ static unsigned int free_tbuf_count(struct slgt_info *info); | |||
468 | static unsigned int tbuf_bytes(struct slgt_info *info); | 471 | static unsigned int tbuf_bytes(struct slgt_info *info); |
469 | static void reset_tbufs(struct slgt_info *info); | 472 | static void reset_tbufs(struct slgt_info *info); |
470 | static void tdma_reset(struct slgt_info *info); | 473 | static void tdma_reset(struct slgt_info *info); |
471 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int count); | 474 | static bool tx_load(struct slgt_info *info, const char *buf, unsigned int count); |
472 | 475 | ||
473 | static void get_signals(struct slgt_info *info); | 476 | static void get_signals(struct slgt_info *info); |
474 | static void set_signals(struct slgt_info *info); | 477 | static void set_signals(struct slgt_info *info); |
@@ -518,6 +521,10 @@ static int set_interface(struct slgt_info *info, int if_mode); | |||
518 | static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); | 521 | static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); |
519 | static int get_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); | 522 | static int get_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); |
520 | static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); | 523 | static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); |
524 | static int get_xsync(struct slgt_info *info, int __user *if_mode); | ||
525 | static int set_xsync(struct slgt_info *info, int if_mode); | ||
526 | static int get_xctrl(struct slgt_info *info, int __user *if_mode); | ||
527 | static int set_xctrl(struct slgt_info *info, int if_mode); | ||
521 | 528 | ||
522 | /* | 529 | /* |
523 | * driver functions | 530 | * driver functions |
@@ -676,12 +683,14 @@ static int open(struct tty_struct *tty, struct file *filp) | |||
676 | goto cleanup; | 683 | goto cleanup; |
677 | } | 684 | } |
678 | 685 | ||
686 | mutex_lock(&info->port.mutex); | ||
679 | info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 687 | info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
680 | 688 | ||
681 | spin_lock_irqsave(&info->netlock, flags); | 689 | spin_lock_irqsave(&info->netlock, flags); |
682 | if (info->netcount) { | 690 | if (info->netcount) { |
683 | retval = -EBUSY; | 691 | retval = -EBUSY; |
684 | spin_unlock_irqrestore(&info->netlock, flags); | 692 | spin_unlock_irqrestore(&info->netlock, flags); |
693 | mutex_unlock(&info->port.mutex); | ||
685 | goto cleanup; | 694 | goto cleanup; |
686 | } | 695 | } |
687 | info->port.count++; | 696 | info->port.count++; |
@@ -690,10 +699,12 @@ static int open(struct tty_struct *tty, struct file *filp) | |||
690 | if (info->port.count == 1) { | 699 | if (info->port.count == 1) { |
691 | /* 1st open on this device, init hardware */ | 700 | /* 1st open on this device, init hardware */ |
692 | retval = startup(info); | 701 | retval = startup(info); |
693 | if (retval < 0) | 702 | if (retval < 0) { |
703 | mutex_unlock(&info->port.mutex); | ||
694 | goto cleanup; | 704 | goto cleanup; |
705 | } | ||
695 | } | 706 | } |
696 | 707 | mutex_unlock(&info->port.mutex); | |
697 | retval = block_til_ready(tty, filp, info); | 708 | retval = block_til_ready(tty, filp, info); |
698 | if (retval) { | 709 | if (retval) { |
699 | DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval)); | 710 | DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval)); |
@@ -725,12 +736,14 @@ static void close(struct tty_struct *tty, struct file *filp) | |||
725 | if (tty_port_close_start(&info->port, tty, filp) == 0) | 736 | if (tty_port_close_start(&info->port, tty, filp) == 0) |
726 | goto cleanup; | 737 | goto cleanup; |
727 | 738 | ||
739 | mutex_lock(&info->port.mutex); | ||
728 | if (info->port.flags & ASYNC_INITIALIZED) | 740 | if (info->port.flags & ASYNC_INITIALIZED) |
729 | wait_until_sent(tty, info->timeout); | 741 | wait_until_sent(tty, info->timeout); |
730 | flush_buffer(tty); | 742 | flush_buffer(tty); |
731 | tty_ldisc_flush(tty); | 743 | tty_ldisc_flush(tty); |
732 | 744 | ||
733 | shutdown(info); | 745 | shutdown(info); |
746 | mutex_unlock(&info->port.mutex); | ||
734 | 747 | ||
735 | tty_port_close_end(&info->port, tty); | 748 | tty_port_close_end(&info->port, tty); |
736 | info->port.tty = NULL; | 749 | info->port.tty = NULL; |
@@ -741,17 +754,23 @@ cleanup: | |||
741 | static void hangup(struct tty_struct *tty) | 754 | static void hangup(struct tty_struct *tty) |
742 | { | 755 | { |
743 | struct slgt_info *info = tty->driver_data; | 756 | struct slgt_info *info = tty->driver_data; |
757 | unsigned long flags; | ||
744 | 758 | ||
745 | if (sanity_check(info, tty->name, "hangup")) | 759 | if (sanity_check(info, tty->name, "hangup")) |
746 | return; | 760 | return; |
747 | DBGINFO(("%s hangup\n", info->device_name)); | 761 | DBGINFO(("%s hangup\n", info->device_name)); |
748 | 762 | ||
749 | flush_buffer(tty); | 763 | flush_buffer(tty); |
764 | |||
765 | mutex_lock(&info->port.mutex); | ||
750 | shutdown(info); | 766 | shutdown(info); |
751 | 767 | ||
768 | spin_lock_irqsave(&info->port.lock, flags); | ||
752 | info->port.count = 0; | 769 | info->port.count = 0; |
753 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 770 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; |
754 | info->port.tty = NULL; | 771 | info->port.tty = NULL; |
772 | spin_unlock_irqrestore(&info->port.lock, flags); | ||
773 | mutex_unlock(&info->port.mutex); | ||
755 | 774 | ||
756 | wake_up_interruptible(&info->port.open_wait); | 775 | wake_up_interruptible(&info->port.open_wait); |
757 | } | 776 | } |
@@ -813,59 +832,32 @@ static int write(struct tty_struct *tty, | |||
813 | int ret = 0; | 832 | int ret = 0; |
814 | struct slgt_info *info = tty->driver_data; | 833 | struct slgt_info *info = tty->driver_data; |
815 | unsigned long flags; | 834 | unsigned long flags; |
816 | unsigned int bufs_needed; | ||
817 | 835 | ||
818 | if (sanity_check(info, tty->name, "write")) | 836 | if (sanity_check(info, tty->name, "write")) |
819 | goto cleanup; | 837 | return -EIO; |
838 | |||
820 | DBGINFO(("%s write count=%d\n", info->device_name, count)); | 839 | DBGINFO(("%s write count=%d\n", info->device_name, count)); |
821 | 840 | ||
822 | if (!info->tx_buf) | 841 | if (!info->tx_buf || (count > info->max_frame_size)) |
823 | goto cleanup; | 842 | return -EIO; |
824 | 843 | ||
825 | if (count > info->max_frame_size) { | 844 | if (!count || tty->stopped || tty->hw_stopped) |
826 | ret = -EIO; | 845 | return 0; |
827 | goto cleanup; | ||
828 | } | ||
829 | 846 | ||
830 | if (!count) | 847 | spin_lock_irqsave(&info->lock, flags); |
831 | goto cleanup; | ||
832 | 848 | ||
833 | if (!info->tx_active && info->tx_count) { | 849 | if (info->tx_count) { |
834 | /* send accumulated data from send_char() */ | 850 | /* send accumulated data from send_char() */ |
835 | tx_load(info, info->tx_buf, info->tx_count); | 851 | if (!tx_load(info, info->tx_buf, info->tx_count)) |
836 | goto start; | 852 | goto cleanup; |
853 | info->tx_count = 0; | ||
837 | } | 854 | } |
838 | bufs_needed = (count/DMABUFSIZE); | ||
839 | if (count % DMABUFSIZE) | ||
840 | ++bufs_needed; | ||
841 | if (bufs_needed > free_tbuf_count(info)) | ||
842 | goto cleanup; | ||
843 | |||
844 | ret = info->tx_count = count; | ||
845 | tx_load(info, buf, count); | ||
846 | goto start; | ||
847 | 855 | ||
848 | start: | 856 | if (tx_load(info, buf, count)) |
849 | if (info->tx_count && !tty->stopped && !tty->hw_stopped) { | 857 | ret = count; |
850 | spin_lock_irqsave(&info->lock,flags); | ||
851 | if (!info->tx_active) | ||
852 | tx_start(info); | ||
853 | else if (!(rd_reg32(info, TDCSR) & BIT0)) { | ||
854 | /* transmit still active but transmit DMA stopped */ | ||
855 | unsigned int i = info->tbuf_current; | ||
856 | if (!i) | ||
857 | i = info->tbuf_count; | ||
858 | i--; | ||
859 | /* if DMA buf unsent must try later after tx idle */ | ||
860 | if (desc_count(info->tbufs[i])) | ||
861 | ret = 0; | ||
862 | } | ||
863 | if (ret > 0) | ||
864 | update_tx_timer(info); | ||
865 | spin_unlock_irqrestore(&info->lock,flags); | ||
866 | } | ||
867 | 858 | ||
868 | cleanup: | 859 | cleanup: |
860 | spin_unlock_irqrestore(&info->lock, flags); | ||
869 | DBGINFO(("%s write rc=%d\n", info->device_name, ret)); | 861 | DBGINFO(("%s write rc=%d\n", info->device_name, ret)); |
870 | return ret; | 862 | return ret; |
871 | } | 863 | } |
@@ -882,7 +874,7 @@ static int put_char(struct tty_struct *tty, unsigned char ch) | |||
882 | if (!info->tx_buf) | 874 | if (!info->tx_buf) |
883 | return 0; | 875 | return 0; |
884 | spin_lock_irqsave(&info->lock,flags); | 876 | spin_lock_irqsave(&info->lock,flags); |
885 | if (!info->tx_active && (info->tx_count < info->max_frame_size)) { | 877 | if (info->tx_count < info->max_frame_size) { |
886 | info->tx_buf[info->tx_count++] = ch; | 878 | info->tx_buf[info->tx_count++] = ch; |
887 | ret = 1; | 879 | ret = 1; |
888 | } | 880 | } |
@@ -928,8 +920,6 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) | |||
928 | * Note: use tight timings here to satisfy the NIST-PCTS. | 920 | * Note: use tight timings here to satisfy the NIST-PCTS. |
929 | */ | 921 | */ |
930 | 922 | ||
931 | lock_kernel(); | ||
932 | |||
933 | if (info->params.data_rate) { | 923 | if (info->params.data_rate) { |
934 | char_time = info->timeout/(32 * 5); | 924 | char_time = info->timeout/(32 * 5); |
935 | if (!char_time) | 925 | if (!char_time) |
@@ -947,8 +937,6 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) | |||
947 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) | 937 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) |
948 | break; | 938 | break; |
949 | } | 939 | } |
950 | unlock_kernel(); | ||
951 | |||
952 | exit: | 940 | exit: |
953 | DBGINFO(("%s wait_until_sent exit\n", info->device_name)); | 941 | DBGINFO(("%s wait_until_sent exit\n", info->device_name)); |
954 | } | 942 | } |
@@ -981,10 +969,8 @@ static void flush_chars(struct tty_struct *tty) | |||
981 | DBGINFO(("%s flush_chars start transmit\n", info->device_name)); | 969 | DBGINFO(("%s flush_chars start transmit\n", info->device_name)); |
982 | 970 | ||
983 | spin_lock_irqsave(&info->lock,flags); | 971 | spin_lock_irqsave(&info->lock,flags); |
984 | if (!info->tx_active && info->tx_count) { | 972 | if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count)) |
985 | tx_load(info, info->tx_buf,info->tx_count); | 973 | info->tx_count = 0; |
986 | tx_start(info); | ||
987 | } | ||
988 | spin_unlock_irqrestore(&info->lock,flags); | 974 | spin_unlock_irqrestore(&info->lock,flags); |
989 | } | 975 | } |
990 | 976 | ||
@@ -997,10 +983,9 @@ static void flush_buffer(struct tty_struct *tty) | |||
997 | return; | 983 | return; |
998 | DBGINFO(("%s flush_buffer\n", info->device_name)); | 984 | DBGINFO(("%s flush_buffer\n", info->device_name)); |
999 | 985 | ||
1000 | spin_lock_irqsave(&info->lock,flags); | 986 | spin_lock_irqsave(&info->lock, flags); |
1001 | if (!info->tx_active) | 987 | info->tx_count = 0; |
1002 | info->tx_count = 0; | 988 | spin_unlock_irqrestore(&info->lock, flags); |
1003 | spin_unlock_irqrestore(&info->lock,flags); | ||
1004 | 989 | ||
1005 | tty_wakeup(tty); | 990 | tty_wakeup(tty); |
1006 | } | 991 | } |
@@ -1033,12 +1018,10 @@ static void tx_release(struct tty_struct *tty) | |||
1033 | if (sanity_check(info, tty->name, "tx_release")) | 1018 | if (sanity_check(info, tty->name, "tx_release")) |
1034 | return; | 1019 | return; |
1035 | DBGINFO(("%s tx_release\n", info->device_name)); | 1020 | DBGINFO(("%s tx_release\n", info->device_name)); |
1036 | spin_lock_irqsave(&info->lock,flags); | 1021 | spin_lock_irqsave(&info->lock, flags); |
1037 | if (!info->tx_active && info->tx_count) { | 1022 | if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count)) |
1038 | tx_load(info, info->tx_buf, info->tx_count); | 1023 | info->tx_count = 0; |
1039 | tx_start(info); | 1024 | spin_unlock_irqrestore(&info->lock, flags); |
1040 | } | ||
1041 | spin_unlock_irqrestore(&info->lock,flags); | ||
1042 | } | 1025 | } |
1043 | 1026 | ||
1044 | /* | 1027 | /* |
@@ -1057,9 +1040,6 @@ static int ioctl(struct tty_struct *tty, struct file *file, | |||
1057 | unsigned int cmd, unsigned long arg) | 1040 | unsigned int cmd, unsigned long arg) |
1058 | { | 1041 | { |
1059 | struct slgt_info *info = tty->driver_data; | 1042 | struct slgt_info *info = tty->driver_data; |
1060 | struct mgsl_icount cnow; /* kernel counter temps */ | ||
1061 | struct serial_icounter_struct __user *p_cuser; /* user space */ | ||
1062 | unsigned long flags; | ||
1063 | void __user *argp = (void __user *)arg; | 1043 | void __user *argp = (void __user *)arg; |
1064 | int ret; | 1044 | int ret; |
1065 | 1045 | ||
@@ -1068,13 +1048,32 @@ static int ioctl(struct tty_struct *tty, struct file *file, | |||
1068 | DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd)); | 1048 | DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd)); |
1069 | 1049 | ||
1070 | if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && | 1050 | if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && |
1071 | (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { | 1051 | (cmd != TIOCMIWAIT)) { |
1072 | if (tty->flags & (1 << TTY_IO_ERROR)) | 1052 | if (tty->flags & (1 << TTY_IO_ERROR)) |
1073 | return -EIO; | 1053 | return -EIO; |
1074 | } | 1054 | } |
1075 | 1055 | ||
1076 | lock_kernel(); | 1056 | switch (cmd) { |
1077 | 1057 | case MGSL_IOCWAITEVENT: | |
1058 | return wait_mgsl_event(info, argp); | ||
1059 | case TIOCMIWAIT: | ||
1060 | return modem_input_wait(info,(int)arg); | ||
1061 | case MGSL_IOCSGPIO: | ||
1062 | return set_gpio(info, argp); | ||
1063 | case MGSL_IOCGGPIO: | ||
1064 | return get_gpio(info, argp); | ||
1065 | case MGSL_IOCWAITGPIO: | ||
1066 | return wait_gpio(info, argp); | ||
1067 | case MGSL_IOCGXSYNC: | ||
1068 | return get_xsync(info, argp); | ||
1069 | case MGSL_IOCSXSYNC: | ||
1070 | return set_xsync(info, (int)arg); | ||
1071 | case MGSL_IOCGXCTRL: | ||
1072 | return get_xctrl(info, argp); | ||
1073 | case MGSL_IOCSXCTRL: | ||
1074 | return set_xctrl(info, (int)arg); | ||
1075 | } | ||
1076 | mutex_lock(&info->port.mutex); | ||
1078 | switch (cmd) { | 1077 | switch (cmd) { |
1079 | case MGSL_IOCGPARAMS: | 1078 | case MGSL_IOCGPARAMS: |
1080 | ret = get_params(info, argp); | 1079 | ret = get_params(info, argp); |
@@ -1100,53 +1099,46 @@ static int ioctl(struct tty_struct *tty, struct file *file, | |||
1100 | case MGSL_IOCGSTATS: | 1099 | case MGSL_IOCGSTATS: |
1101 | ret = get_stats(info, argp); | 1100 | ret = get_stats(info, argp); |
1102 | break; | 1101 | break; |
1103 | case MGSL_IOCWAITEVENT: | ||
1104 | ret = wait_mgsl_event(info, argp); | ||
1105 | break; | ||
1106 | case TIOCMIWAIT: | ||
1107 | ret = modem_input_wait(info,(int)arg); | ||
1108 | break; | ||
1109 | case MGSL_IOCGIF: | 1102 | case MGSL_IOCGIF: |
1110 | ret = get_interface(info, argp); | 1103 | ret = get_interface(info, argp); |
1111 | break; | 1104 | break; |
1112 | case MGSL_IOCSIF: | 1105 | case MGSL_IOCSIF: |
1113 | ret = set_interface(info,(int)arg); | 1106 | ret = set_interface(info,(int)arg); |
1114 | break; | 1107 | break; |
1115 | case MGSL_IOCSGPIO: | ||
1116 | ret = set_gpio(info, argp); | ||
1117 | break; | ||
1118 | case MGSL_IOCGGPIO: | ||
1119 | ret = get_gpio(info, argp); | ||
1120 | break; | ||
1121 | case MGSL_IOCWAITGPIO: | ||
1122 | ret = wait_gpio(info, argp); | ||
1123 | break; | ||
1124 | case TIOCGICOUNT: | ||
1125 | spin_lock_irqsave(&info->lock,flags); | ||
1126 | cnow = info->icount; | ||
1127 | spin_unlock_irqrestore(&info->lock,flags); | ||
1128 | p_cuser = argp; | ||
1129 | if (put_user(cnow.cts, &p_cuser->cts) || | ||
1130 | put_user(cnow.dsr, &p_cuser->dsr) || | ||
1131 | put_user(cnow.rng, &p_cuser->rng) || | ||
1132 | put_user(cnow.dcd, &p_cuser->dcd) || | ||
1133 | put_user(cnow.rx, &p_cuser->rx) || | ||
1134 | put_user(cnow.tx, &p_cuser->tx) || | ||
1135 | put_user(cnow.frame, &p_cuser->frame) || | ||
1136 | put_user(cnow.overrun, &p_cuser->overrun) || | ||
1137 | put_user(cnow.parity, &p_cuser->parity) || | ||
1138 | put_user(cnow.brk, &p_cuser->brk) || | ||
1139 | put_user(cnow.buf_overrun, &p_cuser->buf_overrun)) | ||
1140 | ret = -EFAULT; | ||
1141 | ret = 0; | ||
1142 | break; | ||
1143 | default: | 1108 | default: |
1144 | ret = -ENOIOCTLCMD; | 1109 | ret = -ENOIOCTLCMD; |
1145 | } | 1110 | } |
1146 | unlock_kernel(); | 1111 | mutex_unlock(&info->port.mutex); |
1147 | return ret; | 1112 | return ret; |
1148 | } | 1113 | } |
1149 | 1114 | ||
1115 | static int get_icount(struct tty_struct *tty, | ||
1116 | struct serial_icounter_struct *icount) | ||
1117 | |||
1118 | { | ||
1119 | struct slgt_info *info = tty->driver_data; | ||
1120 | struct mgsl_icount cnow; /* kernel counter temps */ | ||
1121 | unsigned long flags; | ||
1122 | |||
1123 | spin_lock_irqsave(&info->lock,flags); | ||
1124 | cnow = info->icount; | ||
1125 | spin_unlock_irqrestore(&info->lock,flags); | ||
1126 | |||
1127 | icount->cts = cnow.cts; | ||
1128 | icount->dsr = cnow.dsr; | ||
1129 | icount->rng = cnow.rng; | ||
1130 | icount->dcd = cnow.dcd; | ||
1131 | icount->rx = cnow.rx; | ||
1132 | icount->tx = cnow.tx; | ||
1133 | icount->frame = cnow.frame; | ||
1134 | icount->overrun = cnow.overrun; | ||
1135 | icount->parity = cnow.parity; | ||
1136 | icount->brk = cnow.brk; | ||
1137 | icount->buf_overrun = cnow.buf_overrun; | ||
1138 | |||
1139 | return 0; | ||
1140 | } | ||
1141 | |||
1150 | /* | 1142 | /* |
1151 | * support for 32 bit ioctl calls on 64 bit systems | 1143 | * support for 32 bit ioctl calls on 64 bit systems |
1152 | */ | 1144 | */ |
@@ -1156,6 +1148,7 @@ static long get_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *us | |||
1156 | struct MGSL_PARAMS32 tmp_params; | 1148 | struct MGSL_PARAMS32 tmp_params; |
1157 | 1149 | ||
1158 | DBGINFO(("%s get_params32\n", info->device_name)); | 1150 | DBGINFO(("%s get_params32\n", info->device_name)); |
1151 | memset(&tmp_params, 0, sizeof(tmp_params)); | ||
1159 | tmp_params.mode = (compat_ulong_t)info->params.mode; | 1152 | tmp_params.mode = (compat_ulong_t)info->params.mode; |
1160 | tmp_params.loopback = info->params.loopback; | 1153 | tmp_params.loopback = info->params.loopback; |
1161 | tmp_params.flags = info->params.flags; | 1154 | tmp_params.flags = info->params.flags; |
@@ -1236,16 +1229,16 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file, | |||
1236 | case MGSL_IOCSGPIO: | 1229 | case MGSL_IOCSGPIO: |
1237 | case MGSL_IOCGGPIO: | 1230 | case MGSL_IOCGGPIO: |
1238 | case MGSL_IOCWAITGPIO: | 1231 | case MGSL_IOCWAITGPIO: |
1239 | case TIOCGICOUNT: | 1232 | case MGSL_IOCGXSYNC: |
1240 | rc = ioctl(tty, file, cmd, (unsigned long)(compat_ptr(arg))); | 1233 | case MGSL_IOCGXCTRL: |
1241 | break; | ||
1242 | |||
1243 | case MGSL_IOCSTXIDLE: | 1234 | case MGSL_IOCSTXIDLE: |
1244 | case MGSL_IOCTXENABLE: | 1235 | case MGSL_IOCTXENABLE: |
1245 | case MGSL_IOCRXENABLE: | 1236 | case MGSL_IOCRXENABLE: |
1246 | case MGSL_IOCTXABORT: | 1237 | case MGSL_IOCTXABORT: |
1247 | case TIOCMIWAIT: | 1238 | case TIOCMIWAIT: |
1248 | case MGSL_IOCSIF: | 1239 | case MGSL_IOCSIF: |
1240 | case MGSL_IOCSXSYNC: | ||
1241 | case MGSL_IOCSXCTRL: | ||
1249 | rc = ioctl(tty, file, cmd, arg); | 1242 | rc = ioctl(tty, file, cmd, arg); |
1250 | break; | 1243 | break; |
1251 | } | 1244 | } |
@@ -1506,27 +1499,25 @@ static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb, | |||
1506 | 1499 | ||
1507 | DBGINFO(("%s hdlc_xmit\n", dev->name)); | 1500 | DBGINFO(("%s hdlc_xmit\n", dev->name)); |
1508 | 1501 | ||
1502 | if (!skb->len) | ||
1503 | return NETDEV_TX_OK; | ||
1504 | |||
1509 | /* stop sending until this frame completes */ | 1505 | /* stop sending until this frame completes */ |
1510 | netif_stop_queue(dev); | 1506 | netif_stop_queue(dev); |
1511 | 1507 | ||
1512 | /* copy data to device buffers */ | ||
1513 | info->tx_count = skb->len; | ||
1514 | tx_load(info, skb->data, skb->len); | ||
1515 | |||
1516 | /* update network statistics */ | 1508 | /* update network statistics */ |
1517 | dev->stats.tx_packets++; | 1509 | dev->stats.tx_packets++; |
1518 | dev->stats.tx_bytes += skb->len; | 1510 | dev->stats.tx_bytes += skb->len; |
1519 | 1511 | ||
1520 | /* done with socket buffer, so free it */ | ||
1521 | dev_kfree_skb(skb); | ||
1522 | |||
1523 | /* save start time for transmit timeout detection */ | 1512 | /* save start time for transmit timeout detection */ |
1524 | dev->trans_start = jiffies; | 1513 | dev->trans_start = jiffies; |
1525 | 1514 | ||
1526 | spin_lock_irqsave(&info->lock,flags); | 1515 | spin_lock_irqsave(&info->lock, flags); |
1527 | tx_start(info); | 1516 | tx_load(info, skb->data, skb->len); |
1528 | update_tx_timer(info); | 1517 | spin_unlock_irqrestore(&info->lock, flags); |
1529 | spin_unlock_irqrestore(&info->lock,flags); | 1518 | |
1519 | /* done with socket buffer, so free it */ | ||
1520 | dev_kfree_skb(skb); | ||
1530 | 1521 | ||
1531 | return NETDEV_TX_OK; | 1522 | return NETDEV_TX_OK; |
1532 | } | 1523 | } |
@@ -1647,6 +1638,8 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1647 | if (cmd != SIOCWANDEV) | 1638 | if (cmd != SIOCWANDEV) |
1648 | return hdlc_ioctl(dev, ifr, cmd); | 1639 | return hdlc_ioctl(dev, ifr, cmd); |
1649 | 1640 | ||
1641 | memset(&new_line, 0, sizeof(new_line)); | ||
1642 | |||
1650 | switch(ifr->ifr_settings.type) { | 1643 | switch(ifr->ifr_settings.type) { |
1651 | case IF_GET_IFACE: /* return current sync_serial_settings */ | 1644 | case IF_GET_IFACE: /* return current sync_serial_settings */ |
1652 | 1645 | ||
@@ -1988,6 +1981,7 @@ static void bh_handler(struct work_struct *work) | |||
1988 | case MGSL_MODE_RAW: | 1981 | case MGSL_MODE_RAW: |
1989 | case MGSL_MODE_MONOSYNC: | 1982 | case MGSL_MODE_MONOSYNC: |
1990 | case MGSL_MODE_BISYNC: | 1983 | case MGSL_MODE_BISYNC: |
1984 | case MGSL_MODE_XSYNC: | ||
1991 | while(rx_get_buf(info)); | 1985 | while(rx_get_buf(info)); |
1992 | break; | 1986 | break; |
1993 | } | 1987 | } |
@@ -2180,7 +2174,7 @@ static void isr_serial(struct slgt_info *info) | |||
2180 | 2174 | ||
2181 | if (info->params.mode == MGSL_MODE_ASYNC) { | 2175 | if (info->params.mode == MGSL_MODE_ASYNC) { |
2182 | if (status & IRQ_TXIDLE) { | 2176 | if (status & IRQ_TXIDLE) { |
2183 | if (info->tx_count) | 2177 | if (info->tx_active) |
2184 | isr_txeom(info, status); | 2178 | isr_txeom(info, status); |
2185 | } | 2179 | } |
2186 | if (info->rx_pio && (status & IRQ_RXDATA)) | 2180 | if (info->rx_pio && (status & IRQ_RXDATA)) |
@@ -2276,13 +2270,42 @@ static void isr_tdma(struct slgt_info *info) | |||
2276 | } | 2270 | } |
2277 | } | 2271 | } |
2278 | 2272 | ||
2273 | /* | ||
2274 | * return true if there are unsent tx DMA buffers, otherwise false | ||
2275 | * | ||
2276 | * if there are unsent buffers then info->tbuf_start | ||
2277 | * is set to index of first unsent buffer | ||
2278 | */ | ||
2279 | static bool unsent_tbufs(struct slgt_info *info) | ||
2280 | { | ||
2281 | unsigned int i = info->tbuf_current; | ||
2282 | bool rc = false; | ||
2283 | |||
2284 | /* | ||
2285 | * search backwards from last loaded buffer (precedes tbuf_current) | ||
2286 | * for first unsent buffer (desc_count > 0) | ||
2287 | */ | ||
2288 | |||
2289 | do { | ||
2290 | if (i) | ||
2291 | i--; | ||
2292 | else | ||
2293 | i = info->tbuf_count - 1; | ||
2294 | if (!desc_count(info->tbufs[i])) | ||
2295 | break; | ||
2296 | info->tbuf_start = i; | ||
2297 | rc = true; | ||
2298 | } while (i != info->tbuf_current); | ||
2299 | |||
2300 | return rc; | ||
2301 | } | ||
2302 | |||
2279 | static void isr_txeom(struct slgt_info *info, unsigned short status) | 2303 | static void isr_txeom(struct slgt_info *info, unsigned short status) |
2280 | { | 2304 | { |
2281 | DBGISR(("%s txeom status=%04x\n", info->device_name, status)); | 2305 | DBGISR(("%s txeom status=%04x\n", info->device_name, status)); |
2282 | 2306 | ||
2283 | slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER); | 2307 | slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER); |
2284 | tdma_reset(info); | 2308 | tdma_reset(info); |
2285 | reset_tbufs(info); | ||
2286 | if (status & IRQ_TXUNDER) { | 2309 | if (status & IRQ_TXUNDER) { |
2287 | unsigned short val = rd_reg16(info, TCR); | 2310 | unsigned short val = rd_reg16(info, TCR); |
2288 | wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */ | 2311 | wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */ |
@@ -2297,8 +2320,12 @@ static void isr_txeom(struct slgt_info *info, unsigned short status) | |||
2297 | info->icount.txok++; | 2320 | info->icount.txok++; |
2298 | } | 2321 | } |
2299 | 2322 | ||
2323 | if (unsent_tbufs(info)) { | ||
2324 | tx_start(info); | ||
2325 | update_tx_timer(info); | ||
2326 | return; | ||
2327 | } | ||
2300 | info->tx_active = false; | 2328 | info->tx_active = false; |
2301 | info->tx_count = 0; | ||
2302 | 2329 | ||
2303 | del_timer(&info->tx_timer); | 2330 | del_timer(&info->tx_timer); |
2304 | 2331 | ||
@@ -2354,26 +2381,27 @@ static irqreturn_t slgt_interrupt(int dummy, void *dev_id) | |||
2354 | 2381 | ||
2355 | DBGISR(("slgt_interrupt irq=%d entry\n", info->irq_level)); | 2382 | DBGISR(("slgt_interrupt irq=%d entry\n", info->irq_level)); |
2356 | 2383 | ||
2357 | spin_lock(&info->lock); | ||
2358 | |||
2359 | while((gsr = rd_reg32(info, GSR) & 0xffffff00)) { | 2384 | while((gsr = rd_reg32(info, GSR) & 0xffffff00)) { |
2360 | DBGISR(("%s gsr=%08x\n", info->device_name, gsr)); | 2385 | DBGISR(("%s gsr=%08x\n", info->device_name, gsr)); |
2361 | info->irq_occurred = true; | 2386 | info->irq_occurred = true; |
2362 | for(i=0; i < info->port_count ; i++) { | 2387 | for(i=0; i < info->port_count ; i++) { |
2363 | if (info->port_array[i] == NULL) | 2388 | if (info->port_array[i] == NULL) |
2364 | continue; | 2389 | continue; |
2390 | spin_lock(&info->port_array[i]->lock); | ||
2365 | if (gsr & (BIT8 << i)) | 2391 | if (gsr & (BIT8 << i)) |
2366 | isr_serial(info->port_array[i]); | 2392 | isr_serial(info->port_array[i]); |
2367 | if (gsr & (BIT16 << (i*2))) | 2393 | if (gsr & (BIT16 << (i*2))) |
2368 | isr_rdma(info->port_array[i]); | 2394 | isr_rdma(info->port_array[i]); |
2369 | if (gsr & (BIT17 << (i*2))) | 2395 | if (gsr & (BIT17 << (i*2))) |
2370 | isr_tdma(info->port_array[i]); | 2396 | isr_tdma(info->port_array[i]); |
2397 | spin_unlock(&info->port_array[i]->lock); | ||
2371 | } | 2398 | } |
2372 | } | 2399 | } |
2373 | 2400 | ||
2374 | if (info->gpio_present) { | 2401 | if (info->gpio_present) { |
2375 | unsigned int state; | 2402 | unsigned int state; |
2376 | unsigned int changed; | 2403 | unsigned int changed; |
2404 | spin_lock(&info->lock); | ||
2377 | while ((changed = rd_reg32(info, IOSR)) != 0) { | 2405 | while ((changed = rd_reg32(info, IOSR)) != 0) { |
2378 | DBGISR(("%s iosr=%08x\n", info->device_name, changed)); | 2406 | DBGISR(("%s iosr=%08x\n", info->device_name, changed)); |
2379 | /* read latched state of GPIO signals */ | 2407 | /* read latched state of GPIO signals */ |
@@ -2385,22 +2413,24 @@ static irqreturn_t slgt_interrupt(int dummy, void *dev_id) | |||
2385 | isr_gpio(info->port_array[i], changed, state); | 2413 | isr_gpio(info->port_array[i], changed, state); |
2386 | } | 2414 | } |
2387 | } | 2415 | } |
2416 | spin_unlock(&info->lock); | ||
2388 | } | 2417 | } |
2389 | 2418 | ||
2390 | for(i=0; i < info->port_count ; i++) { | 2419 | for(i=0; i < info->port_count ; i++) { |
2391 | struct slgt_info *port = info->port_array[i]; | 2420 | struct slgt_info *port = info->port_array[i]; |
2392 | 2421 | if (port == NULL) | |
2393 | if (port && (port->port.count || port->netcount) && | 2422 | continue; |
2423 | spin_lock(&port->lock); | ||
2424 | if ((port->port.count || port->netcount) && | ||
2394 | port->pending_bh && !port->bh_running && | 2425 | port->pending_bh && !port->bh_running && |
2395 | !port->bh_requested) { | 2426 | !port->bh_requested) { |
2396 | DBGISR(("%s bh queued\n", port->device_name)); | 2427 | DBGISR(("%s bh queued\n", port->device_name)); |
2397 | schedule_work(&port->task); | 2428 | schedule_work(&port->task); |
2398 | port->bh_requested = true; | 2429 | port->bh_requested = true; |
2399 | } | 2430 | } |
2431 | spin_unlock(&port->lock); | ||
2400 | } | 2432 | } |
2401 | 2433 | ||
2402 | spin_unlock(&info->lock); | ||
2403 | |||
2404 | DBGISR(("slgt_interrupt irq=%d exit\n", info->irq_level)); | 2434 | DBGISR(("slgt_interrupt irq=%d exit\n", info->irq_level)); |
2405 | return IRQ_HANDLED; | 2435 | return IRQ_HANDLED; |
2406 | } | 2436 | } |
@@ -2880,6 +2910,69 @@ static int set_interface(struct slgt_info *info, int if_mode) | |||
2880 | return 0; | 2910 | return 0; |
2881 | } | 2911 | } |
2882 | 2912 | ||
2913 | static int get_xsync(struct slgt_info *info, int __user *xsync) | ||
2914 | { | ||
2915 | DBGINFO(("%s get_xsync=%x\n", info->device_name, info->xsync)); | ||
2916 | if (put_user(info->xsync, xsync)) | ||
2917 | return -EFAULT; | ||
2918 | return 0; | ||
2919 | } | ||
2920 | |||
2921 | /* | ||
2922 | * set extended sync pattern (1 to 4 bytes) for extended sync mode | ||
2923 | * | ||
2924 | * sync pattern is contained in least significant bytes of value | ||
2925 | * most significant byte of sync pattern is oldest (1st sent/detected) | ||
2926 | */ | ||
2927 | static int set_xsync(struct slgt_info *info, int xsync) | ||
2928 | { | ||
2929 | unsigned long flags; | ||
2930 | |||
2931 | DBGINFO(("%s set_xsync=%x)\n", info->device_name, xsync)); | ||
2932 | spin_lock_irqsave(&info->lock, flags); | ||
2933 | info->xsync = xsync; | ||
2934 | wr_reg32(info, XSR, xsync); | ||
2935 | spin_unlock_irqrestore(&info->lock, flags); | ||
2936 | return 0; | ||
2937 | } | ||
2938 | |||
2939 | static int get_xctrl(struct slgt_info *info, int __user *xctrl) | ||
2940 | { | ||
2941 | DBGINFO(("%s get_xctrl=%x\n", info->device_name, info->xctrl)); | ||
2942 | if (put_user(info->xctrl, xctrl)) | ||
2943 | return -EFAULT; | ||
2944 | return 0; | ||
2945 | } | ||
2946 | |||
2947 | /* | ||
2948 | * set extended control options | ||
2949 | * | ||
2950 | * xctrl[31:19] reserved, must be zero | ||
2951 | * xctrl[18:17] extended sync pattern length in bytes | ||
2952 | * 00 = 1 byte in xsr[7:0] | ||
2953 | * 01 = 2 bytes in xsr[15:0] | ||
2954 | * 10 = 3 bytes in xsr[23:0] | ||
2955 | * 11 = 4 bytes in xsr[31:0] | ||
2956 | * xctrl[16] 1 = enable terminal count, 0=disabled | ||
2957 | * xctrl[15:0] receive terminal count for fixed length packets | ||
2958 | * value is count minus one (0 = 1 byte packet) | ||
2959 | * when terminal count is reached, receiver | ||
2960 | * automatically returns to hunt mode and receive | ||
2961 | * FIFO contents are flushed to DMA buffers with | ||
2962 | * end of frame (EOF) status | ||
2963 | */ | ||
2964 | static int set_xctrl(struct slgt_info *info, int xctrl) | ||
2965 | { | ||
2966 | unsigned long flags; | ||
2967 | |||
2968 | DBGINFO(("%s set_xctrl=%x)\n", info->device_name, xctrl)); | ||
2969 | spin_lock_irqsave(&info->lock, flags); | ||
2970 | info->xctrl = xctrl; | ||
2971 | wr_reg32(info, XCR, xctrl); | ||
2972 | spin_unlock_irqrestore(&info->lock, flags); | ||
2973 | return 0; | ||
2974 | } | ||
2975 | |||
2883 | /* | 2976 | /* |
2884 | * set general purpose IO pin state and direction | 2977 | * set general purpose IO pin state and direction |
2885 | * | 2978 | * |
@@ -2903,7 +2996,7 @@ static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) | |||
2903 | info->device_name, gpio.state, gpio.smask, | 2996 | info->device_name, gpio.state, gpio.smask, |
2904 | gpio.dir, gpio.dmask)); | 2997 | gpio.dir, gpio.dmask)); |
2905 | 2998 | ||
2906 | spin_lock_irqsave(&info->lock,flags); | 2999 | spin_lock_irqsave(&info->port_array[0]->lock, flags); |
2907 | if (gpio.dmask) { | 3000 | if (gpio.dmask) { |
2908 | data = rd_reg32(info, IODR); | 3001 | data = rd_reg32(info, IODR); |
2909 | data |= gpio.dmask & gpio.dir; | 3002 | data |= gpio.dmask & gpio.dir; |
@@ -2916,7 +3009,7 @@ static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) | |||
2916 | data &= ~(gpio.smask & ~gpio.state); | 3009 | data &= ~(gpio.smask & ~gpio.state); |
2917 | wr_reg32(info, IOVR, data); | 3010 | wr_reg32(info, IOVR, data); |
2918 | } | 3011 | } |
2919 | spin_unlock_irqrestore(&info->lock,flags); | 3012 | spin_unlock_irqrestore(&info->port_array[0]->lock, flags); |
2920 | 3013 | ||
2921 | return 0; | 3014 | return 0; |
2922 | } | 3015 | } |
@@ -3017,7 +3110,7 @@ static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) | |||
3017 | return -EINVAL; | 3110 | return -EINVAL; |
3018 | init_cond_wait(&wait, gpio.smask); | 3111 | init_cond_wait(&wait, gpio.smask); |
3019 | 3112 | ||
3020 | spin_lock_irqsave(&info->lock, flags); | 3113 | spin_lock_irqsave(&info->port_array[0]->lock, flags); |
3021 | /* enable interrupts for watched pins */ | 3114 | /* enable interrupts for watched pins */ |
3022 | wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask); | 3115 | wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask); |
3023 | /* get current pin states */ | 3116 | /* get current pin states */ |
@@ -3029,20 +3122,20 @@ static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) | |||
3029 | } else { | 3122 | } else { |
3030 | /* wait for target state */ | 3123 | /* wait for target state */ |
3031 | add_cond_wait(&info->gpio_wait_q, &wait); | 3124 | add_cond_wait(&info->gpio_wait_q, &wait); |
3032 | spin_unlock_irqrestore(&info->lock, flags); | 3125 | spin_unlock_irqrestore(&info->port_array[0]->lock, flags); |
3033 | schedule(); | 3126 | schedule(); |
3034 | if (signal_pending(current)) | 3127 | if (signal_pending(current)) |
3035 | rc = -ERESTARTSYS; | 3128 | rc = -ERESTARTSYS; |
3036 | else | 3129 | else |
3037 | gpio.state = wait.data; | 3130 | gpio.state = wait.data; |
3038 | spin_lock_irqsave(&info->lock, flags); | 3131 | spin_lock_irqsave(&info->port_array[0]->lock, flags); |
3039 | remove_cond_wait(&info->gpio_wait_q, &wait); | 3132 | remove_cond_wait(&info->gpio_wait_q, &wait); |
3040 | } | 3133 | } |
3041 | 3134 | ||
3042 | /* disable all GPIO interrupts if no waiting processes */ | 3135 | /* disable all GPIO interrupts if no waiting processes */ |
3043 | if (info->gpio_wait_q == NULL) | 3136 | if (info->gpio_wait_q == NULL) |
3044 | wr_reg32(info, IOER, 0); | 3137 | wr_reg32(info, IOER, 0); |
3045 | spin_unlock_irqrestore(&info->lock,flags); | 3138 | spin_unlock_irqrestore(&info->port_array[0]->lock, flags); |
3046 | 3139 | ||
3047 | if ((rc == 0) && copy_to_user(user_gpio, &gpio, sizeof(gpio))) | 3140 | if ((rc == 0) && copy_to_user(user_gpio, &gpio, sizeof(gpio))) |
3048 | rc = -EFAULT; | 3141 | rc = -EFAULT; |
@@ -3245,7 +3338,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3245 | } | 3338 | } |
3246 | 3339 | ||
3247 | DBGINFO(("%s block_til_ready wait\n", tty->driver->name)); | 3340 | DBGINFO(("%s block_til_ready wait\n", tty->driver->name)); |
3341 | tty_unlock(); | ||
3248 | schedule(); | 3342 | schedule(); |
3343 | tty_lock(); | ||
3249 | } | 3344 | } |
3250 | 3345 | ||
3251 | set_current_state(TASK_RUNNING); | 3346 | set_current_state(TASK_RUNNING); |
@@ -3573,7 +3668,6 @@ static void device_init(int adapter_num, struct pci_dev *pdev) | |||
3573 | 3668 | ||
3574 | /* copy resource information from first port to others */ | 3669 | /* copy resource information from first port to others */ |
3575 | for (i = 1; i < port_count; ++i) { | 3670 | for (i = 1; i < port_count; ++i) { |
3576 | port_array[i]->lock = port_array[0]->lock; | ||
3577 | port_array[i]->irq_level = port_array[0]->irq_level; | 3671 | port_array[i]->irq_level = port_array[0]->irq_level; |
3578 | port_array[i]->reg_addr = port_array[0]->reg_addr; | 3672 | port_array[i]->reg_addr = port_array[0]->reg_addr; |
3579 | alloc_dma_bufs(port_array[i]); | 3673 | alloc_dma_bufs(port_array[i]); |
@@ -3639,6 +3733,7 @@ static const struct tty_operations ops = { | |||
3639 | .hangup = hangup, | 3733 | .hangup = hangup, |
3640 | .tiocmget = tiocmget, | 3734 | .tiocmget = tiocmget, |
3641 | .tiocmset = tiocmset, | 3735 | .tiocmset = tiocmset, |
3736 | .get_icount = get_icount, | ||
3642 | .proc_fops = &synclink_gt_proc_fops, | 3737 | .proc_fops = &synclink_gt_proc_fops, |
3643 | }; | 3738 | }; |
3644 | 3739 | ||
@@ -3757,7 +3852,9 @@ module_exit(slgt_exit); | |||
3757 | #define CALC_REGADDR() \ | 3852 | #define CALC_REGADDR() \ |
3758 | unsigned long reg_addr = ((unsigned long)info->reg_addr) + addr; \ | 3853 | unsigned long reg_addr = ((unsigned long)info->reg_addr) + addr; \ |
3759 | if (addr >= 0x80) \ | 3854 | if (addr >= 0x80) \ |
3760 | reg_addr += (info->port_num) * 32; | 3855 | reg_addr += (info->port_num) * 32; \ |
3856 | else if (addr >= 0x40) \ | ||
3857 | reg_addr += (info->port_num) * 16; | ||
3761 | 3858 | ||
3762 | static __u8 rd_reg8(struct slgt_info *info, unsigned int addr) | 3859 | static __u8 rd_reg8(struct slgt_info *info, unsigned int addr) |
3763 | { | 3860 | { |
@@ -3949,7 +4046,7 @@ static void tx_start(struct slgt_info *info) | |||
3949 | info->tx_enabled = true; | 4046 | info->tx_enabled = true; |
3950 | } | 4047 | } |
3951 | 4048 | ||
3952 | if (info->tx_count) { | 4049 | if (desc_count(info->tbufs[info->tbuf_start])) { |
3953 | info->drop_rts_on_tx_done = false; | 4050 | info->drop_rts_on_tx_done = false; |
3954 | 4051 | ||
3955 | if (info->params.mode != MGSL_MODE_ASYNC) { | 4052 | if (info->params.mode != MGSL_MODE_ASYNC) { |
@@ -4176,7 +4273,13 @@ static void sync_mode(struct slgt_info *info) | |||
4176 | 4273 | ||
4177 | /* TCR (tx control) | 4274 | /* TCR (tx control) |
4178 | * | 4275 | * |
4179 | * 15..13 mode, 000=HDLC 001=raw 010=async 011=monosync 100=bisync | 4276 | * 15..13 mode |
4277 | * 000=HDLC/SDLC | ||
4278 | * 001=raw bit synchronous | ||
4279 | * 010=asynchronous/isochronous | ||
4280 | * 011=monosync byte synchronous | ||
4281 | * 100=bisync byte synchronous | ||
4282 | * 101=xsync byte synchronous | ||
4180 | * 12..10 encoding | 4283 | * 12..10 encoding |
4181 | * 09 CRC enable | 4284 | * 09 CRC enable |
4182 | * 08 CRC32 | 4285 | * 08 CRC32 |
@@ -4191,6 +4294,9 @@ static void sync_mode(struct slgt_info *info) | |||
4191 | val = BIT2; | 4294 | val = BIT2; |
4192 | 4295 | ||
4193 | switch(info->params.mode) { | 4296 | switch(info->params.mode) { |
4297 | case MGSL_MODE_XSYNC: | ||
4298 | val |= BIT15 + BIT13; | ||
4299 | break; | ||
4194 | case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; | 4300 | case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; |
4195 | case MGSL_MODE_BISYNC: val |= BIT15; break; | 4301 | case MGSL_MODE_BISYNC: val |= BIT15; break; |
4196 | case MGSL_MODE_RAW: val |= BIT13; break; | 4302 | case MGSL_MODE_RAW: val |= BIT13; break; |
@@ -4245,7 +4351,13 @@ static void sync_mode(struct slgt_info *info) | |||
4245 | 4351 | ||
4246 | /* RCR (rx control) | 4352 | /* RCR (rx control) |
4247 | * | 4353 | * |
4248 | * 15..13 mode, 000=HDLC 001=raw 010=async 011=monosync 100=bisync | 4354 | * 15..13 mode |
4355 | * 000=HDLC/SDLC | ||
4356 | * 001=raw bit synchronous | ||
4357 | * 010=asynchronous/isochronous | ||
4358 | * 011=monosync byte synchronous | ||
4359 | * 100=bisync byte synchronous | ||
4360 | * 101=xsync byte synchronous | ||
4249 | * 12..10 encoding | 4361 | * 12..10 encoding |
4250 | * 09 CRC enable | 4362 | * 09 CRC enable |
4251 | * 08 CRC32 | 4363 | * 08 CRC32 |
@@ -4257,6 +4369,9 @@ static void sync_mode(struct slgt_info *info) | |||
4257 | val = 0; | 4369 | val = 0; |
4258 | 4370 | ||
4259 | switch(info->params.mode) { | 4371 | switch(info->params.mode) { |
4372 | case MGSL_MODE_XSYNC: | ||
4373 | val |= BIT15 + BIT13; | ||
4374 | break; | ||
4260 | case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; | 4375 | case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; |
4261 | case MGSL_MODE_BISYNC: val |= BIT15; break; | 4376 | case MGSL_MODE_BISYNC: val |= BIT15; break; |
4262 | case MGSL_MODE_RAW: val |= BIT13; break; | 4377 | case MGSL_MODE_RAW: val |= BIT13; break; |
@@ -4673,6 +4788,7 @@ static bool rx_get_buf(struct slgt_info *info) | |||
4673 | switch(info->params.mode) { | 4788 | switch(info->params.mode) { |
4674 | case MGSL_MODE_MONOSYNC: | 4789 | case MGSL_MODE_MONOSYNC: |
4675 | case MGSL_MODE_BISYNC: | 4790 | case MGSL_MODE_BISYNC: |
4791 | case MGSL_MODE_XSYNC: | ||
4676 | /* ignore residue in byte synchronous modes */ | 4792 | /* ignore residue in byte synchronous modes */ |
4677 | if (desc_residue(info->rbufs[i])) | 4793 | if (desc_residue(info->rbufs[i])) |
4678 | count--; | 4794 | count--; |
@@ -4772,25 +4888,36 @@ static unsigned int tbuf_bytes(struct slgt_info *info) | |||
4772 | } | 4888 | } |
4773 | 4889 | ||
4774 | /* | 4890 | /* |
4775 | * load transmit DMA buffer(s) with data | 4891 | * load data into transmit DMA buffer ring and start transmitter if needed |
4892 | * return true if data accepted, otherwise false (buffers full) | ||
4776 | */ | 4893 | */ |
4777 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) | 4894 | static bool tx_load(struct slgt_info *info, const char *buf, unsigned int size) |
4778 | { | 4895 | { |
4779 | unsigned short count; | 4896 | unsigned short count; |
4780 | unsigned int i; | 4897 | unsigned int i; |
4781 | struct slgt_desc *d; | 4898 | struct slgt_desc *d; |
4782 | 4899 | ||
4783 | if (size == 0) | 4900 | /* check required buffer space */ |
4784 | return; | 4901 | if (DIV_ROUND_UP(size, DMABUFSIZE) > free_tbuf_count(info)) |
4902 | return false; | ||
4785 | 4903 | ||
4786 | DBGDATA(info, buf, size, "tx"); | 4904 | DBGDATA(info, buf, size, "tx"); |
4787 | 4905 | ||
4906 | /* | ||
4907 | * copy data to one or more DMA buffers in circular ring | ||
4908 | * tbuf_start = first buffer for this data | ||
4909 | * tbuf_current = next free buffer | ||
4910 | * | ||
4911 | * Copy all data before making data visible to DMA controller by | ||
4912 | * setting descriptor count of the first buffer. | ||
4913 | * This prevents an active DMA controller from reading the first DMA | ||
4914 | * buffers of a frame and stopping before the final buffers are filled. | ||
4915 | */ | ||
4916 | |||
4788 | info->tbuf_start = i = info->tbuf_current; | 4917 | info->tbuf_start = i = info->tbuf_current; |
4789 | 4918 | ||
4790 | while (size) { | 4919 | while (size) { |
4791 | d = &info->tbufs[i]; | 4920 | d = &info->tbufs[i]; |
4792 | if (++i == info->tbuf_count) | ||
4793 | i = 0; | ||
4794 | 4921 | ||
4795 | count = (unsigned short)((size > DMABUFSIZE) ? DMABUFSIZE : size); | 4922 | count = (unsigned short)((size > DMABUFSIZE) ? DMABUFSIZE : size); |
4796 | memcpy(d->buf, buf, count); | 4923 | memcpy(d->buf, buf, count); |
@@ -4808,18 +4935,34 @@ static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) | |||
4808 | else | 4935 | else |
4809 | set_desc_eof(*d, 0); | 4936 | set_desc_eof(*d, 0); |
4810 | 4937 | ||
4811 | set_desc_count(*d, count); | 4938 | /* set descriptor count for all but first buffer */ |
4939 | if (i != info->tbuf_start) | ||
4940 | set_desc_count(*d, count); | ||
4812 | d->buf_count = count; | 4941 | d->buf_count = count; |
4942 | |||
4943 | if (++i == info->tbuf_count) | ||
4944 | i = 0; | ||
4813 | } | 4945 | } |
4814 | 4946 | ||
4815 | info->tbuf_current = i; | 4947 | info->tbuf_current = i; |
4948 | |||
4949 | /* set first buffer count to make new data visible to DMA controller */ | ||
4950 | d = &info->tbufs[info->tbuf_start]; | ||
4951 | set_desc_count(*d, d->buf_count); | ||
4952 | |||
4953 | /* start transmitter if needed and update transmit timeout */ | ||
4954 | if (!info->tx_active) | ||
4955 | tx_start(info); | ||
4956 | update_tx_timer(info); | ||
4957 | |||
4958 | return true; | ||
4816 | } | 4959 | } |
4817 | 4960 | ||
4818 | static int register_test(struct slgt_info *info) | 4961 | static int register_test(struct slgt_info *info) |
4819 | { | 4962 | { |
4820 | static unsigned short patterns[] = | 4963 | static unsigned short patterns[] = |
4821 | {0x0000, 0xffff, 0xaaaa, 0x5555, 0x6969, 0x9696}; | 4964 | {0x0000, 0xffff, 0xaaaa, 0x5555, 0x6969, 0x9696}; |
4822 | static unsigned int count = sizeof(patterns)/sizeof(patterns[0]); | 4965 | static unsigned int count = ARRAY_SIZE(patterns); |
4823 | unsigned int i; | 4966 | unsigned int i; |
4824 | int rc = 0; | 4967 | int rc = 0; |
4825 | 4968 | ||
@@ -4934,9 +5077,7 @@ static int loopback_test(struct slgt_info *info) | |||
4934 | spin_lock_irqsave(&info->lock,flags); | 5077 | spin_lock_irqsave(&info->lock,flags); |
4935 | async_mode(info); | 5078 | async_mode(info); |
4936 | rx_start(info); | 5079 | rx_start(info); |
4937 | info->tx_count = count; | ||
4938 | tx_load(info, buf, count); | 5080 | tx_load(info, buf, count); |
4939 | tx_start(info); | ||
4940 | spin_unlock_irqrestore(&info->lock, flags); | 5081 | spin_unlock_irqrestore(&info->lock, flags); |
4941 | 5082 | ||
4942 | /* wait for receive complete */ | 5083 | /* wait for receive complete */ |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 2b18adc4ee19..2f9eb4b0dec1 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
@@ -52,7 +52,6 @@ | |||
52 | #include <linux/mm.h> | 52 | #include <linux/mm.h> |
53 | #include <linux/seq_file.h> | 53 | #include <linux/seq_file.h> |
54 | #include <linux/slab.h> | 54 | #include <linux/slab.h> |
55 | #include <linux/smp_lock.h> | ||
56 | #include <linux/netdevice.h> | 55 | #include <linux/netdevice.h> |
57 | #include <linux/vmalloc.h> | 56 | #include <linux/vmalloc.h> |
58 | #include <linux/init.h> | 57 | #include <linux/init.h> |
@@ -813,13 +812,15 @@ static void close(struct tty_struct *tty, struct file *filp) | |||
813 | 812 | ||
814 | if (tty_port_close_start(&info->port, tty, filp) == 0) | 813 | if (tty_port_close_start(&info->port, tty, filp) == 0) |
815 | goto cleanup; | 814 | goto cleanup; |
816 | 815 | ||
816 | mutex_lock(&info->port.mutex); | ||
817 | if (info->port.flags & ASYNC_INITIALIZED) | 817 | if (info->port.flags & ASYNC_INITIALIZED) |
818 | wait_until_sent(tty, info->timeout); | 818 | wait_until_sent(tty, info->timeout); |
819 | 819 | ||
820 | flush_buffer(tty); | 820 | flush_buffer(tty); |
821 | tty_ldisc_flush(tty); | 821 | tty_ldisc_flush(tty); |
822 | shutdown(info); | 822 | shutdown(info); |
823 | mutex_unlock(&info->port.mutex); | ||
823 | 824 | ||
824 | tty_port_close_end(&info->port, tty); | 825 | tty_port_close_end(&info->port, tty); |
825 | info->port.tty = NULL; | 826 | info->port.tty = NULL; |
@@ -835,6 +836,7 @@ cleanup: | |||
835 | static void hangup(struct tty_struct *tty) | 836 | static void hangup(struct tty_struct *tty) |
836 | { | 837 | { |
837 | SLMP_INFO *info = tty->driver_data; | 838 | SLMP_INFO *info = tty->driver_data; |
839 | unsigned long flags; | ||
838 | 840 | ||
839 | if (debug_level >= DEBUG_LEVEL_INFO) | 841 | if (debug_level >= DEBUG_LEVEL_INFO) |
840 | printk("%s(%d):%s hangup()\n", | 842 | printk("%s(%d):%s hangup()\n", |
@@ -843,12 +845,16 @@ static void hangup(struct tty_struct *tty) | |||
843 | if (sanity_check(info, tty->name, "hangup")) | 845 | if (sanity_check(info, tty->name, "hangup")) |
844 | return; | 846 | return; |
845 | 847 | ||
848 | mutex_lock(&info->port.mutex); | ||
846 | flush_buffer(tty); | 849 | flush_buffer(tty); |
847 | shutdown(info); | 850 | shutdown(info); |
848 | 851 | ||
852 | spin_lock_irqsave(&info->port.lock, flags); | ||
849 | info->port.count = 0; | 853 | info->port.count = 0; |
850 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 854 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; |
851 | info->port.tty = NULL; | 855 | info->port.tty = NULL; |
856 | spin_unlock_irqrestore(&info->port.lock, flags); | ||
857 | mutex_unlock(&info->port.mutex); | ||
852 | 858 | ||
853 | wake_up_interruptible(&info->port.open_wait); | 859 | wake_up_interruptible(&info->port.open_wait); |
854 | } | 860 | } |
@@ -1062,9 +1068,7 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) | |||
1062 | if (sanity_check(info, tty->name, "wait_until_sent")) | 1068 | if (sanity_check(info, tty->name, "wait_until_sent")) |
1063 | return; | 1069 | return; |
1064 | 1070 | ||
1065 | lock_kernel(); | 1071 | if (!test_bit(ASYNCB_INITIALIZED, &info->port.flags)) |
1066 | |||
1067 | if (!(info->port.flags & ASYNC_INITIALIZED)) | ||
1068 | goto exit; | 1072 | goto exit; |
1069 | 1073 | ||
1070 | orig_jiffies = jiffies; | 1074 | orig_jiffies = jiffies; |
@@ -1094,8 +1098,10 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) | |||
1094 | break; | 1098 | break; |
1095 | } | 1099 | } |
1096 | } else { | 1100 | } else { |
1097 | //TODO: determine if there is something similar to USC16C32 | 1101 | /* |
1098 | // TXSTATUS_ALL_SENT status | 1102 | * TODO: determine if there is something similar to USC16C32 |
1103 | * TXSTATUS_ALL_SENT status | ||
1104 | */ | ||
1099 | while ( info->tx_active && info->tx_enabled) { | 1105 | while ( info->tx_active && info->tx_enabled) { |
1100 | msleep_interruptible(jiffies_to_msecs(char_time)); | 1106 | msleep_interruptible(jiffies_to_msecs(char_time)); |
1101 | if (signal_pending(current)) | 1107 | if (signal_pending(current)) |
@@ -1106,7 +1112,6 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) | |||
1106 | } | 1112 | } |
1107 | 1113 | ||
1108 | exit: | 1114 | exit: |
1109 | unlock_kernel(); | ||
1110 | if (debug_level >= DEBUG_LEVEL_INFO) | 1115 | if (debug_level >= DEBUG_LEVEL_INFO) |
1111 | printk("%s(%d):%s wait_until_sent() exit\n", | 1116 | printk("%s(%d):%s wait_until_sent() exit\n", |
1112 | __FILE__,__LINE__, info->device_name ); | 1117 | __FILE__,__LINE__, info->device_name ); |
@@ -1122,7 +1127,6 @@ static int write_room(struct tty_struct *tty) | |||
1122 | if (sanity_check(info, tty->name, "write_room")) | 1127 | if (sanity_check(info, tty->name, "write_room")) |
1123 | return 0; | 1128 | return 0; |
1124 | 1129 | ||
1125 | lock_kernel(); | ||
1126 | if (info->params.mode == MGSL_MODE_HDLC) { | 1130 | if (info->params.mode == MGSL_MODE_HDLC) { |
1127 | ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE; | 1131 | ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE; |
1128 | } else { | 1132 | } else { |
@@ -1130,7 +1134,6 @@ static int write_room(struct tty_struct *tty) | |||
1130 | if (ret < 0) | 1134 | if (ret < 0) |
1131 | ret = 0; | 1135 | ret = 0; |
1132 | } | 1136 | } |
1133 | unlock_kernel(); | ||
1134 | 1137 | ||
1135 | if (debug_level >= DEBUG_LEVEL_INFO) | 1138 | if (debug_level >= DEBUG_LEVEL_INFO) |
1136 | printk("%s(%d):%s write_room()=%d\n", | 1139 | printk("%s(%d):%s write_room()=%d\n", |
@@ -1251,14 +1254,10 @@ static void tx_release(struct tty_struct *tty) | |||
1251 | * | 1254 | * |
1252 | * Return Value: 0 if success, otherwise error code | 1255 | * Return Value: 0 if success, otherwise error code |
1253 | */ | 1256 | */ |
1254 | static int do_ioctl(struct tty_struct *tty, struct file *file, | 1257 | static int ioctl(struct tty_struct *tty, struct file *file, |
1255 | unsigned int cmd, unsigned long arg) | 1258 | unsigned int cmd, unsigned long arg) |
1256 | { | 1259 | { |
1257 | SLMP_INFO *info = tty->driver_data; | 1260 | SLMP_INFO *info = tty->driver_data; |
1258 | int error; | ||
1259 | struct mgsl_icount cnow; /* kernel counter temps */ | ||
1260 | struct serial_icounter_struct __user *p_cuser; /* user space */ | ||
1261 | unsigned long flags; | ||
1262 | void __user *argp = (void __user *)arg; | 1261 | void __user *argp = (void __user *)arg; |
1263 | 1262 | ||
1264 | if (debug_level >= DEBUG_LEVEL_INFO) | 1263 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -1269,7 +1268,7 @@ static int do_ioctl(struct tty_struct *tty, struct file *file, | |||
1269 | return -ENODEV; | 1268 | return -ENODEV; |
1270 | 1269 | ||
1271 | if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && | 1270 | if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && |
1272 | (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { | 1271 | (cmd != TIOCMIWAIT)) { |
1273 | if (tty->flags & (1 << TTY_IO_ERROR)) | 1272 | if (tty->flags & (1 << TTY_IO_ERROR)) |
1274 | return -EIO; | 1273 | return -EIO; |
1275 | } | 1274 | } |
@@ -1307,48 +1306,36 @@ static int do_ioctl(struct tty_struct *tty, struct file *file, | |||
1307 | * NB: both 1->0 and 0->1 transitions are counted except for | 1306 | * NB: both 1->0 and 0->1 transitions are counted except for |
1308 | * RI where only 0->1 is counted. | 1307 | * RI where only 0->1 is counted. |
1309 | */ | 1308 | */ |
1310 | case TIOCGICOUNT: | ||
1311 | spin_lock_irqsave(&info->lock,flags); | ||
1312 | cnow = info->icount; | ||
1313 | spin_unlock_irqrestore(&info->lock,flags); | ||
1314 | p_cuser = argp; | ||
1315 | PUT_USER(error,cnow.cts, &p_cuser->cts); | ||
1316 | if (error) return error; | ||
1317 | PUT_USER(error,cnow.dsr, &p_cuser->dsr); | ||
1318 | if (error) return error; | ||
1319 | PUT_USER(error,cnow.rng, &p_cuser->rng); | ||
1320 | if (error) return error; | ||
1321 | PUT_USER(error,cnow.dcd, &p_cuser->dcd); | ||
1322 | if (error) return error; | ||
1323 | PUT_USER(error,cnow.rx, &p_cuser->rx); | ||
1324 | if (error) return error; | ||
1325 | PUT_USER(error,cnow.tx, &p_cuser->tx); | ||
1326 | if (error) return error; | ||
1327 | PUT_USER(error,cnow.frame, &p_cuser->frame); | ||
1328 | if (error) return error; | ||
1329 | PUT_USER(error,cnow.overrun, &p_cuser->overrun); | ||
1330 | if (error) return error; | ||
1331 | PUT_USER(error,cnow.parity, &p_cuser->parity); | ||
1332 | if (error) return error; | ||
1333 | PUT_USER(error,cnow.brk, &p_cuser->brk); | ||
1334 | if (error) return error; | ||
1335 | PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun); | ||
1336 | if (error) return error; | ||
1337 | return 0; | ||
1338 | default: | 1309 | default: |
1339 | return -ENOIOCTLCMD; | 1310 | return -ENOIOCTLCMD; |
1340 | } | 1311 | } |
1341 | return 0; | 1312 | return 0; |
1342 | } | 1313 | } |
1343 | 1314 | ||
1344 | static int ioctl(struct tty_struct *tty, struct file *file, | 1315 | static int get_icount(struct tty_struct *tty, |
1345 | unsigned int cmd, unsigned long arg) | 1316 | struct serial_icounter_struct *icount) |
1346 | { | 1317 | { |
1347 | int ret; | 1318 | SLMP_INFO *info = tty->driver_data; |
1348 | lock_kernel(); | 1319 | struct mgsl_icount cnow; /* kernel counter temps */ |
1349 | ret = do_ioctl(tty, file, cmd, arg); | 1320 | unsigned long flags; |
1350 | unlock_kernel(); | 1321 | |
1351 | return ret; | 1322 | spin_lock_irqsave(&info->lock,flags); |
1323 | cnow = info->icount; | ||
1324 | spin_unlock_irqrestore(&info->lock,flags); | ||
1325 | |||
1326 | icount->cts = cnow.cts; | ||
1327 | icount->dsr = cnow.dsr; | ||
1328 | icount->rng = cnow.rng; | ||
1329 | icount->dcd = cnow.dcd; | ||
1330 | icount->rx = cnow.rx; | ||
1331 | icount->tx = cnow.tx; | ||
1332 | icount->frame = cnow.frame; | ||
1333 | icount->overrun = cnow.overrun; | ||
1334 | icount->parity = cnow.parity; | ||
1335 | icount->brk = cnow.brk; | ||
1336 | icount->buf_overrun = cnow.buf_overrun; | ||
1337 | |||
1338 | return 0; | ||
1352 | } | 1339 | } |
1353 | 1340 | ||
1354 | /* | 1341 | /* |
@@ -2883,7 +2870,9 @@ static int get_stats(SLMP_INFO * info, struct mgsl_icount __user *user_icount) | |||
2883 | if (!user_icount) { | 2870 | if (!user_icount) { |
2884 | memset(&info->icount, 0, sizeof(info->icount)); | 2871 | memset(&info->icount, 0, sizeof(info->icount)); |
2885 | } else { | 2872 | } else { |
2873 | mutex_lock(&info->port.mutex); | ||
2886 | COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount)); | 2874 | COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount)); |
2875 | mutex_unlock(&info->port.mutex); | ||
2887 | if (err) | 2876 | if (err) |
2888 | return -EFAULT; | 2877 | return -EFAULT; |
2889 | } | 2878 | } |
@@ -2898,7 +2887,9 @@ static int get_params(SLMP_INFO * info, MGSL_PARAMS __user *user_params) | |||
2898 | printk("%s(%d):%s get_params()\n", | 2887 | printk("%s(%d):%s get_params()\n", |
2899 | __FILE__,__LINE__, info->device_name); | 2888 | __FILE__,__LINE__, info->device_name); |
2900 | 2889 | ||
2890 | mutex_lock(&info->port.mutex); | ||
2901 | COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS)); | 2891 | COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS)); |
2892 | mutex_unlock(&info->port.mutex); | ||
2902 | if (err) { | 2893 | if (err) { |
2903 | if ( debug_level >= DEBUG_LEVEL_INFO ) | 2894 | if ( debug_level >= DEBUG_LEVEL_INFO ) |
2904 | printk( "%s(%d):%s get_params() user buffer copy failed\n", | 2895 | printk( "%s(%d):%s get_params() user buffer copy failed\n", |
@@ -2926,11 +2917,13 @@ static int set_params(SLMP_INFO * info, MGSL_PARAMS __user *new_params) | |||
2926 | return -EFAULT; | 2917 | return -EFAULT; |
2927 | } | 2918 | } |
2928 | 2919 | ||
2920 | mutex_lock(&info->port.mutex); | ||
2929 | spin_lock_irqsave(&info->lock,flags); | 2921 | spin_lock_irqsave(&info->lock,flags); |
2930 | memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); | 2922 | memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); |
2931 | spin_unlock_irqrestore(&info->lock,flags); | 2923 | spin_unlock_irqrestore(&info->lock,flags); |
2932 | 2924 | ||
2933 | change_params(info); | 2925 | change_params(info); |
2926 | mutex_unlock(&info->port.mutex); | ||
2934 | 2927 | ||
2935 | return 0; | 2928 | return 0; |
2936 | } | 2929 | } |
@@ -3366,7 +3359,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3366 | printk("%s(%d):%s block_til_ready() count=%d\n", | 3359 | printk("%s(%d):%s block_til_ready() count=%d\n", |
3367 | __FILE__,__LINE__, tty->driver->name, port->count ); | 3360 | __FILE__,__LINE__, tty->driver->name, port->count ); |
3368 | 3361 | ||
3362 | tty_unlock(); | ||
3369 | schedule(); | 3363 | schedule(); |
3364 | tty_lock(); | ||
3370 | } | 3365 | } |
3371 | 3366 | ||
3372 | set_current_state(TASK_RUNNING); | 3367 | set_current_state(TASK_RUNNING); |
@@ -3908,6 +3903,7 @@ static const struct tty_operations ops = { | |||
3908 | .hangup = hangup, | 3903 | .hangup = hangup, |
3909 | .tiocmget = tiocmget, | 3904 | .tiocmget = tiocmget, |
3910 | .tiocmset = tiocmset, | 3905 | .tiocmset = tiocmset, |
3906 | .get_icount = get_icount, | ||
3911 | .proc_fops = &synclinkmp_proc_fops, | 3907 | .proc_fops = &synclinkmp_proc_fops, |
3912 | }; | 3908 | }; |
3913 | 3909 | ||
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 1ae2de7d8b4f..eaa5d3efa79d 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c | |||
@@ -1,7 +1,4 @@ | |||
1 | /* -*- linux-c -*- | 1 | /* |
2 | * | ||
3 | * $Id: sysrq.c,v 1.15 1998/08/23 14:56:41 mj Exp $ | ||
4 | * | ||
5 | * Linux Magic System Request Key Hacks | 2 | * Linux Magic System Request Key Hacks |
6 | * | 3 | * |
7 | * (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz> | 4 | * (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz> |
@@ -10,13 +7,17 @@ | |||
10 | * (c) 2000 Crutcher Dunnavant <crutcher+kernel@datastacks.com> | 7 | * (c) 2000 Crutcher Dunnavant <crutcher+kernel@datastacks.com> |
11 | * overhauled to use key registration | 8 | * overhauled to use key registration |
12 | * based upon discusions in irc://irc.openprojects.net/#kernelnewbies | 9 | * based upon discusions in irc://irc.openprojects.net/#kernelnewbies |
10 | * | ||
11 | * Copyright (c) 2010 Dmitry Torokhov | ||
12 | * Input handler conversion | ||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
16 | |||
15 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
16 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
17 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
18 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
19 | #include <linux/tty.h> | ||
20 | #include <linux/mount.h> | 21 | #include <linux/mount.h> |
21 | #include <linux/kdev_t.h> | 22 | #include <linux/kdev_t.h> |
22 | #include <linux/major.h> | 23 | #include <linux/major.h> |
@@ -38,33 +39,35 @@ | |||
38 | #include <linux/workqueue.h> | 39 | #include <linux/workqueue.h> |
39 | #include <linux/hrtimer.h> | 40 | #include <linux/hrtimer.h> |
40 | #include <linux/oom.h> | 41 | #include <linux/oom.h> |
42 | #include <linux/slab.h> | ||
43 | #include <linux/input.h> | ||
41 | 44 | ||
42 | #include <asm/ptrace.h> | 45 | #include <asm/ptrace.h> |
43 | #include <asm/irq_regs.h> | 46 | #include <asm/irq_regs.h> |
44 | 47 | ||
45 | /* Whether we react on sysrq keys or just ignore them */ | 48 | /* Whether we react on sysrq keys or just ignore them */ |
46 | int __read_mostly __sysrq_enabled = 1; | 49 | static int __read_mostly sysrq_enabled = 1; |
47 | 50 | static bool __read_mostly sysrq_always_enabled; | |
48 | static int __read_mostly sysrq_always_enabled; | ||
49 | 51 | ||
50 | int sysrq_on(void) | 52 | static bool sysrq_on(void) |
51 | { | 53 | { |
52 | return __sysrq_enabled || sysrq_always_enabled; | 54 | return sysrq_enabled || sysrq_always_enabled; |
53 | } | 55 | } |
54 | 56 | ||
55 | /* | 57 | /* |
56 | * A value of 1 means 'all', other nonzero values are an op mask: | 58 | * A value of 1 means 'all', other nonzero values are an op mask: |
57 | */ | 59 | */ |
58 | static inline int sysrq_on_mask(int mask) | 60 | static bool sysrq_on_mask(int mask) |
59 | { | 61 | { |
60 | return sysrq_always_enabled || __sysrq_enabled == 1 || | 62 | return sysrq_always_enabled || |
61 | (__sysrq_enabled & mask); | 63 | sysrq_enabled == 1 || |
64 | (sysrq_enabled & mask); | ||
62 | } | 65 | } |
63 | 66 | ||
64 | static int __init sysrq_always_enabled_setup(char *str) | 67 | static int __init sysrq_always_enabled_setup(char *str) |
65 | { | 68 | { |
66 | sysrq_always_enabled = 1; | 69 | sysrq_always_enabled = true; |
67 | printk(KERN_INFO "debug: sysrq always enabled.\n"); | 70 | pr_info("sysrq always enabled.\n"); |
68 | 71 | ||
69 | return 1; | 72 | return 1; |
70 | } | 73 | } |
@@ -72,9 +75,10 @@ static int __init sysrq_always_enabled_setup(char *str) | |||
72 | __setup("sysrq_always_enabled", sysrq_always_enabled_setup); | 75 | __setup("sysrq_always_enabled", sysrq_always_enabled_setup); |
73 | 76 | ||
74 | 77 | ||
75 | static void sysrq_handle_loglevel(int key, struct tty_struct *tty) | 78 | static void sysrq_handle_loglevel(int key) |
76 | { | 79 | { |
77 | int i; | 80 | int i; |
81 | |||
78 | i = key - '0'; | 82 | i = key - '0'; |
79 | console_loglevel = 7; | 83 | console_loglevel = 7; |
80 | printk("Loglevel set to %d\n", i); | 84 | printk("Loglevel set to %d\n", i); |
@@ -88,7 +92,7 @@ static struct sysrq_key_op sysrq_loglevel_op = { | |||
88 | }; | 92 | }; |
89 | 93 | ||
90 | #ifdef CONFIG_VT | 94 | #ifdef CONFIG_VT |
91 | static void sysrq_handle_SAK(int key, struct tty_struct *tty) | 95 | static void sysrq_handle_SAK(int key) |
92 | { | 96 | { |
93 | struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work; | 97 | struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work; |
94 | schedule_work(SAK_work); | 98 | schedule_work(SAK_work); |
@@ -100,11 +104,11 @@ static struct sysrq_key_op sysrq_SAK_op = { | |||
100 | .enable_mask = SYSRQ_ENABLE_KEYBOARD, | 104 | .enable_mask = SYSRQ_ENABLE_KEYBOARD, |
101 | }; | 105 | }; |
102 | #else | 106 | #else |
103 | #define sysrq_SAK_op (*(struct sysrq_key_op *)0) | 107 | #define sysrq_SAK_op (*(struct sysrq_key_op *)NULL) |
104 | #endif | 108 | #endif |
105 | 109 | ||
106 | #ifdef CONFIG_VT | 110 | #ifdef CONFIG_VT |
107 | static void sysrq_handle_unraw(int key, struct tty_struct *tty) | 111 | static void sysrq_handle_unraw(int key) |
108 | { | 112 | { |
109 | struct kbd_struct *kbd = &kbd_table[fg_console]; | 113 | struct kbd_struct *kbd = &kbd_table[fg_console]; |
110 | 114 | ||
@@ -118,10 +122,10 @@ static struct sysrq_key_op sysrq_unraw_op = { | |||
118 | .enable_mask = SYSRQ_ENABLE_KEYBOARD, | 122 | .enable_mask = SYSRQ_ENABLE_KEYBOARD, |
119 | }; | 123 | }; |
120 | #else | 124 | #else |
121 | #define sysrq_unraw_op (*(struct sysrq_key_op *)0) | 125 | #define sysrq_unraw_op (*(struct sysrq_key_op *)NULL) |
122 | #endif /* CONFIG_VT */ | 126 | #endif /* CONFIG_VT */ |
123 | 127 | ||
124 | static void sysrq_handle_crash(int key, struct tty_struct *tty) | 128 | static void sysrq_handle_crash(int key) |
125 | { | 129 | { |
126 | char *killer = NULL; | 130 | char *killer = NULL; |
127 | 131 | ||
@@ -136,7 +140,7 @@ static struct sysrq_key_op sysrq_crash_op = { | |||
136 | .enable_mask = SYSRQ_ENABLE_DUMP, | 140 | .enable_mask = SYSRQ_ENABLE_DUMP, |
137 | }; | 141 | }; |
138 | 142 | ||
139 | static void sysrq_handle_reboot(int key, struct tty_struct *tty) | 143 | static void sysrq_handle_reboot(int key) |
140 | { | 144 | { |
141 | lockdep_off(); | 145 | lockdep_off(); |
142 | local_irq_enable(); | 146 | local_irq_enable(); |
@@ -149,7 +153,7 @@ static struct sysrq_key_op sysrq_reboot_op = { | |||
149 | .enable_mask = SYSRQ_ENABLE_BOOT, | 153 | .enable_mask = SYSRQ_ENABLE_BOOT, |
150 | }; | 154 | }; |
151 | 155 | ||
152 | static void sysrq_handle_sync(int key, struct tty_struct *tty) | 156 | static void sysrq_handle_sync(int key) |
153 | { | 157 | { |
154 | emergency_sync(); | 158 | emergency_sync(); |
155 | } | 159 | } |
@@ -160,7 +164,7 @@ static struct sysrq_key_op sysrq_sync_op = { | |||
160 | .enable_mask = SYSRQ_ENABLE_SYNC, | 164 | .enable_mask = SYSRQ_ENABLE_SYNC, |
161 | }; | 165 | }; |
162 | 166 | ||
163 | static void sysrq_handle_show_timers(int key, struct tty_struct *tty) | 167 | static void sysrq_handle_show_timers(int key) |
164 | { | 168 | { |
165 | sysrq_timer_list_show(); | 169 | sysrq_timer_list_show(); |
166 | } | 170 | } |
@@ -171,7 +175,7 @@ static struct sysrq_key_op sysrq_show_timers_op = { | |||
171 | .action_msg = "Show clockevent devices & pending hrtimers (no others)", | 175 | .action_msg = "Show clockevent devices & pending hrtimers (no others)", |
172 | }; | 176 | }; |
173 | 177 | ||
174 | static void sysrq_handle_mountro(int key, struct tty_struct *tty) | 178 | static void sysrq_handle_mountro(int key) |
175 | { | 179 | { |
176 | emergency_remount(); | 180 | emergency_remount(); |
177 | } | 181 | } |
@@ -183,7 +187,7 @@ static struct sysrq_key_op sysrq_mountro_op = { | |||
183 | }; | 187 | }; |
184 | 188 | ||
185 | #ifdef CONFIG_LOCKDEP | 189 | #ifdef CONFIG_LOCKDEP |
186 | static void sysrq_handle_showlocks(int key, struct tty_struct *tty) | 190 | static void sysrq_handle_showlocks(int key) |
187 | { | 191 | { |
188 | debug_show_all_locks(); | 192 | debug_show_all_locks(); |
189 | } | 193 | } |
@@ -194,7 +198,7 @@ static struct sysrq_key_op sysrq_showlocks_op = { | |||
194 | .action_msg = "Show Locks Held", | 198 | .action_msg = "Show Locks Held", |
195 | }; | 199 | }; |
196 | #else | 200 | #else |
197 | #define sysrq_showlocks_op (*(struct sysrq_key_op *)0) | 201 | #define sysrq_showlocks_op (*(struct sysrq_key_op *)NULL) |
198 | #endif | 202 | #endif |
199 | 203 | ||
200 | #ifdef CONFIG_SMP | 204 | #ifdef CONFIG_SMP |
@@ -221,7 +225,7 @@ static void sysrq_showregs_othercpus(struct work_struct *dummy) | |||
221 | 225 | ||
222 | static DECLARE_WORK(sysrq_showallcpus, sysrq_showregs_othercpus); | 226 | static DECLARE_WORK(sysrq_showallcpus, sysrq_showregs_othercpus); |
223 | 227 | ||
224 | static void sysrq_handle_showallcpus(int key, struct tty_struct *tty) | 228 | static void sysrq_handle_showallcpus(int key) |
225 | { | 229 | { |
226 | /* | 230 | /* |
227 | * Fall back to the workqueue based printing if the | 231 | * Fall back to the workqueue based printing if the |
@@ -247,7 +251,7 @@ static struct sysrq_key_op sysrq_showallcpus_op = { | |||
247 | }; | 251 | }; |
248 | #endif | 252 | #endif |
249 | 253 | ||
250 | static void sysrq_handle_showregs(int key, struct tty_struct *tty) | 254 | static void sysrq_handle_showregs(int key) |
251 | { | 255 | { |
252 | struct pt_regs *regs = get_irq_regs(); | 256 | struct pt_regs *regs = get_irq_regs(); |
253 | if (regs) | 257 | if (regs) |
@@ -261,7 +265,7 @@ static struct sysrq_key_op sysrq_showregs_op = { | |||
261 | .enable_mask = SYSRQ_ENABLE_DUMP, | 265 | .enable_mask = SYSRQ_ENABLE_DUMP, |
262 | }; | 266 | }; |
263 | 267 | ||
264 | static void sysrq_handle_showstate(int key, struct tty_struct *tty) | 268 | static void sysrq_handle_showstate(int key) |
265 | { | 269 | { |
266 | show_state(); | 270 | show_state(); |
267 | } | 271 | } |
@@ -272,7 +276,7 @@ static struct sysrq_key_op sysrq_showstate_op = { | |||
272 | .enable_mask = SYSRQ_ENABLE_DUMP, | 276 | .enable_mask = SYSRQ_ENABLE_DUMP, |
273 | }; | 277 | }; |
274 | 278 | ||
275 | static void sysrq_handle_showstate_blocked(int key, struct tty_struct *tty) | 279 | static void sysrq_handle_showstate_blocked(int key) |
276 | { | 280 | { |
277 | show_state_filter(TASK_UNINTERRUPTIBLE); | 281 | show_state_filter(TASK_UNINTERRUPTIBLE); |
278 | } | 282 | } |
@@ -286,9 +290,9 @@ static struct sysrq_key_op sysrq_showstate_blocked_op = { | |||
286 | #ifdef CONFIG_TRACING | 290 | #ifdef CONFIG_TRACING |
287 | #include <linux/ftrace.h> | 291 | #include <linux/ftrace.h> |
288 | 292 | ||
289 | static void sysrq_ftrace_dump(int key, struct tty_struct *tty) | 293 | static void sysrq_ftrace_dump(int key) |
290 | { | 294 | { |
291 | ftrace_dump(); | 295 | ftrace_dump(DUMP_ALL); |
292 | } | 296 | } |
293 | static struct sysrq_key_op sysrq_ftrace_dump_op = { | 297 | static struct sysrq_key_op sysrq_ftrace_dump_op = { |
294 | .handler = sysrq_ftrace_dump, | 298 | .handler = sysrq_ftrace_dump, |
@@ -297,10 +301,10 @@ static struct sysrq_key_op sysrq_ftrace_dump_op = { | |||
297 | .enable_mask = SYSRQ_ENABLE_DUMP, | 301 | .enable_mask = SYSRQ_ENABLE_DUMP, |
298 | }; | 302 | }; |
299 | #else | 303 | #else |
300 | #define sysrq_ftrace_dump_op (*(struct sysrq_key_op *)0) | 304 | #define sysrq_ftrace_dump_op (*(struct sysrq_key_op *)NULL) |
301 | #endif | 305 | #endif |
302 | 306 | ||
303 | static void sysrq_handle_showmem(int key, struct tty_struct *tty) | 307 | static void sysrq_handle_showmem(int key) |
304 | { | 308 | { |
305 | show_mem(); | 309 | show_mem(); |
306 | } | 310 | } |
@@ -325,7 +329,7 @@ static void send_sig_all(int sig) | |||
325 | } | 329 | } |
326 | } | 330 | } |
327 | 331 | ||
328 | static void sysrq_handle_term(int key, struct tty_struct *tty) | 332 | static void sysrq_handle_term(int key) |
329 | { | 333 | { |
330 | send_sig_all(SIGTERM); | 334 | send_sig_all(SIGTERM); |
331 | console_loglevel = 8; | 335 | console_loglevel = 8; |
@@ -344,7 +348,7 @@ static void moom_callback(struct work_struct *ignored) | |||
344 | 348 | ||
345 | static DECLARE_WORK(moom_work, moom_callback); | 349 | static DECLARE_WORK(moom_work, moom_callback); |
346 | 350 | ||
347 | static void sysrq_handle_moom(int key, struct tty_struct *tty) | 351 | static void sysrq_handle_moom(int key) |
348 | { | 352 | { |
349 | schedule_work(&moom_work); | 353 | schedule_work(&moom_work); |
350 | } | 354 | } |
@@ -356,7 +360,7 @@ static struct sysrq_key_op sysrq_moom_op = { | |||
356 | }; | 360 | }; |
357 | 361 | ||
358 | #ifdef CONFIG_BLOCK | 362 | #ifdef CONFIG_BLOCK |
359 | static void sysrq_handle_thaw(int key, struct tty_struct *tty) | 363 | static void sysrq_handle_thaw(int key) |
360 | { | 364 | { |
361 | emergency_thaw_all(); | 365 | emergency_thaw_all(); |
362 | } | 366 | } |
@@ -368,7 +372,7 @@ static struct sysrq_key_op sysrq_thaw_op = { | |||
368 | }; | 372 | }; |
369 | #endif | 373 | #endif |
370 | 374 | ||
371 | static void sysrq_handle_kill(int key, struct tty_struct *tty) | 375 | static void sysrq_handle_kill(int key) |
372 | { | 376 | { |
373 | send_sig_all(SIGKILL); | 377 | send_sig_all(SIGKILL); |
374 | console_loglevel = 8; | 378 | console_loglevel = 8; |
@@ -380,7 +384,7 @@ static struct sysrq_key_op sysrq_kill_op = { | |||
380 | .enable_mask = SYSRQ_ENABLE_SIGNAL, | 384 | .enable_mask = SYSRQ_ENABLE_SIGNAL, |
381 | }; | 385 | }; |
382 | 386 | ||
383 | static void sysrq_handle_unrt(int key, struct tty_struct *tty) | 387 | static void sysrq_handle_unrt(int key) |
384 | { | 388 | { |
385 | normalize_rt_tasks(); | 389 | normalize_rt_tasks(); |
386 | } | 390 | } |
@@ -476,6 +480,7 @@ struct sysrq_key_op *__sysrq_get_key_op(int key) | |||
476 | i = sysrq_key_table_key2index(key); | 480 | i = sysrq_key_table_key2index(key); |
477 | if (i != -1) | 481 | if (i != -1) |
478 | op_p = sysrq_key_table[i]; | 482 | op_p = sysrq_key_table[i]; |
483 | |||
479 | return op_p; | 484 | return op_p; |
480 | } | 485 | } |
481 | 486 | ||
@@ -487,11 +492,7 @@ static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p) | |||
487 | sysrq_key_table[i] = op_p; | 492 | sysrq_key_table[i] = op_p; |
488 | } | 493 | } |
489 | 494 | ||
490 | /* | 495 | void __handle_sysrq(int key, bool check_mask) |
491 | * This is the non-locking version of handle_sysrq. It must/can only be called | ||
492 | * by sysrq key handlers, as they are inside of the lock | ||
493 | */ | ||
494 | void __handle_sysrq(int key, struct tty_struct *tty, int check_mask) | ||
495 | { | 496 | { |
496 | struct sysrq_key_op *op_p; | 497 | struct sysrq_key_op *op_p; |
497 | int orig_log_level; | 498 | int orig_log_level; |
@@ -518,7 +519,7 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask) | |||
518 | if (!check_mask || sysrq_on_mask(op_p->enable_mask)) { | 519 | if (!check_mask || sysrq_on_mask(op_p->enable_mask)) { |
519 | printk("%s\n", op_p->action_msg); | 520 | printk("%s\n", op_p->action_msg); |
520 | console_loglevel = orig_log_level; | 521 | console_loglevel = orig_log_level; |
521 | op_p->handler(key, tty); | 522 | op_p->handler(key); |
522 | } else { | 523 | } else { |
523 | printk("This sysrq operation is disabled.\n"); | 524 | printk("This sysrq operation is disabled.\n"); |
524 | } | 525 | } |
@@ -543,21 +544,197 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask) | |||
543 | spin_unlock_irqrestore(&sysrq_key_table_lock, flags); | 544 | spin_unlock_irqrestore(&sysrq_key_table_lock, flags); |
544 | } | 545 | } |
545 | 546 | ||
546 | /* | 547 | void handle_sysrq(int key) |
547 | * This function is called by the keyboard handler when SysRq is pressed | ||
548 | * and any other keycode arrives. | ||
549 | */ | ||
550 | void handle_sysrq(int key, struct tty_struct *tty) | ||
551 | { | 548 | { |
552 | if (sysrq_on()) | 549 | if (sysrq_on()) |
553 | __handle_sysrq(key, tty, 1); | 550 | __handle_sysrq(key, true); |
554 | } | 551 | } |
555 | EXPORT_SYMBOL(handle_sysrq); | 552 | EXPORT_SYMBOL(handle_sysrq); |
556 | 553 | ||
554 | #ifdef CONFIG_INPUT | ||
555 | |||
556 | /* Simple translation table for the SysRq keys */ | ||
557 | static const unsigned char sysrq_xlate[KEY_MAX + 1] = | ||
558 | "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ | ||
559 | "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ | ||
560 | "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ | ||
561 | "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ | ||
562 | "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ | ||
563 | "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ | ||
564 | "\r\000/"; /* 0x60 - 0x6f */ | ||
565 | |||
566 | static bool sysrq_down; | ||
567 | static int sysrq_alt_use; | ||
568 | static int sysrq_alt; | ||
569 | static DEFINE_SPINLOCK(sysrq_event_lock); | ||
570 | |||
571 | static bool sysrq_filter(struct input_handle *handle, unsigned int type, | ||
572 | unsigned int code, int value) | ||
573 | { | ||
574 | bool suppress; | ||
575 | |||
576 | /* We are called with interrupts disabled, just take the lock */ | ||
577 | spin_lock(&sysrq_event_lock); | ||
578 | |||
579 | if (type != EV_KEY) | ||
580 | goto out; | ||
581 | |||
582 | switch (code) { | ||
583 | |||
584 | case KEY_LEFTALT: | ||
585 | case KEY_RIGHTALT: | ||
586 | if (value) | ||
587 | sysrq_alt = code; | ||
588 | else { | ||
589 | if (sysrq_down && code == sysrq_alt_use) | ||
590 | sysrq_down = false; | ||
591 | |||
592 | sysrq_alt = 0; | ||
593 | } | ||
594 | break; | ||
595 | |||
596 | case KEY_SYSRQ: | ||
597 | if (value == 1 && sysrq_alt) { | ||
598 | sysrq_down = true; | ||
599 | sysrq_alt_use = sysrq_alt; | ||
600 | } | ||
601 | break; | ||
602 | |||
603 | default: | ||
604 | if (sysrq_down && value && value != 2) | ||
605 | __handle_sysrq(sysrq_xlate[code], true); | ||
606 | break; | ||
607 | } | ||
608 | |||
609 | out: | ||
610 | suppress = sysrq_down; | ||
611 | spin_unlock(&sysrq_event_lock); | ||
612 | |||
613 | return suppress; | ||
614 | } | ||
615 | |||
616 | static int sysrq_connect(struct input_handler *handler, | ||
617 | struct input_dev *dev, | ||
618 | const struct input_device_id *id) | ||
619 | { | ||
620 | struct input_handle *handle; | ||
621 | int error; | ||
622 | |||
623 | sysrq_down = false; | ||
624 | sysrq_alt = 0; | ||
625 | |||
626 | handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); | ||
627 | if (!handle) | ||
628 | return -ENOMEM; | ||
629 | |||
630 | handle->dev = dev; | ||
631 | handle->handler = handler; | ||
632 | handle->name = "sysrq"; | ||
633 | |||
634 | error = input_register_handle(handle); | ||
635 | if (error) { | ||
636 | pr_err("Failed to register input sysrq handler, error %d\n", | ||
637 | error); | ||
638 | goto err_free; | ||
639 | } | ||
640 | |||
641 | error = input_open_device(handle); | ||
642 | if (error) { | ||
643 | pr_err("Failed to open input device, error %d\n", error); | ||
644 | goto err_unregister; | ||
645 | } | ||
646 | |||
647 | return 0; | ||
648 | |||
649 | err_unregister: | ||
650 | input_unregister_handle(handle); | ||
651 | err_free: | ||
652 | kfree(handle); | ||
653 | return error; | ||
654 | } | ||
655 | |||
656 | static void sysrq_disconnect(struct input_handle *handle) | ||
657 | { | ||
658 | input_close_device(handle); | ||
659 | input_unregister_handle(handle); | ||
660 | kfree(handle); | ||
661 | } | ||
662 | |||
663 | /* | ||
664 | * We are matching on KEY_LEFTALT instead of KEY_SYSRQ because not all | ||
665 | * keyboards have SysRq key predefined and so user may add it to keymap | ||
666 | * later, but we expect all such keyboards to have left alt. | ||
667 | */ | ||
668 | static const struct input_device_id sysrq_ids[] = { | ||
669 | { | ||
670 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | | ||
671 | INPUT_DEVICE_ID_MATCH_KEYBIT, | ||
672 | .evbit = { BIT_MASK(EV_KEY) }, | ||
673 | .keybit = { BIT_MASK(KEY_LEFTALT) }, | ||
674 | }, | ||
675 | { }, | ||
676 | }; | ||
677 | |||
678 | static struct input_handler sysrq_handler = { | ||
679 | .filter = sysrq_filter, | ||
680 | .connect = sysrq_connect, | ||
681 | .disconnect = sysrq_disconnect, | ||
682 | .name = "sysrq", | ||
683 | .id_table = sysrq_ids, | ||
684 | }; | ||
685 | |||
686 | static bool sysrq_handler_registered; | ||
687 | |||
688 | static inline void sysrq_register_handler(void) | ||
689 | { | ||
690 | int error; | ||
691 | |||
692 | error = input_register_handler(&sysrq_handler); | ||
693 | if (error) | ||
694 | pr_err("Failed to register input handler, error %d", error); | ||
695 | else | ||
696 | sysrq_handler_registered = true; | ||
697 | } | ||
698 | |||
699 | static inline void sysrq_unregister_handler(void) | ||
700 | { | ||
701 | if (sysrq_handler_registered) { | ||
702 | input_unregister_handler(&sysrq_handler); | ||
703 | sysrq_handler_registered = false; | ||
704 | } | ||
705 | } | ||
706 | |||
707 | #else | ||
708 | |||
709 | static inline void sysrq_register_handler(void) | ||
710 | { | ||
711 | } | ||
712 | |||
713 | static inline void sysrq_unregister_handler(void) | ||
714 | { | ||
715 | } | ||
716 | |||
717 | #endif /* CONFIG_INPUT */ | ||
718 | |||
719 | int sysrq_toggle_support(int enable_mask) | ||
720 | { | ||
721 | bool was_enabled = sysrq_on(); | ||
722 | |||
723 | sysrq_enabled = enable_mask; | ||
724 | |||
725 | if (was_enabled != sysrq_on()) { | ||
726 | if (sysrq_on()) | ||
727 | sysrq_register_handler(); | ||
728 | else | ||
729 | sysrq_unregister_handler(); | ||
730 | } | ||
731 | |||
732 | return 0; | ||
733 | } | ||
734 | |||
557 | static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p, | 735 | static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p, |
558 | struct sysrq_key_op *remove_op_p) | 736 | struct sysrq_key_op *remove_op_p) |
559 | { | 737 | { |
560 | |||
561 | int retval; | 738 | int retval; |
562 | unsigned long flags; | 739 | unsigned long flags; |
563 | 740 | ||
@@ -596,19 +773,39 @@ static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf, | |||
596 | 773 | ||
597 | if (get_user(c, buf)) | 774 | if (get_user(c, buf)) |
598 | return -EFAULT; | 775 | return -EFAULT; |
599 | __handle_sysrq(c, NULL, 0); | 776 | __handle_sysrq(c, false); |
600 | } | 777 | } |
778 | |||
601 | return count; | 779 | return count; |
602 | } | 780 | } |
603 | 781 | ||
604 | static const struct file_operations proc_sysrq_trigger_operations = { | 782 | static const struct file_operations proc_sysrq_trigger_operations = { |
605 | .write = write_sysrq_trigger, | 783 | .write = write_sysrq_trigger, |
784 | .llseek = noop_llseek, | ||
606 | }; | 785 | }; |
607 | 786 | ||
787 | static void sysrq_init_procfs(void) | ||
788 | { | ||
789 | if (!proc_create("sysrq-trigger", S_IWUSR, NULL, | ||
790 | &proc_sysrq_trigger_operations)) | ||
791 | pr_err("Failed to register proc interface\n"); | ||
792 | } | ||
793 | |||
794 | #else | ||
795 | |||
796 | static inline void sysrq_init_procfs(void) | ||
797 | { | ||
798 | } | ||
799 | |||
800 | #endif /* CONFIG_PROC_FS */ | ||
801 | |||
608 | static int __init sysrq_init(void) | 802 | static int __init sysrq_init(void) |
609 | { | 803 | { |
610 | proc_create("sysrq-trigger", S_IWUSR, NULL, &proc_sysrq_trigger_operations); | 804 | sysrq_init_procfs(); |
805 | |||
806 | if (sysrq_on()) | ||
807 | sysrq_register_handler(); | ||
808 | |||
611 | return 0; | 809 | return 0; |
612 | } | 810 | } |
613 | module_init(sysrq_init); | 811 | module_init(sysrq_init); |
614 | #endif | ||
diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c index cad4eb65f13d..ad264185eb10 100644 --- a/drivers/char/tb0219.c +++ b/drivers/char/tb0219.c | |||
@@ -261,6 +261,7 @@ static const struct file_operations tb0219_fops = { | |||
261 | .write = tanbac_tb0219_write, | 261 | .write = tanbac_tb0219_write, |
262 | .open = tanbac_tb0219_open, | 262 | .open = tanbac_tb0219_open, |
263 | .release = tanbac_tb0219_release, | 263 | .release = tanbac_tb0219_release, |
264 | .llseek = no_llseek, | ||
264 | }; | 265 | }; |
265 | 266 | ||
266 | static void tb0219_restart(char *command) | 267 | static void tb0219_restart(char *command) |
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c index 80ea6bcfffdc..0c964cdcc223 100644 --- a/drivers/char/tlclk.c +++ b/drivers/char/tlclk.c | |||
@@ -37,7 +37,7 @@ | |||
37 | #include <linux/ioport.h> | 37 | #include <linux/ioport.h> |
38 | #include <linux/interrupt.h> | 38 | #include <linux/interrupt.h> |
39 | #include <linux/spinlock.h> | 39 | #include <linux/spinlock.h> |
40 | #include <linux/smp_lock.h> | 40 | #include <linux/mutex.h> |
41 | #include <linux/timer.h> | 41 | #include <linux/timer.h> |
42 | #include <linux/sysfs.h> | 42 | #include <linux/sysfs.h> |
43 | #include <linux/device.h> | 43 | #include <linux/device.h> |
@@ -206,7 +206,7 @@ static int tlclk_open(struct inode *inode, struct file *filp) | |||
206 | { | 206 | { |
207 | int result; | 207 | int result; |
208 | 208 | ||
209 | lock_kernel(); | 209 | mutex_lock(&tlclk_mutex); |
210 | if (test_and_set_bit(0, &useflags)) { | 210 | if (test_and_set_bit(0, &useflags)) { |
211 | result = -EBUSY; | 211 | result = -EBUSY; |
212 | /* this legacy device is always one per system and it doesn't | 212 | /* this legacy device is always one per system and it doesn't |
@@ -229,7 +229,7 @@ static int tlclk_open(struct inode *inode, struct file *filp) | |||
229 | inb(TLCLK_REG6); /* Clear interrupt events */ | 229 | inb(TLCLK_REG6); /* Clear interrupt events */ |
230 | 230 | ||
231 | out: | 231 | out: |
232 | unlock_kernel(); | 232 | mutex_unlock(&tlclk_mutex); |
233 | return result; | 233 | return result; |
234 | } | 234 | } |
235 | 235 | ||
@@ -267,6 +267,7 @@ static const struct file_operations tlclk_fops = { | |||
267 | .read = tlclk_read, | 267 | .read = tlclk_read, |
268 | .open = tlclk_open, | 268 | .open = tlclk_open, |
269 | .release = tlclk_release, | 269 | .release = tlclk_release, |
270 | .llseek = noop_llseek, | ||
270 | 271 | ||
271 | }; | 272 | }; |
272 | 273 | ||
diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c index f8bc79f6de34..014c9d90d297 100644 --- a/drivers/char/toshiba.c +++ b/drivers/char/toshiba.c | |||
@@ -68,7 +68,7 @@ | |||
68 | #include <linux/stat.h> | 68 | #include <linux/stat.h> |
69 | #include <linux/proc_fs.h> | 69 | #include <linux/proc_fs.h> |
70 | #include <linux/seq_file.h> | 70 | #include <linux/seq_file.h> |
71 | #include <linux/smp_lock.h> | 71 | #include <linux/mutex.h> |
72 | #include <linux/toshiba.h> | 72 | #include <linux/toshiba.h> |
73 | 73 | ||
74 | #define TOSH_MINOR_DEV 181 | 74 | #define TOSH_MINOR_DEV 181 |
@@ -78,6 +78,7 @@ MODULE_AUTHOR("Jonathan Buzzard <jonathan@buzzard.org.uk>"); | |||
78 | MODULE_DESCRIPTION("Toshiba laptop SMM driver"); | 78 | MODULE_DESCRIPTION("Toshiba laptop SMM driver"); |
79 | MODULE_SUPPORTED_DEVICE("toshiba"); | 79 | MODULE_SUPPORTED_DEVICE("toshiba"); |
80 | 80 | ||
81 | static DEFINE_MUTEX(tosh_mutex); | ||
81 | static int tosh_fn; | 82 | static int tosh_fn; |
82 | module_param_named(fn, tosh_fn, int, 0); | 83 | module_param_named(fn, tosh_fn, int, 0); |
83 | MODULE_PARM_DESC(fn, "User specified Fn key detection port"); | 84 | MODULE_PARM_DESC(fn, "User specified Fn key detection port"); |
@@ -95,6 +96,7 @@ static long tosh_ioctl(struct file *, unsigned int, | |||
95 | static const struct file_operations tosh_fops = { | 96 | static const struct file_operations tosh_fops = { |
96 | .owner = THIS_MODULE, | 97 | .owner = THIS_MODULE, |
97 | .unlocked_ioctl = tosh_ioctl, | 98 | .unlocked_ioctl = tosh_ioctl, |
99 | .llseek = noop_llseek, | ||
98 | }; | 100 | }; |
99 | 101 | ||
100 | static struct miscdevice tosh_device = { | 102 | static struct miscdevice tosh_device = { |
@@ -274,16 +276,16 @@ static long tosh_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
274 | return -EINVAL; | 276 | return -EINVAL; |
275 | 277 | ||
276 | /* do we need to emulate the fan ? */ | 278 | /* do we need to emulate the fan ? */ |
277 | lock_kernel(); | 279 | mutex_lock(&tosh_mutex); |
278 | if (tosh_fan==1) { | 280 | if (tosh_fan==1) { |
279 | if (((ax==0xf300) || (ax==0xf400)) && (bx==0x0004)) { | 281 | if (((ax==0xf300) || (ax==0xf400)) && (bx==0x0004)) { |
280 | err = tosh_emulate_fan(®s); | 282 | err = tosh_emulate_fan(®s); |
281 | unlock_kernel(); | 283 | mutex_unlock(&tosh_mutex); |
282 | break; | 284 | break; |
283 | } | 285 | } |
284 | } | 286 | } |
285 | err = tosh_smm(®s); | 287 | err = tosh_smm(®s); |
286 | unlock_kernel(); | 288 | mutex_unlock(&tosh_mutex); |
287 | break; | 289 | break; |
288 | default: | 290 | default: |
289 | return -EINVAL; | 291 | return -EINVAL; |
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index f5fc64f89c5c..f6595aba4f0f 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig | |||
@@ -17,14 +17,16 @@ menuconfig TCG_TPM | |||
17 | obtained at: <http://sourceforge.net/projects/trousers>. To | 17 | obtained at: <http://sourceforge.net/projects/trousers>. To |
18 | compile this driver as a module, choose M here; the module | 18 | compile this driver as a module, choose M here; the module |
19 | will be called tpm. If unsure, say N. | 19 | will be called tpm. If unsure, say N. |
20 | Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI | 20 | Notes: |
21 | 1) For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI | ||
21 | and CONFIG_PNPACPI. | 22 | and CONFIG_PNPACPI. |
23 | 2) Without ACPI enabled, the BIOS event log won't be accessible, | ||
24 | which is required to validate the PCR 0-7 values. | ||
22 | 25 | ||
23 | if TCG_TPM | 26 | if TCG_TPM |
24 | 27 | ||
25 | config TCG_TIS | 28 | config TCG_TIS |
26 | tristate "TPM Interface Specification 1.2 Interface" | 29 | tristate "TPM Interface Specification 1.2 Interface" |
27 | depends on PNP | ||
28 | ---help--- | 30 | ---help--- |
29 | If you have a TPM security chip that is compliant with the | 31 | If you have a TPM security chip that is compliant with the |
30 | TCG TIS 1.2 TPM specification say Yes and it will be accessible | 32 | TCG TIS 1.2 TPM specification say Yes and it will be accessible |
@@ -56,6 +58,6 @@ config TCG_INFINEON | |||
56 | To compile this driver as a module, choose M here; the module | 58 | To compile this driver as a module, choose M here; the module |
57 | will be called tpm_infineon. | 59 | will be called tpm_infineon. |
58 | Further information on this driver and the supported hardware | 60 | Further information on this driver and the supported hardware |
59 | can be found at http://www.prosec.rub.de/tpm | 61 | can be found at http://www.trust.rub.de/projects/linux-device-driver-infineon-tpm/ |
60 | 62 | ||
61 | endif # TCG_TPM | 63 | endif # TCG_TPM |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index f06bb37defb1..7c4133582dba 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -24,6 +24,7 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/poll.h> | 26 | #include <linux/poll.h> |
27 | #include <linux/slab.h> | ||
27 | #include <linux/mutex.h> | 28 | #include <linux/mutex.h> |
28 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
29 | 30 | ||
@@ -46,6 +47,16 @@ enum tpm_duration { | |||
46 | #define TPM_MAX_PROTECTED_ORDINAL 12 | 47 | #define TPM_MAX_PROTECTED_ORDINAL 12 |
47 | #define TPM_PROTECTED_ORDINAL_MASK 0xFF | 48 | #define TPM_PROTECTED_ORDINAL_MASK 0xFF |
48 | 49 | ||
50 | /* | ||
51 | * Bug workaround - some TPM's don't flush the most | ||
52 | * recently changed pcr on suspend, so force the flush | ||
53 | * with an extend to the selected _unused_ non-volatile pcr. | ||
54 | */ | ||
55 | static int tpm_suspend_pcr; | ||
56 | module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644); | ||
57 | MODULE_PARM_DESC(suspend_pcr, | ||
58 | "PCR to use for dummy writes to faciltate flush on suspend."); | ||
59 | |||
49 | static LIST_HEAD(tpm_chip_list); | 60 | static LIST_HEAD(tpm_chip_list); |
50 | static DEFINE_SPINLOCK(driver_lock); | 61 | static DEFINE_SPINLOCK(driver_lock); |
51 | static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); | 62 | static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); |
@@ -1067,6 +1078,15 @@ void tpm_remove_hardware(struct device *dev) | |||
1067 | } | 1078 | } |
1068 | EXPORT_SYMBOL_GPL(tpm_remove_hardware); | 1079 | EXPORT_SYMBOL_GPL(tpm_remove_hardware); |
1069 | 1080 | ||
1081 | #define TPM_ORD_SAVESTATE cpu_to_be32(152) | ||
1082 | #define SAVESTATE_RESULT_SIZE 10 | ||
1083 | |||
1084 | static struct tpm_input_header savestate_header = { | ||
1085 | .tag = TPM_TAG_RQU_COMMAND, | ||
1086 | .length = cpu_to_be32(10), | ||
1087 | .ordinal = TPM_ORD_SAVESTATE | ||
1088 | }; | ||
1089 | |||
1070 | /* | 1090 | /* |
1071 | * We are about to suspend. Save the TPM state | 1091 | * We are about to suspend. Save the TPM state |
1072 | * so that it can be restored. | 1092 | * so that it can be restored. |
@@ -1074,17 +1094,29 @@ EXPORT_SYMBOL_GPL(tpm_remove_hardware); | |||
1074 | int tpm_pm_suspend(struct device *dev, pm_message_t pm_state) | 1094 | int tpm_pm_suspend(struct device *dev, pm_message_t pm_state) |
1075 | { | 1095 | { |
1076 | struct tpm_chip *chip = dev_get_drvdata(dev); | 1096 | struct tpm_chip *chip = dev_get_drvdata(dev); |
1077 | u8 savestate[] = { | 1097 | struct tpm_cmd_t cmd; |
1078 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 1098 | int rc; |
1079 | 0, 0, 0, 10, /* blob length (in bytes) */ | 1099 | |
1080 | 0, 0, 0, 152 /* TPM_ORD_SaveState */ | 1100 | u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 }; |
1081 | }; | ||
1082 | 1101 | ||
1083 | if (chip == NULL) | 1102 | if (chip == NULL) |
1084 | return -ENODEV; | 1103 | return -ENODEV; |
1085 | 1104 | ||
1086 | tpm_transmit(chip, savestate, sizeof(savestate)); | 1105 | /* for buggy tpm, flush pcrs with extend to selected dummy */ |
1087 | return 0; | 1106 | if (tpm_suspend_pcr) { |
1107 | cmd.header.in = pcrextend_header; | ||
1108 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr); | ||
1109 | memcpy(cmd.params.pcrextend_in.hash, dummy_hash, | ||
1110 | TPM_DIGEST_SIZE); | ||
1111 | rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, | ||
1112 | "extending dummy pcr before suspend"); | ||
1113 | } | ||
1114 | |||
1115 | /* now do the actual savestate */ | ||
1116 | cmd.header.in = savestate_header; | ||
1117 | rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, | ||
1118 | "sending savestate before suspend"); | ||
1119 | return rc; | ||
1088 | } | 1120 | } |
1089 | EXPORT_SYMBOL_GPL(tpm_pm_suspend); | 1121 | EXPORT_SYMBOL_GPL(tpm_pm_suspend); |
1090 | 1122 | ||
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 8e00b4ddd083..792868d24f2a 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -224,6 +224,7 @@ struct tpm_readpubek_params_out { | |||
224 | u8 algorithm[4]; | 224 | u8 algorithm[4]; |
225 | u8 encscheme[2]; | 225 | u8 encscheme[2]; |
226 | u8 sigscheme[2]; | 226 | u8 sigscheme[2]; |
227 | __be32 paramsize; | ||
227 | u8 parameters[12]; /*assuming RSA*/ | 228 | u8 parameters[12]; /*assuming RSA*/ |
228 | __be32 keysize; | 229 | __be32 keysize; |
229 | u8 modulus[256]; | 230 | u8 modulus[256]; |
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c index bf2170fb1cdd..0636520fa9bf 100644 --- a/drivers/char/tpm/tpm_bios.c +++ b/drivers/char/tpm/tpm_bios.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/fs.h> | 22 | #include <linux/fs.h> |
23 | #include <linux/security.h> | 23 | #include <linux/security.h> |
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/slab.h> | ||
25 | #include <acpi/acpi.h> | 26 | #include <acpi/acpi.h> |
26 | #include "tpm.h" | 27 | #include "tpm.h" |
27 | 28 | ||
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index ecba4942fc8e..76da32e11f18 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * Copyright (C) 2005, Marcel Selhorst <m.selhorst@sirrix.com> | 7 | * Copyright (C) 2005, Marcel Selhorst <m.selhorst@sirrix.com> |
8 | * Sirrix AG - security technologies, http://www.sirrix.com and | 8 | * Sirrix AG - security technologies, http://www.sirrix.com and |
9 | * Applied Data Security Group, Ruhr-University Bochum, Germany | 9 | * Applied Data Security Group, Ruhr-University Bochum, Germany |
10 | * Project-Homepage: http://www.prosec.rub.de/tpm | 10 | * Project-Homepage: http://www.trust.rub.de/projects/linux-device-driver-infineon-tpm/ |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or | 12 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License as | 13 | * modify it under the terms of the GNU General Public License as |
@@ -39,12 +39,12 @@ | |||
39 | struct tpm_inf_dev { | 39 | struct tpm_inf_dev { |
40 | int iotype; | 40 | int iotype; |
41 | 41 | ||
42 | void __iomem *mem_base; /* MMIO ioremap'd addr */ | 42 | void __iomem *mem_base; /* MMIO ioremap'd addr */ |
43 | unsigned long map_base; /* phys MMIO base */ | 43 | unsigned long map_base; /* phys MMIO base */ |
44 | unsigned long map_size; /* MMIO region size */ | 44 | unsigned long map_size; /* MMIO region size */ |
45 | unsigned int index_off; /* index register offset */ | 45 | unsigned int index_off; /* index register offset */ |
46 | 46 | ||
47 | unsigned int data_regs; /* Data registers */ | 47 | unsigned int data_regs; /* Data registers */ |
48 | unsigned int data_size; | 48 | unsigned int data_size; |
49 | 49 | ||
50 | unsigned int config_port; /* IO Port config index reg */ | 50 | unsigned int config_port; /* IO Port config index reg */ |
@@ -406,14 +406,14 @@ static const struct tpm_vendor_specific tpm_inf = { | |||
406 | .miscdev = {.fops = &inf_ops,}, | 406 | .miscdev = {.fops = &inf_ops,}, |
407 | }; | 407 | }; |
408 | 408 | ||
409 | static const struct pnp_device_id tpm_pnp_tbl[] = { | 409 | static const struct pnp_device_id tpm_inf_pnp_tbl[] = { |
410 | /* Infineon TPMs */ | 410 | /* Infineon TPMs */ |
411 | {"IFX0101", 0}, | 411 | {"IFX0101", 0}, |
412 | {"IFX0102", 0}, | 412 | {"IFX0102", 0}, |
413 | {"", 0} | 413 | {"", 0} |
414 | }; | 414 | }; |
415 | 415 | ||
416 | MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl); | 416 | MODULE_DEVICE_TABLE(pnp, tpm_inf_pnp_tbl); |
417 | 417 | ||
418 | static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | 418 | static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, |
419 | const struct pnp_device_id *dev_id) | 419 | const struct pnp_device_id *dev_id) |
@@ -430,7 +430,7 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
430 | if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && | 430 | if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && |
431 | !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) { | 431 | !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) { |
432 | 432 | ||
433 | tpm_dev.iotype = TPM_INF_IO_PORT; | 433 | tpm_dev.iotype = TPM_INF_IO_PORT; |
434 | 434 | ||
435 | tpm_dev.config_port = pnp_port_start(dev, 0); | 435 | tpm_dev.config_port = pnp_port_start(dev, 0); |
436 | tpm_dev.config_size = pnp_port_len(dev, 0); | 436 | tpm_dev.config_size = pnp_port_len(dev, 0); |
@@ -459,9 +459,9 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
459 | goto err_last; | 459 | goto err_last; |
460 | } | 460 | } |
461 | } else if (pnp_mem_valid(dev, 0) && | 461 | } else if (pnp_mem_valid(dev, 0) && |
462 | !(pnp_mem_flags(dev, 0) & IORESOURCE_DISABLED)) { | 462 | !(pnp_mem_flags(dev, 0) & IORESOURCE_DISABLED)) { |
463 | 463 | ||
464 | tpm_dev.iotype = TPM_INF_IO_MEM; | 464 | tpm_dev.iotype = TPM_INF_IO_MEM; |
465 | 465 | ||
466 | tpm_dev.map_base = pnp_mem_start(dev, 0); | 466 | tpm_dev.map_base = pnp_mem_start(dev, 0); |
467 | tpm_dev.map_size = pnp_mem_len(dev, 0); | 467 | tpm_dev.map_size = pnp_mem_len(dev, 0); |
@@ -563,11 +563,11 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
563 | "product id 0x%02x%02x" | 563 | "product id 0x%02x%02x" |
564 | "%s\n", | 564 | "%s\n", |
565 | tpm_dev.iotype == TPM_INF_IO_PORT ? | 565 | tpm_dev.iotype == TPM_INF_IO_PORT ? |
566 | tpm_dev.config_port : | 566 | tpm_dev.config_port : |
567 | tpm_dev.map_base + tpm_dev.index_off, | 567 | tpm_dev.map_base + tpm_dev.index_off, |
568 | tpm_dev.iotype == TPM_INF_IO_PORT ? | 568 | tpm_dev.iotype == TPM_INF_IO_PORT ? |
569 | tpm_dev.data_regs : | 569 | tpm_dev.data_regs : |
570 | tpm_dev.map_base + tpm_dev.data_regs, | 570 | tpm_dev.map_base + tpm_dev.data_regs, |
571 | version[0], version[1], | 571 | version[0], version[1], |
572 | vendorid[0], vendorid[1], | 572 | vendorid[0], vendorid[1], |
573 | productid[0], productid[1], chipname); | 573 | productid[0], productid[1], chipname); |
@@ -607,20 +607,55 @@ static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev) | |||
607 | iounmap(tpm_dev.mem_base); | 607 | iounmap(tpm_dev.mem_base); |
608 | release_mem_region(tpm_dev.map_base, tpm_dev.map_size); | 608 | release_mem_region(tpm_dev.map_base, tpm_dev.map_size); |
609 | } | 609 | } |
610 | tpm_dev_vendor_release(chip); | ||
610 | tpm_remove_hardware(chip->dev); | 611 | tpm_remove_hardware(chip->dev); |
611 | } | 612 | } |
612 | } | 613 | } |
613 | 614 | ||
615 | static int tpm_inf_pnp_suspend(struct pnp_dev *dev, pm_message_t pm_state) | ||
616 | { | ||
617 | struct tpm_chip *chip = pnp_get_drvdata(dev); | ||
618 | int rc; | ||
619 | if (chip) { | ||
620 | u8 savestate[] = { | ||
621 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | ||
622 | 0, 0, 0, 10, /* blob length (in bytes) */ | ||
623 | 0, 0, 0, 152 /* TPM_ORD_SaveState */ | ||
624 | }; | ||
625 | dev_info(&dev->dev, "saving TPM state\n"); | ||
626 | rc = tpm_inf_send(chip, savestate, sizeof(savestate)); | ||
627 | if (rc < 0) { | ||
628 | dev_err(&dev->dev, "error while saving TPM state\n"); | ||
629 | return rc; | ||
630 | } | ||
631 | } | ||
632 | return 0; | ||
633 | } | ||
634 | |||
635 | static int tpm_inf_pnp_resume(struct pnp_dev *dev) | ||
636 | { | ||
637 | /* Re-configure TPM after suspending */ | ||
638 | tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR); | ||
639 | tpm_config_out(IOLIMH, TPM_INF_ADDR); | ||
640 | tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA); | ||
641 | tpm_config_out(IOLIML, TPM_INF_ADDR); | ||
642 | tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA); | ||
643 | /* activate register */ | ||
644 | tpm_config_out(TPM_DAR, TPM_INF_ADDR); | ||
645 | tpm_config_out(0x01, TPM_INF_DATA); | ||
646 | tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR); | ||
647 | /* disable RESET, LP and IRQC */ | ||
648 | tpm_data_out(RESET_LP_IRQC_DISABLE, CMD); | ||
649 | return tpm_pm_resume(&dev->dev); | ||
650 | } | ||
651 | |||
614 | static struct pnp_driver tpm_inf_pnp_driver = { | 652 | static struct pnp_driver tpm_inf_pnp_driver = { |
615 | .name = "tpm_inf_pnp", | 653 | .name = "tpm_inf_pnp", |
616 | .driver = { | 654 | .id_table = tpm_inf_pnp_tbl, |
617 | .owner = THIS_MODULE, | ||
618 | .suspend = tpm_pm_suspend, | ||
619 | .resume = tpm_pm_resume, | ||
620 | }, | ||
621 | .id_table = tpm_pnp_tbl, | ||
622 | .probe = tpm_inf_pnp_probe, | 655 | .probe = tpm_inf_pnp_probe, |
623 | .remove = __devexit_p(tpm_inf_pnp_remove), | 656 | .suspend = tpm_inf_pnp_suspend, |
657 | .resume = tpm_inf_pnp_resume, | ||
658 | .remove = __devexit_p(tpm_inf_pnp_remove) | ||
624 | }; | 659 | }; |
625 | 660 | ||
626 | static int __init init_inf(void) | 661 | static int __init init_inf(void) |
@@ -638,5 +673,5 @@ module_exit(cleanup_inf); | |||
638 | 673 | ||
639 | MODULE_AUTHOR("Marcel Selhorst <m.selhorst@sirrix.com>"); | 674 | MODULE_AUTHOR("Marcel Selhorst <m.selhorst@sirrix.com>"); |
640 | MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); | 675 | MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); |
641 | MODULE_VERSION("1.9"); | 676 | MODULE_VERSION("1.9.2"); |
642 | MODULE_LICENSE("GPL"); | 677 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c index 70efba2ee053..a605cb7dd898 100644 --- a/drivers/char/tpm/tpm_nsc.c +++ b/drivers/char/tpm/tpm_nsc.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/slab.h> | ||
23 | #include "tpm.h" | 24 | #include "tpm.h" |
24 | 25 | ||
25 | /* National definitions */ | 26 | /* National definitions */ |
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 2405f17b29dd..1030f8420137 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/moduleparam.h> | 23 | #include <linux/moduleparam.h> |
24 | #include <linux/pnp.h> | 24 | #include <linux/pnp.h> |
25 | #include <linux/slab.h> | ||
25 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
26 | #include <linux/wait.h> | 27 | #include <linux/wait.h> |
27 | #include "tpm.h" | 28 | #include "tpm.h" |
@@ -597,7 +598,7 @@ out_err: | |||
597 | tpm_remove_hardware(chip->dev); | 598 | tpm_remove_hardware(chip->dev); |
598 | return rc; | 599 | return rc; |
599 | } | 600 | } |
600 | 601 | #ifdef CONFIG_PNP | |
601 | static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, | 602 | static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, |
602 | const struct pnp_device_id *pnp_id) | 603 | const struct pnp_device_id *pnp_id) |
603 | { | 604 | { |
@@ -622,7 +623,14 @@ static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg) | |||
622 | 623 | ||
623 | static int tpm_tis_pnp_resume(struct pnp_dev *dev) | 624 | static int tpm_tis_pnp_resume(struct pnp_dev *dev) |
624 | { | 625 | { |
625 | return tpm_pm_resume(&dev->dev); | 626 | struct tpm_chip *chip = pnp_get_drvdata(dev); |
627 | int ret; | ||
628 | |||
629 | ret = tpm_pm_resume(&dev->dev); | ||
630 | if (!ret) | ||
631 | tpm_continue_selftest(chip); | ||
632 | |||
633 | return ret; | ||
626 | } | 634 | } |
627 | 635 | ||
628 | static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = { | 636 | static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = { |
@@ -662,7 +670,7 @@ static struct pnp_driver tis_pnp_driver = { | |||
662 | module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, | 670 | module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, |
663 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); | 671 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); |
664 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); | 672 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); |
665 | 673 | #endif | |
666 | static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg) | 674 | static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg) |
667 | { | 675 | { |
668 | return tpm_pm_suspend(&dev->dev, msg); | 676 | return tpm_pm_suspend(&dev->dev, msg); |
@@ -689,21 +697,21 @@ MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry"); | |||
689 | static int __init init_tis(void) | 697 | static int __init init_tis(void) |
690 | { | 698 | { |
691 | int rc; | 699 | int rc; |
700 | #ifdef CONFIG_PNP | ||
701 | if (!force) | ||
702 | return pnp_register_driver(&tis_pnp_driver); | ||
703 | #endif | ||
692 | 704 | ||
693 | if (force) { | 705 | rc = platform_driver_register(&tis_drv); |
694 | rc = platform_driver_register(&tis_drv); | 706 | if (rc < 0) |
695 | if (rc < 0) | ||
696 | return rc; | ||
697 | if (IS_ERR(pdev=platform_device_register_simple("tpm_tis", -1, NULL, 0))) | ||
698 | return PTR_ERR(pdev); | ||
699 | if((rc=tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0)) != 0) { | ||
700 | platform_device_unregister(pdev); | ||
701 | platform_driver_unregister(&tis_drv); | ||
702 | } | ||
703 | return rc; | 707 | return rc; |
708 | if (IS_ERR(pdev=platform_device_register_simple("tpm_tis", -1, NULL, 0))) | ||
709 | return PTR_ERR(pdev); | ||
710 | if((rc=tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0)) != 0) { | ||
711 | platform_device_unregister(pdev); | ||
712 | platform_driver_unregister(&tis_drv); | ||
704 | } | 713 | } |
705 | 714 | return rc; | |
706 | return pnp_register_driver(&tis_pnp_driver); | ||
707 | } | 715 | } |
708 | 716 | ||
709 | static void __exit cleanup_tis(void) | 717 | static void __exit cleanup_tis(void) |
@@ -727,12 +735,14 @@ static void __exit cleanup_tis(void) | |||
727 | list_del(&i->list); | 735 | list_del(&i->list); |
728 | } | 736 | } |
729 | spin_unlock(&tis_lock); | 737 | spin_unlock(&tis_lock); |
730 | 738 | #ifdef CONFIG_PNP | |
731 | if (force) { | 739 | if (!force) { |
732 | platform_device_unregister(pdev); | ||
733 | platform_driver_unregister(&tis_drv); | ||
734 | } else | ||
735 | pnp_unregister_driver(&tis_pnp_driver); | 740 | pnp_unregister_driver(&tis_pnp_driver); |
741 | return; | ||
742 | } | ||
743 | #endif | ||
744 | platform_device_unregister(pdev); | ||
745 | platform_driver_unregister(&tis_drv); | ||
736 | } | 746 | } |
737 | 747 | ||
738 | module_init(init_tis); | 748 | module_init(init_tis); |
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c index ac16fbec72d0..1b8ee590b4ca 100644 --- a/drivers/char/tty_audit.c +++ b/drivers/char/tty_audit.c | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/audit.h> | 12 | #include <linux/audit.h> |
13 | #include <linux/slab.h> | ||
13 | #include <linux/tty.h> | 14 | #include <linux/tty.h> |
14 | 15 | ||
15 | struct tty_audit_buf { | 16 | struct tty_audit_buf { |
@@ -148,7 +149,6 @@ void tty_audit_fork(struct signal_struct *sig) | |||
148 | spin_lock_irq(¤t->sighand->siglock); | 149 | spin_lock_irq(¤t->sighand->siglock); |
149 | sig->audit_tty = current->signal->audit_tty; | 150 | sig->audit_tty = current->signal->audit_tty; |
150 | spin_unlock_irq(¤t->sighand->siglock); | 151 | spin_unlock_irq(¤t->sighand->siglock); |
151 | sig->tty_audit_buf = NULL; | ||
152 | } | 152 | } |
153 | 153 | ||
154 | /** | 154 | /** |
diff --git a/drivers/char/tty_buffer.c b/drivers/char/tty_buffer.c index 66fa4e10d76b..cc1e9850d655 100644 --- a/drivers/char/tty_buffer.c +++ b/drivers/char/tty_buffer.c | |||
@@ -231,29 +231,31 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size) | |||
231 | EXPORT_SYMBOL_GPL(tty_buffer_request_room); | 231 | EXPORT_SYMBOL_GPL(tty_buffer_request_room); |
232 | 232 | ||
233 | /** | 233 | /** |
234 | * tty_insert_flip_string - Add characters to the tty buffer | 234 | * tty_insert_flip_string_fixed_flag - Add characters to the tty buffer |
235 | * @tty: tty structure | 235 | * @tty: tty structure |
236 | * @chars: characters | 236 | * @chars: characters |
237 | * @flag: flag value for each character | ||
237 | * @size: size | 238 | * @size: size |
238 | * | 239 | * |
239 | * Queue a series of bytes to the tty buffering. All the characters | 240 | * Queue a series of bytes to the tty buffering. All the characters |
240 | * passed are marked as without error. Returns the number added. | 241 | * passed are marked with the supplied flag. Returns the number added. |
241 | * | 242 | * |
242 | * Locking: Called functions may take tty->buf.lock | 243 | * Locking: Called functions may take tty->buf.lock |
243 | */ | 244 | */ |
244 | 245 | ||
245 | int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, | 246 | int tty_insert_flip_string_fixed_flag(struct tty_struct *tty, |
246 | size_t size) | 247 | const unsigned char *chars, char flag, size_t size) |
247 | { | 248 | { |
248 | int copied = 0; | 249 | int copied = 0; |
249 | do { | 250 | do { |
250 | int space = tty_buffer_request_room(tty, size - copied); | 251 | int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); |
252 | int space = tty_buffer_request_room(tty, goal); | ||
251 | struct tty_buffer *tb = tty->buf.tail; | 253 | struct tty_buffer *tb = tty->buf.tail; |
252 | /* If there is no space then tb may be NULL */ | 254 | /* If there is no space then tb may be NULL */ |
253 | if (unlikely(space == 0)) | 255 | if (unlikely(space == 0)) |
254 | break; | 256 | break; |
255 | memcpy(tb->char_buf_ptr + tb->used, chars, space); | 257 | memcpy(tb->char_buf_ptr + tb->used, chars, space); |
256 | memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space); | 258 | memset(tb->flag_buf_ptr + tb->used, flag, space); |
257 | tb->used += space; | 259 | tb->used += space; |
258 | copied += space; | 260 | copied += space; |
259 | chars += space; | 261 | chars += space; |
@@ -262,7 +264,7 @@ int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, | |||
262 | } while (unlikely(size > copied)); | 264 | } while (unlikely(size > copied)); |
263 | return copied; | 265 | return copied; |
264 | } | 266 | } |
265 | EXPORT_SYMBOL(tty_insert_flip_string); | 267 | EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag); |
266 | 268 | ||
267 | /** | 269 | /** |
268 | * tty_insert_flip_string_flags - Add characters to the tty buffer | 270 | * tty_insert_flip_string_flags - Add characters to the tty buffer |
@@ -283,7 +285,8 @@ int tty_insert_flip_string_flags(struct tty_struct *tty, | |||
283 | { | 285 | { |
284 | int copied = 0; | 286 | int copied = 0; |
285 | do { | 287 | do { |
286 | int space = tty_buffer_request_room(tty, size - copied); | 288 | int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); |
289 | int space = tty_buffer_request_room(tty, goal); | ||
287 | struct tty_buffer *tb = tty->buf.tail; | 290 | struct tty_buffer *tb = tty->buf.tail; |
288 | /* If there is no space then tb may be NULL */ | 291 | /* If there is no space then tb may be NULL */ |
289 | if (unlikely(space == 0)) | 292 | if (unlikely(space == 0)) |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index c6f3b48be9dd..c05c5af5aa04 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -96,6 +96,7 @@ | |||
96 | #include <linux/bitops.h> | 96 | #include <linux/bitops.h> |
97 | #include <linux/delay.h> | 97 | #include <linux/delay.h> |
98 | #include <linux/seq_file.h> | 98 | #include <linux/seq_file.h> |
99 | #include <linux/serial.h> | ||
99 | 100 | ||
100 | #include <linux/uaccess.h> | 101 | #include <linux/uaccess.h> |
101 | #include <asm/system.h> | 102 | #include <asm/system.h> |
@@ -136,6 +137,9 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */ | |||
136 | DEFINE_MUTEX(tty_mutex); | 137 | DEFINE_MUTEX(tty_mutex); |
137 | EXPORT_SYMBOL(tty_mutex); | 138 | EXPORT_SYMBOL(tty_mutex); |
138 | 139 | ||
140 | /* Spinlock to protect the tty->tty_files list */ | ||
141 | DEFINE_SPINLOCK(tty_files_lock); | ||
142 | |||
139 | static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); | 143 | static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); |
140 | static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *); | 144 | static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *); |
141 | ssize_t redirected_tty_write(struct file *, const char __user *, | 145 | ssize_t redirected_tty_write(struct file *, const char __user *, |
@@ -149,6 +153,7 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, | |||
149 | #else | 153 | #else |
150 | #define tty_compat_ioctl NULL | 154 | #define tty_compat_ioctl NULL |
151 | #endif | 155 | #endif |
156 | static int __tty_fasync(int fd, struct file *filp, int on); | ||
152 | static int tty_fasync(int fd, struct file *filp, int on); | 157 | static int tty_fasync(int fd, struct file *filp, int on); |
153 | static void release_tty(struct tty_struct *tty, int idx); | 158 | static void release_tty(struct tty_struct *tty, int idx); |
154 | static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); | 159 | static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); |
@@ -179,11 +184,51 @@ struct tty_struct *alloc_tty_struct(void) | |||
179 | 184 | ||
180 | void free_tty_struct(struct tty_struct *tty) | 185 | void free_tty_struct(struct tty_struct *tty) |
181 | { | 186 | { |
187 | if (tty->dev) | ||
188 | put_device(tty->dev); | ||
182 | kfree(tty->write_buf); | 189 | kfree(tty->write_buf); |
183 | tty_buffer_free_all(tty); | 190 | tty_buffer_free_all(tty); |
184 | kfree(tty); | 191 | kfree(tty); |
185 | } | 192 | } |
186 | 193 | ||
194 | static inline struct tty_struct *file_tty(struct file *file) | ||
195 | { | ||
196 | return ((struct tty_file_private *)file->private_data)->tty; | ||
197 | } | ||
198 | |||
199 | /* Associate a new file with the tty structure */ | ||
200 | int tty_add_file(struct tty_struct *tty, struct file *file) | ||
201 | { | ||
202 | struct tty_file_private *priv; | ||
203 | |||
204 | priv = kmalloc(sizeof(*priv), GFP_KERNEL); | ||
205 | if (!priv) | ||
206 | return -ENOMEM; | ||
207 | |||
208 | priv->tty = tty; | ||
209 | priv->file = file; | ||
210 | file->private_data = priv; | ||
211 | |||
212 | spin_lock(&tty_files_lock); | ||
213 | list_add(&priv->list, &tty->tty_files); | ||
214 | spin_unlock(&tty_files_lock); | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | /* Delete file from its tty */ | ||
220 | void tty_del_file(struct file *file) | ||
221 | { | ||
222 | struct tty_file_private *priv = file->private_data; | ||
223 | |||
224 | spin_lock(&tty_files_lock); | ||
225 | list_del(&priv->list); | ||
226 | spin_unlock(&tty_files_lock); | ||
227 | file->private_data = NULL; | ||
228 | kfree(priv); | ||
229 | } | ||
230 | |||
231 | |||
187 | #define TTY_NUMBER(tty) ((tty)->index + (tty)->driver->name_base) | 232 | #define TTY_NUMBER(tty) ((tty)->index + (tty)->driver->name_base) |
188 | 233 | ||
189 | /** | 234 | /** |
@@ -234,11 +279,11 @@ static int check_tty_count(struct tty_struct *tty, const char *routine) | |||
234 | struct list_head *p; | 279 | struct list_head *p; |
235 | int count = 0; | 280 | int count = 0; |
236 | 281 | ||
237 | file_list_lock(); | 282 | spin_lock(&tty_files_lock); |
238 | list_for_each(p, &tty->tty_files) { | 283 | list_for_each(p, &tty->tty_files) { |
239 | count++; | 284 | count++; |
240 | } | 285 | } |
241 | file_list_unlock(); | 286 | spin_unlock(&tty_files_lock); |
242 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 287 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
243 | tty->driver->subtype == PTY_TYPE_SLAVE && | 288 | tty->driver->subtype == PTY_TYPE_SLAVE && |
244 | tty->link && tty->link->count) | 289 | tty->link && tty->link->count) |
@@ -316,7 +361,7 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line) | |||
316 | if (*stp == '\0') | 361 | if (*stp == '\0') |
317 | stp = NULL; | 362 | stp = NULL; |
318 | 363 | ||
319 | if (tty_line >= 0 && tty_line <= p->num && p->ops && | 364 | if (tty_line >= 0 && tty_line < p->num && p->ops && |
320 | p->ops->poll_init && !p->ops->poll_init(p, tty_line, stp)) { | 365 | p->ops->poll_init && !p->ops->poll_init(p, tty_line, stp)) { |
321 | res = tty_driver_kref_get(p); | 366 | res = tty_driver_kref_get(p); |
322 | *line = tty_line; | 367 | *line = tty_line; |
@@ -470,7 +515,7 @@ void tty_wakeup(struct tty_struct *tty) | |||
470 | EXPORT_SYMBOL_GPL(tty_wakeup); | 515 | EXPORT_SYMBOL_GPL(tty_wakeup); |
471 | 516 | ||
472 | /** | 517 | /** |
473 | * do_tty_hangup - actual handler for hangup events | 518 | * __tty_hangup - actual handler for hangup events |
474 | * @work: tty device | 519 | * @work: tty device |
475 | * | 520 | * |
476 | * This can be called by the "eventd" kernel thread. That is process | 521 | * This can be called by the "eventd" kernel thread. That is process |
@@ -483,7 +528,7 @@ EXPORT_SYMBOL_GPL(tty_wakeup); | |||
483 | * remains intact. | 528 | * remains intact. |
484 | * | 529 | * |
485 | * Locking: | 530 | * Locking: |
486 | * BKL | 531 | * BTM |
487 | * redirect lock for undoing redirection | 532 | * redirect lock for undoing redirection |
488 | * file list lock for manipulating list of ttys | 533 | * file list lock for manipulating list of ttys |
489 | * tty_ldisc_lock from called functions | 534 | * tty_ldisc_lock from called functions |
@@ -491,13 +536,12 @@ EXPORT_SYMBOL_GPL(tty_wakeup); | |||
491 | * tasklist_lock to walk task list for hangup event | 536 | * tasklist_lock to walk task list for hangup event |
492 | * ->siglock to protect ->signal/->sighand | 537 | * ->siglock to protect ->signal/->sighand |
493 | */ | 538 | */ |
494 | static void do_tty_hangup(struct work_struct *work) | 539 | void __tty_hangup(struct tty_struct *tty) |
495 | { | 540 | { |
496 | struct tty_struct *tty = | ||
497 | container_of(work, struct tty_struct, hangup_work); | ||
498 | struct file *cons_filp = NULL; | 541 | struct file *cons_filp = NULL; |
499 | struct file *filp, *f = NULL; | 542 | struct file *filp, *f = NULL; |
500 | struct task_struct *p; | 543 | struct task_struct *p; |
544 | struct tty_file_private *priv; | ||
501 | int closecount = 0, n; | 545 | int closecount = 0, n; |
502 | unsigned long flags; | 546 | unsigned long flags; |
503 | int refs = 0; | 547 | int refs = 0; |
@@ -507,28 +551,32 @@ static void do_tty_hangup(struct work_struct *work) | |||
507 | 551 | ||
508 | 552 | ||
509 | spin_lock(&redirect_lock); | 553 | spin_lock(&redirect_lock); |
510 | if (redirect && redirect->private_data == tty) { | 554 | if (redirect && file_tty(redirect) == tty) { |
511 | f = redirect; | 555 | f = redirect; |
512 | redirect = NULL; | 556 | redirect = NULL; |
513 | } | 557 | } |
514 | spin_unlock(&redirect_lock); | 558 | spin_unlock(&redirect_lock); |
515 | 559 | ||
516 | /* inuse_filps is protected by the single kernel lock */ | 560 | tty_lock(); |
517 | lock_kernel(); | 561 | |
518 | check_tty_count(tty, "do_tty_hangup"); | 562 | /* inuse_filps is protected by the single tty lock, |
563 | this really needs to change if we want to flush the | ||
564 | workqueue with the lock held */ | ||
565 | check_tty_count(tty, "tty_hangup"); | ||
519 | 566 | ||
520 | file_list_lock(); | 567 | spin_lock(&tty_files_lock); |
521 | /* This breaks for file handles being sent over AF_UNIX sockets ? */ | 568 | /* This breaks for file handles being sent over AF_UNIX sockets ? */ |
522 | list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) { | 569 | list_for_each_entry(priv, &tty->tty_files, list) { |
570 | filp = priv->file; | ||
523 | if (filp->f_op->write == redirected_tty_write) | 571 | if (filp->f_op->write == redirected_tty_write) |
524 | cons_filp = filp; | 572 | cons_filp = filp; |
525 | if (filp->f_op->write != tty_write) | 573 | if (filp->f_op->write != tty_write) |
526 | continue; | 574 | continue; |
527 | closecount++; | 575 | closecount++; |
528 | tty_fasync(-1, filp, 0); /* can't block */ | 576 | __tty_fasync(-1, filp, 0); /* can't block */ |
529 | filp->f_op = &hung_up_tty_fops; | 577 | filp->f_op = &hung_up_tty_fops; |
530 | } | 578 | } |
531 | file_list_unlock(); | 579 | spin_unlock(&tty_files_lock); |
532 | 580 | ||
533 | tty_ldisc_hangup(tty); | 581 | tty_ldisc_hangup(tty); |
534 | 582 | ||
@@ -594,11 +642,21 @@ static void do_tty_hangup(struct work_struct *work) | |||
594 | */ | 642 | */ |
595 | set_bit(TTY_HUPPED, &tty->flags); | 643 | set_bit(TTY_HUPPED, &tty->flags); |
596 | tty_ldisc_enable(tty); | 644 | tty_ldisc_enable(tty); |
597 | unlock_kernel(); | 645 | |
646 | tty_unlock(); | ||
647 | |||
598 | if (f) | 648 | if (f) |
599 | fput(f); | 649 | fput(f); |
600 | } | 650 | } |
601 | 651 | ||
652 | static void do_tty_hangup(struct work_struct *work) | ||
653 | { | ||
654 | struct tty_struct *tty = | ||
655 | container_of(work, struct tty_struct, hangup_work); | ||
656 | |||
657 | __tty_hangup(tty); | ||
658 | } | ||
659 | |||
602 | /** | 660 | /** |
603 | * tty_hangup - trigger a hangup event | 661 | * tty_hangup - trigger a hangup event |
604 | * @tty: tty to hangup | 662 | * @tty: tty to hangup |
@@ -634,11 +692,12 @@ void tty_vhangup(struct tty_struct *tty) | |||
634 | 692 | ||
635 | printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf)); | 693 | printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf)); |
636 | #endif | 694 | #endif |
637 | do_tty_hangup(&tty->hangup_work); | 695 | __tty_hangup(tty); |
638 | } | 696 | } |
639 | 697 | ||
640 | EXPORT_SYMBOL(tty_vhangup); | 698 | EXPORT_SYMBOL(tty_vhangup); |
641 | 699 | ||
700 | |||
642 | /** | 701 | /** |
643 | * tty_vhangup_self - process vhangup for own ctty | 702 | * tty_vhangup_self - process vhangup for own ctty |
644 | * | 703 | * |
@@ -696,7 +755,8 @@ static void session_clear_tty(struct pid *session) | |||
696 | * exiting; it is 0 if called by the ioctl TIOCNOTTY. | 755 | * exiting; it is 0 if called by the ioctl TIOCNOTTY. |
697 | * | 756 | * |
698 | * Locking: | 757 | * Locking: |
699 | * BKL is taken for hysterical raisins | 758 | * BTM is taken for hysterical raisins, and held when |
759 | * called from no_tty(). | ||
700 | * tty_mutex is taken to protect tty | 760 | * tty_mutex is taken to protect tty |
701 | * ->siglock is taken to protect ->signal/->sighand | 761 | * ->siglock is taken to protect ->signal/->sighand |
702 | * tasklist_lock is taken to walk process list for sessions | 762 | * tasklist_lock is taken to walk process list for sessions |
@@ -714,10 +774,10 @@ void disassociate_ctty(int on_exit) | |||
714 | tty = get_current_tty(); | 774 | tty = get_current_tty(); |
715 | if (tty) { | 775 | if (tty) { |
716 | tty_pgrp = get_pid(tty->pgrp); | 776 | tty_pgrp = get_pid(tty->pgrp); |
717 | lock_kernel(); | 777 | if (on_exit) { |
718 | if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) | 778 | if (tty->driver->type != TTY_DRIVER_TYPE_PTY) |
719 | tty_vhangup(tty); | 779 | tty_vhangup(tty); |
720 | unlock_kernel(); | 780 | } |
721 | tty_kref_put(tty); | 781 | tty_kref_put(tty); |
722 | } else if (on_exit) { | 782 | } else if (on_exit) { |
723 | struct pid *old_pgrp; | 783 | struct pid *old_pgrp; |
@@ -774,9 +834,9 @@ void disassociate_ctty(int on_exit) | |||
774 | void no_tty(void) | 834 | void no_tty(void) |
775 | { | 835 | { |
776 | struct task_struct *tsk = current; | 836 | struct task_struct *tsk = current; |
777 | lock_kernel(); | 837 | tty_lock(); |
778 | disassociate_ctty(0); | 838 | disassociate_ctty(0); |
779 | unlock_kernel(); | 839 | tty_unlock(); |
780 | proc_clear_tty(tsk); | 840 | proc_clear_tty(tsk); |
781 | } | 841 | } |
782 | 842 | ||
@@ -875,12 +935,10 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, | |||
875 | loff_t *ppos) | 935 | loff_t *ppos) |
876 | { | 936 | { |
877 | int i; | 937 | int i; |
878 | struct tty_struct *tty; | 938 | struct inode *inode = file->f_path.dentry->d_inode; |
879 | struct inode *inode; | 939 | struct tty_struct *tty = file_tty(file); |
880 | struct tty_ldisc *ld; | 940 | struct tty_ldisc *ld; |
881 | 941 | ||
882 | tty = (struct tty_struct *)file->private_data; | ||
883 | inode = file->f_path.dentry->d_inode; | ||
884 | if (tty_paranoia_check(tty, inode, "tty_read")) | 942 | if (tty_paranoia_check(tty, inode, "tty_read")) |
885 | return -EIO; | 943 | return -EIO; |
886 | if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags))) | 944 | if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags))) |
@@ -1013,19 +1071,19 @@ out: | |||
1013 | * We don't put it into the syslog queue right now maybe in the future if | 1071 | * We don't put it into the syslog queue right now maybe in the future if |
1014 | * really needed. | 1072 | * really needed. |
1015 | * | 1073 | * |
1016 | * We must still hold the BKL and test the CLOSING flag for the moment. | 1074 | * We must still hold the BTM and test the CLOSING flag for the moment. |
1017 | */ | 1075 | */ |
1018 | 1076 | ||
1019 | void tty_write_message(struct tty_struct *tty, char *msg) | 1077 | void tty_write_message(struct tty_struct *tty, char *msg) |
1020 | { | 1078 | { |
1021 | if (tty) { | 1079 | if (tty) { |
1022 | mutex_lock(&tty->atomic_write_lock); | 1080 | mutex_lock(&tty->atomic_write_lock); |
1023 | lock_kernel(); | 1081 | tty_lock(); |
1024 | if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { | 1082 | if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { |
1025 | unlock_kernel(); | 1083 | tty_unlock(); |
1026 | tty->ops->write(tty, msg, strlen(msg)); | 1084 | tty->ops->write(tty, msg, strlen(msg)); |
1027 | } else | 1085 | } else |
1028 | unlock_kernel(); | 1086 | tty_unlock(); |
1029 | tty_write_unlock(tty); | 1087 | tty_write_unlock(tty); |
1030 | } | 1088 | } |
1031 | return; | 1089 | return; |
@@ -1051,12 +1109,11 @@ void tty_write_message(struct tty_struct *tty, char *msg) | |||
1051 | static ssize_t tty_write(struct file *file, const char __user *buf, | 1109 | static ssize_t tty_write(struct file *file, const char __user *buf, |
1052 | size_t count, loff_t *ppos) | 1110 | size_t count, loff_t *ppos) |
1053 | { | 1111 | { |
1054 | struct tty_struct *tty; | ||
1055 | struct inode *inode = file->f_path.dentry->d_inode; | 1112 | struct inode *inode = file->f_path.dentry->d_inode; |
1113 | struct tty_struct *tty = file_tty(file); | ||
1114 | struct tty_ldisc *ld; | ||
1056 | ssize_t ret; | 1115 | ssize_t ret; |
1057 | struct tty_ldisc *ld; | ||
1058 | 1116 | ||
1059 | tty = (struct tty_struct *)file->private_data; | ||
1060 | if (tty_paranoia_check(tty, inode, "tty_write")) | 1117 | if (tty_paranoia_check(tty, inode, "tty_write")) |
1061 | return -EIO; | 1118 | return -EIO; |
1062 | if (!tty || !tty->ops->write || | 1119 | if (!tty || !tty->ops->write || |
@@ -1208,18 +1265,14 @@ static int tty_driver_install_tty(struct tty_driver *driver, | |||
1208 | int ret; | 1265 | int ret; |
1209 | 1266 | ||
1210 | if (driver->ops->install) { | 1267 | if (driver->ops->install) { |
1211 | lock_kernel(); | ||
1212 | ret = driver->ops->install(driver, tty); | 1268 | ret = driver->ops->install(driver, tty); |
1213 | unlock_kernel(); | ||
1214 | return ret; | 1269 | return ret; |
1215 | } | 1270 | } |
1216 | 1271 | ||
1217 | if (tty_init_termios(tty) == 0) { | 1272 | if (tty_init_termios(tty) == 0) { |
1218 | lock_kernel(); | ||
1219 | tty_driver_kref_get(driver); | 1273 | tty_driver_kref_get(driver); |
1220 | tty->count++; | 1274 | tty->count++; |
1221 | driver->ttys[idx] = tty; | 1275 | driver->ttys[idx] = tty; |
1222 | unlock_kernel(); | ||
1223 | return 0; | 1276 | return 0; |
1224 | } | 1277 | } |
1225 | return -ENOMEM; | 1278 | return -ENOMEM; |
@@ -1312,14 +1365,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | |||
1312 | struct tty_struct *tty; | 1365 | struct tty_struct *tty; |
1313 | int retval; | 1366 | int retval; |
1314 | 1367 | ||
1315 | lock_kernel(); | ||
1316 | /* Check if pty master is being opened multiple times */ | 1368 | /* Check if pty master is being opened multiple times */ |
1317 | if (driver->subtype == PTY_TYPE_MASTER && | 1369 | if (driver->subtype == PTY_TYPE_MASTER && |
1318 | (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) { | 1370 | (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) { |
1319 | unlock_kernel(); | ||
1320 | return ERR_PTR(-EIO); | 1371 | return ERR_PTR(-EIO); |
1321 | } | 1372 | } |
1322 | unlock_kernel(); | ||
1323 | 1373 | ||
1324 | /* | 1374 | /* |
1325 | * First time open is complex, especially for PTY devices. | 1375 | * First time open is complex, especially for PTY devices. |
@@ -1363,9 +1413,7 @@ release_mem_out: | |||
1363 | if (printk_ratelimit()) | 1413 | if (printk_ratelimit()) |
1364 | printk(KERN_INFO "tty_init_dev: ldisc open failed, " | 1414 | printk(KERN_INFO "tty_init_dev: ldisc open failed, " |
1365 | "clearing slot %d\n", idx); | 1415 | "clearing slot %d\n", idx); |
1366 | lock_kernel(); | ||
1367 | release_tty(tty, idx); | 1416 | release_tty(tty, idx); |
1368 | unlock_kernel(); | ||
1369 | return ERR_PTR(retval); | 1417 | return ERR_PTR(retval); |
1370 | } | 1418 | } |
1371 | 1419 | ||
@@ -1419,10 +1467,12 @@ static void release_one_tty(struct work_struct *work) | |||
1419 | tty_driver_kref_put(driver); | 1467 | tty_driver_kref_put(driver); |
1420 | module_put(driver->owner); | 1468 | module_put(driver->owner); |
1421 | 1469 | ||
1422 | file_list_lock(); | 1470 | spin_lock(&tty_files_lock); |
1423 | list_del_init(&tty->tty_files); | 1471 | list_del_init(&tty->tty_files); |
1424 | file_list_unlock(); | 1472 | spin_unlock(&tty_files_lock); |
1425 | 1473 | ||
1474 | put_pid(tty->pgrp); | ||
1475 | put_pid(tty->session); | ||
1426 | free_tty_struct(tty); | 1476 | free_tty_struct(tty); |
1427 | } | 1477 | } |
1428 | 1478 | ||
@@ -1500,20 +1550,20 @@ static void release_tty(struct tty_struct *tty, int idx) | |||
1500 | 1550 | ||
1501 | int tty_release(struct inode *inode, struct file *filp) | 1551 | int tty_release(struct inode *inode, struct file *filp) |
1502 | { | 1552 | { |
1503 | struct tty_struct *tty, *o_tty; | 1553 | struct tty_struct *tty = file_tty(filp); |
1554 | struct tty_struct *o_tty; | ||
1504 | int pty_master, tty_closing, o_tty_closing, do_sleep; | 1555 | int pty_master, tty_closing, o_tty_closing, do_sleep; |
1505 | int devpts; | 1556 | int devpts; |
1506 | int idx; | 1557 | int idx; |
1507 | char buf[64]; | 1558 | char buf[64]; |
1508 | 1559 | ||
1509 | tty = (struct tty_struct *)filp->private_data; | ||
1510 | if (tty_paranoia_check(tty, inode, "tty_release_dev")) | 1560 | if (tty_paranoia_check(tty, inode, "tty_release_dev")) |
1511 | return 0; | 1561 | return 0; |
1512 | 1562 | ||
1513 | lock_kernel(); | 1563 | tty_lock(); |
1514 | check_tty_count(tty, "tty_release_dev"); | 1564 | check_tty_count(tty, "tty_release_dev"); |
1515 | 1565 | ||
1516 | tty_fasync(-1, filp, 0); | 1566 | __tty_fasync(-1, filp, 0); |
1517 | 1567 | ||
1518 | idx = tty->index; | 1568 | idx = tty->index; |
1519 | pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 1569 | pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
@@ -1525,18 +1575,18 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1525 | if (idx < 0 || idx >= tty->driver->num) { | 1575 | if (idx < 0 || idx >= tty->driver->num) { |
1526 | printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " | 1576 | printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " |
1527 | "free (%s)\n", tty->name); | 1577 | "free (%s)\n", tty->name); |
1528 | unlock_kernel(); | 1578 | tty_unlock(); |
1529 | return 0; | 1579 | return 0; |
1530 | } | 1580 | } |
1531 | if (!devpts) { | 1581 | if (!devpts) { |
1532 | if (tty != tty->driver->ttys[idx]) { | 1582 | if (tty != tty->driver->ttys[idx]) { |
1533 | unlock_kernel(); | 1583 | tty_unlock(); |
1534 | printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " | 1584 | printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " |
1535 | "for (%s)\n", idx, tty->name); | 1585 | "for (%s)\n", idx, tty->name); |
1536 | return 0; | 1586 | return 0; |
1537 | } | 1587 | } |
1538 | if (tty->termios != tty->driver->termios[idx]) { | 1588 | if (tty->termios != tty->driver->termios[idx]) { |
1539 | unlock_kernel(); | 1589 | tty_unlock(); |
1540 | printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " | 1590 | printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " |
1541 | "for (%s)\n", | 1591 | "for (%s)\n", |
1542 | idx, tty->name); | 1592 | idx, tty->name); |
@@ -1554,21 +1604,21 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1554 | if (tty->driver->other && | 1604 | if (tty->driver->other && |
1555 | !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { | 1605 | !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { |
1556 | if (o_tty != tty->driver->other->ttys[idx]) { | 1606 | if (o_tty != tty->driver->other->ttys[idx]) { |
1557 | unlock_kernel(); | 1607 | tty_unlock(); |
1558 | printk(KERN_DEBUG "tty_release_dev: other->table[%d] " | 1608 | printk(KERN_DEBUG "tty_release_dev: other->table[%d] " |
1559 | "not o_tty for (%s)\n", | 1609 | "not o_tty for (%s)\n", |
1560 | idx, tty->name); | 1610 | idx, tty->name); |
1561 | return 0 ; | 1611 | return 0 ; |
1562 | } | 1612 | } |
1563 | if (o_tty->termios != tty->driver->other->termios[idx]) { | 1613 | if (o_tty->termios != tty->driver->other->termios[idx]) { |
1564 | unlock_kernel(); | 1614 | tty_unlock(); |
1565 | printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " | 1615 | printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " |
1566 | "not o_termios for (%s)\n", | 1616 | "not o_termios for (%s)\n", |
1567 | idx, tty->name); | 1617 | idx, tty->name); |
1568 | return 0; | 1618 | return 0; |
1569 | } | 1619 | } |
1570 | if (o_tty->link != tty) { | 1620 | if (o_tty->link != tty) { |
1571 | unlock_kernel(); | 1621 | tty_unlock(); |
1572 | printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); | 1622 | printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); |
1573 | return 0; | 1623 | return 0; |
1574 | } | 1624 | } |
@@ -1577,7 +1627,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1577 | if (tty->ops->close) | 1627 | if (tty->ops->close) |
1578 | tty->ops->close(tty, filp); | 1628 | tty->ops->close(tty, filp); |
1579 | 1629 | ||
1580 | unlock_kernel(); | 1630 | tty_unlock(); |
1581 | /* | 1631 | /* |
1582 | * Sanity check: if tty->count is going to zero, there shouldn't be | 1632 | * Sanity check: if tty->count is going to zero, there shouldn't be |
1583 | * any waiters on tty->read_wait or tty->write_wait. We test the | 1633 | * any waiters on tty->read_wait or tty->write_wait. We test the |
@@ -1600,7 +1650,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1600 | opens on /dev/tty */ | 1650 | opens on /dev/tty */ |
1601 | 1651 | ||
1602 | mutex_lock(&tty_mutex); | 1652 | mutex_lock(&tty_mutex); |
1603 | lock_kernel(); | 1653 | tty_lock(); |
1604 | tty_closing = tty->count <= 1; | 1654 | tty_closing = tty->count <= 1; |
1605 | o_tty_closing = o_tty && | 1655 | o_tty_closing = o_tty && |
1606 | (o_tty->count <= (pty_master ? 1 : 0)); | 1656 | (o_tty->count <= (pty_master ? 1 : 0)); |
@@ -1631,7 +1681,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1631 | 1681 | ||
1632 | printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue " | 1682 | printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue " |
1633 | "active!\n", tty_name(tty, buf)); | 1683 | "active!\n", tty_name(tty, buf)); |
1634 | unlock_kernel(); | 1684 | tty_unlock(); |
1635 | mutex_unlock(&tty_mutex); | 1685 | mutex_unlock(&tty_mutex); |
1636 | schedule(); | 1686 | schedule(); |
1637 | } | 1687 | } |
@@ -1664,8 +1714,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1664 | * - do_tty_hangup no longer sees this file descriptor as | 1714 | * - do_tty_hangup no longer sees this file descriptor as |
1665 | * something that needs to be handled for hangups. | 1715 | * something that needs to be handled for hangups. |
1666 | */ | 1716 | */ |
1667 | file_kill(filp); | 1717 | tty_del_file(filp); |
1668 | filp->private_data = NULL; | ||
1669 | 1718 | ||
1670 | /* | 1719 | /* |
1671 | * Perform some housekeeping before deciding whether to return. | 1720 | * Perform some housekeeping before deciding whether to return. |
@@ -1696,7 +1745,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1696 | 1745 | ||
1697 | /* check whether both sides are closing ... */ | 1746 | /* check whether both sides are closing ... */ |
1698 | if (!tty_closing || (o_tty && !o_tty_closing)) { | 1747 | if (!tty_closing || (o_tty && !o_tty_closing)) { |
1699 | unlock_kernel(); | 1748 | tty_unlock(); |
1700 | return 0; | 1749 | return 0; |
1701 | } | 1750 | } |
1702 | 1751 | ||
@@ -1716,7 +1765,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1716 | /* Make this pty number available for reallocation */ | 1765 | /* Make this pty number available for reallocation */ |
1717 | if (devpts) | 1766 | if (devpts) |
1718 | devpts_kill_index(inode, idx); | 1767 | devpts_kill_index(inode, idx); |
1719 | unlock_kernel(); | 1768 | tty_unlock(); |
1720 | return 0; | 1769 | return 0; |
1721 | } | 1770 | } |
1722 | 1771 | ||
@@ -1758,12 +1807,12 @@ retry_open: | |||
1758 | retval = 0; | 1807 | retval = 0; |
1759 | 1808 | ||
1760 | mutex_lock(&tty_mutex); | 1809 | mutex_lock(&tty_mutex); |
1761 | lock_kernel(); | 1810 | tty_lock(); |
1762 | 1811 | ||
1763 | if (device == MKDEV(TTYAUX_MAJOR, 0)) { | 1812 | if (device == MKDEV(TTYAUX_MAJOR, 0)) { |
1764 | tty = get_current_tty(); | 1813 | tty = get_current_tty(); |
1765 | if (!tty) { | 1814 | if (!tty) { |
1766 | unlock_kernel(); | 1815 | tty_unlock(); |
1767 | mutex_unlock(&tty_mutex); | 1816 | mutex_unlock(&tty_mutex); |
1768 | return -ENXIO; | 1817 | return -ENXIO; |
1769 | } | 1818 | } |
@@ -1795,14 +1844,14 @@ retry_open: | |||
1795 | goto got_driver; | 1844 | goto got_driver; |
1796 | } | 1845 | } |
1797 | } | 1846 | } |
1798 | unlock_kernel(); | 1847 | tty_unlock(); |
1799 | mutex_unlock(&tty_mutex); | 1848 | mutex_unlock(&tty_mutex); |
1800 | return -ENODEV; | 1849 | return -ENODEV; |
1801 | } | 1850 | } |
1802 | 1851 | ||
1803 | driver = get_tty_driver(device, &index); | 1852 | driver = get_tty_driver(device, &index); |
1804 | if (!driver) { | 1853 | if (!driver) { |
1805 | unlock_kernel(); | 1854 | tty_unlock(); |
1806 | mutex_unlock(&tty_mutex); | 1855 | mutex_unlock(&tty_mutex); |
1807 | return -ENODEV; | 1856 | return -ENODEV; |
1808 | } | 1857 | } |
@@ -1812,7 +1861,7 @@ got_driver: | |||
1812 | tty = tty_driver_lookup_tty(driver, inode, index); | 1861 | tty = tty_driver_lookup_tty(driver, inode, index); |
1813 | 1862 | ||
1814 | if (IS_ERR(tty)) { | 1863 | if (IS_ERR(tty)) { |
1815 | unlock_kernel(); | 1864 | tty_unlock(); |
1816 | mutex_unlock(&tty_mutex); | 1865 | mutex_unlock(&tty_mutex); |
1817 | return PTR_ERR(tty); | 1866 | return PTR_ERR(tty); |
1818 | } | 1867 | } |
@@ -1828,12 +1877,16 @@ got_driver: | |||
1828 | mutex_unlock(&tty_mutex); | 1877 | mutex_unlock(&tty_mutex); |
1829 | tty_driver_kref_put(driver); | 1878 | tty_driver_kref_put(driver); |
1830 | if (IS_ERR(tty)) { | 1879 | if (IS_ERR(tty)) { |
1831 | unlock_kernel(); | 1880 | tty_unlock(); |
1832 | return PTR_ERR(tty); | 1881 | return PTR_ERR(tty); |
1833 | } | 1882 | } |
1834 | 1883 | ||
1835 | filp->private_data = tty; | 1884 | retval = tty_add_file(tty, filp); |
1836 | file_move(filp, &tty->tty_files); | 1885 | if (retval) { |
1886 | tty_unlock(); | ||
1887 | return retval; | ||
1888 | } | ||
1889 | |||
1837 | check_tty_count(tty, "tty_open"); | 1890 | check_tty_count(tty, "tty_open"); |
1838 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 1891 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
1839 | tty->driver->subtype == PTY_TYPE_MASTER) | 1892 | tty->driver->subtype == PTY_TYPE_MASTER) |
@@ -1858,28 +1911,29 @@ got_driver: | |||
1858 | printk(KERN_DEBUG "error %d in opening %s...", retval, | 1911 | printk(KERN_DEBUG "error %d in opening %s...", retval, |
1859 | tty->name); | 1912 | tty->name); |
1860 | #endif | 1913 | #endif |
1914 | tty_unlock(); /* need to call tty_release without BTM */ | ||
1861 | tty_release(inode, filp); | 1915 | tty_release(inode, filp); |
1862 | if (retval != -ERESTARTSYS) { | 1916 | if (retval != -ERESTARTSYS) |
1863 | unlock_kernel(); | ||
1864 | return retval; | 1917 | return retval; |
1865 | } | 1918 | |
1866 | if (signal_pending(current)) { | 1919 | if (signal_pending(current)) |
1867 | unlock_kernel(); | ||
1868 | return retval; | 1920 | return retval; |
1869 | } | 1921 | |
1870 | schedule(); | 1922 | schedule(); |
1871 | /* | 1923 | /* |
1872 | * Need to reset f_op in case a hangup happened. | 1924 | * Need to reset f_op in case a hangup happened. |
1873 | */ | 1925 | */ |
1926 | tty_lock(); | ||
1874 | if (filp->f_op == &hung_up_tty_fops) | 1927 | if (filp->f_op == &hung_up_tty_fops) |
1875 | filp->f_op = &tty_fops; | 1928 | filp->f_op = &tty_fops; |
1929 | tty_unlock(); | ||
1876 | goto retry_open; | 1930 | goto retry_open; |
1877 | } | 1931 | } |
1878 | unlock_kernel(); | 1932 | tty_unlock(); |
1879 | 1933 | ||
1880 | 1934 | ||
1881 | mutex_lock(&tty_mutex); | 1935 | mutex_lock(&tty_mutex); |
1882 | lock_kernel(); | 1936 | tty_lock(); |
1883 | spin_lock_irq(¤t->sighand->siglock); | 1937 | spin_lock_irq(¤t->sighand->siglock); |
1884 | if (!noctty && | 1938 | if (!noctty && |
1885 | current->signal->leader && | 1939 | current->signal->leader && |
@@ -1887,7 +1941,7 @@ got_driver: | |||
1887 | tty->session == NULL) | 1941 | tty->session == NULL) |
1888 | __proc_set_tty(current, tty); | 1942 | __proc_set_tty(current, tty); |
1889 | spin_unlock_irq(¤t->sighand->siglock); | 1943 | spin_unlock_irq(¤t->sighand->siglock); |
1890 | unlock_kernel(); | 1944 | tty_unlock(); |
1891 | mutex_unlock(&tty_mutex); | 1945 | mutex_unlock(&tty_mutex); |
1892 | return 0; | 1946 | return 0; |
1893 | } | 1947 | } |
@@ -1908,11 +1962,10 @@ got_driver: | |||
1908 | 1962 | ||
1909 | static unsigned int tty_poll(struct file *filp, poll_table *wait) | 1963 | static unsigned int tty_poll(struct file *filp, poll_table *wait) |
1910 | { | 1964 | { |
1911 | struct tty_struct *tty; | 1965 | struct tty_struct *tty = file_tty(filp); |
1912 | struct tty_ldisc *ld; | 1966 | struct tty_ldisc *ld; |
1913 | int ret = 0; | 1967 | int ret = 0; |
1914 | 1968 | ||
1915 | tty = (struct tty_struct *)filp->private_data; | ||
1916 | if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll")) | 1969 | if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll")) |
1917 | return 0; | 1970 | return 0; |
1918 | 1971 | ||
@@ -1923,14 +1976,12 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) | |||
1923 | return ret; | 1976 | return ret; |
1924 | } | 1977 | } |
1925 | 1978 | ||
1926 | static int tty_fasync(int fd, struct file *filp, int on) | 1979 | static int __tty_fasync(int fd, struct file *filp, int on) |
1927 | { | 1980 | { |
1928 | struct tty_struct *tty; | 1981 | struct tty_struct *tty = file_tty(filp); |
1929 | unsigned long flags; | 1982 | unsigned long flags; |
1930 | int retval = 0; | 1983 | int retval = 0; |
1931 | 1984 | ||
1932 | lock_kernel(); | ||
1933 | tty = (struct tty_struct *)filp->private_data; | ||
1934 | if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync")) | 1985 | if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync")) |
1935 | goto out; | 1986 | goto out; |
1936 | 1987 | ||
@@ -1951,8 +2002,10 @@ static int tty_fasync(int fd, struct file *filp, int on) | |||
1951 | pid = task_pid(current); | 2002 | pid = task_pid(current); |
1952 | type = PIDTYPE_PID; | 2003 | type = PIDTYPE_PID; |
1953 | } | 2004 | } |
1954 | retval = __f_setown(filp, pid, type, 0); | 2005 | get_pid(pid); |
1955 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 2006 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
2007 | retval = __f_setown(filp, pid, type, 0); | ||
2008 | put_pid(pid); | ||
1956 | if (retval) | 2009 | if (retval) |
1957 | goto out; | 2010 | goto out; |
1958 | } else { | 2011 | } else { |
@@ -1961,7 +2014,15 @@ static int tty_fasync(int fd, struct file *filp, int on) | |||
1961 | } | 2014 | } |
1962 | retval = 0; | 2015 | retval = 0; |
1963 | out: | 2016 | out: |
1964 | unlock_kernel(); | 2017 | return retval; |
2018 | } | ||
2019 | |||
2020 | static int tty_fasync(int fd, struct file *filp, int on) | ||
2021 | { | ||
2022 | int retval; | ||
2023 | tty_lock(); | ||
2024 | retval = __tty_fasync(fd, filp, on); | ||
2025 | tty_unlock(); | ||
1965 | return retval; | 2026 | return retval; |
1966 | } | 2027 | } |
1967 | 2028 | ||
@@ -2026,7 +2087,7 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg) | |||
2026 | * @rows: rows (character) | 2087 | * @rows: rows (character) |
2027 | * @cols: cols (character) | 2088 | * @cols: cols (character) |
2028 | * | 2089 | * |
2029 | * Update the termios variables and send the neccessary signals to | 2090 | * Update the termios variables and send the necessary signals to |
2030 | * peform a terminal resize correctly | 2091 | * peform a terminal resize correctly |
2031 | */ | 2092 | */ |
2032 | 2093 | ||
@@ -2451,6 +2512,20 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int | |||
2451 | return tty->ops->tiocmset(tty, file, set, clear); | 2512 | return tty->ops->tiocmset(tty, file, set, clear); |
2452 | } | 2513 | } |
2453 | 2514 | ||
2515 | static int tty_tiocgicount(struct tty_struct *tty, void __user *arg) | ||
2516 | { | ||
2517 | int retval = -EINVAL; | ||
2518 | struct serial_icounter_struct icount; | ||
2519 | memset(&icount, 0, sizeof(icount)); | ||
2520 | if (tty->ops->get_icount) | ||
2521 | retval = tty->ops->get_icount(tty, &icount); | ||
2522 | if (retval != 0) | ||
2523 | return retval; | ||
2524 | if (copy_to_user(arg, &icount, sizeof(icount))) | ||
2525 | return -EFAULT; | ||
2526 | return 0; | ||
2527 | } | ||
2528 | |||
2454 | struct tty_struct *tty_pair_get_tty(struct tty_struct *tty) | 2529 | struct tty_struct *tty_pair_get_tty(struct tty_struct *tty) |
2455 | { | 2530 | { |
2456 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 2531 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
@@ -2474,13 +2549,13 @@ EXPORT_SYMBOL(tty_pair_get_pty); | |||
2474 | */ | 2549 | */ |
2475 | long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 2550 | long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
2476 | { | 2551 | { |
2477 | struct tty_struct *tty, *real_tty; | 2552 | struct tty_struct *tty = file_tty(file); |
2553 | struct tty_struct *real_tty; | ||
2478 | void __user *p = (void __user *)arg; | 2554 | void __user *p = (void __user *)arg; |
2479 | int retval; | 2555 | int retval; |
2480 | struct tty_ldisc *ld; | 2556 | struct tty_ldisc *ld; |
2481 | struct inode *inode = file->f_dentry->d_inode; | 2557 | struct inode *inode = file->f_dentry->d_inode; |
2482 | 2558 | ||
2483 | tty = (struct tty_struct *)file->private_data; | ||
2484 | if (tty_paranoia_check(tty, inode, "tty_ioctl")) | 2559 | if (tty_paranoia_check(tty, inode, "tty_ioctl")) |
2485 | return -EINVAL; | 2560 | return -EINVAL; |
2486 | 2561 | ||
@@ -2571,6 +2646,12 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
2571 | case TIOCMBIC: | 2646 | case TIOCMBIC: |
2572 | case TIOCMBIS: | 2647 | case TIOCMBIS: |
2573 | return tty_tiocmset(tty, file, cmd, p); | 2648 | return tty_tiocmset(tty, file, cmd, p); |
2649 | case TIOCGICOUNT: | ||
2650 | retval = tty_tiocgicount(tty, p); | ||
2651 | /* For the moment allow fall through to the old method */ | ||
2652 | if (retval != -EINVAL) | ||
2653 | return retval; | ||
2654 | break; | ||
2574 | case TCFLSH: | 2655 | case TCFLSH: |
2575 | switch (arg) { | 2656 | switch (arg) { |
2576 | case TCIFLUSH: | 2657 | case TCIFLUSH: |
@@ -2602,7 +2683,7 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, | |||
2602 | unsigned long arg) | 2683 | unsigned long arg) |
2603 | { | 2684 | { |
2604 | struct inode *inode = file->f_dentry->d_inode; | 2685 | struct inode *inode = file->f_dentry->d_inode; |
2605 | struct tty_struct *tty = file->private_data; | 2686 | struct tty_struct *tty = file_tty(file); |
2606 | struct tty_ldisc *ld; | 2687 | struct tty_ldisc *ld; |
2607 | int retval = -ENOIOCTLCMD; | 2688 | int retval = -ENOIOCTLCMD; |
2608 | 2689 | ||
@@ -2694,7 +2775,7 @@ void __do_SAK(struct tty_struct *tty) | |||
2694 | if (!filp) | 2775 | if (!filp) |
2695 | continue; | 2776 | continue; |
2696 | if (filp->f_op->read == tty_read && | 2777 | if (filp->f_op->read == tty_read && |
2697 | filp->private_data == tty) { | 2778 | file_tty(filp) == tty) { |
2698 | printk(KERN_NOTICE "SAK: killed process %d" | 2779 | printk(KERN_NOTICE "SAK: killed process %d" |
2699 | " (%s): fd#%d opened to the tty\n", | 2780 | " (%s): fd#%d opened to the tty\n", |
2700 | task_pid_nr(p), p->comm, i); | 2781 | task_pid_nr(p), p->comm, i); |
@@ -2732,6 +2813,20 @@ void do_SAK(struct tty_struct *tty) | |||
2732 | 2813 | ||
2733 | EXPORT_SYMBOL(do_SAK); | 2814 | EXPORT_SYMBOL(do_SAK); |
2734 | 2815 | ||
2816 | static int dev_match_devt(struct device *dev, void *data) | ||
2817 | { | ||
2818 | dev_t *devt = data; | ||
2819 | return dev->devt == *devt; | ||
2820 | } | ||
2821 | |||
2822 | /* Must put_device() after it's unused! */ | ||
2823 | static struct device *tty_get_device(struct tty_struct *tty) | ||
2824 | { | ||
2825 | dev_t devt = tty_devnum(tty); | ||
2826 | return class_find_device(tty_class, NULL, &devt, dev_match_devt); | ||
2827 | } | ||
2828 | |||
2829 | |||
2735 | /** | 2830 | /** |
2736 | * initialize_tty_struct | 2831 | * initialize_tty_struct |
2737 | * @tty: tty to initialize | 2832 | * @tty: tty to initialize |
@@ -2772,6 +2867,7 @@ void initialize_tty_struct(struct tty_struct *tty, | |||
2772 | tty->ops = driver->ops; | 2867 | tty->ops = driver->ops; |
2773 | tty->index = idx; | 2868 | tty->index = idx; |
2774 | tty_line_name(driver, idx, tty->name); | 2869 | tty_line_name(driver, idx, tty->name); |
2870 | tty->dev = tty_get_device(tty); | ||
2775 | } | 2871 | } |
2776 | 2872 | ||
2777 | /** | 2873 | /** |
@@ -2929,6 +3025,7 @@ int tty_register_driver(struct tty_driver *driver) | |||
2929 | int i; | 3025 | int i; |
2930 | dev_t dev; | 3026 | dev_t dev; |
2931 | void **p = NULL; | 3027 | void **p = NULL; |
3028 | struct device *d; | ||
2932 | 3029 | ||
2933 | if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) { | 3030 | if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) { |
2934 | p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL); | 3031 | p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL); |
@@ -2976,12 +3073,31 @@ int tty_register_driver(struct tty_driver *driver) | |||
2976 | mutex_unlock(&tty_mutex); | 3073 | mutex_unlock(&tty_mutex); |
2977 | 3074 | ||
2978 | if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) { | 3075 | if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) { |
2979 | for (i = 0; i < driver->num; i++) | 3076 | for (i = 0; i < driver->num; i++) { |
2980 | tty_register_device(driver, i, NULL); | 3077 | d = tty_register_device(driver, i, NULL); |
3078 | if (IS_ERR(d)) { | ||
3079 | error = PTR_ERR(d); | ||
3080 | goto err; | ||
3081 | } | ||
3082 | } | ||
2981 | } | 3083 | } |
2982 | proc_tty_register_driver(driver); | 3084 | proc_tty_register_driver(driver); |
2983 | driver->flags |= TTY_DRIVER_INSTALLED; | 3085 | driver->flags |= TTY_DRIVER_INSTALLED; |
2984 | return 0; | 3086 | return 0; |
3087 | |||
3088 | err: | ||
3089 | for (i--; i >= 0; i--) | ||
3090 | tty_unregister_device(driver, i); | ||
3091 | |||
3092 | mutex_lock(&tty_mutex); | ||
3093 | list_del(&driver->tty_drivers); | ||
3094 | mutex_unlock(&tty_mutex); | ||
3095 | |||
3096 | unregister_chrdev_region(dev, driver->num); | ||
3097 | driver->ttys = NULL; | ||
3098 | driver->termios = NULL; | ||
3099 | kfree(p); | ||
3100 | return error; | ||
2985 | } | 3101 | } |
2986 | 3102 | ||
2987 | EXPORT_SYMBOL(tty_register_driver); | 3103 | EXPORT_SYMBOL(tty_register_driver); |
@@ -3123,7 +3239,7 @@ static struct cdev tty_cdev, console_cdev; | |||
3123 | * Ok, now we can initialize the rest of the tty devices and can count | 3239 | * Ok, now we can initialize the rest of the tty devices and can count |
3124 | * on memory allocations, interrupts etc.. | 3240 | * on memory allocations, interrupts etc.. |
3125 | */ | 3241 | */ |
3126 | static int __init tty_init(void) | 3242 | int __init tty_init(void) |
3127 | { | 3243 | { |
3128 | cdev_init(&tty_cdev, &tty_fops); | 3244 | cdev_init(&tty_cdev, &tty_fops); |
3129 | if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) || | 3245 | if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) || |
@@ -3144,4 +3260,4 @@ static int __init tty_init(void) | |||
3144 | #endif | 3260 | #endif |
3145 | return 0; | 3261 | return 0; |
3146 | } | 3262 | } |
3147 | module_init(tty_init); | 3263 | |
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 6bd5f8866c74..0c1889971459 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c | |||
@@ -517,19 +517,25 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios) | |||
517 | 517 | ||
518 | /* See if packet mode change of state. */ | 518 | /* See if packet mode change of state. */ |
519 | if (tty->link && tty->link->packet) { | 519 | if (tty->link && tty->link->packet) { |
520 | int extproc = (old_termios.c_lflag & EXTPROC) | | ||
521 | (tty->termios->c_lflag & EXTPROC); | ||
520 | int old_flow = ((old_termios.c_iflag & IXON) && | 522 | int old_flow = ((old_termios.c_iflag & IXON) && |
521 | (old_termios.c_cc[VSTOP] == '\023') && | 523 | (old_termios.c_cc[VSTOP] == '\023') && |
522 | (old_termios.c_cc[VSTART] == '\021')); | 524 | (old_termios.c_cc[VSTART] == '\021')); |
523 | int new_flow = (I_IXON(tty) && | 525 | int new_flow = (I_IXON(tty) && |
524 | STOP_CHAR(tty) == '\023' && | 526 | STOP_CHAR(tty) == '\023' && |
525 | START_CHAR(tty) == '\021'); | 527 | START_CHAR(tty) == '\021'); |
526 | if (old_flow != new_flow) { | 528 | if ((old_flow != new_flow) || extproc) { |
527 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 529 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
528 | tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); | 530 | if (old_flow != new_flow) { |
529 | if (new_flow) | 531 | tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); |
530 | tty->ctrl_status |= TIOCPKT_DOSTOP; | 532 | if (new_flow) |
531 | else | 533 | tty->ctrl_status |= TIOCPKT_DOSTOP; |
532 | tty->ctrl_status |= TIOCPKT_NOSTOP; | 534 | else |
535 | tty->ctrl_status |= TIOCPKT_NOSTOP; | ||
536 | } | ||
537 | if (extproc) | ||
538 | tty->ctrl_status |= TIOCPKT_IOCTL; | ||
533 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 539 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
534 | wake_up_interruptible(&tty->link->read_wait); | 540 | wake_up_interruptible(&tty->link->read_wait); |
535 | } | 541 | } |
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index 3f653f7d849f..412f9775d19c 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c | |||
@@ -440,6 +440,8 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) | |||
440 | * | 440 | * |
441 | * A helper opening method. Also a convenient debugging and check | 441 | * A helper opening method. Also a convenient debugging and check |
442 | * point. | 442 | * point. |
443 | * | ||
444 | * Locking: always called with BTM already held. | ||
443 | */ | 445 | */ |
444 | 446 | ||
445 | static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) | 447 | static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) |
@@ -447,10 +449,9 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) | |||
447 | WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); | 449 | WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); |
448 | if (ld->ops->open) { | 450 | if (ld->ops->open) { |
449 | int ret; | 451 | int ret; |
450 | /* BKL here locks verus a hangup event */ | 452 | /* BTM here locks versus a hangup event */ |
451 | lock_kernel(); | 453 | WARN_ON(!tty_locked()); |
452 | ret = ld->ops->open(tty); | 454 | ret = ld->ops->open(tty); |
453 | unlock_kernel(); | ||
454 | return ret; | 455 | return ret; |
455 | } | 456 | } |
456 | return 0; | 457 | return 0; |
@@ -553,7 +554,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
553 | if (IS_ERR(new_ldisc)) | 554 | if (IS_ERR(new_ldisc)) |
554 | return PTR_ERR(new_ldisc); | 555 | return PTR_ERR(new_ldisc); |
555 | 556 | ||
556 | lock_kernel(); | 557 | tty_lock(); |
557 | /* | 558 | /* |
558 | * We need to look at the tty locking here for pty/tty pairs | 559 | * We need to look at the tty locking here for pty/tty pairs |
559 | * when both sides try to change in parallel. | 560 | * when both sides try to change in parallel. |
@@ -567,12 +568,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
567 | */ | 568 | */ |
568 | 569 | ||
569 | if (tty->ldisc->ops->num == ldisc) { | 570 | if (tty->ldisc->ops->num == ldisc) { |
570 | unlock_kernel(); | 571 | tty_unlock(); |
571 | tty_ldisc_put(new_ldisc); | 572 | tty_ldisc_put(new_ldisc); |
572 | return 0; | 573 | return 0; |
573 | } | 574 | } |
574 | 575 | ||
575 | unlock_kernel(); | 576 | tty_unlock(); |
576 | /* | 577 | /* |
577 | * Problem: What do we do if this blocks ? | 578 | * Problem: What do we do if this blocks ? |
578 | * We could deadlock here | 579 | * We could deadlock here |
@@ -580,6 +581,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
580 | 581 | ||
581 | tty_wait_until_sent(tty, 0); | 582 | tty_wait_until_sent(tty, 0); |
582 | 583 | ||
584 | tty_lock(); | ||
583 | mutex_lock(&tty->ldisc_mutex); | 585 | mutex_lock(&tty->ldisc_mutex); |
584 | 586 | ||
585 | /* | 587 | /* |
@@ -589,13 +591,13 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
589 | 591 | ||
590 | while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { | 592 | while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { |
591 | mutex_unlock(&tty->ldisc_mutex); | 593 | mutex_unlock(&tty->ldisc_mutex); |
594 | tty_unlock(); | ||
592 | wait_event(tty_ldisc_wait, | 595 | wait_event(tty_ldisc_wait, |
593 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); | 596 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); |
597 | tty_lock(); | ||
594 | mutex_lock(&tty->ldisc_mutex); | 598 | mutex_lock(&tty->ldisc_mutex); |
595 | } | 599 | } |
596 | 600 | ||
597 | lock_kernel(); | ||
598 | |||
599 | set_bit(TTY_LDISC_CHANGING, &tty->flags); | 601 | set_bit(TTY_LDISC_CHANGING, &tty->flags); |
600 | 602 | ||
601 | /* | 603 | /* |
@@ -607,7 +609,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
607 | 609 | ||
608 | o_ldisc = tty->ldisc; | 610 | o_ldisc = tty->ldisc; |
609 | 611 | ||
610 | unlock_kernel(); | 612 | tty_unlock(); |
611 | /* | 613 | /* |
612 | * Make sure we don't change while someone holds a | 614 | * Make sure we don't change while someone holds a |
613 | * reference to the line discipline. The TTY_LDISC bit | 615 | * reference to the line discipline. The TTY_LDISC bit |
@@ -632,15 +634,15 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
632 | 634 | ||
633 | flush_scheduled_work(); | 635 | flush_scheduled_work(); |
634 | 636 | ||
637 | tty_lock(); | ||
635 | mutex_lock(&tty->ldisc_mutex); | 638 | mutex_lock(&tty->ldisc_mutex); |
636 | lock_kernel(); | ||
637 | if (test_bit(TTY_HUPPED, &tty->flags)) { | 639 | if (test_bit(TTY_HUPPED, &tty->flags)) { |
638 | /* We were raced by the hangup method. It will have stomped | 640 | /* We were raced by the hangup method. It will have stomped |
639 | the ldisc data and closed the ldisc down */ | 641 | the ldisc data and closed the ldisc down */ |
640 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | 642 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); |
641 | mutex_unlock(&tty->ldisc_mutex); | 643 | mutex_unlock(&tty->ldisc_mutex); |
642 | tty_ldisc_put(new_ldisc); | 644 | tty_ldisc_put(new_ldisc); |
643 | unlock_kernel(); | 645 | tty_unlock(); |
644 | return -EIO; | 646 | return -EIO; |
645 | } | 647 | } |
646 | 648 | ||
@@ -682,7 +684,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
682 | if (o_work) | 684 | if (o_work) |
683 | schedule_delayed_work(&o_tty->buf.work, 1); | 685 | schedule_delayed_work(&o_tty->buf.work, 1); |
684 | mutex_unlock(&tty->ldisc_mutex); | 686 | mutex_unlock(&tty->ldisc_mutex); |
685 | unlock_kernel(); | 687 | tty_unlock(); |
686 | return retval; | 688 | return retval; |
687 | } | 689 | } |
688 | 690 | ||
@@ -706,12 +708,13 @@ static void tty_reset_termios(struct tty_struct *tty) | |||
706 | /** | 708 | /** |
707 | * tty_ldisc_reinit - reinitialise the tty ldisc | 709 | * tty_ldisc_reinit - reinitialise the tty ldisc |
708 | * @tty: tty to reinit | 710 | * @tty: tty to reinit |
711 | * @ldisc: line discipline to reinitialize | ||
709 | * | 712 | * |
710 | * Switch the tty back to N_TTY line discipline and leave the | 713 | * Switch the tty to a line discipline and leave the ldisc |
711 | * ldisc state closed | 714 | * state closed |
712 | */ | 715 | */ |
713 | 716 | ||
714 | static void tty_ldisc_reinit(struct tty_struct *tty) | 717 | static void tty_ldisc_reinit(struct tty_struct *tty, int ldisc) |
715 | { | 718 | { |
716 | struct tty_ldisc *ld; | 719 | struct tty_ldisc *ld; |
717 | 720 | ||
@@ -721,10 +724,10 @@ static void tty_ldisc_reinit(struct tty_struct *tty) | |||
721 | /* | 724 | /* |
722 | * Switch the line discipline back | 725 | * Switch the line discipline back |
723 | */ | 726 | */ |
724 | ld = tty_ldisc_get(N_TTY); | 727 | ld = tty_ldisc_get(ldisc); |
725 | BUG_ON(IS_ERR(ld)); | 728 | BUG_ON(IS_ERR(ld)); |
726 | tty_ldisc_assign(tty, ld); | 729 | tty_ldisc_assign(tty, ld); |
727 | tty_set_termios_ldisc(tty, N_TTY); | 730 | tty_set_termios_ldisc(tty, ldisc); |
728 | } | 731 | } |
729 | 732 | ||
730 | /** | 733 | /** |
@@ -745,6 +748,8 @@ static void tty_ldisc_reinit(struct tty_struct *tty) | |||
745 | void tty_ldisc_hangup(struct tty_struct *tty) | 748 | void tty_ldisc_hangup(struct tty_struct *tty) |
746 | { | 749 | { |
747 | struct tty_ldisc *ld; | 750 | struct tty_ldisc *ld; |
751 | int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS; | ||
752 | int err = 0; | ||
748 | 753 | ||
749 | /* | 754 | /* |
750 | * FIXME! What are the locking issues here? This may me overdoing | 755 | * FIXME! What are the locking issues here? This may me overdoing |
@@ -772,25 +777,45 @@ void tty_ldisc_hangup(struct tty_struct *tty) | |||
772 | wake_up_interruptible_poll(&tty->read_wait, POLLIN); | 777 | wake_up_interruptible_poll(&tty->read_wait, POLLIN); |
773 | /* | 778 | /* |
774 | * Shutdown the current line discipline, and reset it to | 779 | * Shutdown the current line discipline, and reset it to |
775 | * N_TTY. | 780 | * N_TTY if need be. |
781 | * | ||
782 | * Avoid racing set_ldisc or tty_ldisc_release | ||
776 | */ | 783 | */ |
777 | if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { | 784 | mutex_lock(&tty->ldisc_mutex); |
778 | /* Avoid racing set_ldisc or tty_ldisc_release */ | 785 | |
779 | mutex_lock(&tty->ldisc_mutex); | 786 | /* |
780 | tty_ldisc_halt(tty); | 787 | * this is like tty_ldisc_halt, but we need to give up |
781 | if (tty->ldisc) { /* Not yet closed */ | 788 | * the BTM before calling cancel_delayed_work_sync, |
782 | /* Switch back to N_TTY */ | 789 | * which may need to wait for another function taking the BTM |
783 | tty_ldisc_reinit(tty); | 790 | */ |
784 | /* At this point we have a closed ldisc and we want to | 791 | clear_bit(TTY_LDISC, &tty->flags); |
785 | reopen it. We could defer this to the next open but | 792 | tty_unlock(); |
786 | it means auditing a lot of other paths so this is | 793 | cancel_delayed_work_sync(&tty->buf.work); |
787 | a FIXME */ | 794 | mutex_unlock(&tty->ldisc_mutex); |
795 | |||
796 | tty_lock(); | ||
797 | mutex_lock(&tty->ldisc_mutex); | ||
798 | |||
799 | /* At this point we have a closed ldisc and we want to | ||
800 | reopen it. We could defer this to the next open but | ||
801 | it means auditing a lot of other paths so this is | ||
802 | a FIXME */ | ||
803 | if (tty->ldisc) { /* Not yet closed */ | ||
804 | if (reset == 0) { | ||
805 | tty_ldisc_reinit(tty, tty->termios->c_line); | ||
806 | err = tty_ldisc_open(tty, tty->ldisc); | ||
807 | } | ||
808 | /* If the re-open fails or we reset then go to N_TTY. The | ||
809 | N_TTY open cannot fail */ | ||
810 | if (reset || err) { | ||
811 | tty_ldisc_reinit(tty, N_TTY); | ||
788 | WARN_ON(tty_ldisc_open(tty, tty->ldisc)); | 812 | WARN_ON(tty_ldisc_open(tty, tty->ldisc)); |
789 | tty_ldisc_enable(tty); | ||
790 | } | 813 | } |
791 | mutex_unlock(&tty->ldisc_mutex); | 814 | tty_ldisc_enable(tty); |
792 | tty_reset_termios(tty); | ||
793 | } | 815 | } |
816 | mutex_unlock(&tty->ldisc_mutex); | ||
817 | if (reset) | ||
818 | tty_reset_termios(tty); | ||
794 | } | 819 | } |
795 | 820 | ||
796 | /** | 821 | /** |
@@ -841,8 +866,10 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | |||
841 | * race with the set_ldisc code path. | 866 | * race with the set_ldisc code path. |
842 | */ | 867 | */ |
843 | 868 | ||
869 | tty_unlock(); | ||
844 | tty_ldisc_halt(tty); | 870 | tty_ldisc_halt(tty); |
845 | flush_scheduled_work(); | 871 | flush_scheduled_work(); |
872 | tty_lock(); | ||
846 | 873 | ||
847 | mutex_lock(&tty->ldisc_mutex); | 874 | mutex_lock(&tty->ldisc_mutex); |
848 | /* | 875 | /* |
diff --git a/drivers/char/tty_mutex.c b/drivers/char/tty_mutex.c new file mode 100644 index 000000000000..133697540c73 --- /dev/null +++ b/drivers/char/tty_mutex.c | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * drivers/char/tty_lock.c | ||
3 | */ | ||
4 | #include <linux/tty.h> | ||
5 | #include <linux/module.h> | ||
6 | #include <linux/kallsyms.h> | ||
7 | #include <linux/semaphore.h> | ||
8 | #include <linux/sched.h> | ||
9 | |||
10 | /* | ||
11 | * The 'big tty mutex' | ||
12 | * | ||
13 | * This mutex is taken and released by tty_lock() and tty_unlock(), | ||
14 | * replacing the older big kernel lock. | ||
15 | * It can no longer be taken recursively, and does not get | ||
16 | * released implicitly while sleeping. | ||
17 | * | ||
18 | * Don't use in new code. | ||
19 | */ | ||
20 | static DEFINE_MUTEX(big_tty_mutex); | ||
21 | struct task_struct *__big_tty_mutex_owner; | ||
22 | EXPORT_SYMBOL_GPL(__big_tty_mutex_owner); | ||
23 | |||
24 | /* | ||
25 | * Getting the big tty mutex. | ||
26 | */ | ||
27 | void __lockfunc tty_lock(void) | ||
28 | { | ||
29 | struct task_struct *task = current; | ||
30 | |||
31 | WARN_ON(__big_tty_mutex_owner == task); | ||
32 | |||
33 | mutex_lock(&big_tty_mutex); | ||
34 | __big_tty_mutex_owner = task; | ||
35 | } | ||
36 | EXPORT_SYMBOL(tty_lock); | ||
37 | |||
38 | void __lockfunc tty_unlock(void) | ||
39 | { | ||
40 | struct task_struct *task = current; | ||
41 | |||
42 | WARN_ON(__big_tty_mutex_owner != task); | ||
43 | __big_tty_mutex_owner = NULL; | ||
44 | |||
45 | mutex_unlock(&big_tty_mutex); | ||
46 | } | ||
47 | EXPORT_SYMBOL(tty_unlock); | ||
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c index be492dd66437..33d37d230f8f 100644 --- a/drivers/char/tty_port.c +++ b/drivers/char/tty_port.c | |||
@@ -119,7 +119,7 @@ EXPORT_SYMBOL(tty_port_tty_set); | |||
119 | static void tty_port_shutdown(struct tty_port *port) | 119 | static void tty_port_shutdown(struct tty_port *port) |
120 | { | 120 | { |
121 | mutex_lock(&port->mutex); | 121 | mutex_lock(&port->mutex); |
122 | if (port->ops->shutdown && | 122 | if (port->ops->shutdown && !port->console && |
123 | test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) | 123 | test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) |
124 | port->ops->shutdown(port); | 124 | port->ops->shutdown(port); |
125 | mutex_unlock(&port->mutex); | 125 | mutex_unlock(&port->mutex); |
@@ -231,7 +231,7 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
231 | 231 | ||
232 | /* block if port is in the process of being closed */ | 232 | /* block if port is in the process of being closed */ |
233 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { | 233 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { |
234 | wait_event_interruptible(port->close_wait, | 234 | wait_event_interruptible_tty(port->close_wait, |
235 | !(port->flags & ASYNC_CLOSING)); | 235 | !(port->flags & ASYNC_CLOSING)); |
236 | if (port->flags & ASYNC_HUP_NOTIFY) | 236 | if (port->flags & ASYNC_HUP_NOTIFY) |
237 | return -EAGAIN; | 237 | return -EAGAIN; |
@@ -294,7 +294,9 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
294 | retval = -ERESTARTSYS; | 294 | retval = -ERESTARTSYS; |
295 | break; | 295 | break; |
296 | } | 296 | } |
297 | tty_unlock(); | ||
297 | schedule(); | 298 | schedule(); |
299 | tty_lock(); | ||
298 | } | 300 | } |
299 | finish_wait(&port->open_wait, &wait); | 301 | finish_wait(&port->open_wait, &wait); |
300 | 302 | ||
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c new file mode 100644 index 000000000000..c40c1612c8a7 --- /dev/null +++ b/drivers/char/ttyprintk.c | |||
@@ -0,0 +1,225 @@ | |||
1 | /* | ||
2 | * linux/drivers/char/ttyprintk.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Samo Pogacnik | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the smems of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; version 2 of the License. | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * This pseudo device allows user to make printk messages. It is possible | ||
13 | * to store "console" messages inline with kernel messages for better analyses | ||
14 | * of the boot process, for example. | ||
15 | */ | ||
16 | |||
17 | #include <linux/device.h> | ||
18 | #include <linux/serial.h> | ||
19 | #include <linux/tty.h> | ||
20 | |||
21 | struct ttyprintk_port { | ||
22 | struct tty_port port; | ||
23 | struct mutex port_write_mutex; | ||
24 | }; | ||
25 | |||
26 | static struct ttyprintk_port tpk_port; | ||
27 | |||
28 | /* | ||
29 | * Our simple preformatting supports transparent output of (time-stamped) | ||
30 | * printk messages (also suitable for logging service): | ||
31 | * - any cr is replaced by nl | ||
32 | * - adds a ttyprintk source tag in front of each line | ||
33 | * - too long message is fragmeted, with '\'nl between fragments | ||
34 | * - TPK_STR_SIZE isn't really the write_room limiting factor, bcause | ||
35 | * it is emptied on the fly during preformatting. | ||
36 | */ | ||
37 | #define TPK_STR_SIZE 508 /* should be bigger then max expected line length */ | ||
38 | #define TPK_MAX_ROOM 4096 /* we could assume 4K for instance */ | ||
39 | static const char *tpk_tag = "[U] "; /* U for User */ | ||
40 | static int tpk_curr; | ||
41 | |||
42 | static int tpk_printk(const unsigned char *buf, int count) | ||
43 | { | ||
44 | static char tmp[TPK_STR_SIZE + 4]; | ||
45 | int i = tpk_curr; | ||
46 | |||
47 | if (buf == NULL) { | ||
48 | /* flush tmp[] */ | ||
49 | if (tpk_curr > 0) { | ||
50 | /* non nl or cr terminated message - add nl */ | ||
51 | tmp[tpk_curr + 0] = '\n'; | ||
52 | tmp[tpk_curr + 1] = '\0'; | ||
53 | printk(KERN_INFO "%s%s", tpk_tag, tmp); | ||
54 | tpk_curr = 0; | ||
55 | } | ||
56 | return i; | ||
57 | } | ||
58 | |||
59 | for (i = 0; i < count; i++) { | ||
60 | tmp[tpk_curr] = buf[i]; | ||
61 | if (tpk_curr < TPK_STR_SIZE) { | ||
62 | switch (buf[i]) { | ||
63 | case '\r': | ||
64 | /* replace cr with nl */ | ||
65 | tmp[tpk_curr + 0] = '\n'; | ||
66 | tmp[tpk_curr + 1] = '\0'; | ||
67 | printk(KERN_INFO "%s%s", tpk_tag, tmp); | ||
68 | tpk_curr = 0; | ||
69 | if (buf[i + 1] == '\n') | ||
70 | i++; | ||
71 | break; | ||
72 | case '\n': | ||
73 | tmp[tpk_curr + 1] = '\0'; | ||
74 | printk(KERN_INFO "%s%s", tpk_tag, tmp); | ||
75 | tpk_curr = 0; | ||
76 | break; | ||
77 | default: | ||
78 | tpk_curr++; | ||
79 | } | ||
80 | } else { | ||
81 | /* end of tmp buffer reached: cut the message in two */ | ||
82 | tmp[tpk_curr + 1] = '\\'; | ||
83 | tmp[tpk_curr + 2] = '\n'; | ||
84 | tmp[tpk_curr + 3] = '\0'; | ||
85 | printk(KERN_INFO "%s%s", tpk_tag, tmp); | ||
86 | tpk_curr = 0; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | return count; | ||
91 | } | ||
92 | |||
93 | /* | ||
94 | * TTY operations open function. | ||
95 | */ | ||
96 | static int tpk_open(struct tty_struct *tty, struct file *filp) | ||
97 | { | ||
98 | tty->driver_data = &tpk_port; | ||
99 | |||
100 | return tty_port_open(&tpk_port.port, tty, filp); | ||
101 | } | ||
102 | |||
103 | /* | ||
104 | * TTY operations close function. | ||
105 | */ | ||
106 | static void tpk_close(struct tty_struct *tty, struct file *filp) | ||
107 | { | ||
108 | struct ttyprintk_port *tpkp = tty->driver_data; | ||
109 | |||
110 | mutex_lock(&tpkp->port_write_mutex); | ||
111 | /* flush tpk_printk buffer */ | ||
112 | tpk_printk(NULL, 0); | ||
113 | mutex_unlock(&tpkp->port_write_mutex); | ||
114 | |||
115 | tty_port_close(&tpkp->port, tty, filp); | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | * TTY operations write function. | ||
120 | */ | ||
121 | static int tpk_write(struct tty_struct *tty, | ||
122 | const unsigned char *buf, int count) | ||
123 | { | ||
124 | struct ttyprintk_port *tpkp = tty->driver_data; | ||
125 | int ret; | ||
126 | |||
127 | |||
128 | /* exclusive use of tpk_printk within this tty */ | ||
129 | mutex_lock(&tpkp->port_write_mutex); | ||
130 | ret = tpk_printk(buf, count); | ||
131 | mutex_unlock(&tpkp->port_write_mutex); | ||
132 | |||
133 | return ret; | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * TTY operations write_room function. | ||
138 | */ | ||
139 | static int tpk_write_room(struct tty_struct *tty) | ||
140 | { | ||
141 | return TPK_MAX_ROOM; | ||
142 | } | ||
143 | |||
144 | /* | ||
145 | * TTY operations ioctl function. | ||
146 | */ | ||
147 | static int tpk_ioctl(struct tty_struct *tty, struct file *file, | ||
148 | unsigned int cmd, unsigned long arg) | ||
149 | { | ||
150 | struct ttyprintk_port *tpkp = tty->driver_data; | ||
151 | |||
152 | if (!tpkp) | ||
153 | return -EINVAL; | ||
154 | |||
155 | switch (cmd) { | ||
156 | /* Stop TIOCCONS */ | ||
157 | case TIOCCONS: | ||
158 | return -EOPNOTSUPP; | ||
159 | default: | ||
160 | return -ENOIOCTLCMD; | ||
161 | } | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static const struct tty_operations ttyprintk_ops = { | ||
166 | .open = tpk_open, | ||
167 | .close = tpk_close, | ||
168 | .write = tpk_write, | ||
169 | .write_room = tpk_write_room, | ||
170 | .ioctl = tpk_ioctl, | ||
171 | }; | ||
172 | |||
173 | struct tty_port_operations null_ops = { }; | ||
174 | |||
175 | static struct tty_driver *ttyprintk_driver; | ||
176 | |||
177 | static int __init ttyprintk_init(void) | ||
178 | { | ||
179 | int ret = -ENOMEM; | ||
180 | void *rp; | ||
181 | |||
182 | ttyprintk_driver = alloc_tty_driver(1); | ||
183 | if (!ttyprintk_driver) | ||
184 | return ret; | ||
185 | |||
186 | ttyprintk_driver->owner = THIS_MODULE; | ||
187 | ttyprintk_driver->driver_name = "ttyprintk"; | ||
188 | ttyprintk_driver->name = "ttyprintk"; | ||
189 | ttyprintk_driver->major = TTYAUX_MAJOR; | ||
190 | ttyprintk_driver->minor_start = 3; | ||
191 | ttyprintk_driver->num = 1; | ||
192 | ttyprintk_driver->type = TTY_DRIVER_TYPE_CONSOLE; | ||
193 | ttyprintk_driver->init_termios = tty_std_termios; | ||
194 | ttyprintk_driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET; | ||
195 | ttyprintk_driver->flags = TTY_DRIVER_RESET_TERMIOS | | ||
196 | TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | ||
197 | tty_set_operations(ttyprintk_driver, &ttyprintk_ops); | ||
198 | |||
199 | ret = tty_register_driver(ttyprintk_driver); | ||
200 | if (ret < 0) { | ||
201 | printk(KERN_ERR "Couldn't register ttyprintk driver\n"); | ||
202 | goto error; | ||
203 | } | ||
204 | |||
205 | /* create our unnumbered device */ | ||
206 | rp = device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 3), NULL, | ||
207 | ttyprintk_driver->name); | ||
208 | if (IS_ERR(rp)) { | ||
209 | printk(KERN_ERR "Couldn't create ttyprintk device\n"); | ||
210 | ret = PTR_ERR(rp); | ||
211 | goto error; | ||
212 | } | ||
213 | |||
214 | tty_port_init(&tpk_port.port); | ||
215 | tpk_port.port.ops = &null_ops; | ||
216 | mutex_init(&tpk_port.port_write_mutex); | ||
217 | |||
218 | return 0; | ||
219 | |||
220 | error: | ||
221 | put_tty_driver(ttyprintk_driver); | ||
222 | ttyprintk_driver = NULL; | ||
223 | return ret; | ||
224 | } | ||
225 | module_init(ttyprintk_init); | ||
diff --git a/drivers/char/uv_mmtimer.c b/drivers/char/uv_mmtimer.c index 867b67be9f0a..493b47a0d511 100644 --- a/drivers/char/uv_mmtimer.c +++ b/drivers/char/uv_mmtimer.c | |||
@@ -52,6 +52,7 @@ static const struct file_operations uv_mmtimer_fops = { | |||
52 | .owner = THIS_MODULE, | 52 | .owner = THIS_MODULE, |
53 | .mmap = uv_mmtimer_mmap, | 53 | .mmap = uv_mmtimer_mmap, |
54 | .unlocked_ioctl = uv_mmtimer_ioctl, | 54 | .unlocked_ioctl = uv_mmtimer_ioctl, |
55 | .llseek = noop_llseek, | ||
55 | }; | 56 | }; |
56 | 57 | ||
57 | /** | 58 | /** |
@@ -89,13 +90,17 @@ static long uv_mmtimer_ioctl(struct file *file, unsigned int cmd, | |||
89 | switch (cmd) { | 90 | switch (cmd) { |
90 | case MMTIMER_GETOFFSET: /* offset of the counter */ | 91 | case MMTIMER_GETOFFSET: /* offset of the counter */ |
91 | /* | 92 | /* |
92 | * UV RTC register is on its own page | 93 | * Starting with HUB rev 2.0, the UV RTC register is |
94 | * replicated across all cachelines of it's own page. | ||
95 | * This allows faster simultaneous reads from a given socket. | ||
96 | * | ||
97 | * The offset returned is in 64 bit units. | ||
93 | */ | 98 | */ |
94 | if (PAGE_SIZE <= (1 << 16)) | 99 | if (uv_get_min_hub_revision_id() == 1) |
95 | ret = ((UV_LOCAL_MMR_BASE | UVH_RTC) & (PAGE_SIZE-1)) | 100 | ret = 0; |
96 | / 8; | ||
97 | else | 101 | else |
98 | ret = -ENOSYS; | 102 | ret = ((uv_blade_processor_id() * L1_CACHE_BYTES) % |
103 | PAGE_SIZE) / 8; | ||
99 | break; | 104 | break; |
100 | 105 | ||
101 | case MMTIMER_GETRES: /* resolution of the clock in 10^-15 s */ | 106 | case MMTIMER_GETRES: /* resolution of the clock in 10^-15 s */ |
@@ -115,8 +120,8 @@ static long uv_mmtimer_ioctl(struct file *file, unsigned int cmd, | |||
115 | ret = hweight64(UVH_RTC_REAL_TIME_CLOCK_MASK); | 120 | ret = hweight64(UVH_RTC_REAL_TIME_CLOCK_MASK); |
116 | break; | 121 | break; |
117 | 122 | ||
118 | case MMTIMER_MMAPAVAIL: /* can we mmap the clock into userspace? */ | 123 | case MMTIMER_MMAPAVAIL: |
119 | ret = (PAGE_SIZE <= (1 << 16)) ? 1 : 0; | 124 | ret = 1; |
120 | break; | 125 | break; |
121 | 126 | ||
122 | case MMTIMER_GETCOUNTER: | 127 | case MMTIMER_GETCOUNTER: |
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index c1791a63d99d..273ab44cc91d 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c | |||
@@ -35,6 +35,12 @@ | |||
35 | #include <linux/console.h> | 35 | #include <linux/console.h> |
36 | #include <linux/device.h> | 36 | #include <linux/device.h> |
37 | #include <linux/smp_lock.h> | 37 | #include <linux/smp_lock.h> |
38 | #include <linux/sched.h> | ||
39 | #include <linux/fs.h> | ||
40 | #include <linux/poll.h> | ||
41 | #include <linux/signal.h> | ||
42 | #include <linux/slab.h> | ||
43 | #include <linux/notifier.h> | ||
38 | 44 | ||
39 | #include <asm/uaccess.h> | 45 | #include <asm/uaccess.h> |
40 | #include <asm/byteorder.h> | 46 | #include <asm/byteorder.h> |
@@ -45,6 +51,86 @@ | |||
45 | #undef addr | 51 | #undef addr |
46 | #define HEADER_SIZE 4 | 52 | #define HEADER_SIZE 4 |
47 | 53 | ||
54 | struct vcs_poll_data { | ||
55 | struct notifier_block notifier; | ||
56 | unsigned int cons_num; | ||
57 | bool seen_last_update; | ||
58 | wait_queue_head_t waitq; | ||
59 | struct fasync_struct *fasync; | ||
60 | }; | ||
61 | |||
62 | static int | ||
63 | vcs_notifier(struct notifier_block *nb, unsigned long code, void *_param) | ||
64 | { | ||
65 | struct vt_notifier_param *param = _param; | ||
66 | struct vc_data *vc = param->vc; | ||
67 | struct vcs_poll_data *poll = | ||
68 | container_of(nb, struct vcs_poll_data, notifier); | ||
69 | int currcons = poll->cons_num; | ||
70 | |||
71 | if (code != VT_UPDATE) | ||
72 | return NOTIFY_DONE; | ||
73 | |||
74 | if (currcons == 0) | ||
75 | currcons = fg_console; | ||
76 | else | ||
77 | currcons--; | ||
78 | if (currcons != vc->vc_num) | ||
79 | return NOTIFY_DONE; | ||
80 | |||
81 | poll->seen_last_update = false; | ||
82 | wake_up_interruptible(&poll->waitq); | ||
83 | kill_fasync(&poll->fasync, SIGIO, POLL_IN); | ||
84 | return NOTIFY_OK; | ||
85 | } | ||
86 | |||
87 | static void | ||
88 | vcs_poll_data_free(struct vcs_poll_data *poll) | ||
89 | { | ||
90 | unregister_vt_notifier(&poll->notifier); | ||
91 | kfree(poll); | ||
92 | } | ||
93 | |||
94 | static struct vcs_poll_data * | ||
95 | vcs_poll_data_get(struct file *file) | ||
96 | { | ||
97 | struct vcs_poll_data *poll = file->private_data; | ||
98 | |||
99 | if (poll) | ||
100 | return poll; | ||
101 | |||
102 | poll = kzalloc(sizeof(*poll), GFP_KERNEL); | ||
103 | if (!poll) | ||
104 | return NULL; | ||
105 | poll->cons_num = iminor(file->f_path.dentry->d_inode) & 127; | ||
106 | init_waitqueue_head(&poll->waitq); | ||
107 | poll->notifier.notifier_call = vcs_notifier; | ||
108 | if (register_vt_notifier(&poll->notifier) != 0) { | ||
109 | kfree(poll); | ||
110 | return NULL; | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * This code may be called either through ->poll() or ->fasync(). | ||
115 | * If we have two threads using the same file descriptor, they could | ||
116 | * both enter this function, both notice that the structure hasn't | ||
117 | * been allocated yet and go ahead allocating it in parallel, but | ||
118 | * only one of them must survive and be shared otherwise we'd leak | ||
119 | * memory with a dangling notifier callback. | ||
120 | */ | ||
121 | spin_lock(&file->f_lock); | ||
122 | if (!file->private_data) { | ||
123 | file->private_data = poll; | ||
124 | } else { | ||
125 | /* someone else raced ahead of us */ | ||
126 | vcs_poll_data_free(poll); | ||
127 | poll = file->private_data; | ||
128 | } | ||
129 | spin_unlock(&file->f_lock); | ||
130 | |||
131 | return poll; | ||
132 | } | ||
133 | |||
48 | static int | 134 | static int |
49 | vcs_size(struct inode *inode) | 135 | vcs_size(struct inode *inode) |
50 | { | 136 | { |
@@ -102,6 +188,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
102 | struct inode *inode = file->f_path.dentry->d_inode; | 188 | struct inode *inode = file->f_path.dentry->d_inode; |
103 | unsigned int currcons = iminor(inode); | 189 | unsigned int currcons = iminor(inode); |
104 | struct vc_data *vc; | 190 | struct vc_data *vc; |
191 | struct vcs_poll_data *poll; | ||
105 | long pos; | 192 | long pos; |
106 | long viewed, attr, read; | 193 | long viewed, attr, read; |
107 | int col, maxcol; | 194 | int col, maxcol; |
@@ -134,6 +221,9 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
134 | ret = -EINVAL; | 221 | ret = -EINVAL; |
135 | if (pos < 0) | 222 | if (pos < 0) |
136 | goto unlock_out; | 223 | goto unlock_out; |
224 | poll = file->private_data; | ||
225 | if (count && poll) | ||
226 | poll->seen_last_update = true; | ||
137 | read = 0; | 227 | read = 0; |
138 | ret = 0; | 228 | ret = 0; |
139 | while (count) { | 229 | while (count) { |
@@ -448,6 +538,8 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | |||
448 | } | 538 | } |
449 | *ppos += written; | 539 | *ppos += written; |
450 | ret = written; | 540 | ret = written; |
541 | if (written) | ||
542 | vcs_scr_updated(vc); | ||
451 | 543 | ||
452 | unlock_out: | 544 | unlock_out: |
453 | release_console_sem(); | 545 | release_console_sem(); |
@@ -457,24 +549,67 @@ unlock_out: | |||
457 | return ret; | 549 | return ret; |
458 | } | 550 | } |
459 | 551 | ||
552 | static unsigned int | ||
553 | vcs_poll(struct file *file, poll_table *wait) | ||
554 | { | ||
555 | struct vcs_poll_data *poll = vcs_poll_data_get(file); | ||
556 | int ret = 0; | ||
557 | |||
558 | if (poll) { | ||
559 | poll_wait(file, &poll->waitq, wait); | ||
560 | if (!poll->seen_last_update) | ||
561 | ret = POLLIN | POLLRDNORM; | ||
562 | } | ||
563 | return ret; | ||
564 | } | ||
565 | |||
566 | static int | ||
567 | vcs_fasync(int fd, struct file *file, int on) | ||
568 | { | ||
569 | struct vcs_poll_data *poll = file->private_data; | ||
570 | |||
571 | if (!poll) { | ||
572 | /* don't allocate anything if all we want is disable fasync */ | ||
573 | if (!on) | ||
574 | return 0; | ||
575 | poll = vcs_poll_data_get(file); | ||
576 | if (!poll) | ||
577 | return -ENOMEM; | ||
578 | } | ||
579 | |||
580 | return fasync_helper(fd, file, on, &poll->fasync); | ||
581 | } | ||
582 | |||
460 | static int | 583 | static int |
461 | vcs_open(struct inode *inode, struct file *filp) | 584 | vcs_open(struct inode *inode, struct file *filp) |
462 | { | 585 | { |
463 | unsigned int currcons = iminor(inode) & 127; | 586 | unsigned int currcons = iminor(inode) & 127; |
464 | int ret = 0; | 587 | int ret = 0; |
465 | 588 | ||
466 | lock_kernel(); | 589 | tty_lock(); |
467 | if(currcons && !vc_cons_allocated(currcons-1)) | 590 | if(currcons && !vc_cons_allocated(currcons-1)) |
468 | ret = -ENXIO; | 591 | ret = -ENXIO; |
469 | unlock_kernel(); | 592 | tty_unlock(); |
470 | return ret; | 593 | return ret; |
471 | } | 594 | } |
472 | 595 | ||
596 | static int vcs_release(struct inode *inode, struct file *file) | ||
597 | { | ||
598 | struct vcs_poll_data *poll = file->private_data; | ||
599 | |||
600 | if (poll) | ||
601 | vcs_poll_data_free(poll); | ||
602 | return 0; | ||
603 | } | ||
604 | |||
473 | static const struct file_operations vcs_fops = { | 605 | static const struct file_operations vcs_fops = { |
474 | .llseek = vcs_lseek, | 606 | .llseek = vcs_lseek, |
475 | .read = vcs_read, | 607 | .read = vcs_read, |
476 | .write = vcs_write, | 608 | .write = vcs_write, |
609 | .poll = vcs_poll, | ||
610 | .fasync = vcs_fasync, | ||
477 | .open = vcs_open, | 611 | .open = vcs_open, |
612 | .release = vcs_release, | ||
478 | }; | 613 | }; |
479 | 614 | ||
480 | static struct class *vc_class; | 615 | static struct class *vc_class; |
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index 042c8149a6d1..ad6e64a2912d 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c | |||
@@ -46,7 +46,8 @@ | |||
46 | #include <linux/completion.h> | 46 | #include <linux/completion.h> |
47 | #include <linux/proc_fs.h> | 47 | #include <linux/proc_fs.h> |
48 | #include <linux/seq_file.h> | 48 | #include <linux/seq_file.h> |
49 | #include <linux/smp_lock.h> | 49 | #include <linux/mutex.h> |
50 | #include <linux/slab.h> | ||
50 | 51 | ||
51 | #include <asm/uaccess.h> | 52 | #include <asm/uaccess.h> |
52 | #include <asm/ioctls.h> | 53 | #include <asm/ioctls.h> |
@@ -63,6 +64,7 @@ | |||
63 | #define VIOTAPE_KERN_WARN KERN_WARNING "viotape: " | 64 | #define VIOTAPE_KERN_WARN KERN_WARNING "viotape: " |
64 | #define VIOTAPE_KERN_INFO KERN_INFO "viotape: " | 65 | #define VIOTAPE_KERN_INFO KERN_INFO "viotape: " |
65 | 66 | ||
67 | static DEFINE_MUTEX(proc_viotape_mutex); | ||
66 | static int viotape_numdev; | 68 | static int viotape_numdev; |
67 | 69 | ||
68 | /* | 70 | /* |
@@ -683,9 +685,9 @@ static long viotap_unlocked_ioctl(struct file *file, | |||
683 | { | 685 | { |
684 | long rc; | 686 | long rc; |
685 | 687 | ||
686 | lock_kernel(); | 688 | mutex_lock(&proc_viotape_mutex); |
687 | rc = viotap_ioctl(file->f_path.dentry->d_inode, file, cmd, arg); | 689 | rc = viotap_ioctl(file->f_path.dentry->d_inode, file, cmd, arg); |
688 | unlock_kernel(); | 690 | mutex_unlock(&proc_viotape_mutex); |
689 | return rc; | 691 | return rc; |
690 | } | 692 | } |
691 | 693 | ||
@@ -699,7 +701,7 @@ static int viotap_open(struct inode *inode, struct file *file) | |||
699 | if (op == NULL) | 701 | if (op == NULL) |
700 | return -ENOMEM; | 702 | return -ENOMEM; |
701 | 703 | ||
702 | lock_kernel(); | 704 | mutex_lock(&proc_viotape_mutex); |
703 | get_dev_info(file->f_path.dentry->d_inode, &devi); | 705 | get_dev_info(file->f_path.dentry->d_inode, &devi); |
704 | 706 | ||
705 | /* Note: We currently only support one mode! */ | 707 | /* Note: We currently only support one mode! */ |
@@ -730,7 +732,7 @@ static int viotap_open(struct inode *inode, struct file *file) | |||
730 | 732 | ||
731 | free_op: | 733 | free_op: |
732 | free_op_struct(op); | 734 | free_op_struct(op); |
733 | unlock_kernel(); | 735 | mutex_unlock(&proc_viotape_mutex); |
734 | return ret; | 736 | return ret; |
735 | } | 737 | } |
736 | 738 | ||
@@ -803,6 +805,7 @@ const struct file_operations viotap_fops = { | |||
803 | .unlocked_ioctl = viotap_unlocked_ioctl, | 805 | .unlocked_ioctl = viotap_unlocked_ioctl, |
804 | .open = viotap_open, | 806 | .open = viotap_open, |
805 | .release = viotap_release, | 807 | .release = viotap_release, |
808 | .llseek = noop_llseek, | ||
806 | }; | 809 | }; |
807 | 810 | ||
808 | /* Handle interrupt events for tape */ | 811 | /* Handle interrupt events for tape */ |
@@ -865,7 +868,7 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
865 | { | 868 | { |
866 | int i = vdev->unit_address; | 869 | int i = vdev->unit_address; |
867 | int j; | 870 | int j; |
868 | struct device_node *node = vdev->dev.archdata.of_node; | 871 | struct device_node *node = vdev->dev.of_node; |
869 | 872 | ||
870 | if (i >= VIOTAPE_MAX_TAPE) | 873 | if (i >= VIOTAPE_MAX_TAPE) |
871 | return -ENODEV; | 874 | return -ENODEV; |
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index a035ae39a359..6c1b676643a9 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -1,18 +1,6 @@ | |||
1 | /*D:300 | 1 | /* |
2 | * The Guest console driver | 2 | * Copyright (C) 2006, 2007, 2009 Rusty Russell, IBM Corporation |
3 | * | 3 | * Copyright (C) 2009, 2010 Red Hat, Inc. |
4 | * Writing console drivers is one of the few remaining Dark Arts in Linux. | ||
5 | * Fortunately for us, the path of virtual consoles has been well-trodden by | ||
6 | * the PowerPC folks, who wrote "hvc_console.c" to generically support any | ||
7 | * virtual console. We use that infrastructure which only requires us to write | ||
8 | * the basic put_chars and get_chars functions and call the right register | ||
9 | * functions. | ||
10 | :*/ | ||
11 | |||
12 | /*M:002 The console can be flooded: while the Guest is processing input the | ||
13 | * Host can send more. Buffering in the Host could alleviate this, but it is a | ||
14 | * difficult problem in general. :*/ | ||
15 | /* Copyright (C) 2006, 2007 Rusty Russell, IBM Corporation | ||
16 | * | 4 | * |
17 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
18 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
@@ -28,142 +16,906 @@ | |||
28 | * along with this program; if not, write to the Free Software | 16 | * along with this program; if not, write to the Free Software |
29 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
30 | */ | 18 | */ |
19 | #include <linux/cdev.h> | ||
20 | #include <linux/debugfs.h> | ||
21 | #include <linux/device.h> | ||
31 | #include <linux/err.h> | 22 | #include <linux/err.h> |
23 | #include <linux/fs.h> | ||
32 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/list.h> | ||
26 | #include <linux/poll.h> | ||
27 | #include <linux/sched.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/spinlock.h> | ||
33 | #include <linux/virtio.h> | 30 | #include <linux/virtio.h> |
34 | #include <linux/virtio_console.h> | 31 | #include <linux/virtio_console.h> |
32 | #include <linux/wait.h> | ||
33 | #include <linux/workqueue.h> | ||
35 | #include "hvc_console.h" | 34 | #include "hvc_console.h" |
36 | 35 | ||
37 | /*D:340 These represent our input and output console queues, and the virtio | 36 | /* |
38 | * operations for them. */ | 37 | * This is a global struct for storing common data for all the devices |
39 | static struct virtqueue *in_vq, *out_vq; | 38 | * this driver handles. |
40 | static struct virtio_device *vdev; | 39 | * |
40 | * Mainly, it has a linked list for all the consoles in one place so | ||
41 | * that callbacks from hvc for get_chars(), put_chars() work properly | ||
42 | * across multiple devices and multiple ports per device. | ||
43 | */ | ||
44 | struct ports_driver_data { | ||
45 | /* Used for registering chardevs */ | ||
46 | struct class *class; | ||
47 | |||
48 | /* Used for exporting per-port information to debugfs */ | ||
49 | struct dentry *debugfs_dir; | ||
50 | |||
51 | /* List of all the devices we're handling */ | ||
52 | struct list_head portdevs; | ||
53 | |||
54 | /* Number of devices this driver is handling */ | ||
55 | unsigned int index; | ||
56 | |||
57 | /* | ||
58 | * This is used to keep track of the number of hvc consoles | ||
59 | * spawned by this driver. This number is given as the first | ||
60 | * argument to hvc_alloc(). To correctly map an initial | ||
61 | * console spawned via hvc_instantiate to the console being | ||
62 | * hooked up via hvc_alloc, we need to pass the same vtermno. | ||
63 | * | ||
64 | * We also just assume the first console being initialised was | ||
65 | * the first one that got used as the initial console. | ||
66 | */ | ||
67 | unsigned int next_vtermno; | ||
68 | |||
69 | /* All the console devices handled by this driver */ | ||
70 | struct list_head consoles; | ||
71 | }; | ||
72 | static struct ports_driver_data pdrvdata; | ||
73 | |||
74 | DEFINE_SPINLOCK(pdrvdata_lock); | ||
75 | |||
76 | /* This struct holds information that's relevant only for console ports */ | ||
77 | struct console { | ||
78 | /* We'll place all consoles in a list in the pdrvdata struct */ | ||
79 | struct list_head list; | ||
80 | |||
81 | /* The hvc device associated with this console port */ | ||
82 | struct hvc_struct *hvc; | ||
83 | |||
84 | /* The size of the console */ | ||
85 | struct winsize ws; | ||
86 | |||
87 | /* | ||
88 | * This number identifies the number that we used to register | ||
89 | * with hvc in hvc_instantiate() and hvc_alloc(); this is the | ||
90 | * number passed on by the hvc callbacks to us to | ||
91 | * differentiate between the other console ports handled by | ||
92 | * this driver | ||
93 | */ | ||
94 | u32 vtermno; | ||
95 | }; | ||
96 | |||
97 | struct port_buffer { | ||
98 | char *buf; | ||
99 | |||
100 | /* size of the buffer in *buf above */ | ||
101 | size_t size; | ||
102 | |||
103 | /* used length of the buffer */ | ||
104 | size_t len; | ||
105 | /* offset in the buf from which to consume data */ | ||
106 | size_t offset; | ||
107 | }; | ||
108 | |||
109 | /* | ||
110 | * This is a per-device struct that stores data common to all the | ||
111 | * ports for that device (vdev->priv). | ||
112 | */ | ||
113 | struct ports_device { | ||
114 | /* Next portdev in the list, head is in the pdrvdata struct */ | ||
115 | struct list_head list; | ||
116 | |||
117 | /* | ||
118 | * Workqueue handlers where we process deferred work after | ||
119 | * notification | ||
120 | */ | ||
121 | struct work_struct control_work; | ||
122 | |||
123 | struct list_head ports; | ||
124 | |||
125 | /* To protect the list of ports */ | ||
126 | spinlock_t ports_lock; | ||
127 | |||
128 | /* To protect the vq operations for the control channel */ | ||
129 | spinlock_t cvq_lock; | ||
130 | |||
131 | /* The current config space is stored here */ | ||
132 | struct virtio_console_config config; | ||
41 | 133 | ||
42 | /* This is our input buffer, and how much data is left in it. */ | 134 | /* The virtio device we're associated with */ |
43 | static unsigned int in_len; | 135 | struct virtio_device *vdev; |
44 | static char *in, *inbuf; | ||
45 | 136 | ||
46 | /* The operations for our console. */ | 137 | /* |
47 | static struct hv_ops virtio_cons; | 138 | * A couple of virtqueues for the control channel: one for |
139 | * guest->host transfers, one for host->guest transfers | ||
140 | */ | ||
141 | struct virtqueue *c_ivq, *c_ovq; | ||
48 | 142 | ||
49 | /* The hvc device */ | 143 | /* Array of per-port IO virtqueues */ |
50 | static struct hvc_struct *hvc; | 144 | struct virtqueue **in_vqs, **out_vqs; |
51 | 145 | ||
52 | /*D:310 The put_chars() callback is pretty straightforward. | 146 | /* Used for numbering devices for sysfs and debugfs */ |
147 | unsigned int drv_index; | ||
148 | |||
149 | /* Major number for this device. Ports will be created as minors. */ | ||
150 | int chr_major; | ||
151 | }; | ||
152 | |||
153 | /* This struct holds the per-port data */ | ||
154 | struct port { | ||
155 | /* Next port in the list, head is in the ports_device */ | ||
156 | struct list_head list; | ||
157 | |||
158 | /* Pointer to the parent virtio_console device */ | ||
159 | struct ports_device *portdev; | ||
160 | |||
161 | /* The current buffer from which data has to be fed to readers */ | ||
162 | struct port_buffer *inbuf; | ||
163 | |||
164 | /* | ||
165 | * To protect the operations on the in_vq associated with this | ||
166 | * port. Has to be a spinlock because it can be called from | ||
167 | * interrupt context (get_char()). | ||
168 | */ | ||
169 | spinlock_t inbuf_lock; | ||
170 | |||
171 | /* Protect the operations on the out_vq. */ | ||
172 | spinlock_t outvq_lock; | ||
173 | |||
174 | /* The IO vqs for this port */ | ||
175 | struct virtqueue *in_vq, *out_vq; | ||
176 | |||
177 | /* File in the debugfs directory that exposes this port's information */ | ||
178 | struct dentry *debugfs_file; | ||
179 | |||
180 | /* | ||
181 | * The entries in this struct will be valid if this port is | ||
182 | * hooked up to an hvc console | ||
183 | */ | ||
184 | struct console cons; | ||
185 | |||
186 | /* Each port associates with a separate char device */ | ||
187 | struct cdev *cdev; | ||
188 | struct device *dev; | ||
189 | |||
190 | /* Reference-counting to handle port hot-unplugs and file operations */ | ||
191 | struct kref kref; | ||
192 | |||
193 | /* A waitqueue for poll() or blocking read operations */ | ||
194 | wait_queue_head_t waitqueue; | ||
195 | |||
196 | /* The 'name' of the port that we expose via sysfs properties */ | ||
197 | char *name; | ||
198 | |||
199 | /* We can notify apps of host connect / disconnect events via SIGIO */ | ||
200 | struct fasync_struct *async_queue; | ||
201 | |||
202 | /* The 'id' to identify the port with the Host */ | ||
203 | u32 id; | ||
204 | |||
205 | bool outvq_full; | ||
206 | |||
207 | /* Is the host device open */ | ||
208 | bool host_connected; | ||
209 | |||
210 | /* We should allow only one process to open a port */ | ||
211 | bool guest_connected; | ||
212 | }; | ||
213 | |||
214 | /* This is the very early arch-specified put chars function. */ | ||
215 | static int (*early_put_chars)(u32, const char *, int); | ||
216 | |||
217 | static struct port *find_port_by_vtermno(u32 vtermno) | ||
218 | { | ||
219 | struct port *port; | ||
220 | struct console *cons; | ||
221 | unsigned long flags; | ||
222 | |||
223 | spin_lock_irqsave(&pdrvdata_lock, flags); | ||
224 | list_for_each_entry(cons, &pdrvdata.consoles, list) { | ||
225 | if (cons->vtermno == vtermno) { | ||
226 | port = container_of(cons, struct port, cons); | ||
227 | goto out; | ||
228 | } | ||
229 | } | ||
230 | port = NULL; | ||
231 | out: | ||
232 | spin_unlock_irqrestore(&pdrvdata_lock, flags); | ||
233 | return port; | ||
234 | } | ||
235 | |||
236 | static struct port *find_port_by_devt_in_portdev(struct ports_device *portdev, | ||
237 | dev_t dev) | ||
238 | { | ||
239 | struct port *port; | ||
240 | unsigned long flags; | ||
241 | |||
242 | spin_lock_irqsave(&portdev->ports_lock, flags); | ||
243 | list_for_each_entry(port, &portdev->ports, list) | ||
244 | if (port->cdev->dev == dev) | ||
245 | goto out; | ||
246 | port = NULL; | ||
247 | out: | ||
248 | spin_unlock_irqrestore(&portdev->ports_lock, flags); | ||
249 | |||
250 | return port; | ||
251 | } | ||
252 | |||
253 | static struct port *find_port_by_devt(dev_t dev) | ||
254 | { | ||
255 | struct ports_device *portdev; | ||
256 | struct port *port; | ||
257 | unsigned long flags; | ||
258 | |||
259 | spin_lock_irqsave(&pdrvdata_lock, flags); | ||
260 | list_for_each_entry(portdev, &pdrvdata.portdevs, list) { | ||
261 | port = find_port_by_devt_in_portdev(portdev, dev); | ||
262 | if (port) | ||
263 | goto out; | ||
264 | } | ||
265 | port = NULL; | ||
266 | out: | ||
267 | spin_unlock_irqrestore(&pdrvdata_lock, flags); | ||
268 | return port; | ||
269 | } | ||
270 | |||
271 | static struct port *find_port_by_id(struct ports_device *portdev, u32 id) | ||
272 | { | ||
273 | struct port *port; | ||
274 | unsigned long flags; | ||
275 | |||
276 | spin_lock_irqsave(&portdev->ports_lock, flags); | ||
277 | list_for_each_entry(port, &portdev->ports, list) | ||
278 | if (port->id == id) | ||
279 | goto out; | ||
280 | port = NULL; | ||
281 | out: | ||
282 | spin_unlock_irqrestore(&portdev->ports_lock, flags); | ||
283 | |||
284 | return port; | ||
285 | } | ||
286 | |||
287 | static struct port *find_port_by_vq(struct ports_device *portdev, | ||
288 | struct virtqueue *vq) | ||
289 | { | ||
290 | struct port *port; | ||
291 | unsigned long flags; | ||
292 | |||
293 | spin_lock_irqsave(&portdev->ports_lock, flags); | ||
294 | list_for_each_entry(port, &portdev->ports, list) | ||
295 | if (port->in_vq == vq || port->out_vq == vq) | ||
296 | goto out; | ||
297 | port = NULL; | ||
298 | out: | ||
299 | spin_unlock_irqrestore(&portdev->ports_lock, flags); | ||
300 | return port; | ||
301 | } | ||
302 | |||
303 | static bool is_console_port(struct port *port) | ||
304 | { | ||
305 | if (port->cons.hvc) | ||
306 | return true; | ||
307 | return false; | ||
308 | } | ||
309 | |||
310 | static inline bool use_multiport(struct ports_device *portdev) | ||
311 | { | ||
312 | /* | ||
313 | * This condition can be true when put_chars is called from | ||
314 | * early_init | ||
315 | */ | ||
316 | if (!portdev->vdev) | ||
317 | return 0; | ||
318 | return portdev->vdev->features[0] & (1 << VIRTIO_CONSOLE_F_MULTIPORT); | ||
319 | } | ||
320 | |||
321 | static void free_buf(struct port_buffer *buf) | ||
322 | { | ||
323 | kfree(buf->buf); | ||
324 | kfree(buf); | ||
325 | } | ||
326 | |||
327 | static struct port_buffer *alloc_buf(size_t buf_size) | ||
328 | { | ||
329 | struct port_buffer *buf; | ||
330 | |||
331 | buf = kmalloc(sizeof(*buf), GFP_KERNEL); | ||
332 | if (!buf) | ||
333 | goto fail; | ||
334 | buf->buf = kzalloc(buf_size, GFP_KERNEL); | ||
335 | if (!buf->buf) | ||
336 | goto free_buf; | ||
337 | buf->len = 0; | ||
338 | buf->offset = 0; | ||
339 | buf->size = buf_size; | ||
340 | return buf; | ||
341 | |||
342 | free_buf: | ||
343 | kfree(buf); | ||
344 | fail: | ||
345 | return NULL; | ||
346 | } | ||
347 | |||
348 | /* Callers should take appropriate locks */ | ||
349 | static void *get_inbuf(struct port *port) | ||
350 | { | ||
351 | struct port_buffer *buf; | ||
352 | struct virtqueue *vq; | ||
353 | unsigned int len; | ||
354 | |||
355 | vq = port->in_vq; | ||
356 | buf = virtqueue_get_buf(vq, &len); | ||
357 | if (buf) { | ||
358 | buf->len = len; | ||
359 | buf->offset = 0; | ||
360 | } | ||
361 | return buf; | ||
362 | } | ||
363 | |||
364 | /* | ||
365 | * Create a scatter-gather list representing our input buffer and put | ||
366 | * it in the queue. | ||
53 | * | 367 | * |
54 | * We turn the characters into a scatter-gather list, add it to the output | 368 | * Callers should take appropriate locks. |
55 | * queue and then kick the Host. Then we sit here waiting for it to finish: | 369 | */ |
56 | * inefficient in theory, but in practice implementations will do it | 370 | static int add_inbuf(struct virtqueue *vq, struct port_buffer *buf) |
57 | * immediately (lguest's Launcher does). */ | 371 | { |
58 | static int put_chars(u32 vtermno, const char *buf, int count) | 372 | struct scatterlist sg[1]; |
373 | int ret; | ||
374 | |||
375 | sg_init_one(sg, buf->buf, buf->size); | ||
376 | |||
377 | ret = virtqueue_add_buf(vq, sg, 0, 1, buf); | ||
378 | virtqueue_kick(vq); | ||
379 | return ret; | ||
380 | } | ||
381 | |||
382 | /* Discard any unread data this port has. Callers lockers. */ | ||
383 | static void discard_port_data(struct port *port) | ||
384 | { | ||
385 | struct port_buffer *buf; | ||
386 | struct virtqueue *vq; | ||
387 | unsigned int len; | ||
388 | int ret; | ||
389 | |||
390 | vq = port->in_vq; | ||
391 | if (port->inbuf) | ||
392 | buf = port->inbuf; | ||
393 | else | ||
394 | buf = virtqueue_get_buf(vq, &len); | ||
395 | |||
396 | ret = 0; | ||
397 | while (buf) { | ||
398 | if (add_inbuf(vq, buf) < 0) { | ||
399 | ret++; | ||
400 | free_buf(buf); | ||
401 | } | ||
402 | buf = virtqueue_get_buf(vq, &len); | ||
403 | } | ||
404 | port->inbuf = NULL; | ||
405 | if (ret) | ||
406 | dev_warn(port->dev, "Errors adding %d buffers back to vq\n", | ||
407 | ret); | ||
408 | } | ||
409 | |||
410 | static bool port_has_data(struct port *port) | ||
411 | { | ||
412 | unsigned long flags; | ||
413 | bool ret; | ||
414 | |||
415 | spin_lock_irqsave(&port->inbuf_lock, flags); | ||
416 | if (port->inbuf) { | ||
417 | ret = true; | ||
418 | goto out; | ||
419 | } | ||
420 | port->inbuf = get_inbuf(port); | ||
421 | if (port->inbuf) { | ||
422 | ret = true; | ||
423 | goto out; | ||
424 | } | ||
425 | ret = false; | ||
426 | out: | ||
427 | spin_unlock_irqrestore(&port->inbuf_lock, flags); | ||
428 | return ret; | ||
429 | } | ||
430 | |||
431 | static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id, | ||
432 | unsigned int event, unsigned int value) | ||
59 | { | 433 | { |
60 | struct scatterlist sg[1]; | 434 | struct scatterlist sg[1]; |
435 | struct virtio_console_control cpkt; | ||
436 | struct virtqueue *vq; | ||
61 | unsigned int len; | 437 | unsigned int len; |
62 | 438 | ||
63 | /* This is a convenient routine to initialize a single-elem sg list */ | 439 | if (!use_multiport(portdev)) |
64 | sg_init_one(sg, buf, count); | 440 | return 0; |
441 | |||
442 | cpkt.id = port_id; | ||
443 | cpkt.event = event; | ||
444 | cpkt.value = value; | ||
445 | |||
446 | vq = portdev->c_ovq; | ||
65 | 447 | ||
66 | /* add_buf wants a token to identify this buffer: we hand it any | 448 | sg_init_one(sg, &cpkt, sizeof(cpkt)); |
67 | * non-NULL pointer, since there's only ever one buffer. */ | 449 | if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt) >= 0) { |
68 | if (out_vq->vq_ops->add_buf(out_vq, sg, 1, 0, (void *)1) >= 0) { | 450 | virtqueue_kick(vq); |
69 | /* Tell Host to go! */ | 451 | while (!virtqueue_get_buf(vq, &len)) |
70 | out_vq->vq_ops->kick(out_vq); | ||
71 | /* Chill out until it's done with the buffer. */ | ||
72 | while (!out_vq->vq_ops->get_buf(out_vq, &len)) | ||
73 | cpu_relax(); | 452 | cpu_relax(); |
74 | } | 453 | } |
454 | return 0; | ||
455 | } | ||
456 | |||
457 | static ssize_t send_control_msg(struct port *port, unsigned int event, | ||
458 | unsigned int value) | ||
459 | { | ||
460 | /* Did the port get unplugged before userspace closed it? */ | ||
461 | if (port->portdev) | ||
462 | return __send_control_msg(port->portdev, port->id, event, value); | ||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | /* Callers must take the port->outvq_lock */ | ||
467 | static void reclaim_consumed_buffers(struct port *port) | ||
468 | { | ||
469 | void *buf; | ||
470 | unsigned int len; | ||
75 | 471 | ||
76 | /* We're expected to return the amount of data we wrote: all of it. */ | 472 | while ((buf = virtqueue_get_buf(port->out_vq, &len))) { |
77 | return count; | 473 | kfree(buf); |
474 | port->outvq_full = false; | ||
475 | } | ||
78 | } | 476 | } |
79 | 477 | ||
80 | /* Create a scatter-gather list representing our input buffer and put it in the | 478 | static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count, |
81 | * queue. */ | 479 | bool nonblock) |
82 | static void add_inbuf(void) | ||
83 | { | 480 | { |
84 | struct scatterlist sg[1]; | 481 | struct scatterlist sg[1]; |
85 | sg_init_one(sg, inbuf, PAGE_SIZE); | 482 | struct virtqueue *out_vq; |
483 | ssize_t ret; | ||
484 | unsigned long flags; | ||
485 | unsigned int len; | ||
486 | |||
487 | out_vq = port->out_vq; | ||
488 | |||
489 | spin_lock_irqsave(&port->outvq_lock, flags); | ||
490 | |||
491 | reclaim_consumed_buffers(port); | ||
492 | |||
493 | sg_init_one(sg, in_buf, in_count); | ||
494 | ret = virtqueue_add_buf(out_vq, sg, 1, 0, in_buf); | ||
495 | |||
496 | /* Tell Host to go! */ | ||
497 | virtqueue_kick(out_vq); | ||
86 | 498 | ||
87 | /* We should always be able to add one buffer to an empty queue. */ | 499 | if (ret < 0) { |
88 | if (in_vq->vq_ops->add_buf(in_vq, sg, 0, 1, inbuf) < 0) | 500 | in_count = 0; |
89 | BUG(); | 501 | goto done; |
90 | in_vq->vq_ops->kick(in_vq); | 502 | } |
503 | |||
504 | if (ret == 0) | ||
505 | port->outvq_full = true; | ||
506 | |||
507 | if (nonblock) | ||
508 | goto done; | ||
509 | |||
510 | /* | ||
511 | * Wait till the host acknowledges it pushed out the data we | ||
512 | * sent. This is done for data from the hvc_console; the tty | ||
513 | * operations are performed with spinlocks held so we can't | ||
514 | * sleep here. An alternative would be to copy the data to a | ||
515 | * buffer and relax the spinning requirement. The downside is | ||
516 | * we need to kmalloc a GFP_ATOMIC buffer each time the | ||
517 | * console driver writes something out. | ||
518 | */ | ||
519 | while (!virtqueue_get_buf(out_vq, &len)) | ||
520 | cpu_relax(); | ||
521 | done: | ||
522 | spin_unlock_irqrestore(&port->outvq_lock, flags); | ||
523 | /* | ||
524 | * We're expected to return the amount of data we wrote -- all | ||
525 | * of it | ||
526 | */ | ||
527 | return in_count; | ||
91 | } | 528 | } |
92 | 529 | ||
93 | /*D:350 get_chars() is the callback from the hvc_console infrastructure when | 530 | /* |
94 | * an interrupt is received. | 531 | * Give out the data that's requested from the buffer that we have |
95 | * | 532 | * queued up. |
96 | * Most of the code deals with the fact that the hvc_console() infrastructure | 533 | */ |
97 | * only asks us for 16 bytes at a time. We keep in_offset and in_used fields | 534 | static ssize_t fill_readbuf(struct port *port, char *out_buf, size_t out_count, |
98 | * for partially-filled buffers. */ | 535 | bool to_user) |
99 | static int get_chars(u32 vtermno, char *buf, int count) | ||
100 | { | 536 | { |
101 | /* If we don't have an input queue yet, we can't get input. */ | 537 | struct port_buffer *buf; |
102 | BUG_ON(!in_vq); | 538 | unsigned long flags; |
539 | |||
540 | if (!out_count || !port_has_data(port)) | ||
541 | return 0; | ||
542 | |||
543 | buf = port->inbuf; | ||
544 | out_count = min(out_count, buf->len - buf->offset); | ||
545 | |||
546 | if (to_user) { | ||
547 | ssize_t ret; | ||
548 | |||
549 | ret = copy_to_user(out_buf, buf->buf + buf->offset, out_count); | ||
550 | if (ret) | ||
551 | return -EFAULT; | ||
552 | } else { | ||
553 | memcpy(out_buf, buf->buf + buf->offset, out_count); | ||
554 | } | ||
555 | |||
556 | buf->offset += out_count; | ||
103 | 557 | ||
104 | /* No buffer? Try to get one. */ | 558 | if (buf->offset == buf->len) { |
105 | if (!in_len) { | 559 | /* |
106 | in = in_vq->vq_ops->get_buf(in_vq, &in_len); | 560 | * We're done using all the data in this buffer. |
107 | if (!in) | 561 | * Re-queue so that the Host can send us more data. |
562 | */ | ||
563 | spin_lock_irqsave(&port->inbuf_lock, flags); | ||
564 | port->inbuf = NULL; | ||
565 | |||
566 | if (add_inbuf(port->in_vq, buf) < 0) | ||
567 | dev_warn(port->dev, "failed add_buf\n"); | ||
568 | |||
569 | spin_unlock_irqrestore(&port->inbuf_lock, flags); | ||
570 | } | ||
571 | /* Return the number of bytes actually copied */ | ||
572 | return out_count; | ||
573 | } | ||
574 | |||
575 | /* The condition that must be true for polling to end */ | ||
576 | static bool will_read_block(struct port *port) | ||
577 | { | ||
578 | if (!port->guest_connected) { | ||
579 | /* Port got hot-unplugged. Let's exit. */ | ||
580 | return false; | ||
581 | } | ||
582 | return !port_has_data(port) && port->host_connected; | ||
583 | } | ||
584 | |||
585 | static bool will_write_block(struct port *port) | ||
586 | { | ||
587 | bool ret; | ||
588 | |||
589 | if (!port->guest_connected) { | ||
590 | /* Port got hot-unplugged. Let's exit. */ | ||
591 | return false; | ||
592 | } | ||
593 | if (!port->host_connected) | ||
594 | return true; | ||
595 | |||
596 | spin_lock_irq(&port->outvq_lock); | ||
597 | /* | ||
598 | * Check if the Host has consumed any buffers since we last | ||
599 | * sent data (this is only applicable for nonblocking ports). | ||
600 | */ | ||
601 | reclaim_consumed_buffers(port); | ||
602 | ret = port->outvq_full; | ||
603 | spin_unlock_irq(&port->outvq_lock); | ||
604 | |||
605 | return ret; | ||
606 | } | ||
607 | |||
608 | static ssize_t port_fops_read(struct file *filp, char __user *ubuf, | ||
609 | size_t count, loff_t *offp) | ||
610 | { | ||
611 | struct port *port; | ||
612 | ssize_t ret; | ||
613 | |||
614 | port = filp->private_data; | ||
615 | |||
616 | if (!port_has_data(port)) { | ||
617 | /* | ||
618 | * If nothing's connected on the host just return 0 in | ||
619 | * case of list_empty; this tells the userspace app | ||
620 | * that there's no connection | ||
621 | */ | ||
622 | if (!port->host_connected) | ||
108 | return 0; | 623 | return 0; |
624 | if (filp->f_flags & O_NONBLOCK) | ||
625 | return -EAGAIN; | ||
626 | |||
627 | ret = wait_event_interruptible(port->waitqueue, | ||
628 | !will_read_block(port)); | ||
629 | if (ret < 0) | ||
630 | return ret; | ||
631 | } | ||
632 | /* Port got hot-unplugged. */ | ||
633 | if (!port->guest_connected) | ||
634 | return -ENODEV; | ||
635 | /* | ||
636 | * We could've received a disconnection message while we were | ||
637 | * waiting for more data. | ||
638 | * | ||
639 | * This check is not clubbed in the if() statement above as we | ||
640 | * might receive some data as well as the host could get | ||
641 | * disconnected after we got woken up from our wait. So we | ||
642 | * really want to give off whatever data we have and only then | ||
643 | * check for host_connected. | ||
644 | */ | ||
645 | if (!port_has_data(port) && !port->host_connected) | ||
646 | return 0; | ||
647 | |||
648 | return fill_readbuf(port, ubuf, count, true); | ||
649 | } | ||
650 | |||
651 | static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, | ||
652 | size_t count, loff_t *offp) | ||
653 | { | ||
654 | struct port *port; | ||
655 | char *buf; | ||
656 | ssize_t ret; | ||
657 | bool nonblock; | ||
658 | |||
659 | /* Userspace could be out to fool us */ | ||
660 | if (!count) | ||
661 | return 0; | ||
662 | |||
663 | port = filp->private_data; | ||
664 | |||
665 | nonblock = filp->f_flags & O_NONBLOCK; | ||
666 | |||
667 | if (will_write_block(port)) { | ||
668 | if (nonblock) | ||
669 | return -EAGAIN; | ||
670 | |||
671 | ret = wait_event_interruptible(port->waitqueue, | ||
672 | !will_write_block(port)); | ||
673 | if (ret < 0) | ||
674 | return ret; | ||
109 | } | 675 | } |
676 | /* Port got hot-unplugged. */ | ||
677 | if (!port->guest_connected) | ||
678 | return -ENODEV; | ||
679 | |||
680 | count = min((size_t)(32 * 1024), count); | ||
110 | 681 | ||
111 | /* You want more than we have to give? Well, try wanting less! */ | 682 | buf = kmalloc(count, GFP_KERNEL); |
112 | if (in_len < count) | 683 | if (!buf) |
113 | count = in_len; | 684 | return -ENOMEM; |
685 | |||
686 | ret = copy_from_user(buf, ubuf, count); | ||
687 | if (ret) { | ||
688 | ret = -EFAULT; | ||
689 | goto free_buf; | ||
690 | } | ||
114 | 691 | ||
115 | /* Copy across to their buffer and increment offset. */ | 692 | /* |
116 | memcpy(buf, in, count); | 693 | * We now ask send_buf() to not spin for generic ports -- we |
117 | in += count; | 694 | * can re-use the same code path that non-blocking file |
118 | in_len -= count; | 695 | * descriptors take for blocking file descriptors since the |
696 | * wait is already done and we're certain the write will go | ||
697 | * through to the host. | ||
698 | */ | ||
699 | nonblock = true; | ||
700 | ret = send_buf(port, buf, count, nonblock); | ||
119 | 701 | ||
120 | /* Finished? Re-register buffer so Host will use it again. */ | 702 | if (nonblock && ret > 0) |
121 | if (in_len == 0) | 703 | goto out; |
122 | add_inbuf(); | ||
123 | 704 | ||
124 | return count; | 705 | free_buf: |
706 | kfree(buf); | ||
707 | out: | ||
708 | return ret; | ||
125 | } | 709 | } |
126 | /*:*/ | ||
127 | 710 | ||
128 | /*D:320 Console drivers are initialized very early so boot messages can go out, | 711 | static unsigned int port_fops_poll(struct file *filp, poll_table *wait) |
129 | * so we do things slightly differently from the generic virtio initialization | ||
130 | * of the net and block drivers. | ||
131 | * | ||
132 | * At this stage, the console is output-only. It's too early to set up a | ||
133 | * virtqueue, so we let the drivers do some boutique early-output thing. */ | ||
134 | int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)) | ||
135 | { | 712 | { |
136 | virtio_cons.put_chars = put_chars; | 713 | struct port *port; |
137 | return hvc_instantiate(0, 0, &virtio_cons); | 714 | unsigned int ret; |
715 | |||
716 | port = filp->private_data; | ||
717 | poll_wait(filp, &port->waitqueue, wait); | ||
718 | |||
719 | if (!port->guest_connected) { | ||
720 | /* Port got unplugged */ | ||
721 | return POLLHUP; | ||
722 | } | ||
723 | ret = 0; | ||
724 | if (!will_read_block(port)) | ||
725 | ret |= POLLIN | POLLRDNORM; | ||
726 | if (!will_write_block(port)) | ||
727 | ret |= POLLOUT; | ||
728 | if (!port->host_connected) | ||
729 | ret |= POLLHUP; | ||
730 | |||
731 | return ret; | ||
138 | } | 732 | } |
139 | 733 | ||
734 | static void remove_port(struct kref *kref); | ||
735 | |||
736 | static int port_fops_release(struct inode *inode, struct file *filp) | ||
737 | { | ||
738 | struct port *port; | ||
739 | |||
740 | port = filp->private_data; | ||
741 | |||
742 | /* Notify host of port being closed */ | ||
743 | send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0); | ||
744 | |||
745 | spin_lock_irq(&port->inbuf_lock); | ||
746 | port->guest_connected = false; | ||
747 | |||
748 | discard_port_data(port); | ||
749 | |||
750 | spin_unlock_irq(&port->inbuf_lock); | ||
751 | |||
752 | spin_lock_irq(&port->outvq_lock); | ||
753 | reclaim_consumed_buffers(port); | ||
754 | spin_unlock_irq(&port->outvq_lock); | ||
755 | |||
756 | /* | ||
757 | * Locks aren't necessary here as a port can't be opened after | ||
758 | * unplug, and if a port isn't unplugged, a kref would already | ||
759 | * exist for the port. Plus, taking ports_lock here would | ||
760 | * create a dependency on other locks taken by functions | ||
761 | * inside remove_port if we're the last holder of the port, | ||
762 | * creating many problems. | ||
763 | */ | ||
764 | kref_put(&port->kref, remove_port); | ||
765 | |||
766 | return 0; | ||
767 | } | ||
768 | |||
769 | static int port_fops_open(struct inode *inode, struct file *filp) | ||
770 | { | ||
771 | struct cdev *cdev = inode->i_cdev; | ||
772 | struct port *port; | ||
773 | int ret; | ||
774 | |||
775 | port = find_port_by_devt(cdev->dev); | ||
776 | filp->private_data = port; | ||
777 | |||
778 | /* Prevent against a port getting hot-unplugged at the same time */ | ||
779 | spin_lock_irq(&port->portdev->ports_lock); | ||
780 | kref_get(&port->kref); | ||
781 | spin_unlock_irq(&port->portdev->ports_lock); | ||
782 | |||
783 | /* | ||
784 | * Don't allow opening of console port devices -- that's done | ||
785 | * via /dev/hvc | ||
786 | */ | ||
787 | if (is_console_port(port)) { | ||
788 | ret = -ENXIO; | ||
789 | goto out; | ||
790 | } | ||
791 | |||
792 | /* Allow only one process to open a particular port at a time */ | ||
793 | spin_lock_irq(&port->inbuf_lock); | ||
794 | if (port->guest_connected) { | ||
795 | spin_unlock_irq(&port->inbuf_lock); | ||
796 | ret = -EMFILE; | ||
797 | goto out; | ||
798 | } | ||
799 | |||
800 | port->guest_connected = true; | ||
801 | spin_unlock_irq(&port->inbuf_lock); | ||
802 | |||
803 | spin_lock_irq(&port->outvq_lock); | ||
804 | /* | ||
805 | * There might be a chance that we missed reclaiming a few | ||
806 | * buffers in the window of the port getting previously closed | ||
807 | * and opening now. | ||
808 | */ | ||
809 | reclaim_consumed_buffers(port); | ||
810 | spin_unlock_irq(&port->outvq_lock); | ||
811 | |||
812 | nonseekable_open(inode, filp); | ||
813 | |||
814 | /* Notify host of port being opened */ | ||
815 | send_control_msg(filp->private_data, VIRTIO_CONSOLE_PORT_OPEN, 1); | ||
816 | |||
817 | return 0; | ||
818 | out: | ||
819 | kref_put(&port->kref, remove_port); | ||
820 | return ret; | ||
821 | } | ||
822 | |||
823 | static int port_fops_fasync(int fd, struct file *filp, int mode) | ||
824 | { | ||
825 | struct port *port; | ||
826 | |||
827 | port = filp->private_data; | ||
828 | return fasync_helper(fd, filp, mode, &port->async_queue); | ||
829 | } | ||
830 | |||
831 | /* | ||
832 | * The file operations that we support: programs in the guest can open | ||
833 | * a console device, read from it, write to it, poll for data and | ||
834 | * close it. The devices are at | ||
835 | * /dev/vport<device number>p<port number> | ||
836 | */ | ||
837 | static const struct file_operations port_fops = { | ||
838 | .owner = THIS_MODULE, | ||
839 | .open = port_fops_open, | ||
840 | .read = port_fops_read, | ||
841 | .write = port_fops_write, | ||
842 | .poll = port_fops_poll, | ||
843 | .release = port_fops_release, | ||
844 | .fasync = port_fops_fasync, | ||
845 | .llseek = no_llseek, | ||
846 | }; | ||
847 | |||
140 | /* | 848 | /* |
141 | * virtio console configuration. This supports: | 849 | * The put_chars() callback is pretty straightforward. |
142 | * - console resize | 850 | * |
851 | * We turn the characters into a scatter-gather list, add it to the | ||
852 | * output queue and then kick the Host. Then we sit here waiting for | ||
853 | * it to finish: inefficient in theory, but in practice | ||
854 | * implementations will do it immediately (lguest's Launcher does). | ||
143 | */ | 855 | */ |
144 | static void virtcons_apply_config(struct virtio_device *dev) | 856 | static int put_chars(u32 vtermno, const char *buf, int count) |
145 | { | 857 | { |
146 | struct winsize ws; | 858 | struct port *port; |
147 | 859 | ||
148 | if (virtio_has_feature(dev, VIRTIO_CONSOLE_F_SIZE)) { | 860 | if (unlikely(early_put_chars)) |
149 | dev->config->get(dev, | 861 | return early_put_chars(vtermno, buf, count); |
150 | offsetof(struct virtio_console_config, cols), | 862 | |
151 | &ws.ws_col, sizeof(u16)); | 863 | port = find_port_by_vtermno(vtermno); |
152 | dev->config->get(dev, | 864 | if (!port) |
153 | offsetof(struct virtio_console_config, rows), | 865 | return -EPIPE; |
154 | &ws.ws_row, sizeof(u16)); | 866 | |
155 | hvc_resize(hvc, ws); | 867 | return send_buf(port, (void *)buf, count, false); |
156 | } | ||
157 | } | 868 | } |
158 | 869 | ||
159 | /* | 870 | /* |
160 | * we support only one console, the hvc struct is a global var | 871 | * get_chars() is the callback from the hvc_console infrastructure |
161 | * We set the configuration at this point, since we now have a tty | 872 | * when an interrupt is received. |
873 | * | ||
874 | * We call out to fill_readbuf that gets us the required data from the | ||
875 | * buffers that are queued up. | ||
162 | */ | 876 | */ |
877 | static int get_chars(u32 vtermno, char *buf, int count) | ||
878 | { | ||
879 | struct port *port; | ||
880 | |||
881 | /* If we've not set up the port yet, we have no input to give. */ | ||
882 | if (unlikely(early_put_chars)) | ||
883 | return 0; | ||
884 | |||
885 | port = find_port_by_vtermno(vtermno); | ||
886 | if (!port) | ||
887 | return -EPIPE; | ||
888 | |||
889 | /* If we don't have an input queue yet, we can't get input. */ | ||
890 | BUG_ON(!port->in_vq); | ||
891 | |||
892 | return fill_readbuf(port, buf, count, false); | ||
893 | } | ||
894 | |||
895 | static void resize_console(struct port *port) | ||
896 | { | ||
897 | struct virtio_device *vdev; | ||
898 | |||
899 | /* The port could have been hot-unplugged */ | ||
900 | if (!port || !is_console_port(port)) | ||
901 | return; | ||
902 | |||
903 | vdev = port->portdev->vdev; | ||
904 | if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE)) | ||
905 | hvc_resize(port->cons.hvc, port->cons.ws); | ||
906 | } | ||
907 | |||
908 | /* We set the configuration at this point, since we now have a tty */ | ||
163 | static int notifier_add_vio(struct hvc_struct *hp, int data) | 909 | static int notifier_add_vio(struct hvc_struct *hp, int data) |
164 | { | 910 | { |
911 | struct port *port; | ||
912 | |||
913 | port = find_port_by_vtermno(hp->vtermno); | ||
914 | if (!port) | ||
915 | return -EINVAL; | ||
916 | |||
165 | hp->irq_requested = 1; | 917 | hp->irq_requested = 1; |
166 | virtcons_apply_config(vdev); | 918 | resize_console(port); |
167 | 919 | ||
168 | return 0; | 920 | return 0; |
169 | } | 921 | } |
@@ -173,79 +925,879 @@ static void notifier_del_vio(struct hvc_struct *hp, int data) | |||
173 | hp->irq_requested = 0; | 925 | hp->irq_requested = 0; |
174 | } | 926 | } |
175 | 927 | ||
176 | static void hvc_handle_input(struct virtqueue *vq) | 928 | /* The operations for console ports. */ |
929 | static const struct hv_ops hv_ops = { | ||
930 | .get_chars = get_chars, | ||
931 | .put_chars = put_chars, | ||
932 | .notifier_add = notifier_add_vio, | ||
933 | .notifier_del = notifier_del_vio, | ||
934 | .notifier_hangup = notifier_del_vio, | ||
935 | }; | ||
936 | |||
937 | /* | ||
938 | * Console drivers are initialized very early so boot messages can go | ||
939 | * out, so we do things slightly differently from the generic virtio | ||
940 | * initialization of the net and block drivers. | ||
941 | * | ||
942 | * At this stage, the console is output-only. It's too early to set | ||
943 | * up a virtqueue, so we let the drivers do some boutique early-output | ||
944 | * thing. | ||
945 | */ | ||
946 | int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)) | ||
947 | { | ||
948 | early_put_chars = put_chars; | ||
949 | return hvc_instantiate(0, 0, &hv_ops); | ||
950 | } | ||
951 | |||
952 | int init_port_console(struct port *port) | ||
953 | { | ||
954 | int ret; | ||
955 | |||
956 | /* | ||
957 | * The Host's telling us this port is a console port. Hook it | ||
958 | * up with an hvc console. | ||
959 | * | ||
960 | * To set up and manage our virtual console, we call | ||
961 | * hvc_alloc(). | ||
962 | * | ||
963 | * The first argument of hvc_alloc() is the virtual console | ||
964 | * number. The second argument is the parameter for the | ||
965 | * notification mechanism (like irq number). We currently | ||
966 | * leave this as zero, virtqueues have implicit notifications. | ||
967 | * | ||
968 | * The third argument is a "struct hv_ops" containing the | ||
969 | * put_chars() get_chars(), notifier_add() and notifier_del() | ||
970 | * pointers. The final argument is the output buffer size: we | ||
971 | * can do any size, so we put PAGE_SIZE here. | ||
972 | */ | ||
973 | port->cons.vtermno = pdrvdata.next_vtermno; | ||
974 | |||
975 | port->cons.hvc = hvc_alloc(port->cons.vtermno, 0, &hv_ops, PAGE_SIZE); | ||
976 | if (IS_ERR(port->cons.hvc)) { | ||
977 | ret = PTR_ERR(port->cons.hvc); | ||
978 | dev_err(port->dev, | ||
979 | "error %d allocating hvc for port\n", ret); | ||
980 | port->cons.hvc = NULL; | ||
981 | return ret; | ||
982 | } | ||
983 | spin_lock_irq(&pdrvdata_lock); | ||
984 | pdrvdata.next_vtermno++; | ||
985 | list_add_tail(&port->cons.list, &pdrvdata.consoles); | ||
986 | spin_unlock_irq(&pdrvdata_lock); | ||
987 | port->guest_connected = true; | ||
988 | |||
989 | /* | ||
990 | * Start using the new console output if this is the first | ||
991 | * console to come up. | ||
992 | */ | ||
993 | if (early_put_chars) | ||
994 | early_put_chars = NULL; | ||
995 | |||
996 | /* Notify host of port being opened */ | ||
997 | send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 1); | ||
998 | |||
999 | return 0; | ||
1000 | } | ||
1001 | |||
1002 | static ssize_t show_port_name(struct device *dev, | ||
1003 | struct device_attribute *attr, char *buffer) | ||
1004 | { | ||
1005 | struct port *port; | ||
1006 | |||
1007 | port = dev_get_drvdata(dev); | ||
1008 | |||
1009 | return sprintf(buffer, "%s\n", port->name); | ||
1010 | } | ||
1011 | |||
1012 | static DEVICE_ATTR(name, S_IRUGO, show_port_name, NULL); | ||
1013 | |||
1014 | static struct attribute *port_sysfs_entries[] = { | ||
1015 | &dev_attr_name.attr, | ||
1016 | NULL | ||
1017 | }; | ||
1018 | |||
1019 | static struct attribute_group port_attribute_group = { | ||
1020 | .name = NULL, /* put in device directory */ | ||
1021 | .attrs = port_sysfs_entries, | ||
1022 | }; | ||
1023 | |||
1024 | static int debugfs_open(struct inode *inode, struct file *filp) | ||
1025 | { | ||
1026 | filp->private_data = inode->i_private; | ||
1027 | return 0; | ||
1028 | } | ||
1029 | |||
1030 | static ssize_t debugfs_read(struct file *filp, char __user *ubuf, | ||
1031 | size_t count, loff_t *offp) | ||
1032 | { | ||
1033 | struct port *port; | ||
1034 | char *buf; | ||
1035 | ssize_t ret, out_offset, out_count; | ||
1036 | |||
1037 | out_count = 1024; | ||
1038 | buf = kmalloc(out_count, GFP_KERNEL); | ||
1039 | if (!buf) | ||
1040 | return -ENOMEM; | ||
1041 | |||
1042 | port = filp->private_data; | ||
1043 | out_offset = 0; | ||
1044 | out_offset += snprintf(buf + out_offset, out_count, | ||
1045 | "name: %s\n", port->name ? port->name : ""); | ||
1046 | out_offset += snprintf(buf + out_offset, out_count - out_offset, | ||
1047 | "guest_connected: %d\n", port->guest_connected); | ||
1048 | out_offset += snprintf(buf + out_offset, out_count - out_offset, | ||
1049 | "host_connected: %d\n", port->host_connected); | ||
1050 | out_offset += snprintf(buf + out_offset, out_count - out_offset, | ||
1051 | "outvq_full: %d\n", port->outvq_full); | ||
1052 | out_offset += snprintf(buf + out_offset, out_count - out_offset, | ||
1053 | "is_console: %s\n", | ||
1054 | is_console_port(port) ? "yes" : "no"); | ||
1055 | out_offset += snprintf(buf + out_offset, out_count - out_offset, | ||
1056 | "console_vtermno: %u\n", port->cons.vtermno); | ||
1057 | |||
1058 | ret = simple_read_from_buffer(ubuf, count, offp, buf, out_offset); | ||
1059 | kfree(buf); | ||
1060 | return ret; | ||
1061 | } | ||
1062 | |||
1063 | static const struct file_operations port_debugfs_ops = { | ||
1064 | .owner = THIS_MODULE, | ||
1065 | .open = debugfs_open, | ||
1066 | .read = debugfs_read, | ||
1067 | }; | ||
1068 | |||
1069 | static void set_console_size(struct port *port, u16 rows, u16 cols) | ||
1070 | { | ||
1071 | if (!port || !is_console_port(port)) | ||
1072 | return; | ||
1073 | |||
1074 | port->cons.ws.ws_row = rows; | ||
1075 | port->cons.ws.ws_col = cols; | ||
1076 | } | ||
1077 | |||
1078 | static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock) | ||
1079 | { | ||
1080 | struct port_buffer *buf; | ||
1081 | unsigned int nr_added_bufs; | ||
1082 | int ret; | ||
1083 | |||
1084 | nr_added_bufs = 0; | ||
1085 | do { | ||
1086 | buf = alloc_buf(PAGE_SIZE); | ||
1087 | if (!buf) | ||
1088 | break; | ||
1089 | |||
1090 | spin_lock_irq(lock); | ||
1091 | ret = add_inbuf(vq, buf); | ||
1092 | if (ret < 0) { | ||
1093 | spin_unlock_irq(lock); | ||
1094 | free_buf(buf); | ||
1095 | break; | ||
1096 | } | ||
1097 | nr_added_bufs++; | ||
1098 | spin_unlock_irq(lock); | ||
1099 | } while (ret > 0); | ||
1100 | |||
1101 | return nr_added_bufs; | ||
1102 | } | ||
1103 | |||
1104 | static void send_sigio_to_port(struct port *port) | ||
1105 | { | ||
1106 | if (port->async_queue && port->guest_connected) | ||
1107 | kill_fasync(&port->async_queue, SIGIO, POLL_OUT); | ||
1108 | } | ||
1109 | |||
1110 | static int add_port(struct ports_device *portdev, u32 id) | ||
1111 | { | ||
1112 | char debugfs_name[16]; | ||
1113 | struct port *port; | ||
1114 | struct port_buffer *buf; | ||
1115 | dev_t devt; | ||
1116 | unsigned int nr_added_bufs; | ||
1117 | int err; | ||
1118 | |||
1119 | port = kmalloc(sizeof(*port), GFP_KERNEL); | ||
1120 | if (!port) { | ||
1121 | err = -ENOMEM; | ||
1122 | goto fail; | ||
1123 | } | ||
1124 | kref_init(&port->kref); | ||
1125 | |||
1126 | port->portdev = portdev; | ||
1127 | port->id = id; | ||
1128 | |||
1129 | port->name = NULL; | ||
1130 | port->inbuf = NULL; | ||
1131 | port->cons.hvc = NULL; | ||
1132 | port->async_queue = NULL; | ||
1133 | |||
1134 | port->cons.ws.ws_row = port->cons.ws.ws_col = 0; | ||
1135 | |||
1136 | port->host_connected = port->guest_connected = false; | ||
1137 | |||
1138 | port->outvq_full = false; | ||
1139 | |||
1140 | port->in_vq = portdev->in_vqs[port->id]; | ||
1141 | port->out_vq = portdev->out_vqs[port->id]; | ||
1142 | |||
1143 | port->cdev = cdev_alloc(); | ||
1144 | if (!port->cdev) { | ||
1145 | dev_err(&port->portdev->vdev->dev, "Error allocating cdev\n"); | ||
1146 | err = -ENOMEM; | ||
1147 | goto free_port; | ||
1148 | } | ||
1149 | port->cdev->ops = &port_fops; | ||
1150 | |||
1151 | devt = MKDEV(portdev->chr_major, id); | ||
1152 | err = cdev_add(port->cdev, devt, 1); | ||
1153 | if (err < 0) { | ||
1154 | dev_err(&port->portdev->vdev->dev, | ||
1155 | "Error %d adding cdev for port %u\n", err, id); | ||
1156 | goto free_cdev; | ||
1157 | } | ||
1158 | port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev, | ||
1159 | devt, port, "vport%up%u", | ||
1160 | port->portdev->drv_index, id); | ||
1161 | if (IS_ERR(port->dev)) { | ||
1162 | err = PTR_ERR(port->dev); | ||
1163 | dev_err(&port->portdev->vdev->dev, | ||
1164 | "Error %d creating device for port %u\n", | ||
1165 | err, id); | ||
1166 | goto free_cdev; | ||
1167 | } | ||
1168 | |||
1169 | spin_lock_init(&port->inbuf_lock); | ||
1170 | spin_lock_init(&port->outvq_lock); | ||
1171 | init_waitqueue_head(&port->waitqueue); | ||
1172 | |||
1173 | /* Fill the in_vq with buffers so the host can send us data. */ | ||
1174 | nr_added_bufs = fill_queue(port->in_vq, &port->inbuf_lock); | ||
1175 | if (!nr_added_bufs) { | ||
1176 | dev_err(port->dev, "Error allocating inbufs\n"); | ||
1177 | err = -ENOMEM; | ||
1178 | goto free_device; | ||
1179 | } | ||
1180 | |||
1181 | /* | ||
1182 | * If we're not using multiport support, this has to be a console port | ||
1183 | */ | ||
1184 | if (!use_multiport(port->portdev)) { | ||
1185 | err = init_port_console(port); | ||
1186 | if (err) | ||
1187 | goto free_inbufs; | ||
1188 | } | ||
1189 | |||
1190 | spin_lock_irq(&portdev->ports_lock); | ||
1191 | list_add_tail(&port->list, &port->portdev->ports); | ||
1192 | spin_unlock_irq(&portdev->ports_lock); | ||
1193 | |||
1194 | /* | ||
1195 | * Tell the Host we're set so that it can send us various | ||
1196 | * configuration parameters for this port (eg, port name, | ||
1197 | * caching, whether this is a console port, etc.) | ||
1198 | */ | ||
1199 | send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1); | ||
1200 | |||
1201 | if (pdrvdata.debugfs_dir) { | ||
1202 | /* | ||
1203 | * Finally, create the debugfs file that we can use to | ||
1204 | * inspect a port's state at any time | ||
1205 | */ | ||
1206 | sprintf(debugfs_name, "vport%up%u", | ||
1207 | port->portdev->drv_index, id); | ||
1208 | port->debugfs_file = debugfs_create_file(debugfs_name, 0444, | ||
1209 | pdrvdata.debugfs_dir, | ||
1210 | port, | ||
1211 | &port_debugfs_ops); | ||
1212 | } | ||
1213 | return 0; | ||
1214 | |||
1215 | free_inbufs: | ||
1216 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) | ||
1217 | free_buf(buf); | ||
1218 | free_device: | ||
1219 | device_destroy(pdrvdata.class, port->dev->devt); | ||
1220 | free_cdev: | ||
1221 | cdev_del(port->cdev); | ||
1222 | free_port: | ||
1223 | kfree(port); | ||
1224 | fail: | ||
1225 | /* The host might want to notify management sw about port add failure */ | ||
1226 | __send_control_msg(portdev, id, VIRTIO_CONSOLE_PORT_READY, 0); | ||
1227 | return err; | ||
1228 | } | ||
1229 | |||
1230 | /* No users remain, remove all port-specific data. */ | ||
1231 | static void remove_port(struct kref *kref) | ||
1232 | { | ||
1233 | struct port *port; | ||
1234 | |||
1235 | port = container_of(kref, struct port, kref); | ||
1236 | |||
1237 | sysfs_remove_group(&port->dev->kobj, &port_attribute_group); | ||
1238 | device_destroy(pdrvdata.class, port->dev->devt); | ||
1239 | cdev_del(port->cdev); | ||
1240 | |||
1241 | kfree(port->name); | ||
1242 | |||
1243 | debugfs_remove(port->debugfs_file); | ||
1244 | |||
1245 | kfree(port); | ||
1246 | } | ||
1247 | |||
1248 | /* | ||
1249 | * Port got unplugged. Remove port from portdev's list and drop the | ||
1250 | * kref reference. If no userspace has this port opened, it will | ||
1251 | * result in immediate removal the port. | ||
1252 | */ | ||
1253 | static void unplug_port(struct port *port) | ||
1254 | { | ||
1255 | struct port_buffer *buf; | ||
1256 | |||
1257 | spin_lock_irq(&port->portdev->ports_lock); | ||
1258 | list_del(&port->list); | ||
1259 | spin_unlock_irq(&port->portdev->ports_lock); | ||
1260 | |||
1261 | if (port->guest_connected) { | ||
1262 | port->guest_connected = false; | ||
1263 | port->host_connected = false; | ||
1264 | wake_up_interruptible(&port->waitqueue); | ||
1265 | |||
1266 | /* Let the app know the port is going down. */ | ||
1267 | send_sigio_to_port(port); | ||
1268 | } | ||
1269 | |||
1270 | if (is_console_port(port)) { | ||
1271 | spin_lock_irq(&pdrvdata_lock); | ||
1272 | list_del(&port->cons.list); | ||
1273 | spin_unlock_irq(&pdrvdata_lock); | ||
1274 | #if 0 | ||
1275 | /* | ||
1276 | * hvc_remove() not called as removing one hvc port | ||
1277 | * results in other hvc ports getting frozen. | ||
1278 | * | ||
1279 | * Once this is resolved in hvc, this functionality | ||
1280 | * will be enabled. Till that is done, the -EPIPE | ||
1281 | * return from get_chars() above will help | ||
1282 | * hvc_console.c to clean up on ports we remove here. | ||
1283 | */ | ||
1284 | hvc_remove(port->cons.hvc); | ||
1285 | #endif | ||
1286 | } | ||
1287 | |||
1288 | /* Remove unused data this port might have received. */ | ||
1289 | discard_port_data(port); | ||
1290 | |||
1291 | reclaim_consumed_buffers(port); | ||
1292 | |||
1293 | /* Remove buffers we queued up for the Host to send us data in. */ | ||
1294 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) | ||
1295 | free_buf(buf); | ||
1296 | |||
1297 | /* | ||
1298 | * We should just assume the device itself has gone off -- | ||
1299 | * else a close on an open port later will try to send out a | ||
1300 | * control message. | ||
1301 | */ | ||
1302 | port->portdev = NULL; | ||
1303 | |||
1304 | /* | ||
1305 | * Locks around here are not necessary - a port can't be | ||
1306 | * opened after we removed the port struct from ports_list | ||
1307 | * above. | ||
1308 | */ | ||
1309 | kref_put(&port->kref, remove_port); | ||
1310 | } | ||
1311 | |||
1312 | /* Any private messages that the Host and Guest want to share */ | ||
1313 | static void handle_control_message(struct ports_device *portdev, | ||
1314 | struct port_buffer *buf) | ||
177 | { | 1315 | { |
178 | if (hvc_poll(hvc)) | 1316 | struct virtio_console_control *cpkt; |
1317 | struct port *port; | ||
1318 | size_t name_size; | ||
1319 | int err; | ||
1320 | |||
1321 | cpkt = (struct virtio_console_control *)(buf->buf + buf->offset); | ||
1322 | |||
1323 | port = find_port_by_id(portdev, cpkt->id); | ||
1324 | if (!port && cpkt->event != VIRTIO_CONSOLE_PORT_ADD) { | ||
1325 | /* No valid header at start of buffer. Drop it. */ | ||
1326 | dev_dbg(&portdev->vdev->dev, | ||
1327 | "Invalid index %u in control packet\n", cpkt->id); | ||
1328 | return; | ||
1329 | } | ||
1330 | |||
1331 | switch (cpkt->event) { | ||
1332 | case VIRTIO_CONSOLE_PORT_ADD: | ||
1333 | if (port) { | ||
1334 | dev_dbg(&portdev->vdev->dev, | ||
1335 | "Port %u already added\n", port->id); | ||
1336 | send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1); | ||
1337 | break; | ||
1338 | } | ||
1339 | if (cpkt->id >= portdev->config.max_nr_ports) { | ||
1340 | dev_warn(&portdev->vdev->dev, | ||
1341 | "Request for adding port with out-of-bound id %u, max. supported id: %u\n", | ||
1342 | cpkt->id, portdev->config.max_nr_ports - 1); | ||
1343 | break; | ||
1344 | } | ||
1345 | add_port(portdev, cpkt->id); | ||
1346 | break; | ||
1347 | case VIRTIO_CONSOLE_PORT_REMOVE: | ||
1348 | unplug_port(port); | ||
1349 | break; | ||
1350 | case VIRTIO_CONSOLE_CONSOLE_PORT: | ||
1351 | if (!cpkt->value) | ||
1352 | break; | ||
1353 | if (is_console_port(port)) | ||
1354 | break; | ||
1355 | |||
1356 | init_port_console(port); | ||
1357 | /* | ||
1358 | * Could remove the port here in case init fails - but | ||
1359 | * have to notify the host first. | ||
1360 | */ | ||
1361 | break; | ||
1362 | case VIRTIO_CONSOLE_RESIZE: { | ||
1363 | struct { | ||
1364 | __u16 rows; | ||
1365 | __u16 cols; | ||
1366 | } size; | ||
1367 | |||
1368 | if (!is_console_port(port)) | ||
1369 | break; | ||
1370 | |||
1371 | memcpy(&size, buf->buf + buf->offset + sizeof(*cpkt), | ||
1372 | sizeof(size)); | ||
1373 | set_console_size(port, size.rows, size.cols); | ||
1374 | |||
1375 | port->cons.hvc->irq_requested = 1; | ||
1376 | resize_console(port); | ||
1377 | break; | ||
1378 | } | ||
1379 | case VIRTIO_CONSOLE_PORT_OPEN: | ||
1380 | port->host_connected = cpkt->value; | ||
1381 | wake_up_interruptible(&port->waitqueue); | ||
1382 | /* | ||
1383 | * If the host port got closed and the host had any | ||
1384 | * unconsumed buffers, we'll be able to reclaim them | ||
1385 | * now. | ||
1386 | */ | ||
1387 | spin_lock_irq(&port->outvq_lock); | ||
1388 | reclaim_consumed_buffers(port); | ||
1389 | spin_unlock_irq(&port->outvq_lock); | ||
1390 | |||
1391 | /* | ||
1392 | * If the guest is connected, it'll be interested in | ||
1393 | * knowing the host connection state changed. | ||
1394 | */ | ||
1395 | send_sigio_to_port(port); | ||
1396 | break; | ||
1397 | case VIRTIO_CONSOLE_PORT_NAME: | ||
1398 | /* | ||
1399 | * Skip the size of the header and the cpkt to get the size | ||
1400 | * of the name that was sent | ||
1401 | */ | ||
1402 | name_size = buf->len - buf->offset - sizeof(*cpkt) + 1; | ||
1403 | |||
1404 | port->name = kmalloc(name_size, GFP_KERNEL); | ||
1405 | if (!port->name) { | ||
1406 | dev_err(port->dev, | ||
1407 | "Not enough space to store port name\n"); | ||
1408 | break; | ||
1409 | } | ||
1410 | strncpy(port->name, buf->buf + buf->offset + sizeof(*cpkt), | ||
1411 | name_size - 1); | ||
1412 | port->name[name_size - 1] = 0; | ||
1413 | |||
1414 | /* | ||
1415 | * Since we only have one sysfs attribute, 'name', | ||
1416 | * create it only if we have a name for the port. | ||
1417 | */ | ||
1418 | err = sysfs_create_group(&port->dev->kobj, | ||
1419 | &port_attribute_group); | ||
1420 | if (err) { | ||
1421 | dev_err(port->dev, | ||
1422 | "Error %d creating sysfs device attributes\n", | ||
1423 | err); | ||
1424 | } else { | ||
1425 | /* | ||
1426 | * Generate a udev event so that appropriate | ||
1427 | * symlinks can be created based on udev | ||
1428 | * rules. | ||
1429 | */ | ||
1430 | kobject_uevent(&port->dev->kobj, KOBJ_CHANGE); | ||
1431 | } | ||
1432 | break; | ||
1433 | } | ||
1434 | } | ||
1435 | |||
1436 | static void control_work_handler(struct work_struct *work) | ||
1437 | { | ||
1438 | struct ports_device *portdev; | ||
1439 | struct virtqueue *vq; | ||
1440 | struct port_buffer *buf; | ||
1441 | unsigned int len; | ||
1442 | |||
1443 | portdev = container_of(work, struct ports_device, control_work); | ||
1444 | vq = portdev->c_ivq; | ||
1445 | |||
1446 | spin_lock(&portdev->cvq_lock); | ||
1447 | while ((buf = virtqueue_get_buf(vq, &len))) { | ||
1448 | spin_unlock(&portdev->cvq_lock); | ||
1449 | |||
1450 | buf->len = len; | ||
1451 | buf->offset = 0; | ||
1452 | |||
1453 | handle_control_message(portdev, buf); | ||
1454 | |||
1455 | spin_lock(&portdev->cvq_lock); | ||
1456 | if (add_inbuf(portdev->c_ivq, buf) < 0) { | ||
1457 | dev_warn(&portdev->vdev->dev, | ||
1458 | "Error adding buffer to queue\n"); | ||
1459 | free_buf(buf); | ||
1460 | } | ||
1461 | } | ||
1462 | spin_unlock(&portdev->cvq_lock); | ||
1463 | } | ||
1464 | |||
1465 | static void in_intr(struct virtqueue *vq) | ||
1466 | { | ||
1467 | struct port *port; | ||
1468 | unsigned long flags; | ||
1469 | |||
1470 | port = find_port_by_vq(vq->vdev->priv, vq); | ||
1471 | if (!port) | ||
1472 | return; | ||
1473 | |||
1474 | spin_lock_irqsave(&port->inbuf_lock, flags); | ||
1475 | if (!port->inbuf) | ||
1476 | port->inbuf = get_inbuf(port); | ||
1477 | |||
1478 | /* | ||
1479 | * Don't queue up data when port is closed. This condition | ||
1480 | * can be reached when a console port is not yet connected (no | ||
1481 | * tty is spawned) and the host sends out data to console | ||
1482 | * ports. For generic serial ports, the host won't | ||
1483 | * (shouldn't) send data till the guest is connected. | ||
1484 | */ | ||
1485 | if (!port->guest_connected) | ||
1486 | discard_port_data(port); | ||
1487 | |||
1488 | spin_unlock_irqrestore(&port->inbuf_lock, flags); | ||
1489 | |||
1490 | wake_up_interruptible(&port->waitqueue); | ||
1491 | |||
1492 | /* Send a SIGIO indicating new data in case the process asked for it */ | ||
1493 | send_sigio_to_port(port); | ||
1494 | |||
1495 | if (is_console_port(port) && hvc_poll(port->cons.hvc)) | ||
179 | hvc_kick(); | 1496 | hvc_kick(); |
180 | } | 1497 | } |
181 | 1498 | ||
182 | /*D:370 Once we're further in boot, we get probed like any other virtio device. | 1499 | static void control_intr(struct virtqueue *vq) |
183 | * At this stage we set up the output virtqueue. | 1500 | { |
184 | * | 1501 | struct ports_device *portdev; |
185 | * To set up and manage our virtual console, we call hvc_alloc(). Since we | 1502 | |
186 | * never remove the console device we never need this pointer again. | 1503 | portdev = vq->vdev->priv; |
187 | * | 1504 | schedule_work(&portdev->control_work); |
188 | * Finally we put our input buffer in the input queue, ready to receive. */ | 1505 | } |
189 | static int __devinit virtcons_probe(struct virtio_device *dev) | 1506 | |
1507 | static void config_intr(struct virtio_device *vdev) | ||
1508 | { | ||
1509 | struct ports_device *portdev; | ||
1510 | |||
1511 | portdev = vdev->priv; | ||
1512 | |||
1513 | if (!use_multiport(portdev)) { | ||
1514 | struct port *port; | ||
1515 | u16 rows, cols; | ||
1516 | |||
1517 | vdev->config->get(vdev, | ||
1518 | offsetof(struct virtio_console_config, cols), | ||
1519 | &cols, sizeof(u16)); | ||
1520 | vdev->config->get(vdev, | ||
1521 | offsetof(struct virtio_console_config, rows), | ||
1522 | &rows, sizeof(u16)); | ||
1523 | |||
1524 | port = find_port_by_id(portdev, 0); | ||
1525 | set_console_size(port, rows, cols); | ||
1526 | |||
1527 | /* | ||
1528 | * We'll use this way of resizing only for legacy | ||
1529 | * support. For newer userspace | ||
1530 | * (VIRTIO_CONSOLE_F_MULTPORT+), use control messages | ||
1531 | * to indicate console size changes so that it can be | ||
1532 | * done per-port. | ||
1533 | */ | ||
1534 | resize_console(port); | ||
1535 | } | ||
1536 | } | ||
1537 | |||
1538 | static int init_vqs(struct ports_device *portdev) | ||
190 | { | 1539 | { |
191 | vq_callback_t *callbacks[] = { hvc_handle_input, NULL}; | 1540 | vq_callback_t **io_callbacks; |
192 | const char *names[] = { "input", "output" }; | 1541 | char **io_names; |
193 | struct virtqueue *vqs[2]; | 1542 | struct virtqueue **vqs; |
1543 | u32 i, j, nr_ports, nr_queues; | ||
194 | int err; | 1544 | int err; |
195 | 1545 | ||
196 | vdev = dev; | 1546 | nr_ports = portdev->config.max_nr_ports; |
1547 | nr_queues = use_multiport(portdev) ? (nr_ports + 1) * 2 : 2; | ||
197 | 1548 | ||
198 | /* This is the scratch page we use to receive console input */ | 1549 | vqs = kmalloc(nr_queues * sizeof(struct virtqueue *), GFP_KERNEL); |
199 | inbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); | 1550 | if (!vqs) { |
200 | if (!inbuf) { | ||
201 | err = -ENOMEM; | 1551 | err = -ENOMEM; |
202 | goto fail; | 1552 | goto fail; |
203 | } | 1553 | } |
1554 | io_callbacks = kmalloc(nr_queues * sizeof(vq_callback_t *), GFP_KERNEL); | ||
1555 | if (!io_callbacks) { | ||
1556 | err = -ENOMEM; | ||
1557 | goto free_vqs; | ||
1558 | } | ||
1559 | io_names = kmalloc(nr_queues * sizeof(char *), GFP_KERNEL); | ||
1560 | if (!io_names) { | ||
1561 | err = -ENOMEM; | ||
1562 | goto free_callbacks; | ||
1563 | } | ||
1564 | portdev->in_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *), | ||
1565 | GFP_KERNEL); | ||
1566 | if (!portdev->in_vqs) { | ||
1567 | err = -ENOMEM; | ||
1568 | goto free_names; | ||
1569 | } | ||
1570 | portdev->out_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *), | ||
1571 | GFP_KERNEL); | ||
1572 | if (!portdev->out_vqs) { | ||
1573 | err = -ENOMEM; | ||
1574 | goto free_invqs; | ||
1575 | } | ||
204 | 1576 | ||
1577 | /* | ||
1578 | * For backward compat (newer host but older guest), the host | ||
1579 | * spawns a console port first and also inits the vqs for port | ||
1580 | * 0 before others. | ||
1581 | */ | ||
1582 | j = 0; | ||
1583 | io_callbacks[j] = in_intr; | ||
1584 | io_callbacks[j + 1] = NULL; | ||
1585 | io_names[j] = "input"; | ||
1586 | io_names[j + 1] = "output"; | ||
1587 | j += 2; | ||
1588 | |||
1589 | if (use_multiport(portdev)) { | ||
1590 | io_callbacks[j] = control_intr; | ||
1591 | io_callbacks[j + 1] = NULL; | ||
1592 | io_names[j] = "control-i"; | ||
1593 | io_names[j + 1] = "control-o"; | ||
1594 | |||
1595 | for (i = 1; i < nr_ports; i++) { | ||
1596 | j += 2; | ||
1597 | io_callbacks[j] = in_intr; | ||
1598 | io_callbacks[j + 1] = NULL; | ||
1599 | io_names[j] = "input"; | ||
1600 | io_names[j + 1] = "output"; | ||
1601 | } | ||
1602 | } | ||
205 | /* Find the queues. */ | 1603 | /* Find the queues. */ |
206 | /* FIXME: This is why we want to wean off hvc: we do nothing | 1604 | err = portdev->vdev->config->find_vqs(portdev->vdev, nr_queues, vqs, |
207 | * when input comes in. */ | 1605 | io_callbacks, |
208 | err = vdev->config->find_vqs(vdev, 2, vqs, callbacks, names); | 1606 | (const char **)io_names); |
209 | if (err) | 1607 | if (err) |
1608 | goto free_outvqs; | ||
1609 | |||
1610 | j = 0; | ||
1611 | portdev->in_vqs[0] = vqs[0]; | ||
1612 | portdev->out_vqs[0] = vqs[1]; | ||
1613 | j += 2; | ||
1614 | if (use_multiport(portdev)) { | ||
1615 | portdev->c_ivq = vqs[j]; | ||
1616 | portdev->c_ovq = vqs[j + 1]; | ||
1617 | |||
1618 | for (i = 1; i < nr_ports; i++) { | ||
1619 | j += 2; | ||
1620 | portdev->in_vqs[i] = vqs[j]; | ||
1621 | portdev->out_vqs[i] = vqs[j + 1]; | ||
1622 | } | ||
1623 | } | ||
1624 | kfree(io_callbacks); | ||
1625 | kfree(io_names); | ||
1626 | kfree(vqs); | ||
1627 | |||
1628 | return 0; | ||
1629 | |||
1630 | free_names: | ||
1631 | kfree(io_names); | ||
1632 | free_callbacks: | ||
1633 | kfree(io_callbacks); | ||
1634 | free_outvqs: | ||
1635 | kfree(portdev->out_vqs); | ||
1636 | free_invqs: | ||
1637 | kfree(portdev->in_vqs); | ||
1638 | free_vqs: | ||
1639 | kfree(vqs); | ||
1640 | fail: | ||
1641 | return err; | ||
1642 | } | ||
1643 | |||
1644 | static const struct file_operations portdev_fops = { | ||
1645 | .owner = THIS_MODULE, | ||
1646 | }; | ||
1647 | |||
1648 | /* | ||
1649 | * Once we're further in boot, we get probed like any other virtio | ||
1650 | * device. | ||
1651 | * | ||
1652 | * If the host also supports multiple console ports, we check the | ||
1653 | * config space to see how many ports the host has spawned. We | ||
1654 | * initialize each port found. | ||
1655 | */ | ||
1656 | static int __devinit virtcons_probe(struct virtio_device *vdev) | ||
1657 | { | ||
1658 | struct ports_device *portdev; | ||
1659 | int err; | ||
1660 | bool multiport; | ||
1661 | |||
1662 | portdev = kmalloc(sizeof(*portdev), GFP_KERNEL); | ||
1663 | if (!portdev) { | ||
1664 | err = -ENOMEM; | ||
1665 | goto fail; | ||
1666 | } | ||
1667 | |||
1668 | /* Attach this portdev to this virtio_device, and vice-versa. */ | ||
1669 | portdev->vdev = vdev; | ||
1670 | vdev->priv = portdev; | ||
1671 | |||
1672 | spin_lock_irq(&pdrvdata_lock); | ||
1673 | portdev->drv_index = pdrvdata.index++; | ||
1674 | spin_unlock_irq(&pdrvdata_lock); | ||
1675 | |||
1676 | portdev->chr_major = register_chrdev(0, "virtio-portsdev", | ||
1677 | &portdev_fops); | ||
1678 | if (portdev->chr_major < 0) { | ||
1679 | dev_err(&vdev->dev, | ||
1680 | "Error %d registering chrdev for device %u\n", | ||
1681 | portdev->chr_major, portdev->drv_index); | ||
1682 | err = portdev->chr_major; | ||
210 | goto free; | 1683 | goto free; |
1684 | } | ||
211 | 1685 | ||
212 | in_vq = vqs[0]; | 1686 | multiport = false; |
213 | out_vq = vqs[1]; | 1687 | portdev->config.max_nr_ports = 1; |
1688 | if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) { | ||
1689 | multiport = true; | ||
1690 | vdev->features[0] |= 1 << VIRTIO_CONSOLE_F_MULTIPORT; | ||
214 | 1691 | ||
215 | /* Start using the new console output. */ | 1692 | vdev->config->get(vdev, offsetof(struct virtio_console_config, |
216 | virtio_cons.get_chars = get_chars; | 1693 | max_nr_ports), |
217 | virtio_cons.put_chars = put_chars; | 1694 | &portdev->config.max_nr_ports, |
218 | virtio_cons.notifier_add = notifier_add_vio; | 1695 | sizeof(portdev->config.max_nr_ports)); |
219 | virtio_cons.notifier_del = notifier_del_vio; | 1696 | } |
220 | virtio_cons.notifier_hangup = notifier_del_vio; | ||
221 | 1697 | ||
222 | /* The first argument of hvc_alloc() is the virtual console number, so | 1698 | /* Let the Host know we support multiple ports.*/ |
223 | * we use zero. The second argument is the parameter for the | 1699 | vdev->config->finalize_features(vdev); |
224 | * notification mechanism (like irq number). We currently leave this | 1700 | |
225 | * as zero, virtqueues have implicit notifications. | 1701 | err = init_vqs(portdev); |
226 | * | 1702 | if (err < 0) { |
227 | * The third argument is a "struct hv_ops" containing the put_chars() | 1703 | dev_err(&vdev->dev, "Error %d initializing vqs\n", err); |
228 | * get_chars(), notifier_add() and notifier_del() pointers. | 1704 | goto free_chrdev; |
229 | * The final argument is the output buffer size: we can do any size, | ||
230 | * so we put PAGE_SIZE here. */ | ||
231 | hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE); | ||
232 | if (IS_ERR(hvc)) { | ||
233 | err = PTR_ERR(hvc); | ||
234 | goto free_vqs; | ||
235 | } | 1705 | } |
236 | 1706 | ||
237 | /* Register the input buffer the first time. */ | 1707 | spin_lock_init(&portdev->ports_lock); |
238 | add_inbuf(); | 1708 | INIT_LIST_HEAD(&portdev->ports); |
1709 | |||
1710 | if (multiport) { | ||
1711 | unsigned int nr_added_bufs; | ||
1712 | |||
1713 | spin_lock_init(&portdev->cvq_lock); | ||
1714 | INIT_WORK(&portdev->control_work, &control_work_handler); | ||
1715 | |||
1716 | nr_added_bufs = fill_queue(portdev->c_ivq, &portdev->cvq_lock); | ||
1717 | if (!nr_added_bufs) { | ||
1718 | dev_err(&vdev->dev, | ||
1719 | "Error allocating buffers for control queue\n"); | ||
1720 | err = -ENOMEM; | ||
1721 | goto free_vqs; | ||
1722 | } | ||
1723 | } else { | ||
1724 | /* | ||
1725 | * For backward compatibility: Create a console port | ||
1726 | * if we're running on older host. | ||
1727 | */ | ||
1728 | add_port(portdev, 0); | ||
1729 | } | ||
1730 | |||
1731 | spin_lock_irq(&pdrvdata_lock); | ||
1732 | list_add_tail(&portdev->list, &pdrvdata.portdevs); | ||
1733 | spin_unlock_irq(&pdrvdata_lock); | ||
1734 | |||
1735 | __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, | ||
1736 | VIRTIO_CONSOLE_DEVICE_READY, 1); | ||
239 | return 0; | 1737 | return 0; |
240 | 1738 | ||
241 | free_vqs: | 1739 | free_vqs: |
1740 | /* The host might want to notify mgmt sw about device add failure */ | ||
1741 | __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, | ||
1742 | VIRTIO_CONSOLE_DEVICE_READY, 0); | ||
242 | vdev->config->del_vqs(vdev); | 1743 | vdev->config->del_vqs(vdev); |
1744 | kfree(portdev->in_vqs); | ||
1745 | kfree(portdev->out_vqs); | ||
1746 | free_chrdev: | ||
1747 | unregister_chrdev(portdev->chr_major, "virtio-portsdev"); | ||
243 | free: | 1748 | free: |
244 | kfree(inbuf); | 1749 | kfree(portdev); |
245 | fail: | 1750 | fail: |
246 | return err; | 1751 | return err; |
247 | } | 1752 | } |
248 | 1753 | ||
1754 | static void virtcons_remove(struct virtio_device *vdev) | ||
1755 | { | ||
1756 | struct ports_device *portdev; | ||
1757 | struct port *port, *port2; | ||
1758 | |||
1759 | portdev = vdev->priv; | ||
1760 | |||
1761 | spin_lock_irq(&pdrvdata_lock); | ||
1762 | list_del(&portdev->list); | ||
1763 | spin_unlock_irq(&pdrvdata_lock); | ||
1764 | |||
1765 | /* Disable interrupts for vqs */ | ||
1766 | vdev->config->reset(vdev); | ||
1767 | /* Finish up work that's lined up */ | ||
1768 | cancel_work_sync(&portdev->control_work); | ||
1769 | |||
1770 | list_for_each_entry_safe(port, port2, &portdev->ports, list) | ||
1771 | unplug_port(port); | ||
1772 | |||
1773 | unregister_chrdev(portdev->chr_major, "virtio-portsdev"); | ||
1774 | |||
1775 | /* | ||
1776 | * When yanking out a device, we immediately lose the | ||
1777 | * (device-side) queues. So there's no point in keeping the | ||
1778 | * guest side around till we drop our final reference. This | ||
1779 | * also means that any ports which are in an open state will | ||
1780 | * have to just stop using the port, as the vqs are going | ||
1781 | * away. | ||
1782 | */ | ||
1783 | if (use_multiport(portdev)) { | ||
1784 | struct port_buffer *buf; | ||
1785 | unsigned int len; | ||
1786 | |||
1787 | while ((buf = virtqueue_get_buf(portdev->c_ivq, &len))) | ||
1788 | free_buf(buf); | ||
1789 | |||
1790 | while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq))) | ||
1791 | free_buf(buf); | ||
1792 | } | ||
1793 | |||
1794 | vdev->config->del_vqs(vdev); | ||
1795 | kfree(portdev->in_vqs); | ||
1796 | kfree(portdev->out_vqs); | ||
1797 | |||
1798 | kfree(portdev); | ||
1799 | } | ||
1800 | |||
249 | static struct virtio_device_id id_table[] = { | 1801 | static struct virtio_device_id id_table[] = { |
250 | { VIRTIO_ID_CONSOLE, VIRTIO_DEV_ANY_ID }, | 1802 | { VIRTIO_ID_CONSOLE, VIRTIO_DEV_ANY_ID }, |
251 | { 0 }, | 1803 | { 0 }, |
@@ -253,6 +1805,7 @@ static struct virtio_device_id id_table[] = { | |||
253 | 1805 | ||
254 | static unsigned int features[] = { | 1806 | static unsigned int features[] = { |
255 | VIRTIO_CONSOLE_F_SIZE, | 1807 | VIRTIO_CONSOLE_F_SIZE, |
1808 | VIRTIO_CONSOLE_F_MULTIPORT, | ||
256 | }; | 1809 | }; |
257 | 1810 | ||
258 | static struct virtio_driver virtio_console = { | 1811 | static struct virtio_driver virtio_console = { |
@@ -262,14 +1815,42 @@ static struct virtio_driver virtio_console = { | |||
262 | .driver.owner = THIS_MODULE, | 1815 | .driver.owner = THIS_MODULE, |
263 | .id_table = id_table, | 1816 | .id_table = id_table, |
264 | .probe = virtcons_probe, | 1817 | .probe = virtcons_probe, |
265 | .config_changed = virtcons_apply_config, | 1818 | .remove = virtcons_remove, |
1819 | .config_changed = config_intr, | ||
266 | }; | 1820 | }; |
267 | 1821 | ||
268 | static int __init init(void) | 1822 | static int __init init(void) |
269 | { | 1823 | { |
1824 | int err; | ||
1825 | |||
1826 | pdrvdata.class = class_create(THIS_MODULE, "virtio-ports"); | ||
1827 | if (IS_ERR(pdrvdata.class)) { | ||
1828 | err = PTR_ERR(pdrvdata.class); | ||
1829 | pr_err("Error %d creating virtio-ports class\n", err); | ||
1830 | return err; | ||
1831 | } | ||
1832 | |||
1833 | pdrvdata.debugfs_dir = debugfs_create_dir("virtio-ports", NULL); | ||
1834 | if (!pdrvdata.debugfs_dir) { | ||
1835 | pr_warning("Error %ld creating debugfs dir for virtio-ports\n", | ||
1836 | PTR_ERR(pdrvdata.debugfs_dir)); | ||
1837 | } | ||
1838 | INIT_LIST_HEAD(&pdrvdata.consoles); | ||
1839 | INIT_LIST_HEAD(&pdrvdata.portdevs); | ||
1840 | |||
270 | return register_virtio_driver(&virtio_console); | 1841 | return register_virtio_driver(&virtio_console); |
271 | } | 1842 | } |
1843 | |||
1844 | static void __exit fini(void) | ||
1845 | { | ||
1846 | unregister_virtio_driver(&virtio_console); | ||
1847 | |||
1848 | class_destroy(pdrvdata.class); | ||
1849 | if (pdrvdata.debugfs_dir) | ||
1850 | debugfs_remove_recursive(pdrvdata.debugfs_dir); | ||
1851 | } | ||
272 | module_init(init); | 1852 | module_init(init); |
1853 | module_exit(fini); | ||
273 | 1854 | ||
274 | MODULE_DEVICE_TABLE(virtio, id_table); | 1855 | MODULE_DEVICE_TABLE(virtio, id_table); |
275 | MODULE_DESCRIPTION("Virtio console driver"); | 1856 | MODULE_DESCRIPTION("Virtio console driver"); |
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c index 994e1a58b987..12de1202d22c 100644 --- a/drivers/char/vme_scc.c +++ b/drivers/char/vme_scc.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/fcntl.h> | 27 | #include <linux/fcntl.h> |
28 | #include <linux/major.h> | 28 | #include <linux/major.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/slab.h> | ||
31 | #include <linux/miscdevice.h> | 30 | #include <linux/miscdevice.h> |
32 | #include <linux/console.h> | 31 | #include <linux/console.h> |
33 | #include <linux/init.h> | 32 | #include <linux/init.h> |
@@ -136,7 +135,7 @@ static const struct tty_port_operations scc_port_ops = { | |||
136 | * vme_scc_init() and support functions | 135 | * vme_scc_init() and support functions |
137 | *---------------------------------------------------------------------------*/ | 136 | *---------------------------------------------------------------------------*/ |
138 | 137 | ||
139 | static int scc_init_drivers(void) | 138 | static int __init scc_init_drivers(void) |
140 | { | 139 | { |
141 | int error; | 140 | int error; |
142 | 141 | ||
@@ -172,7 +171,7 @@ static int scc_init_drivers(void) | |||
172 | /* ports[] array is indexed by line no (i.e. [0] for ttyS0, [1] for ttyS1). | 171 | /* ports[] array is indexed by line no (i.e. [0] for ttyS0, [1] for ttyS1). |
173 | */ | 172 | */ |
174 | 173 | ||
175 | static void scc_init_portstructs(void) | 174 | static void __init scc_init_portstructs(void) |
176 | { | 175 | { |
177 | struct scc_port *port; | 176 | struct scc_port *port; |
178 | int i; | 177 | int i; |
@@ -195,7 +194,7 @@ static void scc_init_portstructs(void) | |||
195 | 194 | ||
196 | 195 | ||
197 | #ifdef CONFIG_MVME147_SCC | 196 | #ifdef CONFIG_MVME147_SCC |
198 | static int mvme147_scc_init(void) | 197 | static int __init mvme147_scc_init(void) |
199 | { | 198 | { |
200 | struct scc_port *port; | 199 | struct scc_port *port; |
201 | int error; | 200 | int error; |
@@ -298,7 +297,7 @@ fail: | |||
298 | 297 | ||
299 | 298 | ||
300 | #ifdef CONFIG_MVME162_SCC | 299 | #ifdef CONFIG_MVME162_SCC |
301 | static int mvme162_scc_init(void) | 300 | static int __init mvme162_scc_init(void) |
302 | { | 301 | { |
303 | struct scc_port *port; | 302 | struct scc_port *port; |
304 | int error; | 303 | int error; |
@@ -404,7 +403,7 @@ fail: | |||
404 | 403 | ||
405 | 404 | ||
406 | #ifdef CONFIG_BVME6000_SCC | 405 | #ifdef CONFIG_BVME6000_SCC |
407 | static int bvme6000_scc_init(void) | 406 | static int __init bvme6000_scc_init(void) |
408 | { | 407 | { |
409 | struct scc_port *port; | 408 | struct scc_port *port; |
410 | int error; | 409 | int error; |
@@ -503,7 +502,7 @@ fail_free_b_rx: | |||
503 | #endif | 502 | #endif |
504 | 503 | ||
505 | 504 | ||
506 | static int vme_scc_init(void) | 505 | static int __init vme_scc_init(void) |
507 | { | 506 | { |
508 | int res = -ENODEV; | 507 | int res = -ENODEV; |
509 | 508 | ||
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 50faa1fb0f06..a8ec48ed14d9 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -104,6 +104,8 @@ | |||
104 | #include <linux/io.h> | 104 | #include <linux/io.h> |
105 | #include <asm/system.h> | 105 | #include <asm/system.h> |
106 | #include <linux/uaccess.h> | 106 | #include <linux/uaccess.h> |
107 | #include <linux/kdb.h> | ||
108 | #include <linux/ctype.h> | ||
107 | 109 | ||
108 | #define MAX_NR_CON_DRIVER 16 | 110 | #define MAX_NR_CON_DRIVER 16 |
109 | 111 | ||
@@ -187,10 +189,16 @@ static DECLARE_WORK(console_work, console_callback); | |||
187 | * fg_console is the current virtual console, | 189 | * fg_console is the current virtual console, |
188 | * last_console is the last used one, | 190 | * last_console is the last used one, |
189 | * want_console is the console we want to switch to, | 191 | * want_console is the console we want to switch to, |
192 | * saved_* variants are for save/restore around kernel debugger enter/leave | ||
190 | */ | 193 | */ |
191 | int fg_console; | 194 | int fg_console; |
192 | int last_console; | 195 | int last_console; |
193 | int want_console = -1; | 196 | int want_console = -1; |
197 | static int saved_fg_console; | ||
198 | static int saved_last_console; | ||
199 | static int saved_want_console; | ||
200 | static int saved_vc_mode; | ||
201 | static int saved_console_blanked; | ||
194 | 202 | ||
195 | /* | 203 | /* |
196 | * For each existing display, we have a pointer to console currently visible | 204 | * For each existing display, we have a pointer to console currently visible |
@@ -280,8 +288,12 @@ static inline unsigned short *screenpos(struct vc_data *vc, int offset, int view | |||
280 | return p; | 288 | return p; |
281 | } | 289 | } |
282 | 290 | ||
291 | /* Called from the keyboard irq path.. */ | ||
283 | static inline void scrolldelta(int lines) | 292 | static inline void scrolldelta(int lines) |
284 | { | 293 | { |
294 | /* FIXME */ | ||
295 | /* scrolldelta needs some kind of consistency lock, but the BKL was | ||
296 | and still is not protecting versus the scheduled back end */ | ||
285 | scrollback_delta += lines; | 297 | scrollback_delta += lines; |
286 | schedule_console_callback(); | 298 | schedule_console_callback(); |
287 | } | 299 | } |
@@ -698,7 +710,10 @@ void redraw_screen(struct vc_data *vc, int is_switch) | |||
698 | update_attr(vc); | 710 | update_attr(vc); |
699 | clear_buffer_attributes(vc); | 711 | clear_buffer_attributes(vc); |
700 | } | 712 | } |
701 | if (update && vc->vc_mode != KD_GRAPHICS) | 713 | |
714 | /* Forcibly update if we're panicing */ | ||
715 | if ((update && vc->vc_mode != KD_GRAPHICS) || | ||
716 | vt_force_oops_output(vc)) | ||
702 | do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2); | 717 | do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2); |
703 | } | 718 | } |
704 | set_cursor(vc); | 719 | set_cursor(vc); |
@@ -736,6 +751,7 @@ static void visual_init(struct vc_data *vc, int num, int init) | |||
736 | vc->vc_hi_font_mask = 0; | 751 | vc->vc_hi_font_mask = 0; |
737 | vc->vc_complement_mask = 0; | 752 | vc->vc_complement_mask = 0; |
738 | vc->vc_can_do_color = 0; | 753 | vc->vc_can_do_color = 0; |
754 | vc->vc_panic_force_write = false; | ||
739 | vc->vc_sw->con_init(vc, init); | 755 | vc->vc_sw->con_init(vc, init); |
740 | if (!vc->vc_complement_mask) | 756 | if (!vc->vc_complement_mask) |
741 | vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; | 757 | vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; |
@@ -768,6 +784,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ | |||
768 | if (!vc) | 784 | if (!vc) |
769 | return -ENOMEM; | 785 | return -ENOMEM; |
770 | vc_cons[currcons].d = vc; | 786 | vc_cons[currcons].d = vc; |
787 | tty_port_init(&vc->port); | ||
771 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); | 788 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); |
772 | visual_init(vc, currcons, 1); | 789 | visual_init(vc, currcons, 1); |
773 | if (!*vc->vc_uni_pagedir_loc) | 790 | if (!*vc->vc_uni_pagedir_loc) |
@@ -821,7 +838,7 @@ static inline int resize_screen(struct vc_data *vc, int width, int height, | |||
821 | * | 838 | * |
822 | * Resize a virtual console, clipping according to the actual constraints. | 839 | * Resize a virtual console, clipping according to the actual constraints. |
823 | * If the caller passes a tty structure then update the termios winsize | 840 | * If the caller passes a tty structure then update the termios winsize |
824 | * information and perform any neccessary signal handling. | 841 | * information and perform any necessary signal handling. |
825 | * | 842 | * |
826 | * Caller must hold the console semaphore. Takes the termios mutex and | 843 | * Caller must hold the console semaphore. Takes the termios mutex and |
827 | * ctrl_lock of the tty IFF a tty is passed. | 844 | * ctrl_lock of the tty IFF a tty is passed. |
@@ -831,9 +848,10 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, | |||
831 | unsigned int cols, unsigned int lines) | 848 | unsigned int cols, unsigned int lines) |
832 | { | 849 | { |
833 | unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; | 850 | unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; |
851 | unsigned long end; | ||
834 | unsigned int old_cols, old_rows, old_row_size, old_screen_size; | 852 | unsigned int old_cols, old_rows, old_row_size, old_screen_size; |
835 | unsigned int new_cols, new_rows, new_row_size, new_screen_size; | 853 | unsigned int new_cols, new_rows, new_row_size, new_screen_size; |
836 | unsigned int end, user; | 854 | unsigned int user; |
837 | unsigned short *newscreen; | 855 | unsigned short *newscreen; |
838 | 856 | ||
839 | WARN_CONSOLE_UNLOCKED(); | 857 | WARN_CONSOLE_UNLOCKED(); |
@@ -888,22 +906,16 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, | |||
888 | * bottom of buffer | 906 | * bottom of buffer |
889 | */ | 907 | */ |
890 | old_origin += (old_rows - new_rows) * old_row_size; | 908 | old_origin += (old_rows - new_rows) * old_row_size; |
891 | end = vc->vc_scr_end; | ||
892 | } else { | 909 | } else { |
893 | /* | 910 | /* |
894 | * Cursor is in no man's land, copy 1/2 screenful | 911 | * Cursor is in no man's land, copy 1/2 screenful |
895 | * from the top and bottom of cursor position | 912 | * from the top and bottom of cursor position |
896 | */ | 913 | */ |
897 | old_origin += (vc->vc_y - new_rows/2) * old_row_size; | 914 | old_origin += (vc->vc_y - new_rows/2) * old_row_size; |
898 | end = old_origin + (old_row_size * new_rows); | ||
899 | } | 915 | } |
900 | } else | 916 | } |
901 | /* | 917 | |
902 | * Cursor near the top, copy contents from the top of buffer | 918 | end = old_origin + old_row_size * min(old_rows, new_rows); |
903 | */ | ||
904 | end = (old_rows > new_rows) ? old_origin + | ||
905 | (old_row_size * new_rows) : | ||
906 | vc->vc_scr_end; | ||
907 | 919 | ||
908 | update_attr(vc); | 920 | update_attr(vc); |
909 | 921 | ||
@@ -956,12 +968,12 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, | |||
956 | * Resize a virtual console as seen from the console end of things. We | 968 | * Resize a virtual console as seen from the console end of things. We |
957 | * use the common vc_do_resize methods to update the structures. The | 969 | * use the common vc_do_resize methods to update the structures. The |
958 | * caller must hold the console sem to protect console internals and | 970 | * caller must hold the console sem to protect console internals and |
959 | * vc->vc_tty | 971 | * vc->port.tty |
960 | */ | 972 | */ |
961 | 973 | ||
962 | int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) | 974 | int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) |
963 | { | 975 | { |
964 | return vc_do_resize(vc->vc_tty, vc, cols, rows); | 976 | return vc_do_resize(vc->port.tty, vc, cols, rows); |
965 | } | 977 | } |
966 | 978 | ||
967 | /** | 979 | /** |
@@ -1789,8 +1801,8 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) | |||
1789 | vc->vc_state = ESnormal; | 1801 | vc->vc_state = ESnormal; |
1790 | return; | 1802 | return; |
1791 | case ESpalette: | 1803 | case ESpalette: |
1792 | if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) { | 1804 | if (isxdigit(c)) { |
1793 | vc->vc_par[vc->vc_npar++] = (c > '9' ? (c & 0xDF) - 'A' + 10 : c - '0'); | 1805 | vc->vc_par[vc->vc_npar++] = hex_to_bin(c); |
1794 | if (vc->vc_npar == 7) { | 1806 | if (vc->vc_npar == 7) { |
1795 | int i = vc->vc_par[0] * 3, j = 1; | 1807 | int i = vc->vc_par[0] * 3, j = 1; |
1796 | vc->vc_palette[i] = 16 * vc->vc_par[j++]; | 1808 | vc->vc_palette[i] = 16 * vc->vc_par[j++]; |
@@ -2119,8 +2131,6 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co | |||
2119 | uint8_t inverse; | 2131 | uint8_t inverse; |
2120 | uint8_t width; | 2132 | uint8_t width; |
2121 | u16 himask, charmask; | 2133 | u16 himask, charmask; |
2122 | const unsigned char *orig_buf = NULL; | ||
2123 | int orig_count; | ||
2124 | 2134 | ||
2125 | if (in_interrupt()) | 2135 | if (in_interrupt()) |
2126 | return count; | 2136 | return count; |
@@ -2142,8 +2152,6 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co | |||
2142 | release_console_sem(); | 2152 | release_console_sem(); |
2143 | return 0; | 2153 | return 0; |
2144 | } | 2154 | } |
2145 | orig_buf = buf; | ||
2146 | orig_count = count; | ||
2147 | 2155 | ||
2148 | himask = vc->vc_hi_font_mask; | 2156 | himask = vc->vc_hi_font_mask; |
2149 | charmask = himask ? 0x1ff : 0xff; | 2157 | charmask = himask ? 0x1ff : 0xff; |
@@ -2502,7 +2510,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) | |||
2502 | goto quit; | 2510 | goto quit; |
2503 | } | 2511 | } |
2504 | 2512 | ||
2505 | if (vc->vc_mode != KD_TEXT) | 2513 | if (vc->vc_mode != KD_TEXT && !vt_force_oops_output(vc)) |
2506 | goto quit; | 2514 | goto quit; |
2507 | 2515 | ||
2508 | /* undraw cursor first */ | 2516 | /* undraw cursor first */ |
@@ -2608,8 +2616,6 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) | |||
2608 | return -EFAULT; | 2616 | return -EFAULT; |
2609 | ret = 0; | 2617 | ret = 0; |
2610 | 2618 | ||
2611 | lock_kernel(); | ||
2612 | |||
2613 | switch (type) | 2619 | switch (type) |
2614 | { | 2620 | { |
2615 | case TIOCL_SETSEL: | 2621 | case TIOCL_SETSEL: |
@@ -2684,7 +2690,6 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) | |||
2684 | ret = -EINVAL; | 2690 | ret = -EINVAL; |
2685 | break; | 2691 | break; |
2686 | } | 2692 | } |
2687 | unlock_kernel(); | ||
2688 | return ret; | 2693 | return ret; |
2689 | } | 2694 | } |
2690 | 2695 | ||
@@ -2797,12 +2802,12 @@ static int con_open(struct tty_struct *tty, struct file *filp) | |||
2797 | struct vc_data *vc = vc_cons[currcons].d; | 2802 | struct vc_data *vc = vc_cons[currcons].d; |
2798 | 2803 | ||
2799 | /* Still being freed */ | 2804 | /* Still being freed */ |
2800 | if (vc->vc_tty) { | 2805 | if (vc->port.tty) { |
2801 | release_console_sem(); | 2806 | release_console_sem(); |
2802 | return -ERESTARTSYS; | 2807 | return -ERESTARTSYS; |
2803 | } | 2808 | } |
2804 | tty->driver_data = vc; | 2809 | tty->driver_data = vc; |
2805 | vc->vc_tty = tty; | 2810 | vc->port.tty = tty; |
2806 | 2811 | ||
2807 | if (!tty->winsize.ws_row && !tty->winsize.ws_col) { | 2812 | if (!tty->winsize.ws_row && !tty->winsize.ws_col) { |
2808 | tty->winsize.ws_row = vc_cons[currcons].d->vc_rows; | 2813 | tty->winsize.ws_row = vc_cons[currcons].d->vc_rows; |
@@ -2830,7 +2835,7 @@ static void con_shutdown(struct tty_struct *tty) | |||
2830 | struct vc_data *vc = tty->driver_data; | 2835 | struct vc_data *vc = tty->driver_data; |
2831 | BUG_ON(vc == NULL); | 2836 | BUG_ON(vc == NULL); |
2832 | acquire_console_sem(); | 2837 | acquire_console_sem(); |
2833 | vc->vc_tty = NULL; | 2838 | vc->port.tty = NULL; |
2834 | release_console_sem(); | 2839 | release_console_sem(); |
2835 | tty_shutdown(tty); | 2840 | tty_shutdown(tty); |
2836 | } | 2841 | } |
@@ -2912,6 +2917,7 @@ static int __init con_init(void) | |||
2912 | for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) { | 2917 | for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) { |
2913 | vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT); | 2918 | vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT); |
2914 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); | 2919 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); |
2920 | tty_port_init(&vc->port); | ||
2915 | visual_init(vc, currcons, 1); | 2921 | visual_init(vc, currcons, 1); |
2916 | vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT); | 2922 | vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT); |
2917 | vc_init(vc, vc->vc_rows, vc->vc_cols, | 2923 | vc_init(vc, vc->vc_rows, vc->vc_cols, |
@@ -3418,6 +3424,80 @@ int con_is_bound(const struct consw *csw) | |||
3418 | EXPORT_SYMBOL(con_is_bound); | 3424 | EXPORT_SYMBOL(con_is_bound); |
3419 | 3425 | ||
3420 | /** | 3426 | /** |
3427 | * con_debug_enter - prepare the console for the kernel debugger | ||
3428 | * @sw: console driver | ||
3429 | * | ||
3430 | * Called when the console is taken over by the kernel debugger, this | ||
3431 | * function needs to save the current console state, then put the console | ||
3432 | * into a state suitable for the kernel debugger. | ||
3433 | * | ||
3434 | * RETURNS: | ||
3435 | * Zero on success, nonzero if a failure occurred when trying to prepare | ||
3436 | * the console for the debugger. | ||
3437 | */ | ||
3438 | int con_debug_enter(struct vc_data *vc) | ||
3439 | { | ||
3440 | int ret = 0; | ||
3441 | |||
3442 | saved_fg_console = fg_console; | ||
3443 | saved_last_console = last_console; | ||
3444 | saved_want_console = want_console; | ||
3445 | saved_vc_mode = vc->vc_mode; | ||
3446 | saved_console_blanked = console_blanked; | ||
3447 | vc->vc_mode = KD_TEXT; | ||
3448 | console_blanked = 0; | ||
3449 | if (vc->vc_sw->con_debug_enter) | ||
3450 | ret = vc->vc_sw->con_debug_enter(vc); | ||
3451 | #ifdef CONFIG_KGDB_KDB | ||
3452 | /* Set the initial LINES variable if it is not already set */ | ||
3453 | if (vc->vc_rows < 999) { | ||
3454 | int linecount; | ||
3455 | char lns[4]; | ||
3456 | const char *setargs[3] = { | ||
3457 | "set", | ||
3458 | "LINES", | ||
3459 | lns, | ||
3460 | }; | ||
3461 | if (kdbgetintenv(setargs[0], &linecount)) { | ||
3462 | snprintf(lns, 4, "%i", vc->vc_rows); | ||
3463 | kdb_set(2, setargs); | ||
3464 | } | ||
3465 | } | ||
3466 | #endif /* CONFIG_KGDB_KDB */ | ||
3467 | return ret; | ||
3468 | } | ||
3469 | EXPORT_SYMBOL_GPL(con_debug_enter); | ||
3470 | |||
3471 | /** | ||
3472 | * con_debug_leave - restore console state | ||
3473 | * @sw: console driver | ||
3474 | * | ||
3475 | * Restore the console state to what it was before the kernel debugger | ||
3476 | * was invoked. | ||
3477 | * | ||
3478 | * RETURNS: | ||
3479 | * Zero on success, nonzero if a failure occurred when trying to restore | ||
3480 | * the console. | ||
3481 | */ | ||
3482 | int con_debug_leave(void) | ||
3483 | { | ||
3484 | struct vc_data *vc; | ||
3485 | int ret = 0; | ||
3486 | |||
3487 | fg_console = saved_fg_console; | ||
3488 | last_console = saved_last_console; | ||
3489 | want_console = saved_want_console; | ||
3490 | console_blanked = saved_console_blanked; | ||
3491 | vc_cons[fg_console].d->vc_mode = saved_vc_mode; | ||
3492 | |||
3493 | vc = vc_cons[fg_console].d; | ||
3494 | if (vc->vc_sw->con_debug_leave) | ||
3495 | ret = vc->vc_sw->con_debug_leave(vc); | ||
3496 | return ret; | ||
3497 | } | ||
3498 | EXPORT_SYMBOL_GPL(con_debug_leave); | ||
3499 | |||
3500 | /** | ||
3421 | * register_con_driver - register console driver to console layer | 3501 | * register_con_driver - register console driver to console layer |
3422 | * @csw: console driver | 3502 | * @csw: console driver |
3423 | * @first: the first console to take over, minimum value is 0 | 3503 | * @first: the first console to take over, minimum value is 0 |
@@ -3707,7 +3787,8 @@ void do_unblank_screen(int leaving_gfx) | |||
3707 | return; | 3787 | return; |
3708 | } | 3788 | } |
3709 | vc = vc_cons[fg_console].d; | 3789 | vc = vc_cons[fg_console].d; |
3710 | if (vc->vc_mode != KD_TEXT) | 3790 | /* Try to unblank in oops case too */ |
3791 | if (vc->vc_mode != KD_TEXT && !vt_force_oops_output(vc)) | ||
3711 | return; /* but leave console_blanked != 0 */ | 3792 | return; /* but leave console_blanked != 0 */ |
3712 | 3793 | ||
3713 | if (blankinterval) { | 3794 | if (blankinterval) { |
@@ -3716,7 +3797,7 @@ void do_unblank_screen(int leaving_gfx) | |||
3716 | } | 3797 | } |
3717 | 3798 | ||
3718 | console_blanked = 0; | 3799 | console_blanked = 0; |
3719 | if (vc->vc_sw->con_blank(vc, 0, leaving_gfx)) | 3800 | if (vc->vc_sw->con_blank(vc, 0, leaving_gfx) || vt_force_oops_output(vc)) |
3720 | /* Low-level driver cannot restore -> do it ourselves */ | 3801 | /* Low-level driver cannot restore -> do it ourselves */ |
3721 | update_screen(vc); | 3802 | update_screen(vc); |
3722 | if (console_blank_hook) | 3803 | if (console_blank_hook) |
@@ -3971,13 +4052,9 @@ static int con_font_set(struct vc_data *vc, struct console_font_op *op) | |||
3971 | font.charcount = op->charcount; | 4052 | font.charcount = op->charcount; |
3972 | font.height = op->height; | 4053 | font.height = op->height; |
3973 | font.width = op->width; | 4054 | font.width = op->width; |
3974 | font.data = kmalloc(size, GFP_KERNEL); | 4055 | font.data = memdup_user(op->data, size); |
3975 | if (!font.data) | 4056 | if (IS_ERR(font.data)) |
3976 | return -ENOMEM; | 4057 | return PTR_ERR(font.data); |
3977 | if (copy_from_user(font.data, op->data, size)) { | ||
3978 | kfree(font.data); | ||
3979 | return -EFAULT; | ||
3980 | } | ||
3981 | acquire_console_sem(); | 4058 | acquire_console_sem(); |
3982 | if (vc->vc_sw->con_font_set) | 4059 | if (vc->vc_sw->con_font_set) |
3983 | rc = vc->vc_sw->con_font_set(vc, &font, op->flags); | 4060 | rc = vc->vc_sw->con_font_set(vc, &font, op->flags); |
@@ -4105,6 +4182,11 @@ void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org) | |||
4105 | } | 4182 | } |
4106 | } | 4183 | } |
4107 | 4184 | ||
4185 | void vcs_scr_updated(struct vc_data *vc) | ||
4186 | { | ||
4187 | notify_update(vc); | ||
4188 | } | ||
4189 | |||
4108 | /* | 4190 | /* |
4109 | * Visible symbols for modules | 4191 | * Visible symbols for modules |
4110 | */ | 4192 | */ |
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index 6aa10284104a..6b68a0fb4611 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c | |||
@@ -133,7 +133,7 @@ static void vt_event_wait(struct vt_event_wait *vw) | |||
133 | list_add(&vw->list, &vt_events); | 133 | list_add(&vw->list, &vt_events); |
134 | spin_unlock_irqrestore(&vt_event_lock, flags); | 134 | spin_unlock_irqrestore(&vt_event_lock, flags); |
135 | /* Wait for it to pass */ | 135 | /* Wait for it to pass */ |
136 | wait_event_interruptible(vt_event_waitqueue, vw->done); | 136 | wait_event_interruptible_tty(vt_event_waitqueue, vw->done); |
137 | /* Dequeue it */ | 137 | /* Dequeue it */ |
138 | spin_lock_irqsave(&vt_event_lock, flags); | 138 | spin_lock_irqsave(&vt_event_lock, flags); |
139 | list_del(&vw->list); | 139 | list_del(&vw->list); |
@@ -503,13 +503,14 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
503 | struct kbd_struct * kbd; | 503 | struct kbd_struct * kbd; |
504 | unsigned int console; | 504 | unsigned int console; |
505 | unsigned char ucval; | 505 | unsigned char ucval; |
506 | unsigned int uival; | ||
506 | void __user *up = (void __user *)arg; | 507 | void __user *up = (void __user *)arg; |
507 | int i, perm; | 508 | int i, perm; |
508 | int ret = 0; | 509 | int ret = 0; |
509 | 510 | ||
510 | console = vc->vc_num; | 511 | console = vc->vc_num; |
511 | 512 | ||
512 | lock_kernel(); | 513 | tty_lock(); |
513 | 514 | ||
514 | if (!vc_cons_allocated(console)) { /* impossible? */ | 515 | if (!vc_cons_allocated(console)) { /* impossible? */ |
515 | ret = -ENOIOCTLCMD; | 516 | ret = -ENOIOCTLCMD; |
@@ -533,11 +534,14 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
533 | case KIOCSOUND: | 534 | case KIOCSOUND: |
534 | if (!perm) | 535 | if (!perm) |
535 | goto eperm; | 536 | goto eperm; |
536 | /* FIXME: This is an old broken API but we need to keep it | 537 | /* |
537 | supported and somehow separate the historic advertised | 538 | * The use of PIT_TICK_RATE is historic, it used to be |
538 | tick rate from any real one */ | 539 | * the platform-dependent CLOCK_TICK_RATE between 2.6.12 |
540 | * and 2.6.36, which was a minor but unfortunate ABI | ||
541 | * change. | ||
542 | */ | ||
539 | if (arg) | 543 | if (arg) |
540 | arg = CLOCK_TICK_RATE / arg; | 544 | arg = PIT_TICK_RATE / arg; |
541 | kd_mksound(arg, 0); | 545 | kd_mksound(arg, 0); |
542 | break; | 546 | break; |
543 | 547 | ||
@@ -553,11 +557,8 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
553 | */ | 557 | */ |
554 | ticks = HZ * ((arg >> 16) & 0xffff) / 1000; | 558 | ticks = HZ * ((arg >> 16) & 0xffff) / 1000; |
555 | count = ticks ? (arg & 0xffff) : 0; | 559 | count = ticks ? (arg & 0xffff) : 0; |
556 | /* FIXME: This is an old broken API but we need to keep it | ||
557 | supported and somehow separate the historic advertised | ||
558 | tick rate from any real one */ | ||
559 | if (count) | 560 | if (count) |
560 | count = CLOCK_TICK_RATE / count; | 561 | count = PIT_TICK_RATE / count; |
561 | kd_mksound(count, ticks); | 562 | kd_mksound(count, ticks); |
562 | break; | 563 | break; |
563 | } | 564 | } |
@@ -657,7 +658,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
657 | break; | 658 | break; |
658 | 659 | ||
659 | case KDGETMODE: | 660 | case KDGETMODE: |
660 | ucval = vc->vc_mode; | 661 | uival = vc->vc_mode; |
661 | goto setint; | 662 | goto setint; |
662 | 663 | ||
663 | case KDMAPDISP: | 664 | case KDMAPDISP: |
@@ -695,7 +696,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
695 | break; | 696 | break; |
696 | 697 | ||
697 | case KDGKBMODE: | 698 | case KDGKBMODE: |
698 | ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW : | 699 | uival = ((kbd->kbdmode == VC_RAW) ? K_RAW : |
699 | (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW : | 700 | (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW : |
700 | (kbd->kbdmode == VC_UNICODE) ? K_UNICODE : | 701 | (kbd->kbdmode == VC_UNICODE) ? K_UNICODE : |
701 | K_XLATE); | 702 | K_XLATE); |
@@ -717,9 +718,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
717 | break; | 718 | break; |
718 | 719 | ||
719 | case KDGKBMETA: | 720 | case KDGKBMETA: |
720 | ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT); | 721 | uival = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT); |
721 | setint: | 722 | setint: |
722 | ret = put_user(ucval, (int __user *)arg); | 723 | ret = put_user(uival, (int __user *)arg); |
723 | break; | 724 | break; |
724 | 725 | ||
725 | case KDGETKEYCODE: | 726 | case KDGETKEYCODE: |
@@ -949,7 +950,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
949 | for (i = 0; i < MAX_NR_CONSOLES; ++i) | 950 | for (i = 0; i < MAX_NR_CONSOLES; ++i) |
950 | if (! VT_IS_IN_USE(i)) | 951 | if (! VT_IS_IN_USE(i)) |
951 | break; | 952 | break; |
952 | ucval = i < MAX_NR_CONSOLES ? (i+1) : -1; | 953 | uival = i < MAX_NR_CONSOLES ? (i+1) : -1; |
953 | goto setint; | 954 | goto setint; |
954 | 955 | ||
955 | /* | 956 | /* |
@@ -1303,7 +1304,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
1303 | if (!perm) | 1304 | if (!perm) |
1304 | goto eperm; | 1305 | goto eperm; |
1305 | ret = copy_from_user(&ui, up, sizeof(struct unimapinit)); | 1306 | ret = copy_from_user(&ui, up, sizeof(struct unimapinit)); |
1306 | if (!ret) | 1307 | if (ret) |
1308 | ret = -EFAULT; | ||
1309 | else | ||
1307 | con_clear_unimap(vc, &ui); | 1310 | con_clear_unimap(vc, &ui); |
1308 | break; | 1311 | break; |
1309 | } | 1312 | } |
@@ -1334,7 +1337,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
1334 | ret = -ENOIOCTLCMD; | 1337 | ret = -ENOIOCTLCMD; |
1335 | } | 1338 | } |
1336 | out: | 1339 | out: |
1337 | unlock_kernel(); | 1340 | tty_unlock(); |
1338 | return ret; | 1341 | return ret; |
1339 | eperm: | 1342 | eperm: |
1340 | ret = -EPERM; | 1343 | ret = -EPERM; |
@@ -1367,7 +1370,7 @@ void vc_SAK(struct work_struct *work) | |||
1367 | acquire_console_sem(); | 1370 | acquire_console_sem(); |
1368 | vc = vc_con->d; | 1371 | vc = vc_con->d; |
1369 | if (vc) { | 1372 | if (vc) { |
1370 | tty = vc->vc_tty; | 1373 | tty = vc->port.tty; |
1371 | /* | 1374 | /* |
1372 | * SAK should also work in all raw modes and reset | 1375 | * SAK should also work in all raw modes and reset |
1373 | * them properly. | 1376 | * them properly. |
@@ -1501,7 +1504,7 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file, | |||
1501 | 1504 | ||
1502 | console = vc->vc_num; | 1505 | console = vc->vc_num; |
1503 | 1506 | ||
1504 | lock_kernel(); | 1507 | tty_lock(); |
1505 | 1508 | ||
1506 | if (!vc_cons_allocated(console)) { /* impossible? */ | 1509 | if (!vc_cons_allocated(console)) { /* impossible? */ |
1507 | ret = -ENOIOCTLCMD; | 1510 | ret = -ENOIOCTLCMD; |
@@ -1569,11 +1572,11 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file, | |||
1569 | goto fallback; | 1572 | goto fallback; |
1570 | } | 1573 | } |
1571 | out: | 1574 | out: |
1572 | unlock_kernel(); | 1575 | tty_unlock(); |
1573 | return ret; | 1576 | return ret; |
1574 | 1577 | ||
1575 | fallback: | 1578 | fallback: |
1576 | unlock_kernel(); | 1579 | tty_unlock(); |
1577 | return vt_ioctl(tty, file, cmd, arg); | 1580 | return vt_ioctl(tty, file, cmd, arg); |
1578 | } | 1581 | } |
1579 | 1582 | ||
@@ -1759,10 +1762,13 @@ int vt_move_to_console(unsigned int vt, int alloc) | |||
1759 | return -EIO; | 1762 | return -EIO; |
1760 | } | 1763 | } |
1761 | release_console_sem(); | 1764 | release_console_sem(); |
1765 | tty_lock(); | ||
1762 | if (vt_waitactive(vt + 1)) { | 1766 | if (vt_waitactive(vt + 1)) { |
1763 | pr_debug("Suspend: Can't switch VCs."); | 1767 | pr_debug("Suspend: Can't switch VCs."); |
1768 | tty_unlock(); | ||
1764 | return -EINTR; | 1769 | return -EINTR; |
1765 | } | 1770 | } |
1771 | tty_unlock(); | ||
1766 | return prev; | 1772 | return prev; |
1767 | } | 1773 | } |
1768 | 1774 | ||
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index 4846d50199f3..9f2272e6de1c 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c | |||
@@ -81,11 +81,11 @@ | |||
81 | #include <linux/poll.h> | 81 | #include <linux/poll.h> |
82 | #include <linux/proc_fs.h> | 82 | #include <linux/proc_fs.h> |
83 | #include <linux/mutex.h> | 83 | #include <linux/mutex.h> |
84 | #include <linux/smp_lock.h> | ||
85 | #include <linux/sysctl.h> | 84 | #include <linux/sysctl.h> |
86 | #include <linux/fs.h> | 85 | #include <linux/fs.h> |
87 | #include <linux/cdev.h> | 86 | #include <linux/cdev.h> |
88 | #include <linux/platform_device.h> | 87 | #include <linux/platform_device.h> |
88 | #include <linux/slab.h> | ||
89 | 89 | ||
90 | #include <asm/io.h> | 90 | #include <asm/io.h> |
91 | #include <asm/uaccess.h> | 91 | #include <asm/uaccess.h> |
@@ -93,6 +93,7 @@ | |||
93 | 93 | ||
94 | #ifdef CONFIG_OF | 94 | #ifdef CONFIG_OF |
95 | /* For open firmware. */ | 95 | /* For open firmware. */ |
96 | #include <linux/of_address.h> | ||
96 | #include <linux/of_device.h> | 97 | #include <linux/of_device.h> |
97 | #include <linux/of_platform.h> | 98 | #include <linux/of_platform.h> |
98 | #endif | 99 | #endif |
@@ -110,6 +111,7 @@ | |||
110 | #define HWICAP_DEVICES 1 | 111 | #define HWICAP_DEVICES 1 |
111 | 112 | ||
112 | /* An array, which is set to true when the device is registered. */ | 113 | /* An array, which is set to true when the device is registered. */ |
114 | static DEFINE_MUTEX(hwicap_mutex); | ||
113 | static bool probed_devices[HWICAP_DEVICES]; | 115 | static bool probed_devices[HWICAP_DEVICES]; |
114 | static struct mutex icap_sem; | 116 | static struct mutex icap_sem; |
115 | 117 | ||
@@ -500,7 +502,7 @@ static int hwicap_open(struct inode *inode, struct file *file) | |||
500 | struct hwicap_drvdata *drvdata; | 502 | struct hwicap_drvdata *drvdata; |
501 | int status; | 503 | int status; |
502 | 504 | ||
503 | lock_kernel(); | 505 | mutex_lock(&hwicap_mutex); |
504 | drvdata = container_of(inode->i_cdev, struct hwicap_drvdata, cdev); | 506 | drvdata = container_of(inode->i_cdev, struct hwicap_drvdata, cdev); |
505 | 507 | ||
506 | status = mutex_lock_interruptible(&drvdata->sem); | 508 | status = mutex_lock_interruptible(&drvdata->sem); |
@@ -526,7 +528,7 @@ static int hwicap_open(struct inode *inode, struct file *file) | |||
526 | error: | 528 | error: |
527 | mutex_unlock(&drvdata->sem); | 529 | mutex_unlock(&drvdata->sem); |
528 | out: | 530 | out: |
529 | unlock_kernel(); | 531 | mutex_unlock(&hwicap_mutex); |
530 | return status; | 532 | return status; |
531 | } | 533 | } |
532 | 534 | ||
@@ -565,6 +567,7 @@ static const struct file_operations hwicap_fops = { | |||
565 | .read = hwicap_read, | 567 | .read = hwicap_read, |
566 | .open = hwicap_open, | 568 | .open = hwicap_open, |
567 | .release = hwicap_release, | 569 | .release = hwicap_release, |
570 | .llseek = noop_llseek, | ||
568 | }; | 571 | }; |
569 | 572 | ||
570 | static int __devinit hwicap_setup(struct device *dev, int id, | 573 | static int __devinit hwicap_setup(struct device *dev, int id, |
@@ -760,7 +763,7 @@ static struct platform_driver hwicap_platform_driver = { | |||
760 | 763 | ||
761 | #if defined(CONFIG_OF) | 764 | #if defined(CONFIG_OF) |
762 | static int __devinit | 765 | static int __devinit |
763 | hwicap_of_probe(struct of_device *op, const struct of_device_id *match) | 766 | hwicap_of_probe(struct platform_device *op, const struct of_device_id *match) |
764 | { | 767 | { |
765 | struct resource res; | 768 | struct resource res; |
766 | const unsigned int *id; | 769 | const unsigned int *id; |
@@ -771,18 +774,18 @@ hwicap_of_probe(struct of_device *op, const struct of_device_id *match) | |||
771 | 774 | ||
772 | dev_dbg(&op->dev, "hwicap_of_probe(%p, %p)\n", op, match); | 775 | dev_dbg(&op->dev, "hwicap_of_probe(%p, %p)\n", op, match); |
773 | 776 | ||
774 | rc = of_address_to_resource(op->node, 0, &res); | 777 | rc = of_address_to_resource(op->dev.of_node, 0, &res); |
775 | if (rc) { | 778 | if (rc) { |
776 | dev_err(&op->dev, "invalid address\n"); | 779 | dev_err(&op->dev, "invalid address\n"); |
777 | return rc; | 780 | return rc; |
778 | } | 781 | } |
779 | 782 | ||
780 | id = of_get_property(op->node, "port-number", NULL); | 783 | id = of_get_property(op->dev.of_node, "port-number", NULL); |
781 | 784 | ||
782 | /* It's most likely that we're using V4, if the family is not | 785 | /* It's most likely that we're using V4, if the family is not |
783 | specified */ | 786 | specified */ |
784 | regs = &v4_config_registers; | 787 | regs = &v4_config_registers; |
785 | family = of_get_property(op->node, "xlnx,family", NULL); | 788 | family = of_get_property(op->dev.of_node, "xlnx,family", NULL); |
786 | 789 | ||
787 | if (family) { | 790 | if (family) { |
788 | if (!strcmp(family, "virtex2p")) { | 791 | if (!strcmp(family, "virtex2p")) { |
@@ -797,7 +800,7 @@ hwicap_of_probe(struct of_device *op, const struct of_device_id *match) | |||
797 | regs); | 800 | regs); |
798 | } | 801 | } |
799 | 802 | ||
800 | static int __devexit hwicap_of_remove(struct of_device *op) | 803 | static int __devexit hwicap_of_remove(struct platform_device *op) |
801 | { | 804 | { |
802 | return hwicap_remove(&op->dev); | 805 | return hwicap_remove(&op->dev); |
803 | } | 806 | } |
@@ -811,13 +814,12 @@ static const struct of_device_id __devinitconst hwicap_of_match[] = { | |||
811 | MODULE_DEVICE_TABLE(of, hwicap_of_match); | 814 | MODULE_DEVICE_TABLE(of, hwicap_of_match); |
812 | 815 | ||
813 | static struct of_platform_driver hwicap_of_driver = { | 816 | static struct of_platform_driver hwicap_of_driver = { |
814 | .owner = THIS_MODULE, | ||
815 | .name = DRIVER_NAME, | ||
816 | .match_table = hwicap_of_match, | ||
817 | .probe = hwicap_of_probe, | 817 | .probe = hwicap_of_probe, |
818 | .remove = __devexit_p(hwicap_of_remove), | 818 | .remove = __devexit_p(hwicap_of_remove), |
819 | .driver = { | 819 | .driver = { |
820 | .name = DRIVER_NAME, | 820 | .name = DRIVER_NAME, |
821 | .owner = THIS_MODULE, | ||
822 | .of_match_table = hwicap_of_match, | ||
821 | }, | 823 | }, |
822 | }; | 824 | }; |
823 | 825 | ||