* [PATCH 1/2] Add a new helper for sleepable BTM acquirements which is used by tty_write_message()
From: Jeff Liu @ 2012-06-30 9:39 UTC (permalink / raw)
To: linux-serial
Cc: linux-fsdevel@vger.kernel.org, linux-ext4@vger.kernel.org, gregkh,
Jan Kara, Ted Ts'o
This helper only used by tty_write_message(), it will sleep until BTM lock acquired.
Signed-off-by: Jie Liu <jeff.liu@oracle.com>
---
drivers/tty/tty_mutex.c | 13 +++++++++++++
include/linux/tty.h | 1 +
2 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c
index 9ff986c..e638636 100644
--- a/drivers/tty/tty_mutex.c
+++ b/drivers/tty/tty_mutex.c
@@ -30,3 +30,16 @@ void __lockfunc tty_unlock(void)
mutex_unlock(&big_tty_mutex);
}
EXPORT_SYMBOL(tty_unlock);
+
+/*
+ * Wait until getting the big tty mutex.
+ * This function only used by tty_write_message().
+ */
+void __lockfunc tty_lock_wait(void)
+{
+ while (!mutex_trylock(&big_tty_mutex)) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule();
+ }
+}
+EXPORT_SYMBOL(tty_lock_wait);
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 9f47ab5..5e01e0b 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -607,6 +607,7 @@ extern long vt_compat_ioctl(struct tty_struct *tty,
/* functions for preparation of BKL removal */
extern void __lockfunc tty_lock(void) __acquires(tty_lock);
extern void __lockfunc tty_unlock(void) __releases(tty_lock);
+extern void __lockfunc tty_lock_wait(void) __acquires(tty_lock);
/*
* this shall be called only from where BTM is held (like close)
--
1.7.9
^ permalink raw reply related
* [PATCH 0/2] Fix potential dead lock for tty_write_message() if CONFIG_PRINT_QUOTA_WARNING is enabled
From: Jeff Liu @ 2012-06-30 9:39 UTC (permalink / raw)
To: linux-serial
Cc: linux-fsdevel@vger.kernel.org, linux-ext4@vger.kernel.org, gregkh,
Jan Kara, Ted Ts'o
Hello,
I observed the below lockdep warning info at syslog on 3.5-rc4, it could be simply reproduced by creating
files more than the soft limits of inode quota on ext4 if CONFIG_PRINT_QUOTA_WARNING is enabled.
jeff@pibroch:~$ uname -a
Linux pibroch 3.5.0-rc4-dirty #220 SMP Fri Jun 29 11:30:20 CST 2012 i686 GNU/Linux
jeff@pibroch:~$ quota -u jeff
Disk quotas for user jeff (uid 1000):
Filesystem blocks quota limit grace files quota limit grace
/dev/sda8 0 0 0 1 100 6000
So creating 110 a files could got quota warns.
$ for((i=0;i<110;i++));do touch "/ext4_mount_path/testme.".$i;done
[ 213.324324] =====================================================
[ 213.324337] [ INFO: possible circular locking dependency detected ]
[ 213.324353] 3.5.0-rc4 #201 Not tainted
[ 213.324364] -------------------------------------------------------
[ 213.324376] touch/2237 is trying to acquire lock:
[ 213.324413] (&tty->atomic_write_lock){+.+...}, at: [<c14dcc02>] tty_write_message+0x40/0x103
[ 213.324426] [ 213.324426] but task is already holding lock:
[ 213.324469] (jbd2_handle){+.+...}, at: [<f8202060>] start_this_handle+0xa19/0xa8a [jbd2]
[ 213.324482] [ 213.324482] which lock already depends on the new lock.
[ 213.324482] [ 213.324497] [ 213.324497] the existing dependency chain (in reverse order) is:
[ 213.324525] [ 213.324525] -> #2 (jbd2_handle){+.+...}:
[ 213.324546] [<c1101e89>] lock_acquire+0x198/0x1d3
[ 213.324576] [<f82020a4>] start_this_handle+0xa5d/0xa8a [jbd2]
[ 213.324608] [<f820247a>] jbd2__journal_start+0x11b/0x187 [jbd2]
[ 213.324638] [<f8202506>] jbd2_journal_start+0x20/0x30 [jbd2]
[ 213.324701] [<f8a8028c>] ext4_journal_start_sb+0x280/0x296 [ext4]
[ 213.324753] [<f8a5a9bd>] ext4_dirty_inode+0x27/0x84 [ext4]
[ 213.324767] [<c127e24e>] __mark_inode_dirty+0x52/0x2e7
[ 213.324781] [<c12675fe>] update_time+0x10f/0x126
[ 213.324794] [<c1267c07>] touch_atime+0x235/0x25e
[ 213.324841] [<f8a49fac>] ext4_file_mmap+0x5c/0x7d [ext4]
[ 213.324856] [<c1201bf9>] mmap_region+0x449/0x7c4
[ 213.324870] [<c1202435>] do_mmap_pgoff+0x4c1/0x4db
[ 213.324884] [<c11e7bb4>] vm_mmap_pgoff+0x98/0xc7
[ 213.324899] [<c11ffa5e>] sys_mmap_pgoff+0x16a/0x1bf
[ 213.324912] [<c18a5224>] syscall_call+0x7/0xb
[ 213.324929] [ 213.324929] -> #1 (&mm->mmap_sem){++++++}:
[ 213.324943] [<c1101e89>] lock_acquire+0x198/0x1d3
[ 213.324956] [<c11f3bcb>] might_fault+0xbf/0xf8
[ 213.324970] [<c13e1cd3>] _copy_from_user+0x40/0x8a
[ 213.324982] [<c14da3cf>] copy_from_user+0x16/0x26
[ 213.324994] [<c14dc80b>] tty_write+0x282/0x3c7
[ 213.325006] [<c14dca34>] redirected_tty_write+0xe4/0xfd
[ 213.325020] [<c123f955>] vfs_write+0xf5/0x1a3
[ 213.325033] [<c123fcb8>] sys_write+0x6c/0xa9
[ 213.325045] [<c18b169f>] sysenter_do_call+0x12/0x38
[ 213.325062] [ 213.325062] -> #0 (&tty->atomic_write_lock){+.+...}:
[ 213.325078] [<c1100e70>] __lock_acquire+0x15bb/0x1b98
[ 213.325091] [<c1101e89>] lock_acquire+0x198/0x1d3
[ 213.325105] [<c189fb16>] __mutex_lock_common+0x52/0x7cd
[ 213.325118] [<c18a0439>] mutex_lock_nested+0x5c/0x70
[ 213.325130] [<c14dcc02>] tty_write_message+0x40/0x103
[ 213.325144] [<c12bf9fd>] flush_warnings+0x17c/0x313
[ 213.325157] [<c12c47c4>] dquot_alloc_inode+0x1e4/0x1fc
[ 213.325207] [<f8a4db1e>] ext4_new_inode+0x11f5/0x1576 [ext4]
[ 213.325262] [<f8a6166d>] ext4_create+0x160/0x230 [ext4]
[ 213.325276] [<c1253dc2>] vfs_create+0xc4/0x106
[ 213.325297] [<c1254ee2>] do_last+0x437/0xdcc
[ 213.325310] [<c125762a>] path_openat+0x10e/0x5a7
[ 213.325323] [<c1257c57>] do_filp_open+0x39/0xc2
[ 213.325335] [<c123e362>] do_sys_open+0xb5/0x1bb
[ 213.325347] [<c123e4a1>] sys_open+0x39/0x5b
[ 213.325360] [<c18a5224>] syscall_call+0x7/0xb
[ 213.325368] [ 213.325368] other info that might help us debug this:
[ 213.325368] [ 213.325391] Chain exists of:
[ 213.325391] &tty->atomic_write_lock --> &mm->mmap_sem --> jbd2_handle
[ 213.325391] [ 213.325401] Possible unsafe locking scenario:
[ 213.325401] [ 213.325410] CPU0 CPU1
[ 213.325417] ---- ----
[ 213.325558] lock(jbd2_handle);
[ 213.325571] lock(&mm->mmap_sem);
[ 213.325583] lock(jbd2_handle);
[ 213.325595] lock(&tty->atomic_write_lock);
[ 213.325602] [ 213.325602] *** DEADLOCK ***
[ 213.325602] [ 213.325613] 2 locks held by touch/2237:
[ 213.325639] #0: (&type->i_mutex_dir_key#3){+.+.+.}, at: [<c1254da1>] do_last+0x2f6/0xdcc
[ 213.325673] #1: (jbd2_handle){+.+...}, at: [<f8202060>] start_this_handle+0xa19/0xa8a [jbd2]
[ 213.325682] [ 213.325682] stack backtrace:
[ 213.325693] Pid: 2237, comm: touch Not tainted 3.5.0-rc4 #201
[ 213.325702] Call Trace:
[ 213.325717] [<c10faac9>] print_circular_bug+0x3fa/0x412
[ 213.325732] [<c1100e70>] __lock_acquire+0x15bb/0x1b98
[ 213.325747] [<c1101e89>] lock_acquire+0x198/0x1d3
[ 213.325761] [<c14dcc02>] ? tty_write_message+0x40/0x103
[ 213.325776] [<c189fb16>] __mutex_lock_common+0x52/0x7cd
[ 213.325789] [<c14dcc02>] ? tty_write_message+0x40/0x103
[ 213.325804] [<c18a525d>] ? restore_all+0xf/0xf
[ 213.325819] [<c10b396c>] ? need_resched+0x22/0x3a
[ 213.325833] [<c18a0439>] mutex_lock_nested+0x5c/0x70
[ 213.325847] [<c14dcc02>] ? tty_write_message+0x40/0x103
[ 213.325860] [<c14dcc02>] tty_write_message+0x40/0x103
[ 213.325874] [<c12bf9fd>] flush_warnings+0x17c/0x313
[ 213.325888] [<c12c47c4>] dquot_alloc_inode+0x1e4/0x1fc
[ 213.325941] [<f8a4db1e>] ext4_new_inode+0x11f5/0x1576 [ext4]
[ 213.326000] [<f8a6166d>] ext4_create+0x160/0x230 [ext4]
[ 213.326018] [<c1253dc2>] vfs_create+0xc4/0x106
[ 213.326033] [<c1254ee2>] do_last+0x437/0xdcc
[ 213.326048] [<c125762a>] path_openat+0x10e/0x5a7
[ 213.326063] [<c1257c57>] do_filp_open+0x39/0xc2
[ 213.326077] [<c1101cdc>] ? lock_release+0x4b3/0x4c8
[ 213.326090] [<c18a5116>] ? _raw_spin_unlock+0x4c/0x5d
[ 213.326104] [<c126c821>] ? alloc_fd+0x2fe/0x317
[ 213.326118] [<c123e362>] do_sys_open+0xb5/0x1bb
[ 213.326132] [<c123e4a1>] sys_open+0x39/0x5b
[ 213.326145] [<c18a5224>] syscall_call+0x7/0xb
looks this issue is caused by the tty_write_message()->....->tty_write() because it will call copy_from_user() which will
produce page faults and kick off ext4 inode dirty process on another CPU if possible.
According to my understood, if the current process was be preempted when its time quantum expires, the need_resched field of
the current process is set, so the scheduler is invoked and the current process will be re-scheduled to run and call
next tty_write_message() at dquot.c->print_warning(), and it need to acquire atomic_write_lock again, however, this lock has
already been hold by another process, so the race situation is occurred.
I know such kind of issue should be better to fix at quota module, I have also tried to fix it there but no luck. :(
For now, I could only work out a stupid patch set to let lockdep happy by making both tty_write_lock and BTM lock sleepable.
Thanks,
-Jeff
^ permalink raw reply
* Re: artpec.c / serial_core.c hardware flow control problem
From: Alan Cox @ 2012-06-29 16:31 UTC (permalink / raw)
To: Johan Adolfsson
Cc: Mikael Lars Johansson, linux-serial@vger.kernel.org,
Mikael Starvik, Jesper Nilsson, Johan Adolfsson
In-Reply-To: <4BEA3FF3CAA35E408EA55C7BE2E61D055C79D9B622@xmail3.se.axis.com>
> Do you mean the entire if () { return; } statement or just the RELEVANT_IFLAG part?
It's not enough to check the iflag in this case - a termios changing
c_cc[VSTOP) - which is what STOP_CHAR(tty) is, also might need
the stop handling reprogramming.
Alan
^ permalink raw reply
* RE: artpec.c / serial_core.c hardware flow control problem
From: Johan Adolfsson @ 2012-06-29 15:16 UTC (permalink / raw)
To: Alan Cox, Mikael Lars Johansson
Cc: linux-serial@vger.kernel.org, Mikael Starvik, Jesper Nilsson,
Johan Adolfsson
In-Reply-To: <20120628172421.4cb91ada@pyramind.ukuu.org.uk>
> -----Original Message-----
> From: linux-serial-owner@vger.kernel.org [mailto:linux-serial-
> owner@vger.kernel.org] On Behalf Of Alan Cox
> Sent: den 28 juni 2012 18:24
>
> On Thu, 28 Jun 2012 17:29:27 +0200
> Mikael Johansson <mikael.lars.johansson@axis.com> wrote:
>
> > Greetings,
> >
> > We have a problem with drivers/serial/artpec.c (Not yet in main tree)
> > which uses hardware supported flow control (XON/XOFF). We do
> cfmakeraw()
> > and tcsetattr() from userspace to set a termios struct where (c_iflag
> &
> > IXON) is not set. The problem is that the call to tcsetattr() is not
> > propagated down to serial_artpec_set_termios(), the reason being that
> > uart_set_termios() doesn't think that IXON is a RELEVANT_IFLAG and
> > returns prematurely instead of calling uart_change_speed -->
> > ops->set_termios().
> >
> > Could this be fixed by making IXON a RELEVANT_IFLAG?:
>
> That's actually insufficient for those cases - you can set the
> characters
> used for things as well plus IXANY and IXOFF.
>
> It's a stupid "optimisation" and the only reason I didn't get rid of it
> before was in case it broke something else. Time for it to go.
>
> So yeah - I'd just delete it.
Do you mean the entire if () { return; } statement or just the RELEVANT_IFLAG part?
> If you are doing hardware XON/XOFF watch c_cc[VSTART] and c_cc[VSTOP].
> Those control the symbol used for soft flow control.
We use STOP_CHAR(tty), we only have hardware support for stopping transfer,
the tty layer kicks in and enables it again.
> Alan
/Johan
^ permalink raw reply
* [PATCH] tty: localise the lock
From: Alan Cox @ 2012-06-29 13:48 UTC (permalink / raw)
To: greg, linux-serial
From: Alan Cox <alan@linux.intel.com>
The termios and other changes mean the other protections needed on the driver
tty arrays should be adequate. Turn it all back on.
This contains pieces folded in from the fixes made to the original patches
| From: Geert Uytterhoeven <geert@linux-m68k.org> (fix m68k)
| From: Paul Gortmaker <paul.gortmaker@windriver.com> (fix cris)
| From: Jiri Kosina <jkosina@suze.cz> (lockdep)
| From: Eric Dumazet <eric.dumazet@gmail.com> (lockdep)
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/tty/amiserial.c | 14 ++++----
drivers/tty/cyclades.c | 2 +
drivers/tty/n_r3964.c | 10 +++---
drivers/tty/pty.c | 25 ++++++++-------
drivers/tty/serial/crisv10.c | 8 ++---
drivers/tty/synclink.c | 4 +-
drivers/tty/synclink_gt.c | 4 +-
drivers/tty/synclinkmp.c | 4 +-
drivers/tty/tty_io.c | 67 ++++++++++++++++++++++++----------------
drivers/tty/tty_ldisc.c | 67 ++++++++++++++++++++++------------------
drivers/tty/tty_mutex.c | 71 +++++++++++++++++++++++++++++++++---------
drivers/tty/tty_port.c | 6 ++--
include/linux/tty.h | 23 ++++++++------
net/bluetooth/rfcomm/tty.c | 4 +-
14 files changed, 190 insertions(+), 119 deletions(-)
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index 0e8441e..998731f 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -1033,7 +1033,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state,
if (!retinfo)
return -EFAULT;
memset(&tmp, 0, sizeof(tmp));
- tty_lock();
+ tty_lock(tty);
tmp.line = tty->index;
tmp.port = state->port;
tmp.flags = state->tport.flags;
@@ -1042,7 +1042,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state,
tmp.close_delay = state->tport.close_delay;
tmp.closing_wait = state->tport.closing_wait;
tmp.custom_divisor = state->custom_divisor;
- tty_unlock();
+ tty_unlock(tty);
if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
return -EFAULT;
return 0;
@@ -1059,12 +1059,12 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
return -EFAULT;
- tty_lock();
+ tty_lock(tty);
change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) ||
new_serial.custom_divisor != state->custom_divisor;
if (new_serial.irq || new_serial.port != state->port ||
new_serial.xmit_fifo_size != state->xmit_fifo_size) {
- tty_unlock();
+ tty_unlock(tty);
return -EINVAL;
}
@@ -1074,7 +1074,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
(new_serial.xmit_fifo_size != state->xmit_fifo_size) ||
((new_serial.flags & ~ASYNC_USR_MASK) !=
(port->flags & ~ASYNC_USR_MASK))) {
- tty_unlock();
+ tty_unlock(tty);
return -EPERM;
}
port->flags = ((port->flags & ~ASYNC_USR_MASK) |
@@ -1084,7 +1084,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
}
if (new_serial.baud_base < 9600) {
- tty_unlock();
+ tty_unlock(tty);
return -EINVAL;
}
@@ -1116,7 +1116,7 @@ check_and_exit:
}
} else
retval = startup(tty, state);
- tty_unlock();
+ tty_unlock(tty);
return retval;
}
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
index b9511f1..9475cbc 100644
--- a/drivers/tty/cyclades.c
+++ b/drivers/tty/cyclades.c
@@ -1599,7 +1599,7 @@ static int cy_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->port.flags & ASYNC_CLOSING)) {
- wait_event_interruptible_tty(info->port.close_wait,
+ wait_event_interruptible_tty(tty, info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
}
diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c
index 5c6c314..1e64050 100644
--- a/drivers/tty/n_r3964.c
+++ b/drivers/tty/n_r3964.c
@@ -1065,7 +1065,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
TRACE_L("read()");
- tty_lock();
+ tty_lock(tty);
pClient = findClient(pInfo, task_pid(current));
if (pClient) {
@@ -1077,7 +1077,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
goto unlock;
}
/* block until there is a message: */
- wait_event_interruptible_tty(pInfo->read_wait,
+ wait_event_interruptible_tty(tty, pInfo->read_wait,
(pMsg = remove_msg(pInfo, pClient)));
}
@@ -1107,7 +1107,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
}
ret = -EPERM;
unlock:
- tty_unlock();
+ tty_unlock(tty);
return ret;
}
@@ -1156,7 +1156,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
pHeader->locks = 0;
pHeader->owner = NULL;
- tty_lock();
+ tty_lock(tty);
pClient = findClient(pInfo, task_pid(current));
if (pClient) {
@@ -1175,7 +1175,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
add_tx_queue(pInfo, pHeader);
trigger_transmit(pInfo);
- tty_unlock();
+ tty_unlock(tty);
return 0;
}
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index f1ba793..33526f9 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -47,6 +47,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
wake_up_interruptible(&tty->read_wait);
wake_up_interruptible(&tty->write_wait);
tty->packet = 0;
+ /* Review - krefs on tty_link ?? */
if (!tty->link)
return;
tty->link->packet = 0;
@@ -62,9 +63,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
mutex_unlock(&devpts_mutex);
}
#endif
- tty_unlock();
+ tty_unlock(tty);
tty_vhangup(tty->link);
- tty_lock();
+ tty_lock(tty);
}
}
@@ -599,26 +600,27 @@ static int ptmx_open(struct inode *inode, struct file *filp)
return retval;
/* find a device that is not in use. */
- tty_lock();
+ mutex_lock(&devpts_mutex);
index = devpts_new_index(inode);
- tty_unlock();
if (index < 0) {
retval = index;
goto err_file;
}
+ mutex_unlock(&devpts_mutex);
+
mutex_lock(&tty_mutex);
- mutex_lock(&devpts_mutex);
tty = tty_init_dev(ptm_driver, index);
- mutex_unlock(&devpts_mutex);
- tty_lock();
- mutex_unlock(&tty_mutex);
if (IS_ERR(tty)) {
retval = PTR_ERR(tty);
goto out;
}
+ /* The tty returned here is locked so we can safely
+ drop the mutex */
+ mutex_unlock(&tty_mutex);
+
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
tty_add_file(tty, filp);
@@ -631,16 +633,17 @@ static int ptmx_open(struct inode *inode, struct file *filp)
if (retval)
goto err_release;
- tty_unlock();
+ tty_unlock(tty);
return 0;
err_release:
- tty_unlock();
+ tty_unlock(tty);
tty_release(inode, filp);
return retval;
out:
+ mutex_unlock(&tty_mutex);
devpts_kill_index(inode, index);
- tty_unlock();
err_file:
+ mutex_unlock(&devpts_mutex);
tty_free_file(filp);
return retval;
}
diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c
index 6b705b2..a770b10 100644
--- a/drivers/tty/serial/crisv10.c
+++ b/drivers/tty/serial/crisv10.c
@@ -3976,7 +3976,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
- wait_event_interruptible_tty(info->close_wait,
+ wait_event_interruptible_tty(tty, info->close_wait,
!(info->flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
if (info->flags & ASYNC_HUP_NOTIFY)
@@ -4052,9 +4052,9 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
printk("block_til_ready blocking: ttyS%d, count = %d\n",
info->line, info->count);
#endif
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&info->open_wait, &wait);
@@ -4115,7 +4115,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
- wait_event_interruptible_tty(info->close_wait,
+ wait_event_interruptible_tty(tty, info->close_wait,
!(info->flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
return ((info->flags & ASYNC_HUP_NOTIFY) ?
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
index bdeeb31..991bae8 100644
--- a/drivers/tty/synclink.c
+++ b/drivers/tty/synclink.c
@@ -3338,9 +3338,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
printk("%s(%d):block_til_ready blocking on %s count=%d\n",
__FILE__,__LINE__, tty->driver->name, port->count );
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c
index f02d18a..9130253 100644
--- a/drivers/tty/synclink_gt.c
+++ b/drivers/tty/synclink_gt.c
@@ -3336,9 +3336,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
}
DBGINFO(("%s block_til_ready wait\n", tty->driver->name));
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c
index ae75a3c..95fd4e2 100644
--- a/drivers/tty/synclinkmp.c
+++ b/drivers/tty/synclinkmp.c
@@ -3357,9 +3357,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
printk("%s(%d):%s block_til_ready() count=%d\n",
__FILE__,__LINE__, tty->driver->name, port->count );
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index e062c1b..a8fcfe7 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -185,6 +185,7 @@ void free_tty_struct(struct tty_struct *tty)
put_device(tty->dev);
kfree(tty->write_buf);
tty_buffer_free_all(tty);
+ tty->magic = 0xDEADDEAD;
kfree(tty);
}
@@ -573,7 +574,7 @@ void __tty_hangup(struct tty_struct *tty)
}
spin_unlock(&redirect_lock);
- tty_lock();
+ tty_lock(tty);
/* some functions below drop BTM, so we need this bit */
set_bit(TTY_HUPPING, &tty->flags);
@@ -666,7 +667,7 @@ void __tty_hangup(struct tty_struct *tty)
clear_bit(TTY_HUPPING, &tty->flags);
tty_ldisc_enable(tty);
- tty_unlock();
+ tty_unlock(tty);
if (f)
fput(f);
@@ -1103,12 +1104,12 @@ void tty_write_message(struct tty_struct *tty, char *msg)
{
if (tty) {
mutex_lock(&tty->atomic_write_lock);
- tty_lock();
+ tty_lock(tty);
if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) {
- tty_unlock();
+ tty_unlock(tty);
tty->ops->write(tty, msg, strlen(msg));
} else
- tty_unlock();
+ tty_unlock(tty);
tty_write_unlock(tty);
}
return;
@@ -1405,6 +1406,7 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
}
initialize_tty_struct(tty, driver, idx);
+ tty_lock(tty);
retval = tty_driver_install_tty(driver, tty);
if (retval < 0)
goto err_deinit_tty;
@@ -1417,9 +1419,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
retval = tty_ldisc_setup(tty, tty->link);
if (retval)
goto err_release_tty;
+ /* Return the tty locked so that it cannot vanish under the caller */
return tty;
err_deinit_tty:
+ tty_unlock(tty);
deinitialize_tty_struct(tty);
free_tty_struct(tty);
err_module_put:
@@ -1428,6 +1432,7 @@ err_module_put:
/* call the tty release_tty routine to clean out this slot */
err_release_tty:
+ tty_unlock(tty);
printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, "
"clearing slot %d\n", idx);
release_tty(tty, idx);
@@ -1609,7 +1614,7 @@ int tty_release(struct inode *inode, struct file *filp)
if (tty_paranoia_check(tty, inode, __func__))
return 0;
- tty_lock();
+ tty_lock(tty);
check_tty_count(tty, __func__);
__tty_fasync(-1, filp, 0);
@@ -1618,10 +1623,11 @@ int tty_release(struct inode *inode, struct file *filp)
pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER);
devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
+ /* Review: parallel close */
o_tty = tty->link;
if (tty_release_checks(tty, o_tty, idx)) {
- tty_unlock();
+ tty_unlock(tty);
return 0;
}
@@ -1633,7 +1639,7 @@ int tty_release(struct inode *inode, struct file *filp)
if (tty->ops->close)
tty->ops->close(tty, filp);
- tty_unlock();
+ tty_unlock(tty);
/*
* Sanity check: if tty->count is going to zero, there shouldn't be
* any waiters on tty->read_wait or tty->write_wait. We test the
@@ -1656,7 +1662,7 @@ int tty_release(struct inode *inode, struct file *filp)
opens on /dev/tty */
mutex_lock(&tty_mutex);
- tty_lock();
+ tty_lock_pair(tty, o_tty);
tty_closing = tty->count <= 1;
o_tty_closing = o_tty &&
(o_tty->count <= (pty_master ? 1 : 0));
@@ -1687,7 +1693,7 @@ int tty_release(struct inode *inode, struct file *filp)
printk(KERN_WARNING "%s: %s: read/write wait queue active!\n",
__func__, tty_name(tty, buf));
- tty_unlock();
+ tty_unlock_pair(tty, o_tty);
mutex_unlock(&tty_mutex);
schedule();
}
@@ -1750,7 +1756,7 @@ int tty_release(struct inode *inode, struct file *filp)
/* check whether both sides are closing ... */
if (!tty_closing || (o_tty && !o_tty_closing)) {
- tty_unlock();
+ tty_unlock_pair(tty, o_tty);
return 0;
}
@@ -1763,14 +1769,16 @@ int tty_release(struct inode *inode, struct file *filp)
tty_ldisc_release(tty, o_tty);
/*
* The release_tty function takes care of the details of clearing
- * the slots and preserving the termios structure.
+ * the slots and preserving the termios structure. The tty_unlock_pair
+ * should be safe as we keep a kref while the tty is locked (so the
+ * unlock never unlocks a freed tty).
*/
release_tty(tty, idx);
+ tty_unlock_pair(tty, o_tty);
/* Make this pty number available for reallocation */
if (devpts)
devpts_kill_index(inode, idx);
- tty_unlock();
return 0;
}
@@ -1874,6 +1882,9 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp,
* Locking: tty_mutex protects tty, tty_lookup_driver and tty_init_dev.
* tty->count should protect the rest.
* ->siglock protects ->signal/->sighand
+ *
+ * Note: the tty_unlock/lock cases without a ref are only safe due to
+ * tty_mutex
*/
static int tty_open(struct inode *inode, struct file *filp)
@@ -1897,8 +1908,7 @@ retry_open:
retval = 0;
mutex_lock(&tty_mutex);
- tty_lock();
-
+ /* This is protected by the tty_mutex */
tty = tty_open_current_tty(device, filp);
if (IS_ERR(tty)) {
retval = PTR_ERR(tty);
@@ -1919,17 +1929,19 @@ retry_open:
}
if (tty) {
+ tty_lock(tty);
retval = tty_reopen(tty);
- if (retval)
+ if (retval < 0) {
+ tty_unlock(tty);
tty = ERR_PTR(retval);
- } else
+ }
+ } else /* Returns with the tty_lock held for now */
tty = tty_init_dev(driver, index);
mutex_unlock(&tty_mutex);
if (driver)
tty_driver_kref_put(driver);
if (IS_ERR(tty)) {
- tty_unlock();
retval = PTR_ERR(tty);
goto err_file;
}
@@ -1958,7 +1970,7 @@ retry_open:
printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__,
retval, tty->name);
#endif
- tty_unlock(); /* need to call tty_release without BTM */
+ tty_unlock(tty); /* need to call tty_release without BTM */
tty_release(inode, filp);
if (retval != -ERESTARTSYS)
return retval;
@@ -1970,17 +1982,15 @@ retry_open:
/*
* Need to reset f_op in case a hangup happened.
*/
- tty_lock();
if (filp->f_op == &hung_up_tty_fops)
filp->f_op = &tty_fops;
- tty_unlock();
goto retry_open;
}
- tty_unlock();
+ tty_unlock(tty);
mutex_lock(&tty_mutex);
- tty_lock();
+ tty_lock(tty);
spin_lock_irq(¤t->sighand->siglock);
if (!noctty &&
current->signal->leader &&
@@ -1988,11 +1998,10 @@ retry_open:
tty->session == NULL)
__proc_set_tty(current, tty);
spin_unlock_irq(¤t->sighand->siglock);
- tty_unlock();
+ tty_unlock(tty);
mutex_unlock(&tty_mutex);
return 0;
err_unlock:
- tty_unlock();
mutex_unlock(&tty_mutex);
/* after locks to avoid deadlock */
if (!IS_ERR_OR_NULL(driver))
@@ -2075,10 +2084,13 @@ out:
static int tty_fasync(int fd, struct file *filp, int on)
{
+ struct tty_struct *tty = file_tty(filp);
int retval;
- tty_lock();
+
+ tty_lock(tty);
retval = __tty_fasync(fd, filp, on);
- tty_unlock();
+ tty_unlock(tty);
+
return retval;
}
@@ -2915,6 +2927,7 @@ void initialize_tty_struct(struct tty_struct *tty,
tty->pgrp = NULL;
tty->overrun_time = jiffies;
tty_buffer_init(tty);
+ mutex_init(&tty->legacy_mutex);
mutex_init(&tty->termios_mutex);
mutex_init(&tty->ldisc_mutex);
init_waitqueue_head(&tty->write_wait);
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 073e533..9260c08 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -568,7 +568,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
if (IS_ERR(new_ldisc))
return PTR_ERR(new_ldisc);
- tty_lock();
+ tty_lock(tty);
/*
* We need to look at the tty locking here for pty/tty pairs
* when both sides try to change in parallel.
@@ -582,12 +582,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
*/
if (tty->ldisc->ops->num == ldisc) {
- tty_unlock();
+ tty_unlock(tty);
tty_ldisc_put(new_ldisc);
return 0;
}
- tty_unlock();
+ tty_unlock(tty);
/*
* Problem: What do we do if this blocks ?
* We could deadlock here
@@ -595,7 +595,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
tty_wait_until_sent(tty, 0);
- tty_lock();
+ tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
/*
@@ -605,10 +605,10 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) {
mutex_unlock(&tty->ldisc_mutex);
- tty_unlock();
+ tty_unlock(tty);
wait_event(tty_ldisc_wait,
test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0);
- tty_lock();
+ tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
}
@@ -623,7 +623,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
o_ldisc = tty->ldisc;
- tty_unlock();
+ tty_unlock(tty);
/*
* Make sure we don't change while someone holds a
* reference to the line discipline. The TTY_LDISC bit
@@ -650,7 +650,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
retval = tty_ldisc_wait_idle(tty, 5 * HZ);
- tty_lock();
+ tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
/* handle wait idle failure locked */
@@ -665,7 +665,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
clear_bit(TTY_LDISC_CHANGING, &tty->flags);
mutex_unlock(&tty->ldisc_mutex);
tty_ldisc_put(new_ldisc);
- tty_unlock();
+ tty_unlock(tty);
return -EIO;
}
@@ -708,7 +708,7 @@ enable:
if (o_work)
schedule_work(&o_tty->buf.work);
mutex_unlock(&tty->ldisc_mutex);
- tty_unlock();
+ tty_unlock(tty);
return retval;
}
@@ -816,11 +816,11 @@ void tty_ldisc_hangup(struct tty_struct *tty)
* need to wait for another function taking the BTM
*/
clear_bit(TTY_LDISC, &tty->flags);
- tty_unlock();
+ tty_unlock(tty);
cancel_work_sync(&tty->buf.work);
mutex_unlock(&tty->ldisc_mutex);
retry:
- tty_lock();
+ tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
/* At this point we have a closed ldisc and we want to
@@ -831,7 +831,7 @@ retry:
if (atomic_read(&tty->ldisc->users) != 1) {
char cur_n[TASK_COMM_LEN], tty_n[64];
long timeout = 3 * HZ;
- tty_unlock();
+ tty_unlock(tty);
while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
timeout = MAX_SCHEDULE_TIMEOUT;
@@ -894,6 +894,23 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
tty_ldisc_enable(tty);
return 0;
}
+
+static void tty_ldisc_kill(struct tty_struct *tty)
+{
+ mutex_lock(&tty->ldisc_mutex);
+ /*
+ * Now kill off the ldisc
+ */
+ tty_ldisc_close(tty, tty->ldisc);
+ tty_ldisc_put(tty->ldisc);
+ /* Force an oops if we mess this up */
+ tty->ldisc = NULL;
+
+ /* Ensure the next open requests the N_TTY ldisc */
+ tty_set_termios_ldisc(tty, N_TTY);
+ mutex_unlock(&tty->ldisc_mutex);
+}
+
/**
* tty_ldisc_release - release line discipline
* @tty: tty being shut down
@@ -912,27 +929,19 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
* race with the set_ldisc code path.
*/
- tty_unlock();
+ tty_unlock_pair(tty, o_tty);
tty_ldisc_halt(tty);
tty_ldisc_flush_works(tty);
- tty_lock();
-
- mutex_lock(&tty->ldisc_mutex);
- /*
- * Now kill off the ldisc
- */
- tty_ldisc_close(tty, tty->ldisc);
- tty_ldisc_put(tty->ldisc);
- /* Force an oops if we mess this up */
- tty->ldisc = NULL;
+ if (o_tty) {
+ tty_ldisc_halt(o_tty);
+ tty_ldisc_flush_works(o_tty);
+ }
+ tty_lock_pair(tty, o_tty);
- /* Ensure the next open requests the N_TTY ldisc */
- tty_set_termios_ldisc(tty, N_TTY);
- mutex_unlock(&tty->ldisc_mutex);
- /* This will need doing differently if we need to lock */
+ tty_ldisc_kill(tty);
if (o_tty)
- tty_ldisc_release(o_tty, NULL);
+ tty_ldisc_kill(o_tty);
/* And the memory resources remaining (buffers, termios) will be
disposed of when the kref hits zero */
diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c
index 9ff986c..67feac9 100644
--- a/drivers/tty/tty_mutex.c
+++ b/drivers/tty/tty_mutex.c
@@ -4,29 +4,70 @@
#include <linux/semaphore.h>
#include <linux/sched.h>
-/*
- * The 'big tty mutex'
- *
- * This mutex is taken and released by tty_lock() and tty_unlock(),
- * replacing the older big kernel lock.
- * It can no longer be taken recursively, and does not get
- * released implicitly while sleeping.
- *
- * Don't use in new code.
- */
-static DEFINE_MUTEX(big_tty_mutex);
+/* Legacy tty mutex glue */
+
+enum {
+ TTY_MUTEX_NORMAL,
+ TTY_MUTEX_NESTED,
+};
/*
* Getting the big tty mutex.
*/
-void __lockfunc tty_lock(void)
+
+static void __lockfunc tty_lock_nested(struct tty_struct *tty,
+ unsigned int subclass)
{
- mutex_lock(&big_tty_mutex);
+ if (tty->magic != TTY_MAGIC) {
+ printk(KERN_ERR "L Bad %p\n", tty);
+ WARN_ON(1);
+ return;
+ }
+ tty_kref_get(tty);
+ mutex_lock_nested(&tty->legacy_mutex, subclass);
+}
+
+void __lockfunc tty_lock(struct tty_struct *tty)
+{
+ return tty_lock_nested(tty, TTY_MUTEX_NORMAL);
}
EXPORT_SYMBOL(tty_lock);
-void __lockfunc tty_unlock(void)
+void __lockfunc tty_unlock(struct tty_struct *tty)
{
- mutex_unlock(&big_tty_mutex);
+ if (tty->magic != TTY_MAGIC) {
+ printk(KERN_ERR "U Bad %p\n", tty);
+ WARN_ON(1);
+ return;
+ }
+ mutex_unlock(&tty->legacy_mutex);
+ tty_kref_put(tty);
}
EXPORT_SYMBOL(tty_unlock);
+
+/*
+ * Getting the big tty mutex for a pair of ttys with lock ordering
+ * On a non pty/tty pair tty2 can be NULL which is just fine.
+ */
+void __lockfunc tty_lock_pair(struct tty_struct *tty,
+ struct tty_struct *tty2)
+{
+ if (tty < tty2) {
+ tty_lock(tty);
+ tty_lock_nested(tty2, TTY_MUTEX_NESTED);
+ } else {
+ if (tty2 && tty2 != tty)
+ tty_lock(tty2);
+ tty_lock_nested(tty, TTY_MUTEX_NESTED);
+ }
+}
+EXPORT_SYMBOL(tty_lock_pair);
+
+void __lockfunc tty_unlock_pair(struct tty_struct *tty,
+ struct tty_struct *tty2)
+{
+ tty_unlock(tty);
+ if (tty2 && tty2 != tty)
+ tty_unlock(tty2);
+}
+EXPORT_SYMBOL(tty_unlock_pair);
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index c9a0c1f..f5ee6f1 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -230,7 +230,7 @@ int tty_port_block_til_ready(struct tty_port *port,
/* block if port is in the process of being closed */
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
- wait_event_interruptible_tty(port->close_wait,
+ wait_event_interruptible_tty(tty, port->close_wait,
!(port->flags & ASYNC_CLOSING));
if (port->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN;
@@ -296,9 +296,9 @@ int tty_port_block_til_ready(struct tty_port *port,
retval = -ERESTARTSYS;
break;
}
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
finish_wait(&port->open_wait, &wait);
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 4132d9e..0e31891 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -268,6 +268,7 @@ struct tty_struct {
struct mutex ldisc_mutex;
struct tty_ldisc *ldisc;
+ struct mutex legacy_mutex;
struct mutex termios_mutex;
spinlock_t ctrl_lock;
/* Termios values are protected by the termios mutex */
@@ -604,8 +605,12 @@ extern long vt_compat_ioctl(struct tty_struct *tty,
/* tty_mutex.c */
/* functions for preparation of BKL removal */
-extern void __lockfunc tty_lock(void) __acquires(tty_lock);
-extern void __lockfunc tty_unlock(void) __releases(tty_lock);
+extern void __lockfunc tty_lock(struct tty_struct *tty);
+extern void __lockfunc tty_unlock(struct tty_struct *tty);
+extern void __lockfunc tty_lock_pair(struct tty_struct *tty,
+ struct tty_struct *tty2);
+extern void __lockfunc tty_unlock_pair(struct tty_struct *tty,
+ struct tty_struct *tty2);
/*
* this shall be called only from where BTM is held (like close)
@@ -620,9 +625,9 @@ extern void __lockfunc tty_unlock(void) __releases(tty_lock);
static inline void tty_wait_until_sent_from_close(struct tty_struct *tty,
long timeout)
{
- tty_unlock(); /* tty->ops->close holds the BTM, drop it while waiting */
+ tty_unlock(tty); /* tty->ops->close holds the BTM, drop it while waiting */
tty_wait_until_sent(tty, timeout);
- tty_lock();
+ tty_lock(tty);
}
/*
@@ -637,16 +642,16 @@ static inline void tty_wait_until_sent_from_close(struct tty_struct *tty,
*
* Do not use in new code.
*/
-#define wait_event_interruptible_tty(wq, condition) \
+#define wait_event_interruptible_tty(tty, wq, condition) \
({ \
int __ret = 0; \
if (!(condition)) { \
- __wait_event_interruptible_tty(wq, condition, __ret); \
+ __wait_event_interruptible_tty(tty, wq, condition, __ret); \
} \
__ret; \
})
-#define __wait_event_interruptible_tty(wq, condition, ret) \
+#define __wait_event_interruptible_tty(tty, wq, condition, ret) \
do { \
DEFINE_WAIT(__wait); \
\
@@ -655,9 +660,9 @@ do { \
if (condition) \
break; \
if (!signal_pending(current)) { \
- tty_unlock(); \
+ tty_unlock(tty); \
schedule(); \
- tty_lock(); \
+ tty_lock(tty); \
continue; \
} \
ret = -ERESTARTSYS; \
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 363bca1..18679a4 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -710,9 +710,9 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
break;
}
- tty_unlock();
+ tty_unlock(tty);
schedule();
- tty_lock();
+ tty_lock(tty);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&dev->wait, &wait);
^ permalink raw reply related
* Re: [PATCH V2 5/6] x86: add CONFIG_ARM_AMBA, selected by STA2X11
From: H. Peter Anvin @ 2012-06-28 20:06 UTC (permalink / raw)
To: Alessandro Rubini
Cc: linux-kernel, Giancarlo Asnaghi, Alan Cox, Russell King, x86,
Greg Kroah-Hartman, Arnd Bergmann, linux-arm-kernel, linux-serial,
linux-arch
In-Reply-To: <f85fefb10b7a7407b77180be65b18bf0426145b9.1338222461.git.rubini@gnudd.com>
On 05/28/2012 09:37 AM, Alessandro Rubini wrote:
> The sta2x11 I/O Hub is a bridge from PCIe to AMBA. It reuses a number
> of amba drivers and needs to activate core bus support.
>
> Signed-off-by: Alessandro Rubini <rubini@gnudd.com>
> Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
> ---
> arch/x86/Kconfig | 4 ++++
> 1 files changed, 4 insertions(+), 0 deletions(-)
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index 91dea918..112718f 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -500,6 +500,7 @@ config STA2X11
> select SWIOTLB
> select MFD_STA2X11
> select ARCH_REQUIRE_GPIOLIB
> + select ARM_AMBA
> default n
> ---help---
> This adds support for boards based on the STA2X11 IO-Hub,
> @@ -2173,6 +2174,9 @@ config GEOS
>
> endif # X86_32
>
> +config ARM_AMBA
> + bool
> +
> config AMD_NB
> def_bool y
> depends on CPU_SUP_AMD && PCI
Nacked-by: H. Peter Anvin <hpa@zytor.com>
This brings in tons of code into the x86 all{yes,mod}config builds, and
as perhaps one could expect some of it doesn't compile. For example:
/home/hpa/kernel/tip.x86-platform/drivers/dma/pl330.c: In function
‘dmac_alloc_resources’:
/home/hpa/kernel/tip.x86-platform/drivers/dma/pl330.c:2056:2: warning:
passing argument 3 of ‘dma_alloc_attrs’ from incompatible
pointer type [enabled by default]
In file included from
/home/hpa/kernel/tip.x86-platform/include/linux/dma-mapping.h:73:0,
from
/home/hpa/kernel/tip.x86-platform/drivers/dma/pl330.c:22:
/home/hpa/kernel/tip.x86-platform/arch/x86/include/asm/dma-mapping.h:130:1:
note: expected ‘dma_addr_t *’ but argument is of typ
e ‘u32 *’
CC sound/pci/au88x0/au8830.o
/home/hpa/kernel/tip.x86-platform/drivers/dma/pl330.c:73:0: warning:
"DS" redefined [enabled by default]
In file included from
/home/hpa/kernel/tip.x86-platform/arch/x86/include/asm/ptrace.h:5:0,
from
/home/hpa/kernel/tip.x86-platform/arch/x86/include/asm/vm86.h:130,
from
/home/hpa/kernel/tip.x86-platform/arch/x86/include/asm/processor.h:10,
from
/home/hpa/kernel/tip.x86-platform/arch/x86/include/asm/thread_info.h:22,
from
/home/hpa/kernel/tip.x86-platform/include/linux/thread_info.h:54,
from
/home/hpa/kernel/tip.x86-platform/include/linux/preempt.h:9,
from
/home/hpa/kernel/tip.x86-platform/include/linux/spinlock.h:50,
from
/home/hpa/kernel/tip.x86-platform/include/linux/vmalloc.h:4,
from
/home/hpa/kernel/tip.x86-platform/arch/x86/include/asm/io.h:195,
from
/home/hpa/kernel/tip.x86-platform/include/linux/io.h:22,
from
/home/hpa/kernel/tip.x86-platform/drivers/dma/pl330.c:15:
/home/hpa/kernel/tip.x86-platform/arch/x86/include/asm/ptrace-abi.h:13:0: note:
this is the location of the previous definition
/home/hpa/kernel/tip.x86-platform/drivers/dma/pl330.c:89:0: warning:
"ES" redefined [enabled by default]
In file included from
/home/hpa/kernel/tip.x86-platform/arch/x86/include/asm/ptrace.h:5:0,
from
/home/hpa/kernel/tip.x86-platform/arch/x86/include/asm/vm86.h:130,
from
/home/hpa/kernel/tip.x86-platform/arch/x86/include/asm/processor.h:10,
from
/home/hpa/kernel/tip.x86-platform/arch/x86/include/asm/thread_info.h:22,
from
/home/hpa/kernel/tip.x86-platform/include/linux/thread_info.h:54,
from
/home/hpa/kernel/tip.x86-platform/include/linux/preempt.h:9,
from
/home/hpa/kernel/tip.x86-platform/include/linux/spinlock.h:50,
from
/home/hpa/kernel/tip.x86-platform/include/linux/vmalloc.h:4,
from
/home/hpa/kernel/tip.x86-platform/arch/x86/include/asm/io.h:195,
from
/home/hpa/kernel/tip.x86-platform/include/linux/io.h:22,
from
/home/hpa/kernel/tip.x86-platform/drivers/dma/pl330.c:15:
/home/hpa/kernel/tip.x86-platform/arch/x86/include/asm/ptrace-abi.h:14:0: note:
this is the location of the previous definition
/home/hpa/kernel/tip.x86-platform/drivers/dma/pl330.c:100:0: warning:
"CS" redefined [enabled by default]
In file included from
/home/hpa/kernel/tip.x86-platform/arch/x86/include/asm/ptrace.h:5:0,
from
/home/hpa/kernel/tip.x86-platform/arch/x86/include/asm/vm86.h:130,
from
/home/hpa/kernel/tip.x86-platform/arch/x86/include/asm/processor.h:10,
from
/home/hpa/kernel/tip.x86-platform/arch/x86/include/asm/thread_info.h:22,
from
/home/hpa/kernel/tip.x86-platform/include/linux/thread_info.h:54,
from
/home/hpa/kernel/tip.x86-platform/include/linux/preempt.h:9,
from
/home/hpa/kernel/tip.x86-platform/include/linux/spinlock.h:50,
from
/home/hpa/kernel/tip.x86-platform/include/linux/vmalloc.h:4,
from
/home/hpa/kernel/tip.x86-platform/arch/x86/include/asm/io.h:195,
from
/home/hpa/kernel/tip.x86-platform/include/linux/io.h:22,
from
/home/hpa/kernel/tip.x86-platform/drivers/dma/pl330.c:15:
/home/hpa/kernel/tip.x86-platform/arch/x86/include/asm/ptrace-abi.h:19:0: note:
this is the location of the previous definition
CC drivers/dma/pch_dma.o
CC drivers/dma/amba-pl08x.o
/home/hpa/kernel/tip.x86-platform/drivers/dma/amba-pl08x.c:86:32: fatal
error: asm/hardware/pl080.h: No such file or directory
compilation terminated.
make[4]: *** [drivers/dma/amba-pl08x.o] Error 1
make[3]: *** [drivers/dma] Error 2
make[2]: *** [drivers] Error 2
make[2]: *** Waiting for unfinished jobs....
--
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel. I don't speak on their behalf.
^ permalink raw reply
* Re: artpec.c / serial_core.c hardware flow control problem
From: Alan Cox @ 2012-06-28 16:24 UTC (permalink / raw)
To: Mikael Johansson
Cc: linux-serial, Mikael Starvik, Jesper Nilsson, Johan Adolfsson
In-Reply-To: <4FEC7857.6010006@axis.com>
On Thu, 28 Jun 2012 17:29:27 +0200
Mikael Johansson <mikael.lars.johansson@axis.com> wrote:
> Greetings,
>
> We have a problem with drivers/serial/artpec.c (Not yet in main tree)
> which uses hardware supported flow control (XON/XOFF). We do cfmakeraw()
> and tcsetattr() from userspace to set a termios struct where (c_iflag &
> IXON) is not set. The problem is that the call to tcsetattr() is not
> propagated down to serial_artpec_set_termios(), the reason being that
> uart_set_termios() doesn't think that IXON is a RELEVANT_IFLAG and
> returns prematurely instead of calling uart_change_speed -->
> ops->set_termios().
>
> Could this be fixed by making IXON a RELEVANT_IFLAG?:
That's actually insufficient for those cases - you can set the characters
used for things as well plus IXANY and IXOFF.
It's a stupid "optimisation" and the only reason I didn't get rid of it
before was in case it broke something else. Time for it to go.
So yeah - I'd just delete it.
If you are doing hardware XON/XOFF watch c_cc[VSTART] and c_cc[VSTOP].
Those control the symbol used for soft flow control.
Alan
^ permalink raw reply
* artpec.c / serial_core.c hardware flow control problem
From: Mikael Johansson @ 2012-06-28 15:29 UTC (permalink / raw)
To: linux-serial; +Cc: Mikael Starvik, Jesper Nilsson, Johan Adolfsson
Greetings,
We have a problem with drivers/serial/artpec.c (Not yet in main tree)
which uses hardware supported flow control (XON/XOFF). We do cfmakeraw()
and tcsetattr() from userspace to set a termios struct where (c_iflag &
IXON) is not set. The problem is that the call to tcsetattr() is not
propagated down to serial_artpec_set_termios(), the reason being that
uart_set_termios() doesn't think that IXON is a RELEVANT_IFLAG and
returns prematurely instead of calling uart_change_speed -->
ops->set_termios().
Could this be fixed by making IXON a RELEVANT_IFLAG?:
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 7f28307..d45473d 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1211,7 +1211,7 @@ static void uart_set_termios(struct tty_struct *tty,
* bits in c_cflag; c_[io]speed will always be set
* appropriately by set_termios() in tty_ioctl.c
*/
-#define RELEVANT_IFLAG(iflag) ((iflag) &
(IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+#define RELEVANT_IFLAG(iflag) ((iflag) &
(IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|IXON))
if ((cflag ^ old_termios->c_cflag) == 0 &&
tty->termios->c_ospeed == old_termios->c_ospeed &&
tty->termios->c_ispeed == old_termios->c_ispeed &&
Or should it be fixed at some other level?
Note: This was tested on 2.6.35 but appears to have the same code in the
newer kernels. Not many drivers seem to look at the IXON flag, only
crisv10, omap_serial and jsm_neo.
Best regards,
Mikael Johansson
^ permalink raw reply related
* OMAP4430ES2 UART garbage on v3.5-rc4
From: Paul Walmsley @ 2012-06-28 8:28 UTC (permalink / raw)
To: balbi, govindraj.raja; +Cc: khilman, linux-omap, linux-serial
Hi,
On 4430ES2 Panda, the serial port prints garbage at the end of long
transmissions from the board when dynamic idle is enabled. Here's an
example (search for "Minicom2.6.1"):
http://www.pwsan.com/omap/testlogs/am35xx_devel_3.6/20120628014213/pm/4430es2panda_log.txt
My recollection is that this used to happen on some earlier kernels after
the OMAP serial Ragnarok a few months ago, but it was masked by some other
issue up until v3.5-rc4..
Who is looking after the OMAP UART driver these days?
- Paul
^ permalink raw reply
* Hey! This may be interesting for you...
From: Essie Widmer @ 2012-06-28 0:18 UTC (permalink / raw)
To: edds@comcast.net
Hello darling?)
I won’t waste your time for no reason and I will switch over to the general issue – I’m looking for a man who can satisfy me fully, you know what I mean, right?;) I got tired of sissies and men who can’t even take care of themselves.
About myself in three words – young, wild and free. You may switch the word ‘young’ on ‘beautiful’ if you’d like). I've got no hang-ups and BDSM is the only bad habit I got.
Anyway if you aren’t afraid of girls like me then u r lucky.
Please reply and I’ll write you more about myself. Also we can share some (even erotic) pictures as well.) I’m pretty sure that it will turn out to be an interesting meeting.
Don't think too long! I'm waiting for you!
Can't wait to talk to you!
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 06/12] 8250: use the 8250 register interface not the legacy one
From: Alan Cox @ 2012-06-27 22:50 UTC (permalink / raw)
To: Paul Gortmaker; +Cc: greg, linux-serial
In-Reply-To: <CAP=VYLopNPeYCi4uQoHuqU0vWFF5hc4J9x3uzSOXJVv=DGLLWw@mail.gmail.com>
On Wed, 27 Jun 2012 18:39:53 -0400
Paul Gortmaker <paul.gortmaker@windriver.com> wrote:
> On Wed, Jun 27, 2012 at 7:22 AM, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
> > From: Alan Cox <alan@linux.intel.com>
> >
> > The old interface just copies bits over and calls the newer one.
> > In addition we can now pass more information.
> >
> > Signed-off-by: Alan Cox <alan@linux.intel.com>
> > ---
>
> [...]
>
> > - * serial8250_register_port and serial8250_unregister_port allows for
> > + * serial8250_register_8250_port and serial8250_unregister_port allows
>
> This seems a bit lopsided. Can we convert the unregister too, and
> then just keep the old names, and avoid the doubling up on the
> presence of 8250 in the name? (I confess to having not looked
> at the code to seeing if there is an obvious barrier to doing this),
That wouldn't be a bad idea for a follow up. I didn't pick the names -
they were changed earlier so that we could have both APIs. Now the old
API is gone we could at some point rename it back - but that ought to
wait a while so any out of tree stuff continues to break for a bit to
avoid accidents.
Alan
^ permalink raw reply
* Re: [PATCH 06/12] 8250: use the 8250 register interface not the legacy one
From: Paul Gortmaker @ 2012-06-27 22:39 UTC (permalink / raw)
To: Alan Cox; +Cc: greg, linux-serial
In-Reply-To: <20120627112205.5678.80154.stgit@localhost.localdomain>
On Wed, Jun 27, 2012 at 7:22 AM, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
> From: Alan Cox <alan@linux.intel.com>
>
> The old interface just copies bits over and calls the newer one.
> In addition we can now pass more information.
>
> Signed-off-by: Alan Cox <alan@linux.intel.com>
> ---
[...]
> - * serial8250_register_port and serial8250_unregister_port allows for
> + * serial8250_register_8250_port and serial8250_unregister_port allows
This seems a bit lopsided. Can we convert the unregister too, and
then just keep the old names, and avoid the doubling up on the
presence of 8250 in the name? (I confess to having not looked
at the code to seeing if there is an obvious barrier to doing this),
Paul.
^ permalink raw reply
* Re: 2.6.25 upgraded to 2.6.36: serial app stops working
From: folkert @ 2012-06-27 20:26 UTC (permalink / raw)
To: Greg KH; +Cc: linux-serial
In-Reply-To: <20101130164232.GB18017@kroah.com>
> > I upgraded my linux system to 2.6.36. Now suddenly my serial driver for
> > my MSF receiver stopped working. Two things I noticed: I need to open
> > the serial device (/dev/ttyS0, a regular uart, see below) with O_NDELAY
> > for open() to return at all. Then something funny happens: I read bytes
> > from the device (at 50bps) which runs fine for a while but then suddenly
> > I get a burst of '0x00' bytes - precisely at the point at which the MSF
> > radio device sends a timecode! So I think the device fiddles with one of
> > the pins of the serial port confusing the linux serial driver. This
> > worked fine upto and including 2.6.25 (maybe later too) but with 2.6.36
> > this fails.
> > Anyone an idea what might go wrong here? And how to fix it?
>
> Any chance you could use 'git bisect' on the kernel tree to see what
> caused the change? Moving from .25 to .36 is a huge jump, many many
> years of development and loads of things have changed so we need some
> help to narrow the problem down.
Hmmm, I might have missed this message :-)
Anyway a few months ago I retried it and had same problem. BUT: the
other receiver I have, has a serial-to-usb converter in it. So it is an
USB device but maybe a special one? Anyway: it has exact the same
problem. It is possible that maybe they're just broken both.
As you may deduct from my replying-delay, it has no great priority for
me.
Folkert van Heusden
--
http://www.vanheusden.com/sysopview/ - for the real sysop
----------------------------------------------------------------------
Phone: +31-6-41278122, PGP-key: 1F28D8AE, www.vanheusden.com
^ permalink raw reply
* Re: [PATCH 01/12] f81232: correct stubbed termios handler
From: Greg KH @ 2012-06-27 19:35 UTC (permalink / raw)
To: Alan Cox; +Cc: linux-serial
In-Reply-To: <20120627112102.5678.4141.stgit@localhost.localdomain>
On Wed, Jun 27, 2012 at 12:21:04PM +0100, Alan Cox wrote:
> From: Alan Cox <alan@linux.intel.com>
>
> Signed-off-by: Alan Cox <alan@linux.intel.com>
> ---
>
> drivers/usb/serial/f81232.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c
> index 499b15f..acd3267 100644
> --- a/drivers/usb/serial/f81232.c
> +++ b/drivers/usb/serial/f81232.c
> @@ -177,6 +177,7 @@ static void f81232_set_termios(struct tty_struct *tty,
> return;
>
> /* Do the real work here... */
> + tty_termios_copy_hw(&tty->termios, old_termios);
This patch still breaks the build, so I'm guessing the others still have
the same issues I reported yesterday?
Care to redo these?
greg k-h
^ permalink raw reply
* Re: [PATCH 04/12] gpio-sch: Fix leak of resource
From: Greg KH @ 2012-06-27 19:32 UTC (permalink / raw)
To: Alan Cox; +Cc: linux-serial
In-Reply-To: <20120627112140.5678.79917.stgit@localhost.localdomain>
On Wed, Jun 27, 2012 at 12:21:42PM +0100, Alan Cox wrote:
> From: Alan Cox <alan@linux.intel.com>
>
> Signed-off-by: Alan Cox <alan@linux.intel.com>
> ---
>
> drivers/gpio/gpio-sch.c | 3 ++-
Again, I can't take this patch, it should go to the GPIO maintainer.
greg k-h
^ permalink raw reply
* Re: [PATCH 3/3] serial/8250: delete WR SBC850 UART quirk handling
From: Alan Cox @ 2012-06-27 14:37 UTC (permalink / raw)
To: Paul Gortmaker
Cc: benh, linuxppc-dev, Alan Cox, Greg Kroah-Hartman, linux-serial
In-Reply-To: <4FEB1307.7060209@windriver.com>
> I will, once Alpha is removed from the tree. At the moment,
> it still uses it.
Ok I hadn't realised that.
Alan
^ permalink raw reply
* Re: [PATCH 3/3] serial/8250: delete WR SBC850 UART quirk handling
From: Paul Gortmaker @ 2012-06-27 14:04 UTC (permalink / raw)
To: Alan Cox; +Cc: benh, linuxppc-dev, Alan Cox, Greg Kroah-Hartman, linux-serial
In-Reply-To: <20120627125242.08a3114e@pyramind.ukuu.org.uk>
On 12-06-27 07:52 AM, Alan Cox wrote:
> On Tue, 26 Jun 2012 15:54:29 -0400
> Paul Gortmaker <paul.gortmaker@windriver.com> wrote:
>
>> We've are dropping the support for the EOL SBC8560, so we can
>> also delete this variant of the Alpha quirk support.
>>
>> Cc: Alan Cox <alan@linux.intel.com>
>> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>> Cc: linux-serial@vger.kernel.org
>> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
>> ---
>> drivers/tty/serial/8250/8250.h | 7 -------
>> 1 files changed, 0 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
>> index f9719d1..ffd1e6e 100644
>> --- a/drivers/tty/serial/8250/8250.h
>> +++ b/drivers/tty/serial/8250/8250.h
>> @@ -119,13 +119,6 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value)
>> * is cleared, the machine locks up with endless interrupts.
>> */
>> #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
>
> Would you mind removing all of the crap from this if its going (eg
> 8250.c) not just the header so it gets missed ? Kill the symbol entirely ?
I will, once Alpha is removed from the tree. At the moment,
it still uses it.
Paul.
--
>
> Alan
^ permalink raw reply
* Re: [PATCH 3/3] serial/8250: delete WR SBC850 UART quirk handling
From: Alan Cox @ 2012-06-27 11:52 UTC (permalink / raw)
To: Paul Gortmaker
Cc: benh, linuxppc-dev, Alan Cox, Greg Kroah-Hartman, linux-serial
In-Reply-To: <1340740469-31445-4-git-send-email-paul.gortmaker@windriver.com>
On Tue, 26 Jun 2012 15:54:29 -0400
Paul Gortmaker <paul.gortmaker@windriver.com> wrote:
> We've are dropping the support for the EOL SBC8560, so we can
> also delete this variant of the Alpha quirk support.
>
> Cc: Alan Cox <alan@linux.intel.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: linux-serial@vger.kernel.org
> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
> ---
> drivers/tty/serial/8250/8250.h | 7 -------
> 1 files changed, 0 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
> index f9719d1..ffd1e6e 100644
> --- a/drivers/tty/serial/8250/8250.h
> +++ b/drivers/tty/serial/8250/8250.h
> @@ -119,13 +119,6 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value)
> * is cleared, the machine locks up with endless interrupts.
> */
> #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
Would you mind removing all of the crap from this if its going (eg
8250.c) not just the header so it gets missed ? Kill the symbol entirely ?
Alan
^ permalink raw reply
* [PATCH 12/12] tty: Move the handling of the tty release logic
From: Alan Cox @ 2012-06-27 11:23 UTC (permalink / raw)
To: greg, linux-serial
In-Reply-To: <20120627112102.5678.4141.stgit@localhost.localdomain>
From: Alan Cox <alan@linux.intel.com>
Now that we don't have tty->termios tied to drivers->tty we can untangle
the logic here. In addition we can push the removal logic out of the
destructor path.
At that point we can think about sorting out tty_port and console and all
the other ugly hangovers.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/tty/pty.c | 8 --------
drivers/tty/tty_io.c | 16 +++++-----------
drivers/tty/vt/vt.c | 1 -
drivers/usb/serial/usb-serial.c | 3 +--
include/linux/tty.h | 1 -
include/linux/tty_driver.h | 11 +++--------
6 files changed, 9 insertions(+), 31 deletions(-)
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 56dcef4..f1ba793 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -497,12 +497,6 @@ static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
return tty;
}
-static void pty_unix98_shutdown(struct tty_struct *tty)
-{
- tty_driver_remove_tty(tty->driver, tty);
- /* We have our own method as we don't use the tty index */
-}
-
/* We have no need to install and remove our tty objects as devpts does all
the work for us */
@@ -563,7 +557,6 @@ static const struct tty_operations ptm_unix98_ops = {
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
.ioctl = pty_unix98_ioctl,
- .shutdown = pty_unix98_shutdown,
.resize = pty_resize
};
@@ -579,7 +572,6 @@ static const struct tty_operations pty_unix98_ops = {
.chars_in_buffer = pty_chars_in_buffer,
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
- .shutdown = pty_unix98_shutdown
};
/**
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 14db2a8..e062c1b 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1443,12 +1443,6 @@ void tty_free_termios(struct tty_struct *tty)
}
EXPORT_SYMBOL(tty_free_termios);
-void tty_shutdown(struct tty_struct *tty)
-{
- tty_driver_remove_tty(tty->driver, tty);
- tty_free_termios(tty);
-}
-EXPORT_SYMBOL(tty_shutdown);
/**
* release_one_tty - release tty structure memory
@@ -1492,11 +1486,6 @@ static void queue_release_one_tty(struct kref *kref)
{
struct tty_struct *tty = container_of(kref, struct tty_struct, kref);
- if (tty->ops->shutdown)
- tty->ops->shutdown(tty);
- else
- tty_shutdown(tty);
-
/* The hangup queue is now free so we can reuse it rather than
waste a chunk of memory for each port */
INIT_WORK(&tty->hangup_work, release_one_tty);
@@ -1536,6 +1525,11 @@ static void release_tty(struct tty_struct *tty, int idx)
/* This should always be true but check for the moment */
WARN_ON(tty->index != idx);
+ if (tty->ops->shutdown)
+ tty->ops->shutdown(tty);
+ tty_free_termios(tty);
+ tty_driver_remove_tty(tty->driver, tty);
+
if (tty->link)
tty_kref_put(tty->link);
tty_kref_put(tty);
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 02c7cdd..2c9af9c 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -2839,7 +2839,6 @@ static void con_shutdown(struct tty_struct *tty)
console_lock();
vc->port.tty = NULL;
console_unlock();
- tty_shutdown(tty);
}
static int default_italic_color = 2; // green (ASCII)
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 003b191..3bca1ea 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -305,8 +305,7 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
* Do the resource freeing and refcount dropping for the port.
* Avoid freeing the console.
*
- * Called asynchronously after the last tty kref is dropped,
- * and the tty layer has already done the tty_shutdown(tty);
+ * Called asynchronously after the last tty kref is dropped.
*/
static void serial_cleanup(struct tty_struct *tty)
{
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 86fce83..4132d9e 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -423,7 +423,6 @@ extern void tty_unthrottle(struct tty_struct *tty);
extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws);
extern void tty_driver_remove_tty(struct tty_driver *driver,
struct tty_struct *tty);
-extern void tty_shutdown(struct tty_struct *tty);
extern void tty_free_termios(struct tty_struct *tty);
extern int is_current_pgrp_orphaned(void);
extern struct pid *tty_get_pgrp(struct tty_struct *tty);
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index 6e6dbb7..2bcf2a9 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -45,14 +45,9 @@
*
* void (*shutdown)(struct tty_struct * tty);
*
- * This routine is called synchronously when a particular tty device
- * is closed for the last time freeing up the resources.
- * Note that tty_shutdown() is not called if ops->shutdown is defined.
- * This means one is responsible to take care of calling ops->remove (e.g.
- * via tty_driver_remove_tty) and releasing tty->termios.
- * Note that this hook may be called from *all* the contexts where one
- * uses tty refcounting (e.g. tty_port_tty_get).
- *
+ * This routine is called under the tty lock when a particular tty device
+ * is closed for the last time. It executes before the tty resources
+ * are freed so may execute while another function holds a tty kref.
*
* void (*cleanup)(struct tty_struct * tty);
*
^ permalink raw reply related
* [PATCH 11/12] vt: fix the keyboard/led locking
From: Alan Cox @ 2012-06-27 11:23 UTC (permalink / raw)
To: greg, linux-serial
In-Reply-To: <20120627112102.5678.4141.stgit@localhost.localdomain>
From: Alan Cox <alan@linux.intel.com>
We touch the LED from both keyboard callback and direct paths. In
one case we've got the lock held way up the call chain and in the
other we haven't. This leads to complete insanity so fix it by giving
the LED bits their own lock.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/tty/vt/keyboard.c | 42 ++++++++++++++++++++++--------------------
include/linux/kbd_kern.h | 1 -
2 files changed, 22 insertions(+), 21 deletions(-)
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 48cc6f2..816cbbd 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -119,6 +119,7 @@ static const int NR_TYPES = ARRAY_SIZE(max_vals);
static struct input_handler kbd_handler;
static DEFINE_SPINLOCK(kbd_event_lock);
+static DEFINE_SPINLOCK(led_lock);
static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)]; /* keyboard key bitmap */
static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
static bool dead_key_next;
@@ -984,7 +985,7 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
* or (ii) whatever pattern of lights people want to show using KDSETLED,
* or (iii) specified bits of specified words in kernel memory.
*/
-unsigned char getledstate(void)
+static unsigned char getledstate(void)
{
return ledstate;
}
@@ -992,7 +993,7 @@ unsigned char getledstate(void)
void setledstate(struct kbd_struct *kbd, unsigned int led)
{
unsigned long flags;
- spin_lock_irqsave(&kbd_event_lock, flags);
+ spin_lock_irqsave(&led_lock, flags);
if (!(led & ~7)) {
ledioctl = led;
kbd->ledmode = LED_SHOW_IOCTL;
@@ -1000,7 +1001,7 @@ void setledstate(struct kbd_struct *kbd, unsigned int led)
kbd->ledmode = LED_SHOW_FLAGS;
set_leds();
- spin_unlock_irqrestore(&kbd_event_lock, flags);
+ spin_unlock_irqrestore(&led_lock, flags);
}
static inline unsigned char getleds(void)
@@ -1053,9 +1054,9 @@ int vt_get_leds(int console, int flag)
struct kbd_struct * kbd = kbd_table + console;
int ret;
- spin_lock_irqsave(&kbd_event_lock, flags);
+ spin_lock_irqsave(&led_lock, flags);
ret = vc_kbd_led(kbd, flag);
- spin_unlock_irqrestore(&kbd_event_lock, flags);
+ spin_unlock_irqrestore(&led_lock, flags);
return ret;
}
@@ -1091,11 +1092,11 @@ void vt_set_led_state(int console, int leds)
void vt_kbd_con_start(int console)
{
struct kbd_struct * kbd = kbd_table + console;
-/* unsigned long flags; */
-/* spin_lock_irqsave(&kbd_event_lock, flags); */
+ unsigned long flags;
+ spin_lock_irqsave(&led_lock, flags);
clr_vc_kbd_led(kbd, VC_SCROLLOCK);
set_leds();
-/* spin_unlock_irqrestore(&kbd_event_lock, flags); */
+ spin_unlock_irqrestore(&led_lock, flags);
}
/**
@@ -1104,21 +1105,15 @@ void vt_kbd_con_start(int console)
*
* Handle console stop. This is a wrapper for the VT layer
* so that we can keep kbd knowledge internal
- *
- * FIXME: We eventually need to hold the kbd lock here to protect
- * the LED updating. We can't do it yet because fn_hold calls stop_tty
- * and start_tty under the kbd_event_lock, while normal tty paths
- * don't hold the lock. We probably need to split out an LED lock
- * but not during an -rc release!
*/
void vt_kbd_con_stop(int console)
{
struct kbd_struct * kbd = kbd_table + console;
-/* unsigned long flags; */
-/* spin_lock_irqsave(&kbd_event_lock, flags); */
+ unsigned long flags;
+ spin_lock_irqsave(&led_lock, flags);
set_vc_kbd_led(kbd, VC_SCROLLOCK);
set_leds();
-/* spin_unlock_irqrestore(&kbd_event_lock, flags); */
+ spin_unlock_irqrestore(&led_lock, flags);
}
/*
@@ -1130,7 +1125,12 @@ void vt_kbd_con_stop(int console)
*/
static void kbd_bh(unsigned long dummy)
{
- unsigned char leds = getleds();
+ unsigned char leds;
+ unsigned long flags;
+
+ spin_lock_irqsave(&led_lock, flags);
+ leds = getleds();
+ spin_unlock_irqrestore(&led_lock, flags);
if (leds != ledstate) {
input_handler_for_each_handle(&kbd_handler, &leds,
@@ -2035,11 +2035,11 @@ int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm)
return -EPERM;
if (arg & ~0x77)
return -EINVAL;
- spin_lock_irqsave(&kbd_event_lock, flags);
+ spin_lock_irqsave(&led_lock, flags);
kbd->ledflagstate = (arg & 7);
kbd->default_ledflagstate = ((arg >> 4) & 7);
set_leds();
- spin_unlock_irqrestore(&kbd_event_lock, flags);
+ spin_unlock_irqrestore(&led_lock, flags);
return 0;
/* the ioctls below only set the lights, not the functions */
@@ -2134,8 +2134,10 @@ void vt_reset_keyboard(int console)
clr_vc_kbd_mode(kbd, VC_CRLF);
kbd->lockstate = 0;
kbd->slockstate = 0;
+ spin_lock(&led_lock);
kbd->ledmode = LED_SHOW_FLAGS;
kbd->ledflagstate = kbd->default_ledflagstate;
+ spin_unlock(&led_lock);
/* do not do set_leds here because this causes an endless tasklet loop
when the keyboard hasn't been initialized yet */
spin_unlock_irqrestore(&kbd_event_lock, flags);
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index daf4a3a..37d5877 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -65,7 +65,6 @@ struct kbd_struct {
extern int kbd_init(void);
-extern unsigned char getledstate(void);
extern void setledstate(struct kbd_struct *kbd, unsigned int led);
extern int do_poke_blanked_console;
^ permalink raw reply related
* [PATCH 10/12] tty: tidy up the RESET_TERMIOS case
From: Alan Cox @ 2012-06-27 11:22 UTC (permalink / raw)
To: greg, linux-serial
In-Reply-To: <20120627112102.5678.4141.stgit@localhost.localdomain>
From: Alan Cox <alan@linux.intel.com>
If we are going to reset the termios then we don't need the driver side
buffers at all as we now have the tty allocation.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/tty/tty_io.c | 45 +++++++++++++++++++++++----------------------
1 file changed, 23 insertions(+), 22 deletions(-)
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index f5c8d4f..14db2a8 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1249,16 +1249,20 @@ int tty_init_termios(struct tty_struct *tty)
struct ktermios *tp;
int idx = tty->index;
- tp = tty->driver->termios[idx];
- if (tp == NULL) {
- tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL);
- if (tp == NULL)
- return -ENOMEM;
- *tp = tty->driver->init_termios;
- tty->driver->termios[idx] = tp;
- }
- tty->termios = *tp;
-
+ if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
+ tty->termios = tty->driver->init_termios;
+ else {
+ tp = tty->driver->termios[idx];
+ if (tp == NULL) {
+ tp = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
+ if (tp == NULL)
+ return -ENOMEM;
+ tp[0] = tty->driver->init_termios;
+ tty->driver->termios[idx] = tp;
+ }
+ tty->termios = tp[0];
+ tty->termios_locked = tp[1];
+ }
/* Compatibility until drivers always set this */
tty->termios.c_ispeed = tty_termios_input_baud_rate(&tty->termios);
tty->termios.c_ospeed = tty_termios_baud_rate(&tty->termios);
@@ -1432,16 +1436,9 @@ err_release_tty:
void tty_free_termios(struct tty_struct *tty)
{
- struct ktermios *tp;
int idx = tty->index;
/* Kill this flag and push into drivers for locking etc */
- if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
- /* FIXME: Locking on ->termios array */
- tp = tty->driver->termios[idx];
- tty->driver->termios[idx] = NULL;
- kfree(tp);
- }
- else
+ if (!(tty->driver->flags & TTY_DRIVER_RESET_TERMIOS))
*tty->driver->termios[idx] = tty->termios;
}
EXPORT_SYMBOL(tty_free_termios);
@@ -3069,16 +3066,19 @@ static void destruct_tty_driver(struct kref *kref)
* drivers are removed from the kernel.
*/
for (i = 0; i < driver->num; i++) {
- tp = driver->termios[i];
- if (tp) {
- driver->termios[i] = NULL;
- kfree(tp);
+ if (!(driver->flags & TTY_DRIVER_RESET_TERMIOS)) {
+ tp = driver->termios[i];
+ if (tp) {
+ driver->termios[i] = NULL;
+ kfree(tp);
+ }
}
if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV))
tty_unregister_device(driver, i);
}
p = driver->ttys;
proc_tty_unregister_driver(driver);
+ /* FIXME: who frees driver->termios itself */
driver->ttys = NULL;
driver->termios = NULL;
kfree(p);
@@ -3117,6 +3117,7 @@ int tty_register_driver(struct tty_driver *driver)
void **p = NULL;
struct device *d;
+ /* FIXME: at this point we are overallocating for the RESET_TERMIOS case */
if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL);
if (!p)
^ permalink raw reply related
* [PATCH 08/12] 8250: add support for ASIX devices with a FIFO bug
From: Alan Cox @ 2012-06-27 11:22 UTC (permalink / raw)
To: greg, linux-serial
In-Reply-To: <20120627112102.5678.4141.stgit@localhost.localdomain>
From: Alan Cox <alan@linux.intel.com>
Information and a different patch provided by <donald@asix.com.tw>. We do
it a little differently to keep the modularity and to avoid playing with
RLSI.
We add a new uart bug for the parity flaw and set it in the pci matches.
If parity check is enabled then we drop the FIFO trigger to 1 as per the
Asix reference code.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/tty/serial/8250/8250.c | 8 ++++++--
drivers/tty/serial/8250/8250.h | 1 +
drivers/tty/serial/8250/8250_pci.c | 24 +++++++++++++++++++++---
3 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index 779d791..641768c 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -2194,6 +2194,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
unsigned char cval, fcr = 0;
unsigned long flags;
unsigned int baud, quot;
+ int fifo_bug = 0;
switch (termios->c_cflag & CSIZE) {
case CS5:
@@ -2213,8 +2214,11 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
if (termios->c_cflag & CSTOPB)
cval |= UART_LCR_STOP;
- if (termios->c_cflag & PARENB)
+ if (termios->c_cflag & PARENB) {
cval |= UART_LCR_PARITY;
+ if (up->bugs & UART_BUG_PARITY)
+ fifo_bug = 1;
+ }
if (!(termios->c_cflag & PARODD))
cval |= UART_LCR_EPAR;
#ifdef CMSPAR
@@ -2238,7 +2242,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
fcr = uart_config[port->type].fcr;
- if (baud < 2400) {
+ if (baud < 2400 || fifo_bug) {
fcr &= ~UART_FCR_TRIGGER_MASK;
fcr |= UART_FCR_TRIGGER_1;
}
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index f9719d1..c335b2b 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -78,6 +78,7 @@ struct serial8250_config {
#define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */
#define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */
#define UART_BUG_THRE (1 << 3) /* UART has buggy THRE reassertion */
+#define UART_BUG_PARITY (1 << 4) /* UART mishandles parity if FIFO enabled */
#define PROBE_RSA (1 << 0)
#define PROBE_ANY (~0)
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 7269b15..8f137d8 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1032,8 +1032,15 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
return number_uarts;
}
-static int
-pci_default_setup(struct serial_private *priv,
+static int pci_asix_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_8250_port *port, int idx)
+{
+ port->bugs |= UART_BUG_PARITY;
+ return pci_default_setup(priv, board, port, idx);
+}
+
+static int pci_default_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
@@ -1187,6 +1194,7 @@ pci_xr17c154_setup(struct serial_private *priv,
#define PCIE_DEVICE_ID_NEO_2_OX_IBM 0x00F6
#define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001
#define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d
+#define PCI_VENDOR_ID_ASIX 0x9710
/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
@@ -1726,7 +1734,17 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_omegapci_setup,
- },
+ },
+ /*
+ * ASIX devices with FIFO bug
+ */
+ {
+ .vendor = PCI_VENDOR_ID_ASIX,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_asix_setup,
+ },
/*
* Default "match everything" terminator entry
*/
^ permalink raw reply related
* [PATCH 07/12] 8250: propogate the bugs field
From: Alan Cox @ 2012-06-27 11:22 UTC (permalink / raw)
To: greg, linux-serial
In-Reply-To: <20120627112102.5678.4141.stgit@localhost.localdomain>
From: Alan Cox <alan@linux.intel.com>
Now we are using the uart_8250_port this is trivial
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/tty/serial/8250/8250.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index 5e3f6a3..779d791 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -3147,6 +3147,7 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
uart->port.regshift = up->port.regshift;
uart->port.iotype = up->port.iotype;
uart->port.flags = up->port.flags | UPF_BOOT_AUTOCONF;
+ uart->bugs = up->bugs;
uart->port.mapbase = up->port.mapbase;
uart->port.private_data = up->port.private_data;
if (up->port.dev)
^ permalink raw reply related
* [PATCH 06/12] 8250: use the 8250 register interface not the legacy one
From: Alan Cox @ 2012-06-27 11:22 UTC (permalink / raw)
To: greg, linux-serial
In-Reply-To: <20120627112102.5678.4141.stgit@localhost.localdomain>
From: Alan Cox <alan@linux.intel.com>
The old interface just copies bits over and calls the newer one.
In addition we can now pass more information.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/tty/serial/8250/8250.c | 71 +++++++++-----------------
drivers/tty/serial/8250/8250_acorn.c | 22 ++++----
drivers/tty/serial/8250/8250_dw.c | 38 +++++++-------
drivers/tty/serial/8250/8250_gsc.c | 26 +++++-----
drivers/tty/serial/8250/8250_hp300.c | 26 +++++-----
drivers/tty/serial/8250/8250_pci.c | 92 +++++++++++++++++-----------------
drivers/tty/serial/8250/8250_pnp.c | 28 +++++-----
drivers/tty/serial/8250/serial_cs.c | 30 ++++++-----
include/linux/serial_8250.h | 1
9 files changed, 155 insertions(+), 179 deletions(-)
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index 47d061b..5e3f6a3 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -2971,36 +2971,36 @@ void serial8250_resume_port(int line)
static int __devinit serial8250_probe(struct platform_device *dev)
{
struct plat_serial8250_port *p = dev->dev.platform_data;
- struct uart_port port;
+ struct uart_8250_port uart;
int ret, i, irqflag = 0;
- memset(&port, 0, sizeof(struct uart_port));
+ memset(&uart, 0, sizeof(uart));
if (share_irqs)
irqflag = IRQF_SHARED;
for (i = 0; p && p->flags != 0; p++, i++) {
- port.iobase = p->iobase;
- port.membase = p->membase;
- port.irq = p->irq;
- port.irqflags = p->irqflags;
- port.uartclk = p->uartclk;
- port.regshift = p->regshift;
- port.iotype = p->iotype;
- port.flags = p->flags;
- port.mapbase = p->mapbase;
- port.hub6 = p->hub6;
- port.private_data = p->private_data;
- port.type = p->type;
- port.serial_in = p->serial_in;
- port.serial_out = p->serial_out;
- port.handle_irq = p->handle_irq;
- port.handle_break = p->handle_break;
- port.set_termios = p->set_termios;
- port.pm = p->pm;
- port.dev = &dev->dev;
- port.irqflags |= irqflag;
- ret = serial8250_register_port(&port);
+ uart.port.iobase = p->iobase;
+ uart.port.membase = p->membase;
+ uart.port.irq = p->irq;
+ uart.port.irqflags = p->irqflags;
+ uart.port.uartclk = p->uartclk;
+ uart.port.regshift = p->regshift;
+ uart.port.iotype = p->iotype;
+ uart.port.flags = p->flags;
+ uart.port.mapbase = p->mapbase;
+ uart.port.hub6 = p->hub6;
+ uart.port.private_data = p->private_data;
+ uart.port.type = p->type;
+ uart.port.serial_in = p->serial_in;
+ uart.port.serial_out = p->serial_out;
+ uart.port.handle_irq = p->handle_irq;
+ uart.port.handle_break = p->handle_break;
+ uart.port.set_termios = p->set_termios;
+ uart.port.pm = p->pm;
+ uart.port.dev = &dev->dev;
+ uart.port.irqflags |= irqflag;
+ ret = serial8250_register_8250_port(&uart);
if (ret < 0) {
dev_err(&dev->dev, "unable to register port at index %d "
"(IO%lx MEM%llx IRQ%d): %d\n", i,
@@ -3073,7 +3073,7 @@ static struct platform_driver serial8250_isa_driver = {
static struct platform_device *serial8250_isa_devs;
/*
- * serial8250_register_port and serial8250_unregister_port allows for
+ * serial8250_register_8250_port and serial8250_unregister_port allows for
* 16x50 serial ports to be configured at run-time, to support PCMCIA
* modems and PCI multiport cards.
*/
@@ -3190,29 +3190,6 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
EXPORT_SYMBOL(serial8250_register_8250_port);
/**
- * serial8250_register_port - register a serial port
- * @port: serial port template
- *
- * Configure the serial port specified by the request. If the
- * port exists and is in use, it is hung up and unregistered
- * first.
- *
- * The port is then probed and if necessary the IRQ is autodetected
- * If this fails an error is returned.
- *
- * On success the port is ready to use and the line number is returned.
- */
-int serial8250_register_port(struct uart_port *port)
-{
- struct uart_8250_port up;
-
- memset(&up, 0, sizeof(up));
- memcpy(&up.port, port, sizeof(*port));
- return serial8250_register_8250_port(&up);
-}
-EXPORT_SYMBOL(serial8250_register_port);
-
-/**
* serial8250_unregister_port - remove a 16x50 serial port at runtime
* @line: serial line number
*
diff --git a/drivers/tty/serial/8250/8250_acorn.c b/drivers/tty/serial/8250/8250_acorn.c
index b0ce8c5..8574983 100644
--- a/drivers/tty/serial/8250/8250_acorn.c
+++ b/drivers/tty/serial/8250/8250_acorn.c
@@ -43,7 +43,7 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct serial_card_info *info;
struct serial_card_type *type = id->data;
- struct uart_port port;
+ struct uart_8250_port uart;
unsigned long bus_addr;
unsigned int i;
@@ -62,19 +62,19 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
ecard_set_drvdata(ec, info);
- memset(&port, 0, sizeof(struct uart_port));
- port.irq = ec->irq;
- port.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
- port.uartclk = type->uartclk;
- port.iotype = UPIO_MEM;
- port.regshift = 2;
- port.dev = &ec->dev;
+ memset(&uart, 0, sizeof(struct uart_8250_port));
+ uart.port.irq = ec->irq;
+ uart.port.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ uart.port.uartclk = type->uartclk;
+ uart.port.iotype = UPIO_MEM;
+ uart.port.regshift = 2;
+ uart.port.dev = &ec->dev;
for (i = 0; i < info->num_ports; i ++) {
- port.membase = info->vaddr + type->offset[i];
- port.mapbase = bus_addr + type->offset[i];
+ uart.port.membase = info->vaddr + type->offset[i];
+ uart.port.mapbase = bus_addr + type->offset[i];
- info->ports[i] = serial8250_register_port(&port);
+ info->ports[i] = serial8250_register_8250_port(&uart);
}
return 0;
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index f574eef..afb955f 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -89,7 +89,7 @@ static int dw8250_handle_irq(struct uart_port *p)
static int __devinit dw8250_probe(struct platform_device *pdev)
{
- struct uart_port port = {};
+ struct uart_8250_port uart = {};
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
struct device_node *np = pdev->dev.of_node;
@@ -104,28 +104,28 @@ static int __devinit dw8250_probe(struct platform_device *pdev)
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- port.private_data = data;
-
- spin_lock_init(&port.lock);
- port.mapbase = regs->start;
- port.irq = irq->start;
- port.handle_irq = dw8250_handle_irq;
- port.type = PORT_8250;
- port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
+ uart.port.private_data = data;
+
+ spin_lock_init(&uart.port.lock);
+ uart.port.mapbase = regs->start;
+ uart.port.irq = irq->start;
+ uart.port.handle_irq = dw8250_handle_irq;
+ uart.port.type = PORT_8250;
+ uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
UPF_FIXED_PORT | UPF_FIXED_TYPE;
- port.dev = &pdev->dev;
+ uart.port.dev = &pdev->dev;
- port.iotype = UPIO_MEM;
- port.serial_in = dw8250_serial_in;
- port.serial_out = dw8250_serial_out;
+ uart.port.iotype = UPIO_MEM;
+ uart.port.serial_in = dw8250_serial_in;
+ uart.port.serial_out = dw8250_serial_out;
if (!of_property_read_u32(np, "reg-io-width", &val)) {
switch (val) {
case 1:
break;
case 4:
- port.iotype = UPIO_MEM32;
- port.serial_in = dw8250_serial_in32;
- port.serial_out = dw8250_serial_out32;
+ uart.port.iotype = UPIO_MEM32;
+ uart.port.serial_in = dw8250_serial_in32;
+ uart.port.serial_out = dw8250_serial_out32;
break;
default:
dev_err(&pdev->dev, "unsupported reg-io-width (%u)\n",
@@ -135,15 +135,15 @@ static int __devinit dw8250_probe(struct platform_device *pdev)
}
if (!of_property_read_u32(np, "reg-shift", &val))
- port.regshift = val;
+ uart.port.regshift = val;
if (of_property_read_u32(np, "clock-frequency", &val)) {
dev_err(&pdev->dev, "no clock-frequency property set\n");
return -EINVAL;
}
- port.uartclk = val;
+ uart.uart.port.uartclk = val;
- data->line = serial8250_register_port(&port);
+ data->line = serial8250_register_8250_port(&uart);
if (data->line < 0)
return data->line;
diff --git a/drivers/tty/serial/8250/8250_gsc.c b/drivers/tty/serial/8250/8250_gsc.c
index d8c0ffb..097dff9 100644
--- a/drivers/tty/serial/8250/8250_gsc.c
+++ b/drivers/tty/serial/8250/8250_gsc.c
@@ -26,7 +26,7 @@
static int __init serial_init_chip(struct parisc_device *dev)
{
- struct uart_port port;
+ struct uart_8250_port uart;
unsigned long address;
int err;
@@ -48,21 +48,21 @@ static int __init serial_init_chip(struct parisc_device *dev)
if (dev->id.sversion != 0x8d)
address += 0x800;
- memset(&port, 0, sizeof(port));
- port.iotype = UPIO_MEM;
+ memset(&uart, 0, sizeof(uart));
+ uart.port.iotype = UPIO_MEM;
/* 7.272727MHz on Lasi. Assumed the same for Dino, Wax and Timi. */
- port.uartclk = 7272727;
- port.mapbase = address;
- port.membase = ioremap_nocache(address, 16);
- port.irq = dev->irq;
- port.flags = UPF_BOOT_AUTOCONF;
- port.dev = &dev->dev;
-
- err = serial8250_register_port(&port);
+ uart.port.uartclk = 7272727;
+ uart.port.mapbase = address;
+ uart.port.membase = ioremap_nocache(address, 16);
+ uart.port.irq = dev->irq;
+ uart.port.flags = UPF_BOOT_AUTOCONF;
+ uart.port.dev = &dev->dev;
+
+ err = serial8250_register_8250_port(&uart);
if (err < 0) {
printk(KERN_WARNING
- "serial8250_register_port returned error %d\n", err);
- iounmap(port.membase);
+ "serial8250_register_8250_port returned error %d\n", err);
+ iounmap(uart.port.membase);
return err;
}
diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c
index c13438c..8f1dd2c 100644
--- a/drivers/tty/serial/8250/8250_hp300.c
+++ b/drivers/tty/serial/8250/8250_hp300.c
@@ -171,7 +171,7 @@ static int __devinit hpdca_init_one(struct dio_dev *d,
return 0;
}
#endif
- memset(&port, 0, sizeof(struct uart_port));
+ memset(&uart, 0, sizeof(uart));
/* Memory mapped I/O */
port.iotype = UPIO_MEM;
@@ -182,7 +182,7 @@ static int __devinit hpdca_init_one(struct dio_dev *d,
port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
port.regshift = 1;
port.dev = &d->dev;
- line = serial8250_register_port(&port);
+ line = serial8250_register_8250_port(&uart);
if (line < 0) {
printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d"
@@ -210,7 +210,7 @@ static int __init hp300_8250_init(void)
#ifdef CONFIG_HPAPCI
int line;
unsigned long base;
- struct uart_port uport;
+ struct uart_8250_port uart;
struct hp300_port *port;
int i;
#endif
@@ -248,26 +248,26 @@ static int __init hp300_8250_init(void)
if (!port)
return -ENOMEM;
- memset(&uport, 0, sizeof(struct uart_port));
+ memset(&uart, 0, sizeof(uart));
base = (FRODO_BASE + FRODO_APCI_OFFSET(i));
/* Memory mapped I/O */
- uport.iotype = UPIO_MEM;
- uport.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \
+ uart.port.iotype = UPIO_MEM;
+ uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \
| UPF_BOOT_AUTOCONF;
/* XXX - no interrupt support yet */
- uport.irq = 0;
- uport.uartclk = HPAPCI_BAUD_BASE * 16;
- uport.mapbase = base;
- uport.membase = (char *)(base + DIO_VIRADDRBASE);
- uport.regshift = 2;
+ uart.port.irq = 0;
+ uart.port.uartclk = HPAPCI_BAUD_BASE * 16;
+ uart.port.mapbase = base;
+ uart.port.membase = (char *)(base + DIO_VIRADDRBASE);
+ uart.port.regshift = 2;
- line = serial8250_register_port(&uport);
+ line = serial8250_register_8250_port(&uart);
if (line < 0) {
printk(KERN_NOTICE "8250_hp300: register_serial() APCI"
- " %d irq %d failed\n", i, uport.irq);
+ " %d irq %d failed\n", i, uart.port.irq);
kfree(port);
continue;
}
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 28e7c7c..7269b15 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -44,7 +44,7 @@ struct pci_serial_quirk {
int (*init)(struct pci_dev *dev);
int (*setup)(struct serial_private *,
const struct pciserial_board *,
- struct uart_port *, int);
+ struct uart_8250_port *, int);
void (*exit)(struct pci_dev *dev);
};
@@ -59,7 +59,7 @@ struct serial_private {
};
static int pci_default_setup(struct serial_private*,
- const struct pciserial_board*, struct uart_port*, int);
+ const struct pciserial_board*, struct uart_8250_port *, int);
static void moan_device(const char *str, struct pci_dev *dev)
{
@@ -74,7 +74,7 @@ static void moan_device(const char *str, struct pci_dev *dev)
}
static int
-setup_port(struct serial_private *priv, struct uart_port *port,
+setup_port(struct serial_private *priv, struct uart_8250_port *port,
int bar, int offset, int regshift)
{
struct pci_dev *dev = priv->dev;
@@ -93,17 +93,17 @@ setup_port(struct serial_private *priv, struct uart_port *port,
if (!priv->remapped_bar[bar])
return -ENOMEM;
- port->iotype = UPIO_MEM;
- port->iobase = 0;
- port->mapbase = base + offset;
- port->membase = priv->remapped_bar[bar] + offset;
- port->regshift = regshift;
+ port->port.iotype = UPIO_MEM;
+ port->port.iobase = 0;
+ port->port.mapbase = base + offset;
+ port->port.membase = priv->remapped_bar[bar] + offset;
+ port->port.regshift = regshift;
} else {
- port->iotype = UPIO_PORT;
- port->iobase = base + offset;
- port->mapbase = 0;
- port->membase = NULL;
- port->regshift = 0;
+ port->port.iotype = UPIO_PORT;
+ port->port.iobase = base + offset;
+ port->port.mapbase = 0;
+ port->port.membase = NULL;
+ port->port.regshift = 0;
}
return 0;
}
@@ -113,7 +113,7 @@ setup_port(struct serial_private *priv, struct uart_port *port,
*/
static int addidata_apci7800_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar = 0, offset = board->first_offset;
bar = FL_GET_BASE(board->flags);
@@ -140,7 +140,7 @@ static int addidata_apci7800_setup(struct serial_private *priv,
*/
static int
afavlab_setup(struct serial_private *priv, const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -195,7 +195,7 @@ static int pci_hp_diva_init(struct pci_dev *dev)
static int
pci_hp_diva_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int offset = board->first_offset;
unsigned int bar = FL_GET_BASE(board->flags);
@@ -370,7 +370,7 @@ static void __devexit pci_ni8430_exit(struct pci_dev *dev)
/* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */
static int
sbs_setup(struct serial_private *priv, const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -525,7 +525,7 @@ static int pci_siig_init(struct pci_dev *dev)
static int pci_siig_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0;
@@ -619,7 +619,7 @@ static int pci_timedia_init(struct pci_dev *dev)
static int
pci_timedia_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar = 0, offset = board->first_offset;
@@ -653,7 +653,7 @@ pci_timedia_setup(struct serial_private *priv,
static int
titan_400l_800l_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -754,7 +754,7 @@ static int pci_ni8430_init(struct pci_dev *dev)
static int
pci_ni8430_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
void __iomem *p;
unsigned long base, len;
@@ -781,7 +781,7 @@ pci_ni8430_setup(struct serial_private *priv,
static int pci_netmos_9900_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar;
@@ -1035,7 +1035,7 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
static int
pci_default_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
unsigned int bar, offset = board->first_offset, maxnr;
@@ -1057,15 +1057,15 @@ pci_default_setup(struct serial_private *priv,
static int
ce4100_serial_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
int ret;
ret = setup_port(priv, port, 0, 0, board->reg_shift);
- port->iotype = UPIO_MEM32;
- port->type = PORT_XSCALE;
- port->flags = (port->flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
- port->regshift = 2;
+ port->port.iotype = UPIO_MEM32;
+ port->port.type = PORT_XSCALE;
+ port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
+ port->port.regshift = 2;
return ret;
}
@@ -1073,16 +1073,16 @@ ce4100_serial_setup(struct serial_private *priv,
static int
pci_omegapci_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
return setup_port(priv, port, 2, idx * 8, 0);
}
static int skip_tx_en_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
- port->flags |= UPF_NO_TXEN_TEST;
+ port->port.flags |= UPF_NO_TXEN_TEST;
printk(KERN_DEBUG "serial8250: skipping TxEn test for device "
"[%04x:%04x] subsystem [%04x:%04x]\n",
priv->dev->vendor,
@@ -1131,11 +1131,11 @@ static unsigned int kt_serial_in(struct uart_port *p, int offset)
static int kt_serial_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
- port->flags |= UPF_BUG_THRE;
- port->serial_in = kt_serial_in;
- port->handle_break = kt_handle_break;
+ port->port.flags |= UPF_BUG_THRE;
+ port->port.serial_in = kt_serial_in;
+ port->port.handle_break = kt_handle_break;
return skip_tx_en_setup(priv, board, port, idx);
}
@@ -1151,9 +1151,9 @@ static int pci_eg20t_init(struct pci_dev *dev)
static int
pci_xr17c154_setup(struct serial_private *priv,
const struct pciserial_board *board,
- struct uart_port *port, int idx)
+ struct uart_8250_port *port, int idx)
{
- port->flags |= UPF_EXAR_EFR;
+ port->port.flags |= UPF_EXAR_EFR;
return pci_default_setup(priv, board, port, idx);
}
@@ -2728,7 +2728,7 @@ serial_pci_matches(const struct pciserial_board *board,
struct serial_private *
pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
{
- struct uart_port serial_port;
+ struct uart_8250_port uart;
struct serial_private *priv;
struct pci_serial_quirk *quirk;
int rc, nr_ports, i;
@@ -2768,22 +2768,22 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
priv->dev = dev;
priv->quirk = quirk;
- memset(&serial_port, 0, sizeof(struct uart_port));
- serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
- serial_port.uartclk = board->base_baud * 16;
- serial_port.irq = get_pci_irq(dev, board);
- serial_port.dev = &dev->dev;
+ memset(&uart, 0, sizeof(uart));
+ uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ uart.port.uartclk = board->base_baud * 16;
+ uart.port.irq = get_pci_irq(dev, board);
+ uart.port.dev = &dev->dev;
for (i = 0; i < nr_ports; i++) {
- if (quirk->setup(priv, board, &serial_port, i))
+ if (quirk->setup(priv, board, &uart, i))
break;
#ifdef SERIAL_DEBUG_PCI
printk(KERN_DEBUG "Setup PCI port: port %lx, irq %d, type %d\n",
- serial_port.iobase, serial_port.irq, serial_port.iotype);
+ uart.port.iobase, uart.port.irq, uart.port.iotype);
#endif
- priv->line[i] = serial8250_register_port(&serial_port);
+ priv->line[i] = serial8250_register_8250_port(&uart);
if (priv->line[i] < 0) {
printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]);
break;
diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c
index a2f2365..fde5aa6 100644
--- a/drivers/tty/serial/8250/8250_pnp.c
+++ b/drivers/tty/serial/8250/8250_pnp.c
@@ -424,7 +424,7 @@ static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags)
static int __devinit
serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
{
- struct uart_port port;
+ struct uart_8250_port uart;
int ret, line, flags = dev_id->driver_data;
if (flags & UNKNOWN_DEV) {
@@ -433,32 +433,32 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
return ret;
}
- memset(&port, 0, sizeof(struct uart_port));
+ memset(&uart, 0, sizeof(uart));
if (pnp_irq_valid(dev, 0))
- port.irq = pnp_irq(dev, 0);
+ uart.port.irq = pnp_irq(dev, 0);
if (pnp_port_valid(dev, 0)) {
- port.iobase = pnp_port_start(dev, 0);
- port.iotype = UPIO_PORT;
+ uart.port.iobase = pnp_port_start(dev, 0);
+ uart.port.iotype = UPIO_PORT;
} else if (pnp_mem_valid(dev, 0)) {
- port.mapbase = pnp_mem_start(dev, 0);
- port.iotype = UPIO_MEM;
- port.flags = UPF_IOREMAP;
+ uart.port.mapbase = pnp_mem_start(dev, 0);
+ uart.port.iotype = UPIO_MEM;
+ uart.port.flags = UPF_IOREMAP;
} else
return -ENODEV;
#ifdef SERIAL_DEBUG_PNP
printk(KERN_DEBUG
"Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n",
- port.iobase, port.mapbase, port.irq, port.iotype);
+ uart.port.iobase, uart.port.mapbase, uart.port.irq, uart.port.iotype);
#endif
- port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
+ uart.port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE)
- port.flags |= UPF_SHARE_IRQ;
- port.uartclk = 1843200;
- port.dev = &dev->dev;
+ uart.port.flags |= UPF_SHARE_IRQ;
+ uart.port.uartclk = 1843200;
+ uart.port.dev = &dev->dev;
- line = serial8250_register_port(&port);
+ line = serial8250_register_8250_port(&uart);
if (line < 0)
return -ENODEV;
diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c
index 29b695d..b7d48b3 100644
--- a/drivers/tty/serial/8250/serial_cs.c
+++ b/drivers/tty/serial/8250/serial_cs.c
@@ -73,7 +73,7 @@ struct serial_quirk {
unsigned int prodid;
int multi; /* 1 = multifunction, > 1 = # ports */
void (*config)(struct pcmcia_device *);
- void (*setup)(struct pcmcia_device *, struct uart_port *);
+ void (*setup)(struct pcmcia_device *, struct uart_8250_port *);
void (*wakeup)(struct pcmcia_device *);
int (*post)(struct pcmcia_device *);
};
@@ -105,9 +105,9 @@ struct serial_cfg_mem {
* Elan VPU16551 UART with 14.7456MHz oscillator
* manfid 0x015D, 0x4C45
*/
-static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_port *port)
+static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_8250_port *uart)
{
- port->uartclk = 14745600;
+ uart->port.uartclk = 14745600;
}
static int quirk_post_ibm(struct pcmcia_device *link)
@@ -343,25 +343,25 @@ static void serial_detach(struct pcmcia_device *link)
static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
unsigned int iobase, int irq)
{
- struct uart_port port;
+ struct uart_8250_port uart;
int line;
- memset(&port, 0, sizeof (struct uart_port));
- port.iobase = iobase;
- port.irq = irq;
- port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
- port.uartclk = 1843200;
- port.dev = &handle->dev;
+ memset(&uart, 0, sizeof(uart));
+ uart.port.iobase = iobase;
+ uart.port.irq = irq;
+ uart.port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
+ uart.port.uartclk = 1843200;
+ uart.port.dev = &handle->dev;
if (buggy_uart)
- port.flags |= UPF_BUGGY_UART;
+ uart.port.flags |= UPF_BUGGY_UART;
if (info->quirk && info->quirk->setup)
- info->quirk->setup(handle, &port);
+ info->quirk->setup(handle, &uart);
- line = serial8250_register_port(&port);
+ line = serial8250_register_8250_port(&uart);
if (line < 0) {
- printk(KERN_NOTICE "serial_cs: serial8250_register_port() at "
- "0x%04lx, irq %d failed\n", (u_long)iobase, irq);
+ pr_err("serial_cs: serial8250_register_8250_port() at 0x%04lx, irq %d failed\n",
+ (unsigned long)iobase, irq);
return -EINVAL;
}
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index a416e92..f41dcc9 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -69,7 +69,6 @@ struct uart_port;
struct uart_8250_port;
int serial8250_register_8250_port(struct uart_8250_port *);
-int serial8250_register_port(struct uart_port *);
void serial8250_unregister_port(int line);
void serial8250_suspend_port(int line);
void serial8250_resume_port(int line);
^ permalink raw reply related
* [PATCH 05/12] usb, kobil: Sort out some bogus tty handling
From: Alan Cox @ 2012-06-27 11:21 UTC (permalink / raw)
To: greg, linux-serial
In-Reply-To: <20120627112102.5678.4141.stgit@localhost.localdomain>
From: Alan Cox <alan@linux.intel.com>
Stuff noticed while doing the termios conversion.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/usb/serial/kobil_sct.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index fafeabb..0852472 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -192,8 +192,8 @@ static void kobil_init_termios(struct tty_struct *tty)
{
/* Default to echo off and other sane device settings */
tty->termios->c_lflag = 0;
- tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE);
- tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF;
+ tty->termios->c_iflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE);
+ tty->termios->c_iflag |= IGNBRK | IGNPAR | IXOFF;
/* do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) */
tty->termios->c_oflag &= ~ONLCR;
}
@@ -588,7 +588,7 @@ static void kobil_set_termios(struct tty_struct *tty,
if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
/* This device doesn't support ioctl calls */
- *tty->termios = *old;
+ tty_termios_copy_hw(tty->termios, old_termios);
return;
}
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox