Loading...
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 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 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 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 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 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 | /* * WUSB Wire Adapter: Radio Control Interface (WUSB[8]) * Notification and Event Handling * * Copyright (C) 2005-2006 Intel Corporation * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * * The RC interface of the Host Wire Adapter (USB dongle) or WHCI PCI * card delivers a stream of notifications and events to the * notification end event endpoint or area. This code takes care of * getting a buffer with that data, breaking it up in separate * notifications and events and then deliver those. * * Events are answers to commands and they carry a context ID that * associates them to the command. Notifications are that, * notifications, they come out of the blue and have a context ID of * zero. Think of the context ID kind of like a handler. The * uwb_rc_neh_* code deals with managing context IDs. * * This is why you require a handle to operate on a UWB host. When you * open a handle a context ID is assigned to you. * * So, as it is done is: * * 1. Add an event handler [uwb_rc_neh_add()] (assigns a ctx id) * 2. Issue command [rc->cmd(rc, ...)] * 3. Arm the timeout timer [uwb_rc_neh_arm()] * 4, Release the reference to the neh [uwb_rc_neh_put()] * 5. Wait for the callback * 6. Command result (RCEB) is passed to the callback * * If (2) fails, you should remove the handle [uwb_rc_neh_rm()] * instead of arming the timer. * * Handles are for using in *serialized* code, single thread. * * When the notification/event comes, the IRQ handler/endpoint * callback passes the data read to uwb_rc_neh_grok() which will break * it up in a discrete series of events, look up who is listening for * them and execute the pertinent callbacks. * * If the reader detects an error while reading the data stream, call * uwb_rc_neh_error(). * * CONSTRAINTS/ASSUMPTIONS: * * - Most notifications/events are small (less thank .5k), copying * around is ok. * * - Notifications/events are ALWAYS smaller than PAGE_SIZE * * - Notifications/events always come in a single piece (ie: a buffer * will always contain entire notifications/events). * * - we cannot know in advance how long each event is (because they * lack a length field in their header--smart move by the standards * body, btw). So we need a facility to get the event size given the * header. This is what the EST code does (notif/Event Size * Tables), check nest.c--as well, you can associate the size to * the handle [w/ neh->extra_size()]. * * - Most notifications/events are fixed size; only a few are variable * size (NEST takes care of that). * * - Listeners of events expect them, so they usually provide a * buffer, as they know the size. Listeners to notifications don't, * so we allocate their buffers dynamically. */ #include <linux/kernel.h> #include <linux/timer.h> #include <linux/slab.h> #include <linux/err.h> #include <linux/export.h> #include "uwb-internal.h" /* * UWB Radio Controller Notification/Event Handle * * Represents an entity waiting for an event coming from the UWB Radio * Controller with a given context id (context) and type (evt_type and * evt). On reception of the notification/event, the callback (cb) is * called with the event. * * If the timer expires before the event is received, the callback is * called with -ETIMEDOUT as the event size. */ struct uwb_rc_neh { struct kref kref; struct uwb_rc *rc; u8 evt_type; __le16 evt; u8 context; u8 completed; uwb_rc_cmd_cb_f cb; void *arg; struct timer_list timer; struct list_head list_node; }; static void uwb_rc_neh_timer(struct timer_list *t); static void uwb_rc_neh_release(struct kref *kref) { struct uwb_rc_neh *neh = container_of(kref, struct uwb_rc_neh, kref); kfree(neh); } static void uwb_rc_neh_get(struct uwb_rc_neh *neh) { kref_get(&neh->kref); } /** * uwb_rc_neh_put - release reference to a neh * @neh: the neh */ void uwb_rc_neh_put(struct uwb_rc_neh *neh) { kref_put(&neh->kref, uwb_rc_neh_release); } /** * Assigns @neh a context id from @rc's pool * * @rc: UWB Radio Controller descriptor; @rc->neh_lock taken * @neh: Notification/Event Handle * @returns 0 if context id was assigned ok; < 0 errno on error (if * all the context IDs are taken). * * (assumes @wa is locked). * * NOTE: WUSB spec reserves context ids 0x00 for notifications and * 0xff is invalid, so they must not be used. Initialization * fills up those two in the bitmap so they are not allocated. * * We spread the allocation around to reduce the possibility of two * consecutive opened @neh's getting the same context ID assigned (to * avoid surprises with late events that timed out long time ago). So * first we search from where @rc->ctx_roll is, if not found, we * search from zero. */ static int __uwb_rc_ctx_get(struct uwb_rc *rc, struct uwb_rc_neh *neh) { int result; result = find_next_zero_bit(rc->ctx_bm, UWB_RC_CTX_MAX, rc->ctx_roll++); if (result < UWB_RC_CTX_MAX) goto found; result = find_first_zero_bit(rc->ctx_bm, UWB_RC_CTX_MAX); if (result < UWB_RC_CTX_MAX) goto found; return -ENFILE; found: set_bit(result, rc->ctx_bm); neh->context = result; return 0; } /** Releases @neh's context ID back to @rc (@rc->neh_lock is locked). */ static void __uwb_rc_ctx_put(struct uwb_rc *rc, struct uwb_rc_neh *neh) { struct device *dev = &rc->uwb_dev.dev; if (neh->context == 0) return; if (test_bit(neh->context, rc->ctx_bm) == 0) { dev_err(dev, "context %u not set in bitmap\n", neh->context); WARN_ON(1); } clear_bit(neh->context, rc->ctx_bm); neh->context = 0; } /** * uwb_rc_neh_add - add a neh for a radio controller command * @rc: the radio controller * @cmd: the radio controller command * @expected_type: the type of the expected response event * @expected_event: the expected event ID * @cb: callback for when the event is received * @arg: argument for the callback * * Creates a neh and adds it to the list of those waiting for an * event. A context ID will be assigned to the command. */ struct uwb_rc_neh *uwb_rc_neh_add(struct uwb_rc *rc, struct uwb_rccb *cmd, u8 expected_type, u16 expected_event, uwb_rc_cmd_cb_f cb, void *arg) { int result; unsigned long flags; struct device *dev = &rc->uwb_dev.dev; struct uwb_rc_neh *neh; neh = kzalloc(sizeof(*neh), GFP_KERNEL); if (neh == NULL) { result = -ENOMEM; goto error_kzalloc; } kref_init(&neh->kref); INIT_LIST_HEAD(&neh->list_node); timer_setup(&neh->timer, uwb_rc_neh_timer, 0); neh->rc = rc; neh->evt_type = expected_type; neh->evt = cpu_to_le16(expected_event); neh->cb = cb; neh->arg = arg; spin_lock_irqsave(&rc->neh_lock, flags); result = __uwb_rc_ctx_get(rc, neh); if (result >= 0) { cmd->bCommandContext = neh->context; list_add_tail(&neh->list_node, &rc->neh_list); uwb_rc_neh_get(neh); } spin_unlock_irqrestore(&rc->neh_lock, flags); if (result < 0) goto error_ctx_get; return neh; error_ctx_get: kfree(neh); error_kzalloc: dev_err(dev, "cannot open handle to radio controller: %d\n", result); return ERR_PTR(result); } static void __uwb_rc_neh_rm(struct uwb_rc *rc, struct uwb_rc_neh *neh) { __uwb_rc_ctx_put(rc, neh); list_del(&neh->list_node); } /** * uwb_rc_neh_rm - remove a neh. * @rc: the radio controller * @neh: the neh to remove * * Remove an active neh immediately instead of waiting for the event * (or a time out). */ void uwb_rc_neh_rm(struct uwb_rc *rc, struct uwb_rc_neh *neh) { unsigned long flags; spin_lock_irqsave(&rc->neh_lock, flags); __uwb_rc_neh_rm(rc, neh); spin_unlock_irqrestore(&rc->neh_lock, flags); del_timer_sync(&neh->timer); uwb_rc_neh_put(neh); } /** * uwb_rc_neh_arm - arm an event handler timeout timer * * @rc: UWB Radio Controller * @neh: Notification/event handler for @rc * * The timer is only armed if the neh is active. */ void uwb_rc_neh_arm(struct uwb_rc *rc, struct uwb_rc_neh *neh) { unsigned long flags; spin_lock_irqsave(&rc->neh_lock, flags); if (neh->context) mod_timer(&neh->timer, jiffies + msecs_to_jiffies(UWB_RC_CMD_TIMEOUT_MS)); spin_unlock_irqrestore(&rc->neh_lock, flags); } static void uwb_rc_neh_cb(struct uwb_rc_neh *neh, struct uwb_rceb *rceb, size_t size) { (*neh->cb)(neh->rc, neh->arg, rceb, size); uwb_rc_neh_put(neh); } static bool uwb_rc_neh_match(struct uwb_rc_neh *neh, const struct uwb_rceb *rceb) { return neh->evt_type == rceb->bEventType && neh->evt == rceb->wEvent && neh->context == rceb->bEventContext; } /** * Find the handle waiting for a RC Radio Control Event * * @rc: UWB Radio Controller * @rceb: Pointer to the RCEB buffer * @event_size: Pointer to the size of the RCEB buffer. Might be * adjusted to take into account the @neh->extra_size * settings. * * If the listener has no buffer (NULL buffer), one is allocated for * the right size (the amount of data received). @neh->ptr will point * to the event payload, which always starts with a 'struct * uwb_rceb'. kfree() it when done. */ static struct uwb_rc_neh *uwb_rc_neh_lookup(struct uwb_rc *rc, const struct uwb_rceb *rceb) { struct uwb_rc_neh *neh = NULL, *h; unsigned long flags; spin_lock_irqsave(&rc->neh_lock, flags); list_for_each_entry(h, &rc->neh_list, list_node) { if (uwb_rc_neh_match(h, rceb)) { neh = h; break; } } if (neh) __uwb_rc_neh_rm(rc, neh); spin_unlock_irqrestore(&rc->neh_lock, flags); return neh; } /* * Process notifications coming from the radio control interface * * @rc: UWB Radio Control Interface descriptor * @neh: Notification/Event Handler @neh->ptr points to * @uwb_evt->buffer. * * This function is called by the event/notif handling subsystem when * notifications arrive (hwarc_probe() arms a notification/event handle * that calls back this function for every received notification; this * function then will rearm itself). * * Notification data buffers are dynamically allocated by the NEH * handling code in neh.c [uwb_rc_neh_lookup()]. What is actually * allocated is space to contain the notification data. * * Buffers are prefixed with a Radio Control Event Block (RCEB) as * defined by the WUSB Wired-Adapter Radio Control interface. We * just use it for the notification code. * * On each case statement we just transcode endianess of the different * fields. We declare a pointer to a RCI definition of an event, and * then to a UWB definition of the same event (which are the same, * remember). Event if we use different pointers */ static void uwb_rc_notif(struct uwb_rc *rc, struct uwb_rceb *rceb, ssize_t size) { struct device *dev = &rc->uwb_dev.dev; struct uwb_event *uwb_evt; if (size == -ESHUTDOWN) return; if (size < 0) { dev_err(dev, "ignoring event with error code %zu\n", size); return; } uwb_evt = kzalloc(sizeof(*uwb_evt), GFP_ATOMIC); if (unlikely(uwb_evt == NULL)) { dev_err(dev, "no memory to queue event 0x%02x/%04x/%02x\n", rceb->bEventType, le16_to_cpu(rceb->wEvent), rceb->bEventContext); return; } uwb_evt->rc = __uwb_rc_get(rc); /* will be put by uwbd's uwbd_event_handle() */ uwb_evt->ts_jiffies = jiffies; uwb_evt->type = UWB_EVT_TYPE_NOTIF; uwb_evt->notif.size = size; uwb_evt->notif.rceb = rceb; uwbd_event_queue(uwb_evt); } static void uwb_rc_neh_grok_event(struct uwb_rc *rc, struct uwb_rceb *rceb, size_t size) { struct device *dev = &rc->uwb_dev.dev; struct uwb_rc_neh *neh; struct uwb_rceb *notif; unsigned long flags; if (rceb->bEventContext == 0) { notif = kmalloc(size, GFP_ATOMIC); if (notif) { memcpy(notif, rceb, size); uwb_rc_notif(rc, notif, size); } else dev_err(dev, "event 0x%02x/%04x/%02x (%zu bytes): no memory\n", rceb->bEventType, le16_to_cpu(rceb->wEvent), rceb->bEventContext, size); } else { neh = uwb_rc_neh_lookup(rc, rceb); if (neh) { spin_lock_irqsave(&rc->neh_lock, flags); /* to guard against a timeout */ neh->completed = 1; del_timer(&neh->timer); spin_unlock_irqrestore(&rc->neh_lock, flags); uwb_rc_neh_cb(neh, rceb, size); } else dev_warn(dev, "event 0x%02x/%04x/%02x (%zu bytes): nobody cared\n", rceb->bEventType, le16_to_cpu(rceb->wEvent), rceb->bEventContext, size); } } /** * Given a buffer with one or more UWB RC events/notifications, break * them up and dispatch them. * * @rc: UWB Radio Controller * @buf: Buffer with the stream of notifications/events * @buf_size: Amount of data in the buffer * * Note each notification/event starts always with a 'struct * uwb_rceb', so the minimum size if 4 bytes. * * The device may pass us events formatted differently than expected. * These are first filtered, potentially creating a new event in a new * memory location. If a new event is created by the filter it is also * freed here. * * For each notif/event, tries to guess the size looking at the EST * tables, then looks for a neh that is waiting for that event and if * found, copies the payload to the neh's buffer and calls it back. If * not, the data is ignored. * * Note that if we can't find a size description in the EST tables, we * still might find a size in the 'neh' handle in uwb_rc_neh_lookup(). * * Assumptions: * * @rc->neh_lock is NOT taken * * We keep track of various sizes here: * size: contains the size of the buffer that is processed for the * incoming event. this buffer may contain events that are not * formatted as WHCI. * real_size: the actual space taken by this event in the buffer. * We need to keep track of the real size of an event to be able to * advance the buffer correctly. * event_size: the size of the event as expected by the core layer * [OR] the size of the event after filtering. if the filtering * created a new event in a new memory location then this is * effectively the size of a new event buffer */ void uwb_rc_neh_grok(struct uwb_rc *rc, void *buf, size_t buf_size) { struct device *dev = &rc->uwb_dev.dev; void *itr; struct uwb_rceb *rceb; size_t size, real_size, event_size; int needtofree; itr = buf; size = buf_size; while (size > 0) { if (size < sizeof(*rceb)) { dev_err(dev, "not enough data in event buffer to " "process incoming events (%zu left, minimum is " "%zu)\n", size, sizeof(*rceb)); break; } rceb = itr; if (rc->filter_event) { needtofree = rc->filter_event(rc, &rceb, size, &real_size, &event_size); if (needtofree < 0 && needtofree != -ENOANO) { dev_err(dev, "BUG: Unable to filter event " "(0x%02x/%04x/%02x) from " "device. \n", rceb->bEventType, le16_to_cpu(rceb->wEvent), rceb->bEventContext); break; } } else needtofree = -ENOANO; /* do real processing if there was no filtering or the * filtering didn't act */ if (needtofree == -ENOANO) { ssize_t ret = uwb_est_find_size(rc, rceb, size); if (ret < 0) break; if (ret > size) { dev_err(dev, "BUG: hw sent incomplete event " "0x%02x/%04x/%02x (%zd bytes), only got " "%zu bytes. We don't handle that.\n", rceb->bEventType, le16_to_cpu(rceb->wEvent), rceb->bEventContext, ret, size); break; } real_size = event_size = ret; } uwb_rc_neh_grok_event(rc, rceb, event_size); if (needtofree == 1) kfree(rceb); itr += real_size; size -= real_size; } } EXPORT_SYMBOL_GPL(uwb_rc_neh_grok); /** * The entity that reads from the device notification/event channel has * detected an error. * * @rc: UWB Radio Controller * @error: Errno error code * */ void uwb_rc_neh_error(struct uwb_rc *rc, int error) { struct uwb_rc_neh *neh; unsigned long flags; for (;;) { spin_lock_irqsave(&rc->neh_lock, flags); if (list_empty(&rc->neh_list)) { spin_unlock_irqrestore(&rc->neh_lock, flags); break; } neh = list_first_entry(&rc->neh_list, struct uwb_rc_neh, list_node); __uwb_rc_neh_rm(rc, neh); spin_unlock_irqrestore(&rc->neh_lock, flags); del_timer_sync(&neh->timer); uwb_rc_neh_cb(neh, NULL, error); } } EXPORT_SYMBOL_GPL(uwb_rc_neh_error); static void uwb_rc_neh_timer(struct timer_list *t) { struct uwb_rc_neh *neh = from_timer(neh, t, timer); struct uwb_rc *rc = neh->rc; unsigned long flags; spin_lock_irqsave(&rc->neh_lock, flags); if (neh->completed) { spin_unlock_irqrestore(&rc->neh_lock, flags); return; } if (neh->context) __uwb_rc_neh_rm(rc, neh); else neh = NULL; spin_unlock_irqrestore(&rc->neh_lock, flags); if (neh) uwb_rc_neh_cb(neh, NULL, -ETIMEDOUT); } /** Initializes the @rc's neh subsystem */ void uwb_rc_neh_create(struct uwb_rc *rc) { spin_lock_init(&rc->neh_lock); INIT_LIST_HEAD(&rc->neh_list); set_bit(0, rc->ctx_bm); /* 0 is reserved (see [WUSB] table 8-65) */ set_bit(0xff, rc->ctx_bm); /* and 0xff is invalid */ rc->ctx_roll = 1; } /** Release's the @rc's neh subsystem */ void uwb_rc_neh_destroy(struct uwb_rc *rc) { unsigned long flags; struct uwb_rc_neh *neh; for (;;) { spin_lock_irqsave(&rc->neh_lock, flags); if (list_empty(&rc->neh_list)) { spin_unlock_irqrestore(&rc->neh_lock, flags); break; } neh = list_first_entry(&rc->neh_list, struct uwb_rc_neh, list_node); __uwb_rc_neh_rm(rc, neh); spin_unlock_irqrestore(&rc->neh_lock, flags); del_timer_sync(&neh->timer); uwb_rc_neh_put(neh); } } |