diff options
author | Al Viro <viro@ftp.linux.org.uk> | 2006-10-24 14:15:29 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-25 09:01:10 +0400 |
commit | 3a51237dc11efe283b40ea0248f4e26ab935dbd1 (patch) | |
tree | d27f5f2cbaea27119914186650739f281f796e77 /arch/um/drivers/mconsole_kern.c | |
parent | 6c50444723f2e6487b3377450f90d813a88e6c31 (diff) | |
download | linux-3a51237dc11efe283b40ea0248f4e26ab935dbd1.tar.xz |
[PATCH] uml: mconsole fixes
* when we have stop/sysrq/go, we get pt_regs of whatever executes
mc_work_proc(). Would be better to see what we had at the time of
interrupt that got us stop.
* stop/stop/stop..... will give stack overflow. Shouldn't allow stop
from mconsole_stop().
* stop/stop/go leaves us inside mconsole_stop() with
os_set_fd_block(req->originating_fd, 0);
reactivate_fd(req->originating_fd, MCONSOLE_IRQ);
just done by nested mconsole_stop(). Ditto.
* once we'd seen stop, there's a period when INTR commands are executed
out of order (as they should; we might have the things stuck badly
enough to never reach mconsole_stop(), but still not badly enough to
block mconsole_interrupt(); in that situation we _want_ things like
"cad" to be executed immediately). Once we enter monsole_stop(), all
INTR commands will be executed in order, mixed with PROC ones. We'd
better let user see that such change of behaviour has happened.
(Suggested by lennert).
* stack footprint of monsole_interrupt() is an atrocity; AFAICS we can
safely make struct mc_request req; static in function there.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/um/drivers/mconsole_kern.c')
-rw-r--r-- | arch/um/drivers/mconsole_kern.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index d08bd036ccb8..7b172160fe04 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -79,7 +79,7 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id) /* long to avoid size mismatch warnings from gcc */ long fd; struct mconsole_entry *new; - struct mc_request req; + static struct mc_request req; /* that's OK */ fd = (long) dev_id; while (mconsole_get_request(fd, &req)){ @@ -91,6 +91,7 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id) mconsole_reply(&req, "Out of memory", 1, 0); else { new->request = req; + new->request.regs = get_irq_regs()->regs; list_add(&new->list, &mc_requests); } } @@ -314,9 +315,21 @@ void mconsole_stop(struct mc_request *req) { deactivate_fd(req->originating_fd, MCONSOLE_IRQ); os_set_fd_block(req->originating_fd, 1); - mconsole_reply(req, "", 0, 0); - while(mconsole_get_request(req->originating_fd, req)){ - if(req->cmd->handler == mconsole_go) break; + mconsole_reply(req, "stopped", 0, 0); + while (mconsole_get_request(req->originating_fd, req)) { + if (req->cmd->handler == mconsole_go) + break; + if (req->cmd->handler == mconsole_stop) { + mconsole_reply(req, "Already stopped", 1, 0); + continue; + } + if (req->cmd->handler == mconsole_sysrq) { + struct pt_regs *old_regs; + old_regs = set_irq_regs((struct pt_regs *)&req->regs); + mconsole_sysrq(req); + set_irq_regs(old_regs); + continue; + } (*req->cmd->handler)(req); } os_set_fd_block(req->originating_fd, 0); @@ -673,9 +686,7 @@ static void with_console(struct mc_request *req, void (*proc)(void *), static void sysrq_proc(void *arg) { char *op = arg; - struct pt_regs *old_regs = set_irq_regs(¤t->thread.regs); handle_sysrq(*op, NULL); - set_irq_regs(old_regs); } void mconsole_sysrq(struct mc_request *req) |