#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"
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;
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;
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;
.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);
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;
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;
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;
*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:
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);
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)
}
__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:
- */