Skip to content

Commit 54e3f3e

Browse files
committed
Merge tag 'tty-4.5-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial fixes from Greg KH: "Here are some small tty/serial driver fixes for 4.5-rc2. They resolve a number of reported problems (the ioctl one specifically has been pointed out by numerous people) and one patch adds some new device ids for the 8250_pci driver. All have been in linux-next successfully" * tag 'tty-4.5-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: serial: 8250_pci: Add Intel Broadwell ports staging/speakup: Use tty_ldisc_ref() for paste kworker n_tty: Fix unsafe reference to "other" ldisc tty: Fix unsafe ldisc reference via ioctl(TIOCGETD) tty: Retry failed reopen if tty teardown in-progress tty: Wait interruptibly for tty lock on reopen
2 parents 8c4e378 + 6c55d9b commit 54e3f3e

File tree

6 files changed

+82
-12
lines changed

6 files changed

+82
-12
lines changed

drivers/staging/speakup/selection.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,9 @@ static void __speakup_paste_selection(struct work_struct *work)
142142
struct tty_ldisc *ld;
143143
DECLARE_WAITQUEUE(wait, current);
144144

145-
ld = tty_ldisc_ref_wait(tty);
145+
ld = tty_ldisc_ref(tty);
146+
if (!ld)
147+
goto tty_unref;
146148
tty_buffer_lock_exclusive(&vc->port);
147149

148150
add_wait_queue(&vc->paste_wait, &wait);
@@ -162,6 +164,7 @@ static void __speakup_paste_selection(struct work_struct *work)
162164

163165
tty_buffer_unlock_exclusive(&vc->port);
164166
tty_ldisc_deref(ld);
167+
tty_unref:
165168
tty_kref_put(tty);
166169
}
167170

drivers/tty/n_tty.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -269,16 +269,13 @@ static void n_tty_check_throttle(struct tty_struct *tty)
269269

270270
static void n_tty_check_unthrottle(struct tty_struct *tty)
271271
{
272-
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
273-
tty->link->ldisc->ops->write_wakeup == n_tty_write_wakeup) {
272+
if (tty->driver->type == TTY_DRIVER_TYPE_PTY) {
274273
if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE)
275274
return;
276275
if (!tty->count)
277276
return;
278277
n_tty_kick_worker(tty);
279-
n_tty_write_wakeup(tty->link);
280-
if (waitqueue_active(&tty->link->write_wait))
281-
wake_up_interruptible_poll(&tty->link->write_wait, POLLOUT);
278+
tty_wakeup(tty->link);
282279
return;
283280
}
284281

drivers/tty/serial/8250/8250_pci.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,6 +1379,9 @@ ce4100_serial_setup(struct serial_private *priv,
13791379
#define PCI_DEVICE_ID_INTEL_BSW_UART1 0x228a
13801380
#define PCI_DEVICE_ID_INTEL_BSW_UART2 0x228c
13811381

1382+
#define PCI_DEVICE_ID_INTEL_BDW_UART1 0x9ce3
1383+
#define PCI_DEVICE_ID_INTEL_BDW_UART2 0x9ce4
1384+
13821385
#define BYT_PRV_CLK 0x800
13831386
#define BYT_PRV_CLK_EN (1 << 0)
13841387
#define BYT_PRV_CLK_M_VAL_SHIFT 1
@@ -1461,11 +1464,13 @@ byt_serial_setup(struct serial_private *priv,
14611464
switch (pdev->device) {
14621465
case PCI_DEVICE_ID_INTEL_BYT_UART1:
14631466
case PCI_DEVICE_ID_INTEL_BSW_UART1:
1467+
case PCI_DEVICE_ID_INTEL_BDW_UART1:
14641468
rx_param->src_id = 3;
14651469
tx_param->dst_id = 2;
14661470
break;
14671471
case PCI_DEVICE_ID_INTEL_BYT_UART2:
14681472
case PCI_DEVICE_ID_INTEL_BSW_UART2:
1473+
case PCI_DEVICE_ID_INTEL_BDW_UART2:
14691474
rx_param->src_id = 5;
14701475
tx_param->dst_id = 4;
14711476
break;
@@ -2062,6 +2067,20 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
20622067
.subdevice = PCI_ANY_ID,
20632068
.setup = byt_serial_setup,
20642069
},
2070+
{
2071+
.vendor = PCI_VENDOR_ID_INTEL,
2072+
.device = PCI_DEVICE_ID_INTEL_BDW_UART1,
2073+
.subvendor = PCI_ANY_ID,
2074+
.subdevice = PCI_ANY_ID,
2075+
.setup = byt_serial_setup,
2076+
},
2077+
{
2078+
.vendor = PCI_VENDOR_ID_INTEL,
2079+
.device = PCI_DEVICE_ID_INTEL_BDW_UART2,
2080+
.subvendor = PCI_ANY_ID,
2081+
.subdevice = PCI_ANY_ID,
2082+
.setup = byt_serial_setup,
2083+
},
20652084
/*
20662085
* ITE
20672086
*/
@@ -5506,6 +5525,16 @@ static struct pci_device_id serial_pci_tbl[] = {
55065525
PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
55075526
pbn_byt },
55085527

5528+
/* Intel Broadwell */
5529+
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BDW_UART1,
5530+
PCI_ANY_ID, PCI_ANY_ID,
5531+
PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
5532+
pbn_byt },
5533+
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BDW_UART2,
5534+
PCI_ANY_ID, PCI_ANY_ID,
5535+
PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
5536+
pbn_byt },
5537+
55095538
/*
55105539
* Intel Quark x1000
55115540
*/

drivers/tty/tty_io.c

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,13 +1463,13 @@ static int tty_reopen(struct tty_struct *tty)
14631463
{
14641464
struct tty_driver *driver = tty->driver;
14651465

1466-
if (!tty->count)
1467-
return -EIO;
1468-
14691466
if (driver->type == TTY_DRIVER_TYPE_PTY &&
14701467
driver->subtype == PTY_TYPE_MASTER)
14711468
return -EIO;
14721469

1470+
if (!tty->count)
1471+
return -EAGAIN;
1472+
14731473
if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN))
14741474
return -EBUSY;
14751475

@@ -2065,7 +2065,12 @@ static int tty_open(struct inode *inode, struct file *filp)
20652065

20662066
if (tty) {
20672067
mutex_unlock(&tty_mutex);
2068-
tty_lock(tty);
2068+
retval = tty_lock_interruptible(tty);
2069+
if (retval) {
2070+
if (retval == -EINTR)
2071+
retval = -ERESTARTSYS;
2072+
goto err_unref;
2073+
}
20692074
/* safe to drop the kref from tty_driver_lookup_tty() */
20702075
tty_kref_put(tty);
20712076
retval = tty_reopen(tty);
@@ -2083,7 +2088,11 @@ static int tty_open(struct inode *inode, struct file *filp)
20832088

20842089
if (IS_ERR(tty)) {
20852090
retval = PTR_ERR(tty);
2086-
goto err_file;
2091+
if (retval != -EAGAIN || signal_pending(current))
2092+
goto err_file;
2093+
tty_free_file(filp);
2094+
schedule();
2095+
goto retry_open;
20872096
}
20882097

20892098
tty_add_file(tty, filp);
@@ -2152,6 +2161,7 @@ static int tty_open(struct inode *inode, struct file *filp)
21522161
return 0;
21532162
err_unlock:
21542163
mutex_unlock(&tty_mutex);
2164+
err_unref:
21552165
/* after locks to avoid deadlock */
21562166
if (!IS_ERR_OR_NULL(driver))
21572167
tty_driver_kref_put(driver);
@@ -2648,6 +2658,28 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
26482658
return ret;
26492659
}
26502660

2661+
/**
2662+
* tiocgetd - get line discipline
2663+
* @tty: tty device
2664+
* @p: pointer to user data
2665+
*
2666+
* Retrieves the line discipline id directly from the ldisc.
2667+
*
2668+
* Locking: waits for ldisc reference (in case the line discipline
2669+
* is changing or the tty is being hungup)
2670+
*/
2671+
2672+
static int tiocgetd(struct tty_struct *tty, int __user *p)
2673+
{
2674+
struct tty_ldisc *ld;
2675+
int ret;
2676+
2677+
ld = tty_ldisc_ref_wait(tty);
2678+
ret = put_user(ld->ops->num, p);
2679+
tty_ldisc_deref(ld);
2680+
return ret;
2681+
}
2682+
26512683
/**
26522684
* send_break - performed time break
26532685
* @tty: device to break on
@@ -2874,7 +2906,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
28742906
case TIOCGSID:
28752907
return tiocgsid(tty, real_tty, p);
28762908
case TIOCGETD:
2877-
return put_user(tty->ldisc->ops->num, (int __user *)p);
2909+
return tiocgetd(tty, p);
28782910
case TIOCSETD:
28792911
return tiocsetd(tty, p);
28802912
case TIOCVHANGUP:

drivers/tty/tty_mutex.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ void __lockfunc tty_lock(struct tty_struct *tty)
1919
}
2020
EXPORT_SYMBOL(tty_lock);
2121

22+
int tty_lock_interruptible(struct tty_struct *tty)
23+
{
24+
if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty))
25+
return -EIO;
26+
tty_kref_get(tty);
27+
return mutex_lock_interruptible(&tty->legacy_mutex);
28+
}
29+
2230
void __lockfunc tty_unlock(struct tty_struct *tty)
2331
{
2432
if (WARN(tty->magic != TTY_MAGIC, "U Bad %p\n", tty))

include/linux/tty.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,7 @@ extern long vt_compat_ioctl(struct tty_struct *tty,
649649
/* tty_mutex.c */
650650
/* functions for preparation of BKL removal */
651651
extern void __lockfunc tty_lock(struct tty_struct *tty);
652+
extern int tty_lock_interruptible(struct tty_struct *tty);
652653
extern void __lockfunc tty_unlock(struct tty_struct *tty);
653654
extern void __lockfunc tty_lock_slave(struct tty_struct *tty);
654655
extern void __lockfunc tty_unlock_slave(struct tty_struct *tty);

0 commit comments

Comments
 (0)