Skip to content

Commit

Permalink
Merge branch 'for-linus-3.6-rc1' of git://git.kernel.org/pub/scm/linu…
Browse files Browse the repository at this point in the history
…x/kernel/git/rw/uml

Pull UML fixes from Richard Weinberger:
 "This patch set contains mostly fixes and cleanups.  The UML tty driver
  uses now tty_port and is no longer broken like hell  :-)"

* 'for-linus-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml:
  um: Add arch/x86/um to MAINTAINERS
  um: pass siginfo to guest process
  um: fix ubd_file_size for read-only files
  um: pull interrupt_end() into userspace()
  um: split syscall_trace(), pass pt_regs to it
  um: switch UPT_SET_RETURN_VALUE and regs_return_value to pt_regs
  um: set BLK_CGROUP=y in defconfig
  um: remove count_lock
  um: fully use tty_port
  um: Remove dead code
  um: remove line_ioctl()
  TTY: um/line, use tty from tty_port
  TTY: um/line, add tty_port
  • Loading branch information
torvalds committed Aug 1, 2012
2 parents a6dc772 + b070989 commit 1871e84
Show file tree
Hide file tree
Showing 23 changed files with 206 additions and 302 deletions.
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -7382,6 +7382,7 @@ W: http://user-mode-linux.sourceforge.net
S: Maintained
F: Documentation/virtual/uml/
F: arch/um/
F: arch/x86/um/
F: fs/hostfs/
F: fs/hppfs/

Expand Down
2 changes: 1 addition & 1 deletion arch/um/defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ CONFIG_CGROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_CFS_BANDWIDTH is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_BLK_CGROUP=m
CONFIG_BLK_CGROUP=y
# CONFIG_DEBUG_BLK_CGROUP is not set
# CONFIG_CHECKPOINT_RESTORE is not set
CONFIG_NAMESPACES=y
Expand Down
4 changes: 3 additions & 1 deletion arch/um/drivers/chan_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,11 @@ void chan_enable_winch(struct chan *chan, struct tty_struct *tty)
static void line_timer_cb(struct work_struct *work)
{
struct line *line = container_of(work, struct line, task.work);
struct tty_struct *tty = tty_port_tty_get(&line->port);

if (!line->throttled)
chan_interrupt(line, line->tty, line->driver->read_irq);
chan_interrupt(line, tty, line->driver->read_irq);
tty_kref_put(tty);
}

int enable_chan(struct line *line)
Expand Down
218 changes: 63 additions & 155 deletions arch/um/drivers/line.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ static irqreturn_t line_interrupt(int irq, void *data)
{
struct chan *chan = data;
struct line *line = chan->line;
struct tty_struct *tty = tty_port_tty_get(&line->port);

if (line)
chan_interrupt(line, line->tty, irq);
chan_interrupt(line, tty, irq);
tty_kref_put(tty);
return IRQ_HANDLED;
}

Expand Down Expand Up @@ -219,92 +221,6 @@ void line_set_termios(struct tty_struct *tty, struct ktermios * old)
/* nothing */
}

static const struct {
int cmd;
char *level;
char *name;
} tty_ioctls[] = {
/* don't print these, they flood the log ... */
{ TCGETS, NULL, "TCGETS" },
{ TCSETS, NULL, "TCSETS" },
{ TCSETSW, NULL, "TCSETSW" },
{ TCFLSH, NULL, "TCFLSH" },
{ TCSBRK, NULL, "TCSBRK" },

/* general tty stuff */
{ TCSETSF, KERN_DEBUG, "TCSETSF" },
{ TCGETA, KERN_DEBUG, "TCGETA" },
{ TIOCMGET, KERN_DEBUG, "TIOCMGET" },
{ TCSBRKP, KERN_DEBUG, "TCSBRKP" },
{ TIOCMSET, KERN_DEBUG, "TIOCMSET" },

/* linux-specific ones */
{ TIOCLINUX, KERN_INFO, "TIOCLINUX" },
{ KDGKBMODE, KERN_INFO, "KDGKBMODE" },
{ KDGKBTYPE, KERN_INFO, "KDGKBTYPE" },
{ KDSIGACCEPT, KERN_INFO, "KDSIGACCEPT" },
};

int line_ioctl(struct tty_struct *tty, unsigned int cmd,
unsigned long arg)
{
int ret;
int i;

ret = 0;
switch(cmd) {
#ifdef TIOCGETP
case TIOCGETP:
case TIOCSETP:
case TIOCSETN:
#endif
#ifdef TIOCGETC
case TIOCGETC:
case TIOCSETC:
#endif
#ifdef TIOCGLTC
case TIOCGLTC:
case TIOCSLTC:
#endif
/* Note: these are out of date as we now have TCGETS2 etc but this
whole lot should probably go away */
case TCGETS:
case TCSETSF:
case TCSETSW:
case TCSETS:
case TCGETA:
case TCSETAF:
case TCSETAW:
case TCSETA:
case TCXONC:
case TCFLSH:
case TIOCOUTQ:
case TIOCINQ:
case TIOCGLCKTRMIOS:
case TIOCSLCKTRMIOS:
case TIOCPKT:
case TIOCGSOFTCAR:
case TIOCSSOFTCAR:
return -ENOIOCTLCMD;
#if 0
case TCwhatever:
/* do something */
break;
#endif
default:
for (i = 0; i < ARRAY_SIZE(tty_ioctls); i++)
if (cmd == tty_ioctls[i].cmd)
break;
if (i == ARRAY_SIZE(tty_ioctls)) {
printk(KERN_ERR "%s: %s: unknown ioctl: 0x%x\n",
__func__, tty->name, cmd);
}
ret = -ENOIOCTLCMD;
break;
}
return ret;
}

void line_throttle(struct tty_struct *tty)
{
struct line *line = tty->driver_data;
Expand Down Expand Up @@ -333,7 +249,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
{
struct chan *chan = data;
struct line *line = chan->line;
struct tty_struct *tty = line->tty;
struct tty_struct *tty;
int err;

/*
Expand All @@ -352,10 +268,13 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
}
spin_unlock(&line->lock);

tty = tty_port_tty_get(&line->port);
if (tty == NULL)
return IRQ_NONE;

tty_wakeup(tty);
tty_kref_put(tty);

return IRQ_HANDLED;
}

Expand All @@ -377,88 +296,75 @@ int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
return err;
}

/*
* Normally, a driver like this can rely mostly on the tty layer
* locking, particularly when it comes to the driver structure.
* However, in this case, mconsole requests can come in "from the
* side", and race with opens and closes.
*
* mconsole config requests will want to be sure the device isn't in
* use, and get_config, open, and close will want a stable
* configuration. The checking and modification of the configuration
* is done under a spinlock. Checking whether the device is in use is
* line->tty->count > 1, also under the spinlock.
*
* line->count serves to decide whether the device should be enabled or
* disabled on the host. If it's equal to 0, then we are doing the
* first open or last close. Otherwise, open and close just return.
*/

int line_open(struct line *lines, struct tty_struct *tty)
static int line_activate(struct tty_port *port, struct tty_struct *tty)
{
struct line *line = &lines[tty->index];
int err = -ENODEV;

mutex_lock(&line->count_lock);
if (!line->valid)
goto out_unlock;

err = 0;
if (line->count++)
goto out_unlock;

BUG_ON(tty->driver_data);
tty->driver_data = line;
line->tty = tty;
int ret;
struct line *line = tty->driver_data;

err = enable_chan(line);
if (err) /* line_close() will be called by our caller */
goto out_unlock;
ret = enable_chan(line);
if (ret)
return ret;

if (!line->sigio) {
chan_enable_winch(line->chan_out, tty);
line->sigio = 1;
}

chan_window_size(line, &tty->winsize.ws_row,
&tty->winsize.ws_col);
out_unlock:
mutex_unlock(&line->count_lock);
return err;
&tty->winsize.ws_col);

return 0;
}

static void unregister_winch(struct tty_struct *tty);
static const struct tty_port_operations line_port_ops = {
.activate = line_activate,
};

void line_close(struct tty_struct *tty, struct file * filp)
int line_open(struct tty_struct *tty, struct file *filp)
{
struct line *line = tty->driver_data;

/*
* If line_open fails (and tty->driver_data is never set),
* tty_open will call line_close. So just return in this case.
*/
if (line == NULL)
return;
return tty_port_open(&line->port, tty, filp);
}

/* We ignore the error anyway! */
flush_buffer(line);
int line_install(struct tty_driver *driver, struct tty_struct *tty,
struct line *line)
{
int ret;

mutex_lock(&line->count_lock);
BUG_ON(!line->valid);
ret = tty_standard_install(driver, tty);
if (ret)
return ret;

if (--line->count)
goto out_unlock;
tty->driver_data = line;

line->tty = NULL;
tty->driver_data = NULL;
return 0;
}

static void unregister_winch(struct tty_struct *tty);

void line_cleanup(struct tty_struct *tty)
{
struct line *line = tty->driver_data;

if (line->sigio) {
unregister_winch(tty);
line->sigio = 0;
}
}

void line_close(struct tty_struct *tty, struct file * filp)
{
struct line *line = tty->driver_data;

out_unlock:
mutex_unlock(&line->count_lock);
tty_port_close(&line->port, tty, filp);
}

void line_hangup(struct tty_struct *tty)
{
struct line *line = tty->driver_data;

tty_port_hangup(&line->port);
}

void close_lines(struct line *lines, int nlines)
Expand All @@ -476,9 +382,7 @@ int setup_one_line(struct line *lines, int n, char *init,
struct tty_driver *driver = line->driver->driver;
int err = -EINVAL;

mutex_lock(&line->count_lock);

if (line->count) {
if (line->port.count) {
*error_out = "Device is already open";
goto out;
}
Expand Down Expand Up @@ -519,7 +423,6 @@ int setup_one_line(struct line *lines, int n, char *init,
}
}
out:
mutex_unlock(&line->count_lock);
return err;
}

Expand Down Expand Up @@ -607,13 +510,17 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,

line = &lines[dev];

mutex_lock(&line->count_lock);
if (!line->valid)
CONFIG_CHUNK(str, size, n, "none", 1);
else if (line->tty == NULL)
CONFIG_CHUNK(str, size, n, line->init_str, 1);
else n = chan_config_string(line, str, size, error_out);
mutex_unlock(&line->count_lock);
else {
struct tty_struct *tty = tty_port_tty_get(&line->port);
if (tty == NULL) {
CONFIG_CHUNK(str, size, n, line->init_str, 1);
} else {
n = chan_config_string(line, str, size, error_out);
tty_kref_put(tty);
}
}

return n;
}
Expand Down Expand Up @@ -663,8 +570,9 @@ int register_lines(struct line_driver *line_driver,
driver->init_termios = tty_std_termios;

for (i = 0; i < nlines; i++) {
tty_port_init(&lines[i].port);
lines[i].port.ops = &line_port_ops;
spin_lock_init(&lines[i].lock);
mutex_init(&lines[i].count_lock);
lines[i].driver = line_driver;
INIT_LIST_HEAD(&lines[i].chan_list);
}
Expand Down
12 changes: 6 additions & 6 deletions arch/um/drivers/line.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ struct line_driver {
};

struct line {
struct tty_struct *tty;
struct mutex count_lock;
unsigned long count;
struct tty_port port;
int valid;

char *init_str;
Expand All @@ -59,7 +57,11 @@ struct line {
};

extern void line_close(struct tty_struct *tty, struct file * filp);
extern int line_open(struct line *lines, struct tty_struct *tty);
extern int line_open(struct tty_struct *tty, struct file *filp);
extern int line_install(struct tty_driver *driver, struct tty_struct *tty,
struct line *line);
extern void line_cleanup(struct tty_struct *tty);
extern void line_hangup(struct tty_struct *tty);
extern int line_setup(char **conf, unsigned nlines, char **def,
char *init, char *name);
extern int line_write(struct tty_struct *tty, const unsigned char *buf,
Expand All @@ -70,8 +72,6 @@ extern int line_chars_in_buffer(struct tty_struct *tty);
extern void line_flush_buffer(struct tty_struct *tty);
extern void line_flush_chars(struct tty_struct *tty);
extern int line_write_room(struct tty_struct *tty);
extern int line_ioctl(struct tty_struct *tty, unsigned int cmd,
unsigned long arg);
extern void line_throttle(struct tty_struct *tty);
extern void line_unthrottle(struct tty_struct *tty);

Expand Down
Loading

0 comments on commit 1871e84

Please sign in to comment.