1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72#include <linux/kthread.h>
73#include <linux/module.h>
74#include <linux/freezer.h>
75#include "uwb-internal.h"
76
77#define D_LOCAL 1
78#include <linux/uwb/debug.h>
79
80
81
82
83
84
85
86
87
88
89
90
91typedef int (*uwbd_evt_handler_f)(struct uwb_event *);
92
93
94
95
96
97
98
99struct uwbd_event {
100 uwbd_evt_handler_f handler;
101 const char *name;
102};
103
104
105static
106struct uwbd_event uwbd_events[] = {
107 [UWB_RC_EVT_BEACON] = {
108 .handler = uwbd_evt_handle_rc_beacon,
109 .name = "BEACON_RECEIVED"
110 },
111 [UWB_RC_EVT_BEACON_SIZE] = {
112 .handler = uwbd_evt_handle_rc_beacon_size,
113 .name = "BEACON_SIZE_CHANGE"
114 },
115 [UWB_RC_EVT_BPOIE_CHANGE] = {
116 .handler = uwbd_evt_handle_rc_bpoie_change,
117 .name = "BPOIE_CHANGE"
118 },
119 [UWB_RC_EVT_BP_SLOT_CHANGE] = {
120 .handler = uwbd_evt_handle_rc_bp_slot_change,
121 .name = "BP_SLOT_CHANGE"
122 },
123 [UWB_RC_EVT_DRP_AVAIL] = {
124 .handler = uwbd_evt_handle_rc_drp_avail,
125 .name = "DRP_AVAILABILITY_CHANGE"
126 },
127 [UWB_RC_EVT_DRP] = {
128 .handler = uwbd_evt_handle_rc_drp,
129 .name = "DRP"
130 },
131 [UWB_RC_EVT_DEV_ADDR_CONFLICT] = {
132 .handler = uwbd_evt_handle_rc_dev_addr_conflict,
133 .name = "DEV_ADDR_CONFLICT",
134 },
135};
136
137
138
139struct uwbd_evt_type_handler {
140 const char *name;
141 struct uwbd_event *uwbd_events;
142 size_t size;
143};
144
145#define UWBD_EVT_TYPE_HANDLER(n,a) { \
146 .name = (n), \
147 .uwbd_events = (a), \
148 .size = sizeof(a)/sizeof((a)[0]) \
149}
150
151
152
153static
154struct uwbd_evt_type_handler uwbd_evt_type_handlers[] = {
155 [UWB_RC_CET_GENERAL] = UWBD_EVT_TYPE_HANDLER("RC", uwbd_events)
156};
157
158static const
159size_t uwbd_evt_type_handlers_len =
160 sizeof(uwbd_evt_type_handlers) / sizeof(uwbd_evt_type_handlers[0]);
161
162static const struct uwbd_event uwbd_message_handlers[] = {
163 [UWB_EVT_MSG_RESET] = {
164 .handler = uwbd_msg_handle_reset,
165 .name = "reset",
166 },
167};
168
169static DEFINE_MUTEX(uwbd_event_mutex);
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188static
189int uwbd_event_handle_urc(struct uwb_event *evt)
190{
191 struct uwbd_evt_type_handler *type_table;
192 uwbd_evt_handler_f handler;
193 u8 type, context;
194 u16 event;
195
196 type = evt->notif.rceb->bEventType;
197 event = le16_to_cpu(evt->notif.rceb->wEvent);
198 context = evt->notif.rceb->bEventContext;
199
200 if (type > uwbd_evt_type_handlers_len) {
201 printk(KERN_ERR "UWBD: event type %u: unknown (too high)\n", type);
202 return -EINVAL;
203 }
204 type_table = &uwbd_evt_type_handlers[type];
205 if (type_table->uwbd_events == NULL) {
206 printk(KERN_ERR "UWBD: event type %u: unknown\n", type);
207 return -EINVAL;
208 }
209 if (event > type_table->size) {
210 printk(KERN_ERR "UWBD: event %s[%u]: unknown (too high)\n",
211 type_table->name, event);
212 return -EINVAL;
213 }
214 handler = type_table->uwbd_events[event].handler;
215 if (handler == NULL) {
216 printk(KERN_ERR "UWBD: event %s[%u]: unknown\n", type_table->name, event);
217 return -EINVAL;
218 }
219 return (*handler)(evt);
220}
221
222static void uwbd_event_handle_message(struct uwb_event *evt)
223{
224 struct uwb_rc *rc;
225 int result;
226
227 rc = evt->rc;
228
229 if (evt->message < 0 || evt->message >= ARRAY_SIZE(uwbd_message_handlers)) {
230 dev_err(&rc->uwb_dev.dev, "UWBD: invalid message type %d\n", evt->message);
231 return;
232 }
233
234
235
236
237 if (evt->message == UWB_EVT_MSG_RESET)
238 mutex_unlock(&uwbd_event_mutex);
239
240 result = uwbd_message_handlers[evt->message].handler(evt);
241 if (result < 0)
242 dev_err(&rc->uwb_dev.dev, "UWBD: '%s' message failed: %d\n",
243 uwbd_message_handlers[evt->message].name, result);
244
245 if (evt->message == UWB_EVT_MSG_RESET)
246 mutex_lock(&uwbd_event_mutex);
247}
248
249static void uwbd_event_handle(struct uwb_event *evt)
250{
251 struct uwb_rc *rc;
252 int should_keep;
253
254 rc = evt->rc;
255
256 if (rc->ready) {
257 switch (evt->type) {
258 case UWB_EVT_TYPE_NOTIF:
259 should_keep = uwbd_event_handle_urc(evt);
260 if (should_keep <= 0)
261 kfree(evt->notif.rceb);
262 break;
263 case UWB_EVT_TYPE_MSG:
264 uwbd_event_handle_message(evt);
265 break;
266 default:
267 dev_err(&rc->uwb_dev.dev, "UWBD: invalid event type %d\n", evt->type);
268 break;
269 }
270 }
271
272 __uwb_rc_put(rc);
273}
274
275
276
277
278static int uwbd_pid;
279
280static struct task_struct *uwbd_task;
281
282static DECLARE_WAIT_QUEUE_HEAD(uwbd_wq);
283
284static struct list_head uwbd_event_list = LIST_HEAD_INIT(uwbd_event_list);
285
286static DEFINE_SPINLOCK(uwbd_event_list_lock);
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301static int uwbd(void *unused)
302{
303 unsigned long flags;
304 struct list_head list = LIST_HEAD_INIT(list);
305 struct uwb_event *evt, *nxt;
306 int should_stop = 0;
307 while (1) {
308 wait_event_interruptible_timeout(
309 uwbd_wq,
310 !list_empty(&uwbd_event_list)
311 || (should_stop = kthread_should_stop()),
312 HZ);
313 if (should_stop)
314 break;
315 try_to_freeze();
316
317 mutex_lock(&uwbd_event_mutex);
318 spin_lock_irqsave(&uwbd_event_list_lock, flags);
319 list_splice_init(&uwbd_event_list, &list);
320 spin_unlock_irqrestore(&uwbd_event_list_lock, flags);
321 list_for_each_entry_safe(evt, nxt, &list, list_node) {
322 list_del(&evt->list_node);
323 uwbd_event_handle(evt);
324 kfree(evt);
325 }
326 mutex_unlock(&uwbd_event_mutex);
327
328 uwb_beca_purge();
329 }
330 return 0;
331}
332
333
334
335void uwbd_start(void)
336{
337 uwbd_task = kthread_run(uwbd, NULL, "uwbd");
338 if (uwbd_task == NULL)
339 printk(KERN_ERR "UWB: Cannot start management daemon; "
340 "UWB won't work\n");
341 else
342 uwbd_pid = uwbd_task->pid;
343}
344
345
346void uwbd_stop(void)
347{
348 unsigned long flags;
349 struct uwb_event *evt, *nxt;
350 kthread_stop(uwbd_task);
351 spin_lock_irqsave(&uwbd_event_list_lock, flags);
352 uwbd_pid = 0;
353 list_for_each_entry_safe(evt, nxt, &uwbd_event_list, list_node) {
354 if (evt->type == UWB_EVT_TYPE_NOTIF)
355 kfree(evt->notif.rceb);
356 kfree(evt);
357 }
358 spin_unlock_irqrestore(&uwbd_event_list_lock, flags);
359 uwb_beca_release();
360}
361
362
363
364
365
366
367
368
369
370
371
372
373
374void uwbd_event_queue(struct uwb_event *evt)
375{
376 unsigned long flags;
377 spin_lock_irqsave(&uwbd_event_list_lock, flags);
378 if (uwbd_pid != 0) {
379 list_add(&evt->list_node, &uwbd_event_list);
380 wake_up_all(&uwbd_wq);
381 } else {
382 __uwb_rc_put(evt->rc);
383 if (evt->type == UWB_EVT_TYPE_NOTIF)
384 kfree(evt->notif.rceb);
385 kfree(evt);
386 }
387 spin_unlock_irqrestore(&uwbd_event_list_lock, flags);
388 return;
389}
390
391void uwbd_flush(struct uwb_rc *rc)
392{
393 struct uwb_event *evt, *nxt;
394
395 mutex_lock(&uwbd_event_mutex);
396
397 spin_lock_irq(&uwbd_event_list_lock);
398 list_for_each_entry_safe(evt, nxt, &uwbd_event_list, list_node) {
399 if (evt->rc == rc) {
400 __uwb_rc_put(rc);
401 list_del(&evt->list_node);
402 if (evt->type == UWB_EVT_TYPE_NOTIF)
403 kfree(evt->notif.rceb);
404 kfree(evt);
405 }
406 }
407 spin_unlock_irq(&uwbd_event_list_lock);
408
409 mutex_unlock(&uwbd_event_mutex);
410}