aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/generic_serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/generic_serial.c')
-rw-r--r--drivers/char/generic_serial.c120
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);
62void gs_put_char(struct tty_struct * tty, unsigned char ch) 52void 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
177int 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");