mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-09 14:50:19 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: tty_port,usb-console: Fix usb serial console open/close regression tty: cpm_uart: use resource_size() tty_buffer: Fix distinct type warning hvc_console: Fix race between hvc_close and hvc_remove uartlite: Fix build on sparc. tty: Take a 256 byte padding into account when buffering below sub-page units Revert "tty: Add a new VT mode which is like VT_PROCESS but doesn't require a VT_RELDISP ioctl call"
This commit is contained in:
commit
8dba8f9494
@ -312,6 +312,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
|
|||||||
spin_lock_irqsave(&hp->lock, flags);
|
spin_lock_irqsave(&hp->lock, flags);
|
||||||
/* Check and then increment for fast path open. */
|
/* Check and then increment for fast path open. */
|
||||||
if (hp->count++ > 0) {
|
if (hp->count++ > 0) {
|
||||||
|
tty_kref_get(tty);
|
||||||
spin_unlock_irqrestore(&hp->lock, flags);
|
spin_unlock_irqrestore(&hp->lock, flags);
|
||||||
hvc_kick();
|
hvc_kick();
|
||||||
return 0;
|
return 0;
|
||||||
@ -319,7 +320,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
|
|||||||
|
|
||||||
tty->driver_data = hp;
|
tty->driver_data = hp;
|
||||||
|
|
||||||
hp->tty = tty;
|
hp->tty = tty_kref_get(tty);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&hp->lock, flags);
|
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);
|
spin_lock_irqsave(&hp->lock, flags);
|
||||||
hp->tty = NULL;
|
hp->tty = NULL;
|
||||||
spin_unlock_irqrestore(&hp->lock, flags);
|
spin_unlock_irqrestore(&hp->lock, flags);
|
||||||
|
tty_kref_put(tty);
|
||||||
tty->driver_data = NULL;
|
tty->driver_data = NULL;
|
||||||
kref_put(&hp->kref, destroy_hvc_struct);
|
kref_put(&hp->kref, destroy_hvc_struct);
|
||||||
printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);
|
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;
|
return;
|
||||||
|
|
||||||
hp = tty->driver_data;
|
hp = tty->driver_data;
|
||||||
|
|
||||||
spin_lock_irqsave(&hp->lock, flags);
|
spin_lock_irqsave(&hp->lock, flags);
|
||||||
|
tty_kref_get(tty);
|
||||||
|
|
||||||
if (--hp->count == 0) {
|
if (--hp->count == 0) {
|
||||||
/* We are done with the tty pointer now. */
|
/* We are done with the tty pointer now. */
|
||||||
hp->tty = NULL;
|
hp->tty = NULL;
|
||||||
spin_unlock_irqrestore(&hp->lock, flags);
|
spin_unlock_irqrestore(&hp->lock, flags);
|
||||||
|
|
||||||
|
/* Put the ref obtained in hvc_open() */
|
||||||
|
tty_kref_put(tty);
|
||||||
|
|
||||||
if (hp->ops->notifier_del)
|
if (hp->ops->notifier_del)
|
||||||
hp->ops->notifier_del(hp, hp->data);
|
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);
|
spin_unlock_irqrestore(&hp->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tty_kref_put(tty);
|
||||||
kref_put(&hp->kref, destroy_hvc_struct);
|
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);
|
spin_unlock_irqrestore(&hp->lock, flags);
|
||||||
|
|
||||||
if (hp->ops->notifier_hangup)
|
if (hp->ops->notifier_hangup)
|
||||||
hp->ops->notifier_hangup(hp, hp->data);
|
hp->ops->notifier_hangup(hp, hp->data);
|
||||||
|
|
||||||
while(temp_open_count) {
|
while(temp_open_count) {
|
||||||
--temp_open_count;
|
--temp_open_count;
|
||||||
|
tty_kref_put(tty);
|
||||||
kref_put(&hp->kref, destroy_hvc_struct);
|
kref_put(&hp->kref, destroy_hvc_struct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -592,7 +601,7 @@ int hvc_poll(struct hvc_struct *hp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* No tty attached, just skip */
|
/* No tty attached, just skip */
|
||||||
tty = hp->tty;
|
tty = tty_kref_get(hp->tty);
|
||||||
if (tty == NULL)
|
if (tty == NULL)
|
||||||
goto bail;
|
goto bail;
|
||||||
|
|
||||||
@ -672,6 +681,8 @@ int hvc_poll(struct hvc_struct *hp)
|
|||||||
|
|
||||||
tty_flip_buffer_push(tty);
|
tty_flip_buffer_push(tty);
|
||||||
}
|
}
|
||||||
|
if (tty)
|
||||||
|
tty_kref_put(tty);
|
||||||
|
|
||||||
return poll_mask;
|
return poll_mask;
|
||||||
}
|
}
|
||||||
@ -807,7 +818,7 @@ int hvc_remove(struct hvc_struct *hp)
|
|||||||
struct tty_struct *tty;
|
struct tty_struct *tty;
|
||||||
|
|
||||||
spin_lock_irqsave(&hp->lock, flags);
|
spin_lock_irqsave(&hp->lock, flags);
|
||||||
tty = hp->tty;
|
tty = tty_kref_get(hp->tty);
|
||||||
|
|
||||||
if (hp->index < MAX_NR_HVC_CONSOLES)
|
if (hp->index < MAX_NR_HVC_CONSOLES)
|
||||||
vtermnos[hp->index] = -1;
|
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
|
* We 'put' the instance that was grabbed when the kref instance
|
||||||
* was initialized using kref_init(). Let the last holder of this
|
* 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.
|
* below.
|
||||||
*/
|
*/
|
||||||
kref_put(&hp->kref, destroy_hvc_struct);
|
kref_put(&hp->kref, destroy_hvc_struct);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function call will auto chain call hvc_hangup. The tty should
|
* This function call will auto chain call hvc_hangup.
|
||||||
* always be valid at this time unless a simultaneous tty close already
|
|
||||||
* cleaned up the hvc_struct.
|
|
||||||
*/
|
*/
|
||||||
if (tty)
|
if (tty) {
|
||||||
tty_hangup(tty);
|
tty_vhangup(tty);
|
||||||
|
tty_kref_put(tty);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(hvc_remove);
|
EXPORT_SYMBOL_GPL(hvc_remove);
|
||||||
|
@ -248,7 +248,7 @@ int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
|
|||||||
{
|
{
|
||||||
int copied = 0;
|
int copied = 0;
|
||||||
do {
|
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);
|
int space = tty_buffer_request_room(tty, goal);
|
||||||
struct tty_buffer *tb = tty->buf.tail;
|
struct tty_buffer *tb = tty->buf.tail;
|
||||||
/* If there is no space then tb may be NULL */
|
/* 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;
|
int copied = 0;
|
||||||
do {
|
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);
|
int space = tty_buffer_request_room(tty, goal);
|
||||||
struct tty_buffer *tb = tty->buf.tail;
|
struct tty_buffer *tb = tty->buf.tail;
|
||||||
/* If there is no space then tb may be NULL */
|
/* If there is no space then tb may be NULL */
|
||||||
|
@ -119,7 +119,7 @@ EXPORT_SYMBOL(tty_port_tty_set);
|
|||||||
static void tty_port_shutdown(struct tty_port *port)
|
static void tty_port_shutdown(struct tty_port *port)
|
||||||
{
|
{
|
||||||
mutex_lock(&port->mutex);
|
mutex_lock(&port->mutex);
|
||||||
if (port->ops->shutdown &&
|
if (port->ops->shutdown && !port->console &&
|
||||||
test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
|
test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
|
||||||
port->ops->shutdown(port);
|
port->ops->shutdown(port);
|
||||||
mutex_unlock(&port->mutex);
|
mutex_unlock(&port->mutex);
|
||||||
|
@ -888,7 +888,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
|
|||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto out;
|
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;
|
ret = -EINVAL;
|
||||||
goto out;
|
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
|
* telling it that it has acquired. Also check if it has died and
|
||||||
* clean up (similar to logic employed in change_console())
|
* 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
|
* Send the signal as privileged - kill_pid() will
|
||||||
* tell us if the process has gone or something else
|
* 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.
|
* vt to auto control.
|
||||||
*/
|
*/
|
||||||
vc = vc_cons[fg_console].d;
|
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
|
* Send the signal as privileged - kill_pid() will
|
||||||
* tell us if the process has gone or something else
|
* 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;
|
vc->vt_newvt = new_vc->vc_num;
|
||||||
if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) {
|
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
|
* It worked. Mark the vt to switch to and
|
||||||
* normal operation. In this case, we'll also change back
|
* return. The process needs to send us a
|
||||||
* to KD_TEXT mode. I'm not sure if this is strictly correct
|
* VT_RELDISP ioctl to complete the switch.
|
||||||
* 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);
|
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...
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port,
|
|||||||
void __iomem *pram;
|
void __iomem *pram;
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
struct resource res;
|
struct resource res;
|
||||||
unsigned long len;
|
resource_size_t len;
|
||||||
|
|
||||||
/* Don't remap parameter RAM if it has already been initialized
|
/* Don't remap parameter RAM if it has already been initialized
|
||||||
* during console setup.
|
* 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))
|
if (of_address_to_resource(np, 1, &res))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
len = 1 + res.end - res.start;
|
len = resource_size(&res);
|
||||||
pram = ioremap(res.start, len);
|
pram = ioremap(res.start, len);
|
||||||
if (!pram)
|
if (!pram)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -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
|
/* The console is special in terms of closing the device so
|
||||||
* indicate this port is now acting as a system console. */
|
* indicate this port is now acting as a system console. */
|
||||||
port->console = 1;
|
port->console = 1;
|
||||||
|
port->port.console = 1;
|
||||||
|
|
||||||
mutex_unlock(&serial->disc_mutex);
|
mutex_unlock(&serial->disc_mutex);
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -70,12 +70,13 @@ struct tty_buffer {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* We default to dicing tty buffer allocations to this many characters
|
* We default to dicing tty buffer allocations to this many characters
|
||||||
* in order to avoid multiple page allocations. We assume tty_buffer itself
|
* in order to avoid multiple page allocations. We know the size of
|
||||||
* is under 256 bytes. See tty_buffer_find for the allocation logic this
|
* tty_buffer itself but it must also be taken into account that the
|
||||||
* must match
|
* 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 {
|
struct tty_bufhead {
|
||||||
@ -223,6 +224,7 @@ struct tty_port {
|
|||||||
wait_queue_head_t close_wait; /* Close waiters */
|
wait_queue_head_t close_wait; /* Close waiters */
|
||||||
wait_queue_head_t delta_msr_wait; /* Modem status change */
|
wait_queue_head_t delta_msr_wait; /* Modem status change */
|
||||||
unsigned long flags; /* TTY flags ASY_*/
|
unsigned long flags; /* TTY flags ASY_*/
|
||||||
|
unsigned char console:1; /* port is a console */
|
||||||
struct mutex mutex; /* Locking */
|
struct mutex mutex; /* Locking */
|
||||||
struct mutex buf_mutex; /* Buffer alloc lock */
|
struct mutex buf_mutex; /* Buffer alloc lock */
|
||||||
unsigned char *xmit_buf; /* Optional buffer */
|
unsigned char *xmit_buf; /* Optional buffer */
|
||||||
|
@ -27,7 +27,7 @@ struct vt_mode {
|
|||||||
#define VT_SETMODE 0x5602 /* set mode of active vt */
|
#define VT_SETMODE 0x5602 /* set mode of active vt */
|
||||||
#define VT_AUTO 0x00 /* auto vt switching */
|
#define VT_AUTO 0x00 /* auto vt switching */
|
||||||
#define VT_PROCESS 0x01 /* process controls 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 {
|
struct vt_stat {
|
||||||
unsigned short v_active; /* active vt */
|
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_SENDSIG 0x5604 /* signal to send to bitmask of vts */
|
||||||
|
|
||||||
#define VT_RELDISP 0x5605 /* release display */
|
#define VT_RELDISP 0x5605 /* release display */
|
||||||
#define VT_ACKACQ 0x02 /* acknowledge switch */
|
|
||||||
|
|
||||||
#define VT_ACTIVATE 0x5606 /* make vt active */
|
#define VT_ACTIVATE 0x5606 /* make vt active */
|
||||||
#define VT_WAITACTIVE 0x5607 /* wait for vt active */
|
#define VT_WAITACTIVE 0x5607 /* wait for vt active */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user