Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 19672
b: refs/heads/master
c: 808249c
h: refs/heads/master
v: v3
  • Loading branch information
Paul Fulghum authored and Linus Torvalds committed Feb 3, 2006
1 parent 59e80e6 commit 7fe88ba
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 34 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 546cfdf47f2ea2438b01f8626a60b87f9d8d1e53
refs/heads/master: 808249ceba49cdb3054c0aa5b75a61862d6cab94
6 changes: 3 additions & 3 deletions trunk/drivers/char/cyclades.c
Original file line number Diff line number Diff line change
Expand Up @@ -1233,7 +1233,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
info->idle_stats.recv_idle = jiffies;
}
schedule_delayed_work(&tty->buf.work, 1);
tty_schedule_flip(tty);
}
/* end of service */
cy_writeb(base_addr+(CyRIR<<index), (save_xir & 0x3f));
Expand Down Expand Up @@ -1606,7 +1606,7 @@ cyz_handle_rx(struct cyclades_port *info,
}
#endif
info->idle_stats.recv_idle = jiffies;
schedule_delayed_work(&tty->buf.work, 1);
tty_schedule_flip(tty);
}
/* Update rx_get */
cy_writel(&buf_ctrl->rx_get, new_rx_get);
Expand Down Expand Up @@ -1809,7 +1809,7 @@ cyz_handle_cmd(struct cyclades_card *cinfo)
if(delta_count)
cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
if(special_count)
schedule_delayed_work(&tty->buf.work, 1);
tty_schedule_flip(tty);
}
}

Expand Down
4 changes: 2 additions & 2 deletions trunk/drivers/char/esp.c
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ static inline void receive_chars_pio(struct esp_struct *info, int num_bytes)
}
}

schedule_delayed_work(&tty->buf.work, 1);
tty_schedule_flip(tty);

info->stat_flags &= ~ESP_STAT_RX_TIMEOUT;
release_pio_buffer(pio_buf);
Expand Down Expand Up @@ -426,7 +426,7 @@ static inline void receive_chars_dma_done(struct esp_struct *info,
}
tty_insert_flip_char(tty, dma_buffer[num_bytes - 1], statflag);
}
schedule_delayed_work(&tty->buf.work, 1);
tty_schedule_flip(tty);
}

if (dma_bytes != num_bytes) {
Expand Down
77 changes: 50 additions & 27 deletions trunk/drivers/char/tty_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ static void tty_buffer_free_all(struct tty_struct *tty)

static void tty_buffer_init(struct tty_struct *tty)
{
spin_lock_init(&tty->buf.lock);
tty->buf.head = NULL;
tty->buf.tail = NULL;
tty->buf.free = NULL;
Expand All @@ -266,6 +267,7 @@ static struct tty_buffer *tty_buffer_alloc(size_t size)
p->used = 0;
p->size = size;
p->next = NULL;
p->active = 0;
p->char_buf_ptr = (char *)(p->data);
p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
/* printk("Flip create %p\n", p); */
Expand Down Expand Up @@ -312,25 +314,36 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)

int tty_buffer_request_room(struct tty_struct *tty, size_t size)
{
struct tty_buffer *b = tty->buf.tail, *n;
int left = 0;
struct tty_buffer *b, *n;
int left;
unsigned long flags;

spin_lock_irqsave(&tty->buf.lock, flags);

/* OPTIMISATION: We could keep a per tty "zero" sized buffer to
remove this conditional if its worth it. This would be invisible
to the callers */
if(b != NULL)
if ((b = tty->buf.tail) != NULL) {
left = b->size - b->used;
if(left >= size)
return size;
/* This is the slow path - looking for new buffers to use */
n = tty_buffer_find(tty, size);
if(n == NULL)
return left;
if(b != NULL)
b->next = n;
else
tty->buf.head = n;
tty->buf.tail = n;
b->active = 1;
} else
left = 0;

if (left < size) {
/* This is the slow path - looking for new buffers to use */
if ((n = tty_buffer_find(tty, size)) != NULL) {
if (b != NULL) {
b->next = n;
b->active = 0;
} else
tty->buf.head = n;
tty->buf.tail = n;
n->active = 1;
} else
size = left;
}

spin_unlock_irqrestore(&tty->buf.lock, flags);
return size;
}

Expand Down Expand Up @@ -396,10 +409,12 @@ EXPORT_SYMBOL_GPL(tty_insert_flip_string_flags);
int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size)
{
int space = tty_buffer_request_room(tty, size);
struct tty_buffer *tb = tty->buf.tail;
*chars = tb->char_buf_ptr + tb->used;
memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
tb->used += space;
if (likely(space)) {
struct tty_buffer *tb = tty->buf.tail;
*chars = tb->char_buf_ptr + tb->used;
memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
tb->used += space;
}
return space;
}

Expand All @@ -416,10 +431,12 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size)
{
int space = tty_buffer_request_room(tty, size);
struct tty_buffer *tb = tty->buf.tail;
*chars = tb->char_buf_ptr + tb->used;
*flags = tb->flag_buf_ptr + tb->used;
tb->used += space;
if (likely(space)) {
struct tty_buffer *tb = tty->buf.tail;
*chars = tb->char_buf_ptr + tb->used;
*flags = tb->flag_buf_ptr + tb->used;
tb->used += space;
}
return space;
}

Expand Down Expand Up @@ -2747,20 +2764,20 @@ static void flush_to_ldisc(void *private_)
schedule_delayed_work(&tty->buf.work, 1);
goto out;
}
spin_lock_irqsave(&tty->read_lock, flags);
while((tbuf = tty->buf.head) != NULL) {
spin_lock_irqsave(&tty->buf.lock, flags);
while((tbuf = tty->buf.head) != NULL && !tbuf->active) {
tty->buf.head = tbuf->next;
if (tty->buf.head == NULL)
tty->buf.tail = NULL;
spin_unlock_irqrestore(&tty->read_lock, flags);
spin_unlock_irqrestore(&tty->buf.lock, flags);
/* printk("Process buffer %p for %d\n", tbuf, tbuf->used); */
disc->receive_buf(tty, tbuf->char_buf_ptr,
tbuf->flag_buf_ptr,
tbuf->used);
spin_lock_irqsave(&tty->read_lock, flags);
spin_lock_irqsave(&tty->buf.lock, flags);
tty_buffer_free(tty, tbuf);
}
spin_unlock_irqrestore(&tty->read_lock, flags);
spin_unlock_irqrestore(&tty->buf.lock, flags);
out:
tty_ldisc_deref(disc);
}
Expand Down Expand Up @@ -2852,6 +2869,12 @@ EXPORT_SYMBOL(tty_get_baud_rate);

void tty_flip_buffer_push(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);

if (tty->low_latency)
flush_to_ldisc((void *) tty);
else
Expand Down
5 changes: 5 additions & 0 deletions trunk/include/linux/kbd_kern.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
2 changes: 2 additions & 0 deletions trunk/include/linux/tty.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,15 @@ struct tty_buffer {
unsigned char *flag_buf_ptr;
int used;
int size;
int active;
/* Data points here */
unsigned long data[0];
};

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 */
Expand Down
7 changes: 6 additions & 1 deletion trunk/include/linux/tty_flip.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}

Expand Down

0 comments on commit 7fe88ba

Please sign in to comment.