diff options
-rw-r--r-- | drivers/tty/n_tty.c | 7 | ||||
-rw-r--r-- | drivers/tty/pty.c | 2 | ||||
-rw-r--r-- | drivers/tty/tty_buffer.c | 102 | ||||
-rw-r--r-- | drivers/tty/tty_io.c | 2 | ||||
-rw-r--r-- | drivers/tty/tty_ldisc.c | 10 | ||||
-rw-r--r-- | drivers/tty/tty_port.c | 2 | ||||
-rw-r--r-- | include/linux/tty.h | 6 | ||||
-rw-r--r-- | include/linux/tty_flip.h | 2 |
8 files changed, 70 insertions, 63 deletions
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 531e539dbfc..60b076cc4e2 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c | |||
@@ -149,8 +149,11 @@ static void n_tty_set_room(struct tty_struct *tty) | |||
149 | tty->receive_room = left; | 149 | tty->receive_room = left; |
150 | 150 | ||
151 | /* Did this open up the receive buffer? We may need to flip */ | 151 | /* Did this open up the receive buffer? We may need to flip */ |
152 | if (left && !old_left) | 152 | if (left && !old_left) { |
153 | schedule_work(&tty->buf.work); | 153 | WARN_RATELIMIT(tty->port->itty == NULL, |
154 | "scheduling with invalid itty"); | ||
155 | schedule_work(&tty->port->buf.work); | ||
156 | } | ||
154 | } | 157 | } |
155 | 158 | ||
156 | static void put_tty_queue_nolock(unsigned char c, struct n_tty_data *ldata) | 159 | static void put_tty_queue_nolock(unsigned char c, struct n_tty_data *ldata) |
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index c3269086267..4219f040adb 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c | |||
@@ -93,7 +93,7 @@ static void pty_unthrottle(struct tty_struct *tty) | |||
93 | 93 | ||
94 | static int pty_space(struct tty_struct *to) | 94 | static int pty_space(struct tty_struct *to) |
95 | { | 95 | { |
96 | int n = 8192 - to->buf.memory_used; | 96 | int n = 8192 - to->port->buf.memory_used; |
97 | if (n < 0) | 97 | if (n < 0) |
98 | return 0; | 98 | return 0; |
99 | return n; | 99 | return n; |
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index ddd74d41cbb..06725f5cc81 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c | |||
@@ -27,9 +27,9 @@ | |||
27 | * Locking: none | 27 | * Locking: none |
28 | */ | 28 | */ |
29 | 29 | ||
30 | void tty_buffer_free_all(struct tty_struct *tty) | 30 | void tty_buffer_free_all(struct tty_port *port) |
31 | { | 31 | { |
32 | struct tty_bufhead *buf = &tty->buf; | 32 | struct tty_bufhead *buf = &port->buf; |
33 | struct tty_buffer *thead; | 33 | struct tty_buffer *thead; |
34 | 34 | ||
35 | while ((thead = buf->head) != NULL) { | 35 | while ((thead = buf->head) != NULL) { |
@@ -56,11 +56,11 @@ void tty_buffer_free_all(struct tty_struct *tty) | |||
56 | * Locking: Caller must hold tty->buf.lock | 56 | * Locking: Caller must hold tty->buf.lock |
57 | */ | 57 | */ |
58 | 58 | ||
59 | static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size) | 59 | static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size) |
60 | { | 60 | { |
61 | struct tty_buffer *p; | 61 | struct tty_buffer *p; |
62 | 62 | ||
63 | if (tty->buf.memory_used + size > 65536) | 63 | if (port->buf.memory_used + size > 65536) |
64 | return NULL; | 64 | return NULL; |
65 | p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); | 65 | p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); |
66 | if (p == NULL) | 66 | if (p == NULL) |
@@ -72,7 +72,7 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size) | |||
72 | p->read = 0; | 72 | p->read = 0; |
73 | p->char_buf_ptr = (char *)(p->data); | 73 | p->char_buf_ptr = (char *)(p->data); |
74 | p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size; | 74 | p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size; |
75 | tty->buf.memory_used += size; | 75 | port->buf.memory_used += size; |
76 | return p; | 76 | return p; |
77 | } | 77 | } |
78 | 78 | ||
@@ -87,9 +87,9 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size) | |||
87 | * Locking: Caller must hold tty->buf.lock | 87 | * Locking: Caller must hold tty->buf.lock |
88 | */ | 88 | */ |
89 | 89 | ||
90 | static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b) | 90 | static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b) |
91 | { | 91 | { |
92 | struct tty_bufhead *buf = &tty->buf; | 92 | struct tty_bufhead *buf = &port->buf; |
93 | 93 | ||
94 | /* Dumb strategy for now - should keep some stats */ | 94 | /* Dumb strategy for now - should keep some stats */ |
95 | buf->memory_used -= b->size; | 95 | buf->memory_used -= b->size; |
@@ -114,14 +114,14 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b) | |||
114 | * Locking: Caller must hold tty->buf.lock | 114 | * Locking: Caller must hold tty->buf.lock |
115 | */ | 115 | */ |
116 | 116 | ||
117 | static void __tty_buffer_flush(struct tty_struct *tty) | 117 | static void __tty_buffer_flush(struct tty_port *port) |
118 | { | 118 | { |
119 | struct tty_bufhead *buf = &tty->buf; | 119 | struct tty_bufhead *buf = &port->buf; |
120 | struct tty_buffer *thead; | 120 | struct tty_buffer *thead; |
121 | 121 | ||
122 | while ((thead = buf->head) != NULL) { | 122 | while ((thead = buf->head) != NULL) { |
123 | buf->head = thead->next; | 123 | buf->head = thead->next; |
124 | tty_buffer_free(tty, thead); | 124 | tty_buffer_free(port, thead); |
125 | } | 125 | } |
126 | buf->tail = NULL; | 126 | buf->tail = NULL; |
127 | } | 127 | } |
@@ -140,7 +140,7 @@ static void __tty_buffer_flush(struct tty_struct *tty) | |||
140 | void tty_buffer_flush(struct tty_struct *tty) | 140 | void tty_buffer_flush(struct tty_struct *tty) |
141 | { | 141 | { |
142 | struct tty_port *port = tty->port; | 142 | struct tty_port *port = tty->port; |
143 | struct tty_bufhead *buf = &tty->buf; | 143 | struct tty_bufhead *buf = &port->buf; |
144 | unsigned long flags; | 144 | unsigned long flags; |
145 | 145 | ||
146 | spin_lock_irqsave(&buf->lock, flags); | 146 | spin_lock_irqsave(&buf->lock, flags); |
@@ -155,7 +155,7 @@ void tty_buffer_flush(struct tty_struct *tty) | |||
155 | test_bit(TTYP_FLUSHPENDING, &port->iflags) == 0); | 155 | test_bit(TTYP_FLUSHPENDING, &port->iflags) == 0); |
156 | return; | 156 | return; |
157 | } else | 157 | } else |
158 | __tty_buffer_flush(tty); | 158 | __tty_buffer_flush(port); |
159 | spin_unlock_irqrestore(&buf->lock, flags); | 159 | spin_unlock_irqrestore(&buf->lock, flags); |
160 | } | 160 | } |
161 | 161 | ||
@@ -171,9 +171,9 @@ void tty_buffer_flush(struct tty_struct *tty) | |||
171 | * Locking: Caller must hold tty->buf.lock | 171 | * Locking: Caller must hold tty->buf.lock |
172 | */ | 172 | */ |
173 | 173 | ||
174 | static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size) | 174 | static struct tty_buffer *tty_buffer_find(struct tty_port *port, size_t size) |
175 | { | 175 | { |
176 | struct tty_buffer **tbh = &tty->buf.free; | 176 | struct tty_buffer **tbh = &port->buf.free; |
177 | while ((*tbh) != NULL) { | 177 | while ((*tbh) != NULL) { |
178 | struct tty_buffer *t = *tbh; | 178 | struct tty_buffer *t = *tbh; |
179 | if (t->size >= size) { | 179 | if (t->size >= size) { |
@@ -182,14 +182,14 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size) | |||
182 | t->used = 0; | 182 | t->used = 0; |
183 | t->commit = 0; | 183 | t->commit = 0; |
184 | t->read = 0; | 184 | t->read = 0; |
185 | tty->buf.memory_used += t->size; | 185 | port->buf.memory_used += t->size; |
186 | return t; | 186 | return t; |
187 | } | 187 | } |
188 | tbh = &((*tbh)->next); | 188 | tbh = &((*tbh)->next); |
189 | } | 189 | } |
190 | /* Round the buffer size out */ | 190 | /* Round the buffer size out */ |
191 | size = (size + 0xFF) & ~0xFF; | 191 | size = (size + 0xFF) & ~0xFF; |
192 | return tty_buffer_alloc(tty, size); | 192 | return tty_buffer_alloc(port, size); |
193 | /* Should possibly check if this fails for the largest buffer we | 193 | /* Should possibly check if this fails for the largest buffer we |
194 | have queued and recycle that ? */ | 194 | have queued and recycle that ? */ |
195 | } | 195 | } |
@@ -200,11 +200,11 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size) | |||
200 | * | 200 | * |
201 | * Make at least size bytes of linear space available for the tty | 201 | * Make at least size bytes of linear space available for the tty |
202 | * buffer. If we fail return the size we managed to find. | 202 | * buffer. If we fail return the size we managed to find. |
203 | * Locking: Caller must hold tty->buf.lock | 203 | * Locking: Caller must hold port->buf.lock |
204 | */ | 204 | */ |
205 | static int __tty_buffer_request_room(struct tty_struct *tty, size_t size) | 205 | static int __tty_buffer_request_room(struct tty_port *port, size_t size) |
206 | { | 206 | { |
207 | struct tty_bufhead *buf = &tty->buf; | 207 | struct tty_bufhead *buf = &port->buf; |
208 | struct tty_buffer *b, *n; | 208 | struct tty_buffer *b, *n; |
209 | int left; | 209 | int left; |
210 | /* OPTIMISATION: We could keep a per tty "zero" sized buffer to | 210 | /* OPTIMISATION: We could keep a per tty "zero" sized buffer to |
@@ -218,7 +218,7 @@ static int __tty_buffer_request_room(struct tty_struct *tty, size_t size) | |||
218 | 218 | ||
219 | if (left < size) { | 219 | if (left < size) { |
220 | /* This is the slow path - looking for new buffers to use */ | 220 | /* This is the slow path - looking for new buffers to use */ |
221 | if ((n = tty_buffer_find(tty, size)) != NULL) { | 221 | if ((n = tty_buffer_find(port, size)) != NULL) { |
222 | if (b != NULL) { | 222 | if (b != NULL) { |
223 | b->next = n; | 223 | b->next = n; |
224 | b->commit = b->used; | 224 | b->commit = b->used; |
@@ -241,16 +241,17 @@ static int __tty_buffer_request_room(struct tty_struct *tty, size_t size) | |||
241 | * Make at least size bytes of linear space available for the tty | 241 | * Make at least size bytes of linear space available for the tty |
242 | * buffer. If we fail return the size we managed to find. | 242 | * buffer. If we fail return the size we managed to find. |
243 | * | 243 | * |
244 | * Locking: Takes tty->buf.lock | 244 | * Locking: Takes port->buf.lock |
245 | */ | 245 | */ |
246 | int tty_buffer_request_room(struct tty_struct *tty, size_t size) | 246 | int tty_buffer_request_room(struct tty_struct *tty, size_t size) |
247 | { | 247 | { |
248 | struct tty_port *port = tty->port; | ||
248 | unsigned long flags; | 249 | unsigned long flags; |
249 | int length; | 250 | int length; |
250 | 251 | ||
251 | spin_lock_irqsave(&tty->buf.lock, flags); | 252 | spin_lock_irqsave(&port->buf.lock, flags); |
252 | length = __tty_buffer_request_room(tty, size); | 253 | length = __tty_buffer_request_room(port, size); |
253 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 254 | spin_unlock_irqrestore(&port->buf.lock, flags); |
254 | return length; | 255 | return length; |
255 | } | 256 | } |
256 | EXPORT_SYMBOL_GPL(tty_buffer_request_room); | 257 | EXPORT_SYMBOL_GPL(tty_buffer_request_room); |
@@ -265,13 +266,13 @@ EXPORT_SYMBOL_GPL(tty_buffer_request_room); | |||
265 | * Queue a series of bytes to the tty buffering. All the characters | 266 | * Queue a series of bytes to the tty buffering. All the characters |
266 | * passed are marked with the supplied flag. Returns the number added. | 267 | * passed are marked with the supplied flag. Returns the number added. |
267 | * | 268 | * |
268 | * Locking: Called functions may take tty->buf.lock | 269 | * Locking: Called functions may take port->buf.lock |
269 | */ | 270 | */ |
270 | 271 | ||
271 | int tty_insert_flip_string_fixed_flag(struct tty_struct *tty, | 272 | int tty_insert_flip_string_fixed_flag(struct tty_struct *tty, |
272 | const unsigned char *chars, char flag, size_t size) | 273 | const unsigned char *chars, char flag, size_t size) |
273 | { | 274 | { |
274 | struct tty_bufhead *buf = &tty->buf; | 275 | struct tty_bufhead *buf = &tty->port->buf; |
275 | int copied = 0; | 276 | int copied = 0; |
276 | do { | 277 | do { |
277 | int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); | 278 | int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); |
@@ -280,7 +281,7 @@ int tty_insert_flip_string_fixed_flag(struct tty_struct *tty, | |||
280 | struct tty_buffer *tb; | 281 | struct tty_buffer *tb; |
281 | 282 | ||
282 | spin_lock_irqsave(&buf->lock, flags); | 283 | spin_lock_irqsave(&buf->lock, flags); |
283 | space = __tty_buffer_request_room(tty, goal); | 284 | space = __tty_buffer_request_room(tty->port, goal); |
284 | tb = buf->tail; | 285 | tb = buf->tail; |
285 | /* If there is no space then tb may be NULL */ | 286 | /* If there is no space then tb may be NULL */ |
286 | if (unlikely(space == 0)) { | 287 | if (unlikely(space == 0)) { |
@@ -311,13 +312,13 @@ EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag); | |||
311 | * the flags array indicates the status of the character. Returns the | 312 | * the flags array indicates the status of the character. Returns the |
312 | * number added. | 313 | * number added. |
313 | * | 314 | * |
314 | * Locking: Called functions may take tty->buf.lock | 315 | * Locking: Called functions may take port->buf.lock |
315 | */ | 316 | */ |
316 | 317 | ||
317 | int tty_insert_flip_string_flags(struct tty_struct *tty, | 318 | int tty_insert_flip_string_flags(struct tty_struct *tty, |
318 | const unsigned char *chars, const char *flags, size_t size) | 319 | const unsigned char *chars, const char *flags, size_t size) |
319 | { | 320 | { |
320 | struct tty_bufhead *buf = &tty->buf; | 321 | struct tty_bufhead *buf = &tty->port->buf; |
321 | int copied = 0; | 322 | int copied = 0; |
322 | do { | 323 | do { |
323 | int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); | 324 | int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); |
@@ -326,7 +327,7 @@ int tty_insert_flip_string_flags(struct tty_struct *tty, | |||
326 | struct tty_buffer *tb; | 327 | struct tty_buffer *tb; |
327 | 328 | ||
328 | spin_lock_irqsave(&buf->lock, __flags); | 329 | spin_lock_irqsave(&buf->lock, __flags); |
329 | space = __tty_buffer_request_room(tty, goal); | 330 | space = __tty_buffer_request_room(tty->port, goal); |
330 | tb = buf->tail; | 331 | tb = buf->tail; |
331 | /* If there is no space then tb may be NULL */ | 332 | /* If there is no space then tb may be NULL */ |
332 | if (unlikely(space == 0)) { | 333 | if (unlikely(space == 0)) { |
@@ -357,12 +358,12 @@ EXPORT_SYMBOL(tty_insert_flip_string_flags); | |||
357 | * Note that this function can only be used when the low_latency flag | 358 | * Note that this function can only be used when the low_latency flag |
358 | * is unset. Otherwise the workqueue won't be flushed. | 359 | * is unset. Otherwise the workqueue won't be flushed. |
359 | * | 360 | * |
360 | * Locking: Takes tty->buf.lock | 361 | * Locking: Takes port->buf.lock |
361 | */ | 362 | */ |
362 | 363 | ||
363 | void tty_schedule_flip(struct tty_struct *tty) | 364 | void tty_schedule_flip(struct tty_struct *tty) |
364 | { | 365 | { |
365 | struct tty_bufhead *buf = &tty->buf; | 366 | struct tty_bufhead *buf = &tty->port->buf; |
366 | unsigned long flags; | 367 | unsigned long flags; |
367 | 368 | ||
368 | spin_lock_irqsave(&buf->lock, flags); | 369 | spin_lock_irqsave(&buf->lock, flags); |
@@ -385,19 +386,19 @@ EXPORT_SYMBOL(tty_schedule_flip); | |||
385 | * that need their own block copy routines into the buffer. There is no | 386 | * that need their own block copy routines into the buffer. There is no |
386 | * guarantee the buffer is a DMA target! | 387 | * guarantee the buffer is a DMA target! |
387 | * | 388 | * |
388 | * Locking: May call functions taking tty->buf.lock | 389 | * Locking: May call functions taking port->buf.lock |
389 | */ | 390 | */ |
390 | 391 | ||
391 | int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, | 392 | int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, |
392 | size_t size) | 393 | size_t size) |
393 | { | 394 | { |
394 | struct tty_bufhead *buf = &tty->buf; | 395 | struct tty_bufhead *buf = &tty->port->buf; |
395 | int space; | 396 | int space; |
396 | unsigned long flags; | 397 | unsigned long flags; |
397 | struct tty_buffer *tb; | 398 | struct tty_buffer *tb; |
398 | 399 | ||
399 | spin_lock_irqsave(&buf->lock, flags); | 400 | spin_lock_irqsave(&buf->lock, flags); |
400 | space = __tty_buffer_request_room(tty, size); | 401 | space = __tty_buffer_request_room(tty->port, size); |
401 | 402 | ||
402 | tb = buf->tail; | 403 | tb = buf->tail; |
403 | if (likely(space)) { | 404 | if (likely(space)) { |
@@ -423,19 +424,19 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string); | |||
423 | * that need their own block copy routines into the buffer. There is no | 424 | * that need their own block copy routines into the buffer. There is no |
424 | * guarantee the buffer is a DMA target! | 425 | * guarantee the buffer is a DMA target! |
425 | * | 426 | * |
426 | * Locking: May call functions taking tty->buf.lock | 427 | * Locking: May call functions taking port->buf.lock |
427 | */ | 428 | */ |
428 | 429 | ||
429 | int tty_prepare_flip_string_flags(struct tty_struct *tty, | 430 | int tty_prepare_flip_string_flags(struct tty_struct *tty, |
430 | unsigned char **chars, char **flags, size_t size) | 431 | unsigned char **chars, char **flags, size_t size) |
431 | { | 432 | { |
432 | struct tty_bufhead *buf = &tty->buf; | 433 | struct tty_bufhead *buf = &tty->port->buf; |
433 | int space; | 434 | int space; |
434 | unsigned long __flags; | 435 | unsigned long __flags; |
435 | struct tty_buffer *tb; | 436 | struct tty_buffer *tb; |
436 | 437 | ||
437 | spin_lock_irqsave(&buf->lock, __flags); | 438 | spin_lock_irqsave(&buf->lock, __flags); |
438 | space = __tty_buffer_request_room(tty, size); | 439 | space = __tty_buffer_request_room(tty->port, size); |
439 | 440 | ||
440 | tb = buf->tail; | 441 | tb = buf->tail; |
441 | if (likely(space)) { | 442 | if (likely(space)) { |
@@ -464,13 +465,16 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags); | |||
464 | 465 | ||
465 | static void flush_to_ldisc(struct work_struct *work) | 466 | static void flush_to_ldisc(struct work_struct *work) |
466 | { | 467 | { |
467 | struct tty_struct *tty = | 468 | struct tty_port *port = container_of(work, struct tty_port, buf.work); |
468 | container_of(work, struct tty_struct, buf.work); | 469 | struct tty_bufhead *buf = &port->buf; |
469 | struct tty_port *port = tty->port; | 470 | struct tty_struct *tty; |
470 | struct tty_bufhead *buf = &tty->buf; | ||
471 | unsigned long flags; | 471 | unsigned long flags; |
472 | struct tty_ldisc *disc; | 472 | struct tty_ldisc *disc; |
473 | 473 | ||
474 | tty = port->itty; | ||
475 | if (WARN_RATELIMIT(tty == NULL, "tty is NULL")) | ||
476 | return; | ||
477 | |||
474 | disc = tty_ldisc_ref(tty); | 478 | disc = tty_ldisc_ref(tty); |
475 | if (disc == NULL) /* !TTY_LDISC */ | 479 | if (disc == NULL) /* !TTY_LDISC */ |
476 | return; | 480 | return; |
@@ -489,7 +493,7 @@ static void flush_to_ldisc(struct work_struct *work) | |||
489 | if (head->next == NULL) | 493 | if (head->next == NULL) |
490 | break; | 494 | break; |
491 | buf->head = head->next; | 495 | buf->head = head->next; |
492 | tty_buffer_free(tty, head); | 496 | tty_buffer_free(port, head); |
493 | continue; | 497 | continue; |
494 | } | 498 | } |
495 | /* Ldisc or user is trying to flush the buffers | 499 | /* Ldisc or user is trying to flush the buffers |
@@ -515,7 +519,7 @@ static void flush_to_ldisc(struct work_struct *work) | |||
515 | /* We may have a deferred request to flush the input buffer, | 519 | /* We may have a deferred request to flush the input buffer, |
516 | if so pull the chain under the lock and empty the queue */ | 520 | if so pull the chain under the lock and empty the queue */ |
517 | if (test_bit(TTYP_FLUSHPENDING, &port->iflags)) { | 521 | if (test_bit(TTYP_FLUSHPENDING, &port->iflags)) { |
518 | __tty_buffer_flush(tty); | 522 | __tty_buffer_flush(port); |
519 | clear_bit(TTYP_FLUSHPENDING, &port->iflags); | 523 | clear_bit(TTYP_FLUSHPENDING, &port->iflags); |
520 | wake_up(&tty->read_wait); | 524 | wake_up(&tty->read_wait); |
521 | } | 525 | } |
@@ -535,7 +539,7 @@ static void flush_to_ldisc(struct work_struct *work) | |||
535 | void tty_flush_to_ldisc(struct tty_struct *tty) | 539 | void tty_flush_to_ldisc(struct tty_struct *tty) |
536 | { | 540 | { |
537 | if (!tty->low_latency) | 541 | if (!tty->low_latency) |
538 | flush_work(&tty->buf.work); | 542 | flush_work(&tty->port->buf.work); |
539 | } | 543 | } |
540 | 544 | ||
541 | /** | 545 | /** |
@@ -553,7 +557,7 @@ void tty_flush_to_ldisc(struct tty_struct *tty) | |||
553 | 557 | ||
554 | void tty_flip_buffer_push(struct tty_struct *tty) | 558 | void tty_flip_buffer_push(struct tty_struct *tty) |
555 | { | 559 | { |
556 | struct tty_bufhead *buf = &tty->buf; | 560 | struct tty_bufhead *buf = &tty->port->buf; |
557 | unsigned long flags; | 561 | unsigned long flags; |
558 | 562 | ||
559 | spin_lock_irqsave(&buf->lock, flags); | 563 | spin_lock_irqsave(&buf->lock, flags); |
@@ -578,9 +582,9 @@ EXPORT_SYMBOL(tty_flip_buffer_push); | |||
578 | * Locking: none | 582 | * Locking: none |
579 | */ | 583 | */ |
580 | 584 | ||
581 | void tty_buffer_init(struct tty_struct *tty) | 585 | void tty_buffer_init(struct tty_port *port) |
582 | { | 586 | { |
583 | struct tty_bufhead *buf = &tty->buf; | 587 | struct tty_bufhead *buf = &port->buf; |
584 | 588 | ||
585 | spin_lock_init(&buf->lock); | 589 | spin_lock_init(&buf->lock); |
586 | buf->head = NULL; | 590 | buf->head = NULL; |
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 202008f38ca..a3eba7f359e 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
@@ -186,7 +186,6 @@ void free_tty_struct(struct tty_struct *tty) | |||
186 | if (tty->dev) | 186 | if (tty->dev) |
187 | put_device(tty->dev); | 187 | put_device(tty->dev); |
188 | kfree(tty->write_buf); | 188 | kfree(tty->write_buf); |
189 | tty_buffer_free_all(tty); | ||
190 | tty->magic = 0xDEADDEAD; | 189 | tty->magic = 0xDEADDEAD; |
191 | kfree(tty); | 190 | kfree(tty); |
192 | } | 191 | } |
@@ -2935,7 +2934,6 @@ void initialize_tty_struct(struct tty_struct *tty, | |||
2935 | tty_ldisc_init(tty); | 2934 | tty_ldisc_init(tty); |
2936 | tty->session = NULL; | 2935 | tty->session = NULL; |
2937 | tty->pgrp = NULL; | 2936 | tty->pgrp = NULL; |
2938 | tty_buffer_init(tty); | ||
2939 | mutex_init(&tty->legacy_mutex); | 2937 | mutex_init(&tty->legacy_mutex); |
2940 | mutex_init(&tty->termios_mutex); | 2938 | mutex_init(&tty->termios_mutex); |
2941 | mutex_init(&tty->ldisc_mutex); | 2939 | mutex_init(&tty->ldisc_mutex); |
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 47e3968df10..f4e6754525d 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c | |||
@@ -512,7 +512,7 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) | |||
512 | static int tty_ldisc_halt(struct tty_struct *tty) | 512 | static int tty_ldisc_halt(struct tty_struct *tty) |
513 | { | 513 | { |
514 | clear_bit(TTY_LDISC, &tty->flags); | 514 | clear_bit(TTY_LDISC, &tty->flags); |
515 | return cancel_work_sync(&tty->buf.work); | 515 | return cancel_work_sync(&tty->port->buf.work); |
516 | } | 516 | } |
517 | 517 | ||
518 | /** | 518 | /** |
@@ -525,7 +525,7 @@ static void tty_ldisc_flush_works(struct tty_struct *tty) | |||
525 | { | 525 | { |
526 | flush_work(&tty->hangup_work); | 526 | flush_work(&tty->hangup_work); |
527 | flush_work(&tty->SAK_work); | 527 | flush_work(&tty->SAK_work); |
528 | flush_work(&tty->buf.work); | 528 | flush_work(&tty->port->buf.work); |
529 | } | 529 | } |
530 | 530 | ||
531 | /** | 531 | /** |
@@ -704,9 +704,9 @@ enable: | |||
704 | /* Restart the work queue in case no characters kick it off. Safe if | 704 | /* Restart the work queue in case no characters kick it off. Safe if |
705 | already running */ | 705 | already running */ |
706 | if (work) | 706 | if (work) |
707 | schedule_work(&tty->buf.work); | 707 | schedule_work(&tty->port->buf.work); |
708 | if (o_work) | 708 | if (o_work) |
709 | schedule_work(&o_tty->buf.work); | 709 | schedule_work(&o_tty->port->buf.work); |
710 | mutex_unlock(&tty->ldisc_mutex); | 710 | mutex_unlock(&tty->ldisc_mutex); |
711 | tty_unlock(tty); | 711 | tty_unlock(tty); |
712 | return retval; | 712 | return retval; |
@@ -817,7 +817,7 @@ void tty_ldisc_hangup(struct tty_struct *tty) | |||
817 | */ | 817 | */ |
818 | clear_bit(TTY_LDISC, &tty->flags); | 818 | clear_bit(TTY_LDISC, &tty->flags); |
819 | tty_unlock(tty); | 819 | tty_unlock(tty); |
820 | cancel_work_sync(&tty->buf.work); | 820 | cancel_work_sync(&tty->port->buf.work); |
821 | mutex_unlock(&tty->ldisc_mutex); | 821 | mutex_unlock(&tty->ldisc_mutex); |
822 | retry: | 822 | retry: |
823 | tty_lock(tty); | 823 | tty_lock(tty); |
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index d7bdd8d0c23..416b42f7c34 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c | |||
@@ -21,6 +21,7 @@ | |||
21 | void tty_port_init(struct tty_port *port) | 21 | void tty_port_init(struct tty_port *port) |
22 | { | 22 | { |
23 | memset(port, 0, sizeof(*port)); | 23 | memset(port, 0, sizeof(*port)); |
24 | tty_buffer_init(port); | ||
24 | init_waitqueue_head(&port->open_wait); | 25 | init_waitqueue_head(&port->open_wait); |
25 | init_waitqueue_head(&port->close_wait); | 26 | init_waitqueue_head(&port->close_wait); |
26 | init_waitqueue_head(&port->delta_msr_wait); | 27 | init_waitqueue_head(&port->delta_msr_wait); |
@@ -126,6 +127,7 @@ static void tty_port_destructor(struct kref *kref) | |||
126 | struct tty_port *port = container_of(kref, struct tty_port, kref); | 127 | struct tty_port *port = container_of(kref, struct tty_port, kref); |
127 | if (port->xmit_buf) | 128 | if (port->xmit_buf) |
128 | free_page((unsigned long)port->xmit_buf); | 129 | free_page((unsigned long)port->xmit_buf); |
130 | tty_buffer_free_all(port); | ||
129 | if (port->ops->destruct) | 131 | if (port->ops->destruct) |
130 | port->ops->destruct(port); | 132 | port->ops->destruct(port); |
131 | else | 133 | else |
diff --git a/include/linux/tty.h b/include/linux/tty.h index 9be74d649a5..d7ff88fb896 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -188,6 +188,7 @@ struct tty_port_operations { | |||
188 | }; | 188 | }; |
189 | 189 | ||
190 | struct tty_port { | 190 | struct tty_port { |
191 | struct tty_bufhead buf; /* Locked internally */ | ||
191 | struct tty_struct *tty; /* Back pointer */ | 192 | struct tty_struct *tty; /* Back pointer */ |
192 | struct tty_struct *itty; /* internal back ptr */ | 193 | struct tty_struct *itty; /* internal back ptr */ |
193 | const struct tty_port_operations *ops; /* Port operations */ | 194 | const struct tty_port_operations *ops; /* Port operations */ |
@@ -259,7 +260,6 @@ struct tty_struct { | |||
259 | 260 | ||
260 | struct tty_struct *link; | 261 | struct tty_struct *link; |
261 | struct fasync_struct *fasync; | 262 | struct fasync_struct *fasync; |
262 | struct tty_bufhead buf; /* Locked internally */ | ||
263 | int alt_speed; /* For magic substitution of 38400 bps */ | 263 | int alt_speed; /* For magic substitution of 38400 bps */ |
264 | wait_queue_head_t write_wait; | 264 | wait_queue_head_t write_wait; |
265 | wait_queue_head_t read_wait; | 265 | wait_queue_head_t read_wait; |
@@ -388,9 +388,9 @@ extern void disassociate_ctty(int priv); | |||
388 | extern void no_tty(void); | 388 | extern void no_tty(void); |
389 | extern void tty_flip_buffer_push(struct tty_struct *tty); | 389 | extern void tty_flip_buffer_push(struct tty_struct *tty); |
390 | extern void tty_flush_to_ldisc(struct tty_struct *tty); | 390 | extern void tty_flush_to_ldisc(struct tty_struct *tty); |
391 | extern void tty_buffer_free_all(struct tty_struct *tty); | 391 | extern void tty_buffer_free_all(struct tty_port *port); |
392 | extern void tty_buffer_flush(struct tty_struct *tty); | 392 | extern void tty_buffer_flush(struct tty_struct *tty); |
393 | extern void tty_buffer_init(struct tty_struct *tty); | 393 | extern void tty_buffer_init(struct tty_port *port); |
394 | extern speed_t tty_get_baud_rate(struct tty_struct *tty); | 394 | extern speed_t tty_get_baud_rate(struct tty_struct *tty); |
395 | extern speed_t tty_termios_baud_rate(struct ktermios *termios); | 395 | extern speed_t tty_termios_baud_rate(struct ktermios *termios); |
396 | extern speed_t tty_termios_input_baud_rate(struct ktermios *termios); | 396 | extern speed_t tty_termios_input_baud_rate(struct ktermios *termios); |
diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h index 9239d033a0a..2002344ed36 100644 --- a/include/linux/tty_flip.h +++ b/include/linux/tty_flip.h | |||
@@ -11,7 +11,7 @@ void tty_schedule_flip(struct tty_struct *tty); | |||
11 | static inline int tty_insert_flip_char(struct tty_struct *tty, | 11 | static inline int tty_insert_flip_char(struct tty_struct *tty, |
12 | unsigned char ch, char flag) | 12 | unsigned char ch, char flag) |
13 | { | 13 | { |
14 | struct tty_buffer *tb = tty->buf.tail; | 14 | struct tty_buffer *tb = tty->port->buf.tail; |
15 | if (tb && tb->used < tb->size) { | 15 | if (tb && tb->used < tb->size) { |
16 | tb->flag_buf_ptr[tb->used] = flag; | 16 | tb->flag_buf_ptr[tb->used] = flag; |
17 | tb->char_buf_ptr[tb->used++] = ch; | 17 | tb->char_buf_ptr[tb->used++] = ch; |