diff options
Diffstat (limited to 'drivers/tty/tty_buffer.c')
| -rw-r--r-- | drivers/tty/tty_buffer.c | 228 |
1 files changed, 129 insertions, 99 deletions
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 91e326ffe7db..6cf87d7afb7e 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c | |||
| @@ -27,19 +27,21 @@ | |||
| 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 = &port->buf; | ||
| 32 | struct tty_buffer *thead; | 33 | struct tty_buffer *thead; |
| 33 | while ((thead = tty->buf.head) != NULL) { | 34 | |
| 34 | tty->buf.head = thead->next; | 35 | while ((thead = buf->head) != NULL) { |
| 36 | buf->head = thead->next; | ||
| 35 | kfree(thead); | 37 | kfree(thead); |
| 36 | } | 38 | } |
| 37 | while ((thead = tty->buf.free) != NULL) { | 39 | while ((thead = buf->free) != NULL) { |
| 38 | tty->buf.free = thead->next; | 40 | buf->free = thead->next; |
| 39 | kfree(thead); | 41 | kfree(thead); |
| 40 | } | 42 | } |
| 41 | tty->buf.tail = NULL; | 43 | buf->tail = NULL; |
| 42 | tty->buf.memory_used = 0; | 44 | buf->memory_used = 0; |
| 43 | } | 45 | } |
| 44 | 46 | ||
| 45 | /** | 47 | /** |
| @@ -54,11 +56,11 @@ void tty_buffer_free_all(struct tty_struct *tty) | |||
| 54 | * Locking: Caller must hold tty->buf.lock | 56 | * Locking: Caller must hold tty->buf.lock |
| 55 | */ | 57 | */ |
| 56 | 58 | ||
| 57 | 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) |
| 58 | { | 60 | { |
| 59 | struct tty_buffer *p; | 61 | struct tty_buffer *p; |
| 60 | 62 | ||
| 61 | if (tty->buf.memory_used + size > 65536) | 63 | if (port->buf.memory_used + size > 65536) |
| 62 | return NULL; | 64 | return NULL; |
| 63 | p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); | 65 | p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); |
| 64 | if (p == NULL) | 66 | if (p == NULL) |
| @@ -70,7 +72,7 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size) | |||
| 70 | p->read = 0; | 72 | p->read = 0; |
| 71 | p->char_buf_ptr = (char *)(p->data); | 73 | p->char_buf_ptr = (char *)(p->data); |
| 72 | p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size; | 74 | p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size; |
| 73 | tty->buf.memory_used += size; | 75 | port->buf.memory_used += size; |
| 74 | return p; | 76 | return p; |
| 75 | } | 77 | } |
| 76 | 78 | ||
| @@ -85,17 +87,19 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size) | |||
| 85 | * Locking: Caller must hold tty->buf.lock | 87 | * Locking: Caller must hold tty->buf.lock |
| 86 | */ | 88 | */ |
| 87 | 89 | ||
| 88 | 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) |
| 89 | { | 91 | { |
| 92 | struct tty_bufhead *buf = &port->buf; | ||
| 93 | |||
| 90 | /* Dumb strategy for now - should keep some stats */ | 94 | /* Dumb strategy for now - should keep some stats */ |
| 91 | tty->buf.memory_used -= b->size; | 95 | buf->memory_used -= b->size; |
| 92 | WARN_ON(tty->buf.memory_used < 0); | 96 | WARN_ON(buf->memory_used < 0); |
| 93 | 97 | ||
| 94 | if (b->size >= 512) | 98 | if (b->size >= 512) |
| 95 | kfree(b); | 99 | kfree(b); |
| 96 | else { | 100 | else { |
| 97 | b->next = tty->buf.free; | 101 | b->next = buf->free; |
| 98 | tty->buf.free = b; | 102 | buf->free = b; |
| 99 | } | 103 | } |
| 100 | } | 104 | } |
| 101 | 105 | ||
| @@ -110,15 +114,16 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b) | |||
| 110 | * Locking: Caller must hold tty->buf.lock | 114 | * Locking: Caller must hold tty->buf.lock |
| 111 | */ | 115 | */ |
| 112 | 116 | ||
| 113 | static void __tty_buffer_flush(struct tty_struct *tty) | 117 | static void __tty_buffer_flush(struct tty_port *port) |
| 114 | { | 118 | { |
| 119 | struct tty_bufhead *buf = &port->buf; | ||
| 115 | struct tty_buffer *thead; | 120 | struct tty_buffer *thead; |
| 116 | 121 | ||
| 117 | while ((thead = tty->buf.head) != NULL) { | 122 | while ((thead = buf->head) != NULL) { |
| 118 | tty->buf.head = thead->next; | 123 | buf->head = thead->next; |
| 119 | tty_buffer_free(tty, thead); | 124 | tty_buffer_free(port, thead); |
| 120 | } | 125 | } |
| 121 | tty->buf.tail = NULL; | 126 | buf->tail = NULL; |
| 122 | } | 127 | } |
| 123 | 128 | ||
| 124 | /** | 129 | /** |
| @@ -134,21 +139,24 @@ static void __tty_buffer_flush(struct tty_struct *tty) | |||
| 134 | 139 | ||
| 135 | void tty_buffer_flush(struct tty_struct *tty) | 140 | void tty_buffer_flush(struct tty_struct *tty) |
| 136 | { | 141 | { |
| 142 | struct tty_port *port = tty->port; | ||
| 143 | struct tty_bufhead *buf = &port->buf; | ||
| 137 | unsigned long flags; | 144 | unsigned long flags; |
| 138 | spin_lock_irqsave(&tty->buf.lock, flags); | 145 | |
| 146 | spin_lock_irqsave(&buf->lock, flags); | ||
| 139 | 147 | ||
| 140 | /* If the data is being pushed to the tty layer then we can't | 148 | /* If the data is being pushed to the tty layer then we can't |
| 141 | process it here. Instead set a flag and the flush_to_ldisc | 149 | process it here. Instead set a flag and the flush_to_ldisc |
| 142 | path will process the flush request before it exits */ | 150 | path will process the flush request before it exits */ |
| 143 | if (test_bit(TTY_FLUSHING, &tty->flags)) { | 151 | if (test_bit(TTYP_FLUSHING, &port->iflags)) { |
| 144 | set_bit(TTY_FLUSHPENDING, &tty->flags); | 152 | set_bit(TTYP_FLUSHPENDING, &port->iflags); |
| 145 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 153 | spin_unlock_irqrestore(&buf->lock, flags); |
| 146 | wait_event(tty->read_wait, | 154 | wait_event(tty->read_wait, |
| 147 | test_bit(TTY_FLUSHPENDING, &tty->flags) == 0); | 155 | test_bit(TTYP_FLUSHPENDING, &port->iflags) == 0); |
| 148 | return; | 156 | return; |
| 149 | } else | 157 | } else |
| 150 | __tty_buffer_flush(tty); | 158 | __tty_buffer_flush(port); |
| 151 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 159 | spin_unlock_irqrestore(&buf->lock, flags); |
| 152 | } | 160 | } |
| 153 | 161 | ||
| 154 | /** | 162 | /** |
| @@ -163,9 +171,9 @@ void tty_buffer_flush(struct tty_struct *tty) | |||
| 163 | * Locking: Caller must hold tty->buf.lock | 171 | * Locking: Caller must hold tty->buf.lock |
| 164 | */ | 172 | */ |
| 165 | 173 | ||
| 166 | 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) |
| 167 | { | 175 | { |
| 168 | struct tty_buffer **tbh = &tty->buf.free; | 176 | struct tty_buffer **tbh = &port->buf.free; |
| 169 | while ((*tbh) != NULL) { | 177 | while ((*tbh) != NULL) { |
| 170 | struct tty_buffer *t = *tbh; | 178 | struct tty_buffer *t = *tbh; |
| 171 | if (t->size >= size) { | 179 | if (t->size >= size) { |
| @@ -174,14 +182,14 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size) | |||
| 174 | t->used = 0; | 182 | t->used = 0; |
| 175 | t->commit = 0; | 183 | t->commit = 0; |
| 176 | t->read = 0; | 184 | t->read = 0; |
| 177 | tty->buf.memory_used += t->size; | 185 | port->buf.memory_used += t->size; |
| 178 | return t; | 186 | return t; |
| 179 | } | 187 | } |
| 180 | tbh = &((*tbh)->next); | 188 | tbh = &((*tbh)->next); |
| 181 | } | 189 | } |
| 182 | /* Round the buffer size out */ | 190 | /* Round the buffer size out */ |
| 183 | size = (size + 0xFF) & ~0xFF; | 191 | size = (size + 0xFF) & ~0xFF; |
| 184 | return tty_buffer_alloc(tty, size); | 192 | return tty_buffer_alloc(port, size); |
| 185 | /* Should possibly check if this fails for the largest buffer we | 193 | /* Should possibly check if this fails for the largest buffer we |
| 186 | have queued and recycle that ? */ | 194 | have queued and recycle that ? */ |
| 187 | } | 195 | } |
| @@ -192,29 +200,31 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size) | |||
| 192 | * | 200 | * |
| 193 | * 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 |
| 194 | * buffer. If we fail return the size we managed to find. | 202 | * buffer. If we fail return the size we managed to find. |
| 195 | * Locking: Caller must hold tty->buf.lock | 203 | * Locking: Caller must hold port->buf.lock |
| 196 | */ | 204 | */ |
| 197 | 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) |
| 198 | { | 206 | { |
| 207 | struct tty_bufhead *buf = &port->buf; | ||
| 199 | struct tty_buffer *b, *n; | 208 | struct tty_buffer *b, *n; |
| 200 | int left; | 209 | int left; |
| 201 | /* OPTIMISATION: We could keep a per tty "zero" sized buffer to | 210 | /* OPTIMISATION: We could keep a per tty "zero" sized buffer to |
| 202 | remove this conditional if its worth it. This would be invisible | 211 | remove this conditional if its worth it. This would be invisible |
| 203 | to the callers */ | 212 | to the callers */ |
| 204 | if ((b = tty->buf.tail) != NULL) | 213 | b = buf->tail; |
| 214 | if (b != NULL) | ||
| 205 | left = b->size - b->used; | 215 | left = b->size - b->used; |
| 206 | else | 216 | else |
| 207 | left = 0; | 217 | left = 0; |
| 208 | 218 | ||
| 209 | if (left < size) { | 219 | if (left < size) { |
| 210 | /* This is the slow path - looking for new buffers to use */ | 220 | /* This is the slow path - looking for new buffers to use */ |
| 211 | if ((n = tty_buffer_find(tty, size)) != NULL) { | 221 | if ((n = tty_buffer_find(port, size)) != NULL) { |
| 212 | if (b != NULL) { | 222 | if (b != NULL) { |
| 213 | b->next = n; | 223 | b->next = n; |
| 214 | b->commit = b->used; | 224 | b->commit = b->used; |
| 215 | } else | 225 | } else |
| 216 | tty->buf.head = n; | 226 | buf->head = n; |
| 217 | tty->buf.tail = n; | 227 | buf->tail = n; |
| 218 | } else | 228 | } else |
| 219 | size = left; | 229 | size = left; |
| 220 | } | 230 | } |
| @@ -231,16 +241,17 @@ static int __tty_buffer_request_room(struct tty_struct *tty, size_t size) | |||
| 231 | * 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 |
| 232 | * buffer. If we fail return the size we managed to find. | 242 | * buffer. If we fail return the size we managed to find. |
| 233 | * | 243 | * |
| 234 | * Locking: Takes tty->buf.lock | 244 | * Locking: Takes port->buf.lock |
| 235 | */ | 245 | */ |
| 236 | 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) |
| 237 | { | 247 | { |
| 248 | struct tty_port *port = tty->port; | ||
| 238 | unsigned long flags; | 249 | unsigned long flags; |
| 239 | int length; | 250 | int length; |
| 240 | 251 | ||
| 241 | spin_lock_irqsave(&tty->buf.lock, flags); | 252 | spin_lock_irqsave(&port->buf.lock, flags); |
| 242 | length = __tty_buffer_request_room(tty, size); | 253 | length = __tty_buffer_request_room(port, size); |
| 243 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 254 | spin_unlock_irqrestore(&port->buf.lock, flags); |
| 244 | return length; | 255 | return length; |
| 245 | } | 256 | } |
| 246 | EXPORT_SYMBOL_GPL(tty_buffer_request_room); | 257 | EXPORT_SYMBOL_GPL(tty_buffer_request_room); |
| @@ -255,12 +266,13 @@ EXPORT_SYMBOL_GPL(tty_buffer_request_room); | |||
| 255 | * 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 |
| 256 | * passed are marked with the supplied flag. Returns the number added. | 267 | * passed are marked with the supplied flag. Returns the number added. |
| 257 | * | 268 | * |
| 258 | * Locking: Called functions may take tty->buf.lock | 269 | * Locking: Called functions may take port->buf.lock |
| 259 | */ | 270 | */ |
| 260 | 271 | ||
| 261 | int tty_insert_flip_string_fixed_flag(struct tty_struct *tty, | 272 | int tty_insert_flip_string_fixed_flag(struct tty_struct *tty, |
| 262 | const unsigned char *chars, char flag, size_t size) | 273 | const unsigned char *chars, char flag, size_t size) |
| 263 | { | 274 | { |
| 275 | struct tty_bufhead *buf = &tty->port->buf; | ||
| 264 | int copied = 0; | 276 | int copied = 0; |
| 265 | do { | 277 | do { |
| 266 | int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); | 278 | int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); |
| @@ -268,18 +280,18 @@ int tty_insert_flip_string_fixed_flag(struct tty_struct *tty, | |||
| 268 | unsigned long flags; | 280 | unsigned long flags; |
| 269 | struct tty_buffer *tb; | 281 | struct tty_buffer *tb; |
| 270 | 282 | ||
| 271 | spin_lock_irqsave(&tty->buf.lock, flags); | 283 | spin_lock_irqsave(&buf->lock, flags); |
| 272 | space = __tty_buffer_request_room(tty, goal); | 284 | space = __tty_buffer_request_room(tty->port, goal); |
| 273 | tb = tty->buf.tail; | 285 | tb = buf->tail; |
| 274 | /* If there is no space then tb may be NULL */ | 286 | /* If there is no space then tb may be NULL */ |
| 275 | if (unlikely(space == 0)) { | 287 | if (unlikely(space == 0)) { |
| 276 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 288 | spin_unlock_irqrestore(&buf->lock, flags); |
| 277 | break; | 289 | break; |
| 278 | } | 290 | } |
| 279 | memcpy(tb->char_buf_ptr + tb->used, chars, space); | 291 | memcpy(tb->char_buf_ptr + tb->used, chars, space); |
| 280 | memset(tb->flag_buf_ptr + tb->used, flag, space); | 292 | memset(tb->flag_buf_ptr + tb->used, flag, space); |
| 281 | tb->used += space; | 293 | tb->used += space; |
| 282 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 294 | spin_unlock_irqrestore(&buf->lock, flags); |
| 283 | copied += space; | 295 | copied += space; |
| 284 | chars += space; | 296 | chars += space; |
| 285 | /* There is a small chance that we need to split the data over | 297 | /* There is a small chance that we need to split the data over |
| @@ -300,12 +312,13 @@ EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag); | |||
| 300 | * the flags array indicates the status of the character. Returns the | 312 | * the flags array indicates the status of the character. Returns the |
| 301 | * number added. | 313 | * number added. |
| 302 | * | 314 | * |
| 303 | * Locking: Called functions may take tty->buf.lock | 315 | * Locking: Called functions may take port->buf.lock |
| 304 | */ | 316 | */ |
| 305 | 317 | ||
| 306 | int tty_insert_flip_string_flags(struct tty_struct *tty, | 318 | int tty_insert_flip_string_flags(struct tty_struct *tty, |
| 307 | const unsigned char *chars, const char *flags, size_t size) | 319 | const unsigned char *chars, const char *flags, size_t size) |
| 308 | { | 320 | { |
| 321 | struct tty_bufhead *buf = &tty->port->buf; | ||
| 309 | int copied = 0; | 322 | int copied = 0; |
| 310 | do { | 323 | do { |
| 311 | int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); | 324 | int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); |
| @@ -313,18 +326,18 @@ int tty_insert_flip_string_flags(struct tty_struct *tty, | |||
| 313 | unsigned long __flags; | 326 | unsigned long __flags; |
| 314 | struct tty_buffer *tb; | 327 | struct tty_buffer *tb; |
| 315 | 328 | ||
| 316 | spin_lock_irqsave(&tty->buf.lock, __flags); | 329 | spin_lock_irqsave(&buf->lock, __flags); |
| 317 | space = __tty_buffer_request_room(tty, goal); | 330 | space = __tty_buffer_request_room(tty->port, goal); |
| 318 | tb = tty->buf.tail; | 331 | tb = buf->tail; |
| 319 | /* If there is no space then tb may be NULL */ | 332 | /* If there is no space then tb may be NULL */ |
| 320 | if (unlikely(space == 0)) { | 333 | if (unlikely(space == 0)) { |
| 321 | spin_unlock_irqrestore(&tty->buf.lock, __flags); | 334 | spin_unlock_irqrestore(&buf->lock, __flags); |
| 322 | break; | 335 | break; |
| 323 | } | 336 | } |
| 324 | memcpy(tb->char_buf_ptr + tb->used, chars, space); | 337 | memcpy(tb->char_buf_ptr + tb->used, chars, space); |
| 325 | memcpy(tb->flag_buf_ptr + tb->used, flags, space); | 338 | memcpy(tb->flag_buf_ptr + tb->used, flags, space); |
| 326 | tb->used += space; | 339 | tb->used += space; |
| 327 | spin_unlock_irqrestore(&tty->buf.lock, __flags); | 340 | spin_unlock_irqrestore(&buf->lock, __flags); |
| 328 | copied += space; | 341 | copied += space; |
| 329 | chars += space; | 342 | chars += space; |
| 330 | flags += space; | 343 | flags += space; |
| @@ -342,18 +355,23 @@ EXPORT_SYMBOL(tty_insert_flip_string_flags); | |||
| 342 | * Takes any pending buffers and transfers their ownership to the | 355 | * Takes any pending buffers and transfers their ownership to the |
| 343 | * ldisc side of the queue. It then schedules those characters for | 356 | * ldisc side of the queue. It then schedules those characters for |
| 344 | * processing by the line discipline. | 357 | * processing by the line discipline. |
| 358 | * Note that this function can only be used when the low_latency flag | ||
| 359 | * is unset. Otherwise the workqueue won't be flushed. | ||
| 345 | * | 360 | * |
| 346 | * Locking: Takes tty->buf.lock | 361 | * Locking: Takes port->buf.lock |
| 347 | */ | 362 | */ |
| 348 | 363 | ||
| 349 | void tty_schedule_flip(struct tty_struct *tty) | 364 | void tty_schedule_flip(struct tty_struct *tty) |
| 350 | { | 365 | { |
| 366 | struct tty_bufhead *buf = &tty->port->buf; | ||
| 351 | unsigned long flags; | 367 | unsigned long flags; |
| 352 | spin_lock_irqsave(&tty->buf.lock, flags); | 368 | WARN_ON(tty->low_latency); |
| 353 | if (tty->buf.tail != NULL) | 369 | |
| 354 | tty->buf.tail->commit = tty->buf.tail->used; | 370 | spin_lock_irqsave(&buf->lock, flags); |
| 355 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 371 | if (buf->tail != NULL) |
| 356 | schedule_work(&tty->buf.work); | 372 | buf->tail->commit = buf->tail->used; |
| 373 | spin_unlock_irqrestore(&buf->lock, flags); | ||
| 374 | schedule_work(&buf->work); | ||
| 357 | } | 375 | } |
| 358 | EXPORT_SYMBOL(tty_schedule_flip); | 376 | EXPORT_SYMBOL(tty_schedule_flip); |
| 359 | 377 | ||
| @@ -369,26 +387,27 @@ EXPORT_SYMBOL(tty_schedule_flip); | |||
| 369 | * that need their own block copy routines into the buffer. There is no | 387 | * that need their own block copy routines into the buffer. There is no |
| 370 | * guarantee the buffer is a DMA target! | 388 | * guarantee the buffer is a DMA target! |
| 371 | * | 389 | * |
| 372 | * Locking: May call functions taking tty->buf.lock | 390 | * Locking: May call functions taking port->buf.lock |
| 373 | */ | 391 | */ |
| 374 | 392 | ||
| 375 | int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, | 393 | int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, |
| 376 | size_t size) | 394 | size_t size) |
| 377 | { | 395 | { |
| 396 | struct tty_bufhead *buf = &tty->port->buf; | ||
| 378 | int space; | 397 | int space; |
| 379 | unsigned long flags; | 398 | unsigned long flags; |
| 380 | struct tty_buffer *tb; | 399 | struct tty_buffer *tb; |
| 381 | 400 | ||
| 382 | spin_lock_irqsave(&tty->buf.lock, flags); | 401 | spin_lock_irqsave(&buf->lock, flags); |
| 383 | space = __tty_buffer_request_room(tty, size); | 402 | space = __tty_buffer_request_room(tty->port, size); |
| 384 | 403 | ||
| 385 | tb = tty->buf.tail; | 404 | tb = buf->tail; |
| 386 | if (likely(space)) { | 405 | if (likely(space)) { |
| 387 | *chars = tb->char_buf_ptr + tb->used; | 406 | *chars = tb->char_buf_ptr + tb->used; |
| 388 | memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space); | 407 | memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space); |
| 389 | tb->used += space; | 408 | tb->used += space; |
| 390 | } | 409 | } |
| 391 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 410 | spin_unlock_irqrestore(&buf->lock, flags); |
| 392 | return space; | 411 | return space; |
| 393 | } | 412 | } |
| 394 | EXPORT_SYMBOL_GPL(tty_prepare_flip_string); | 413 | EXPORT_SYMBOL_GPL(tty_prepare_flip_string); |
| @@ -406,26 +425,27 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string); | |||
| 406 | * that need their own block copy routines into the buffer. There is no | 425 | * that need their own block copy routines into the buffer. There is no |
| 407 | * guarantee the buffer is a DMA target! | 426 | * guarantee the buffer is a DMA target! |
| 408 | * | 427 | * |
| 409 | * Locking: May call functions taking tty->buf.lock | 428 | * Locking: May call functions taking port->buf.lock |
| 410 | */ | 429 | */ |
| 411 | 430 | ||
| 412 | int tty_prepare_flip_string_flags(struct tty_struct *tty, | 431 | int tty_prepare_flip_string_flags(struct tty_struct *tty, |
| 413 | unsigned char **chars, char **flags, size_t size) | 432 | unsigned char **chars, char **flags, size_t size) |
| 414 | { | 433 | { |
| 434 | struct tty_bufhead *buf = &tty->port->buf; | ||
| 415 | int space; | 435 | int space; |
| 416 | unsigned long __flags; | 436 | unsigned long __flags; |
| 417 | struct tty_buffer *tb; | 437 | struct tty_buffer *tb; |
| 418 | 438 | ||
| 419 | spin_lock_irqsave(&tty->buf.lock, __flags); | 439 | spin_lock_irqsave(&buf->lock, __flags); |
| 420 | space = __tty_buffer_request_room(tty, size); | 440 | space = __tty_buffer_request_room(tty->port, size); |
| 421 | 441 | ||
| 422 | tb = tty->buf.tail; | 442 | tb = buf->tail; |
| 423 | if (likely(space)) { | 443 | if (likely(space)) { |
| 424 | *chars = tb->char_buf_ptr + tb->used; | 444 | *chars = tb->char_buf_ptr + tb->used; |
| 425 | *flags = tb->flag_buf_ptr + tb->used; | 445 | *flags = tb->flag_buf_ptr + tb->used; |
| 426 | tb->used += space; | 446 | tb->used += space; |
| 427 | } | 447 | } |
| 428 | spin_unlock_irqrestore(&tty->buf.lock, __flags); | 448 | spin_unlock_irqrestore(&buf->lock, __flags); |
| 429 | return space; | 449 | return space; |
| 430 | } | 450 | } |
| 431 | EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags); | 451 | EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags); |
| @@ -446,20 +466,25 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags); | |||
| 446 | 466 | ||
| 447 | static void flush_to_ldisc(struct work_struct *work) | 467 | static void flush_to_ldisc(struct work_struct *work) |
| 448 | { | 468 | { |
| 449 | struct tty_struct *tty = | 469 | struct tty_port *port = container_of(work, struct tty_port, buf.work); |
| 450 | container_of(work, struct tty_struct, buf.work); | 470 | struct tty_bufhead *buf = &port->buf; |
| 471 | struct tty_struct *tty; | ||
| 451 | unsigned long flags; | 472 | unsigned long flags; |
| 452 | struct tty_ldisc *disc; | 473 | struct tty_ldisc *disc; |
| 453 | 474 | ||
| 475 | tty = port->itty; | ||
| 476 | if (WARN_RATELIMIT(tty == NULL, "tty is NULL")) | ||
| 477 | return; | ||
| 478 | |||
| 454 | disc = tty_ldisc_ref(tty); | 479 | disc = tty_ldisc_ref(tty); |
| 455 | if (disc == NULL) /* !TTY_LDISC */ | 480 | if (disc == NULL) /* !TTY_LDISC */ |
| 456 | return; | 481 | return; |
| 457 | 482 | ||
| 458 | spin_lock_irqsave(&tty->buf.lock, flags); | 483 | spin_lock_irqsave(&buf->lock, flags); |
| 459 | 484 | ||
| 460 | if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) { | 485 | if (!test_and_set_bit(TTYP_FLUSHING, &port->iflags)) { |
| 461 | struct tty_buffer *head; | 486 | struct tty_buffer *head; |
| 462 | while ((head = tty->buf.head) != NULL) { | 487 | while ((head = buf->head) != NULL) { |
| 463 | int count; | 488 | int count; |
| 464 | char *char_buf; | 489 | char *char_buf; |
| 465 | unsigned char *flag_buf; | 490 | unsigned char *flag_buf; |
| @@ -468,14 +493,14 @@ static void flush_to_ldisc(struct work_struct *work) | |||
| 468 | if (!count) { | 493 | if (!count) { |
| 469 | if (head->next == NULL) | 494 | if (head->next == NULL) |
| 470 | break; | 495 | break; |
| 471 | tty->buf.head = head->next; | 496 | buf->head = head->next; |
| 472 | tty_buffer_free(tty, head); | 497 | tty_buffer_free(port, head); |
| 473 | continue; | 498 | continue; |
| 474 | } | 499 | } |
| 475 | /* Ldisc or user is trying to flush the buffers | 500 | /* Ldisc or user is trying to flush the buffers |
| 476 | we are feeding to the ldisc, stop feeding the | 501 | we are feeding to the ldisc, stop feeding the |
| 477 | line discipline as we want to empty the queue */ | 502 | line discipline as we want to empty the queue */ |
| 478 | if (test_bit(TTY_FLUSHPENDING, &tty->flags)) | 503 | if (test_bit(TTYP_FLUSHPENDING, &port->iflags)) |
| 479 | break; | 504 | break; |
| 480 | if (!tty->receive_room) | 505 | if (!tty->receive_room) |
| 481 | break; | 506 | break; |
| @@ -484,22 +509,22 @@ static void flush_to_ldisc(struct work_struct *work) | |||
| 484 | char_buf = head->char_buf_ptr + head->read; | 509 | char_buf = head->char_buf_ptr + head->read; |
| 485 | flag_buf = head->flag_buf_ptr + head->read; | 510 | flag_buf = head->flag_buf_ptr + head->read; |
| 486 | head->read += count; | 511 | head->read += count; |
| 487 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 512 | spin_unlock_irqrestore(&buf->lock, flags); |
| 488 | disc->ops->receive_buf(tty, char_buf, | 513 | disc->ops->receive_buf(tty, char_buf, |
| 489 | flag_buf, count); | 514 | flag_buf, count); |
| 490 | spin_lock_irqsave(&tty->buf.lock, flags); | 515 | spin_lock_irqsave(&buf->lock, flags); |
| 491 | } | 516 | } |
| 492 | clear_bit(TTY_FLUSHING, &tty->flags); | 517 | clear_bit(TTYP_FLUSHING, &port->iflags); |
| 493 | } | 518 | } |
| 494 | 519 | ||
| 495 | /* We may have a deferred request to flush the input buffer, | 520 | /* We may have a deferred request to flush the input buffer, |
| 496 | if so pull the chain under the lock and empty the queue */ | 521 | if so pull the chain under the lock and empty the queue */ |
| 497 | if (test_bit(TTY_FLUSHPENDING, &tty->flags)) { | 522 | if (test_bit(TTYP_FLUSHPENDING, &port->iflags)) { |
| 498 | __tty_buffer_flush(tty); | 523 | __tty_buffer_flush(port); |
| 499 | clear_bit(TTY_FLUSHPENDING, &tty->flags); | 524 | clear_bit(TTYP_FLUSHPENDING, &port->iflags); |
| 500 | wake_up(&tty->read_wait); | 525 | wake_up(&tty->read_wait); |
| 501 | } | 526 | } |
| 502 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 527 | spin_unlock_irqrestore(&buf->lock, flags); |
| 503 | 528 | ||
| 504 | tty_ldisc_deref(disc); | 529 | tty_ldisc_deref(disc); |
| 505 | } | 530 | } |
| @@ -514,7 +539,8 @@ static void flush_to_ldisc(struct work_struct *work) | |||
| 514 | */ | 539 | */ |
| 515 | void tty_flush_to_ldisc(struct tty_struct *tty) | 540 | void tty_flush_to_ldisc(struct tty_struct *tty) |
| 516 | { | 541 | { |
| 517 | flush_work(&tty->buf.work); | 542 | if (!tty->low_latency) |
| 543 | flush_work(&tty->port->buf.work); | ||
| 518 | } | 544 | } |
| 519 | 545 | ||
| 520 | /** | 546 | /** |
| @@ -532,16 +558,18 @@ void tty_flush_to_ldisc(struct tty_struct *tty) | |||
| 532 | 558 | ||
| 533 | void tty_flip_buffer_push(struct tty_struct *tty) | 559 | void tty_flip_buffer_push(struct tty_struct *tty) |
| 534 | { | 560 | { |
| 561 | struct tty_bufhead *buf = &tty->port->buf; | ||
| 535 | unsigned long flags; | 562 | unsigned long flags; |
| 536 | spin_lock_irqsave(&tty->buf.lock, flags); | 563 | |
| 537 | if (tty->buf.tail != NULL) | 564 | spin_lock_irqsave(&buf->lock, flags); |
| 538 | tty->buf.tail->commit = tty->buf.tail->used; | 565 | if (buf->tail != NULL) |
| 539 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 566 | buf->tail->commit = buf->tail->used; |
| 567 | spin_unlock_irqrestore(&buf->lock, flags); | ||
| 540 | 568 | ||
| 541 | if (tty->low_latency) | 569 | if (tty->low_latency) |
| 542 | flush_to_ldisc(&tty->buf.work); | 570 | flush_to_ldisc(&buf->work); |
| 543 | else | 571 | else |
| 544 | schedule_work(&tty->buf.work); | 572 | schedule_work(&buf->work); |
| 545 | } | 573 | } |
| 546 | EXPORT_SYMBOL(tty_flip_buffer_push); | 574 | EXPORT_SYMBOL(tty_flip_buffer_push); |
| 547 | 575 | ||
| @@ -555,13 +583,15 @@ EXPORT_SYMBOL(tty_flip_buffer_push); | |||
| 555 | * Locking: none | 583 | * Locking: none |
| 556 | */ | 584 | */ |
| 557 | 585 | ||
| 558 | void tty_buffer_init(struct tty_struct *tty) | 586 | void tty_buffer_init(struct tty_port *port) |
| 559 | { | 587 | { |
| 560 | spin_lock_init(&tty->buf.lock); | 588 | struct tty_bufhead *buf = &port->buf; |
| 561 | tty->buf.head = NULL; | 589 | |
| 562 | tty->buf.tail = NULL; | 590 | spin_lock_init(&buf->lock); |
| 563 | tty->buf.free = NULL; | 591 | buf->head = NULL; |
| 564 | tty->buf.memory_used = 0; | 592 | buf->tail = NULL; |
| 565 | INIT_WORK(&tty->buf.work, flush_to_ldisc); | 593 | buf->free = NULL; |
| 594 | buf->memory_used = 0; | ||
| 595 | INIT_WORK(&buf->work, flush_to_ldisc); | ||
| 566 | } | 596 | } |
| 567 | 597 | ||
