From 2f16669d322e05171c9e1cfd94f402f7399bd2a3 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:51:52 +0100 Subject: TTY: remove re-assignments to tty_driver members All num, magic and owner are set by alloc_tty_driver. No need to re-set them on each allocation site. pti driver sets something different to what it passes to alloc_tty_driver. It is not a bug, since we don't use the lines parameter in any way. Anyway this is fixed, and now we do the right thing. Signed-off-by: Jiri Slaby Acked-by: Tilman Schmidt Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 1 - arch/m68k/emu/nfcon.c | 1 - arch/xtensa/platforms/iss/console.c | 1 - 3 files changed, 3 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index bff0824cf8a4..f513dc02bb87 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -928,7 +928,6 @@ simrs_init (void) /* Initialize the tty_driver structure */ - hp_simserial_driver->owner = THIS_MODULE; hp_simserial_driver->driver_name = "simserial"; hp_simserial_driver->name = "ttyS"; hp_simserial_driver->major = TTY_MAJOR; diff --git a/arch/m68k/emu/nfcon.c b/arch/m68k/emu/nfcon.c index ab20dc0ff63b..8db25e806947 100644 --- a/arch/m68k/emu/nfcon.c +++ b/arch/m68k/emu/nfcon.c @@ -127,7 +127,6 @@ static int __init nfcon_init(void) if (!nfcon_tty_driver) return -ENOMEM; - nfcon_tty_driver->owner = THIS_MODULE; nfcon_tty_driver->driver_name = "nfcon"; nfcon_tty_driver->name = "nfcon"; nfcon_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM; diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c index 2c723e8b30da..247e9d40a52e 100644 --- a/arch/xtensa/platforms/iss/console.c +++ b/arch/xtensa/platforms/iss/console.c @@ -216,7 +216,6 @@ int __init rs_init(void) /* Initialize the tty_driver structure */ - serial_driver->owner = THIS_MODULE; serial_driver->driver_name = "iss_serial"; serial_driver->name = "ttyS"; serial_driver->major = TTY_MAJOR; -- cgit v1.2.3 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') 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.3 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') 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.3 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') 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.3 From 410235fd4d20b8feaf8930a0575d23acc088aa87 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:01 +0100 Subject: TTY: remove unneeded tty->index checks Checking if tty->index is in bounds is not needed. The tty has the index set in the initial open. This is done in get_tty_driver. And it can be only in interval <0,driver->num). So remove the tests which check exactly this interval. Some are left untouched as they check against the current backing device count. (Leaving apart that the check is racy in most of the cases.) Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 9 +++------ arch/xtensa/platforms/iss/console.c | 8 ++------ drivers/char/pcmcia/synclink_cs.c | 2 +- drivers/isdn/capi/capi.c | 3 +-- drivers/isdn/gigaset/common.c | 2 -- drivers/isdn/i4l/isdn_tty.c | 7 ++----- drivers/s390/char/con3215.c | 8 ++------ drivers/tty/amiserial.c | 10 +++------- drivers/tty/cyclades.c | 6 +----- drivers/tty/hvc/hvcs.c | 24 ++++++++++-------------- drivers/tty/hvc/hvsi.c | 5 +---- drivers/tty/isicom.c | 2 -- drivers/tty/mxser.c | 2 -- drivers/tty/rocket.c | 6 +++--- drivers/tty/serial/68328serial.c | 9 ++------- drivers/tty/serial/crisv10.c | 15 +++------------ drivers/tty/synclink.c | 2 +- drivers/tty/synclink_gt.c | 2 +- drivers/tty/synclinkmp.c | 2 +- drivers/usb/gadget/u_serial.c | 3 --- net/irda/ircomm/ircomm_tty.c | 6 +----- 21 files changed, 38 insertions(+), 95 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index f513dc02bb87..2a2fe0c56119 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -769,13 +769,10 @@ errout: static int rs_open(struct tty_struct *tty, struct file * filp) { struct async_struct *info; - int retval, line; + int retval; unsigned long page; - line = tty->index; - if ((line < 0) || (line >= NR_PORTS)) - return -ENODEV; - retval = get_async_struct(line, &info); + retval = get_async_struct(tty->index, &info); if (retval) return retval; tty->driver_data = info; @@ -920,7 +917,7 @@ simrs_init (void) if (!ia64_platform_is("hpsim")) return -ENODEV; - hp_simserial_driver = alloc_tty_driver(1); + hp_simserial_driver = alloc_tty_driver(NR_PORTS); if (!hp_simserial_driver) return -ENOMEM; diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c index 247e9d40a52e..19a802a13096 100644 --- a/arch/xtensa/platforms/iss/console.c +++ b/arch/xtensa/platforms/iss/console.c @@ -68,11 +68,6 @@ static void rs_poll(unsigned long); static int rs_open(struct tty_struct *tty, struct file * filp) { - int line = tty->index; - - if ((line < 0) || (line >= SERIAL_MAX_NUM_LINES)) - return -ENODEV; - spin_lock(&timer_lock); if (tty->count == 1) { @@ -101,6 +96,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) { spin_lock(&timer_lock); if (tty->count == 1) + /* this will cause a deadlock if the timer ticks right now */ del_timer_sync(&serial_timer); spin_unlock(&timer_lock); } @@ -210,7 +206,7 @@ static const struct tty_operations serial_ops = { int __init rs_init(void) { - serial_driver = alloc_tty_driver(1); + serial_driver = alloc_tty_driver(SERIAL_MAX_NUM_LINES); printk ("%s %s\n", serial_name, serial_version); diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index c3bcb1221e6b..f6453df4921c 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -2484,7 +2484,7 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp) /* verify range of specified line number */ line = tty->index; - if ((line < 0) || (line >= mgslpc_device_count)) { + if (line >= mgslpc_device_count) { printk("%s(%d):mgslpc_open with invalid line #%d.\n", __FILE__,__LINE__,line); return -ENODEV; diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index baf08eba495c..3a7905b06e53 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -1013,8 +1013,7 @@ static const struct file_operations capi_fops = static int capinc_tty_install(struct tty_driver *driver, struct tty_struct *tty) { - int idx = tty->index; - struct capiminor *mp = capiminor_get(idx); + struct capiminor *mp = capiminor_get(tty->index); int ret = tty_standard_install(driver, tty); if (ret == 0) diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index db621db67f61..ac0186e54bf4 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -1051,8 +1051,6 @@ static struct cardstate *gigaset_get_cs_by_minor(unsigned minor) struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty) { - if (tty->index < 0 || tty->index >= tty->driver->num) - return NULL; return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start); } diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 2c26b64ebbea..ac4840124bc0 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1590,12 +1590,9 @@ static int isdn_tty_open(struct tty_struct *tty, struct file *filp) { modem_info *info; - int retval, line; + int retval; - line = tty->index; - if (line < 0 || line >= ISDN_MAX_CHANNELS) - return -ENODEV; - info = &dev->mdm.info[line]; + info = &dev->mdm.info[tty->index]; if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open")) return -ENODEV; if (!try_module_get(info->owner)) { diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index fe916bfd60f2..ed23fec7abbe 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -926,13 +926,9 @@ console_initcall(con3215_init); static int tty3215_open(struct tty_struct *tty, struct file * filp) { struct raw3215_info *raw; - int retval, line; + int retval; - line = tty->index; - if ((line < 0) || (line >= NR_3215)) - return -ENODEV; - - raw = raw3215[line]; + raw = raw3215[tty->index]; if (raw == NULL) return -ENODEV; diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index b42f00d987ae..753286257554 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -1768,13 +1768,9 @@ static int get_async_struct(int line, struct async_struct **ret_info) static int rs_open(struct tty_struct *tty, struct file * filp) { struct async_struct *info; - int retval, line; + int retval; - line = tty->index; - if ((line < 0) || (line >= NR_PORTS)) { - return -ENODEV; - } - retval = get_async_struct(line, &info); + retval = get_async_struct(tty->index, &info); if (retval) { return retval; } @@ -1964,7 +1960,7 @@ static int __init amiga_serial_probe(struct platform_device *pdev) struct serial_state * state; int error; - serial_driver = alloc_tty_driver(1); + serial_driver = alloc_tty_driver(NR_PORTS); if (!serial_driver) return -ENOMEM; diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index bc7b5a5650ba..e61cabdd69df 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -1515,13 +1515,9 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) static int cy_open(struct tty_struct *tty, struct file *filp) { struct cyclades_port *info; - unsigned int i, line; + unsigned int i, line = tty->index; int retval; - line = tty->index; - if (tty->index < 0 || NR_PORTS <= line) - return -ENODEV; - for (i = 0; i < NR_CARDS; i++) if (line < cy_card[i].first_line + cy_card[i].nports && line >= cy_card[i].first_line) diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c index da0aa476804d..d23759183b47 100644 --- a/drivers/tty/hvc/hvcs.c +++ b/drivers/tty/hvc/hvcs.c @@ -1090,27 +1090,23 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address, */ static struct hvcs_struct *hvcs_get_by_index(int index) { - struct hvcs_struct *hvcsd = NULL; + struct hvcs_struct *hvcsd; unsigned long flags; spin_lock(&hvcs_structs_lock); - /* We can immediately discard OOB requests */ - if (index >= 0 && index < HVCS_MAX_SERVER_ADAPTERS) { - list_for_each_entry(hvcsd, &hvcs_structs, next) { - spin_lock_irqsave(&hvcsd->lock, flags); - if (hvcsd->index == index) { - kref_get(&hvcsd->kref); - spin_unlock_irqrestore(&hvcsd->lock, flags); - spin_unlock(&hvcs_structs_lock); - return hvcsd; - } + list_for_each_entry(hvcsd, &hvcs_structs, next) { + spin_lock_irqsave(&hvcsd->lock, flags); + if (hvcsd->index == index) { + kref_get(&hvcsd->kref); spin_unlock_irqrestore(&hvcsd->lock, flags); + spin_unlock(&hvcs_structs_lock); + return hvcsd; } - hvcsd = NULL; + spin_unlock_irqrestore(&hvcsd->lock, flags); } - spin_unlock(&hvcs_structs_lock); - return hvcsd; + + return NULL; } /* diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c index 60bc45164189..a7488b748647 100644 --- a/drivers/tty/hvc/hvsi.c +++ b/drivers/tty/hvc/hvsi.c @@ -737,14 +737,11 @@ static int hvsi_open(struct tty_struct *tty, struct file *filp) { struct hvsi_struct *hp; unsigned long flags; - int line = tty->index; int ret; pr_debug("%s\n", __func__); - if (line < 0 || line >= hvsi_count) - return -ENODEV; - hp = &hvsi_ports[line]; + hp = &hvsi_ports[tty->index]; tty->driver_data = hp; diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c index b3a28b5f02ad..03c14979accf 100644 --- a/drivers/tty/isicom.c +++ b/drivers/tty/isicom.c @@ -849,8 +849,6 @@ static struct tty_port *isicom_find_port(struct tty_struct *tty) unsigned int board; int line = tty->index; - if (line < 0 || line > PORT_COUNT-1) - return NULL; board = BOARD(line); card = &isi_card[board]; diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 260d03123524..17ff377e4129 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -1010,8 +1010,6 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) line = tty->index; if (line == MXSER_PORTS) return 0; - if (line < 0 || line > MXSER_PORTS) - return -ENODEV; info = &mxser_boards[line / MXSER_PORTS_PER_BOARD].ports[line % MXSER_PORTS_PER_BOARD]; if (!info->ioaddr) return -ENODEV; diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index b088e1ea4331..777d5f9cf6cc 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -892,12 +892,12 @@ static int rp_open(struct tty_struct *tty, struct file *filp) { struct r_port *info; struct tty_port *port; - int line = 0, retval; + int retval; CHANNEL_t *cp; unsigned long page; - line = tty->index; - if (line < 0 || line >= MAX_RP_PORTS || ((info = rp_table[line]) == NULL)) + info = rp_table[tty->index]; + if (info == NULL) return -ENXIO; port = &info->port; diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c index a88ef9782a4f..7398390e7e65 100644 --- a/drivers/tty/serial/68328serial.c +++ b/drivers/tty/serial/68328serial.c @@ -1190,14 +1190,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, int rs_open(struct tty_struct *tty, struct file * filp) { struct m68k_serial *info; - int retval, line; - - line = tty->index; - - if (line >= NR_PORTS || line < 0) /* we have exactly one */ - return -ENODEV; + int retval; - info = &m68k_soft[line]; + info = &m68k_soft[tty->index]; if (serial_paranoia_check(info, tty->name, "rs_open")) return -ENODEV; diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index 1dfba7b779c8..23d791696879 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -4105,20 +4105,11 @@ static int rs_open(struct tty_struct *tty, struct file * filp) { struct e100_serial *info; - int retval, line; + int retval; unsigned long page; int allocated_resources = 0; - /* find which port we want to open */ - line = tty->index; - - if (line < 0 || line >= NR_PORTS) - return -ENODEV; - - /* find the corresponding e100_serial struct in the table */ - info = rs_table + line; - - /* don't allow the opening of ports that are not enabled in the HW config */ + info = rs_table + tty->index; if (!info->enabled) return -ENODEV; @@ -4131,7 +4122,7 @@ rs_open(struct tty_struct *tty, struct file * filp) tty->driver_data = info; info->port.tty = tty; - info->port.tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + tty->low_latency = !!(info->flags & ASYNC_LOW_LATENCY); if (!tmp_buf) { page = get_zeroed_page(GFP_KERNEL); diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index 2b2988c779c7..8e518da85fd5 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c @@ -3381,7 +3381,7 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp) /* verify range of specified line number */ line = tty->index; - if ((line < 0) || (line >= mgsl_device_count)) { + if (line >= mgsl_device_count) { printk("%s(%d):mgsl_open with invalid line #%d.\n", __FILE__,__LINE__,line); return -ENODEV; diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index a8b66be37e6e..6bee4907c6a5 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c @@ -654,7 +654,7 @@ static int open(struct tty_struct *tty, struct file *filp) unsigned long flags; line = tty->index; - if ((line < 0) || (line >= slgt_device_count)) { + if (line >= slgt_device_count) { DBGERR(("%s: open with invalid line #%d.\n", driver_name, line)); return -ENODEV; } diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c index ddabb61c85ba..4fb6c4b31b79 100644 --- a/drivers/tty/synclinkmp.c +++ b/drivers/tty/synclinkmp.c @@ -721,7 +721,7 @@ static int open(struct tty_struct *tty, struct file *filp) unsigned long flags; line = tty->index; - if ((line < 0) || (line >= synclinkmp_device_count)) { + if (line >= synclinkmp_device_count) { printk("%s(%d): open with invalid line #%d.\n", __FILE__,__LINE__,line); return -ENODEV; diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index 490b01dd5d60..6c23938d2711 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -725,9 +725,6 @@ static int gs_open(struct tty_struct *tty, struct file *file) struct gs_port *port; int status; - if (port_num < 0 || port_num >= n_ports) - return -ENXIO; - do { mutex_lock(&ports[port_num].lock); port = ports[port_num].port; diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index 828f88603d6c..6b9d5a0e42f9 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -365,16 +365,12 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) { struct ircomm_tty_cb *self; - unsigned int line; + unsigned int line = tty->index; unsigned long flags; int ret; IRDA_DEBUG(2, "%s()\n", __func__ ); - line = tty->index; - if (line >= IRCOMM_TTY_PORTS) - return -ENODEV; - /* Check if instance already exists */ self = hashbin_lock_find(ircomm_tty, line, NULL); if (!self) { -- cgit v1.2.3 From 86e7e874635ea76fee8608646afcb103414c6e72 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:05 +0100 Subject: XTENSA: iss/console, use setup_timer Use setup_timer instead of explicit assignments. Signed-off-by: Jiri Slaby Cc: Chris Zankel Signed-off-by: Greg Kroah-Hartman --- arch/xtensa/platforms/iss/console.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c index 19a802a13096..01842e4d1904 100644 --- a/arch/xtensa/platforms/iss/console.c +++ b/arch/xtensa/platforms/iss/console.c @@ -69,11 +69,8 @@ static void rs_poll(unsigned long); static int rs_open(struct tty_struct *tty, struct file * filp) { spin_lock(&timer_lock); - if (tty->count == 1) { - init_timer(&serial_timer); - serial_timer.data = (unsigned long) tty; - serial_timer.function = rs_poll; + setup_timer(&serial_timer, rs_poll, (unsigned long)tty); mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE); } spin_unlock(&timer_lock); -- cgit v1.2.3 From c9ddb1d6e29697029118377c1f4f9a4a148d755e Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:06 +0100 Subject: XTENSA: iss/console, fix potential deadlock If the timer ticks while we are holding the spinlock, the system deadlocks. It is due to synchronous del_timer. So to fix that, use spinlocks that properly disable bottom halves. Signed-off-by: Jiri Slaby Cc: Chris Zankel Signed-off-by: Greg Kroah-Hartman --- arch/xtensa/platforms/iss/console.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c index 01842e4d1904..94ab8eca9d77 100644 --- a/arch/xtensa/platforms/iss/console.c +++ b/arch/xtensa/platforms/iss/console.c @@ -91,11 +91,10 @@ static int rs_open(struct tty_struct *tty, struct file * filp) */ static void rs_close(struct tty_struct *tty, struct file * filp) { - spin_lock(&timer_lock); + spin_lock_bh(&timer_lock); if (tty->count == 1) - /* this will cause a deadlock if the timer ticks right now */ del_timer_sync(&serial_timer); - spin_unlock(&timer_lock); + spin_unlock_bh(&timer_lock); } -- cgit v1.2.3 From 885f8b0f8ab497b8520f95ff3c1bb7efb1c331ac Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:07 +0100 Subject: TTY: iss/console, use tty_port Even though the port is not used for anything real there yet, this will change as tty buffers will be in tty_port in the near future. So the port will be needed in all drivers. Signed-off-by: Jiri Slaby Cc: Chris Zankel Signed-off-by: Greg Kroah-Hartman --- arch/xtensa/platforms/iss/console.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c index 94ab8eca9d77..d1a7861b81f7 100644 --- a/arch/xtensa/platforms/iss/console.c +++ b/arch/xtensa/platforms/iss/console.c @@ -37,6 +37,7 @@ #define SERIAL_TIMER_VALUE (20 * HZ) static struct tty_driver *serial_driver; +static struct tty_port serial_port; static struct timer_list serial_timer; static DEFINE_SPINLOCK(timer_lock); @@ -68,6 +69,7 @@ static void rs_poll(unsigned long); static int rs_open(struct tty_struct *tty, struct file * filp) { + tty->port = &serial_port; spin_lock(&timer_lock); if (tty->count == 1) { setup_timer(&serial_timer, rs_poll, (unsigned long)tty); @@ -202,6 +204,8 @@ static const struct tty_operations serial_ops = { int __init rs_init(void) { + tty_port_init(&serial_port); + serial_driver = alloc_tty_driver(SERIAL_MAX_NUM_LINES); printk ("%s %s\n", serial_name, serial_version); -- cgit v1.2.3 From 11ba8899f96066600a7adeee28baed7a4a8cb7eb Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:10 +0100 Subject: TTY: remove serialP.h inclusion from some files All of them do not use the ugly interface defined in that header. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- arch/xtensa/platforms/iss/console.c | 1 - drivers/tty/serial/ioc4_serial.c | 1 - drivers/tty/serial/m32r_sio.c | 1 - 3 files changed, 3 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c index d1a7861b81f7..f9726f6afdf1 100644 --- a/arch/xtensa/platforms/iss/console.c +++ b/arch/xtensa/platforms/iss/console.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include diff --git a/drivers/tty/serial/ioc4_serial.c b/drivers/tty/serial/ioc4_serial.c index dfec69a310ab..e16894fb2ca3 100644 --- a/drivers/tty/serial/ioc4_serial.c +++ b/drivers/tty/serial/ioc4_serial.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c index e465dda63edf..a0703624d5e5 100644 --- a/drivers/tty/serial/m32r_sio.c +++ b/drivers/tty/serial/m32r_sio.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From 9c8efecc91c02056340ae19612315f3225e6dbe2 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:12 +0100 Subject: TTY: serialP, remove unused material First, remove unused macro and rs_multiport_struct structure. Nobody uses them at all. Further, the 2 drivers (they are below) which use the rest of structures from serialP.h (async_struct and serial_state) do not use all the members. Remove the members: * which are unused or * which are only initialized and never used for something real. Everybody should avoid the structures with a looong distance. Finally, remove the ALPHA kludge MCR quirks. They are 1:1 copy from 8250.h. No need to redefine them here. The 2 promised users of the structures: arch/ia64/hp/sim/simserial.c drivers/tty/amiserial.c Signed-off-by: Jiri Slaby Cc: Geert Uytterhoeven Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 10 +------- drivers/tty/amiserial.c | 6 ----- include/linux/serialP.h | 59 -------------------------------------------- 3 files changed, 1 insertion(+), 74 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 2a2fe0c56119..9890b58960a7 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -72,7 +72,7 @@ static char *serial_version = "0.6"; */ static struct serial_state rs_table[NR_PORTS]={ /* UART CLK PORT IRQ FLAGS */ - { 0, BASE_BAUD, 0x3F8, 0, STD_COM_FLAGS,0,PORT_16550 } /* ttyS0 */ + { BASE_BAUD, 0x3F8, 0, STD_COM_FLAGS, PORT_16550 } /* ttyS0 */ }; /* @@ -194,11 +194,6 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id) * ------------------------------------------------------------------- */ -static void do_softint(struct work_struct *private_) -{ - printk(KERN_ERR "simserial: do_softint called\n"); -} - static int rs_put_char(struct tty_struct *tty, unsigned char ch) { struct async_struct *info = (struct async_struct *)tty->driver_data; @@ -641,13 +636,10 @@ static int get_async_struct(int line, struct async_struct **ret_info) } init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); - init_waitqueue_head(&info->delta_msr_wait); - info->magic = SERIAL_MAGIC; info->port = sstate->port; info->flags = sstate->flags; info->xmit_fifo_size = sstate->xmit_fifo_size; info->line = line; - INIT_WORK(&info->work, do_softint); info->state = sstate; if (sstate->info) { kfree(info); diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 753286257554..c6d8913dd6f6 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -473,7 +473,6 @@ static irqreturn_t ser_rx_int(int irq, void *dev_id) return IRQ_NONE; receive_chars(info); - info->last_active = jiffies; #ifdef SERIAL_DEBUG_INTR printk("end.\n"); #endif @@ -494,7 +493,6 @@ static irqreturn_t ser_tx_int(int irq, void *dev_id) return IRQ_NONE; transmit_chars(info); - info->last_active = jiffies; #ifdef SERIAL_DEBUG_INTR printk("end.\n"); #endif @@ -828,7 +826,6 @@ static void change_speed(struct async_struct *info, mb(); } - info->LCR = cval; /* Save LCR */ local_irq_restore(flags); } @@ -1743,7 +1740,6 @@ static int get_async_struct(int line, struct async_struct **ret_info) init_waitqueue_head(&info->close_wait); init_waitqueue_head(&info->delta_msr_wait); #endif - info->magic = SERIAL_MAGIC; info->port = sstate->port; info->flags = sstate->flags; info->xmit_fifo_size = sstate->xmit_fifo_size; @@ -1840,7 +1836,6 @@ static inline void line_info(struct seq_file *m, struct serial_state *state) if (!info) { info = &scr_info; /* This is just for serial_{in,out} */ - info->magic = SERIAL_MAGIC; info->flags = state->flags; info->quot = 0; info->tty = NULL; @@ -1987,7 +1982,6 @@ static int __init amiga_serial_probe(struct platform_device *pdev) goto fail_put_tty_driver; state = rs_table; - state->magic = SSTATE_MAGIC; state->port = (int)&custom.serdatr; /* Just to give it a value */ state->line = 0; state->custom_divisor = 0; diff --git a/include/linux/serialP.h b/include/linux/serialP.h index ec27b34bbbd6..c1acdb2c8584 100644 --- a/include/linux/serialP.h +++ b/include/linux/serialP.h @@ -26,32 +26,23 @@ #include struct serial_state { - int magic; int baud_base; unsigned long port; int irq; int flags; - int hub6; int type; int line; - int revision; /* Chip revision (950) */ int xmit_fifo_size; int custom_divisor; int count; - u8 *iomem_base; - u16 iomem_reg_shift; unsigned short close_delay; unsigned short closing_wait; /* time to wait before closing */ struct async_icount icount; - int io_type; struct async_struct *info; - struct pci_dev *dev; }; struct async_struct { - int magic; unsigned long port; - int hub6; int flags; int xmit_fifo_size; struct serial_state *state; @@ -63,21 +54,12 @@ struct async_struct { int x_char; /* xon/xoff character */ int close_delay; unsigned short closing_wait; - unsigned short closing_wait2; /* obsolete */ int IER; /* Interrupt Enable Register */ int MCR; /* Modem control register */ - int LCR; /* Line control register */ - int ACR; /* 16950 Additional Control Reg. */ unsigned long event; - unsigned long last_active; int line; int blocked_open; /* # of blocked opens */ struct circ_buf xmit; - spinlock_t xmit_lock; - u8 *iomem_base; - u16 iomem_reg_shift; - int io_type; - struct work_struct work; struct tasklet_struct tlet; wait_queue_head_t open_wait; wait_queue_head_t close_wait; @@ -86,51 +68,10 @@ struct async_struct { struct async_struct *prev_port; }; -#define CONFIGURED_SERIAL_PORT(info) ((info)->port || ((info)->iomem_base)) - -#define SERIAL_MAGIC 0x5301 -#define SSTATE_MAGIC 0x5302 - /* * Events are used to schedule things to happen at timer-interrupt * time, instead of at rs interrupt time. */ #define RS_EVENT_WRITE_WAKEUP 0 -/* - * Multiport serial configuration structure --- internal structure - */ -struct rs_multiport_struct { - int port1; - unsigned char mask1, match1; - int port2; - unsigned char mask2, match2; - int port3; - unsigned char mask3, match3; - int port4; - unsigned char mask4, match4; - int port_monitor; -}; - -#if defined(__alpha__) && !defined(CONFIG_PCI) -/* - * Digital did something really horribly wrong with the OUT1 and OUT2 - * lines on at least some ALPHA's. The failure mode is that if either - * is cleared, the machine locks up with endless interrupts. - * - * This is still used by arch/mips/au1000/common/serial.c for some weird - * reason (mips != alpha!) - */ -#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1) -#elif defined(CONFIG_SBC8560) -/* - * WindRiver did something similarly broken on their SBC8560 board. The - * UART tristates its IRQ output while OUT2 is clear, but they pulled - * the interrupt line _up_ instead of down, so if we register the IRQ - * while the UART is in that state, we die in an IRQ storm. */ -#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2) -#else -#define ALPHA_KLUDGE_MCR 0 -#endif - #endif /* _LINUX_SERIAL_H */ -- cgit v1.2.3 From c5f0508b992ad081ba378a59b2404966f9f89429 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:13 +0100 Subject: TTY: amiserial, remove tasklet for tty_wakeup tty_wakeup is safe to be called from all contexts. No need to schedule a tasklet for that. Let's call it directly like in other drivers. This allows us to kill another member of async_struct structure. (If we remove the dummy uses in simserial.) Signed-off-by: Jiri Slaby Cc: Geert Uytterhoeven Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 2 -- drivers/tty/amiserial.c | 42 ++---------------------------------------- include/linux/serialP.h | 8 -------- 3 files changed, 2 insertions(+), 50 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 9890b58960a7..0d324e85379e 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -572,7 +572,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp) shutdown(info); rs_flush_buffer(tty); tty_ldisc_flush(tty); - info->event = 0; info->tty = NULL; if (info->blocked_open) { if (info->close_delay) @@ -610,7 +609,6 @@ static void rs_hangup(struct tty_struct *tty) return; shutdown(info); - info->event = 0; state->count = 0; info->flags &= ~ASYNC_NORMAL_ACTIVE; info->tty = NULL; diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index c6d8913dd6f6..d5fac8626988 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -231,17 +231,6 @@ static void rs_start(struct tty_struct *tty) * ----------------------------------------------------------------------- */ -/* - * This routine is used by the interrupt handler to schedule - * processing in the software interrupt portion of the driver. - */ -static void rs_sched_event(struct async_struct *info, - int event) -{ - info->event |= 1 << event; - tasklet_schedule(&info->tlet); -} - static void receive_chars(struct async_struct *info) { int status; @@ -359,7 +348,7 @@ static void transmit_chars(struct async_struct *info) if (CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) < WAKEUP_CHARS) - rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); + tty_wakeup(info->tty); #ifdef SERIAL_DEBUG_INTR printk("THRE..."); @@ -427,7 +416,7 @@ static void check_modem_status(struct async_struct *info) /* set a pending Tx Interrupt, transmitter should restart now */ custom.intreq = IF_SETCLR | IF_TBE; mb(); - rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); + tty_wakeup(info->tty); return; } } else { @@ -506,29 +495,6 @@ static irqreturn_t ser_tx_int(int irq, void *dev_id) * ------------------------------------------------------------------- */ -/* - * This routine is used to handle the "bottom half" processing for the - * serial driver, known also the "software interrupt" processing. - * This processing is done at the kernel interrupt level, after the - * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This - * is where time-consuming activities which can not be done in the - * interrupt driver proper are done; the interrupt driver schedules - * them using rs_sched_event(), and they get done here. - */ - -static void do_softint(unsigned long private_) -{ - struct async_struct *info = (struct async_struct *) private_; - struct tty_struct *tty; - - tty = info->tty; - if (!tty) - return; - - if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) - tty_wakeup(tty); -} - /* * --------------------------------------------------------------- * Low level utility subroutines for the serial driver: routines to @@ -1506,7 +1472,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp) tty_ldisc_flush(tty); tty->closing = 0; - info->event = 0; info->tty = NULL; if (info->blocked_open) { if (info->close_delay) { @@ -1597,7 +1562,6 @@ static void rs_hangup(struct tty_struct *tty) rs_flush_buffer(tty); shutdown(info); - info->event = 0; state->count = 0; info->flags &= ~ASYNC_NORMAL_ACTIVE; info->tty = NULL; @@ -1744,7 +1708,6 @@ static int get_async_struct(int line, struct async_struct **ret_info) info->flags = sstate->flags; info->xmit_fifo_size = sstate->xmit_fifo_size; info->line = line; - tasklet_init(&info->tlet, do_softint, (unsigned long)info); info->state = sstate; if (sstate->info) { kfree(info); @@ -2050,7 +2013,6 @@ static int __exit amiga_serial_remove(struct platform_device *pdev) struct async_struct *info = state->info; /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ - tasklet_kill(&info->tlet); if ((error = tty_unregister_driver(serial_driver))) printk("SERIAL: failed to unregister serial driver (%d)\n", error); diff --git a/include/linux/serialP.h b/include/linux/serialP.h index c1acdb2c8584..beaf39f819d6 100644 --- a/include/linux/serialP.h +++ b/include/linux/serialP.h @@ -56,11 +56,9 @@ struct async_struct { unsigned short closing_wait; int IER; /* Interrupt Enable Register */ int MCR; /* Modem control register */ - unsigned long event; int line; int blocked_open; /* # of blocked opens */ struct circ_buf xmit; - struct tasklet_struct tlet; wait_queue_head_t open_wait; wait_queue_head_t close_wait; wait_queue_head_t delta_msr_wait; @@ -68,10 +66,4 @@ struct async_struct { struct async_struct *prev_port; }; -/* - * Events are used to schedule things to happen at timer-interrupt - * time, instead of at rs interrupt time. - */ -#define RS_EVENT_WRITE_WAKEUP 0 - #endif /* _LINUX_SERIAL_H */ -- cgit v1.2.3 From 0745d19abc492437e601c83281287d10202ee411 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 8 Mar 2012 21:01:16 +0100 Subject: hpsim, fix SAL handling in fw-emu The switch-cases of SAL_FREQ_BASE generate non-relocatable code. The same as for the ifs one level upper. This causes oopses early in boot because the kernel jumps to the hell instead of the offset in sal callback. So use ifs here for SAL_FREQ_BASE decision too. Isn't there any compiler directive or settings to solve that cleanly? Signed-off-by: Jiri Slaby Signed-off-by: Tony Luck Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/boot/fw-emu.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/boot/fw-emu.c b/arch/ia64/hp/sim/boot/fw-emu.c index bf6d9d8c802f..0216e28300fa 100644 --- a/arch/ia64/hp/sim/boot/fw-emu.c +++ b/arch/ia64/hp/sim/boot/fw-emu.c @@ -160,28 +160,19 @@ sal_emulator (long index, unsigned long in1, unsigned long in2, */ status = 0; if (index == SAL_FREQ_BASE) { - switch (in1) { - case SAL_FREQ_BASE_PLATFORM: + if (in1 == SAL_FREQ_BASE_PLATFORM) r9 = 200000000; - break; - - case SAL_FREQ_BASE_INTERVAL_TIMER: + else if (in1 == SAL_FREQ_BASE_INTERVAL_TIMER) { /* * Is this supposed to be the cr.itc frequency * or something platform specific? The SAL * doc ain't exactly clear on this... */ r9 = 700000000; - break; - - case SAL_FREQ_BASE_REALTIME_CLOCK: + } else if (in1 == SAL_FREQ_BASE_REALTIME_CLOCK) r9 = 1; - break; - - default: + else status = -1; - break; - } } else if (index == SAL_SET_VECTORS) { ; } else if (index == SAL_GET_STATE_INFO) { -- cgit v1.2.3 From 035cfe5ac55d399169b7f61f7a111d3d7075190c Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 8 Mar 2012 21:01:17 +0100 Subject: simserial, include some headers And remove declarations which are already in the headers. Signed-off-by: Jiri Slaby Signed-off-by: Tony Luck Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 0d324e85379e..35ae642b2a1a 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -34,9 +34,12 @@ #include #include +#include #include #include +#include "hpsim_ssc.h" + #undef SIMSERIAL_DEBUG /* define this to get some debug information */ #define KEYBOARD_INTR 3 /* must match with simulator! */ @@ -45,11 +48,6 @@ #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED : IRQF_DISABLED) -#define SSC_GETCHAR 21 - -extern long ia64_ssc (long, long, long, long, int); -extern void ia64_ssc_connect_irq (long intr, long irq); - static char *serial_name = "SimSerial driver"; static char *serial_version = "0.6"; -- cgit v1.2.3 From 6efb6b77ff6fd512e9ef45b29f1940cb924cd7a6 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 8 Mar 2012 21:01:18 +0100 Subject: hpsim, initialize chip for assigned irqs Currently, when assign_irq_vector is called and the irq connected in the simulator, the irq is not ready. request_irq will return ENOSYS immediately. It is because the irq chip is unset. Hence set the chip properly to irq_type_hp_sim. And make sure this is done from both users of simulated interrupts. Also we have to set handler here, otherwise we end up in handle_bad_int resulting in spam in logs and no irqs handled. We use handle_simple_irq as these are SW interrupts that need no ACK or anything. Signed-off-by: Jiri Slaby Signed-off-by: Tony Luck Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/hpsim_irq.c | 36 ++++++++++++++++++++++++++++++------ arch/ia64/hp/sim/hpsim_setup.c | 6 ------ arch/ia64/hp/sim/simeth.c | 19 +++---------------- arch/ia64/hp/sim/simserial.c | 3 +-- arch/ia64/include/asm/hpsim.h | 2 +- 5 files changed, 35 insertions(+), 31 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/hpsim_irq.c b/arch/ia64/hp/sim/hpsim_irq.c index 4bd9a63260ee..0aa70ebda49d 100644 --- a/arch/ia64/hp/sim/hpsim_irq.c +++ b/arch/ia64/hp/sim/hpsim_irq.c @@ -10,6 +10,8 @@ #include #include +#include "hpsim_ssc.h" + static unsigned int hpsim_irq_startup(struct irq_data *data) { @@ -37,15 +39,37 @@ static struct irq_chip irq_type_hp_sim = { .irq_set_affinity = hpsim_set_affinity_noop, }; +static void hpsim_irq_set_chip(int irq) +{ + struct irq_chip *chip = irq_get_chip(irq); + + if (chip == &no_irq_chip) + irq_set_chip(irq, &irq_type_hp_sim); +} + +static void hpsim_connect_irq(int intr, int irq) +{ + ia64_ssc(intr, irq, 0, 0, SSC_CONNECT_INTERRUPT); +} + +int hpsim_get_irq(int intr) +{ + int irq = assign_irq_vector(AUTO_ASSIGN); + + if (irq >= 0) { + hpsim_irq_set_chip(irq); + irq_set_handler(irq, handle_simple_irq); + hpsim_connect_irq(intr, irq); + } + + return irq; +} + void __init hpsim_irq_init (void) { int i; - for_each_active_irq(i) { - struct irq_chip *chip = irq_get_chip(i); - - if (chip == &no_irq_chip) - irq_set_chip(i, &irq_type_hp_sim); - } + for_each_active_irq(i) + hpsim_irq_set_chip(i); } diff --git a/arch/ia64/hp/sim/hpsim_setup.c b/arch/ia64/hp/sim/hpsim_setup.c index f629e903ebc7..664a5402a695 100644 --- a/arch/ia64/hp/sim/hpsim_setup.c +++ b/arch/ia64/hp/sim/hpsim_setup.c @@ -25,12 +25,6 @@ #include "hpsim_ssc.h" -void -ia64_ssc_connect_irq (long intr, long irq) -{ - ia64_ssc(intr, irq, 0, 0, SSC_CONNECT_INTERRUPT); -} - void ia64_ctl_trace (long on) { diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c index 47afcc61f6e5..e343357f80b9 100644 --- a/arch/ia64/hp/sim/simeth.c +++ b/arch/ia64/hp/sim/simeth.c @@ -128,17 +128,6 @@ netdev_probe(char *name, unsigned char *ether) } -static inline int -netdev_connect(int irq) -{ - /* XXX Fix me - * this does not support multiple cards - * also no return value - */ - ia64_ssc_connect_irq(NETWORK_INTR, irq); - return 0; -} - static inline int netdev_attach(int fd, int irq, unsigned int ipaddr) { @@ -226,15 +215,13 @@ simeth_probe1(void) return err; } - if ((rc = assign_irq_vector(AUTO_ASSIGN)) < 0) - panic("%s: out of interrupt vectors!\n", __func__); - dev->irq = rc; - /* * attach the interrupt in the simulator, this does enable interrupts * until a netdev_attach() is called */ - netdev_connect(dev->irq); + if ((rc = hpsim_get_irq(NETWORK_INTR)) < 0) + panic("%s: out of interrupt vectors!\n", __func__); + dev->irq = rc; printk(KERN_INFO "%s: hosteth=%s simfd=%d, HwAddr", dev->name, simeth_device, local->simfd); diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 35ae642b2a1a..3a079decde51 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -933,11 +933,10 @@ simrs_init (void) if (state->type == PORT_UNKNOWN) continue; if (!state->irq) { - if ((rc = assign_irq_vector(AUTO_ASSIGN)) < 0) + if ((rc = hpsim_get_irq(KEYBOARD_INTR)) < 0) panic("%s: out of interrupt vectors!\n", __func__); state->irq = rc; - ia64_ssc_connect_irq(KEYBOARD_INTR, state->irq); } printk(KERN_INFO "ttyS%d at 0x%04lx (irq = %d) is a %s\n", diff --git a/arch/ia64/include/asm/hpsim.h b/arch/ia64/include/asm/hpsim.h index 892ab198a9da..0fe50225daa4 100644 --- a/arch/ia64/include/asm/hpsim.h +++ b/arch/ia64/include/asm/hpsim.h @@ -10,7 +10,7 @@ int simcons_register(void); struct tty_driver; extern struct tty_driver *hp_simserial_driver; -void ia64_ssc_connect_irq(long intr, long irq); +extern int hpsim_get_irq(int intr); void ia64_ctl_trace(long on); #endif -- cgit v1.2.3 From 9e12dd5fce1c676e709625bd2f55dc83664c3c93 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 8 Mar 2012 21:01:19 +0100 Subject: simserial, bail out when request_irq fails Without this, the code succeeds when the port is opened by root and we get unwanted interrupts storm on the first key stroke. Instead of that, tell the user we failed and that we won't continue. I suppose, the code was copied from the serial layer where we may want to change the irq number, so we must allow open even of the failing port. This is not the case for this driver at all. Signed-off-by: Jiri Slaby Signed-off-by: Tony Luck Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 3a079decde51..8f68972b015f 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -692,15 +692,8 @@ startup(struct async_struct *info) handler = rs_interrupt_single; retval = request_irq(state->irq, handler, IRQ_T(info), "simserial", NULL); - if (retval) { - if (capable(CAP_SYS_ADMIN)) { - if (info->tty) - set_bit(TTY_IO_ERROR, - &info->tty->flags); - retval = 0; - } + if (retval) goto errout; - } } /* -- cgit v1.2.3 From 979b6d89766ed573bca6a6e902193c4cad502909 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:15 +0100 Subject: TTY: simserial, use only one copy of async flags The same as for amiserial. Use only one instance of the flags. Also remove them from async_struct now. Nobody else uses them. Signed-off-by: Jiri Slaby Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 48 +++++++++++++++++++++----------------------- include/linux/serialP.h | 1 - 2 files changed, 23 insertions(+), 26 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 8f68972b015f..a08a53f033b4 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -46,7 +46,7 @@ #define NR_PORTS 1 /* only one port for now */ -#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED : IRQF_DISABLED) +#define IRQ_T(state) ((state->flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED : IRQF_DISABLED) static char *serial_name = "SimSerial driver"; static char *serial_version = "0.6"; @@ -455,12 +455,11 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) static void shutdown(struct async_struct * info) { unsigned long flags; - struct serial_state *state; + struct serial_state *state = info->state; int retval; - if (!(info->flags & ASYNC_INITIALIZED)) return; - - state = info->state; + if (!(state->flags & ASYNC_INITIALIZED)) + return; #ifdef SIMSERIAL_DEBUG printk("Shutting down serial port %d (irq %d)....", info->line, @@ -487,7 +486,8 @@ static void shutdown(struct async_struct * info) if (IRQ_ports[state->irq]) { free_irq(state->irq, NULL); retval = request_irq(state->irq, rs_interrupt_single, - IRQ_T(info), "serial", NULL); + IRQ_T(state), "serial", + NULL); if (retval) printk(KERN_ERR "serial shutdown: request_irq: error %d" @@ -503,7 +503,7 @@ static void shutdown(struct async_struct * info) if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); - info->flags &= ~ASYNC_INITIALIZED; + state->flags &= ~ASYNC_INITIALIZED; } local_irq_restore(flags); } @@ -560,7 +560,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) local_irq_restore(flags); return; } - info->flags |= ASYNC_CLOSING; + state->flags |= ASYNC_CLOSING; local_irq_restore(flags); /* @@ -576,7 +576,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) schedule_timeout_interruptible(info->close_delay); wake_up_interruptible(&info->open_wait); } - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); + state->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); wake_up_interruptible(&info->close_wait); } @@ -600,15 +600,13 @@ static void rs_hangup(struct tty_struct *tty) printk("rs_hangup: called\n"); #endif - state = info->state; - rs_flush_buffer(tty); - if (info->flags & ASYNC_CLOSING) + if (state->flags & ASYNC_CLOSING) return; shutdown(info); state->count = 0; - info->flags &= ~ASYNC_NORMAL_ACTIVE; + state->flags &= ~ASYNC_NORMAL_ACTIVE; info->tty = NULL; wake_up_interruptible(&info->open_wait); } @@ -633,7 +631,6 @@ static int get_async_struct(int line, struct async_struct **ret_info) init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); info->port = sstate->port; - info->flags = sstate->flags; info->xmit_fifo_size = sstate->xmit_fifo_size; info->line = line; info->state = sstate; @@ -661,7 +658,7 @@ startup(struct async_struct *info) local_irq_save(flags); - if (info->flags & ASYNC_INITIALIZED) { + if (state->flags & ASYNC_INITIALIZED) { free_page(page); goto errout; } @@ -691,7 +688,8 @@ startup(struct async_struct *info) } else handler = rs_interrupt_single; - retval = request_irq(state->irq, handler, IRQ_T(info), "simserial", NULL); + retval = request_irq(state->irq, handler, IRQ_T(state), + "simserial", NULL); if (retval) goto errout; } @@ -721,17 +719,17 @@ startup(struct async_struct *info) * Set up the tty->alt_speed kludge */ if (info->tty) { - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) info->tty->alt_speed = 57600; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) info->tty->alt_speed = 115200; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) info->tty->alt_speed = 230400; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) info->tty->alt_speed = 460800; } - info->flags |= ASYNC_INITIALIZED; + state->flags |= ASYNC_INITIALIZED; local_irq_restore(flags); return 0; @@ -762,7 +760,7 @@ static int rs_open(struct tty_struct *tty, struct file * filp) #ifdef SIMSERIAL_DEBUG printk("rs_open %s, count = %d\n", tty->name, info->state->count); #endif - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + info->tty->low_latency = (info->state->flags & ASYNC_LOW_LATENCY) ? 1 : 0; if (!tmp_buf) { page = get_zeroed_page(GFP_KERNEL); @@ -778,11 +776,11 @@ static int rs_open(struct tty_struct *tty, struct file * filp) * If the port is the middle of closing, bail out now */ if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) + (info->state->flags & ASYNC_CLOSING)) { + if (info->state->flags & ASYNC_CLOSING) interruptible_sleep_on(&info->close_wait); #ifdef SERIAL_DO_RESTART - return ((info->flags & ASYNC_HUP_NOTIFY) ? + return ((info->state->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); #else return -EAGAIN; diff --git a/include/linux/serialP.h b/include/linux/serialP.h index beaf39f819d6..6741f57cc2ae 100644 --- a/include/linux/serialP.h +++ b/include/linux/serialP.h @@ -43,7 +43,6 @@ struct serial_state { struct async_struct { unsigned long port; - int flags; int xmit_fifo_size; struct serial_state *state; struct tty_struct *tty; -- cgit v1.2.3 From d852256389f1bcf506710ea5de77debde40013b9 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:16 +0100 Subject: TTY: simserial/amiserial, use one instance of other members This means: * close_delay * closing_wait * line * port * xmit_fifo_size This actually fixes a bug in amiserial. It initializes one and uses the other of the close delays. Yes, duplicating structure members is evil. Signed-off-by: Jiri Slaby Cc: Geert Uytterhoeven Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 9 +++------ drivers/tty/amiserial.c | 19 ++++++++----------- include/linux/serialP.h | 5 ----- 3 files changed, 11 insertions(+), 22 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index a08a53f033b4..d32b759b23f1 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -553,7 +553,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) } if (--state->count < 0) { printk(KERN_ERR "rs_close: bad serial port count for ttys%d: %d\n", - info->line, state->count); + state->line, state->count); state->count = 0; } if (state->count) { @@ -572,8 +572,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp) tty_ldisc_flush(tty); info->tty = NULL; if (info->blocked_open) { - if (info->close_delay) - schedule_timeout_interruptible(info->close_delay); + if (state->close_delay) + schedule_timeout_interruptible(state->close_delay); wake_up_interruptible(&info->open_wait); } state->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); @@ -630,9 +630,6 @@ static int get_async_struct(int line, struct async_struct **ret_info) } init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); - info->port = sstate->port; - info->xmit_fifo_size = sstate->xmit_fifo_size; - info->line = line; info->state = sstate; if (sstate->info) { kfree(info); diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 8556ca022dbc..5540216e64fd 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -723,7 +723,7 @@ static void change_speed(struct async_struct *info, if (!quot) quot = baud_base / 9600; info->quot = quot; - info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base); + info->timeout = ((info->state->xmit_fifo_size*HZ*bits*quot) / baud_base); info->timeout += HZ/50; /* Add .02 seconds of slop */ /* CTS flow control flag and modem status interrupts */ @@ -1425,7 +1425,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) } if (--state->count < 0) { printk("rs_close: bad serial port count for ttys%d: %d\n", - info->line, state->count); + state->line, state->count); state->count = 0; } if (state->count) { @@ -1439,8 +1439,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp) * the line discipline to only process XON/XOFF characters. */ tty->closing = 1; - if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, info->closing_wait); + if (state->closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, state->closing_wait); /* * At this point we stop accepting input. To do this, we * disable the receive line status interrupts, and tell the @@ -1470,8 +1470,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp) tty->closing = 0; info->tty = NULL; if (info->blocked_open) { - if (info->close_delay) { - msleep_interruptible(jiffies_to_msecs(info->close_delay)); + if (state->close_delay) { + msleep_interruptible(jiffies_to_msecs(state->close_delay)); } wake_up_interruptible(&info->open_wait); } @@ -1492,7 +1492,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) return; - if (info->xmit_fifo_size == 0) + if (info->state->xmit_fifo_size == 0) return; /* Just in case.... */ orig_jiffies = jiffies; @@ -1505,7 +1505,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) * Note: we have to use pretty tight timings here to satisfy * the NIST-PCTS. */ - char_time = (info->timeout - HZ/50) / info->xmit_fifo_size; + char_time = (info->timeout - HZ/50) / info->state->xmit_fifo_size; char_time = char_time / 5; if (char_time == 0) char_time = 1; @@ -1700,9 +1700,6 @@ static int get_async_struct(int line, struct async_struct **ret_info) init_waitqueue_head(&info->close_wait); init_waitqueue_head(&info->delta_msr_wait); #endif - info->port = sstate->port; - info->xmit_fifo_size = sstate->xmit_fifo_size; - info->line = line; info->state = sstate; if (sstate->info) { kfree(info); diff --git a/include/linux/serialP.h b/include/linux/serialP.h index 6741f57cc2ae..6ce488c46589 100644 --- a/include/linux/serialP.h +++ b/include/linux/serialP.h @@ -42,8 +42,6 @@ struct serial_state { }; struct async_struct { - unsigned long port; - int xmit_fifo_size; struct serial_state *state; struct tty_struct *tty; int read_status_mask; @@ -51,11 +49,8 @@ struct async_struct { int timeout; int quot; int x_char; /* xon/xoff character */ - int close_delay; - unsigned short closing_wait; int IER; /* Interrupt Enable Register */ int MCR; /* Modem control register */ - int line; int blocked_open; /* # of blocked opens */ struct circ_buf xmit; wait_queue_head_t open_wait; -- cgit v1.2.3 From 964105b501071e8a0e9feb1d0e4b3e46508bc38e Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:17 +0100 Subject: TTY: simserial, remove support of shared interrupts It never worked there. The ISR was never written for that kind of stuff. So remove all that crap with a hash of linked lists and pass the pointer directly to the ISR. BTW this answers the question there: * I don't know exactly why they don't use the dev_id opaque data * pointer instead of this extra lookup table -> Because they thought they will support more devices bound to a single interrupt w/o IRQF_SHARED. They would need exactly the hash there. What I don't understand is rebinding of the interrupt in the shutdown path. They perhaps meant to do just synchronize_irq? In any case, this is all gone and free_irq there properly. By removing the hash we save some bits (exactly NR_IRQS * 8 bytes of .bss and over a kilo of .text): before: text data bss dec hex filename 19600 320 8227 28147 6df3 ../a/ia64/arch/ia64/hp/sim/simserial.o after: text data bss dec hex filename 18568 320 28 18916 49e4 ../a/ia64/arch/ia64/hp/sim/simserial.o Note that a shared interrupt could not work too. request_irq requires data parameter to be non-NULL. So the whole IRQ_T exercise was pointless. Finally, this helps us remove another two members of async_struct :). Signed-off-by: Jiri Slaby Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 64 +++++--------------------------------------- include/linux/serialP.h | 2 -- 2 files changed, 7 insertions(+), 59 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index d32b759b23f1..c35552df035e 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -92,8 +92,6 @@ static struct serial_uart_config uart_config[] = { struct tty_driver *hp_simserial_driver; -static struct async_struct *IRQ_ports[NR_IRQS]; - static struct console *console; static unsigned char *tmp_buf; @@ -167,14 +165,9 @@ static void receive_chars(struct tty_struct *tty) */ static irqreturn_t rs_interrupt_single(int irq, void *dev_id) { - struct async_struct * info; + struct async_struct *info = dev_id; - /* - * I don't know exactly why they don't use the dev_id opaque data - * pointer instead of this extra lookup table - */ - info = IRQ_ports[irq]; - if (!info || !info->tty) { + if (!info->tty) { printk(KERN_INFO "simrs_interrupt_single: info|tty=0 info=%p problem\n", info); return IRQ_NONE; } @@ -456,7 +449,6 @@ static void shutdown(struct async_struct * info) { unsigned long flags; struct serial_state *state = info->state; - int retval; if (!(state->flags & ASYNC_INITIALIZED)) return; @@ -468,33 +460,8 @@ static void shutdown(struct async_struct * info) local_irq_save(flags); { - /* - * First unlink the serial port from the IRQ chain... - */ - if (info->next_port) - info->next_port->prev_port = info->prev_port; - if (info->prev_port) - info->prev_port->next_port = info->next_port; - else - IRQ_ports[state->irq] = info->next_port; - - /* - * Free the IRQ, if necessary - */ - if (state->irq && (!IRQ_ports[state->irq] || - !IRQ_ports[state->irq]->next_port)) { - if (IRQ_ports[state->irq]) { - free_irq(state->irq, NULL); - retval = request_irq(state->irq, rs_interrupt_single, - IRQ_T(state), "serial", - NULL); - - if (retval) - printk(KERN_ERR "serial shutdown: request_irq: error %d" - " Couldn't reacquire IRQ.\n", retval); - } else - free_irq(state->irq, NULL); - } + if (state->irq) + free_irq(state->irq, info); if (info->xmit.buf) { free_page((unsigned long) info->xmit.buf); @@ -645,7 +612,6 @@ startup(struct async_struct *info) { unsigned long flags; int retval=0; - irq_handler_t handler; struct serial_state *state= info->state; unsigned long page; @@ -677,29 +643,13 @@ startup(struct async_struct *info) /* * Allocate the IRQ if necessary */ - if (state->irq && (!IRQ_ports[state->irq] || - !IRQ_ports[state->irq]->next_port)) { - if (IRQ_ports[state->irq]) { - retval = -EBUSY; - goto errout; - } else - handler = rs_interrupt_single; - - retval = request_irq(state->irq, handler, IRQ_T(state), - "simserial", NULL); + if (state->irq) { + retval = request_irq(state->irq, rs_interrupt_single, + IRQ_T(state), "simserial", info); if (retval) goto errout; } - /* - * Insert serial port into IRQ chain. - */ - info->prev_port = NULL; - info->next_port = IRQ_ports[state->irq]; - if (info->next_port) - info->next_port->prev_port = info; - IRQ_ports[state->irq] = info; - if (info->tty) clear_bit(TTY_IO_ERROR, &info->tty->flags); info->xmit.head = info->xmit.tail = 0; diff --git a/include/linux/serialP.h b/include/linux/serialP.h index 6ce488c46589..b8543f902453 100644 --- a/include/linux/serialP.h +++ b/include/linux/serialP.h @@ -56,8 +56,6 @@ struct async_struct { wait_queue_head_t open_wait; wait_queue_head_t close_wait; wait_queue_head_t delta_msr_wait; - struct async_struct *next_port; /* For the linked list */ - struct async_struct *prev_port; }; #endif /* _LINUX_SERIAL_H */ -- cgit v1.2.3 From 2f8c521a1d41faf96f729c76991eb4ad70294513 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:18 +0100 Subject: TTY: simserial, remove IRQ_T We do not set ASYNC_SHARE_IRQ anywhere. And since IRQF_DISABLED is a noop, pass zero to request_irq directly instead of this ugly macro. Signed-off-by: Jiri Slaby Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index c35552df035e..8b5a1342e119 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -46,8 +46,6 @@ #define NR_PORTS 1 /* only one port for now */ -#define IRQ_T(state) ((state->flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED : IRQF_DISABLED) - static char *serial_name = "SimSerial driver"; static char *serial_version = "0.6"; @@ -644,8 +642,8 @@ startup(struct async_struct *info) * Allocate the IRQ if necessary */ if (state->irq) { - retval = request_irq(state->irq, rs_interrupt_single, - IRQ_T(state), "simserial", info); + retval = request_irq(state->irq, rs_interrupt_single, 0, + "simserial", info); if (retval) goto errout; } -- cgit v1.2.3 From 916b765675b7044bd5895b7430a2aa2c63ea4545 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:20 +0100 Subject: TTY: serialP, merge serial_state and async_struct This is the final step to get rid of the one of the structures. A further cleanup will follow. And I struct serial_state deserves cease to exist after a switch to tty_port too. While changing the lines, it removes also pointless tty->driver_data casts. Signed-off-by: Jiri Slaby Cc: Geert Uytterhoeven Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 160 +++++++++-------------- drivers/tty/amiserial.c | 301 +++++++++++++++++-------------------------- include/linux/serialP.h | 14 +- 3 files changed, 191 insertions(+), 284 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 8b5a1342e119..7b6e60e9167b 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -163,7 +163,7 @@ static void receive_chars(struct tty_struct *tty) */ static irqreturn_t rs_interrupt_single(int irq, void *dev_id) { - struct async_struct *info = dev_id; + struct serial_state *info = dev_id; if (!info->tty) { printk(KERN_INFO "simrs_interrupt_single: info|tty=0 info=%p problem\n", info); @@ -185,7 +185,7 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id) static int rs_put_char(struct tty_struct *tty, unsigned char ch) { - struct async_struct *info = (struct async_struct *)tty->driver_data; + struct serial_state *info = tty->driver_data; unsigned long flags; if (!tty || !info->xmit.buf) @@ -202,12 +202,11 @@ static int rs_put_char(struct tty_struct *tty, unsigned char ch) return 1; } -static void transmit_chars(struct async_struct *info, int *intr_done) +static void transmit_chars(struct serial_state *info, int *intr_done) { int count; unsigned long flags; - local_irq_save(flags); if (info->x_char) { @@ -215,7 +214,7 @@ static void transmit_chars(struct async_struct *info, int *intr_done) console->write(console, &c, 1); - info->state->icount.tx++; + info->icount.tx++; info->x_char = 0; goto out; @@ -256,7 +255,7 @@ out: static void rs_flush_chars(struct tty_struct *tty) { - struct async_struct *info = (struct async_struct *)tty->driver_data; + struct serial_state *info = tty->driver_data; if (info->xmit.head == info->xmit.tail || tty->stopped || tty->hw_stopped || !info->xmit.buf) @@ -269,8 +268,8 @@ static void rs_flush_chars(struct tty_struct *tty) static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) { + struct serial_state *info = tty->driver_data; int c, ret = 0; - struct async_struct *info = (struct async_struct *)tty->driver_data; unsigned long flags; if (!tty || !info->xmit.buf || !tmp_buf) return 0; @@ -303,21 +302,21 @@ static int rs_write(struct tty_struct * tty, static int rs_write_room(struct tty_struct *tty) { - struct async_struct *info = (struct async_struct *)tty->driver_data; + struct serial_state *info = tty->driver_data; return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); } static int rs_chars_in_buffer(struct tty_struct *tty) { - struct async_struct *info = (struct async_struct *)tty->driver_data; + struct serial_state *info = tty->driver_data; return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); } static void rs_flush_buffer(struct tty_struct *tty) { - struct async_struct *info = (struct async_struct *)tty->driver_data; + struct serial_state *info = tty->driver_data; unsigned long flags; local_irq_save(flags); @@ -333,7 +332,7 @@ static void rs_flush_buffer(struct tty_struct *tty) */ static void rs_send_xchar(struct tty_struct *tty, char ch) { - struct async_struct *info = (struct async_struct *)tty->driver_data; + struct serial_state *info = tty->driver_data; info->x_char = ch; if (ch) { @@ -362,7 +361,7 @@ static void rs_throttle(struct tty_struct * tty) static void rs_unthrottle(struct tty_struct * tty) { - struct async_struct *info = (struct async_struct *)tty->driver_data; + struct serial_state *info = tty->driver_data; if (I_IXOFF(tty)) { if (info->x_char) @@ -443,23 +442,22 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) * This routine will shutdown a serial port; interrupts are disabled, and * DTR is dropped if the hangup on close termio flag is on. */ -static void shutdown(struct async_struct * info) +static void shutdown(struct serial_state *info) { unsigned long flags; - struct serial_state *state = info->state; - if (!(state->flags & ASYNC_INITIALIZED)) + if (!(info->flags & ASYNC_INITIALIZED)) return; #ifdef SIMSERIAL_DEBUG - printk("Shutting down serial port %d (irq %d)....", info->line, - state->irq); + printk("Shutting down serial port %d (irq %d)...\n", info->line, + info->irq); #endif local_irq_save(flags); { - if (state->irq) - free_irq(state->irq, info); + if (info->irq) + free_irq(info->irq, info); if (info->xmit.buf) { free_page((unsigned long) info->xmit.buf); @@ -468,7 +466,7 @@ static void shutdown(struct async_struct * info) if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); - state->flags &= ~ASYNC_INITIALIZED; + info->flags &= ~ASYNC_INITIALIZED; } local_irq_restore(flags); } @@ -485,13 +483,11 @@ static void shutdown(struct async_struct * info) */ static void rs_close(struct tty_struct *tty, struct file * filp) { - struct async_struct * info = (struct async_struct *)tty->driver_data; - struct serial_state *state; + struct serial_state *info = tty->driver_data; unsigned long flags; - if (!info ) return; - - state = info->state; + if (!info) + return; local_irq_save(flags); if (tty_hung_up_p(filp)) { @@ -502,30 +498,30 @@ static void rs_close(struct tty_struct *tty, struct file * filp) return; } #ifdef SIMSERIAL_DEBUG - printk("rs_close ttys%d, count = %d\n", info->line, state->count); + printk("rs_close ttys%d, count = %d\n", info->line, info->count); #endif - if ((tty->count == 1) && (state->count != 1)) { + if ((tty->count == 1) && (info->count != 1)) { /* * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. state->count should always + * structure will be freed. info->count should always * be one in these conditions. If it's greater than * one, we've got real problems, since it means the * serial port won't be shutdown. */ printk(KERN_ERR "rs_close: bad serial port count; tty->count is 1, " - "state->count is %d\n", state->count); - state->count = 1; + "info->count is %d\n", info->count); + info->count = 1; } - if (--state->count < 0) { + if (--info->count < 0) { printk(KERN_ERR "rs_close: bad serial port count for ttys%d: %d\n", - state->line, state->count); - state->count = 0; + info->line, info->count); + info->count = 0; } - if (state->count) { + if (info->count) { local_irq_restore(flags); return; } - state->flags |= ASYNC_CLOSING; + info->flags |= ASYNC_CLOSING; local_irq_restore(flags); /* @@ -537,11 +533,11 @@ static void rs_close(struct tty_struct *tty, struct file * filp) tty_ldisc_flush(tty); info->tty = NULL; if (info->blocked_open) { - if (state->close_delay) - schedule_timeout_interruptible(state->close_delay); + if (info->close_delay) + schedule_timeout_interruptible(info->close_delay); wake_up_interruptible(&info->open_wait); } - state->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); wake_up_interruptible(&info->close_wait); } @@ -558,59 +554,28 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) */ static void rs_hangup(struct tty_struct *tty) { - struct async_struct * info = (struct async_struct *)tty->driver_data; - struct serial_state *state = info->state; + struct serial_state *info = tty->driver_data; #ifdef SIMSERIAL_DEBUG printk("rs_hangup: called\n"); #endif rs_flush_buffer(tty); - if (state->flags & ASYNC_CLOSING) + if (info->flags & ASYNC_CLOSING) return; shutdown(info); - state->count = 0; - state->flags &= ~ASYNC_NORMAL_ACTIVE; + info->count = 0; + info->flags &= ~ASYNC_NORMAL_ACTIVE; info->tty = NULL; wake_up_interruptible(&info->open_wait); } -static int get_async_struct(int line, struct async_struct **ret_info) -{ - struct async_struct *info; - struct serial_state *sstate; - - sstate = rs_table + line; - sstate->count++; - if (sstate->info) { - *ret_info = sstate->info; - return 0; - } - info = kzalloc(sizeof(struct async_struct), GFP_KERNEL); - if (!info) { - sstate->count--; - return -ENOMEM; - } - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - info->state = sstate; - if (sstate->info) { - kfree(info); - *ret_info = sstate->info; - return 0; - } - *ret_info = sstate->info = info; - return 0; -} - -static int -startup(struct async_struct *info) +static int startup(struct serial_state *state) { unsigned long flags; int retval=0; - struct serial_state *state= info->state; unsigned long page; page = get_zeroed_page(GFP_KERNEL); @@ -625,17 +590,18 @@ startup(struct async_struct *info) } if (!state->port || !state->type) { - if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); + if (state->tty) + set_bit(TTY_IO_ERROR, &state->tty->flags); free_page(page); goto errout; } - if (info->xmit.buf) + if (state->xmit.buf) free_page(page); else - info->xmit.buf = (unsigned char *) page; + state->xmit.buf = (unsigned char *) page; #ifdef SIMSERIAL_DEBUG - printk("startup: ttys%d (irq %d)...", info->line, state->irq); + printk("startup: ttys%d (irq %d)...", state->line, state->irq); #endif /* @@ -643,14 +609,15 @@ startup(struct async_struct *info) */ if (state->irq) { retval = request_irq(state->irq, rs_interrupt_single, 0, - "simserial", info); + "simserial", state); if (retval) goto errout; } - if (info->tty) clear_bit(TTY_IO_ERROR, &info->tty->flags); + if (state->tty) + clear_bit(TTY_IO_ERROR, &state->tty->flags); - info->xmit.head = info->xmit.tail = 0; + state->xmit.head = state->xmit.tail = 0; #if 0 /* @@ -663,15 +630,15 @@ startup(struct async_struct *info) /* * Set up the tty->alt_speed kludge */ - if (info->tty) { + if (state->tty) { if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; + state->tty->alt_speed = 57600; if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->tty->alt_speed = 115200; + state->tty->alt_speed = 115200; if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->tty->alt_speed = 230400; + state->tty->alt_speed = 230400; if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; + state->tty->alt_speed = 460800; } state->flags |= ASYNC_INITIALIZED; @@ -692,20 +659,18 @@ errout: */ static int rs_open(struct tty_struct *tty, struct file * filp) { - struct async_struct *info; + struct serial_state *info = rs_table + tty->index; int retval; unsigned long page; - retval = get_async_struct(tty->index, &info); - if (retval) - return retval; - tty->driver_data = info; + info->count++; info->tty = tty; + tty->driver_data = info; #ifdef SIMSERIAL_DEBUG - printk("rs_open %s, count = %d\n", tty->name, info->state->count); + printk("rs_open %s, count = %d\n", tty->name, info->count); #endif - info->tty->low_latency = (info->state->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; if (!tmp_buf) { page = get_zeroed_page(GFP_KERNEL); @@ -720,12 +685,11 @@ static int rs_open(struct tty_struct *tty, struct file * filp) /* * If the port is the middle of closing, bail out now */ - if (tty_hung_up_p(filp) || - (info->state->flags & ASYNC_CLOSING)) { - if (info->state->flags & ASYNC_CLOSING) + if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) interruptible_sleep_on(&info->close_wait); #ifdef SERIAL_DO_RESTART - return ((info->state->flags & ASYNC_HUP_NOTIFY) ? + return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); #else return -EAGAIN; @@ -865,6 +829,8 @@ simrs_init (void) * Let's have a little bit of fun ! */ for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { + init_waitqueue_head(&state->open_wait); + init_waitqueue_head(&state->close_wait); if (state->type == PORT_UNKNOWN) continue; diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 7607c6ebd39a..410e8e7e6bfe 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -45,7 +45,7 @@ #if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT) #define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \ - tty->name, (info->state->flags), serial_driver->refcount,info->count,tty->count,s) + tty->name, (info->flags), serial_driver->refcount,info->count,tty->count,s) #else #define DBG_CNT(s) #endif @@ -102,7 +102,7 @@ static struct tty_driver *serial_driver; static unsigned char current_ctl_bits; -static void change_speed(struct async_struct *info, struct ktermios *old); +static void change_speed(struct serial_state *info, struct ktermios *old); static void rs_wait_until_sent(struct tty_struct *tty, int timeout); @@ -115,7 +115,7 @@ static struct serial_state rs_table[1]; #define serial_isroot() (capable(CAP_SYS_ADMIN)) -static inline int serial_paranoia_check(struct async_struct *info, +static inline int serial_paranoia_check(struct serial_state *info, char *name, const char *routine) { #ifdef SERIAL_PARANOIA_CHECK @@ -168,7 +168,7 @@ static __inline__ void rtsdtr_ctrl(int bits) */ static void rs_stop(struct tty_struct *tty) { - struct async_struct *info = tty->driver_data; + struct serial_state *info = tty->driver_data; unsigned long flags; if (serial_paranoia_check(info, tty->name, "rs_stop")) @@ -188,7 +188,7 @@ static void rs_stop(struct tty_struct *tty) static void rs_start(struct tty_struct *tty) { - struct async_struct *info = tty->driver_data; + struct serial_state *info = tty->driver_data; unsigned long flags; if (serial_paranoia_check(info, tty->name, "rs_start")) @@ -229,7 +229,7 @@ static void rs_start(struct tty_struct *tty) * ----------------------------------------------------------------------- */ -static void receive_chars(struct async_struct *info) +static void receive_chars(struct serial_state *info) { int status; int serdatr; @@ -238,7 +238,7 @@ static void receive_chars(struct async_struct *info) struct async_icount *icount; int oe = 0; - icount = &info->state->icount; + icount = &info->icount; status = UART_LSR_DR; /* We obviously have a character! */ serdatr = custom.serdatr; @@ -295,7 +295,7 @@ static void receive_chars(struct async_struct *info) printk("handling break...."); #endif flag = TTY_BREAK; - if (info->state->flags & ASYNC_SAK) + if (info->flags & ASYNC_SAK) do_SAK(tty); } else if (status & UART_LSR_PE) flag = TTY_PARITY; @@ -318,14 +318,14 @@ out: return; } -static void transmit_chars(struct async_struct *info) +static void transmit_chars(struct serial_state *info) { custom.intreq = IF_TBE; mb(); if (info->x_char) { custom.serdat = info->x_char | 0x100; mb(); - info->state->icount.tx++; + info->icount.tx++; info->x_char = 0; return; } @@ -341,7 +341,7 @@ static void transmit_chars(struct async_struct *info) custom.serdat = info->xmit.buf[info->xmit.tail++] | 0x100; mb(); info->xmit.tail = info->xmit.tail & (SERIAL_XMIT_SIZE-1); - info->state->icount.tx++; + info->icount.tx++; if (CIRC_CNT(info->xmit.head, info->xmit.tail, @@ -358,7 +358,7 @@ static void transmit_chars(struct async_struct *info) } } -static void check_modem_status(struct async_struct *info) +static void check_modem_status(struct serial_state *info) { unsigned char status = ciab.pra & (SER_DCD | SER_CTS | SER_DSR); unsigned char dstatus; @@ -369,14 +369,14 @@ static void check_modem_status(struct async_struct *info) current_ctl_bits = status; if (dstatus) { - icount = &info->state->icount; + icount = &info->icount; /* update input line counters */ if (dstatus & SER_DSR) icount->dsr++; if (dstatus & SER_DCD) { icount->dcd++; #ifdef CONFIG_HARD_PPS - if ((info->state->flags & ASYNC_HARDPPS_CD) && + if ((info->flags & ASYNC_HARDPPS_CD) && !(status & SER_DCD)) hardpps(); #endif @@ -386,7 +386,7 @@ static void check_modem_status(struct async_struct *info) wake_up_interruptible(&info->delta_msr_wait); } - if ((info->state->flags & ASYNC_CHECK_CD) && (dstatus & SER_DCD)) { + if ((info->flags & ASYNC_CHECK_CD) && (dstatus & SER_DCD)) { #if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR)) printk("ttyS%d CD now %s...", info->line, (!(status & SER_DCD)) ? "on" : "off"); @@ -401,7 +401,7 @@ static void check_modem_status(struct async_struct *info) tty_hangup(info->tty); } } - if (info->state->flags & ASYNC_CTS_FLOW) { + if (info->flags & ASYNC_CTS_FLOW) { if (info->tty->hw_stopped) { if (!(status & SER_CTS)) { #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) @@ -437,7 +437,7 @@ static void check_modem_status(struct async_struct *info) static irqreturn_t ser_vbl_int( int irq, void *data) { /* vbl is just a periodic interrupt we tie into to update modem status */ - struct async_struct *info = data; + struct serial_state *info = data; /* * TBD - is it better to unregister from this interrupt or to * ignore it if MSI is clear ? @@ -449,14 +449,13 @@ static irqreturn_t ser_vbl_int( int irq, void *data) static irqreturn_t ser_rx_int(int irq, void *dev_id) { - struct serial_state *state = dev_id; - struct async_struct *info = state->info; + struct serial_state *info = dev_id; #ifdef SERIAL_DEBUG_INTR printk("ser_rx_int..."); #endif - if (!info || !info->tty) + if (!info->tty) return IRQ_NONE; receive_chars(info); @@ -468,15 +467,14 @@ static irqreturn_t ser_rx_int(int irq, void *dev_id) static irqreturn_t ser_tx_int(int irq, void *dev_id) { - struct serial_state *state = dev_id; - struct async_struct *info = state->info; + struct serial_state *info = dev_id; if (custom.serdatr & SDR_TBE) { #ifdef SERIAL_DEBUG_INTR printk("ser_tx_int..."); #endif - if (!info || !info->tty) + if (!info->tty) return IRQ_NONE; transmit_chars(info); @@ -502,7 +500,7 @@ static irqreturn_t ser_tx_int(int irq, void *dev_id) * --------------------------------------------------------------- */ -static int startup(struct async_struct * info) +static int startup(struct serial_state *info) { unsigned long flags; int retval=0; @@ -514,7 +512,7 @@ static int startup(struct async_struct * info) local_irq_save(flags); - if (info->state->flags & ASYNC_INITIALIZED) { + if (info->flags & ASYNC_INITIALIZED) { free_page(page); goto errout; } @@ -565,13 +563,13 @@ static int startup(struct async_struct * info) * Set up the tty->alt_speed kludge */ if (info->tty) { - if ((info->state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) info->tty->alt_speed = 57600; - if ((info->state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) info->tty->alt_speed = 115200; - if ((info->state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) info->tty->alt_speed = 230400; - if ((info->state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) info->tty->alt_speed = 460800; } @@ -580,7 +578,7 @@ static int startup(struct async_struct * info) */ change_speed(info, NULL); - info->state->flags |= ASYNC_INITIALIZED; + info->flags |= ASYNC_INITIALIZED; local_irq_restore(flags); return 0; @@ -593,15 +591,15 @@ errout: * This routine will shutdown a serial port; interrupts are disabled, and * DTR is dropped if the hangup on close termio flag is on. */ -static void shutdown(struct async_struct * info) +static void shutdown(struct serial_state *info) { unsigned long flags; struct serial_state *state; - if (!(info->state->flags & ASYNC_INITIALIZED)) + if (!(info->flags & ASYNC_INITIALIZED)) return; - state = info->state; + state = info; #ifdef SERIAL_DEBUG_OPEN printk("Shutting down serial port %d ....\n", info->line); @@ -640,7 +638,7 @@ static void shutdown(struct async_struct * info) if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); - info->state->flags &= ~ASYNC_INITIALIZED; + info->flags &= ~ASYNC_INITIALIZED; local_irq_restore(flags); } @@ -649,7 +647,7 @@ static void shutdown(struct async_struct * info) * This routine is called to set the UART divisor registers to match * the specified baud rate for a serial port. */ -static void change_speed(struct async_struct *info, +static void change_speed(struct serial_state *info, struct ktermios *old_termios) { int quot = 0, baud_base, baud; @@ -683,10 +681,10 @@ static void change_speed(struct async_struct *info, baud = tty_get_baud_rate(info->tty); if (!baud) baud = 9600; /* B0 transition handled in rs_set_termios */ - baud_base = info->state->baud_base; + baud_base = info->baud_base; if (baud == 38400 && - ((info->state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) - quot = info->state->custom_divisor; + ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) + quot = info->custom_divisor; else { if (baud == 134) /* Special case since 134 is really 134.5 */ @@ -703,8 +701,8 @@ static void change_speed(struct async_struct *info, if (!baud) baud = 9600; if (baud == 38400 && - ((info->state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) - quot = info->state->custom_divisor; + ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) + quot = info->custom_divisor; else { if (baud == 134) /* Special case since 134 is really 134.5 */ @@ -717,22 +715,22 @@ static void change_speed(struct async_struct *info, if (!quot) quot = baud_base / 9600; info->quot = quot; - info->timeout = ((info->state->xmit_fifo_size*HZ*bits*quot) / baud_base); + info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base); info->timeout += HZ/50; /* Add .02 seconds of slop */ /* CTS flow control flag and modem status interrupts */ info->IER &= ~UART_IER_MSI; - if (info->state->flags & ASYNC_HARDPPS_CD) + if (info->flags & ASYNC_HARDPPS_CD) info->IER |= UART_IER_MSI; if (cflag & CRTSCTS) { - info->state->flags |= ASYNC_CTS_FLOW; + info->flags |= ASYNC_CTS_FLOW; info->IER |= UART_IER_MSI; } else - info->state->flags &= ~ASYNC_CTS_FLOW; + info->flags &= ~ASYNC_CTS_FLOW; if (cflag & CLOCAL) - info->state->flags &= ~ASYNC_CHECK_CD; + info->flags &= ~ASYNC_CHECK_CD; else { - info->state->flags |= ASYNC_CHECK_CD; + info->flags |= ASYNC_CHECK_CD; info->IER |= UART_IER_MSI; } /* TBD: @@ -791,7 +789,7 @@ static void change_speed(struct async_struct *info, static int rs_put_char(struct tty_struct *tty, unsigned char ch) { - struct async_struct *info; + struct serial_state *info; unsigned long flags; info = tty->driver_data; @@ -818,7 +816,7 @@ static int rs_put_char(struct tty_struct *tty, unsigned char ch) static void rs_flush_chars(struct tty_struct *tty) { - struct async_struct *info = tty->driver_data; + struct serial_state *info = tty->driver_data; unsigned long flags; if (serial_paranoia_check(info, tty->name, "rs_flush_chars")) @@ -843,11 +841,9 @@ static void rs_flush_chars(struct tty_struct *tty) static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) { int c, ret = 0; - struct async_struct *info; + struct serial_state *info = tty->driver_data; unsigned long flags; - info = tty->driver_data; - if (serial_paranoia_check(info, tty->name, "rs_write")) return 0; @@ -891,7 +887,7 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count static int rs_write_room(struct tty_struct *tty) { - struct async_struct *info = tty->driver_data; + struct serial_state *info = tty->driver_data; if (serial_paranoia_check(info, tty->name, "rs_write_room")) return 0; @@ -900,7 +896,7 @@ static int rs_write_room(struct tty_struct *tty) static int rs_chars_in_buffer(struct tty_struct *tty) { - struct async_struct *info = tty->driver_data; + struct serial_state *info = tty->driver_data; if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer")) return 0; @@ -909,7 +905,7 @@ static int rs_chars_in_buffer(struct tty_struct *tty) static void rs_flush_buffer(struct tty_struct *tty) { - struct async_struct *info = tty->driver_data; + struct serial_state *info = tty->driver_data; unsigned long flags; if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) @@ -926,7 +922,7 @@ static void rs_flush_buffer(struct tty_struct *tty) */ static void rs_send_xchar(struct tty_struct *tty, char ch) { - struct async_struct *info = tty->driver_data; + struct serial_state *info = tty->driver_data; unsigned long flags; if (serial_paranoia_check(info, tty->name, "rs_send_char")) @@ -961,7 +957,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch) */ static void rs_throttle(struct tty_struct * tty) { - struct async_struct *info = tty->driver_data; + struct serial_state *info = tty->driver_data; unsigned long flags; #ifdef SERIAL_DEBUG_THROTTLE char buf[64]; @@ -986,7 +982,7 @@ static void rs_throttle(struct tty_struct * tty) static void rs_unthrottle(struct tty_struct * tty) { - struct async_struct *info = tty->driver_data; + struct serial_state *info = tty->driver_data; unsigned long flags; #ifdef SERIAL_DEBUG_THROTTLE char buf[64]; @@ -1017,11 +1013,10 @@ static void rs_unthrottle(struct tty_struct * tty) * ------------------------------------------------------------ */ -static int get_serial_info(struct async_struct * info, +static int get_serial_info(struct serial_state *state, struct serial_struct __user * retinfo) { struct serial_struct tmp; - struct serial_state *state = info->state; if (!retinfo) return -EFAULT; @@ -1043,11 +1038,11 @@ static int get_serial_info(struct async_struct * info, return 0; } -static int set_serial_info(struct async_struct * info, +static int set_serial_info(struct serial_state *state, struct serial_struct __user * new_info) { struct serial_struct new_serial; - struct serial_state old_state, *state; + struct serial_state old_state; unsigned int change_irq,change_port; int retval = 0; @@ -1055,7 +1050,6 @@ static int set_serial_info(struct async_struct * info, return -EFAULT; tty_lock(); - state = info->state; old_state = *state; change_irq = new_serial.irq != state->irq; @@ -1094,7 +1088,7 @@ static int set_serial_info(struct async_struct * info, state->custom_divisor = new_serial.custom_divisor; state->close_delay = new_serial.close_delay * HZ/100; state->closing_wait = new_serial.closing_wait * HZ/100; - info->tty->low_latency = (state->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + state->tty->low_latency = (state->flags & ASYNC_LOW_LATENCY) ? 1 : 0; check_and_exit: if (state->flags & ASYNC_INITIALIZED) { @@ -1102,17 +1096,17 @@ check_and_exit: (state->flags & ASYNC_SPD_MASK)) || (old_state.custom_divisor != state->custom_divisor)) { if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; + state->tty->alt_speed = 57600; if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->tty->alt_speed = 115200; + state->tty->alt_speed = 115200; if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->tty->alt_speed = 230400; + state->tty->alt_speed = 230400; if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; - change_speed(info, NULL); + state->tty->alt_speed = 460800; + change_speed(state, NULL); } } else - retval = startup(info); + retval = startup(state); tty_unlock(); return retval; } @@ -1128,7 +1122,7 @@ check_and_exit: * transmit holding register is empty. This functionality * allows an RS485 driver to be written in user space. */ -static int get_lsr_info(struct async_struct * info, unsigned int __user *value) +static int get_lsr_info(struct serial_state *info, unsigned int __user *value) { unsigned char status; unsigned int result; @@ -1147,7 +1141,7 @@ static int get_lsr_info(struct async_struct * info, unsigned int __user *value) static int rs_tiocmget(struct tty_struct *tty) { - struct async_struct * info = tty->driver_data; + struct serial_state *info = tty->driver_data; unsigned char control, status; unsigned long flags; @@ -1170,7 +1164,7 @@ static int rs_tiocmget(struct tty_struct *tty) static int rs_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { - struct async_struct * info = tty->driver_data; + struct serial_state *info = tty->driver_data; unsigned long flags; if (serial_paranoia_check(info, tty->name, "rs_ioctl")) @@ -1197,7 +1191,7 @@ static int rs_tiocmset(struct tty_struct *tty, unsigned int set, */ static int rs_break(struct tty_struct *tty, int break_state) { - struct async_struct * info = tty->driver_data; + struct serial_state *info = tty->driver_data; unsigned long flags; if (serial_paranoia_check(info, tty->name, "rs_break")) @@ -1222,12 +1216,12 @@ static int rs_break(struct tty_struct *tty, int break_state) static int rs_get_icount(struct tty_struct *tty, struct serial_icounter_struct *icount) { - struct async_struct *info = tty->driver_data; + struct serial_state *info = tty->driver_data; struct async_icount cnow; unsigned long flags; local_irq_save(flags); - cnow = info->state->icount; + cnow = info->icount; local_irq_restore(flags); icount->cts = cnow.cts; icount->dsr = cnow.dsr; @@ -1247,7 +1241,7 @@ static int rs_get_icount(struct tty_struct *tty, static int rs_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { - struct async_struct * info = tty->driver_data; + struct serial_state *info = tty->driver_data; struct async_icount cprev, cnow; /* kernel counter temps */ void __user *argp = (void __user *)arg; unsigned long flags; @@ -1275,7 +1269,7 @@ static int rs_ioctl(struct tty_struct *tty, case TIOCSERGSTRUCT: if (copy_to_user(argp, - info, sizeof(struct async_struct))) + info, sizeof(struct serial_state))) return -EFAULT; return 0; @@ -1288,7 +1282,7 @@ static int rs_ioctl(struct tty_struct *tty, case TIOCMIWAIT: local_irq_save(flags); /* note the counters on entry */ - cprev = info->state->icount; + cprev = info->icount; local_irq_restore(flags); while (1) { interruptible_sleep_on(&info->delta_msr_wait); @@ -1296,7 +1290,7 @@ static int rs_ioctl(struct tty_struct *tty, if (signal_pending(current)) return -ERESTARTSYS; local_irq_save(flags); - cnow = info->state->icount; /* atomic copy */ + cnow = info->icount; /* atomic copy */ local_irq_restore(flags); if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) @@ -1325,7 +1319,7 @@ static int rs_ioctl(struct tty_struct *tty, static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { - struct async_struct *info = tty->driver_data; + struct serial_state *info = tty->driver_data; unsigned long flags; unsigned int cflag = tty->termios->c_cflag; @@ -1385,15 +1379,12 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) */ static void rs_close(struct tty_struct *tty, struct file * filp) { - struct async_struct * info = tty->driver_data; - struct serial_state *state; + struct serial_state *state = tty->driver_data; unsigned long flags; - if (!info || serial_paranoia_check(info, tty->name, "rs_close")) + if (!state || serial_paranoia_check(state, tty->name, "rs_close")) return; - state = info->state; - local_irq_save(flags); if (tty_hung_up_p(filp)) { @@ -1403,7 +1394,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) } #ifdef SERIAL_DEBUG_OPEN - printk("rs_close ttys%d, count = %d\n", info->line, state->count); + printk("rs_close ttys%d, count = %d\n", state->line, state->count); #endif if ((tty->count == 1) && (state->count != 1)) { /* @@ -1441,7 +1432,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) * interrupt driver to stop checking the data ready bit in the * line status register. */ - info->read_status_mask &= ~UART_LSR_DR; + state->read_status_mask &= ~UART_LSR_DR; if (state->flags & ASYNC_INITIALIZED) { /* disable receive interrupts */ custom.intena = IF_RBF; @@ -1455,22 +1446,22 @@ static void rs_close(struct tty_struct *tty, struct file * filp) * has completely drained; this is especially * important if there is a transmit FIFO! */ - rs_wait_until_sent(tty, info->timeout); + rs_wait_until_sent(tty, state->timeout); } - shutdown(info); + shutdown(state); rs_flush_buffer(tty); tty_ldisc_flush(tty); tty->closing = 0; - info->tty = NULL; - if (info->blocked_open) { + state->tty = NULL; + if (state->blocked_open) { if (state->close_delay) { msleep_interruptible(jiffies_to_msecs(state->close_delay)); } - wake_up_interruptible(&info->open_wait); + wake_up_interruptible(&state->open_wait); } state->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); + wake_up_interruptible(&state->close_wait); local_irq_restore(flags); } @@ -1479,14 +1470,14 @@ static void rs_close(struct tty_struct *tty, struct file * filp) */ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) { - struct async_struct * info = tty->driver_data; + struct serial_state *info = tty->driver_data; unsigned long orig_jiffies, char_time; int lsr; if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) return; - if (info->state->xmit_fifo_size == 0) + if (info->xmit_fifo_size == 0) return; /* Just in case.... */ orig_jiffies = jiffies; @@ -1499,7 +1490,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) * Note: we have to use pretty tight timings here to satisfy * the NIST-PCTS. */ - char_time = (info->timeout - HZ/50) / info->state->xmit_fifo_size; + char_time = (info->timeout - HZ/50) / info->xmit_fifo_size; char_time = char_time / 5; if (char_time == 0) char_time = 1; @@ -1542,18 +1533,15 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) */ static void rs_hangup(struct tty_struct *tty) { - struct async_struct * info = tty->driver_data; - struct serial_state *state = info->state; + struct serial_state *info = tty->driver_data; if (serial_paranoia_check(info, tty->name, "rs_hangup")) return; - state = info->state; - rs_flush_buffer(tty); shutdown(info); - state->count = 0; - state->flags &= ~ASYNC_NORMAL_ACTIVE; + info->count = 0; + info->flags &= ~ASYNC_NORMAL_ACTIVE; info->tty = NULL; wake_up_interruptible(&info->open_wait); } @@ -1564,14 +1552,13 @@ static void rs_hangup(struct tty_struct *tty) * ------------------------------------------------------------ */ static int block_til_ready(struct tty_struct *tty, struct file * filp, - struct async_struct *info) + struct serial_state *info) { #ifdef DECLARE_WAITQUEUE DECLARE_WAITQUEUE(wait, current); #else struct wait_queue wait = { current, NULL }; #endif - struct serial_state *state = info->state; int retval; int do_clocal = 0, extra_count = 0; unsigned long flags; @@ -1581,11 +1568,11 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, * until it's done, and then try again. */ if (tty_hung_up_p(filp) || - (state->flags & ASYNC_CLOSING)) { - if (state->flags & ASYNC_CLOSING) + (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) interruptible_sleep_on(&info->close_wait); #ifdef SERIAL_DO_RESTART - return ((state->flags & ASYNC_HUP_NOTIFY) ? + return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); #else return -EAGAIN; @@ -1598,7 +1585,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, */ if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { - state->flags |= ASYNC_NORMAL_ACTIVE; + info->flags |= ASYNC_NORMAL_ACTIVE; return 0; } @@ -1608,7 +1595,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, /* * Block waiting for the carrier detect and the line to become * free (i.e., not in use by the callout). While we are in - * this loop, state->count is dropped by one, so that + * this loop, info->count is dropped by one, so that * rs_close() knows when to free things. We restore it upon * exit, either normal or abnormal. */ @@ -1616,12 +1603,12 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, add_wait_queue(&info->open_wait, &wait); #ifdef SERIAL_DEBUG_OPEN printk("block_til_ready before block: ttys%d, count = %d\n", - state->line, state->count); + info->line, info->count); #endif local_irq_save(flags); if (!tty_hung_up_p(filp)) { extra_count = 1; - state->count--; + info->count--; } local_irq_restore(flags); info->blocked_open++; @@ -1632,9 +1619,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, local_irq_restore(flags); set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || - !(state->flags & ASYNC_INITIALIZED)) { + !(info->flags & ASYNC_INITIALIZED)) { #ifdef SERIAL_DO_RESTART - if (state->flags & ASYNC_HUP_NOTIFY) + if (info->flags & ASYNC_HUP_NOTIFY) retval = -EAGAIN; else retval = -ERESTARTSYS; @@ -1643,7 +1630,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, #endif break; } - if (!(state->flags & ASYNC_CLOSING) && + if (!(info->flags & ASYNC_CLOSING) && (do_clocal || (!(ciab.pra & SER_DCD)) )) break; if (signal_pending(current)) { @@ -1652,7 +1639,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, } #ifdef SERIAL_DEBUG_OPEN printk("block_til_ready blocking: ttys%d, count = %d\n", - info->line, state->count); + info->line, info->count); #endif tty_unlock(); schedule(); @@ -1661,46 +1648,15 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, __set_current_state(TASK_RUNNING); remove_wait_queue(&info->open_wait, &wait); if (extra_count) - state->count++; + info->count++; info->blocked_open--; #ifdef SERIAL_DEBUG_OPEN printk("block_til_ready after blocking: ttys%d, count = %d\n", - info->line, state->count); + info->line, info->count); #endif if (retval) return retval; - state->flags |= ASYNC_NORMAL_ACTIVE; - return 0; -} - -static int get_async_struct(int line, struct async_struct **ret_info) -{ - struct async_struct *info; - struct serial_state *sstate; - - sstate = rs_table + line; - sstate->count++; - if (sstate->info) { - *ret_info = sstate->info; - return 0; - } - info = kzalloc(sizeof(struct async_struct), GFP_KERNEL); - if (!info) { - sstate->count--; - return -ENOMEM; - } -#ifdef DECLARE_WAITQUEUE - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - init_waitqueue_head(&info->delta_msr_wait); -#endif - info->state = sstate; - if (sstate->info) { - kfree(info); - *ret_info = sstate->info; - return 0; - } - *ret_info = sstate->info = info; + info->flags |= ASYNC_NORMAL_ACTIVE; return 0; } @@ -1712,32 +1668,29 @@ static int get_async_struct(int line, struct async_struct **ret_info) */ static int rs_open(struct tty_struct *tty, struct file * filp) { - struct async_struct *info; + struct serial_state *info = rs_table + tty->index; int retval; - retval = get_async_struct(tty->index, &info); - if (retval) { - return retval; - } - tty->driver_data = info; + info->count++; info->tty = tty; + tty->driver_data = info; if (serial_paranoia_check(info, tty->name, "rs_open")) return -ENODEV; #ifdef SERIAL_DEBUG_OPEN - printk("rs_open %s, count = %d\n", tty->name, info->state->count); + printk("rs_open %s, count = %d\n", tty->name, info->count); #endif - info->tty->low_latency = (info->state->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; /* * If the port is the middle of closing, bail out now */ if (tty_hung_up_p(filp) || - (info->state->flags & ASYNC_CLOSING)) { - if (info->state->flags & ASYNC_CLOSING) + (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) interruptible_sleep_on(&info->close_wait); #ifdef SERIAL_DO_RESTART - return ((info->state->flags & ASYNC_HUP_NOTIFY) ? + return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); #else return -EAGAIN; @@ -1773,24 +1726,14 @@ static int rs_open(struct tty_struct *tty, struct file * filp) static inline void line_info(struct seq_file *m, struct serial_state *state) { - struct async_struct *info = state->info, scr_info; char stat_buf[30], control, status; unsigned long flags; seq_printf(m, "%d: uart:amiga_builtin",state->line); - /* - * Figure out the current RS-232 lines - */ - if (!info) { - info = &scr_info; /* This is just for serial_{in,out} */ - - info->quot = 0; - info->tty = NULL; - } local_irq_save(flags); status = ciab.pra; - control = info ? info->MCR : status; + control = (state->flags & ASYNC_INITIALIZED) ? state->MCR : status; local_irq_restore(flags); stat_buf[0] = 0; @@ -1806,9 +1749,8 @@ static inline void line_info(struct seq_file *m, struct serial_state *state) if(!(status & SER_DCD)) strcat(stat_buf, "|CD"); - if (info->quot) { - seq_printf(m, " baud:%d", state->baud_base / info->quot); - } + if (state->quot) + seq_printf(m, " baud:%d", state->baud_base / state->quot); seq_printf(m, " tx:%d rx:%d", state->icount.tx, state->icount.rx); @@ -1938,6 +1880,9 @@ static int __init amiga_serial_probe(struct platform_device *pdev) state->icount.rx = state->icount.tx = 0; state->icount.frame = state->icount.parity = 0; state->icount.overrun = state->icount.brk = 0; + init_waitqueue_head(&state->open_wait); + init_waitqueue_head(&state->close_wait); + init_waitqueue_head(&state->delta_msr_wait); printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n", state->line); @@ -1993,7 +1938,6 @@ static int __exit amiga_serial_remove(struct platform_device *pdev) { int error; struct serial_state *state = platform_get_drvdata(pdev); - struct async_struct *info = state->info; /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ if ((error = tty_unregister_driver(serial_driver))) @@ -2001,11 +1945,8 @@ static int __exit amiga_serial_remove(struct platform_device *pdev) error); put_tty_driver(serial_driver); - rs_table[0].info = NULL; - kfree(info); - - free_irq(IRQ_AMIGA_TBE, rs_table); - free_irq(IRQ_AMIGA_RBF, rs_table); + free_irq(IRQ_AMIGA_TBE, state); + free_irq(IRQ_AMIGA_RBF, state); platform_set_drvdata(pdev, NULL); diff --git a/include/linux/serialP.h b/include/linux/serialP.h index b8543f902453..984f5ba8da4e 100644 --- a/include/linux/serialP.h +++ b/include/linux/serialP.h @@ -38,24 +38,24 @@ struct serial_state { unsigned short close_delay; unsigned short closing_wait; /* time to wait before closing */ struct async_icount icount; - struct async_struct *info; -}; -struct async_struct { - struct serial_state *state; - struct tty_struct *tty; + /* amiserial */ int read_status_mask; int ignore_status_mask; int timeout; int quot; - int x_char; /* xon/xoff character */ int IER; /* Interrupt Enable Register */ int MCR; /* Modem control register */ + wait_queue_head_t delta_msr_wait; + /* simserial */ + int x_char; /* xon/xoff character */ int blocked_open; /* # of blocked opens */ struct circ_buf xmit; wait_queue_head_t open_wait; wait_queue_head_t close_wait; - wait_queue_head_t delta_msr_wait; + struct tty_struct *tty; + /* /simserial */ + /* /amiserial */ }; #endif /* _LINUX_SERIAL_H */ -- cgit v1.2.3 From 5e99d5458729b0eb763ca83a2fbb95f6276c4243 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:23 +0100 Subject: TTY: simserial, pass tty down to functions This avoids pain with tty refcounting and touching tty_port in the future. It allows us to remove some state->tty tests because the tty passed down to them can never be NULL. Signed-off-by: Jiri Slaby Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 50 +++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 26 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 7b6e60e9167b..a76a27ed3de0 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -202,7 +202,8 @@ static int rs_put_char(struct tty_struct *tty, unsigned char ch) return 1; } -static void transmit_chars(struct serial_state *info, int *intr_done) +static void transmit_chars(struct tty_struct *tty, struct serial_state *info, + int *intr_done) { int count; unsigned long flags; @@ -220,10 +221,11 @@ static void transmit_chars(struct serial_state *info, int *intr_done) goto out; } - if (info->xmit.head == info->xmit.tail || info->tty->stopped || info->tty->hw_stopped) { + if (info->xmit.head == info->xmit.tail || tty->stopped || + tty->hw_stopped) { #ifdef SIMSERIAL_DEBUG printk("transmit_chars: head=%d, tail=%d, stopped=%d\n", - info->xmit.head, info->xmit.tail, info->tty->stopped); + info->xmit.head, info->xmit.tail, tty->stopped); #endif goto out; } @@ -261,7 +263,7 @@ static void rs_flush_chars(struct tty_struct *tty) !info->xmit.buf) return; - transmit_chars(info, NULL); + transmit_chars(tty, info, NULL); } @@ -295,7 +297,7 @@ static int rs_write(struct tty_struct * tty, */ if (CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) && !tty->stopped && !tty->hw_stopped) { - transmit_chars(info, NULL); + transmit_chars(tty, info, NULL); } return ret; } @@ -340,7 +342,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch) * I guess we could call console->write() directly but * let's do that for now. */ - transmit_chars(info, NULL); + transmit_chars(tty, info, NULL); } } @@ -442,7 +444,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) * This routine will shutdown a serial port; interrupts are disabled, and * DTR is dropped if the hangup on close termio flag is on. */ -static void shutdown(struct serial_state *info) +static void shutdown(struct tty_struct *tty, struct serial_state *info) { unsigned long flags; @@ -464,7 +466,7 @@ static void shutdown(struct serial_state *info) info->xmit.buf = NULL; } - if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); + set_bit(TTY_IO_ERROR, &tty->flags); info->flags &= ~ASYNC_INITIALIZED; } @@ -528,7 +530,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. */ - shutdown(info); + shutdown(tty, info); rs_flush_buffer(tty); tty_ldisc_flush(tty); info->tty = NULL; @@ -563,7 +565,7 @@ static void rs_hangup(struct tty_struct *tty) rs_flush_buffer(tty); if (info->flags & ASYNC_CLOSING) return; - shutdown(info); + shutdown(tty, info); info->count = 0; info->flags &= ~ASYNC_NORMAL_ACTIVE; @@ -572,7 +574,7 @@ static void rs_hangup(struct tty_struct *tty) } -static int startup(struct serial_state *state) +static int startup(struct tty_struct *tty, struct serial_state *state) { unsigned long flags; int retval=0; @@ -590,8 +592,7 @@ static int startup(struct serial_state *state) } if (!state->port || !state->type) { - if (state->tty) - set_bit(TTY_IO_ERROR, &state->tty->flags); + set_bit(TTY_IO_ERROR, &tty->flags); free_page(page); goto errout; } @@ -614,8 +615,7 @@ static int startup(struct serial_state *state) goto errout; } - if (state->tty) - clear_bit(TTY_IO_ERROR, &state->tty->flags); + clear_bit(TTY_IO_ERROR, &tty->flags); state->xmit.head = state->xmit.tail = 0; @@ -630,16 +630,14 @@ static int startup(struct serial_state *state) /* * Set up the tty->alt_speed kludge */ - if (state->tty) { - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - state->tty->alt_speed = 57600; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - state->tty->alt_speed = 115200; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - state->tty->alt_speed = 230400; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - state->tty->alt_speed = 460800; - } + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + tty->alt_speed = 57600; + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + tty->alt_speed = 115200; + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + tty->alt_speed = 230400; + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + tty->alt_speed = 460800; state->flags |= ASYNC_INITIALIZED; local_irq_restore(flags); @@ -699,7 +697,7 @@ static int rs_open(struct tty_struct *tty, struct file * filp) /* * Start up serial port */ - retval = startup(info); + retval = startup(tty, info); if (retval) { return retval; } -- cgit v1.2.3 From 87758791c99715433841f1c054b49166506513e4 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:24 +0100 Subject: TTY: amiserial/simserial, use tty_port Add tty_port to serial_state and start using common tty port members from tty_port in amiserial and simserial. The rest will follow one by one. Signed-off-by: Jiri Slaby Cc: Geert Uytterhoeven Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 24 ++++++++--------- drivers/tty/amiserial.c | 63 ++++++++++++++++++++++---------------------- include/linux/serialP.h | 7 ++--- 3 files changed, 45 insertions(+), 49 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index a76a27ed3de0..614c091b203f 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -165,7 +165,7 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id) { struct serial_state *info = dev_id; - if (!info->tty) { + if (!info->tport.tty) { printk(KERN_INFO "simrs_interrupt_single: info|tty=0 info=%p problem\n", info); return IRQ_NONE; } @@ -173,7 +173,7 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id) * pretty simple in our case, because we only get interrupts * on inbound traffic */ - receive_chars(info->tty); + receive_chars(info->tport.tty); return IRQ_HANDLED; } @@ -533,14 +533,14 @@ static void rs_close(struct tty_struct *tty, struct file * filp) shutdown(tty, info); rs_flush_buffer(tty); tty_ldisc_flush(tty); - info->tty = NULL; - if (info->blocked_open) { + info->tport.tty = NULL; + if (info->tport.blocked_open) { if (info->close_delay) schedule_timeout_interruptible(info->close_delay); - wake_up_interruptible(&info->open_wait); + wake_up_interruptible(&info->tport.open_wait); } info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); + wake_up_interruptible(&info->tport.close_wait); } /* @@ -569,8 +569,8 @@ static void rs_hangup(struct tty_struct *tty) info->count = 0; info->flags &= ~ASYNC_NORMAL_ACTIVE; - info->tty = NULL; - wake_up_interruptible(&info->open_wait); + info->tport.tty = NULL; + wake_up_interruptible(&info->tport.open_wait); } @@ -662,8 +662,9 @@ static int rs_open(struct tty_struct *tty, struct file * filp) unsigned long page; info->count++; - info->tty = tty; + info->tport.tty = tty; tty->driver_data = info; + tty->port = &info->tport; #ifdef SIMSERIAL_DEBUG printk("rs_open %s, count = %d\n", tty->name, info->count); @@ -685,7 +686,7 @@ static int rs_open(struct tty_struct *tty, struct file * filp) */ if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); + interruptible_sleep_on(&info->tport.close_wait); #ifdef SERIAL_DO_RESTART return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); @@ -827,8 +828,7 @@ simrs_init (void) * Let's have a little bit of fun ! */ for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { - init_waitqueue_head(&state->open_wait); - init_waitqueue_head(&state->close_wait); + tty_port_init(&state->tport); if (state->type == PORT_UNKNOWN) continue; diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 5b87744748d5..71d3331d6e84 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -234,7 +234,7 @@ static void receive_chars(struct serial_state *info) { int status; int serdatr; - struct tty_struct *tty = info->tty; + struct tty_struct *tty = info->tport.tty; unsigned char ch, flag; struct async_icount *icount; int oe = 0; @@ -331,8 +331,8 @@ static void transmit_chars(struct serial_state *info) return; } if (info->xmit.head == info->xmit.tail - || info->tty->stopped - || info->tty->hw_stopped) { + || info->tport.tty->stopped + || info->tport.tty->hw_stopped) { info->IER &= ~UART_IER_THRI; custom.intena = IF_TBE; mb(); @@ -347,7 +347,7 @@ static void transmit_chars(struct serial_state *info) if (CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) < WAKEUP_CHARS) - tty_wakeup(info->tty); + tty_wakeup(info->tport.tty); #ifdef SERIAL_DEBUG_INTR printk("THRE..."); @@ -384,7 +384,7 @@ static void check_modem_status(struct serial_state *info) } if (dstatus & SER_CTS) icount->cts++; - wake_up_interruptible(&info->delta_msr_wait); + wake_up_interruptible(&info->tport.delta_msr_wait); } if ((info->flags & ASYNC_CHECK_CD) && (dstatus & SER_DCD)) { @@ -393,29 +393,29 @@ static void check_modem_status(struct serial_state *info) (!(status & SER_DCD)) ? "on" : "off"); #endif if (!(status & SER_DCD)) - wake_up_interruptible(&info->open_wait); + wake_up_interruptible(&info->tport.open_wait); else { #ifdef SERIAL_DEBUG_OPEN printk("doing serial hangup..."); #endif - if (info->tty) - tty_hangup(info->tty); + if (info->tport.tty) + tty_hangup(info->tport.tty); } } if (info->flags & ASYNC_CTS_FLOW) { - if (info->tty->hw_stopped) { + if (info->tport.tty->hw_stopped) { if (!(status & SER_CTS)) { #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) printk("CTS tx start..."); #endif - info->tty->hw_stopped = 0; + info->tport.tty->hw_stopped = 0; info->IER |= UART_IER_THRI; custom.intena = IF_SETCLR | IF_TBE; mb(); /* set a pending Tx Interrupt, transmitter should restart now */ custom.intreq = IF_SETCLR | IF_TBE; mb(); - tty_wakeup(info->tty); + tty_wakeup(info->tport.tty); return; } } else { @@ -423,7 +423,7 @@ static void check_modem_status(struct serial_state *info) #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) printk("CTS tx stop..."); #endif - info->tty->hw_stopped = 1; + info->tport.tty->hw_stopped = 1; info->IER &= ~UART_IER_THRI; /* disable Tx interrupt and remove any pending interrupts */ custom.intena = IF_TBE; @@ -456,7 +456,7 @@ static irqreturn_t ser_rx_int(int irq, void *dev_id) printk("ser_rx_int..."); #endif - if (!info->tty) + if (!info->tport.tty) return IRQ_NONE; receive_chars(info); @@ -475,7 +475,7 @@ static irqreturn_t ser_tx_int(int irq, void *dev_id) printk("ser_tx_int..."); #endif - if (!info->tty) + if (!info->tport.tty) return IRQ_NONE; transmit_chars(info); @@ -607,7 +607,7 @@ static void shutdown(struct tty_struct *tty, struct serial_state *info) * clear delta_msr_wait queue to avoid mem leaks: we may free the irq * here so the queue might never be waken up */ - wake_up_interruptible(&info->delta_msr_wait); + wake_up_interruptible(&info->tport.delta_msr_wait); /* * Free the IRQ, if necessary @@ -1274,7 +1274,7 @@ static int rs_ioctl(struct tty_struct *tty, cprev = info->icount; local_irq_restore(flags); while (1) { - interruptible_sleep_on(&info->delta_msr_wait); + interruptible_sleep_on(&info->tport.delta_msr_wait); /* see if a signal did it */ if (signal_pending(current)) return -ERESTARTSYS; @@ -1442,15 +1442,15 @@ static void rs_close(struct tty_struct *tty, struct file * filp) tty_ldisc_flush(tty); tty->closing = 0; - state->tty = NULL; - if (state->blocked_open) { + state->tport.tty = NULL; + if (state->tport.blocked_open) { if (state->close_delay) { msleep_interruptible(jiffies_to_msecs(state->close_delay)); } - wake_up_interruptible(&state->open_wait); + wake_up_interruptible(&state->tport.open_wait); } state->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&state->close_wait); + wake_up_interruptible(&state->tport.close_wait); local_irq_restore(flags); } @@ -1531,8 +1531,8 @@ static void rs_hangup(struct tty_struct *tty) shutdown(tty, info); info->count = 0; info->flags &= ~ASYNC_NORMAL_ACTIVE; - info->tty = NULL; - wake_up_interruptible(&info->open_wait); + info->tport.tty = NULL; + wake_up_interruptible(&info->tport.open_wait); } /* @@ -1559,7 +1559,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); + interruptible_sleep_on(&info->tport.close_wait); #ifdef SERIAL_DO_RESTART return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); @@ -1589,7 +1589,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, * exit, either normal or abnormal. */ retval = 0; - add_wait_queue(&info->open_wait, &wait); + add_wait_queue(&info->tport.open_wait, &wait); #ifdef SERIAL_DEBUG_OPEN printk("block_til_ready before block: ttys%d, count = %d\n", info->line, info->count); @@ -1600,7 +1600,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, info->count--; } local_irq_restore(flags); - info->blocked_open++; + info->tport.blocked_open++; while (1) { local_irq_save(flags); if (tty->termios->c_cflag & CBAUD) @@ -1635,10 +1635,10 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, tty_lock(); } __set_current_state(TASK_RUNNING); - remove_wait_queue(&info->open_wait, &wait); + remove_wait_queue(&info->tport.open_wait, &wait); if (extra_count) info->count++; - info->blocked_open--; + info->tport.blocked_open--; #ifdef SERIAL_DEBUG_OPEN printk("block_til_ready after blocking: ttys%d, count = %d\n", info->line, info->count); @@ -1661,8 +1661,9 @@ static int rs_open(struct tty_struct *tty, struct file * filp) int retval; info->count++; - info->tty = tty; + info->tport.tty = tty; tty->driver_data = info; + tty->port = &info->tport; if (serial_paranoia_check(info, tty->name, "rs_open")) return -ENODEV; @@ -1677,7 +1678,7 @@ static int rs_open(struct tty_struct *tty, struct file * filp) if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); + interruptible_sleep_on(&info->tport.close_wait); #ifdef SERIAL_DO_RESTART return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); @@ -1869,9 +1870,7 @@ static int __init amiga_serial_probe(struct platform_device *pdev) state->icount.rx = state->icount.tx = 0; state->icount.frame = state->icount.parity = 0; state->icount.overrun = state->icount.brk = 0; - init_waitqueue_head(&state->open_wait); - init_waitqueue_head(&state->close_wait); - init_waitqueue_head(&state->delta_msr_wait); + tty_port_init(&state->tport); printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n", state->line); diff --git a/include/linux/serialP.h b/include/linux/serialP.h index 984f5ba8da4e..32d45b869cbc 100644 --- a/include/linux/serialP.h +++ b/include/linux/serialP.h @@ -23,6 +23,7 @@ #include #include #include +#include #include struct serial_state { @@ -38,6 +39,7 @@ struct serial_state { unsigned short close_delay; unsigned short closing_wait; /* time to wait before closing */ struct async_icount icount; + struct tty_port tport; /* amiserial */ int read_status_mask; @@ -46,14 +48,9 @@ struct serial_state { int quot; int IER; /* Interrupt Enable Register */ int MCR; /* Modem control register */ - wait_queue_head_t delta_msr_wait; /* simserial */ int x_char; /* xon/xoff character */ - int blocked_open; /* # of blocked opens */ struct circ_buf xmit; - wait_queue_head_t open_wait; - wait_queue_head_t close_wait; - struct tty_struct *tty; /* /simserial */ /* /amiserial */ }; -- cgit v1.2.3 From 799be6ff2fd7294f428a9e68a7786490c862c1af Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:25 +0100 Subject: TTY: amiserial/simserial, use close delays from tty_port Note that previously simserial set the delay to 0. So we preserve that. BUT, is it correct? Signed-off-by: Jiri Slaby Cc: Geert Uytterhoeven Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 5 +++-- drivers/tty/amiserial.c | 20 +++++++++----------- include/linux/serialP.h | 2 -- 3 files changed, 12 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 614c091b203f..fb324b345e88 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -535,8 +535,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp) tty_ldisc_flush(tty); info->tport.tty = NULL; if (info->tport.blocked_open) { - if (info->close_delay) - schedule_timeout_interruptible(info->close_delay); + if (info->tport.close_delay) + schedule_timeout_interruptible(info->tport.close_delay); wake_up_interruptible(&info->tport.open_wait); } info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); @@ -829,6 +829,7 @@ simrs_init (void) */ for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { tty_port_init(&state->tport); + state->tport.close_delay = 0; /* XXX really 0? */ if (state->type == PORT_UNKNOWN) continue; diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 71d3331d6e84..06e3a0990c8b 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -1022,8 +1022,8 @@ static int get_serial_info(struct serial_state *state, tmp.flags = state->flags; tmp.xmit_fifo_size = state->xmit_fifo_size; tmp.baud_base = state->baud_base; - tmp.close_delay = state->close_delay; - tmp.closing_wait = state->closing_wait; + tmp.close_delay = state->tport.close_delay; + tmp.closing_wait = state->tport.closing_wait; tmp.custom_divisor = state->custom_divisor; tty_unlock(); if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) @@ -1052,7 +1052,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state, if (!serial_isroot()) { if ((new_serial.baud_base != state->baud_base) || - (new_serial.close_delay != state->close_delay) || + (new_serial.close_delay != state->tport.close_delay) || (new_serial.xmit_fifo_size != state->xmit_fifo_size) || ((new_serial.flags & ~ASYNC_USR_MASK) != (state->flags & ~ASYNC_USR_MASK))) @@ -1077,8 +1077,8 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state, state->flags = ((state->flags & ~ASYNC_FLAGS) | (new_serial.flags & ASYNC_FLAGS)); state->custom_divisor = new_serial.custom_divisor; - state->close_delay = new_serial.close_delay * HZ/100; - state->closing_wait = new_serial.closing_wait * HZ/100; + state->tport.close_delay = new_serial.close_delay * HZ/100; + state->tport.closing_wait = new_serial.closing_wait * HZ/100; tty->low_latency = (state->flags & ASYNC_LOW_LATENCY) ? 1 : 0; check_and_exit: @@ -1413,8 +1413,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp) * the line discipline to only process XON/XOFF characters. */ tty->closing = 1; - if (state->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, state->closing_wait); + if (state->tport.closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, state->tport.closing_wait); /* * At this point we stop accepting input. To do this, we * disable the receive line status interrupts, and tell the @@ -1444,8 +1444,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp) tty->closing = 0; state->tport.tty = NULL; if (state->tport.blocked_open) { - if (state->close_delay) { - msleep_interruptible(jiffies_to_msecs(state->close_delay)); + if (state->tport.close_delay) { + msleep_interruptible(jiffies_to_msecs(state->tport.close_delay)); } wake_up_interruptible(&state->tport.open_wait); } @@ -1863,8 +1863,6 @@ static int __init amiga_serial_probe(struct platform_device *pdev) state->port = (int)&custom.serdatr; /* Just to give it a value */ state->line = 0; state->custom_divisor = 0; - state->close_delay = 5*HZ/10; - state->closing_wait = 30*HZ; state->icount.cts = state->icount.dsr = state->icount.rng = state->icount.dcd = 0; state->icount.rx = state->icount.tx = 0; diff --git a/include/linux/serialP.h b/include/linux/serialP.h index 32d45b869cbc..997edd008b92 100644 --- a/include/linux/serialP.h +++ b/include/linux/serialP.h @@ -36,8 +36,6 @@ struct serial_state { int xmit_fifo_size; int custom_divisor; int count; - unsigned short close_delay; - unsigned short closing_wait; /* time to wait before closing */ struct async_icount icount; struct tty_port tport; -- cgit v1.2.3 From 12c8035435fa16e3f6b18049bb1d7815c00a7a58 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:26 +0100 Subject: TTY: amiserial/simserial, use count from tty_port Nothing special. Just remove count from serial_state and change all users to use tty_port. Signed-off-by: Jiri Slaby Cc: Geert Uytterhoeven Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 24 ++++++++++++------------ drivers/tty/amiserial.c | 34 +++++++++++++++++----------------- include/linux/serialP.h | 1 - 3 files changed, 29 insertions(+), 30 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index fb324b345e88..baa2b1ec00a0 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -500,26 +500,26 @@ static void rs_close(struct tty_struct *tty, struct file * filp) return; } #ifdef SIMSERIAL_DEBUG - printk("rs_close ttys%d, count = %d\n", info->line, info->count); + printk("rs_close ttys%d, count = %d\n", info->line, info->tport.count); #endif - if ((tty->count == 1) && (info->count != 1)) { + if ((tty->count == 1) && (info->tport.count != 1)) { /* * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. info->count should always + * structure will be freed. info->tport.count should always * be one in these conditions. If it's greater than * one, we've got real problems, since it means the * serial port won't be shutdown. */ printk(KERN_ERR "rs_close: bad serial port count; tty->count is 1, " - "info->count is %d\n", info->count); - info->count = 1; + "info->tport.count is %d\n", info->tport.count); + info->tport.count = 1; } - if (--info->count < 0) { + if (--info->tport.count < 0) { printk(KERN_ERR "rs_close: bad serial port count for ttys%d: %d\n", - info->line, info->count); - info->count = 0; + info->line, info->tport.count); + info->tport.count = 0; } - if (info->count) { + if (info->tport.count) { local_irq_restore(flags); return; } @@ -567,7 +567,7 @@ static void rs_hangup(struct tty_struct *tty) return; shutdown(tty, info); - info->count = 0; + info->tport.count = 0; info->flags &= ~ASYNC_NORMAL_ACTIVE; info->tport.tty = NULL; wake_up_interruptible(&info->tport.open_wait); @@ -661,13 +661,13 @@ static int rs_open(struct tty_struct *tty, struct file * filp) int retval; unsigned long page; - info->count++; + info->tport.count++; info->tport.tty = tty; tty->driver_data = info; tty->port = &info->tport; #ifdef SIMSERIAL_DEBUG - printk("rs_open %s, count = %d\n", tty->name, info->count); + printk("rs_open %s, count = %d\n", tty->name, info->tport.count); #endif tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 06e3a0990c8b..8ad64a0f1251 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -1383,26 +1383,26 @@ static void rs_close(struct tty_struct *tty, struct file * filp) } #ifdef SERIAL_DEBUG_OPEN - printk("rs_close ttys%d, count = %d\n", state->line, state->count); + printk("rs_close ttys%d, count = %d\n", state->line, state->tport.count); #endif - if ((tty->count == 1) && (state->count != 1)) { + if ((tty->count == 1) && (state->tport.count != 1)) { /* * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. state->count should always + * structure will be freed. state->tport.count should always * be one in these conditions. If it's greater than * one, we've got real problems, since it means the * serial port won't be shutdown. */ printk("rs_close: bad serial port count; tty->count is 1, " - "state->count is %d\n", state->count); - state->count = 1; + "state->tport.count is %d\n", state->tport.count); + state->tport.count = 1; } - if (--state->count < 0) { + if (--state->tport.count < 0) { printk("rs_close: bad serial port count for ttys%d: %d\n", - state->line, state->count); - state->count = 0; + state->line, state->tport.count); + state->tport.count = 0; } - if (state->count) { + if (state->tport.count) { DBG_CNT("before DEC-2"); local_irq_restore(flags); return; @@ -1529,7 +1529,7 @@ static void rs_hangup(struct tty_struct *tty) rs_flush_buffer(tty); shutdown(tty, info); - info->count = 0; + info->tport.count = 0; info->flags &= ~ASYNC_NORMAL_ACTIVE; info->tport.tty = NULL; wake_up_interruptible(&info->tport.open_wait); @@ -1584,7 +1584,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, /* * Block waiting for the carrier detect and the line to become * free (i.e., not in use by the callout). While we are in - * this loop, info->count is dropped by one, so that + * this loop, info->tport.count is dropped by one, so that * rs_close() knows when to free things. We restore it upon * exit, either normal or abnormal. */ @@ -1592,12 +1592,12 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, add_wait_queue(&info->tport.open_wait, &wait); #ifdef SERIAL_DEBUG_OPEN printk("block_til_ready before block: ttys%d, count = %d\n", - info->line, info->count); + info->line, info->tport.count); #endif local_irq_save(flags); if (!tty_hung_up_p(filp)) { extra_count = 1; - info->count--; + info->tport.count--; } local_irq_restore(flags); info->tport.blocked_open++; @@ -1628,7 +1628,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, } #ifdef SERIAL_DEBUG_OPEN printk("block_til_ready blocking: ttys%d, count = %d\n", - info->line, info->count); + info->line, info->tport.count); #endif tty_unlock(); schedule(); @@ -1637,11 +1637,11 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, __set_current_state(TASK_RUNNING); remove_wait_queue(&info->tport.open_wait, &wait); if (extra_count) - info->count++; + info->tport.count++; info->tport.blocked_open--; #ifdef SERIAL_DEBUG_OPEN printk("block_til_ready after blocking: ttys%d, count = %d\n", - info->line, info->count); + info->line, info->tport.count); #endif if (retval) return retval; @@ -1660,7 +1660,7 @@ static int rs_open(struct tty_struct *tty, struct file * filp) struct serial_state *info = rs_table + tty->index; int retval; - info->count++; + info->tport.count++; info->tport.tty = tty; tty->driver_data = info; tty->port = &info->tport; diff --git a/include/linux/serialP.h b/include/linux/serialP.h index 997edd008b92..a6612b9c7e84 100644 --- a/include/linux/serialP.h +++ b/include/linux/serialP.h @@ -35,7 +35,6 @@ struct serial_state { int line; int xmit_fifo_size; int custom_divisor; - int count; struct async_icount icount; struct tty_port tport; -- cgit v1.2.3 From 01bd730d92bd002adc3f3317d8e3328c629b436c Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:27 +0100 Subject: TTY: amiserial/simserial, use flags from tty_port This changes flags' type to ulong which is appropriate for all the set/clear_bits performed in the drivers.. Signed-off-by: Jiri Slaby Cc: Geert Uytterhoeven Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 33 +++++------ drivers/tty/amiserial.c | 129 ++++++++++++++++++++++--------------------- include/linux/serialP.h | 1 - 3 files changed, 83 insertions(+), 80 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index baa2b1ec00a0..c65c49d31e7f 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -448,7 +448,7 @@ static void shutdown(struct tty_struct *tty, struct serial_state *info) { unsigned long flags; - if (!(info->flags & ASYNC_INITIALIZED)) + if (!(info->tport.flags & ASYNC_INITIALIZED)) return; #ifdef SIMSERIAL_DEBUG @@ -468,7 +468,7 @@ static void shutdown(struct tty_struct *tty, struct serial_state *info) set_bit(TTY_IO_ERROR, &tty->flags); - info->flags &= ~ASYNC_INITIALIZED; + info->tport.flags &= ~ASYNC_INITIALIZED; } local_irq_restore(flags); } @@ -523,7 +523,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) local_irq_restore(flags); return; } - info->flags |= ASYNC_CLOSING; + info->tport.flags |= ASYNC_CLOSING; local_irq_restore(flags); /* @@ -539,7 +539,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) schedule_timeout_interruptible(info->tport.close_delay); wake_up_interruptible(&info->tport.open_wait); } - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); + info->tport.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); wake_up_interruptible(&info->tport.close_wait); } @@ -563,12 +563,12 @@ static void rs_hangup(struct tty_struct *tty) #endif rs_flush_buffer(tty); - if (info->flags & ASYNC_CLOSING) + if (info->tport.flags & ASYNC_CLOSING) return; shutdown(tty, info); info->tport.count = 0; - info->flags &= ~ASYNC_NORMAL_ACTIVE; + info->tport.flags &= ~ASYNC_NORMAL_ACTIVE; info->tport.tty = NULL; wake_up_interruptible(&info->tport.open_wait); } @@ -576,6 +576,7 @@ static void rs_hangup(struct tty_struct *tty) static int startup(struct tty_struct *tty, struct serial_state *state) { + struct tty_port *port = &state->tport; unsigned long flags; int retval=0; unsigned long page; @@ -586,7 +587,7 @@ static int startup(struct tty_struct *tty, struct serial_state *state) local_irq_save(flags); - if (state->flags & ASYNC_INITIALIZED) { + if (port->flags & ASYNC_INITIALIZED) { free_page(page); goto errout; } @@ -630,16 +631,16 @@ static int startup(struct tty_struct *tty, struct serial_state *state) /* * Set up the tty->alt_speed kludge */ - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) tty->alt_speed = 57600; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) tty->alt_speed = 115200; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) tty->alt_speed = 230400; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) tty->alt_speed = 460800; - state->flags |= ASYNC_INITIALIZED; + port->flags |= ASYNC_INITIALIZED; local_irq_restore(flags); return 0; @@ -669,7 +670,7 @@ static int rs_open(struct tty_struct *tty, struct file * filp) #ifdef SIMSERIAL_DEBUG printk("rs_open %s, count = %d\n", tty->name, info->tport.count); #endif - tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + tty->low_latency = (info->tport.flags & ASYNC_LOW_LATENCY) ? 1 : 0; if (!tmp_buf) { page = get_zeroed_page(GFP_KERNEL); @@ -684,11 +685,11 @@ static int rs_open(struct tty_struct *tty, struct file * filp) /* * If the port is the middle of closing, bail out now */ - if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) + if (tty_hung_up_p(filp) || (info->tport.flags & ASYNC_CLOSING)) { + if (info->tport.flags & ASYNC_CLOSING) interruptible_sleep_on(&info->tport.close_wait); #ifdef SERIAL_DO_RESTART - return ((info->flags & ASYNC_HUP_NOTIFY) ? + return ((info->tport.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); #else return -EAGAIN; diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 8ad64a0f1251..7d798262d0c2 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -45,7 +45,7 @@ #if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT) #define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \ - tty->name, (info->flags), serial_driver->refcount,info->count,tty->count,s) + tty->name, (info->tport.flags), serial_driver->refcount,info->count,tty->count,s) #else #define DBG_CNT(s) #endif @@ -296,7 +296,7 @@ static void receive_chars(struct serial_state *info) printk("handling break...."); #endif flag = TTY_BREAK; - if (info->flags & ASYNC_SAK) + if (info->tport.flags & ASYNC_SAK) do_SAK(tty); } else if (status & UART_LSR_PE) flag = TTY_PARITY; @@ -377,7 +377,7 @@ static void check_modem_status(struct serial_state *info) if (dstatus & SER_DCD) { icount->dcd++; #ifdef CONFIG_HARD_PPS - if ((info->flags & ASYNC_HARDPPS_CD) && + if ((info->tport.flags & ASYNC_HARDPPS_CD) && !(status & SER_DCD)) hardpps(); #endif @@ -387,7 +387,7 @@ static void check_modem_status(struct serial_state *info) wake_up_interruptible(&info->tport.delta_msr_wait); } - if ((info->flags & ASYNC_CHECK_CD) && (dstatus & SER_DCD)) { + if ((info->tport.flags & ASYNC_CHECK_CD) && (dstatus & SER_DCD)) { #if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR)) printk("ttyS%d CD now %s...", info->line, (!(status & SER_DCD)) ? "on" : "off"); @@ -402,7 +402,7 @@ static void check_modem_status(struct serial_state *info) tty_hangup(info->tport.tty); } } - if (info->flags & ASYNC_CTS_FLOW) { + if (info->tport.flags & ASYNC_CTS_FLOW) { if (info->tport.tty->hw_stopped) { if (!(status & SER_CTS)) { #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) @@ -503,6 +503,7 @@ static irqreturn_t ser_tx_int(int irq, void *dev_id) static int startup(struct tty_struct *tty, struct serial_state *info) { + struct tty_port *port = &info->tport; unsigned long flags; int retval=0; unsigned long page; @@ -513,7 +514,7 @@ static int startup(struct tty_struct *tty, struct serial_state *info) local_irq_save(flags); - if (info->flags & ASYNC_INITIALIZED) { + if (port->flags & ASYNC_INITIALIZED) { free_page(page); goto errout; } @@ -560,13 +561,13 @@ static int startup(struct tty_struct *tty, struct serial_state *info) /* * Set up the tty->alt_speed kludge */ - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) tty->alt_speed = 57600; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) tty->alt_speed = 115200; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) tty->alt_speed = 230400; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) tty->alt_speed = 460800; /* @@ -574,7 +575,7 @@ static int startup(struct tty_struct *tty, struct serial_state *info) */ change_speed(tty, info, NULL); - info->flags |= ASYNC_INITIALIZED; + port->flags |= ASYNC_INITIALIZED; local_irq_restore(flags); return 0; @@ -592,7 +593,7 @@ static void shutdown(struct tty_struct *tty, struct serial_state *info) unsigned long flags; struct serial_state *state; - if (!(info->flags & ASYNC_INITIALIZED)) + if (!(info->tport.flags & ASYNC_INITIALIZED)) return; state = info; @@ -633,7 +634,7 @@ static void shutdown(struct tty_struct *tty, struct serial_state *info) set_bit(TTY_IO_ERROR, &tty->flags); - info->flags &= ~ASYNC_INITIALIZED; + info->tport.flags &= ~ASYNC_INITIALIZED; local_irq_restore(flags); } @@ -645,6 +646,7 @@ static void shutdown(struct tty_struct *tty, struct serial_state *info) static void change_speed(struct tty_struct *tty, struct serial_state *info, struct ktermios *old_termios) { + struct tty_port *port = &info->tport; int quot = 0, baud_base, baud; unsigned cflag, cval = 0; int bits; @@ -675,8 +677,7 @@ static void change_speed(struct tty_struct *tty, struct serial_state *info, if (!baud) baud = 9600; /* B0 transition handled in rs_set_termios */ baud_base = info->baud_base; - if (baud == 38400 && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) + if (baud == 38400 && (port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) quot = info->custom_divisor; else { if (baud == 134) @@ -694,7 +695,7 @@ static void change_speed(struct tty_struct *tty, struct serial_state *info, if (!baud) baud = 9600; if (baud == 38400 && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) + (port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) quot = info->custom_divisor; else { if (baud == 134) @@ -713,17 +714,17 @@ static void change_speed(struct tty_struct *tty, struct serial_state *info, /* CTS flow control flag and modem status interrupts */ info->IER &= ~UART_IER_MSI; - if (info->flags & ASYNC_HARDPPS_CD) + if (port->flags & ASYNC_HARDPPS_CD) info->IER |= UART_IER_MSI; if (cflag & CRTSCTS) { - info->flags |= ASYNC_CTS_FLOW; + port->flags |= ASYNC_CTS_FLOW; info->IER |= UART_IER_MSI; } else - info->flags &= ~ASYNC_CTS_FLOW; + port->flags &= ~ASYNC_CTS_FLOW; if (cflag & CLOCAL) - info->flags &= ~ASYNC_CHECK_CD; + port->flags &= ~ASYNC_CHECK_CD; else { - info->flags |= ASYNC_CHECK_CD; + port->flags |= ASYNC_CHECK_CD; info->IER |= UART_IER_MSI; } /* TBD: @@ -1019,7 +1020,7 @@ static int get_serial_info(struct serial_state *state, tmp.line = state->line; tmp.port = state->port; tmp.irq = state->irq; - tmp.flags = state->flags; + tmp.flags = state->tport.flags; tmp.xmit_fifo_size = state->xmit_fifo_size; tmp.baud_base = state->baud_base; tmp.close_delay = state->tport.close_delay; @@ -1034,6 +1035,7 @@ static int get_serial_info(struct serial_state *state, static int set_serial_info(struct tty_struct *tty, struct serial_state *state, struct serial_struct __user * new_info) { + struct tty_port *port = &state->tport; struct serial_struct new_serial; bool change_spd; int retval = 0; @@ -1042,7 +1044,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state, return -EFAULT; tty_lock(); - change_spd = ((new_serial.flags ^ state->flags) & ASYNC_SPD_MASK) || + change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) || new_serial.custom_divisor != state->custom_divisor; if (new_serial.irq != state->irq || new_serial.port != state->port || new_serial.xmit_fifo_size != state->xmit_fifo_size) { @@ -1052,12 +1054,12 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state, if (!serial_isroot()) { if ((new_serial.baud_base != state->baud_base) || - (new_serial.close_delay != state->tport.close_delay) || + (new_serial.close_delay != port->close_delay) || (new_serial.xmit_fifo_size != state->xmit_fifo_size) || ((new_serial.flags & ~ASYNC_USR_MASK) != - (state->flags & ~ASYNC_USR_MASK))) + (port->flags & ~ASYNC_USR_MASK))) return -EPERM; - state->flags = ((state->flags & ~ASYNC_USR_MASK) | + port->flags = ((port->flags & ~ASYNC_USR_MASK) | (new_serial.flags & ASYNC_USR_MASK)); state->custom_divisor = new_serial.custom_divisor; goto check_and_exit; @@ -1074,23 +1076,23 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state, */ state->baud_base = new_serial.baud_base; - state->flags = ((state->flags & ~ASYNC_FLAGS) | + port->flags = ((port->flags & ~ASYNC_FLAGS) | (new_serial.flags & ASYNC_FLAGS)); state->custom_divisor = new_serial.custom_divisor; - state->tport.close_delay = new_serial.close_delay * HZ/100; - state->tport.closing_wait = new_serial.closing_wait * HZ/100; - tty->low_latency = (state->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + port->close_delay = new_serial.close_delay * HZ/100; + port->closing_wait = new_serial.closing_wait * HZ/100; + tty->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; check_and_exit: - if (state->flags & ASYNC_INITIALIZED) { + if (port->flags & ASYNC_INITIALIZED) { if (change_spd) { - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) tty->alt_speed = 57600; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) tty->alt_speed = 115200; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) tty->alt_speed = 230400; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) tty->alt_speed = 460800; change_speed(tty, state, NULL); } @@ -1407,7 +1409,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) local_irq_restore(flags); return; } - state->flags |= ASYNC_CLOSING; + state->tport.flags |= ASYNC_CLOSING; /* * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. @@ -1422,7 +1424,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) * line status register. */ state->read_status_mask &= ~UART_LSR_DR; - if (state->flags & ASYNC_INITIALIZED) { + if (state->tport.flags & ASYNC_INITIALIZED) { /* disable receive interrupts */ custom.intena = IF_RBF; mb(); @@ -1449,7 +1451,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) } wake_up_interruptible(&state->tport.open_wait); } - state->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); + state->tport.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); wake_up_interruptible(&state->tport.close_wait); local_irq_restore(flags); } @@ -1530,7 +1532,7 @@ static void rs_hangup(struct tty_struct *tty) rs_flush_buffer(tty); shutdown(tty, info); info->tport.count = 0; - info->flags &= ~ASYNC_NORMAL_ACTIVE; + info->tport.flags &= ~ASYNC_NORMAL_ACTIVE; info->tport.tty = NULL; wake_up_interruptible(&info->tport.open_wait); } @@ -1548,6 +1550,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, #else struct wait_queue wait = { current, NULL }; #endif + struct tty_port *port = &info->tport; int retval; int do_clocal = 0, extra_count = 0; unsigned long flags; @@ -1557,11 +1560,11 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, * until it's done, and then try again. */ if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->tport.close_wait); + (port->flags & ASYNC_CLOSING)) { + if (port->flags & ASYNC_CLOSING) + interruptible_sleep_on(&port->close_wait); #ifdef SERIAL_DO_RESTART - return ((info->flags & ASYNC_HUP_NOTIFY) ? + return ((port->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); #else return -EAGAIN; @@ -1574,7 +1577,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, */ if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { - info->flags |= ASYNC_NORMAL_ACTIVE; + port->flags |= ASYNC_NORMAL_ACTIVE; return 0; } @@ -1584,23 +1587,23 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, /* * Block waiting for the carrier detect and the line to become * free (i.e., not in use by the callout). While we are in - * this loop, info->tport.count is dropped by one, so that + * this loop, port->count is dropped by one, so that * rs_close() knows when to free things. We restore it upon * exit, either normal or abnormal. */ retval = 0; - add_wait_queue(&info->tport.open_wait, &wait); + add_wait_queue(&port->open_wait, &wait); #ifdef SERIAL_DEBUG_OPEN printk("block_til_ready before block: ttys%d, count = %d\n", - info->line, info->tport.count); + info->line, port->count); #endif local_irq_save(flags); if (!tty_hung_up_p(filp)) { extra_count = 1; - info->tport.count--; + port->count--; } local_irq_restore(flags); - info->tport.blocked_open++; + port->blocked_open++; while (1) { local_irq_save(flags); if (tty->termios->c_cflag & CBAUD) @@ -1608,9 +1611,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, local_irq_restore(flags); set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || - !(info->flags & ASYNC_INITIALIZED)) { + !(port->flags & ASYNC_INITIALIZED)) { #ifdef SERIAL_DO_RESTART - if (info->flags & ASYNC_HUP_NOTIFY) + if (port->flags & ASYNC_HUP_NOTIFY) retval = -EAGAIN; else retval = -ERESTARTSYS; @@ -1619,7 +1622,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, #endif break; } - if (!(info->flags & ASYNC_CLOSING) && + if (!(port->flags & ASYNC_CLOSING) && (do_clocal || (!(ciab.pra & SER_DCD)) )) break; if (signal_pending(current)) { @@ -1628,24 +1631,24 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, } #ifdef SERIAL_DEBUG_OPEN printk("block_til_ready blocking: ttys%d, count = %d\n", - info->line, info->tport.count); + info->line, port->count); #endif tty_unlock(); schedule(); tty_lock(); } __set_current_state(TASK_RUNNING); - remove_wait_queue(&info->tport.open_wait, &wait); + remove_wait_queue(&port->open_wait, &wait); if (extra_count) - info->tport.count++; - info->tport.blocked_open--; + port->count++; + port->blocked_open--; #ifdef SERIAL_DEBUG_OPEN printk("block_til_ready after blocking: ttys%d, count = %d\n", - info->line, info->tport.count); + info->line, port->count); #endif if (retval) return retval; - info->flags |= ASYNC_NORMAL_ACTIVE; + port->flags |= ASYNC_NORMAL_ACTIVE; return 0; } @@ -1670,17 +1673,17 @@ static int rs_open(struct tty_struct *tty, struct file * filp) #ifdef SERIAL_DEBUG_OPEN printk("rs_open %s, count = %d\n", tty->name, info->count); #endif - tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + tty->low_latency = (info->tport.flags & ASYNC_LOW_LATENCY) ? 1 : 0; /* * If the port is the middle of closing, bail out now */ if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) + (info->tport.flags & ASYNC_CLOSING)) { + if (info->tport.flags & ASYNC_CLOSING) interruptible_sleep_on(&info->tport.close_wait); #ifdef SERIAL_DO_RESTART - return ((info->flags & ASYNC_HUP_NOTIFY) ? + return ((info->tport.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); #else return -EAGAIN; @@ -1723,7 +1726,7 @@ static inline void line_info(struct seq_file *m, struct serial_state *state) local_irq_save(flags); status = ciab.pra; - control = (state->flags & ASYNC_INITIALIZED) ? state->MCR : status; + control = (state->tport.flags & ASYNC_INITIALIZED) ? state->MCR : status; local_irq_restore(flags); stat_buf[0] = 0; diff --git a/include/linux/serialP.h b/include/linux/serialP.h index a6612b9c7e84..e5e8442c08d6 100644 --- a/include/linux/serialP.h +++ b/include/linux/serialP.h @@ -30,7 +30,6 @@ struct serial_state { int baud_base; unsigned long port; int irq; - int flags; int type; int line; int xmit_fifo_size; -- cgit v1.2.3 From fd2d7a6e60068779bc72029f867b51d3dc2fe0cc Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:28 +0100 Subject: TTY: simserial, remove static initialization We do not use any of the preinitialized rs_state members for something real. So there is no need to initialize them. At the places we used them for printing, just print the values. And since only one port is supported, get rid of the loop. This simplifies simrs_init a heap. Thus we can handle fail paths in a standard way without panicing. Signed-off-by: Jiri Slaby Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 94 +++++++++++++------------------------------- 1 file changed, 27 insertions(+), 67 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index c65c49d31e7f..64ab004b4763 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -49,44 +49,7 @@ static char *serial_name = "SimSerial driver"; static char *serial_version = "0.6"; -/* - * This has been extracted from asm/serial.h. We need one eventually but - * I don't know exactly what we're going to put in it so just fake one - * for now. - */ -#define BASE_BAUD ( 1843200 / 16 ) - -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) - -/* - * Most of the values here are meaningless to this particular driver. - * However some values must be preserved for the code (leveraged from serial.c - * to work correctly). - * port must not be 0 - * type must not be UNKNOWN - * So I picked arbitrary (guess from where?) values instead - */ -static struct serial_state rs_table[NR_PORTS]={ - /* UART CLK PORT IRQ FLAGS */ - { BASE_BAUD, 0x3F8, 0, STD_COM_FLAGS, PORT_16550 } /* ttyS0 */ -}; - -/* - * Just for the fun of it ! - */ -static struct serial_uart_config uart_config[] = { - { "unknown", 1, 0 }, - { "8250", 1, 0 }, - { "16450", 1, 0 }, - { "16550", 1, 0 }, - { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO }, - { "cirrus", 1, 0 }, - { "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH }, - { "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | - UART_STARTECH }, - { "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO}, - { NULL, 0} -}; +static struct serial_state rs_table[NR_PORTS]; struct tty_driver *hp_simserial_driver; @@ -592,11 +555,6 @@ static int startup(struct tty_struct *tty, struct serial_state *state) goto errout; } - if (!state->port || !state->type) { - set_bit(TTY_IO_ERROR, &tty->flags); - free_page(page); - goto errout; - } if (state->xmit.buf) free_page(page); else @@ -725,9 +683,8 @@ static int rs_open(struct tty_struct *tty, struct file * filp) static inline void line_info(struct seq_file *m, struct serial_state *state) { - seq_printf(m, "%d: uart:%s port:%lX irq:%d\n", - state->line, uart_config[state->type].name, - state->port, state->irq); + seq_printf(m, "%d: uart:16550 port:3F8 irq:%d\n", + state->line, state->irq); } static int rs_proc_show(struct seq_file *m, void *v) @@ -796,11 +753,10 @@ static const struct tty_operations hp_ops = { /* * The serial driver boot-time initialization code! */ -static int __init -simrs_init (void) +static int __init simrs_init(void) { - int i, rc; - struct serial_state *state; + struct serial_state *state; + int retval; if (!ia64_platform_is("hpsim")) return -ENODEV; @@ -828,29 +784,33 @@ simrs_init (void) /* * Let's have a little bit of fun ! */ - for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { - tty_port_init(&state->tport); - state->tport.close_delay = 0; /* XXX really 0? */ + state = rs_table; + tty_port_init(&state->tport); + state->tport.close_delay = 0; /* XXX really 0? */ + + retval = hpsim_get_irq(KEYBOARD_INTR); + if (retval < 0) { + printk(KERN_ERR "%s: out of interrupt vectors!\n", + __func__); + goto err_free_tty; + } - if (state->type == PORT_UNKNOWN) continue; + state->irq = retval; - if (!state->irq) { - if ((rc = hpsim_get_irq(KEYBOARD_INTR)) < 0) - panic("%s: out of interrupt vectors!\n", - __func__); - state->irq = rc; - } + /* the port is imaginary */ + printk(KERN_INFO "ttyS%d at 0x03f8 (irq = %d) is a 16550\n", + state->line, state->irq); - printk(KERN_INFO "ttyS%d at 0x%04lx (irq = %d) is a %s\n", - state->line, - state->port, state->irq, - uart_config[state->type].name); + retval = tty_register_driver(hp_simserial_driver); + if (retval) { + printk(KERN_ERR "Couldn't register simserial driver\n"); + goto err_free_tty; } - if (tty_register_driver(hp_simserial_driver)) - panic("Couldn't register simserial driver\n"); - return 0; +err_free_tty: + put_tty_driver(hp_simserial_driver); + return retval; } #ifndef MODULE -- cgit v1.2.3 From d88405d44fd30fcbe77a9db540afd8823b30afdc Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:29 +0100 Subject: TTY: simserial, remove tmp_buf It is totally unused. Signed-off-by: Jiri Slaby Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 64ab004b4763..45df0f427864 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -55,8 +55,6 @@ struct tty_driver *hp_simserial_driver; static struct console *console; -static unsigned char *tmp_buf; - extern struct console *console_drivers; /* from kernel/printk.c */ /* @@ -237,7 +235,8 @@ static int rs_write(struct tty_struct * tty, int c, ret = 0; unsigned long flags; - if (!tty || !info->xmit.buf || !tmp_buf) return 0; + if (!tty || !info->xmit.buf) + return 0; local_irq_save(flags); while (1) { @@ -618,7 +617,6 @@ static int rs_open(struct tty_struct *tty, struct file * filp) { struct serial_state *info = rs_table + tty->index; int retval; - unsigned long page; info->tport.count++; info->tport.tty = tty; @@ -630,16 +628,6 @@ static int rs_open(struct tty_struct *tty, struct file * filp) #endif tty->low_latency = (info->tport.flags & ASYNC_LOW_LATENCY) ? 1 : 0; - if (!tmp_buf) { - page = get_zeroed_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - if (tmp_buf) - free_page(page); - else - tmp_buf = (unsigned char *) page; - } - /* * If the port is the middle of closing, bail out now */ -- cgit v1.2.3 From 98e3a9e6dd99f1b8ac2a03b8b4942eec16ef911b Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:30 +0100 Subject: TTY: simserial, stop using serial_state->{line,icount} * instead of line, use tty->index or an iterator * icount is not made public, only the tx path increments it Signed-off-by: Jiri Slaby Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 45df0f427864..3698a2fe221d 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -176,7 +176,6 @@ static void transmit_chars(struct tty_struct *tty, struct serial_state *info, console->write(console, &c, 1); - info->icount.tx++; info->x_char = 0; goto out; @@ -478,7 +477,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) } if (--info->tport.count < 0) { printk(KERN_ERR "rs_close: bad serial port count for ttys%d: %d\n", - info->line, info->tport.count); + tty->index, info->tport.count); info->tport.count = 0; } if (info->tport.count) { @@ -669,19 +668,14 @@ static int rs_open(struct tty_struct *tty, struct file * filp) * /proc fs routines.... */ -static inline void line_info(struct seq_file *m, struct serial_state *state) -{ - seq_printf(m, "%d: uart:16550 port:3F8 irq:%d\n", - state->line, state->irq); -} - static int rs_proc_show(struct seq_file *m, void *v) { int i; seq_printf(m, "simserinfo:1.0 driver:%s\n", serial_version); for (i = 0; i < NR_PORTS; i++) - line_info(m, &rs_table[i]); + seq_printf(m, "%d: uart:16550 port:3F8 irq:%d\n", + i, rs_table[i].irq); return 0; } @@ -786,8 +780,7 @@ static int __init simrs_init(void) state->irq = retval; /* the port is imaginary */ - printk(KERN_INFO "ttyS%d at 0x03f8 (irq = %d) is a 16550\n", - state->line, state->irq); + printk(KERN_INFO "ttyS0 at 0x03f8 (irq = %d) is a 16550\n", state->irq); retval = tty_register_driver(hp_simserial_driver); if (retval) { -- cgit v1.2.3 From 3c4782dcd9b8d02e79f0f0bd1fe6e30a79790526 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:31 +0100 Subject: TTY: simserial no longer needs serialP Let's do a spin-off of serial_state structure with only needed elements. And remove serialP crap from includes. Signed-off-by: Jiri Slaby Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 9 ++++++++- include/linux/serialP.h | 2 -- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 3698a2fe221d..120aad4d5362 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -27,10 +27,10 @@ #include #include #include +#include #include #include #include -#include #include #include @@ -46,6 +46,13 @@ #define NR_PORTS 1 /* only one port for now */ +struct serial_state { + struct tty_port tport; + struct circ_buf xmit; + int irq; + int x_char; +}; + static char *serial_name = "SimSerial driver"; static char *serial_version = "0.6"; diff --git a/include/linux/serialP.h b/include/linux/serialP.h index e5e8442c08d6..9a04dec1589a 100644 --- a/include/linux/serialP.h +++ b/include/linux/serialP.h @@ -44,10 +44,8 @@ struct serial_state { int quot; int IER; /* Interrupt Enable Register */ int MCR; /* Modem control register */ - /* simserial */ int x_char; /* xon/xoff character */ struct circ_buf xmit; - /* /simserial */ /* /amiserial */ }; -- cgit v1.2.3 From 7f32f8dd349bae106eccb0b9759c932875d6622e Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:32 +0100 Subject: TTY: simserial, define local tty_port pointer And use it to make the code more readable. Since tport doesn't conflict with port anymore and there are not many tport accessors left, do also s/\/port/g. Signed-off-by: Jiri Slaby Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 84 +++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 40 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 120aad4d5362..909357e32c8d 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -47,7 +47,7 @@ #define NR_PORTS 1 /* only one port for now */ struct serial_state { - struct tty_port tport; + struct tty_port port; struct circ_buf xmit; int irq; int x_char; @@ -132,8 +132,9 @@ static void receive_chars(struct tty_struct *tty) static irqreturn_t rs_interrupt_single(int irq, void *dev_id) { struct serial_state *info = dev_id; + struct tty_struct *tty = info->port.tty; - if (!info->tport.tty) { + if (!tty) { printk(KERN_INFO "simrs_interrupt_single: info|tty=0 info=%p problem\n", info); return IRQ_NONE; } @@ -141,7 +142,7 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id) * pretty simple in our case, because we only get interrupts * on inbound traffic */ - receive_chars(info->tport.tty); + receive_chars(tty); return IRQ_HANDLED; } @@ -416,7 +417,7 @@ static void shutdown(struct tty_struct *tty, struct serial_state *info) { unsigned long flags; - if (!(info->tport.flags & ASYNC_INITIALIZED)) + if (!(info->port.flags & ASYNC_INITIALIZED)) return; #ifdef SIMSERIAL_DEBUG @@ -436,7 +437,7 @@ static void shutdown(struct tty_struct *tty, struct serial_state *info) set_bit(TTY_IO_ERROR, &tty->flags); - info->tport.flags &= ~ASYNC_INITIALIZED; + info->port.flags &= ~ASYNC_INITIALIZED; } local_irq_restore(flags); } @@ -454,6 +455,7 @@ static void shutdown(struct tty_struct *tty, struct serial_state *info) static void rs_close(struct tty_struct *tty, struct file * filp) { struct serial_state *info = tty->driver_data; + struct tty_port *port = &info->port; unsigned long flags; if (!info) @@ -468,30 +470,30 @@ static void rs_close(struct tty_struct *tty, struct file * filp) return; } #ifdef SIMSERIAL_DEBUG - printk("rs_close ttys%d, count = %d\n", info->line, info->tport.count); + printk("rs_close ttys%d, count = %d\n", info->line, port->count); #endif - if ((tty->count == 1) && (info->tport.count != 1)) { + if ((tty->count == 1) && (port->count != 1)) { /* * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. info->tport.count should always + * structure will be freed. port->count should always * be one in these conditions. If it's greater than * one, we've got real problems, since it means the * serial port won't be shutdown. */ printk(KERN_ERR "rs_close: bad serial port count; tty->count is 1, " - "info->tport.count is %d\n", info->tport.count); - info->tport.count = 1; + "port->count is %d\n", port->count); + port->count = 1; } - if (--info->tport.count < 0) { + if (--port->count < 0) { printk(KERN_ERR "rs_close: bad serial port count for ttys%d: %d\n", - tty->index, info->tport.count); - info->tport.count = 0; + tty->index, port->count); + port->count = 0; } - if (info->tport.count) { + if (port->count) { local_irq_restore(flags); return; } - info->tport.flags |= ASYNC_CLOSING; + port->flags |= ASYNC_CLOSING; local_irq_restore(flags); /* @@ -501,14 +503,14 @@ static void rs_close(struct tty_struct *tty, struct file * filp) shutdown(tty, info); rs_flush_buffer(tty); tty_ldisc_flush(tty); - info->tport.tty = NULL; - if (info->tport.blocked_open) { - if (info->tport.close_delay) - schedule_timeout_interruptible(info->tport.close_delay); - wake_up_interruptible(&info->tport.open_wait); + port->tty = NULL; + if (port->blocked_open) { + if (port->close_delay) + schedule_timeout_interruptible(port->close_delay); + wake_up_interruptible(&port->open_wait); } - info->tport.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&info->tport.close_wait); + port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); + wake_up_interruptible(&port->close_wait); } /* @@ -525,26 +527,27 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) static void rs_hangup(struct tty_struct *tty) { struct serial_state *info = tty->driver_data; + struct tty_port *port = &info->port; #ifdef SIMSERIAL_DEBUG printk("rs_hangup: called\n"); #endif rs_flush_buffer(tty); - if (info->tport.flags & ASYNC_CLOSING) + if (port->flags & ASYNC_CLOSING) return; shutdown(tty, info); - info->tport.count = 0; - info->tport.flags &= ~ASYNC_NORMAL_ACTIVE; - info->tport.tty = NULL; - wake_up_interruptible(&info->tport.open_wait); + port->count = 0; + port->flags &= ~ASYNC_NORMAL_ACTIVE; + port->tty = NULL; + wake_up_interruptible(&port->open_wait); } static int startup(struct tty_struct *tty, struct serial_state *state) { - struct tty_port *port = &state->tport; + struct tty_port *port = &state->port; unsigned long flags; int retval=0; unsigned long page; @@ -622,26 +625,27 @@ errout: static int rs_open(struct tty_struct *tty, struct file * filp) { struct serial_state *info = rs_table + tty->index; - int retval; + struct tty_port *port = &info->port; + int retval; - info->tport.count++; - info->tport.tty = tty; + port->count++; + port->tty = tty; tty->driver_data = info; - tty->port = &info->tport; + tty->port = port; #ifdef SIMSERIAL_DEBUG - printk("rs_open %s, count = %d\n", tty->name, info->tport.count); + printk("rs_open %s, count = %d\n", tty->name, port->count); #endif - tty->low_latency = (info->tport.flags & ASYNC_LOW_LATENCY) ? 1 : 0; + tty->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; /* * If the port is the middle of closing, bail out now */ - if (tty_hung_up_p(filp) || (info->tport.flags & ASYNC_CLOSING)) { - if (info->tport.flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->tport.close_wait); + if (tty_hung_up_p(filp) || (port->flags & ASYNC_CLOSING)) { + if (port->flags & ASYNC_CLOSING) + interruptible_sleep_on(&port->close_wait); #ifdef SERIAL_DO_RESTART - return ((info->tport.flags & ASYNC_HUP_NOTIFY) ? + return ((port->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); #else return -EAGAIN; @@ -774,8 +778,8 @@ static int __init simrs_init(void) * Let's have a little bit of fun ! */ state = rs_table; - tty_port_init(&state->tport); - state->tport.close_delay = 0; /* XXX really 0? */ + tty_port_init(&state->port); + state->port.close_delay = 0; /* XXX really 0? */ retval = hpsim_get_irq(KEYBOARD_INTR); if (retval < 0) { -- cgit v1.2.3 From 2fcd5caf6d9dbf274ac7ef277f1cc541f1be9784 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:33 +0100 Subject: TTY: simserial, remove some tty ops All ->start, ->stop and ->wait_until_sent are empty and need not be defined. The time to remove them is now. Signed-off-by: Jiri Slaby Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 39 +-------------------------------------- 1 file changed, 1 insertion(+), 38 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 909357e32c8d..d173dba306df 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -64,32 +64,7 @@ static struct console *console; extern struct console *console_drivers; /* from kernel/printk.c */ -/* - * ------------------------------------------------------------ - * rs_stop() and rs_start() - * - * This routines are called before setting or resetting tty->stopped. - * They enable or disable transmitter interrupts, as necessary. - * ------------------------------------------------------------ - */ -static void rs_stop(struct tty_struct *tty) -{ -#ifdef SIMSERIAL_DEBUG - printk("rs_stop: tty->stopped=%d tty->hw_stopped=%d tty->flow_stopped=%d\n", - tty->stopped, tty->hw_stopped, tty->flow_stopped); -#endif - -} - -static void rs_start(struct tty_struct *tty) -{ -#ifdef SIMSERIAL_DEBUG - printk("rs_start: tty->stopped=%d tty->hw_stopped=%d tty->flow_stopped=%d\n", - tty->stopped, tty->hw_stopped, tty->flow_stopped); -#endif -} - -static void receive_chars(struct tty_struct *tty) +static void receive_chars(struct tty_struct *tty) { unsigned char ch; static unsigned char seen_esc = 0; @@ -406,7 +381,6 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) { tty->hw_stopped = 0; - rs_start(tty); } } /* @@ -513,14 +487,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp) wake_up_interruptible(&port->close_wait); } -/* - * rs_wait_until_sent() --- wait until the transmitter is empty - */ -static void rs_wait_until_sent(struct tty_struct *tty, int timeout) -{ -} - - /* * rs_hangup() --- called by tty_hangup() when a hangup is signaled. */ @@ -736,10 +702,7 @@ static const struct tty_operations hp_ops = { .unthrottle = rs_unthrottle, .send_xchar = rs_send_xchar, .set_termios = rs_set_termios, - .stop = rs_stop, - .start = rs_start, .hangup = rs_hangup, - .wait_until_sent = rs_wait_until_sent, .proc_fops = &rs_proc_fops, }; -- cgit v1.2.3 From 37343030458c0eea3f1093b09fc604d4f300eac7 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:34 +0100 Subject: TTY: simserial, use tty_port_close_end The code is identical except locking. But added locks to protect counts do not hurt here. Rather the contrary. Signed-off-by: Jiri Slaby Cc: Tony Luck Cc: Fenghua Yu --- arch/ia64/hp/sim/simserial.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index d173dba306df..53db99af43a2 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -478,13 +478,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp) rs_flush_buffer(tty); tty_ldisc_flush(tty); port->tty = NULL; - if (port->blocked_open) { - if (port->close_delay) - schedule_timeout_interruptible(port->close_delay); - wake_up_interruptible(&port->open_wait); - } - port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&port->close_wait); + + tty_port_close_end(port, tty); } /* @@ -706,6 +701,9 @@ static const struct tty_operations hp_ops = { .proc_fops = &rs_proc_fops, }; +static const struct tty_port_operations hp_port_ops = { +}; + /* * The serial driver boot-time initialization code! */ @@ -742,6 +740,7 @@ static int __init simrs_init(void) */ state = rs_table; tty_port_init(&state->port); + state->port.ops = &hp_port_ops; state->port.close_delay = 0; /* XXX really 0? */ retval = hpsim_get_irq(KEYBOARD_INTR); -- cgit v1.2.3 From 78e74d778a9b3ed80bb73b65ab16f842f48aa287 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:35 +0100 Subject: TTY: simserial, use tty_port_close_start I.e. remove more copied bloat. The only change is that we wait_until_sent now. Which is what we really should do. Signed-off-by: Jiri Slaby Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 36 +----------------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 53db99af43a2..2cd6d23dfdee 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -430,45 +430,12 @@ static void rs_close(struct tty_struct *tty, struct file * filp) { struct serial_state *info = tty->driver_data; struct tty_port *port = &info->port; - unsigned long flags; if (!info) return; - local_irq_save(flags); - if (tty_hung_up_p(filp)) { -#ifdef SIMSERIAL_DEBUG - printk("rs_close: hung_up\n"); -#endif - local_irq_restore(flags); - return; - } -#ifdef SIMSERIAL_DEBUG - printk("rs_close ttys%d, count = %d\n", info->line, port->count); -#endif - if ((tty->count == 1) && (port->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. port->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - printk(KERN_ERR "rs_close: bad serial port count; tty->count is 1, " - "port->count is %d\n", port->count); - port->count = 1; - } - if (--port->count < 0) { - printk(KERN_ERR "rs_close: bad serial port count for ttys%d: %d\n", - tty->index, port->count); - port->count = 0; - } - if (port->count) { - local_irq_restore(flags); + if (tty_port_close_start(port, tty, filp) == 0) return; - } - port->flags |= ASYNC_CLOSING; - local_irq_restore(flags); /* * Now we wait for the transmit buffer to clear; and we notify @@ -476,7 +443,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp) */ shutdown(tty, info); rs_flush_buffer(tty); - tty_ldisc_flush(tty); port->tty = NULL; tty_port_close_end(port, tty); -- cgit v1.2.3 From 3a5c24232463b4978acf8d8668becbf515d30a36 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:36 +0100 Subject: TTY: simserial, properly refcount tty_port->tty So that we will not be surprised in the ISR anymore. Signed-off-by: Jiri Slaby Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 2cd6d23dfdee..b3ec91c9fc71 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -107,7 +107,7 @@ static void receive_chars(struct tty_struct *tty) static irqreturn_t rs_interrupt_single(int irq, void *dev_id) { struct serial_state *info = dev_id; - struct tty_struct *tty = info->port.tty; + struct tty_struct *tty = tty_port_tty_get(&info->port); if (!tty) { printk(KERN_INFO "simrs_interrupt_single: info|tty=0 info=%p problem\n", info); @@ -118,6 +118,7 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id) * on inbound traffic */ receive_chars(tty); + tty_kref_put(tty); return IRQ_HANDLED; } @@ -443,9 +444,9 @@ static void rs_close(struct tty_struct *tty, struct file * filp) */ shutdown(tty, info); rs_flush_buffer(tty); - port->tty = NULL; tty_port_close_end(port, tty); + tty_port_tty_set(port, NULL); } /* @@ -467,7 +468,7 @@ static void rs_hangup(struct tty_struct *tty) port->count = 0; port->flags &= ~ASYNC_NORMAL_ACTIVE; - port->tty = NULL; + tty_port_tty_set(port, NULL); wake_up_interruptible(&port->open_wait); } @@ -556,7 +557,7 @@ static int rs_open(struct tty_struct *tty, struct file * filp) int retval; port->count++; - port->tty = tty; + tty_port_tty_set(port, tty); tty->driver_data = info; tty->port = port; -- cgit v1.2.3 From 9aead90a7f5772fc74f733242d953688748b0ce4 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:37 +0100 Subject: TTY: simserial, use tty_port_open So now we convert startup to be ->activate of tty_port. This means we no longer care about INITIALIZED and TTY_IO_ERROR flags. After we have ->activate much of the code may go as it duplicates what tty_port_open does. In this case tty_port_open adds block_til_ready to the path. But we do not define carrier hooks, so it is a noop. Signed-off-by: Jiri Slaby Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 64 ++++---------------------------------------- 1 file changed, 5 insertions(+), 59 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index b3ec91c9fc71..e9c5fb7b923d 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -473,9 +473,10 @@ static void rs_hangup(struct tty_struct *tty) } -static int startup(struct tty_struct *tty, struct serial_state *state) +static int activate(struct tty_port *port, struct tty_struct *tty) { - struct tty_port *port = &state->port; + struct serial_state *state = container_of(port, struct serial_state, + port); unsigned long flags; int retval=0; unsigned long page; @@ -486,20 +487,11 @@ static int startup(struct tty_struct *tty, struct serial_state *state) local_irq_save(flags); - if (port->flags & ASYNC_INITIALIZED) { - free_page(page); - goto errout; - } - if (state->xmit.buf) free_page(page); else state->xmit.buf = (unsigned char *) page; -#ifdef SIMSERIAL_DEBUG - printk("startup: ttys%d (irq %d)...", state->line, state->irq); -#endif - /* * Allocate the IRQ if necessary */ @@ -510,18 +502,8 @@ static int startup(struct tty_struct *tty, struct serial_state *state) goto errout; } - clear_bit(TTY_IO_ERROR, &tty->flags); - state->xmit.head = state->xmit.tail = 0; -#if 0 - /* - * Set up serial timers... - */ - timer_table[RS_TIMER].expires = jiffies + 2*HZ/100; - timer_active |= 1 << RS_TIMER; -#endif - /* * Set up the tty->alt_speed kludge */ @@ -534,10 +516,6 @@ static int startup(struct tty_struct *tty, struct serial_state *state) if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) tty->alt_speed = 460800; - port->flags |= ASYNC_INITIALIZED; - local_irq_restore(flags); - return 0; - errout: local_irq_restore(flags); return retval; @@ -554,40 +532,10 @@ static int rs_open(struct tty_struct *tty, struct file * filp) { struct serial_state *info = rs_table + tty->index; struct tty_port *port = &info->port; - int retval; - port->count++; - tty_port_tty_set(port, tty); tty->driver_data = info; - tty->port = port; - -#ifdef SIMSERIAL_DEBUG - printk("rs_open %s, count = %d\n", tty->name, port->count); -#endif tty->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; - /* - * If the port is the middle of closing, bail out now - */ - if (tty_hung_up_p(filp) || (port->flags & ASYNC_CLOSING)) { - if (port->flags & ASYNC_CLOSING) - interruptible_sleep_on(&port->close_wait); -#ifdef SERIAL_DO_RESTART - return ((port->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); -#else - return -EAGAIN; -#endif - } - - /* - * Start up serial port - */ - retval = startup(tty, info); - if (retval) { - return retval; - } - /* * figure out which console to use (should be one already) */ @@ -597,10 +545,7 @@ static int rs_open(struct tty_struct *tty, struct file * filp) console = console->next; } -#ifdef SIMSERIAL_DEBUG - printk("rs_open ttys%d successful\n", info->line); -#endif - return 0; + return tty_port_open(port, tty, filp); } /* @@ -669,6 +614,7 @@ static const struct tty_operations hp_ops = { }; static const struct tty_port_operations hp_port_ops = { + .activate = activate, }; /* -- cgit v1.2.3 From 458cd31a4c33ce489eb538193f801ac73ff4010b Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:38 +0100 Subject: TTY: simserial, use tty_port_hangup Convert shutdown to be tty_port_operations->shutdown. Then we can use tty_port_hangup. (And we have to use tty_port_close.) This means we no longer touch ASYNC_INITIALIZED, TTY_IO_ERROR. Also we do not need to do any peculiar TTY logic in the file now. Signed-off-by: Jiri Slaby Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 64 +++++--------------------------------------- 1 file changed, 7 insertions(+), 57 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index e9c5fb7b923d..323c9325e570 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -388,17 +388,11 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) * This routine will shutdown a serial port; interrupts are disabled, and * DTR is dropped if the hangup on close termio flag is on. */ -static void shutdown(struct tty_struct *tty, struct serial_state *info) +static void shutdown(struct tty_port *port) { - unsigned long flags; - - if (!(info->port.flags & ASYNC_INITIALIZED)) - return; - -#ifdef SIMSERIAL_DEBUG - printk("Shutting down serial port %d (irq %d)...\n", info->line, - info->irq); -#endif + struct serial_state *info = container_of(port, struct serial_state, + port); + unsigned long flags; local_irq_save(flags); { @@ -409,70 +403,25 @@ static void shutdown(struct tty_struct *tty, struct serial_state *info) free_page((unsigned long) info->xmit.buf); info->xmit.buf = NULL; } - - set_bit(TTY_IO_ERROR, &tty->flags); - - info->port.flags &= ~ASYNC_INITIALIZED; } local_irq_restore(flags); } -/* - * ------------------------------------------------------------ - * rs_close() - * - * This routine is called when the serial port gets closed. First, we - * wait for the last remaining data to be sent. Then, we unlink its - * async structure from the interrupt chain if necessary, and we free - * that IRQ if nothing is left in the chain. - * ------------------------------------------------------------ - */ static void rs_close(struct tty_struct *tty, struct file * filp) { struct serial_state *info = tty->driver_data; - struct tty_port *port = &info->port; - - if (!info) - return; - - if (tty_port_close_start(port, tty, filp) == 0) - return; - - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - shutdown(tty, info); - rs_flush_buffer(tty); - tty_port_close_end(port, tty); - tty_port_tty_set(port, NULL); + tty_port_close(&info->port, tty, filp); } -/* - * rs_hangup() --- called by tty_hangup() when a hangup is signaled. - */ static void rs_hangup(struct tty_struct *tty) { struct serial_state *info = tty->driver_data; - struct tty_port *port = &info->port; - -#ifdef SIMSERIAL_DEBUG - printk("rs_hangup: called\n"); -#endif rs_flush_buffer(tty); - if (port->flags & ASYNC_CLOSING) - return; - shutdown(tty, info); - - port->count = 0; - port->flags &= ~ASYNC_NORMAL_ACTIVE; - tty_port_tty_set(port, NULL); - wake_up_interruptible(&port->open_wait); + tty_port_hangup(&info->port); } - static int activate(struct tty_port *port, struct tty_struct *tty) { struct serial_state *state = container_of(port, struct serial_state, @@ -615,6 +564,7 @@ static const struct tty_operations hp_ops = { static const struct tty_port_operations hp_port_ops = { .activate = activate, + .shutdown = shutdown, }; /* -- cgit v1.2.3 From adb636fe0845bf1b4dbcb546a1673f40a95062fd Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:39 +0100 Subject: TTY: simserial, remove useless comments Or the obsolete ones like: "Let's have a little bit of fun" I have never had fun with software. For fun, one needs hard-ware. Signed-off-by: Jiri Slaby Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 323c9325e570..d8237c341995 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -4,16 +4,11 @@ * This driver is mostly used for bringup purposes and will go away. * It has a strong dependency on the system console. All outputs * are rerouted to the same facility as the one used by printk which, in our - * case means sys_sim.c console (goes via the simulator). The code hereafter - * is completely leveraged from the serial.c driver. + * case means sys_sim.c console (goes via the simulator). * * Copyright (C) 1999-2000, 2002-2003 Hewlett-Packard Co * Stephane Eranian * David Mosberger-Tang - * - * 02/04/00 D. Mosberger Merged in serial.c bug fixes in rs_close(). - * 02/25/00 D. Mosberger Synced up with 2.3.99pre-5 version of serial.c. - * 07/30/02 D. Mosberger Replace sti()/cli() with explicit spinlocks & local irq masking */ #include @@ -441,9 +436,6 @@ static int activate(struct tty_port *port, struct tty_struct *tty) else state->xmit.buf = (unsigned char *) page; - /* - * Allocate the IRQ if necessary - */ if (state->irq) { retval = request_irq(state->irq, rs_interrupt_single, 0, "simserial", state); @@ -525,19 +517,6 @@ static const struct file_operations rs_proc_fops = { .release = single_release, }; -/* - * --------------------------------------------------------------------- - * rs_init() and friends - * - * rs_init() is called at boot-time to initialize the serial driver. - * --------------------------------------------------------------------- - */ - -/* - * This routine prints out the appropriate serial driver version - * number, and identifies which options were configured into this - * driver. - */ static inline void show_serial_version(void) { printk(KERN_INFO "%s version %s with", serial_name, serial_version); @@ -567,9 +546,6 @@ static const struct tty_port_operations hp_port_ops = { .shutdown = shutdown, }; -/* - * The serial driver boot-time initialization code! - */ static int __init simrs_init(void) { struct serial_state *state; @@ -598,9 +574,6 @@ static int __init simrs_init(void) hp_simserial_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(hp_simserial_driver, &hp_ops); - /* - * Let's have a little bit of fun ! - */ state = rs_table; tty_port_init(&state->port); state->port.ops = &hp_port_ops; -- cgit v1.2.3 From 8b916330567b0b788f35ded5d99a7ef7dc30b293 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:40 +0100 Subject: TTY: simserial, fix includes Use headers from linux/* instead of asm/. Remove declaration of console_drivers, it's in linux/console.h already. Signed-off-by: Jiri Slaby Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index d8237c341995..24d6ca04de86 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -24,14 +24,13 @@ #include #include #include +#include #include #include #include +#include -#include #include -#include -#include #include "hpsim_ssc.h" @@ -57,8 +56,6 @@ struct tty_driver *hp_simserial_driver; static struct console *console; -extern struct console *console_drivers; /* from kernel/printk.c */ - static void receive_chars(struct tty_struct *tty) { unsigned char ch; -- cgit v1.2.3 From f66279cd7d5cdf43686da0d9ed20378581b88d0f Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:41 +0100 Subject: TTY: simserial, reindent some code Make the code to conform to the standard. Also make it readable. Signed-off-by: Jiri Slaby Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 120 ++++++++++++++++--------------------------- 1 file changed, 44 insertions(+), 76 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 24d6ca04de86..516ad09f3131 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -62,28 +62,25 @@ static void receive_chars(struct tty_struct *tty) static unsigned char seen_esc = 0; while ( (ch = ia64_ssc(0, 0, 0, 0, SSC_GETCHAR)) ) { - if ( ch == 27 && seen_esc == 0 ) { + if (ch == 27 && seen_esc == 0) { seen_esc = 1; continue; - } else { - if ( seen_esc==1 && ch == 'O' ) { - seen_esc = 2; - continue; - } else if ( seen_esc == 2 ) { - if ( ch == 'P' ) /* F1 */ - show_state(); + } else if (seen_esc == 1 && ch == 'O') { + seen_esc = 2; + continue; + } else if (seen_esc == 2) { + if (ch == 'P') /* F1 */ + show_state(); #ifdef CONFIG_MAGIC_SYSRQ - if ( ch == 'S' ) { /* F4 */ - do - ch = ia64_ssc(0, 0, 0, 0, - SSC_GETCHAR); - while (!ch); - handle_sysrq(ch); - } -#endif - seen_esc = 0; - continue; + if (ch == 'S') { /* F4 */ + do { + ch = ia64_ssc(0, 0, 0, 0, SSC_GETCHAR); + } while (!ch); + handle_sysrq(ch); } +#endif + seen_esc = 0; + continue; } seen_esc = 0; @@ -195,8 +192,8 @@ static void rs_flush_chars(struct tty_struct *tty) { struct serial_state *info = tty->driver_data; - if (info->xmit.head == info->xmit.tail || tty->stopped || tty->hw_stopped || - !info->xmit.buf) + if (info->xmit.head == info->xmit.tail || tty->stopped || + tty->hw_stopped || !info->xmit.buf) return; transmit_chars(tty, info, NULL); @@ -232,10 +229,10 @@ static int rs_write(struct tty_struct * tty, /* * Hey, we transmit directly from here in our case */ - if (CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) - && !tty->stopped && !tty->hw_stopped) { + if (CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) && + !tty->stopped && !tty->hw_stopped) transmit_chars(tty, info, NULL); - } + return ret; } @@ -293,7 +290,8 @@ static void rs_send_xchar(struct tty_struct *tty, char ch) */ static void rs_throttle(struct tty_struct * tty) { - if (I_IXOFF(tty)) rs_send_xchar(tty, STOP_CHAR(tty)); + if (I_IXOFF(tty)) + rs_send_xchar(tty, STOP_CHAR(tty)); printk(KERN_INFO "simrs_throttle called\n"); } @@ -322,48 +320,21 @@ static int rs_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) } switch (cmd) { - case TIOCGSERIAL: - printk(KERN_INFO "simrs_ioctl TIOCGSERIAL called\n"); - return 0; - case TIOCSSERIAL: - printk(KERN_INFO "simrs_ioctl TIOCSSERIAL called\n"); - return 0; - case TIOCSERCONFIG: - printk(KERN_INFO "rs_ioctl: TIOCSERCONFIG called\n"); - return -EINVAL; - - case TIOCSERGETLSR: /* Get line status register */ - printk(KERN_INFO "rs_ioctl: TIOCSERGETLSR called\n"); - return -EINVAL; - - case TIOCSERGSTRUCT: - printk(KERN_INFO "rs_ioctl: TIOCSERGSTRUCT called\n"); -#if 0 - if (copy_to_user((struct async_struct *) arg, - info, sizeof(struct async_struct))) - return -EFAULT; -#endif - return 0; - - /* - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - * - mask passed in arg for lines of interest - * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) - * Caller should use TIOCGICOUNT to see which one it was - */ - case TIOCMIWAIT: - printk(KERN_INFO "rs_ioctl: TIOCMIWAIT: called\n"); - return 0; - case TIOCSERGWILD: - case TIOCSERSWILD: - /* "setserial -W" is called in Debian boot */ - printk (KERN_INFO "TIOCSER?WILD ioctl obsolete, ignored.\n"); - return 0; - - default: - return -ENOIOCTLCMD; - } - return 0; + case TIOCGSERIAL: + case TIOCSSERIAL: + case TIOCSERGSTRUCT: + case TIOCMIWAIT: + return 0; + case TIOCSERCONFIG: + case TIOCSERGETLSR: /* Get line status register */ + return -EINVAL; + case TIOCSERGWILD: + case TIOCSERSWILD: + /* "setserial -W" is called in Debian boot */ + printk (KERN_INFO "TIOCSER?WILD ioctl obsolete, ignored.\n"); + return 0; + } + return -ENOIOCTLCMD; } #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) @@ -387,14 +358,12 @@ static void shutdown(struct tty_port *port) unsigned long flags; local_irq_save(flags); - { - if (info->irq) - free_irq(info->irq, info); + if (info->irq) + free_irq(info->irq, info); - if (info->xmit.buf) { - free_page((unsigned long) info->xmit.buf); - info->xmit.buf = NULL; - } + if (info->xmit.buf) { + free_page((unsigned long) info->xmit.buf); + info->xmit.buf = NULL; } local_irq_restore(flags); } @@ -418,9 +387,8 @@ static int activate(struct tty_port *port, struct tty_struct *tty) { struct serial_state *state = container_of(port, struct serial_state, port); - unsigned long flags; - int retval=0; - unsigned long page; + unsigned long flags, page; + int retval = 0; page = get_zeroed_page(GFP_KERNEL); if (!page) -- cgit v1.2.3 From 6e9ebcfa20b15f0ccdd4b5395a3c63f79c21fa57 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:42 +0100 Subject: TTY: simserial, final cleanup * remove pointless checks (tty cannot be NULL at that points) * fix some printks (use __func__, print text directly w/o using global strings) * remove some empty lines This is the last patch for simserial. Overall, the driver is 400 lines shorter. Being now at 560 lines. It was tested using ski with a busybox userspace. Signed-off-by: Jiri Slaby Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 516ad09f3131..c34785dca92b 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -47,9 +47,6 @@ struct serial_state { int x_char; }; -static char *serial_name = "SimSerial driver"; -static char *serial_version = "0.6"; - static struct serial_state rs_table[NR_PORTS]; struct tty_driver *hp_simserial_driver; @@ -99,7 +96,7 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id) struct tty_struct *tty = tty_port_tty_get(&info->port); if (!tty) { - printk(KERN_INFO "simrs_interrupt_single: info|tty=0 info=%p problem\n", info); + printk(KERN_INFO "%s: tty=0 problem\n", __func__); return IRQ_NONE; } /* @@ -122,7 +119,7 @@ static int rs_put_char(struct tty_struct *tty, unsigned char ch) struct serial_state *info = tty->driver_data; unsigned long flags; - if (!tty || !info->xmit.buf) + if (!info->xmit.buf) return 0; local_irq_save(flags); @@ -199,7 +196,6 @@ static void rs_flush_chars(struct tty_struct *tty) transmit_chars(tty, info, NULL); } - static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) { @@ -207,7 +203,7 @@ static int rs_write(struct tty_struct * tty, int c, ret = 0; unsigned long flags; - if (!tty || !info->xmit.buf) + if (!info->xmit.buf) return 0; local_irq_save(flags); @@ -309,7 +305,6 @@ static void rs_unthrottle(struct tty_struct * tty) printk(KERN_INFO "simrs_unthrottle called\n"); } - static int rs_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && @@ -462,7 +457,7 @@ static int rs_proc_show(struct seq_file *m, void *v) { int i; - seq_printf(m, "simserinfo:1.0 driver:%s\n", serial_version); + seq_printf(m, "simserinfo:1.0\n"); for (i = 0; i < NR_PORTS; i++) seq_printf(m, "%d: uart:16550 port:3F8 irq:%d\n", i, rs_table[i].irq); @@ -482,12 +477,6 @@ static const struct file_operations rs_proc_fops = { .release = single_release, }; -static inline void show_serial_version(void) -{ - printk(KERN_INFO "%s version %s with", serial_name, serial_version); - printk(KERN_INFO " no serial options enabled\n"); -} - static const struct tty_operations hp_ops = { .open = rs_open, .close = rs_close, @@ -523,7 +512,7 @@ static int __init simrs_init(void) if (!hp_simserial_driver) return -ENOMEM; - show_serial_version(); + printk(KERN_INFO "SimSerial driver with no serial options enabled\n"); /* Initialize the tty_driver structure */ -- cgit v1.2.3 From e380a81e34375a38f253b42394ef06ca3127559f Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:50 +0100 Subject: TTY: pdc_cons, fix racy tty test The tty->count test in the timer was racy. Let's remove the test and properly delete the timer and wait for the body to finish using _sync version of del_timer. Signed-off-by: Jiri Slaby Cc: Kyle McMartin Cc: Helge Deller Cc: "James E.J. Bottomley" Signed-off-by: Greg Kroah-Hartman --- arch/parisc/kernel/pdc_cons.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c index fc770be465ff..c1db65fc4525 100644 --- a/arch/parisc/kernel/pdc_cons.c +++ b/arch/parisc/kernel/pdc_cons.c @@ -103,7 +103,7 @@ static int pdc_console_tty_open(struct tty_struct *tty, struct file *filp) static void pdc_console_tty_close(struct tty_struct *tty, struct file *filp) { if (!tty->count) - del_timer(&pdc_console_timer); + del_timer_sync(&pdc_console_timer); } static int pdc_console_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) @@ -153,7 +153,7 @@ static void pdc_console_poll(unsigned long unused) if (count) tty_flip_buffer_push(tty); - if (tty->count && (pdc_cons.flags & CON_ENABLED)) + if (pdc_cons.flags & CON_ENABLED) mod_timer(&pdc_console_timer, jiffies + PDC_CONS_POLL_DELAY); } -- cgit v1.2.3 From 52b762f7a94c88e5a8aa2be67a06a6f01020cc82 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:51 +0100 Subject: TTY: pdc_cons, fix open vs timer race The timer is initialized too late. tty->open may fire an invalid timer. So initialize the timer earlier using DEFINE_TIMER. Signed-off-by: Jiri Slaby Cc: Kyle McMartin Cc: Helge Deller Cc: "James E.J. Bottomley" Signed-off-by: Greg Kroah-Hartman --- arch/parisc/kernel/pdc_cons.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c index c1db65fc4525..8ad05215d4b1 100644 --- a/arch/parisc/kernel/pdc_cons.c +++ b/arch/parisc/kernel/pdc_cons.c @@ -90,7 +90,8 @@ static int pdc_console_setup(struct console *co, char *options) #define PDC_CONS_POLL_DELAY (30 * HZ / 1000) -static struct timer_list pdc_console_timer; +static void pdc_console_poll(unsigned long unused); +static DEFINE_TIMER(pdc_console_timer, pdc_console_poll, 0, 0); static int pdc_console_tty_open(struct tty_struct *tty, struct file *filp) { @@ -205,10 +206,6 @@ static int __init pdc_console_tty_driver_init(void) pdc_console_tty_driver = drv; - /* No need to initialize the pdc_console_timer if tty isn't allocated */ - init_timer(&pdc_console_timer); - pdc_console_timer.function = pdc_console_poll; - return 0; } -- cgit v1.2.3 From 0b479d54ae7b79f62f09ef977c2228e579924d38 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:52 +0100 Subject: TTY: pdc_cons, fix open vs pdc_console_tty_driver race Assign the pointer to pdc_console_tty_driver (a tty_driver) earlier. Otherwise the timer may dereference NULL. Signed-off-by: Jiri Slaby Cc: Kyle McMartin Cc: Helge Deller Cc: "James E.J. Bottomley" Signed-off-by: Greg Kroah-Hartman --- arch/parisc/kernel/pdc_cons.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c index 8ad05215d4b1..d14e20fc60df 100644 --- a/arch/parisc/kernel/pdc_cons.c +++ b/arch/parisc/kernel/pdc_cons.c @@ -160,9 +160,7 @@ static void pdc_console_poll(unsigned long unused) static int __init pdc_console_tty_driver_init(void) { - int err; - struct tty_driver *drv; /* Check if the console driver is still registered. * It is unregistered if the pdc console was not selected as the @@ -184,28 +182,27 @@ static int __init pdc_console_tty_driver_init(void) printk(KERN_INFO "The PDC console driver is still registered, removing CON_BOOT flag\n"); pdc_cons.flags &= ~CON_BOOT; - drv = alloc_tty_driver(1); + pdc_console_tty_driver = alloc_tty_driver(1); - if (!drv) + if (!pdc_console_tty_driver) return -ENOMEM; - drv->driver_name = "pdc_cons"; - drv->name = "ttyB"; - drv->major = MUX_MAJOR; - drv->minor_start = 0; - drv->type = TTY_DRIVER_TYPE_SYSTEM; - drv->init_termios = tty_std_termios; - drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS; - tty_set_operations(drv, &pdc_console_tty_ops); - - err = tty_register_driver(drv); + pdc_console_tty_driver->driver_name = "pdc_cons"; + pdc_console_tty_driver->name = "ttyB"; + pdc_console_tty_driver->major = MUX_MAJOR; + pdc_console_tty_driver->minor_start = 0; + pdc_console_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM; + pdc_console_tty_driver->init_termios = tty_std_termios; + pdc_console_tty_driver->flags = TTY_DRIVER_REAL_RAW | + TTY_DRIVER_RESET_TERMIOS; + tty_set_operations(pdc_console_tty_driver, &pdc_console_tty_ops); + + err = tty_register_driver(pdc_console_tty_driver); if (err) { printk(KERN_ERR "Unable to register the PDC console TTY driver\n"); return err; } - pdc_console_tty_driver = drv; - return 0; } -- cgit v1.2.3 From 5dd5bc40f3b6e0ccdaad948dbadc94ad0906cb25 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:53 +0100 Subject: TTY: pdc_cons, use tty_port Instead of digging a tty out of the tty_driver struct, which is not defined to work, use tty_port properly. This includes proper tty refcounting even though there is no possible race currently. But we will need tty_port for tty buffers in the future anyway. Signed-off-by: Jiri Slaby Cc: Kyle McMartin Cc: Helge Deller Cc: "James E.J. Bottomley" Signed-off-by: Greg Kroah-Hartman --- arch/parisc/kernel/pdc_cons.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c index d14e20fc60df..4f004596a6e7 100644 --- a/arch/parisc/kernel/pdc_cons.c +++ b/arch/parisc/kernel/pdc_cons.c @@ -92,10 +92,11 @@ static int pdc_console_setup(struct console *co, char *options) static void pdc_console_poll(unsigned long unused); static DEFINE_TIMER(pdc_console_timer, pdc_console_poll, 0, 0); +static struct tty_port tty_port; static int pdc_console_tty_open(struct tty_struct *tty, struct file *filp) { - + tty_port_tty_set(&tty_port, tty); mod_timer(&pdc_console_timer, jiffies + PDC_CONS_POLL_DELAY); return 0; @@ -103,8 +104,10 @@ static int pdc_console_tty_open(struct tty_struct *tty, struct file *filp) static void pdc_console_tty_close(struct tty_struct *tty, struct file *filp) { - if (!tty->count) + if (!tty->count) { del_timer_sync(&pdc_console_timer); + tty_port_tty_set(&tty_port, NULL); + } } static int pdc_console_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) @@ -123,8 +126,6 @@ static int pdc_console_tty_chars_in_buffer(struct tty_struct *tty) return 0; /* no buffer */ } -static struct tty_driver *pdc_console_tty_driver; - static const struct tty_operations pdc_console_tty_ops = { .open = pdc_console_tty_open, .close = pdc_console_tty_close, @@ -135,10 +136,8 @@ static const struct tty_operations pdc_console_tty_ops = { static void pdc_console_poll(unsigned long unused) { - int data, count = 0; - - struct tty_struct *tty = pdc_console_tty_driver->ttys[0]; + struct tty_struct *tty = tty_port_tty_get(&tty_port); if (!tty) return; @@ -154,10 +153,14 @@ static void pdc_console_poll(unsigned long unused) if (count) tty_flip_buffer_push(tty); + tty_kref_put(tty); + if (pdc_cons.flags & CON_ENABLED) mod_timer(&pdc_console_timer, jiffies + PDC_CONS_POLL_DELAY); } +static struct tty_driver *pdc_console_tty_driver; + static int __init pdc_console_tty_driver_init(void) { int err; @@ -182,6 +185,8 @@ static int __init pdc_console_tty_driver_init(void) printk(KERN_INFO "The PDC console driver is still registered, removing CON_BOOT flag\n"); pdc_cons.flags &= ~CON_BOOT; + tty_port_init(&tty_port); + pdc_console_tty_driver = alloc_tty_driver(1); if (!pdc_console_tty_driver) -- cgit v1.2.3