[PATCH] new tty buffering locking fix
Change locking in the new tty buffering facility from using tty->read_lock, which is currently ignored by drivers and thus ineffective. New locking uses a new tty buffering specific lock enforced centrally in the tty buffering code. Two drivers (esp and cyclades) are updated to use the tty buffering functions instead of accessing tty buffering internals directly. This is required for the new locking to work. Minor checks for NULL buffers added to tty_prepare_flip_string/tty_prepare_flip_string_flags Signed-off-by: Paul Fulghum <paulkf@microgate.com> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
committed by
Linus Torvalds
parent
546cfdf47f
commit
808249ceba
@@ -151,6 +151,11 @@ extern unsigned int keymap_count;
|
||||
|
||||
static inline void con_schedule_flip(struct tty_struct *t)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&t->buf.lock, flags);
|
||||
if (t->buf.tail != NULL)
|
||||
t->buf.tail->active = 0;
|
||||
spin_unlock_irqrestore(&t->buf.lock, flags);
|
||||
schedule_work(&t->buf.work);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ struct tty_buffer {
|
||||
unsigned char *flag_buf_ptr;
|
||||
int used;
|
||||
int size;
|
||||
int active;
|
||||
/* Data points here */
|
||||
unsigned long data[0];
|
||||
};
|
||||
@@ -64,6 +65,7 @@ struct tty_buffer {
|
||||
struct tty_bufhead {
|
||||
struct work_struct work;
|
||||
struct semaphore pty_sem;
|
||||
spinlock_t lock;
|
||||
struct tty_buffer *head; /* Queue head */
|
||||
struct tty_buffer *tail; /* Active buffer */
|
||||
struct tty_buffer *free; /* Free queue head */
|
||||
|
||||
@@ -17,7 +17,7 @@ _INLINE_ int tty_insert_flip_char(struct tty_struct *tty,
|
||||
unsigned char ch, char flag)
|
||||
{
|
||||
struct tty_buffer *tb = tty->buf.tail;
|
||||
if (tb && tb->used < tb->size) {
|
||||
if (tb && tb->active && tb->used < tb->size) {
|
||||
tb->flag_buf_ptr[tb->used] = flag;
|
||||
tb->char_buf_ptr[tb->used++] = ch;
|
||||
return 1;
|
||||
@@ -27,6 +27,11 @@ _INLINE_ int tty_insert_flip_char(struct tty_struct *tty,
|
||||
|
||||
_INLINE_ void tty_schedule_flip(struct tty_struct *tty)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&tty->buf.lock, flags);
|
||||
if (tty->buf.tail != NULL)
|
||||
tty->buf.tail->active = 0;
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
schedule_delayed_work(&tty->buf.work, 1);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user