Commit 4da81fa2 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'tty-5.11-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty/serial fixes from Greg KH:
 "Here are three small tty/serial fixes for 5.11-rc5 to resolve reported
  problems:

   - two patches to fix up writing to ttys with splice

   - mvebu-uart driver fix for reported problem

  All of these have been in linux-next with no reported problems"

* tag 'tty-5.11-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  tty: fix up hung_up_tty_write() conversion
  tty: implement write_iter
  serial: mvebu-uart: fix tx lost characters at power off
parents 8f3bfd21 17749851
...@@ -648,6 +648,14 @@ static void wait_for_xmitr(struct uart_port *port) ...@@ -648,6 +648,14 @@ static void wait_for_xmitr(struct uart_port *port)
(val & STAT_TX_RDY(port)), 1, 10000); (val & STAT_TX_RDY(port)), 1, 10000);
} }
static void wait_for_xmite(struct uart_port *port)
{
u32 val;
readl_poll_timeout_atomic(port->membase + UART_STAT, val,
(val & STAT_TX_EMP), 1, 10000);
}
static void mvebu_uart_console_putchar(struct uart_port *port, int ch) static void mvebu_uart_console_putchar(struct uart_port *port, int ch)
{ {
wait_for_xmitr(port); wait_for_xmitr(port);
...@@ -675,7 +683,7 @@ static void mvebu_uart_console_write(struct console *co, const char *s, ...@@ -675,7 +683,7 @@ static void mvebu_uart_console_write(struct console *co, const char *s,
uart_console_write(port, s, count, mvebu_uart_console_putchar); uart_console_write(port, s, count, mvebu_uart_console_putchar);
wait_for_xmitr(port); wait_for_xmite(port);
if (ier) if (ier)
writel(ier, port->membase + UART_CTRL(port)); writel(ier, port->membase + UART_CTRL(port));
......
...@@ -143,9 +143,8 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */ ...@@ -143,9 +143,8 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */
DEFINE_MUTEX(tty_mutex); DEFINE_MUTEX(tty_mutex);
static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);
static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *); static ssize_t tty_write(struct kiocb *, struct iov_iter *);
ssize_t redirected_tty_write(struct file *, const char __user *, ssize_t redirected_tty_write(struct kiocb *, struct iov_iter *);
size_t, loff_t *);
static __poll_t tty_poll(struct file *, poll_table *); static __poll_t tty_poll(struct file *, poll_table *);
static int tty_open(struct inode *, struct file *); static int tty_open(struct inode *, struct file *);
long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg); long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
...@@ -438,8 +437,7 @@ static ssize_t hung_up_tty_read(struct file *file, char __user *buf, ...@@ -438,8 +437,7 @@ static ssize_t hung_up_tty_read(struct file *file, char __user *buf,
return 0; return 0;
} }
static ssize_t hung_up_tty_write(struct file *file, const char __user *buf, static ssize_t hung_up_tty_write(struct kiocb *iocb, struct iov_iter *from)
size_t count, loff_t *ppos)
{ {
return -EIO; return -EIO;
} }
...@@ -478,7 +476,8 @@ static void tty_show_fdinfo(struct seq_file *m, struct file *file) ...@@ -478,7 +476,8 @@ static void tty_show_fdinfo(struct seq_file *m, struct file *file)
static const struct file_operations tty_fops = { static const struct file_operations tty_fops = {
.llseek = no_llseek, .llseek = no_llseek,
.read = tty_read, .read = tty_read,
.write = tty_write, .write_iter = tty_write,
.splice_write = iter_file_splice_write,
.poll = tty_poll, .poll = tty_poll,
.unlocked_ioctl = tty_ioctl, .unlocked_ioctl = tty_ioctl,
.compat_ioctl = tty_compat_ioctl, .compat_ioctl = tty_compat_ioctl,
...@@ -491,7 +490,8 @@ static const struct file_operations tty_fops = { ...@@ -491,7 +490,8 @@ static const struct file_operations tty_fops = {
static const struct file_operations console_fops = { static const struct file_operations console_fops = {
.llseek = no_llseek, .llseek = no_llseek,
.read = tty_read, .read = tty_read,
.write = redirected_tty_write, .write_iter = redirected_tty_write,
.splice_write = iter_file_splice_write,
.poll = tty_poll, .poll = tty_poll,
.unlocked_ioctl = tty_ioctl, .unlocked_ioctl = tty_ioctl,
.compat_ioctl = tty_compat_ioctl, .compat_ioctl = tty_compat_ioctl,
...@@ -503,7 +503,7 @@ static const struct file_operations console_fops = { ...@@ -503,7 +503,7 @@ static const struct file_operations console_fops = {
static const struct file_operations hung_up_tty_fops = { static const struct file_operations hung_up_tty_fops = {
.llseek = no_llseek, .llseek = no_llseek,
.read = hung_up_tty_read, .read = hung_up_tty_read,
.write = hung_up_tty_write, .write_iter = hung_up_tty_write,
.poll = hung_up_tty_poll, .poll = hung_up_tty_poll,
.unlocked_ioctl = hung_up_tty_ioctl, .unlocked_ioctl = hung_up_tty_ioctl,
.compat_ioctl = hung_up_tty_compat_ioctl, .compat_ioctl = hung_up_tty_compat_ioctl,
...@@ -606,9 +606,9 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) ...@@ -606,9 +606,9 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session)
/* This breaks for file handles being sent over AF_UNIX sockets ? */ /* This breaks for file handles being sent over AF_UNIX sockets ? */
list_for_each_entry(priv, &tty->tty_files, list) { list_for_each_entry(priv, &tty->tty_files, list) {
filp = priv->file; filp = priv->file;
if (filp->f_op->write == redirected_tty_write) if (filp->f_op->write_iter == redirected_tty_write)
cons_filp = filp; cons_filp = filp;
if (filp->f_op->write != tty_write) if (filp->f_op->write_iter != tty_write)
continue; continue;
closecount++; closecount++;
__tty_fasync(-1, filp, 0); /* can't block */ __tty_fasync(-1, filp, 0); /* can't block */
...@@ -901,9 +901,9 @@ static inline ssize_t do_tty_write( ...@@ -901,9 +901,9 @@ static inline ssize_t do_tty_write(
ssize_t (*write)(struct tty_struct *, struct file *, const unsigned char *, size_t), ssize_t (*write)(struct tty_struct *, struct file *, const unsigned char *, size_t),
struct tty_struct *tty, struct tty_struct *tty,
struct file *file, struct file *file,
const char __user *buf, struct iov_iter *from)
size_t count)
{ {
size_t count = iov_iter_count(from);
ssize_t ret, written = 0; ssize_t ret, written = 0;
unsigned int chunk; unsigned int chunk;
...@@ -955,14 +955,20 @@ static inline ssize_t do_tty_write( ...@@ -955,14 +955,20 @@ static inline ssize_t do_tty_write(
size_t size = count; size_t size = count;
if (size > chunk) if (size > chunk)
size = chunk; size = chunk;
ret = -EFAULT; ret = -EFAULT;
if (copy_from_user(tty->write_buf, buf, size)) if (copy_from_iter(tty->write_buf, size, from) != size)
break; break;
ret = write(tty, file, tty->write_buf, size); ret = write(tty, file, tty->write_buf, size);
if (ret <= 0) if (ret <= 0)
break; break;
/* FIXME! Have Al check this! */
if (ret != size)
iov_iter_revert(from, size-ret);
written += ret; written += ret;
buf += ret;
count -= ret; count -= ret;
if (!count) if (!count)
break; break;
...@@ -1022,9 +1028,9 @@ void tty_write_message(struct tty_struct *tty, char *msg) ...@@ -1022,9 +1028,9 @@ void tty_write_message(struct tty_struct *tty, char *msg)
* write method will not be invoked in parallel for each device. * write method will not be invoked in parallel for each device.
*/ */
static ssize_t tty_write(struct file *file, const char __user *buf, static ssize_t tty_write(struct kiocb *iocb, struct iov_iter *from)
size_t count, loff_t *ppos)
{ {
struct file *file = iocb->ki_filp;
struct tty_struct *tty = file_tty(file); struct tty_struct *tty = file_tty(file);
struct tty_ldisc *ld; struct tty_ldisc *ld;
ssize_t ret; ssize_t ret;
...@@ -1038,17 +1044,16 @@ static ssize_t tty_write(struct file *file, const char __user *buf, ...@@ -1038,17 +1044,16 @@ static ssize_t tty_write(struct file *file, const char __user *buf,
tty_err(tty, "missing write_room method\n"); tty_err(tty, "missing write_room method\n");
ld = tty_ldisc_ref_wait(tty); ld = tty_ldisc_ref_wait(tty);
if (!ld) if (!ld)
return hung_up_tty_write(file, buf, count, ppos); return hung_up_tty_write(iocb, from);
if (!ld->ops->write) if (!ld->ops->write)
ret = -EIO; ret = -EIO;
else else
ret = do_tty_write(ld->ops->write, tty, file, buf, count); ret = do_tty_write(ld->ops->write, tty, file, from);
tty_ldisc_deref(ld); tty_ldisc_deref(ld);
return ret; return ret;
} }
ssize_t redirected_tty_write(struct file *file, const char __user *buf, ssize_t redirected_tty_write(struct kiocb *iocb, struct iov_iter *iter)
size_t count, loff_t *ppos)
{ {
struct file *p = NULL; struct file *p = NULL;
...@@ -1059,11 +1064,11 @@ ssize_t redirected_tty_write(struct file *file, const char __user *buf, ...@@ -1059,11 +1064,11 @@ ssize_t redirected_tty_write(struct file *file, const char __user *buf,
if (p) { if (p) {
ssize_t res; ssize_t res;
res = vfs_write(p, buf, count, &p->f_pos); res = vfs_iocb_iter_write(p, iocb, iter);
fput(p); fput(p);
return res; return res;
} }
return tty_write(file, buf, count, ppos); return tty_write(iocb, iter);
} }
/* /*
...@@ -2295,7 +2300,7 @@ static int tioccons(struct file *file) ...@@ -2295,7 +2300,7 @@ static int tioccons(struct file *file)
{ {
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
if (file->f_op->write == redirected_tty_write) { if (file->f_op->write_iter == redirected_tty_write) {
struct file *f; struct file *f;
spin_lock(&redirect_lock); spin_lock(&redirect_lock);
f = redirect; f = redirect;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment