X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fum%2Fdrivers%2Fport_kern.c;h=73755f37a8a8409df2c43f0825ababd61a15c08d;hb=16c70f8c1b54b61c3b951b6fb220df250fe09b32;hp=4044053cd9e369d86ebc16e1905145de5e146d4f;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index 4044053cd..73755f37a 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; @@ -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); @@ -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); @@ -253,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) @@ -290,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: - */