1 /* 2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) 3 * Licensed under the GPL 4 */ 5 6 #include "linux/completion.h" 7 #include "linux/interrupt.h" 8 #include "linux/list.h" 9 #include "asm/atomic.h" 10 #include "init.h" 11 #include "irq_kern.h" 12 #include "os.h" 13 #include "port.h" 14 15 struct port_list { 16 struct list_head list; 17 atomic_t wait_count; 18 int has_connection; 19 struct completion done; 20 int port; 21 int fd; 22 spinlock_t lock; 23 struct list_head pending; 24 struct list_head connections; 25 }; 26 27 struct port_dev { 28 struct port_list *port; 29 int helper_pid; 30 int telnetd_pid; 31 }; 32 33 struct connection { 34 struct list_head list; 35 int fd; 36 int helper_pid; 37 int socket[2]; 38 int telnetd_pid; 39 struct port_list *port; 40 }; 41 42 static irqreturn_t pipe_interrupt(int irq, void *data) 43 { 44 struct connection *conn = data; 45 int fd; 46 47 fd = os_rcv_fd(conn->socket[0], &conn->helper_pid); 48 if (fd < 0) { 49 if (fd == -EAGAIN) 50 return IRQ_NONE; 51 52 printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", 53 -fd); 54 os_close_file(conn->fd); 55 } 56 57 list_del(&conn->list); 58 59 conn->fd = fd; 60 list_add(&conn->list, &conn->port->connections); 61 62 complete(&conn->port->done); 63 return IRQ_HANDLED; 64 } 65 66 #define NO_WAITER_MSG \ 67 "****\n" \ 68 "There are currently no UML consoles waiting for port connections.\n" \ 69 "Either disconnect from one to make it available or activate some more\n" \ 70 "by enabling more consoles in the UML /etc/inittab.\n" \ 71 "****\n" 72 73 static int port_accept(struct port_list *port) 74 { 75 struct connection *conn; 76 int fd, socket[2], pid; 77 78 fd = port_connection(port->fd, socket, &pid); 79 if (fd < 0) { 80 if (fd != -EAGAIN) 81 printk(KERN_ERR "port_accept : port_connection " 82 "returned %d\n", -fd); 83 goto out; 84 } 85 86 conn = kmalloc(sizeof(*conn), GFP_ATOMIC); 87 if (conn == NULL) { 88 printk(KERN_ERR "port_accept : failed to allocate " 89 "connection\n"); 90 goto out_close; 91 } 92 *conn = ((struct connection) 93 { .list = LIST_HEAD_INIT(conn->list), 94 .fd = fd, 95 .socket = { socket[0], socket[1] }, 96 .telnetd_pid = pid, 97 .port = port }); 98 99 if (um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, 100 IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, 101 "telnetd", conn)) { 102 printk(KERN_ERR "port_accept : failed to get IRQ for " 103 "telnetd\n"); 104 goto out_free; 105 } 106 107 if (atomic_read(&port->wait_count) == 0) { 108 os_write_file(fd, NO_WAITER_MSG, sizeof(NO_WAITER_MSG)); 109 printk(KERN_ERR "No one waiting for port\n"); 110 } 111 list_add(&conn->list, &port->pending); 112 return 1; 113 114 out_free: 115 kfree(conn); 116 out_close: 117 os_close_file(fd); 118 os_kill_process(pid, 1); 119 out: 120 return 0; 121 } 122 123 static DECLARE_MUTEX(ports_sem); 124 static LIST_HEAD(ports); 125 126 static void port_work_proc(struct work_struct *unused) 127 { 128 struct port_list *port; 129 struct list_head *ele; 130 unsigned long flags; 131 132 local_irq_save(flags); 133 list_for_each(ele, &ports) { 134 port = list_entry(ele, struct port_list, list); 135 if (!port->has_connection) 136 continue; 137 138 reactivate_fd(port->fd, ACCEPT_IRQ); 139 while (port_accept(port)) 140 ; 141 port->has_connection = 0; 142 } 143 local_irq_restore(flags); 144 } 145 146 DECLARE_WORK(port_work, port_work_proc); 147 148 static irqreturn_t port_interrupt(int irq, void *data) 149 { 150 struct port_list *port = data; 151 152 port->has_connection = 1; 153 schedule_work(&port_work); 154 return IRQ_HANDLED; 155 } 156 157 void *port_data(int port_num) 158 { 159 struct list_head *ele; 160 struct port_list *port; 161 struct port_dev *dev = NULL; 162 int fd; 163 164 down(&ports_sem); 165 list_for_each(ele, &ports) { 166 port = list_entry(ele, struct port_list, list); 167 if (port->port == port_num) 168 goto found; 169 } 170 port = kmalloc(sizeof(struct port_list), GFP_KERNEL); 171 if (port == NULL) { 172 printk(KERN_ERR "Allocation of port list failed\n"); 173 goto out; 174 } 175 176 fd = port_listen_fd(port_num); 177 if (fd < 0) { 178 printk(KERN_ERR "binding to port %d failed, errno = %d\n", 179 port_num, -fd); 180 goto out_free; 181 } 182 183 if (um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, 184 IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, 185 "port", port)) { 186 printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); 187 goto out_close; 188 } 189 190 *port = ((struct port_list) 191 { .list = LIST_HEAD_INIT(port->list), 192 .wait_count = ATOMIC_INIT(0), 193 .has_connection = 0, 194 .port = port_num, 195 .fd = fd, 196 .pending = LIST_HEAD_INIT(port->pending), 197 .connections = LIST_HEAD_INIT(port->connections) }); 198 spin_lock_init(&port->lock); 199 init_completion(&port->done); 200 list_add(&port->list, &ports); 201 202 found: 203 dev = kmalloc(sizeof(struct port_dev), GFP_KERNEL); 204 if (dev == NULL) { 205 printk(KERN_ERR "Allocation of port device entry failed\n"); 206 goto out; 207 } 208 209 *dev = ((struct port_dev) { .port = port, 210 .helper_pid = -1, 211 .telnetd_pid = -1 }); 212 goto out; 213 214 out_close: 215 os_close_file(fd); 216 out_free: 217 kfree(port); 218 out: 219 up(&ports_sem); 220 return dev; 221 } 222 223 int port_wait(void *data) 224 { 225 struct port_dev *dev = data; 226 struct connection *conn; 227 struct port_list *port = dev->port; 228 int fd; 229 230 atomic_inc(&port->wait_count); 231 while (1) { 232 fd = -ERESTARTSYS; 233 if (wait_for_completion_interruptible(&port->done)) 234 goto out; 235 236 spin_lock(&port->lock); 237 238 conn = list_entry(port->connections.next, struct connection, 239 list); 240 list_del(&conn->list); 241 spin_unlock(&port->lock); 242 243 os_shutdown_socket(conn->socket[0], 1, 1); 244 os_close_file(conn->socket[0]); 245 os_shutdown_socket(conn->socket[1], 1, 1); 246 os_close_file(conn->socket[1]); 247 248 /* This is done here because freeing an IRQ can't be done 249 * within the IRQ handler. So, pipe_interrupt always ups 250 * the semaphore regardless of whether it got a successful 251 * connection. Then we loop here throwing out failed 252 * connections until a good one is found. 253 */ 254 free_irq(TELNETD_IRQ, conn); 255 256 if (conn->fd >= 0) 257 break; 258 os_close_file(conn->fd); 259 kfree(conn); 260 } 261 262 fd = conn->fd; 263 dev->helper_pid = conn->helper_pid; 264 dev->telnetd_pid = conn->telnetd_pid; 265 kfree(conn); 266 out: 267 atomic_dec(&port->wait_count); 268 return fd; 269 } 270 271 void port_remove_dev(void *d) 272 { 273 struct port_dev *dev = d; 274 275 if (dev->helper_pid != -1) 276 os_kill_process(dev->helper_pid, 0); 277 if (dev->telnetd_pid != -1) 278 os_kill_process(dev->telnetd_pid, 1); 279 dev->helper_pid = -1; 280 dev->telnetd_pid = -1; 281 } 282 283 void port_kern_free(void *d) 284 { 285 struct port_dev *dev = d; 286 287 port_remove_dev(dev); 288 kfree(dev); 289 } 290 291 static void free_port(void) 292 { 293 struct list_head *ele; 294 struct port_list *port; 295 296 list_for_each(ele, &ports) { 297 port = list_entry(ele, struct port_list, list); 298 free_irq_by_fd(port->fd); 299 os_close_file(port->fd); 300 } 301 } 302 303 __uml_exitcall(free_port); 304