Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
- index 8bea09e..6d6509b 100644
- --- a/arch/arm/mach-msm/smd_tty.c
- +++ b/arch/arm/mach-msm/smd_tty.c
- @@ -30,6 +30,7 @@
- #include <asm/mach-types.h>
- #define MAX_SMD_TTYS 32
- +#define SMD_BUF_SIZE (16 * 1024)
- static DEFINE_MUTEX(smd_tty_lock);
- @@ -38,7 +39,8 @@ struct smd_tty_info {
- struct tty_struct *tty;
- struct wake_lock wake_lock;
- int open_count;
- - struct work_struct tty_work;
- + struct delayed_work tty_delayed_work;
- + unsigned char *rx_buffer;
- };
- static struct smd_tty_info smd_tty[MAX_SMD_TTYS];
- @@ -69,10 +71,19 @@ static void smd_readx_cb(void *data, int count, void *ctxt)
- static void smd_tty_work_func(struct work_struct *work)
- {
- - int avail;
- - struct smd_tty_info *info = container_of(work,
- - struct smd_tty_info,
- - tty_work);
- + unsigned char *ptr;
- + int avail;
- + int fail_cnt=0;
- + int exit_loop=0;
- +
- + struct delayed_work *delayed_work = container_of(work,
- + struct delayed_work,
- + work);
- +
- + struct smd_tty_info *info = container_of(delayed_work,
- + struct smd_tty_info,
- + tty_delayed_work);
- +
- struct tty_struct *tty = info->tty;
- if (!tty)
- @@ -94,15 +105,59 @@ static void smd_tty_work_func(struct work_struct *work)
- break;
- }
- - if (smd_readx(info->ch, avail, smd_readx_cb, (void *)tty) != avail) {
- - /* shouldn't be possible since we're in interrupt
- - ** context here and nobody else could 'steal' our
- - ** characters.
- - */
- - printk(KERN_ERR "OOPS - smd_tty_buffer mismatch?!\n");
- - }
- + if(tty->index==7)
- + {
- + if (smd_readx(info->ch, avail, smd_readx_cb, (void *)tty) != avail) {
- + /* shouldn't be possible since we're in interrupt
- + ** context here and nobody else could 'steal' our
- + ** characters.
- + */
- + printk(KERN_ERR "OOPS - smd_tty_buffer mismatch?!\n");
- + }
- + }else{
- + avail = tty_prepare_flip_string(tty, &ptr, avail);
- + if ( avail == 0)
- + {
- + if(fail_cnt)
- + {
- + if(smd_read_avail(info->ch) > 2048)
- + avail = tty_prepare_flip_string(tty, &ptr, 2048);
- + //TODO: this is nice but it can cause the the size of the required tty realloc to get bigger
- + // and bigger since our smd channel is collecting more and more bytes but we have failed to
- + // deliver any of them to userland. Leading to permanent failure of the smd channel.
- + // we should probably try to send smaller chunks to prevent the realloc all togeather.
- +
- +
- + //We have had about enough
- + //need to get started up later because we have already been notified of a non empty
- + //buffer, unforunately the SLAB is not going to give in atm
- + queue_delayed_work(smd_tty_wq, &info->tty_delayed_work,HZ/50);
- + printk("SMD%s: tty induced slab failure. high probability of smd pipe freeze. chan %d, needed %d, smallish %d\n",__func__, tty->index, smd_read_avail(info->ch),avail);
- + if(avail==0)
- + exit_loop=1;
- + }
- + fail_cnt++;
- + }
- +
- + if (avail && smd_read(info->ch, ptr, avail) != avail) {
- + /* shouldn't be possible since we're in interrupt
- + ** context here and nobody else could 'steal' our
- + ** characters.
- + */
- + printk(KERN_ERR "OOPS - smd_tty_buffer mismatch?!");
- + }
- + }
- +
- wake_lock_timeout(&info->wake_lock, HZ / 2);
- mutex_unlock(&smd_tty_lock);
- +
- + if(tty->index!=7)
- + {
- + tty_flip_buffer_push(tty);
- + if(exit_loop)
- + break;
- +
- + }
- }
- /* XXX only when writable and necessary */
- @@ -118,7 +173,8 @@ static void smd_tty_notify(void *priv, unsigned event)
- if (event != SMD_EVENT_DATA)
- return;
- - queue_work(smd_tty_wq, &info->tty_work);
- + queue_delayed_work(smd_tty_wq, &info->tty_delayed_work,0);
- +
- }
- static int smd_tty_open(struct tty_struct *tty, struct file *f)
- @@ -217,7 +273,7 @@ static int smd_tty_chars_in_buffer(struct tty_struct *tty)
- static void smd_tty_unthrottle(struct tty_struct *tty)
- {
- struct smd_tty_info *info = tty->driver_data;
- - queue_work(smd_tty_wq, &info->tty_work);
- + queue_delayed_work(smd_tty_wq, &info->tty_delayed_work,0);
- return;
- }
- @@ -267,13 +323,17 @@ static int __init smd_tty_init(void)
- /* this should be dynamic */
- tty_register_device(smd_tty_driver, 0, 0);
- - INIT_WORK(&smd_tty[0].tty_work, smd_tty_work_func);
- + INIT_DELAYED_WORK(&smd_tty[0].tty_delayed_work, smd_tty_work_func);
- + smd_tty[1].rx_buffer = (unsigned char *)kmalloc(SMD_BUF_SIZE,GFP_KERNEL);
- tty_register_device(smd_tty_driver, 1, 0);
- - INIT_WORK(&smd_tty[1].tty_work, smd_tty_work_func);
- + INIT_DELAYED_WORK(&smd_tty[1].tty_delayed_work, smd_tty_work_func);
- + smd_tty[1].rx_buffer = (unsigned char *)kmalloc(SMD_BUF_SIZE,GFP_KERNEL);
- tty_register_device(smd_tty_driver, 7, 0);
- - INIT_WORK(&smd_tty[7].tty_work, smd_tty_work_func);
- + INIT_DELAYED_WORK(&smd_tty[7].tty_delayed_work, smd_tty_work_func);
- + smd_tty[7].rx_buffer = (unsigned char *)kmalloc(SMD_BUF_SIZE,GFP_KERNEL);
- tty_register_device(smd_tty_driver, 27, 0);
- - INIT_WORK(&smd_tty[27].tty_work, smd_tty_work_func);
- + INIT_DELAYED_WORK(&smd_tty[27].tty_delayed_work, smd_tty_work_func);
- + smd_tty[27].rx_buffer = (unsigned char *)kmalloc(SMD_BUF_SIZE,GFP_KERNEL);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement