Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fa453a62 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus-3.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml

Pull UML changes from Richard Weinberger:
 "Mostly bug fixes and cleanups"

* 'for-linus-3.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml: (35 commits)
  um: Update defconfig
  um: Switch to large mcmodel on x86_64
  MTD: Relax dependencies
  um: Wire CONFIG_GENERIC_IO up
  um: Serve io_remap_pfn_range()
  Introduce CONFIG_GENERIC_IO
  um: allow SUBARCH=x86
  um: most of the SUBARCH uses can be killed
  um: deadlock in line_write_interrupt()
  um: don't bother trying to rebuild CHECKFLAGS for USER_OBJS
  um: use the right ifdef around exports in user_syms.c
  um: a bunch of headers can be killed by using generic-y
  um: ptrace-generic.h doesn't need user.h
  um: kill HOST_TASK_PID
  um: remove pointless include of asm/fixmap.h from asm/pgtable.h
  um: asm-offsets.h might as well come from underlying arch...
  um: merge processor_{32,64}.h a bit...
  um: switch close_chan() to struct line
  um: race fix: initialize delayed_work *before* registering IRQ
  um: line->have_irq is never checked...
  ...
parents 30eebb54 3463ff44
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ config UML
	select HAVE_GENERIC_HARDIRQS
	select GENERIC_IRQ_SHOW
	select GENERIC_CPU_DEVICES
	select GENERIC_IO

config MMU
	bool
+3 −2
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ ifeq ($(SUBARCH),i386)
endif
ifeq ($(SUBARCH),x86_64)
        HEADER_ARCH := x86
	KBUILD_CFLAGS += -mcmodel=large
endif

HOST_DIR := arch/$(HEADER_ARCH)
@@ -50,7 +51,7 @@ KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/um
#
# These apply to USER_CFLAGS to.

KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ \
	$(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap	\
	-Din6addr_loopback=kernel_in6addr_loopback \
	-Din6addr_any=kernel_in6addr_any -Dstrrchr=kernel_strrchr
@@ -99,7 +100,7 @@ KBUILD_KCONFIG := $(HOST_DIR)/um/Kconfig

archheaders:
	$(Q)$(MAKE) -C '$(srctree)' KBUILD_SRC= \
		ARCH=$(SUBARCH) O='$(objtree)' archheaders
		ARCH=$(HEADER_ARCH) O='$(objtree)' archheaders

archprepare: include/generated/user_constants.h

+471 −184

File changed.

Preview size limit exceeded, changes collapsed.

+9 −9
Original line number Diff line number Diff line
@@ -27,24 +27,24 @@ struct chan {
	void *data;
};

extern void chan_interrupt(struct list_head *chans, struct delayed_work *task,
extern void chan_interrupt(struct line *line,
			   struct tty_struct *tty, int irq);
extern int parse_chan_pair(char *str, struct line *line, int device,
			   const struct chan_opts *opts, char **error_out);
extern int write_chan(struct list_head *chans, const char *buf, int len,
extern int write_chan(struct chan *chan, const char *buf, int len,
			     int write_irq);
extern int console_write_chan(struct list_head *chans, const char *buf, 
extern int console_write_chan(struct chan *chan, const char *buf, 
			      int len);
extern int console_open_chan(struct line *line, struct console *co);
extern void deactivate_chan(struct list_head *chans, int irq);
extern void reactivate_chan(struct list_head *chans, int irq);
extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
extern void deactivate_chan(struct chan *chan, int irq);
extern void reactivate_chan(struct chan *chan, int irq);
extern void chan_enable_winch(struct chan *chan, struct tty_struct *tty);
extern int enable_chan(struct line *line);
extern void close_chan(struct list_head *chans, int delay_free_irq);
extern int chan_window_size(struct list_head *chans, 
extern void close_chan(struct line *line);
extern int chan_window_size(struct line *line, 
			     unsigned short *rows_out, 
			     unsigned short *cols_out);
extern int chan_config_string(struct list_head *chans, char *str, int size,
extern int chan_config_string(struct line *line, char *str, int size,
			      char **error_out);

#endif
+88 −110
Original line number Diff line number Diff line
@@ -140,18 +140,18 @@ static int open_chan(struct list_head *chans)
	return err;
}

void chan_enable_winch(struct list_head *chans, struct tty_struct *tty)
void chan_enable_winch(struct chan *chan, struct tty_struct *tty)
{
	struct list_head *ele;
	struct chan *chan;

	list_for_each(ele, chans) {
		chan = list_entry(ele, struct chan, list);
		if (chan->primary && chan->output && chan->ops->winch) {
	if (chan && chan->primary && chan->ops->winch)
		register_winch(chan->fd, tty);
			return;
		}
}

static void line_timer_cb(struct work_struct *work)
{
	struct line *line = container_of(work, struct line, task.work);

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

int enable_chan(struct line *line)
@@ -160,6 +160,8 @@ int enable_chan(struct line *line)
	struct chan *chan;
	int err;

	INIT_DELAYED_WORK(&line->task, line_timer_cb);

	list_for_each(ele, &line->chan_list) {
		chan = list_entry(ele, struct chan, list);
		err = open_one_chan(chan);
@@ -183,7 +185,7 @@ int enable_chan(struct line *line)
	return 0;

 out_close:
	close_chan(&line->chan_list, 0);
	close_chan(line);
	return err;
}

@@ -244,7 +246,7 @@ static void close_one_chan(struct chan *chan, int delay_free_irq)
	chan->fd = -1;
}

void close_chan(struct list_head *chans, int delay_free_irq)
void close_chan(struct line *line)
{
	struct chan *chan;

@@ -253,77 +255,50 @@ void close_chan(struct list_head *chans, int delay_free_irq)
	 * state.  Then, the first one opened will have the original state,
	 * so it must be the last closed.
	 */
	list_for_each_entry_reverse(chan, chans, list) {
		close_one_chan(chan, delay_free_irq);
	list_for_each_entry_reverse(chan, &line->chan_list, list) {
		close_one_chan(chan, 0);
	}
}

void deactivate_chan(struct list_head *chans, int irq)
void deactivate_chan(struct chan *chan, int irq)
{
	struct list_head *ele;

	struct chan *chan;
	list_for_each(ele, chans) {
		chan = list_entry(ele, struct chan, list);

		if (chan->enabled && chan->input)
	if (chan && chan->enabled)
		deactivate_fd(chan->fd, irq);
}
}

void reactivate_chan(struct list_head *chans, int irq)
void reactivate_chan(struct chan *chan, int irq)
{
	struct list_head *ele;
	struct chan *chan;

	list_for_each(ele, chans) {
		chan = list_entry(ele, struct chan, list);

		if (chan->enabled && chan->input)
	if (chan && chan->enabled)
		reactivate_fd(chan->fd, irq);
}
}

int write_chan(struct list_head *chans, const char *buf, int len,
int write_chan(struct chan *chan, const char *buf, int len,
	       int write_irq)
{
	struct list_head *ele;
	struct chan *chan = NULL;
	int n, ret = 0;

	if (len == 0)
	if (len == 0 || !chan || !chan->ops->write)
		return 0;

	list_for_each(ele, chans) {
		chan = list_entry(ele, struct chan, list);
		if (!chan->output || (chan->ops->write == NULL))
			continue;

	n = chan->ops->write(chan->fd, buf, len, chan->data);
	if (chan->primary) {
		ret = n;
		if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len)))
			reactivate_fd(chan->fd, write_irq);
	}
	}
	return ret;
}

int console_write_chan(struct list_head *chans, const char *buf, int len)
int console_write_chan(struct chan *chan, const char *buf, int len)
{
	struct list_head *ele;
	struct chan *chan;
	int n, ret = 0;

	list_for_each(ele, chans) {
		chan = list_entry(ele, struct chan, list);
		if (!chan->output || (chan->ops->console_write == NULL))
			continue;
	if (!chan || !chan->ops->console_write)
		return 0;

	n = chan->ops->console_write(chan->fd, buf, len);
	if (chan->primary)
		ret = n;
	}
	return ret;
}

@@ -340,20 +315,24 @@ int console_open_chan(struct line *line, struct console *co)
	return 0;
}

int chan_window_size(struct list_head *chans, unsigned short *rows_out,
int chan_window_size(struct line *line, unsigned short *rows_out,
		      unsigned short *cols_out)
{
	struct list_head *ele;
	struct chan *chan;

	list_for_each(ele, chans) {
		chan = list_entry(ele, struct chan, list);
		if (chan->primary) {
	chan = line->chan_in;
	if (chan && chan->primary) {
		if (chan->ops->window_size == NULL)
			return 0;
		return chan->ops->window_size(chan->fd, chan->data,
					      rows_out, cols_out);
	}
	chan = line->chan_out;
	if (chan && chan->primary) {
		if (chan->ops->window_size == NULL)
			return 0;
		return chan->ops->window_size(chan->fd, chan->data,
					      rows_out, cols_out);
	}
	return 0;
}
@@ -429,21 +408,15 @@ static int chan_pair_config_string(struct chan *in, struct chan *out,
	return n;
}

int chan_config_string(struct list_head *chans, char *str, int size,
int chan_config_string(struct line *line, char *str, int size,
		       char **error_out)
{
	struct list_head *ele;
	struct chan *chan, *in = NULL, *out = NULL;
	struct chan *in = line->chan_in, *out = line->chan_out;

	list_for_each(ele, chans) {
		chan = list_entry(ele, struct chan, list);
		if (!chan->primary)
			continue;
		if (chan->input)
			in = chan;
		if (chan->output)
			out = chan;
	}
	if (in && !in->primary)
		in = NULL;
	if (out && !out->primary)
		out = NULL;

	return chan_pair_config_string(in, out, str, size, error_out);
}
@@ -547,10 +520,14 @@ int parse_chan_pair(char *str, struct line *line, int device,
	char *in, *out;

	if (!list_empty(chans)) {
		line->chan_in = line->chan_out = NULL;
		free_chan(chans);
		INIT_LIST_HEAD(chans);
	}

	if (!str)
		return 0;

	out = strchr(str, ',');
	if (out != NULL) {
		in = str;
@@ -562,6 +539,7 @@ int parse_chan_pair(char *str, struct line *line, int device,

		new->input = 1;
		list_add(&new->list, chans);
		line->chan_in = new;

		new = parse_chan(line, out, device, opts, error_out);
		if (new == NULL)
@@ -569,6 +547,7 @@ int parse_chan_pair(char *str, struct line *line, int device,

		list_add(&new->list, chans);
		new->output = 1;
		line->chan_out = new;
	}
	else {
		new = parse_chan(line, str, device, opts, error_out);
@@ -578,25 +557,23 @@ int parse_chan_pair(char *str, struct line *line, int device,
		list_add(&new->list, chans);
		new->input = 1;
		new->output = 1;
		line->chan_in = line->chan_out = new;
	}
	return 0;
}

void chan_interrupt(struct list_head *chans, struct delayed_work *task,
		    struct tty_struct *tty, int irq)
void chan_interrupt(struct line *line, struct tty_struct *tty, int irq)
{
	struct list_head *ele, *next;
	struct chan *chan;
	struct chan *chan = line->chan_in;
	int err;
	char c;

	list_for_each_safe(ele, next, chans) {
		chan = list_entry(ele, struct chan, list);
		if (!chan->input || (chan->ops->read == NULL))
			continue;
	if (!chan || !chan->ops->read)
		goto out;

	do {
		if (tty && !tty_buffer_request_room(tty, 1)) {
				schedule_delayed_work(task, 1);
			schedule_delayed_work(&line->task, 1);
			goto out;
		}
		err = chan->ops->read(chan->fd, &c, chan->data);
@@ -610,11 +587,12 @@ void chan_interrupt(struct list_head *chans, struct delayed_work *task,
		if (chan->primary) {
			if (tty != NULL)
				tty_hangup(tty);
				close_chan(chans, 1);
				return;
			}
			else close_one_chan(chan, 1);
			if (line->chan_out != chan)
				close_one_chan(line->chan_out, 1);
		}
		close_one_chan(chan, 1);
		if (chan->primary)
			return;
	}
 out:
	if (tty)
Loading