diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/generic_serial.c | 120 |
1 files changed, 3 insertions, 117 deletions
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index 8ea02755b1c9..8facf3e25c49 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c | |||
@@ -43,16 +43,6 @@ static int gs_debug; | |||
43 | 43 | ||
44 | #define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __FUNCTION__) | 44 | #define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __FUNCTION__) |
45 | #define func_exit() gs_dprintk (GS_DEBUG_FLOW, "gs: exit %s\n", __FUNCTION__) | 45 | #define func_exit() gs_dprintk (GS_DEBUG_FLOW, "gs: exit %s\n", __FUNCTION__) |
46 | #define NEW_WRITE_LOCKING 1 | ||
47 | #if NEW_WRITE_LOCKING | ||
48 | #define DECL /* Nothing */ | ||
49 | #define LOCKIT mutex_lock(& port->port_write_mutex); | ||
50 | #define RELEASEIT mutex_unlock(&port->port_write_mutex); | ||
51 | #else | ||
52 | #define DECL unsigned long flags; | ||
53 | #define LOCKIT save_flags (flags);cli () | ||
54 | #define RELEASEIT restore_flags (flags) | ||
55 | #endif | ||
56 | 46 | ||
57 | #define RS_EVENT_WRITE_WAKEUP 1 | 47 | #define RS_EVENT_WRITE_WAKEUP 1 |
58 | 48 | ||
@@ -62,7 +52,6 @@ module_param(gs_debug, int, 0644); | |||
62 | void gs_put_char(struct tty_struct * tty, unsigned char ch) | 52 | void gs_put_char(struct tty_struct * tty, unsigned char ch) |
63 | { | 53 | { |
64 | struct gs_port *port; | 54 | struct gs_port *port; |
65 | DECL | ||
66 | 55 | ||
67 | func_enter (); | 56 | func_enter (); |
68 | 57 | ||
@@ -75,11 +64,11 @@ void gs_put_char(struct tty_struct * tty, unsigned char ch) | |||
75 | if (! (port->flags & ASYNC_INITIALIZED)) return; | 64 | if (! (port->flags & ASYNC_INITIALIZED)) return; |
76 | 65 | ||
77 | /* Take a lock on the serial tranmit buffer! */ | 66 | /* Take a lock on the serial tranmit buffer! */ |
78 | LOCKIT; | 67 | mutex_lock(& port->port_write_mutex); |
79 | 68 | ||
80 | if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { | 69 | if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { |
81 | /* Sorry, buffer is full, drop character. Update statistics???? -- REW */ | 70 | /* Sorry, buffer is full, drop character. Update statistics???? -- REW */ |
82 | RELEASEIT; | 71 | mutex_unlock(&port->port_write_mutex); |
83 | return; | 72 | return; |
84 | } | 73 | } |
85 | 74 | ||
@@ -87,13 +76,11 @@ void gs_put_char(struct tty_struct * tty, unsigned char ch) | |||
87 | port->xmit_head &= SERIAL_XMIT_SIZE - 1; | 76 | port->xmit_head &= SERIAL_XMIT_SIZE - 1; |
88 | port->xmit_cnt++; /* Characters in buffer */ | 77 | port->xmit_cnt++; /* Characters in buffer */ |
89 | 78 | ||
90 | RELEASEIT; | 79 | mutex_unlock(&port->port_write_mutex); |
91 | func_exit (); | 80 | func_exit (); |
92 | } | 81 | } |
93 | 82 | ||
94 | 83 | ||
95 | #ifdef NEW_WRITE_LOCKING | ||
96 | |||
97 | /* | 84 | /* |
98 | > Problems to take into account are: | 85 | > Problems to take into account are: |
99 | > -1- Interrupts that empty part of the buffer. | 86 | > -1- Interrupts that empty part of the buffer. |
@@ -166,90 +153,6 @@ int gs_write(struct tty_struct * tty, | |||
166 | func_exit (); | 153 | func_exit (); |
167 | return total; | 154 | return total; |
168 | } | 155 | } |
169 | #else | ||
170 | /* | ||
171 | > Problems to take into account are: | ||
172 | > -1- Interrupts that empty part of the buffer. | ||
173 | > -2- page faults on the access to userspace. | ||
174 | > -3- Other processes that are also trying to do a "write". | ||
175 | */ | ||
176 | |||
177 | int gs_write(struct tty_struct * tty, | ||
178 | const unsigned char *buf, int count) | ||
179 | { | ||
180 | struct gs_port *port; | ||
181 | int c, total = 0; | ||
182 | int t; | ||
183 | unsigned long flags; | ||
184 | |||
185 | func_enter (); | ||
186 | |||
187 | /* The standard serial driver returns 0 in this case. | ||
188 | That sounds to me as "No error, I just didn't get to writing any | ||
189 | bytes. Feel free to try again." | ||
190 | The "official" way to write n bytes from buf is: | ||
191 | |||
192 | for (nwritten = 0;nwritten < n;nwritten += rv) { | ||
193 | rv = write (fd, buf+nwritten, n-nwritten); | ||
194 | if (rv < 0) break; // Error: bail out. // | ||
195 | } | ||
196 | |||
197 | which will loop endlessly in this case. The manual page for write | ||
198 | agrees with me. In practise almost everybody writes | ||
199 | "write (fd, buf,n);" but some people might have had to deal with | ||
200 | incomplete writes in the past and correctly implemented it by now... | ||
201 | */ | ||
202 | |||
203 | if (!tty) return -EIO; | ||
204 | |||
205 | port = tty->driver_data; | ||
206 | if (!port || !port->xmit_buf) | ||
207 | return -EIO; | ||
208 | |||
209 | local_save_flags(flags); | ||
210 | while (1) { | ||
211 | cli(); | ||
212 | c = count; | ||
213 | |||
214 | /* This is safe because we "OWN" the "head". Noone else can | ||
215 | change the "head": we own the port_write_mutex. */ | ||
216 | /* Don't overrun the end of the buffer */ | ||
217 | t = SERIAL_XMIT_SIZE - port->xmit_head; | ||
218 | if (t < c) c = t; | ||
219 | |||
220 | /* This is safe because the xmit_cnt can only decrease. This | ||
221 | would increase "t", so we might copy too little chars. */ | ||
222 | /* Don't copy past the "head" of the buffer */ | ||
223 | t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; | ||
224 | if (t < c) c = t; | ||
225 | |||
226 | /* Can't copy more? break out! */ | ||
227 | if (c <= 0) { | ||
228 | local_restore_flags(flags); | ||
229 | break; | ||
230 | } | ||
231 | memcpy(port->xmit_buf + port->xmit_head, buf, c); | ||
232 | port->xmit_head = ((port->xmit_head + c) & | ||
233 | (SERIAL_XMIT_SIZE-1)); | ||
234 | port->xmit_cnt += c; | ||
235 | local_restore_flags(flags); | ||
236 | buf += c; | ||
237 | count -= c; | ||
238 | total += c; | ||
239 | } | ||
240 | |||
241 | if (port->xmit_cnt && | ||
242 | !tty->stopped && | ||
243 | !tty->hw_stopped && | ||
244 | !(port->flags & GS_TX_INTEN)) { | ||
245 | port->flags |= GS_TX_INTEN; | ||
246 | port->rd->enable_tx_interrupts (port); | ||
247 | } | ||
248 | func_exit (); | ||
249 | return total; | ||
250 | } | ||
251 | |||
252 | #endif | ||
253 | 156 | ||
254 | 157 | ||
255 | 158 | ||
@@ -737,23 +640,6 @@ void gs_set_termios (struct tty_struct * tty, | |||
737 | gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp); | 640 | gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp); |
738 | } | 641 | } |
739 | 642 | ||
740 | /* This is an optimization that is only allowed for dumb cards */ | ||
741 | /* Smart cards require knowledge of iflags and oflags too: that | ||
742 | might change hardware cooking mode.... */ | ||
743 | if (old_termios) { | ||
744 | if( (tiosp->c_iflag == old_termios->c_iflag) | ||
745 | && (tiosp->c_oflag == old_termios->c_oflag) | ||
746 | && (tiosp->c_cflag == old_termios->c_cflag) | ||
747 | && (tiosp->c_lflag == old_termios->c_lflag) | ||
748 | && (tiosp->c_line == old_termios->c_line) | ||
749 | && (memcmp(tiosp->c_cc, old_termios->c_cc, NCC) == 0)) { | ||
750 | gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: optimized away\n"); | ||
751 | return /* 0 */; | ||
752 | } | ||
753 | } else | ||
754 | gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: no old_termios: " | ||
755 | "no optimization\n"); | ||
756 | |||
757 | if(old_termios && (gs_debug & GS_DEBUG_TERMIOS)) { | 643 | if(old_termios && (gs_debug & GS_DEBUG_TERMIOS)) { |
758 | if(tiosp->c_iflag != old_termios->c_iflag) printk("c_iflag changed\n"); | 644 | if(tiosp->c_iflag != old_termios->c_iflag) printk("c_iflag changed\n"); |
759 | if(tiosp->c_oflag != old_termios->c_oflag) printk("c_oflag changed\n"); | 645 | if(tiosp->c_oflag != old_termios->c_oflag) printk("c_oflag changed\n"); |