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
73
74
75
76
77
78
79
80
81
82
83
84#include <linux/kernel.h>
85#include <linux/timer.h>
86#include <linux/err.h>
87
88#include "uwb-internal.h"
89#define D_LOCAL 0
90#include <linux/uwb/debug.h>
91
92
93
94
95
96
97
98
99
100
101
102
103struct uwb_rc_neh {
104 struct kref kref;
105
106 struct uwb_rc *rc;
107 u8 evt_type;
108 __le16 evt;
109 u8 context;
110 uwb_rc_cmd_cb_f cb;
111 void *arg;
112
113 struct timer_list timer;
114 struct list_head list_node;
115};
116
117static void uwb_rc_neh_timer(unsigned long arg);
118
119static void uwb_rc_neh_release(struct kref *kref)
120{
121 struct uwb_rc_neh *neh = container_of(kref, struct uwb_rc_neh, kref);
122
123 kfree(neh);
124}
125
126static void uwb_rc_neh_get(struct uwb_rc_neh *neh)
127{
128 kref_get(&neh->kref);
129}
130
131
132
133
134
135void uwb_rc_neh_put(struct uwb_rc_neh *neh)
136{
137 kref_put(&neh->kref, uwb_rc_neh_release);
138}
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161static
162int __uwb_rc_ctx_get(struct uwb_rc *rc, struct uwb_rc_neh *neh)
163{
164 int result;
165 result = find_next_zero_bit(rc->ctx_bm, UWB_RC_CTX_MAX,
166 rc->ctx_roll++);
167 if (result < UWB_RC_CTX_MAX)
168 goto found;
169 result = find_first_zero_bit(rc->ctx_bm, UWB_RC_CTX_MAX);
170 if (result < UWB_RC_CTX_MAX)
171 goto found;
172 return -ENFILE;
173found:
174 set_bit(result, rc->ctx_bm);
175 neh->context = result;
176 return 0;
177}
178
179
180
181static
182void __uwb_rc_ctx_put(struct uwb_rc *rc, struct uwb_rc_neh *neh)
183{
184 struct device *dev = &rc->uwb_dev.dev;
185 if (neh->context == 0)
186 return;
187 if (test_bit(neh->context, rc->ctx_bm) == 0) {
188 dev_err(dev, "context %u not set in bitmap\n",
189 neh->context);
190 WARN_ON(1);
191 }
192 clear_bit(neh->context, rc->ctx_bm);
193 neh->context = 0;
194}
195
196
197
198
199
200
201
202
203
204
205
206
207
208struct uwb_rc_neh *uwb_rc_neh_add(struct uwb_rc *rc, struct uwb_rccb *cmd,
209 u8 expected_type, u16 expected_event,
210 uwb_rc_cmd_cb_f cb, void *arg)
211{
212 int result;
213 unsigned long flags;
214 struct device *dev = &rc->uwb_dev.dev;
215 struct uwb_rc_neh *neh;
216
217 neh = kzalloc(sizeof(*neh), GFP_KERNEL);
218 if (neh == NULL) {
219 result = -ENOMEM;
220 goto error_kzalloc;
221 }
222
223 kref_init(&neh->kref);
224 INIT_LIST_HEAD(&neh->list_node);
225 init_timer(&neh->timer);
226 neh->timer.function = uwb_rc_neh_timer;
227 neh->timer.data = (unsigned long)neh;
228
229 neh->rc = rc;
230 neh->evt_type = expected_type;
231 neh->evt = cpu_to_le16(expected_event);
232 neh->cb = cb;
233 neh->arg = arg;
234
235 spin_lock_irqsave(&rc->neh_lock, flags);
236 result = __uwb_rc_ctx_get(rc, neh);
237 if (result >= 0) {
238 cmd->bCommandContext = neh->context;
239 list_add_tail(&neh->list_node, &rc->neh_list);
240 uwb_rc_neh_get(neh);
241 }
242 spin_unlock_irqrestore(&rc->neh_lock, flags);
243 if (result < 0)
244 goto error_ctx_get;
245
246 return neh;
247
248error_ctx_get:
249 kfree(neh);
250error_kzalloc:
251 dev_err(dev, "cannot open handle to radio controller: %d\n", result);
252 return ERR_PTR(result);
253}
254
255static void __uwb_rc_neh_rm(struct uwb_rc *rc, struct uwb_rc_neh *neh)
256{
257 del_timer(&neh->timer);
258 __uwb_rc_ctx_put(rc, neh);
259 list_del(&neh->list_node);
260}
261
262
263
264
265
266
267
268
269
270void uwb_rc_neh_rm(struct uwb_rc *rc, struct uwb_rc_neh *neh)
271{
272 unsigned long flags;
273
274 spin_lock_irqsave(&rc->neh_lock, flags);
275 __uwb_rc_neh_rm(rc, neh);
276 spin_unlock_irqrestore(&rc->neh_lock, flags);
277
278 uwb_rc_neh_put(neh);
279}
280
281
282
283
284
285
286
287
288
289void uwb_rc_neh_arm(struct uwb_rc *rc, struct uwb_rc_neh *neh)
290{
291 unsigned long flags;
292
293 spin_lock_irqsave(&rc->neh_lock, flags);
294 if (neh->context)
295 mod_timer(&neh->timer,
296 jiffies + msecs_to_jiffies(UWB_RC_CMD_TIMEOUT_MS));
297 spin_unlock_irqrestore(&rc->neh_lock, flags);
298}
299
300static void uwb_rc_neh_cb(struct uwb_rc_neh *neh, struct uwb_rceb *rceb, size_t size)
301{
302 (*neh->cb)(neh->rc, neh->arg, rceb, size);
303 uwb_rc_neh_put(neh);
304}
305
306static bool uwb_rc_neh_match(struct uwb_rc_neh *neh, const struct uwb_rceb *rceb)
307{
308 return neh->evt_type == rceb->bEventType
309 && neh->evt == rceb->wEvent
310 && neh->context == rceb->bEventContext;
311}
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327static
328struct uwb_rc_neh *uwb_rc_neh_lookup(struct uwb_rc *rc,
329 const struct uwb_rceb *rceb)
330{
331 struct uwb_rc_neh *neh = NULL, *h;
332 unsigned long flags;
333
334 spin_lock_irqsave(&rc->neh_lock, flags);
335
336 list_for_each_entry(h, &rc->neh_list, list_node) {
337 if (uwb_rc_neh_match(h, rceb)) {
338 neh = h;
339 break;
340 }
341 }
342
343 if (neh)
344 __uwb_rc_neh_rm(rc, neh);
345
346 spin_unlock_irqrestore(&rc->neh_lock, flags);
347
348 return neh;
349}
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377static
378void uwb_rc_notif(struct uwb_rc *rc, struct uwb_rceb *rceb, ssize_t size)
379{
380 struct device *dev = &rc->uwb_dev.dev;
381 struct uwb_event *uwb_evt;
382
383 if (size == -ESHUTDOWN)
384 return;
385 if (size < 0) {
386 dev_err(dev, "ignoring event with error code %zu\n",
387 size);
388 return;
389 }
390
391 uwb_evt = kzalloc(sizeof(*uwb_evt), GFP_ATOMIC);
392 if (unlikely(uwb_evt == NULL)) {
393 dev_err(dev, "no memory to queue event 0x%02x/%04x/%02x\n",
394 rceb->bEventType, le16_to_cpu(rceb->wEvent),
395 rceb->bEventContext);
396 return;
397 }
398 uwb_evt->rc = __uwb_rc_get(rc);
399 uwb_evt->ts_jiffies = jiffies;
400 uwb_evt->type = UWB_EVT_TYPE_NOTIF;
401 uwb_evt->notif.size = size;
402 uwb_evt->notif.rceb = rceb;
403
404 switch (le16_to_cpu(rceb->wEvent)) {
405
406
407
408
409
410
411 case 0x0103:
412 dev_info(dev, "FIXME: DEVICE ADD\n");
413 return;
414 case 0x0104:
415 dev_info(dev, "FIXME: DEVICE RM\n");
416 return;
417 default:
418 break;
419 }
420
421 uwbd_event_queue(uwb_evt);
422}
423
424static void uwb_rc_neh_grok_event(struct uwb_rc *rc, struct uwb_rceb *rceb, size_t size)
425{
426 struct device *dev = &rc->uwb_dev.dev;
427 struct uwb_rc_neh *neh;
428 struct uwb_rceb *notif;
429
430 if (rceb->bEventContext == 0) {
431 notif = kmalloc(size, GFP_ATOMIC);
432 if (notif) {
433 memcpy(notif, rceb, size);
434 uwb_rc_notif(rc, notif, size);
435 } else
436 dev_err(dev, "event 0x%02x/%04x/%02x (%zu bytes): no memory\n",
437 rceb->bEventType, le16_to_cpu(rceb->wEvent),
438 rceb->bEventContext, size);
439 } else {
440 neh = uwb_rc_neh_lookup(rc, rceb);
441 if (neh)
442 uwb_rc_neh_cb(neh, rceb, size);
443 else
444 dev_warn(dev, "event 0x%02x/%04x/%02x (%zu bytes): nobody cared\n",
445 rceb->bEventType, le16_to_cpu(rceb->wEvent),
446 rceb->bEventContext, size);
447 }
448}
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490void uwb_rc_neh_grok(struct uwb_rc *rc, void *buf, size_t buf_size)
491{
492 struct device *dev = &rc->uwb_dev.dev;
493 void *itr;
494 struct uwb_rceb *rceb;
495 size_t size, real_size, event_size;
496 int needtofree;
497
498 d_fnstart(3, dev, "(rc %p buf %p %zu buf_size)\n", rc, buf, buf_size);
499 d_printf(2, dev, "groking event block: %zu bytes\n", buf_size);
500 itr = buf;
501 size = buf_size;
502 while (size > 0) {
503 if (size < sizeof(*rceb)) {
504 dev_err(dev, "not enough data in event buffer to "
505 "process incoming events (%zu left, minimum is "
506 "%zu)\n", size, sizeof(*rceb));
507 break;
508 }
509
510 rceb = itr;
511 if (rc->filter_event) {
512 needtofree = rc->filter_event(rc, &rceb, size,
513 &real_size, &event_size);
514 if (needtofree < 0 && needtofree != -ENOANO) {
515 dev_err(dev, "BUG: Unable to filter event "
516 "(0x%02x/%04x/%02x) from "
517 "device. \n", rceb->bEventType,
518 le16_to_cpu(rceb->wEvent),
519 rceb->bEventContext);
520 break;
521 }
522 } else
523 needtofree = -ENOANO;
524
525
526 if (needtofree == -ENOANO) {
527 ssize_t ret = uwb_est_find_size(rc, rceb, size);
528 if (ret < 0)
529 break;
530 if (ret > size) {
531 dev_err(dev, "BUG: hw sent incomplete event "
532 "0x%02x/%04x/%02x (%zd bytes), only got "
533 "%zu bytes. We don't handle that.\n",
534 rceb->bEventType, le16_to_cpu(rceb->wEvent),
535 rceb->bEventContext, ret, size);
536 break;
537 }
538 real_size = event_size = ret;
539 }
540 uwb_rc_neh_grok_event(rc, rceb, event_size);
541
542 if (needtofree == 1)
543 kfree(rceb);
544
545 itr += real_size;
546 size -= real_size;
547 d_printf(2, dev, "consumed %zd bytes, %zu left\n",
548 event_size, size);
549 }
550 d_fnend(3, dev, "(rc %p buf %p %zu buf_size) = void\n", rc, buf, buf_size);
551}
552EXPORT_SYMBOL_GPL(uwb_rc_neh_grok);
553
554
555
556
557
558
559
560
561
562
563void uwb_rc_neh_error(struct uwb_rc *rc, int error)
564{
565 struct uwb_rc_neh *neh, *next;
566 unsigned long flags;
567
568 BUG_ON(error >= 0);
569 spin_lock_irqsave(&rc->neh_lock, flags);
570 list_for_each_entry_safe(neh, next, &rc->neh_list, list_node) {
571 __uwb_rc_neh_rm(rc, neh);
572 uwb_rc_neh_cb(neh, NULL, error);
573 }
574 spin_unlock_irqrestore(&rc->neh_lock, flags);
575}
576EXPORT_SYMBOL_GPL(uwb_rc_neh_error);
577
578
579static void uwb_rc_neh_timer(unsigned long arg)
580{
581 struct uwb_rc_neh *neh = (struct uwb_rc_neh *)arg;
582 struct uwb_rc *rc = neh->rc;
583 unsigned long flags;
584
585 spin_lock_irqsave(&rc->neh_lock, flags);
586 __uwb_rc_neh_rm(rc, neh);
587 spin_unlock_irqrestore(&rc->neh_lock, flags);
588
589 uwb_rc_neh_cb(neh, NULL, -ETIMEDOUT);
590}
591
592
593
594void uwb_rc_neh_create(struct uwb_rc *rc)
595{
596 spin_lock_init(&rc->neh_lock);
597 INIT_LIST_HEAD(&rc->neh_list);
598 set_bit(0, rc->ctx_bm);
599 set_bit(0xff, rc->ctx_bm);
600 rc->ctx_roll = 1;
601}
602
603
604
605void uwb_rc_neh_destroy(struct uwb_rc *rc)
606{
607 unsigned long flags;
608 struct uwb_rc_neh *neh, *next;
609
610 spin_lock_irqsave(&rc->neh_lock, flags);
611 list_for_each_entry_safe(neh, next, &rc->neh_list, list_node) {
612 __uwb_rc_neh_rm(rc, neh);
613 uwb_rc_neh_put(neh);
614 }
615 spin_unlock_irqrestore(&rc->neh_lock, flags);
616}