From 5e88e6c4e8b044a1d275f1a599128b95046d2968 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:51:57 +0100 Subject: ALPHA: srmcons, use timer functions It makes the code more readable. We move the setup to the allocation location because we need to initialize timers only once. Signed-off-by: Jiri Slaby Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Matt Turner Signed-off-by: Greg Kroah-Hartman --- arch/alpha/kernel/srmcons.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'arch/alpha/kernel') diff --git a/arch/alpha/kernel/srmcons.c b/arch/alpha/kernel/srmcons.c index 783f4e50c111..f1fdf178bcb4 100644 --- a/arch/alpha/kernel/srmcons.c +++ b/arch/alpha/kernel/srmcons.c @@ -79,10 +79,8 @@ srmcons_receive_chars(unsigned long data) } spin_lock(&srmconsp->lock); - if (srmconsp->tty) { - srmconsp->timer.expires = jiffies + incr; - add_timer(&srmconsp->timer); - } + if (srmconsp->tty) + mod_timer(&srmconsp->timer, jiffies + incr); spin_unlock(&srmconsp->lock); local_irq_restore(flags); @@ -172,7 +170,8 @@ srmcons_get_private_struct(struct srmcons_private **ps) else { srmconsp->tty = NULL; spin_lock_init(&srmconsp->lock); - init_timer(&srmconsp->timer); + setup_timer(&srmconsp->timer, srmcons_receive_chars, + (unsigned long)srmconsp); } spin_unlock_irqrestore(&srmconsp_lock, flags); @@ -199,10 +198,7 @@ srmcons_open(struct tty_struct *tty, struct file *filp) tty->driver_data = srmconsp; srmconsp->tty = tty; - srmconsp->timer.function = srmcons_receive_chars; - srmconsp->timer.data = (unsigned long)srmconsp; - srmconsp->timer.expires = jiffies + 10; - add_timer(&srmconsp->timer); + mod_timer(&srmconsp->timer, jiffies + 10); } spin_unlock_irqrestore(&srmconsp->lock, flags); -- cgit v1.2.1 From ee024d494ab75426bc77e0c053700915f0a1a16d Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:51:58 +0100 Subject: ALPHA: srmcons, fix racy singleton structure The test and the assignment were racy. Make it really a singleton. This is achieved by one global variable initialized at the module init. Signed-off-by: Jiri Slaby Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Matt Turner Signed-off-by: Greg Kroah-Hartman --- arch/alpha/kernel/srmcons.c | 40 +++++----------------------------------- 1 file changed, 5 insertions(+), 35 deletions(-) (limited to 'arch/alpha/kernel') diff --git a/arch/alpha/kernel/srmcons.c b/arch/alpha/kernel/srmcons.c index f1fdf178bcb4..2c89ce5c9ab6 100644 --- a/arch/alpha/kernel/srmcons.c +++ b/arch/alpha/kernel/srmcons.c @@ -33,7 +33,7 @@ struct srmcons_private { struct tty_struct *tty; struct timer_list timer; spinlock_t lock; -}; +} srmcons_singleton; typedef union _srmcons_result { struct { @@ -153,44 +153,11 @@ srmcons_chars_in_buffer(struct tty_struct *tty) return 0; } -static int -srmcons_get_private_struct(struct srmcons_private **ps) -{ - static struct srmcons_private *srmconsp = NULL; - static DEFINE_SPINLOCK(srmconsp_lock); - unsigned long flags; - int retval = 0; - - if (srmconsp == NULL) { - srmconsp = kmalloc(sizeof(*srmconsp), GFP_KERNEL); - spin_lock_irqsave(&srmconsp_lock, flags); - - if (srmconsp == NULL) - retval = -ENOMEM; - else { - srmconsp->tty = NULL; - spin_lock_init(&srmconsp->lock); - setup_timer(&srmconsp->timer, srmcons_receive_chars, - (unsigned long)srmconsp); - } - - spin_unlock_irqrestore(&srmconsp_lock, flags); - } - - *ps = srmconsp; - return retval; -} - static int srmcons_open(struct tty_struct *tty, struct file *filp) { - struct srmcons_private *srmconsp; + struct srmcons_private *srmconsp = &srmcons_singleton; unsigned long flags; - int retval; - - retval = srmcons_get_private_struct(&srmconsp); - if (retval) - return retval; spin_lock_irqsave(&srmconsp->lock, flags); @@ -236,6 +203,9 @@ static const struct tty_operations srmcons_ops = { static int __init srmcons_init(void) { + spin_lock_init(&srmcons_singleton.lock); + setup_timer(&srmcons_singleton.timer, srmcons_receive_chars, + (unsigned long)&srmcons_singleton); if (srm_is_registered_console) { struct tty_driver *driver; int err; -- cgit v1.2.1 From 54089d4cdc89732e65f968209d10aae542482c0c Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:51:59 +0100 Subject: TTY: srmcons, convert to use tty_port This is needed because the tty buffer will become a tty_port member later. That will help us to wipe out most of the races and checks for the tty pointer in hot paths. Signed-off-by: Jiri Slaby Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Matt Turner Signed-off-by: Greg Kroah-Hartman --- arch/alpha/kernel/srmcons.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'arch/alpha/kernel') diff --git a/arch/alpha/kernel/srmcons.c b/arch/alpha/kernel/srmcons.c index 2c89ce5c9ab6..3ea809430eda 100644 --- a/arch/alpha/kernel/srmcons.c +++ b/arch/alpha/kernel/srmcons.c @@ -30,9 +30,8 @@ static int srm_is_registered_console = 0; #define MAX_SRM_CONSOLE_DEVICES 1 /* only support 1 console device */ struct srmcons_private { - struct tty_struct *tty; + struct tty_port port; struct timer_list timer; - spinlock_t lock; } srmcons_singleton; typedef union _srmcons_result { @@ -68,20 +67,21 @@ static void srmcons_receive_chars(unsigned long data) { struct srmcons_private *srmconsp = (struct srmcons_private *)data; + struct tty_port *port = &srmconsp->port; unsigned long flags; int incr = 10; local_irq_save(flags); if (spin_trylock(&srmcons_callback_lock)) { - if (!srmcons_do_receive_chars(srmconsp->tty)) + if (!srmcons_do_receive_chars(port->tty)) incr = 100; spin_unlock(&srmcons_callback_lock); } - spin_lock(&srmconsp->lock); - if (srmconsp->tty) + spin_lock(&port->lock); + if (port->tty) mod_timer(&srmconsp->timer, jiffies + incr); - spin_unlock(&srmconsp->lock); + spin_unlock(&port->lock); local_irq_restore(flags); } @@ -157,18 +157,19 @@ static int srmcons_open(struct tty_struct *tty, struct file *filp) { struct srmcons_private *srmconsp = &srmcons_singleton; + struct tty_port *port = &srmconsp->port; unsigned long flags; - spin_lock_irqsave(&srmconsp->lock, flags); + spin_lock_irqsave(&port->lock, flags); - if (!srmconsp->tty) { + if (!port->tty) { tty->driver_data = srmconsp; - - srmconsp->tty = tty; + tty->port = port; + port->tty = tty; /* XXX proper refcounting */ mod_timer(&srmconsp->timer, jiffies + 10); } - spin_unlock_irqrestore(&srmconsp->lock, flags); + spin_unlock_irqrestore(&port->lock, flags); return 0; } @@ -177,16 +178,17 @@ static void srmcons_close(struct tty_struct *tty, struct file *filp) { struct srmcons_private *srmconsp = tty->driver_data; + struct tty_port *port = &srmconsp->port; unsigned long flags; - spin_lock_irqsave(&srmconsp->lock, flags); + spin_lock_irqsave(&port->lock, flags); if (tty->count == 1) { - srmconsp->tty = NULL; + port->tty = NULL; del_timer(&srmconsp->timer); } - spin_unlock_irqrestore(&srmconsp->lock, flags); + spin_unlock_irqrestore(&port->lock, flags); } @@ -203,7 +205,7 @@ static const struct tty_operations srmcons_ops = { static int __init srmcons_init(void) { - spin_lock_init(&srmcons_singleton.lock); + tty_port_init(&srmcons_singleton.port); setup_timer(&srmcons_singleton.timer, srmcons_receive_chars, (unsigned long)&srmcons_singleton); if (srm_is_registered_console) { -- cgit v1.2.1