X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fum%2Fdrivers%2Fport_kern.c;h=6dfe632f1c14d9a64ebc9a279a65025eefba2ac7;hb=refs%2Fheads%2Fvserver;hp=14f66da4dc902b8d504e014f4d57b00b6c1181ad;hpb=6a77f38946aaee1cd85eeec6cf4229b204c15071;p=linux-2.6.git diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index 14f66da4d..6dfe632f1 100644 --- a/arch/um/drivers/port_kern.c +++ b/arch/um/drivers/port_kern.c @@ -7,9 +7,9 @@ #include "linux/sched.h" #include "linux/slab.h" #include "linux/interrupt.h" -#include "linux/irq.h" #include "linux/spinlock.h" #include "linux/errno.h" +#include "asm/atomic.h" #include "asm/semaphore.h" #include "asm/errno.h" #include "kern_util.h" @@ -22,8 +22,9 @@ struct port_list { struct list_head list; + atomic_t wait_count; int has_connection; - struct semaphore sem; + struct completion done; int port; int fd; spinlock_t lock; @@ -46,7 +47,7 @@ struct connection { struct port_list *port; }; -static irqreturn_t pipe_interrupt(int irq, void *data, struct pt_regs *regs) +static irqreturn_t pipe_interrupt(int irq, void *data) { struct connection *conn = data; int fd; @@ -66,10 +67,17 @@ static irqreturn_t pipe_interrupt(int irq, void *data, struct pt_regs *regs) conn->fd = fd; list_add(&conn->list, &conn->port->connections); - up(&conn->port->sem); + complete(&conn->port->done); return(IRQ_HANDLED); } +#define NO_WAITER_MSG \ + "****\n" \ + "There are currently no UML consoles waiting for port connections.\n" \ + "Either disconnect from one to make it available or activate some more\n" \ + "by enabling more consoles in the UML /etc/inittab.\n" \ + "****\n" + static int port_accept(struct port_list *port) { struct connection *conn; @@ -97,13 +105,17 @@ static int port_accept(struct port_list *port) .port = port }); if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, - SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, + IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, "telnetd", conn)){ printk(KERN_ERR "port_accept : failed to get IRQ for " "telnetd\n"); goto out_free; } + if(atomic_read(&port->wait_count) == 0){ + os_write_file(fd, NO_WAITER_MSG, sizeof(NO_WAITER_MSG)); + printk("No one waiting for port\n"); + } list_add(&conn->list, &port->pending); return(1); @@ -120,7 +132,7 @@ static int port_accept(struct port_list *port) DECLARE_MUTEX(ports_sem); struct list_head ports = LIST_HEAD_INIT(ports); -void port_work_proc(void *unused) +void port_work_proc(struct work_struct *unused) { struct port_list *port; struct list_head *ele; @@ -138,9 +150,9 @@ void port_work_proc(void *unused) local_irq_restore(flags); } -DECLARE_WORK(port_work, port_work_proc, NULL); +DECLARE_WORK(port_work, port_work_proc); -static irqreturn_t port_interrupt(int irq, void *data, struct pt_regs *regs) +static irqreturn_t port_interrupt(int irq, void *data) { struct port_list *port = data; @@ -174,7 +186,7 @@ void *port_data(int port_num) goto out_free; } if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, - SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, "port", + IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, "port", port)){ printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); goto out_close; @@ -182,14 +194,14 @@ void *port_data(int port_num) *port = ((struct port_list) { .list = LIST_HEAD_INIT(port->list), + .wait_count = ATOMIC_INIT(0), .has_connection = 0, - .sem = __SEMAPHORE_INITIALIZER(port->sem, - 0), - .lock = SPIN_LOCK_UNLOCKED, .port = port_num, .fd = fd, .pending = LIST_HEAD_INIT(port->pending), .connections = LIST_HEAD_INIT(port->connections) }); + spin_lock_init(&port->lock); + init_completion(&port->done); list_add(&port->list, &ports); found: @@ -220,9 +232,11 @@ int port_wait(void *data) struct port_list *port = dev->port; int fd; + atomic_inc(&port->wait_count); while(1){ - if(down_interruptible(&port->sem)) - return(-ERESTARTSYS); + fd = -ERESTARTSYS; + if(wait_for_completion_interruptible(&port->done)) + goto out; spin_lock(&port->lock); @@ -242,7 +256,6 @@ int port_wait(void *data) * connection. Then we loop here throwing out failed * connections until a good one is found. */ - free_irq_by_irq_and_dev(TELNETD_IRQ, conn); free_irq(TELNETD_IRQ, conn); if(conn->fd >= 0) break; @@ -254,8 +267,9 @@ int port_wait(void *data) dev->helper_pid = conn->helper_pid; dev->telnetd_pid = conn->telnetd_pid; kfree(conn); - - return(fd); + out: + atomic_dec(&port->wait_count); + return fd; } void port_remove_dev(void *d) @@ -291,14 +305,3 @@ static void free_port(void) } __uml_exitcall(free_port); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */