From 87a6aca504d65f242589583e04df5e74b5eae1fe Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 15 Mar 2010 17:14:15 -0700 Subject: Revert "tty: Add a new VT mode which is like VT_PROCESS but doesn't require a VT_RELDISP ioctl call" This reverts commit eec9fe7d1ab4a0dfac4cb43047a7657fffd0002f. Ari writes as the reason this should be reverted: The problems with this patch include: 1. There's at least one subtlety I overlooked - switching between X servers (i.e. from one X VT to another) still requires the cooperation of both X servers. I was assuming that KMS eliminated this. 2. It hasn't been tested at all (no X server patch exists which uses the new mode). As he was the original author of the patch, I'll revert it. Cc: Ari Entlich Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/char/vt_ioctl.c | 39 +++++++++++++++++++-------------------- include/linux/vt.h | 3 +-- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index 87778dcf872..6aa10284104 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -888,7 +888,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ret = -EFAULT; goto out; } - if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS && tmp.mode != VT_PROCESS_AUTO) { + if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) { ret = -EINVAL; goto out; } @@ -1622,7 +1622,7 @@ static void complete_change_console(struct vc_data *vc) * telling it that it has acquired. Also check if it has died and * clean up (similar to logic employed in change_console()) */ - if (vc->vt_mode.mode == VT_PROCESS || vc->vt_mode.mode == VT_PROCESS_AUTO) { + if (vc->vt_mode.mode == VT_PROCESS) { /* * Send the signal as privileged - kill_pid() will * tell us if the process has gone or something else @@ -1682,7 +1682,7 @@ void change_console(struct vc_data *new_vc) * vt to auto control. */ vc = vc_cons[fg_console].d; - if (vc->vt_mode.mode == VT_PROCESS || vc->vt_mode.mode == VT_PROCESS_AUTO) { + if (vc->vt_mode.mode == VT_PROCESS) { /* * Send the signal as privileged - kill_pid() will * tell us if the process has gone or something else @@ -1693,28 +1693,27 @@ void change_console(struct vc_data *new_vc) */ vc->vt_newvt = new_vc->vc_num; if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) { - if(vc->vt_mode.mode == VT_PROCESS) - /* - * It worked. Mark the vt to switch to and - * return. The process needs to send us a - * VT_RELDISP ioctl to complete the switch. - */ - return; - } else { /* - * The controlling process has died, so we revert back to - * normal operation. In this case, we'll also change back - * to KD_TEXT mode. I'm not sure if this is strictly correct - * but it saves the agony when the X server dies and the screen - * remains blanked due to KD_GRAPHICS! It would be nice to do - * this outside of VT_PROCESS but there is no single process - * to account for and tracking tty count may be undesirable. + * It worked. Mark the vt to switch to and + * return. The process needs to send us a + * VT_RELDISP ioctl to complete the switch. */ - reset_vc(vc); + return; } /* - * Fall through to normal (VT_AUTO and VT_PROCESS_AUTO) handling of the switch... + * The controlling process has died, so we revert back to + * normal operation. In this case, we'll also change back + * to KD_TEXT mode. I'm not sure if this is strictly correct + * but it saves the agony when the X server dies and the screen + * remains blanked due to KD_GRAPHICS! It would be nice to do + * this outside of VT_PROCESS but there is no single process + * to account for and tracking tty count may be undesirable. + */ + reset_vc(vc); + + /* + * Fall through to normal (VT_AUTO) handling of the switch... */ } diff --git a/include/linux/vt.h b/include/linux/vt.h index 778b7b2a47d..d5dd0bc408f 100644 --- a/include/linux/vt.h +++ b/include/linux/vt.h @@ -27,7 +27,7 @@ struct vt_mode { #define VT_SETMODE 0x5602 /* set mode of active vt */ #define VT_AUTO 0x00 /* auto vt switching */ #define VT_PROCESS 0x01 /* process controls switching */ -#define VT_PROCESS_AUTO 0x02 /* process is notified of switching */ +#define VT_ACKACQ 0x02 /* acknowledge switch */ struct vt_stat { unsigned short v_active; /* active vt */ @@ -38,7 +38,6 @@ struct vt_stat { #define VT_SENDSIG 0x5604 /* signal to send to bitmask of vts */ #define VT_RELDISP 0x5605 /* release display */ -#define VT_ACKACQ 0x02 /* acknowledge switch */ #define VT_ACTIVATE 0x5606 /* make vt active */ #define VT_WAITACTIVE 0x5607 /* wait for vt active */ -- cgit v1.2.3-70-g09d2 From 352fa6ad16b89f8ffd1a93b4419b1a8f2259feab Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 2 Mar 2010 22:24:19 +0000 Subject: tty: Take a 256 byte padding into account when buffering below sub-page units The TTY layer takes some care to ensure that only sub-page allocations are made with interrupts disabled. It does this by setting a goal of "TTY_BUFFER_PAGE" to allocate. Unfortunately, while TTY_BUFFER_PAGE takes the size of tty_buffer into account, it fails to account that tty_buffer_find() rounds the buffer size out to the next 256 byte boundary before adding on the size of the tty_buffer. This patch adjusts the TTY_BUFFER_PAGE calculation to take into account the size of the tty_buffer and the padding. Once applied, tty_buffer_alloc() should not require high-order allocations. Signed-off-by: Mel Gorman Cc: stable Signed-off-by: Greg Kroah-Hartman --- include/linux/tty.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/linux/tty.h b/include/linux/tty.h index 568369a8630..593228a520e 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -70,12 +70,13 @@ struct tty_buffer { /* * We default to dicing tty buffer allocations to this many characters - * in order to avoid multiple page allocations. We assume tty_buffer itself - * is under 256 bytes. See tty_buffer_find for the allocation logic this - * must match + * in order to avoid multiple page allocations. We know the size of + * tty_buffer itself but it must also be taken into account that the + * the buffer is 256 byte aligned. See tty_buffer_find for the allocation + * logic this must match */ -#define TTY_BUFFER_PAGE ((PAGE_SIZE - 256) / 2) +#define TTY_BUFFER_PAGE (((PAGE_SIZE - sizeof(struct tty_buffer)) / 2) & ~0xFF) struct tty_bufhead { -- cgit v1.2.3-70-g09d2 From f157b58511e56d418eb582de96fedc4ea03d8061 Mon Sep 17 00:00:00 2001 From: David Miller Date: Wed, 3 Mar 2010 02:50:26 -0800 Subject: uartlite: Fix build on sparc. We can get this driver enabled via MFD_TIMBERDALE which only requires GPIO to be on. But the of_address_to_resource() function is only present on powerpc and microblaze, so we have to conditionalize the CONFIG_OF probing bits on that. Signed-off-by: David S. Miller Acked-by: Grant Likely Signed-off-by: Greg Kroah-Hartman --- drivers/serial/uartlite.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c index ab2ab3c8183..f0a6c61b17f 100644 --- a/drivers/serial/uartlite.c +++ b/drivers/serial/uartlite.c @@ -19,7 +19,7 @@ #include #include #include -#if defined(CONFIG_OF) +#if defined(CONFIG_OF) && (defined(CONFIG_PPC32) || defined(CONFIG_MICROBLAZE)) #include #include #include @@ -581,7 +581,7 @@ static struct platform_driver ulite_platform_driver = { /* --------------------------------------------------------------------- * OF bus bindings */ -#if defined(CONFIG_OF) +#if defined(CONFIG_OF) && (defined(CONFIG_PPC32) || defined(CONFIG_MICROBLAZE)) static int __devinit ulite_of_probe(struct of_device *op, const struct of_device_id *match) { @@ -631,11 +631,11 @@ static inline void __exit ulite_of_unregister(void) { of_unregister_platform_driver(&ulite_of_driver); } -#else /* CONFIG_OF */ -/* CONFIG_OF not enabled; do nothing helpers */ +#else /* CONFIG_OF && (CONFIG_PPC32 || CONFIG_MICROBLAZE) */ +/* Appropriate config not enabled; do nothing helpers */ static inline int __init ulite_of_register(void) { return 0; } static inline void __exit ulite_of_unregister(void) { } -#endif /* CONFIG_OF */ +#endif /* CONFIG_OF && (CONFIG_PPC32 || CONFIG_MICROBLAZE) */ /* --------------------------------------------------------------------- * Module setup/teardown -- cgit v1.2.3-70-g09d2 From e74d098c66543d0731de62eb747ccd5b636a6f4c Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Fri, 12 Mar 2010 11:53:15 +0530 Subject: hvc_console: Fix race between hvc_close and hvc_remove Alan pointed out a race in the code where hvc_remove is invoked. The recent virtio_console work is the first user of hvc_remove(). Alan describes it thus: The hvc_console assumes that a close and remove call can't occur at the same time. In addition tty_hangup(tty) is problematic as tty_hangup is asynchronous itself.... So this can happen hvc_close hvc_remove hung up ? - no lock tty = hp->tty unlock lock hp->tty = NULL unlock notify del kref_put the hvc struct close completes tty is destroyed tty_hangup dead tty tty->ops will be NULL NULL->... This patch adds some tty krefs and also converts to using tty_vhangup(). Reported-by: Alan Cox Signed-off-by: Amit Shah CC: Alan Cox CC: linuxppc-dev@ozlabs.org CC: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- drivers/char/hvc_console.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 465185fc0f5..ba55bba151b 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -312,6 +312,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) spin_lock_irqsave(&hp->lock, flags); /* Check and then increment for fast path open. */ if (hp->count++ > 0) { + tty_kref_get(tty); spin_unlock_irqrestore(&hp->lock, flags); hvc_kick(); return 0; @@ -319,7 +320,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) tty->driver_data = hp; - hp->tty = tty; + hp->tty = tty_kref_get(tty); spin_unlock_irqrestore(&hp->lock, flags); @@ -336,6 +337,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) spin_lock_irqsave(&hp->lock, flags); hp->tty = NULL; spin_unlock_irqrestore(&hp->lock, flags); + tty_kref_put(tty); tty->driver_data = NULL; kref_put(&hp->kref, destroy_hvc_struct); printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc); @@ -363,13 +365,18 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) return; hp = tty->driver_data; + spin_lock_irqsave(&hp->lock, flags); + tty_kref_get(tty); if (--hp->count == 0) { /* We are done with the tty pointer now. */ hp->tty = NULL; spin_unlock_irqrestore(&hp->lock, flags); + /* Put the ref obtained in hvc_open() */ + tty_kref_put(tty); + if (hp->ops->notifier_del) hp->ops->notifier_del(hp, hp->data); @@ -389,6 +396,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) spin_unlock_irqrestore(&hp->lock, flags); } + tty_kref_put(tty); kref_put(&hp->kref, destroy_hvc_struct); } @@ -424,10 +432,11 @@ static void hvc_hangup(struct tty_struct *tty) spin_unlock_irqrestore(&hp->lock, flags); if (hp->ops->notifier_hangup) - hp->ops->notifier_hangup(hp, hp->data); + hp->ops->notifier_hangup(hp, hp->data); while(temp_open_count) { --temp_open_count; + tty_kref_put(tty); kref_put(&hp->kref, destroy_hvc_struct); } } @@ -592,7 +601,7 @@ int hvc_poll(struct hvc_struct *hp) } /* No tty attached, just skip */ - tty = hp->tty; + tty = tty_kref_get(hp->tty); if (tty == NULL) goto bail; @@ -672,6 +681,8 @@ int hvc_poll(struct hvc_struct *hp) tty_flip_buffer_push(tty); } + if (tty) + tty_kref_put(tty); return poll_mask; } @@ -807,7 +818,7 @@ int hvc_remove(struct hvc_struct *hp) struct tty_struct *tty; spin_lock_irqsave(&hp->lock, flags); - tty = hp->tty; + tty = tty_kref_get(hp->tty); if (hp->index < MAX_NR_HVC_CONSOLES) vtermnos[hp->index] = -1; @@ -819,18 +830,18 @@ int hvc_remove(struct hvc_struct *hp) /* * We 'put' the instance that was grabbed when the kref instance * was initialized using kref_init(). Let the last holder of this - * kref cause it to be removed, which will probably be the tty_hangup + * kref cause it to be removed, which will probably be the tty_vhangup * below. */ kref_put(&hp->kref, destroy_hvc_struct); /* - * This function call will auto chain call hvc_hangup. The tty should - * always be valid at this time unless a simultaneous tty close already - * cleaned up the hvc_struct. + * This function call will auto chain call hvc_hangup. */ - if (tty) - tty_hangup(tty); + if (tty) { + tty_vhangup(tty); + tty_kref_put(tty); + } return 0; } EXPORT_SYMBOL_GPL(hvc_remove); -- cgit v1.2.3-70-g09d2 From d4bee0a677cfa5a32f964ffa420e27406c65e605 Mon Sep 17 00:00:00 2001 From: Fang Wenqi Date: Tue, 9 Mar 2010 18:54:28 +0800 Subject: tty_buffer: Fix distinct type warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC drivers/char/tty_buffer.o drivers/char/tty_buffer.c: In function ‘tty_insert_flip_string_fixed_flag’: drivers/char/tty_buffer.c:251: warning: comparison of distinct pointer types lacks a cast drivers/char/tty_buffer.c: In function ‘tty_insert_flip_string_flags’: drivers/char/tty_buffer.c:288: warning: comparison of distinct pointer types lacks a cast Fix it by replacing min() with min_t() in tty_insert_flip_string_flags and tty_insert_flip_string_fixed_flag(). Signed-off-by: Fang Wenqi Signed-off-by: Greg Kroah-Hartman --- drivers/char/tty_buffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/tty_buffer.c b/drivers/char/tty_buffer.c index af8d9771572..7ee52164d47 100644 --- a/drivers/char/tty_buffer.c +++ b/drivers/char/tty_buffer.c @@ -248,7 +248,7 @@ int tty_insert_flip_string_fixed_flag(struct tty_struct *tty, { int copied = 0; do { - int goal = min(size - copied, TTY_BUFFER_PAGE); + int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); int space = tty_buffer_request_room(tty, goal); struct tty_buffer *tb = tty->buf.tail; /* If there is no space then tb may be NULL */ @@ -285,7 +285,7 @@ int tty_insert_flip_string_flags(struct tty_struct *tty, { int copied = 0; do { - int goal = min(size - copied, TTY_BUFFER_PAGE); + int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); int space = tty_buffer_request_room(tty, goal); struct tty_buffer *tb = tty->buf.tail; /* If there is no space then tb may be NULL */ -- cgit v1.2.3-70-g09d2 From 231443665882a02214c3748b9f86615a3ce9e5c2 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 11 Mar 2010 14:08:18 -0800 Subject: tty: cpm_uart: use resource_size() Use the resource_size function instead of manually calculating the resource size. This reduces the chance of introducing off-by-one errors. Signed-off-by: Tobias Klauser Cc: Alan Cox Cc: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/serial/cpm_uart/cpm_uart_cpm2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c index a9802e76b5f..722eac18f38 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c @@ -61,7 +61,7 @@ void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port, void __iomem *pram; unsigned long offset; struct resource res; - unsigned long len; + resource_size_t len; /* Don't remap parameter RAM if it has already been initialized * during console setup. @@ -74,7 +74,7 @@ void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port, if (of_address_to_resource(np, 1, &res)) return NULL; - len = 1 + res.end - res.start; + len = resource_size(&res); pram = ioremap(res.start, len); if (!pram) return NULL; -- cgit v1.2.3-70-g09d2 From 336cee42dd52824e360ab419eab4e8888eb054ec Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Mon, 8 Mar 2010 21:50:11 -0600 Subject: tty_port,usb-console: Fix usb serial console open/close regression Commit e1108a63e10d344284011cccc06328b2cd3e5da3 ("usb_serial: Use the shutdown() operation") breaks the ability to use a usb console starting in 2.6.33. This was observed when using console=ttyUSB0,115200 as a boot argument with an FTDI device. The error is: ftdi_sio ttyUSB0: ftdi_submit_read_urb - failed submitting read urb, error -22 The handling of the ASYNCB_INITIALIZED changed in 2.6.32 such that in tty_port_shutdown() it always clears the flag if it is set. The fix is to add a variable to the tty_port struct to indicate when the tty port is a console. CC: Alan Cox CC: Alan Stern CC: Oliver Neukum CC: Andrew Morton Signed-off-by: Jason Wessel Signed-off-by: Greg Kroah-Hartman --- drivers/char/tty_port.c | 2 +- drivers/usb/serial/console.c | 1 + include/linux/tty.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c index be492dd6643..a3bd1d0b66c 100644 --- a/drivers/char/tty_port.c +++ b/drivers/char/tty_port.c @@ -119,7 +119,7 @@ EXPORT_SYMBOL(tty_port_tty_set); static void tty_port_shutdown(struct tty_port *port) { mutex_lock(&port->mutex); - if (port->ops->shutdown && + if (port->ops->shutdown && !port->console && test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) port->ops->shutdown(port); mutex_unlock(&port->mutex); diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index b22ac325852..f347da2ef00 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -181,6 +181,7 @@ static int usb_console_setup(struct console *co, char *options) /* The console is special in terms of closing the device so * indicate this port is now acting as a system console. */ port->console = 1; + port->port.console = 1; mutex_unlock(&serial->disc_mutex); return retval; diff --git a/include/linux/tty.h b/include/linux/tty.h index 593228a520e..4409967db0c 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -224,6 +224,7 @@ struct tty_port { wait_queue_head_t close_wait; /* Close waiters */ wait_queue_head_t delta_msr_wait; /* Modem status change */ unsigned long flags; /* TTY flags ASY_*/ + unsigned char console:1; /* port is a console */ struct mutex mutex; /* Locking */ struct mutex buf_mutex; /* Buffer alloc lock */ unsigned char *xmit_buf; /* Optional buffer */ -- cgit v1.2.3-70-g09d2