diff options
Diffstat (limited to 'arch/um/drivers/port_kern.c')
-rw-r--r-- | arch/um/drivers/port_kern.c | 82 |
1 files changed, 39 insertions, 43 deletions
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index d8acf7470e70..330543b3129b 100644 --- a/arch/um/drivers/port_kern.c +++ b/arch/um/drivers/port_kern.c | |||
@@ -1,24 +1,16 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/list.h" | 6 | #include "linux/completion.h" |
7 | #include "linux/sched.h" | ||
8 | #include "linux/slab.h" | ||
9 | #include "linux/interrupt.h" | 7 | #include "linux/interrupt.h" |
10 | #include "linux/spinlock.h" | 8 | #include "linux/list.h" |
11 | #include "linux/errno.h" | ||
12 | #include "asm/atomic.h" | 9 | #include "asm/atomic.h" |
13 | #include "asm/semaphore.h" | ||
14 | #include "asm/errno.h" | ||
15 | #include "kern_util.h" | ||
16 | #include "kern.h" | ||
17 | #include "irq_user.h" | ||
18 | #include "irq_kern.h" | ||
19 | #include "port.h" | ||
20 | #include "init.h" | 10 | #include "init.h" |
11 | #include "irq_kern.h" | ||
21 | #include "os.h" | 12 | #include "os.h" |
13 | #include "port.h" | ||
22 | 14 | ||
23 | struct port_list { | 15 | struct port_list { |
24 | struct list_head list; | 16 | struct list_head list; |
@@ -53,8 +45,8 @@ static irqreturn_t pipe_interrupt(int irq, void *data) | |||
53 | int fd; | 45 | int fd; |
54 | 46 | ||
55 | fd = os_rcv_fd(conn->socket[0], &conn->helper_pid); | 47 | fd = os_rcv_fd(conn->socket[0], &conn->helper_pid); |
56 | if(fd < 0){ | 48 | if (fd < 0) { |
57 | if(fd == -EAGAIN) | 49 | if (fd == -EAGAIN) |
58 | return IRQ_NONE; | 50 | return IRQ_NONE; |
59 | 51 | ||
60 | printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", | 52 | printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", |
@@ -81,18 +73,18 @@ static irqreturn_t pipe_interrupt(int irq, void *data) | |||
81 | static int port_accept(struct port_list *port) | 73 | static int port_accept(struct port_list *port) |
82 | { | 74 | { |
83 | struct connection *conn; | 75 | struct connection *conn; |
84 | int fd, socket[2], pid, ret = 0; | 76 | int fd, socket[2], pid; |
85 | 77 | ||
86 | fd = port_connection(port->fd, socket, &pid); | 78 | fd = port_connection(port->fd, socket, &pid); |
87 | if(fd < 0){ | 79 | if (fd < 0) { |
88 | if(fd != -EAGAIN) | 80 | if (fd != -EAGAIN) |
89 | printk(KERN_ERR "port_accept : port_connection " | 81 | printk(KERN_ERR "port_accept : port_connection " |
90 | "returned %d\n", -fd); | 82 | "returned %d\n", -fd); |
91 | goto out; | 83 | goto out; |
92 | } | 84 | } |
93 | 85 | ||
94 | conn = kmalloc(sizeof(*conn), GFP_ATOMIC); | 86 | conn = kmalloc(sizeof(*conn), GFP_ATOMIC); |
95 | if(conn == NULL){ | 87 | if (conn == NULL) { |
96 | printk(KERN_ERR "port_accept : failed to allocate " | 88 | printk(KERN_ERR "port_accept : failed to allocate " |
97 | "connection\n"); | 89 | "connection\n"); |
98 | goto out_close; | 90 | goto out_close; |
@@ -104,17 +96,17 @@ static int port_accept(struct port_list *port) | |||
104 | .telnetd_pid = pid, | 96 | .telnetd_pid = pid, |
105 | .port = port }); | 97 | .port = port }); |
106 | 98 | ||
107 | if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, | 99 | if (um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, |
108 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, | 100 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, |
109 | "telnetd", conn)){ | 101 | "telnetd", conn)) { |
110 | printk(KERN_ERR "port_accept : failed to get IRQ for " | 102 | printk(KERN_ERR "port_accept : failed to get IRQ for " |
111 | "telnetd\n"); | 103 | "telnetd\n"); |
112 | goto out_free; | 104 | goto out_free; |
113 | } | 105 | } |
114 | 106 | ||
115 | if(atomic_read(&port->wait_count) == 0){ | 107 | if (atomic_read(&port->wait_count) == 0) { |
116 | os_write_file(fd, NO_WAITER_MSG, sizeof(NO_WAITER_MSG)); | 108 | os_write_file(fd, NO_WAITER_MSG, sizeof(NO_WAITER_MSG)); |
117 | printk("No one waiting for port\n"); | 109 | printk(KERN_ERR "No one waiting for port\n"); |
118 | } | 110 | } |
119 | list_add(&conn->list, &port->pending); | 111 | list_add(&conn->list, &port->pending); |
120 | return 1; | 112 | return 1; |
@@ -123,28 +115,29 @@ static int port_accept(struct port_list *port) | |||
123 | kfree(conn); | 115 | kfree(conn); |
124 | out_close: | 116 | out_close: |
125 | os_close_file(fd); | 117 | os_close_file(fd); |
126 | if(pid != -1) | 118 | os_kill_process(pid, 1); |
127 | os_kill_process(pid, 1); | ||
128 | out: | 119 | out: |
129 | return ret; | 120 | return 0; |
130 | } | 121 | } |
131 | 122 | ||
132 | static DECLARE_MUTEX(ports_sem); | 123 | static DECLARE_MUTEX(ports_sem); |
133 | static LIST_HEAD(ports); | 124 | static LIST_HEAD(ports); |
134 | 125 | ||
135 | void port_work_proc(struct work_struct *unused) | 126 | static void port_work_proc(struct work_struct *unused) |
136 | { | 127 | { |
137 | struct port_list *port; | 128 | struct port_list *port; |
138 | struct list_head *ele; | 129 | struct list_head *ele; |
139 | unsigned long flags; | 130 | unsigned long flags; |
140 | 131 | ||
141 | local_irq_save(flags); | 132 | local_irq_save(flags); |
142 | list_for_each(ele, &ports){ | 133 | list_for_each(ele, &ports) { |
143 | port = list_entry(ele, struct port_list, list); | 134 | port = list_entry(ele, struct port_list, list); |
144 | if(!port->has_connection) | 135 | if (!port->has_connection) |
145 | continue; | 136 | continue; |
137 | |||
146 | reactivate_fd(port->fd, ACCEPT_IRQ); | 138 | reactivate_fd(port->fd, ACCEPT_IRQ); |
147 | while(port_accept(port)) ; | 139 | while (port_accept(port)) |
140 | ; | ||
148 | port->has_connection = 0; | 141 | port->has_connection = 0; |
149 | } | 142 | } |
150 | local_irq_restore(flags); | 143 | local_irq_restore(flags); |
@@ -169,25 +162,27 @@ void *port_data(int port_num) | |||
169 | int fd; | 162 | int fd; |
170 | 163 | ||
171 | down(&ports_sem); | 164 | down(&ports_sem); |
172 | list_for_each(ele, &ports){ | 165 | list_for_each(ele, &ports) { |
173 | port = list_entry(ele, struct port_list, list); | 166 | port = list_entry(ele, struct port_list, list); |
174 | if(port->port == port_num) goto found; | 167 | if (port->port == port_num) |
168 | goto found; | ||
175 | } | 169 | } |
176 | port = kmalloc(sizeof(struct port_list), GFP_KERNEL); | 170 | port = kmalloc(sizeof(struct port_list), GFP_KERNEL); |
177 | if(port == NULL){ | 171 | if (port == NULL) { |
178 | printk(KERN_ERR "Allocation of port list failed\n"); | 172 | printk(KERN_ERR "Allocation of port list failed\n"); |
179 | goto out; | 173 | goto out; |
180 | } | 174 | } |
181 | 175 | ||
182 | fd = port_listen_fd(port_num); | 176 | fd = port_listen_fd(port_num); |
183 | if(fd < 0){ | 177 | if (fd < 0) { |
184 | printk(KERN_ERR "binding to port %d failed, errno = %d\n", | 178 | printk(KERN_ERR "binding to port %d failed, errno = %d\n", |
185 | port_num, -fd); | 179 | port_num, -fd); |
186 | goto out_free; | 180 | goto out_free; |
187 | } | 181 | } |
188 | if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, | 182 | |
183 | if (um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, | ||
189 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, | 184 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, |
190 | "port", port)){ | 185 | "port", port)) { |
191 | printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); | 186 | printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); |
192 | goto out_close; | 187 | goto out_close; |
193 | } | 188 | } |
@@ -206,7 +201,7 @@ void *port_data(int port_num) | |||
206 | 201 | ||
207 | found: | 202 | found: |
208 | dev = kmalloc(sizeof(struct port_dev), GFP_KERNEL); | 203 | dev = kmalloc(sizeof(struct port_dev), GFP_KERNEL); |
209 | if(dev == NULL){ | 204 | if (dev == NULL) { |
210 | printk(KERN_ERR "Allocation of port device entry failed\n"); | 205 | printk(KERN_ERR "Allocation of port device entry failed\n"); |
211 | goto out; | 206 | goto out; |
212 | } | 207 | } |
@@ -233,9 +228,9 @@ int port_wait(void *data) | |||
233 | int fd; | 228 | int fd; |
234 | 229 | ||
235 | atomic_inc(&port->wait_count); | 230 | atomic_inc(&port->wait_count); |
236 | while(1){ | 231 | while (1) { |
237 | fd = -ERESTARTSYS; | 232 | fd = -ERESTARTSYS; |
238 | if(wait_for_completion_interruptible(&port->done)) | 233 | if (wait_for_completion_interruptible(&port->done)) |
239 | goto out; | 234 | goto out; |
240 | 235 | ||
241 | spin_lock(&port->lock); | 236 | spin_lock(&port->lock); |
@@ -258,7 +253,8 @@ int port_wait(void *data) | |||
258 | */ | 253 | */ |
259 | free_irq(TELNETD_IRQ, conn); | 254 | free_irq(TELNETD_IRQ, conn); |
260 | 255 | ||
261 | if(conn->fd >= 0) break; | 256 | if (conn->fd >= 0) |
257 | break; | ||
262 | os_close_file(conn->fd); | 258 | os_close_file(conn->fd); |
263 | kfree(conn); | 259 | kfree(conn); |
264 | } | 260 | } |
@@ -276,9 +272,9 @@ void port_remove_dev(void *d) | |||
276 | { | 272 | { |
277 | struct port_dev *dev = d; | 273 | struct port_dev *dev = d; |
278 | 274 | ||
279 | if(dev->helper_pid != -1) | 275 | if (dev->helper_pid != -1) |
280 | os_kill_process(dev->helper_pid, 0); | 276 | os_kill_process(dev->helper_pid, 0); |
281 | if(dev->telnetd_pid != -1) | 277 | if (dev->telnetd_pid != -1) |
282 | os_kill_process(dev->telnetd_pid, 1); | 278 | os_kill_process(dev->telnetd_pid, 1); |
283 | dev->helper_pid = -1; | 279 | dev->helper_pid = -1; |
284 | dev->telnetd_pid = -1; | 280 | dev->telnetd_pid = -1; |
@@ -297,7 +293,7 @@ static void free_port(void) | |||
297 | struct list_head *ele; | 293 | struct list_head *ele; |
298 | struct port_list *port; | 294 | struct port_list *port; |
299 | 295 | ||
300 | list_for_each(ele, &ports){ | 296 | list_for_each(ele, &ports) { |
301 | port = list_entry(ele, struct port_list, list); | 297 | port = list_entry(ele, struct port_list, list); |
302 | free_irq_by_fd(port->fd); | 298 | free_irq_by_fd(port->fd); |
303 | os_close_file(port->fd); | 299 | os_close_file(port->fd); |