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