X-Git-Url: http://ftp.safe.ca/?p=safe%2Fjmp%2Flinux-2.6;a=blobdiff_plain;f=arch%2Fum%2Fdrivers%2Fport_kern.c;h=4ebc8a34738f7d43a6020c8a05e604d8cad7d8e5;hp=c41efd207fcc23b33cf35b09edd94d1c841893c8;hb=d43c36dc6b357fa1806800f18aa30123c747a6d1;hpb=dbce706e2550253c5ab6043f4f5dfde0cd02470f diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index c41efd2..4ebc8a3 100644 --- a/arch/um/drivers/port_kern.c +++ b/arch/um/drivers/port_kern.c @@ -1,25 +1,18 @@ -/* - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) +/* + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) * Licensed under the GPL */ -#include "linux/list.h" -#include "linux/sched.h" -#include "linux/slab.h" +#include "linux/completion.h" #include "linux/interrupt.h" -#include "linux/irq.h" -#include "linux/spinlock.h" -#include "linux/errno.h" +#include "linux/list.h" +#include "linux/mutex.h" +#include "linux/workqueue.h" #include "asm/atomic.h" -#include "asm/semaphore.h" -#include "asm/errno.h" -#include "kern_util.h" -#include "kern.h" -#include "irq_user.h" -#include "irq_kern.h" -#include "port.h" #include "init.h" +#include "irq_kern.h" #include "os.h" +#include "port.h" struct port_list { struct list_head list; @@ -48,17 +41,17 @@ 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; fd = os_rcv_fd(conn->socket[0], &conn->helper_pid); - if(fd < 0){ - if(fd == -EAGAIN) - return(IRQ_NONE); + if (fd < 0) { + if (fd == -EAGAIN) + return IRQ_NONE; - printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", + printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", -fd); os_close_file(conn->fd); } @@ -69,7 +62,7 @@ static irqreturn_t pipe_interrupt(int irq, void *data, struct pt_regs *regs) list_add(&conn->list, &conn->port->connections); complete(&conn->port->done); - return(IRQ_HANDLED); + return IRQ_HANDLED; } #define NO_WAITER_MSG \ @@ -82,85 +75,86 @@ static irqreturn_t pipe_interrupt(int irq, void *data, struct pt_regs *regs) static int port_accept(struct port_list *port) { struct connection *conn; - int fd, socket[2], pid, ret = 0; + int fd, socket[2], pid; fd = port_connection(port->fd, socket, &pid); - if(fd < 0){ - if(fd != -EAGAIN) + if (fd < 0) { + if (fd != -EAGAIN) printk(KERN_ERR "port_accept : port_connection " "returned %d\n", -fd); goto out; } conn = kmalloc(sizeof(*conn), GFP_ATOMIC); - if(conn == NULL){ + if (conn == NULL) { printk(KERN_ERR "port_accept : failed to allocate " "connection\n"); goto out_close; } - *conn = ((struct connection) + *conn = ((struct connection) { .list = LIST_HEAD_INIT(conn->list), .fd = fd, .socket = { socket[0], socket[1] }, .telnetd_pid = pid, .port = port }); - if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, - SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, - "telnetd", conn)){ + if (um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, + 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){ + 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"); + printk(KERN_ERR "No one waiting for port\n"); } list_add(&conn->list, &port->pending); - return(1); + return 1; out_free: kfree(conn); out_close: os_close_file(fd); - if(pid != -1) - os_kill_process(pid, 1); + os_kill_process(pid, 1); out: - return(ret); -} + return 0; +} -DECLARE_MUTEX(ports_sem); -struct list_head ports = LIST_HEAD_INIT(ports); +static DEFINE_MUTEX(ports_mutex); +static LIST_HEAD(ports); -void port_work_proc(void *unused) +static void port_work_proc(struct work_struct *unused) { struct port_list *port; struct list_head *ele; unsigned long flags; local_irq_save(flags); - list_for_each(ele, &ports){ + list_for_each(ele, &ports) { port = list_entry(ele, struct port_list, list); - if(!port->has_connection) + if (!port->has_connection) continue; + reactivate_fd(port->fd, ACCEPT_IRQ); - while(port_accept(port)) ; + while (port_accept(port)) + ; port->has_connection = 0; } 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; port->has_connection = 1; schedule_work(&port_work); - return(IRQ_HANDLED); -} + return IRQ_HANDLED; +} void *port_data(int port_num) { @@ -169,31 +163,33 @@ void *port_data(int port_num) struct port_dev *dev = NULL; int fd; - down(&ports_sem); - list_for_each(ele, &ports){ + mutex_lock(&ports_mutex); + list_for_each(ele, &ports) { port = list_entry(ele, struct port_list, list); - if(port->port == port_num) goto found; + if (port->port == port_num) + goto found; } port = kmalloc(sizeof(struct port_list), GFP_KERNEL); - if(port == NULL){ + if (port == NULL) { printk(KERN_ERR "Allocation of port list failed\n"); goto out; } fd = port_listen_fd(port_num); - if(fd < 0){ + if (fd < 0) { printk(KERN_ERR "binding to port %d failed, errno = %d\n", port_num, -fd); goto out_free; } - if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, - SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, "port", - port)){ + + if (um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, + 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; } - *port = ((struct port_list) + *port = ((struct port_list) { .list = LIST_HEAD_INIT(port->list), .wait_count = ATOMIC_INIT(0), .has_connection = 0, @@ -207,7 +203,7 @@ void *port_data(int port_num) found: dev = kmalloc(sizeof(struct port_dev), GFP_KERNEL); - if(dev == NULL){ + if (dev == NULL) { printk(KERN_ERR "Allocation of port device entry failed\n"); goto out; } @@ -217,13 +213,13 @@ void *port_data(int port_num) .telnetd_pid = -1 }); goto out; - out_free: - kfree(port); out_close: os_close_file(fd); + out_free: + kfree(port); out: - up(&ports_sem); - return(dev); + mutex_unlock(&ports_mutex); + return dev; } int port_wait(void *data) @@ -233,15 +229,15 @@ int port_wait(void *data) struct port_list *port = dev->port; int fd; - atomic_inc(&port->wait_count); - while(1){ + atomic_inc(&port->wait_count); + while (1) { fd = -ERESTARTSYS; - if(wait_for_completion_interruptible(&port->done)) - goto out; + if (wait_for_completion_interruptible(&port->done)) + goto out; spin_lock(&port->lock); - conn = list_entry(port->connections.next, struct connection, + conn = list_entry(port->connections.next, struct connection, list); list_del(&conn->list); spin_unlock(&port->lock); @@ -249,17 +245,18 @@ int port_wait(void *data) os_shutdown_socket(conn->socket[0], 1, 1); os_close_file(conn->socket[0]); os_shutdown_socket(conn->socket[1], 1, 1); - os_close_file(conn->socket[1]); + os_close_file(conn->socket[1]); /* This is done here because freeing an IRQ can't be done * within the IRQ handler. So, pipe_interrupt always ups * the semaphore regardless of whether it got a successful - * connection. Then we loop here throwing out failed + * connection. Then we loop here throwing out failed * connections until a good one is found. */ free_irq(TELNETD_IRQ, conn); - if(conn->fd >= 0) break; + if (conn->fd >= 0) + break; os_close_file(conn->fd); kfree(conn); } @@ -277,9 +274,9 @@ void port_remove_dev(void *d) { struct port_dev *dev = d; - if(dev->helper_pid != -1) + if (dev->helper_pid != -1) os_kill_process(dev->helper_pid, 0); - if(dev->telnetd_pid != -1) + if (dev->telnetd_pid != -1) os_kill_process(dev->telnetd_pid, 1); dev->helper_pid = -1; dev->telnetd_pid = -1; @@ -298,7 +295,7 @@ static void free_port(void) struct list_head *ele; struct port_list *port; - list_for_each(ele, &ports){ + list_for_each(ele, &ports) { port = list_entry(ele, struct port_list, list); free_irq_by_fd(port->fd); os_close_file(port->fd);