Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.1-rc2 583 lines 14 kB view raw
1/* 2 * Ultra Wide Band 3 * Life cycle of radio controllers 4 * 5 * Copyright (C) 2005-2006 Intel Corporation 6 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License version 10 * 2 as published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 * 02110-1301, USA. 21 * 22 * 23 * FIXME: docs 24 * 25 * A UWB radio controller is also a UWB device, so it embeds one... 26 * 27 * List of RCs comes from the 'struct class uwb_rc_class'. 28 */ 29 30#include <linux/kernel.h> 31#include <linux/string.h> 32#include <linux/device.h> 33#include <linux/err.h> 34#include <linux/random.h> 35#include <linux/kdev_t.h> 36#include <linux/etherdevice.h> 37#include <linux/usb.h> 38#include <linux/slab.h> 39#include <linux/export.h> 40 41#include "uwb-internal.h" 42 43static int uwb_rc_index_match(struct device *dev, const void *data) 44{ 45 const int *index = data; 46 struct uwb_rc *rc = dev_get_drvdata(dev); 47 48 if (rc->index == *index) 49 return 1; 50 return 0; 51} 52 53static struct uwb_rc *uwb_rc_find_by_index(int index) 54{ 55 struct device *dev; 56 struct uwb_rc *rc = NULL; 57 58 dev = class_find_device(&uwb_rc_class, NULL, &index, uwb_rc_index_match); 59 if (dev) { 60 rc = dev_get_drvdata(dev); 61 put_device(dev); 62 } 63 64 return rc; 65} 66 67static int uwb_rc_new_index(void) 68{ 69 int index = 0; 70 71 for (;;) { 72 if (!uwb_rc_find_by_index(index)) 73 return index; 74 if (++index < 0) 75 index = 0; 76 } 77} 78 79/** 80 * Release the backing device of a uwb_rc that has been dynamically allocated. 81 */ 82static void uwb_rc_sys_release(struct device *dev) 83{ 84 struct uwb_dev *uwb_dev = container_of(dev, struct uwb_dev, dev); 85 struct uwb_rc *rc = container_of(uwb_dev, struct uwb_rc, uwb_dev); 86 87 uwb_rc_ie_release(rc); 88 kfree(rc); 89} 90 91 92void uwb_rc_init(struct uwb_rc *rc) 93{ 94 struct uwb_dev *uwb_dev = &rc->uwb_dev; 95 96 uwb_dev_init(uwb_dev); 97 rc->uwb_dev.dev.class = &uwb_rc_class; 98 rc->uwb_dev.dev.release = uwb_rc_sys_release; 99 uwb_rc_neh_create(rc); 100 rc->beaconing = -1; 101 rc->scan_type = UWB_SCAN_DISABLED; 102 INIT_LIST_HEAD(&rc->notifs_chain.list); 103 mutex_init(&rc->notifs_chain.mutex); 104 INIT_LIST_HEAD(&rc->uwb_beca.list); 105 mutex_init(&rc->uwb_beca.mutex); 106 uwb_drp_avail_init(rc); 107 uwb_rc_ie_init(rc); 108 uwb_rsv_init(rc); 109 uwb_rc_pal_init(rc); 110} 111EXPORT_SYMBOL_GPL(uwb_rc_init); 112 113 114struct uwb_rc *uwb_rc_alloc(void) 115{ 116 struct uwb_rc *rc; 117 rc = kzalloc(sizeof(*rc), GFP_KERNEL); 118 if (rc == NULL) 119 return NULL; 120 uwb_rc_init(rc); 121 return rc; 122} 123EXPORT_SYMBOL_GPL(uwb_rc_alloc); 124 125/* 126 * Show the ASIE that is broadcast in the UWB beacon by this uwb_rc device. 127 */ 128static ssize_t ASIE_show(struct device *dev, 129 struct device_attribute *attr, char *buf) 130{ 131 struct uwb_dev *uwb_dev = to_uwb_dev(dev); 132 struct uwb_rc *rc = uwb_dev->rc; 133 struct uwb_ie_hdr *ie; 134 void *ptr; 135 size_t len; 136 int result = 0; 137 138 /* init empty buffer. */ 139 result = scnprintf(buf, PAGE_SIZE, "\n"); 140 mutex_lock(&rc->ies_mutex); 141 /* walk IEData looking for an ASIE. */ 142 ptr = rc->ies->IEData; 143 len = le16_to_cpu(rc->ies->wIELength); 144 for (;;) { 145 ie = uwb_ie_next(&ptr, &len); 146 if (!ie) 147 break; 148 if (ie->element_id == UWB_APP_SPEC_IE) { 149 result = uwb_ie_dump_hex(ie, 150 ie->length + sizeof(struct uwb_ie_hdr), 151 buf, PAGE_SIZE); 152 break; 153 } 154 } 155 mutex_unlock(&rc->ies_mutex); 156 157 return result; 158} 159 160/* 161 * Update the ASIE that is broadcast in the UWB beacon by this uwb_rc device. 162 */ 163static ssize_t ASIE_store(struct device *dev, 164 struct device_attribute *attr, 165 const char *buf, size_t size) 166{ 167 struct uwb_dev *uwb_dev = to_uwb_dev(dev); 168 struct uwb_rc *rc = uwb_dev->rc; 169 char ie_buf[255]; 170 int result, ie_len = 0; 171 const char *cur_ptr = buf; 172 struct uwb_ie_hdr *ie; 173 174 /* empty string means clear the ASIE. */ 175 if (strlen(buf) <= 1) { 176 uwb_rc_ie_rm(rc, UWB_APP_SPEC_IE); 177 return size; 178 } 179 180 /* if non-empty string, convert string of hex chars to binary. */ 181 while (ie_len < sizeof(ie_buf)) { 182 int char_count; 183 184 if (sscanf(cur_ptr, " %02hhX %n", 185 &(ie_buf[ie_len]), &char_count) > 0) { 186 ++ie_len; 187 /* skip chars read from cur_ptr. */ 188 cur_ptr += char_count; 189 } else { 190 break; 191 } 192 } 193 194 /* validate IE length and type. */ 195 if (ie_len < sizeof(struct uwb_ie_hdr)) { 196 dev_err(dev, "%s: Invalid ASIE size %d.\n", __func__, ie_len); 197 return -EINVAL; 198 } 199 200 ie = (struct uwb_ie_hdr *)ie_buf; 201 if (ie->element_id != UWB_APP_SPEC_IE) { 202 dev_err(dev, "%s: Invalid IE element type size = 0x%02X.\n", 203 __func__, ie->element_id); 204 return -EINVAL; 205 } 206 207 /* bounds check length field from user. */ 208 if (ie->length > (ie_len - sizeof(struct uwb_ie_hdr))) 209 ie->length = ie_len - sizeof(struct uwb_ie_hdr); 210 211 /* 212 * Valid ASIE received. Remove current ASIE then add the new one using 213 * uwb_rc_ie_add. 214 */ 215 uwb_rc_ie_rm(rc, UWB_APP_SPEC_IE); 216 217 result = uwb_rc_ie_add(rc, ie, ie->length + sizeof(struct uwb_ie_hdr)); 218 219 return result >= 0 ? size : result; 220} 221static DEVICE_ATTR_RW(ASIE); 222 223static struct attribute *rc_attrs[] = { 224 &dev_attr_mac_address.attr, 225 &dev_attr_scan.attr, 226 &dev_attr_beacon.attr, 227 &dev_attr_ASIE.attr, 228 NULL, 229}; 230 231static const struct attribute_group rc_attr_group = { 232 .attrs = rc_attrs, 233}; 234 235/* 236 * Registration of sysfs specific stuff 237 */ 238static int uwb_rc_sys_add(struct uwb_rc *rc) 239{ 240 return sysfs_create_group(&rc->uwb_dev.dev.kobj, &rc_attr_group); 241} 242 243 244static void __uwb_rc_sys_rm(struct uwb_rc *rc) 245{ 246 sysfs_remove_group(&rc->uwb_dev.dev.kobj, &rc_attr_group); 247} 248 249/** 250 * uwb_rc_mac_addr_setup - get an RC's EUI-48 address or set it 251 * @rc: the radio controller. 252 * 253 * If the EUI-48 address is 00:00:00:00:00:00 or FF:FF:FF:FF:FF:FF 254 * then a random locally administered EUI-48 is generated and set on 255 * the device. The probability of address collisions is sufficiently 256 * unlikely (1/2^40 = 9.1e-13) that they're not checked for. 257 */ 258static 259int uwb_rc_mac_addr_setup(struct uwb_rc *rc) 260{ 261 int result; 262 struct device *dev = &rc->uwb_dev.dev; 263 struct uwb_dev *uwb_dev = &rc->uwb_dev; 264 char devname[UWB_ADDR_STRSIZE]; 265 struct uwb_mac_addr addr; 266 267 result = uwb_rc_mac_addr_get(rc, &addr); 268 if (result < 0) { 269 dev_err(dev, "cannot retrieve UWB EUI-48 address: %d\n", result); 270 return result; 271 } 272 273 if (uwb_mac_addr_unset(&addr) || uwb_mac_addr_bcast(&addr)) { 274 addr.data[0] = 0x02; /* locally administered and unicast */ 275 get_random_bytes(&addr.data[1], sizeof(addr.data)-1); 276 277 result = uwb_rc_mac_addr_set(rc, &addr); 278 if (result < 0) { 279 uwb_mac_addr_print(devname, sizeof(devname), &addr); 280 dev_err(dev, "cannot set EUI-48 address %s: %d\n", 281 devname, result); 282 return result; 283 } 284 } 285 uwb_dev->mac_addr = addr; 286 return 0; 287} 288 289 290 291static int uwb_rc_setup(struct uwb_rc *rc) 292{ 293 int result; 294 struct device *dev = &rc->uwb_dev.dev; 295 296 result = uwb_radio_setup(rc); 297 if (result < 0) { 298 dev_err(dev, "cannot setup UWB radio: %d\n", result); 299 goto error; 300 } 301 result = uwb_rc_mac_addr_setup(rc); 302 if (result < 0) { 303 dev_err(dev, "cannot setup UWB MAC address: %d\n", result); 304 goto error; 305 } 306 result = uwb_rc_dev_addr_assign(rc); 307 if (result < 0) { 308 dev_err(dev, "cannot assign UWB DevAddr: %d\n", result); 309 goto error; 310 } 311 result = uwb_rc_ie_setup(rc); 312 if (result < 0) { 313 dev_err(dev, "cannot setup IE subsystem: %d\n", result); 314 goto error_ie_setup; 315 } 316 result = uwb_rsv_setup(rc); 317 if (result < 0) { 318 dev_err(dev, "cannot setup reservation subsystem: %d\n", result); 319 goto error_rsv_setup; 320 } 321 uwb_dbg_add_rc(rc); 322 return 0; 323 324error_rsv_setup: 325 uwb_rc_ie_release(rc); 326error_ie_setup: 327error: 328 return result; 329} 330 331 332/** 333 * Register a new UWB radio controller 334 * 335 * Did you call uwb_rc_init() on your rc? 336 * 337 * We assume that this is being called with a > 0 refcount on 338 * it [through ops->{get|put}_device(). We'll take our own, though. 339 * 340 * @parent_dev is our real device, the one that provides the actual UWB device 341 */ 342int uwb_rc_add(struct uwb_rc *rc, struct device *parent_dev, void *priv) 343{ 344 int result; 345 struct device *dev; 346 char macbuf[UWB_ADDR_STRSIZE], devbuf[UWB_ADDR_STRSIZE]; 347 348 rc->index = uwb_rc_new_index(); 349 350 dev = &rc->uwb_dev.dev; 351 dev_set_name(dev, "uwb%d", rc->index); 352 353 rc->priv = priv; 354 355 init_waitqueue_head(&rc->uwbd.wq); 356 INIT_LIST_HEAD(&rc->uwbd.event_list); 357 spin_lock_init(&rc->uwbd.event_list_lock); 358 359 uwbd_start(rc); 360 361 result = rc->start(rc); 362 if (result < 0) 363 goto error_rc_start; 364 365 result = uwb_rc_setup(rc); 366 if (result < 0) { 367 dev_err(dev, "cannot setup UWB radio controller: %d\n", result); 368 goto error_rc_setup; 369 } 370 371 result = uwb_dev_add(&rc->uwb_dev, parent_dev, rc); 372 if (result < 0 && result != -EADDRNOTAVAIL) 373 goto error_dev_add; 374 375 result = uwb_rc_sys_add(rc); 376 if (result < 0) { 377 dev_err(parent_dev, "cannot register UWB radio controller " 378 "dev attributes: %d\n", result); 379 goto error_sys_add; 380 } 381 382 uwb_mac_addr_print(macbuf, sizeof(macbuf), &rc->uwb_dev.mac_addr); 383 uwb_dev_addr_print(devbuf, sizeof(devbuf), &rc->uwb_dev.dev_addr); 384 dev_info(dev, 385 "new uwb radio controller (mac %s dev %s) on %s %s\n", 386 macbuf, devbuf, parent_dev->bus->name, dev_name(parent_dev)); 387 rc->ready = 1; 388 return 0; 389 390error_sys_add: 391 uwb_dev_rm(&rc->uwb_dev); 392error_dev_add: 393error_rc_setup: 394 rc->stop(rc); 395error_rc_start: 396 uwbd_stop(rc); 397 return result; 398} 399EXPORT_SYMBOL_GPL(uwb_rc_add); 400 401 402static int uwb_dev_offair_helper(struct device *dev, void *priv) 403{ 404 struct uwb_dev *uwb_dev = to_uwb_dev(dev); 405 406 return __uwb_dev_offair(uwb_dev, uwb_dev->rc); 407} 408 409/* 410 * Remove a Radio Controller; stop beaconing/scanning, disconnect all children 411 */ 412void uwb_rc_rm(struct uwb_rc *rc) 413{ 414 rc->ready = 0; 415 416 uwb_dbg_del_rc(rc); 417 uwb_rsv_remove_all(rc); 418 uwb_radio_shutdown(rc); 419 420 rc->stop(rc); 421 422 uwbd_stop(rc); 423 uwb_rc_neh_destroy(rc); 424 425 uwb_dev_lock(&rc->uwb_dev); 426 rc->priv = NULL; 427 rc->cmd = NULL; 428 uwb_dev_unlock(&rc->uwb_dev); 429 mutex_lock(&rc->uwb_beca.mutex); 430 uwb_dev_for_each(rc, uwb_dev_offair_helper, NULL); 431 __uwb_rc_sys_rm(rc); 432 mutex_unlock(&rc->uwb_beca.mutex); 433 uwb_rsv_cleanup(rc); 434 uwb_beca_release(rc); 435 uwb_dev_rm(&rc->uwb_dev); 436} 437EXPORT_SYMBOL_GPL(uwb_rc_rm); 438 439static int find_rc_try_get(struct device *dev, const void *data) 440{ 441 const struct uwb_rc *target_rc = data; 442 struct uwb_rc *rc = dev_get_drvdata(dev); 443 444 if (rc == NULL) { 445 WARN_ON(1); 446 return 0; 447 } 448 if (rc == target_rc) { 449 if (rc->ready == 0) 450 return 0; 451 else 452 return 1; 453 } 454 return 0; 455} 456 457/** 458 * Given a radio controller descriptor, validate and refcount it 459 * 460 * @returns NULL if the rc does not exist or is quiescing; the ptr to 461 * it otherwise. 462 */ 463struct uwb_rc *__uwb_rc_try_get(struct uwb_rc *target_rc) 464{ 465 struct device *dev; 466 struct uwb_rc *rc = NULL; 467 468 dev = class_find_device(&uwb_rc_class, NULL, target_rc, 469 find_rc_try_get); 470 if (dev) { 471 rc = dev_get_drvdata(dev); 472 __uwb_rc_get(rc); 473 put_device(dev); 474 } 475 476 return rc; 477} 478EXPORT_SYMBOL_GPL(__uwb_rc_try_get); 479 480/* 481 * RC get for external refcount acquirers... 482 * 483 * Increments the refcount of the device and it's backend modules 484 */ 485static inline struct uwb_rc *uwb_rc_get(struct uwb_rc *rc) 486{ 487 if (rc->ready == 0) 488 return NULL; 489 uwb_dev_get(&rc->uwb_dev); 490 return rc; 491} 492 493static int find_rc_grandpa(struct device *dev, const void *data) 494{ 495 const struct device *grandpa_dev = data; 496 struct uwb_rc *rc = dev_get_drvdata(dev); 497 498 if (rc->uwb_dev.dev.parent->parent == grandpa_dev) { 499 rc = uwb_rc_get(rc); 500 return 1; 501 } 502 return 0; 503} 504 505/** 506 * Locate and refcount a radio controller given a common grand-parent 507 * 508 * @grandpa_dev Pointer to the 'grandparent' device structure. 509 * @returns NULL If the rc does not exist or is quiescing; the ptr to 510 * it otherwise, properly referenced. 511 * 512 * The Radio Control interface (or the UWB Radio Controller) is always 513 * an interface of a device. The parent is the interface, the 514 * grandparent is the device that encapsulates the interface. 515 * 516 * There is no need to lock around as the "grandpa" would be 517 * refcounted by the target, and to remove the referemes, the 518 * uwb_rc_class->sem would have to be taken--we hold it, ergo we 519 * should be safe. 520 */ 521struct uwb_rc *uwb_rc_get_by_grandpa(const struct device *grandpa_dev) 522{ 523 struct device *dev; 524 struct uwb_rc *rc = NULL; 525 526 dev = class_find_device(&uwb_rc_class, NULL, grandpa_dev, 527 find_rc_grandpa); 528 if (dev) { 529 rc = dev_get_drvdata(dev); 530 put_device(dev); 531 } 532 533 return rc; 534} 535EXPORT_SYMBOL_GPL(uwb_rc_get_by_grandpa); 536 537/** 538 * Find a radio controller by device address 539 * 540 * @returns the pointer to the radio controller, properly referenced 541 */ 542static int find_rc_dev(struct device *dev, const void *data) 543{ 544 const struct uwb_dev_addr *addr = data; 545 struct uwb_rc *rc = dev_get_drvdata(dev); 546 547 if (rc == NULL) { 548 WARN_ON(1); 549 return 0; 550 } 551 if (!uwb_dev_addr_cmp(&rc->uwb_dev.dev_addr, addr)) { 552 rc = uwb_rc_get(rc); 553 return 1; 554 } 555 return 0; 556} 557 558struct uwb_rc *uwb_rc_get_by_dev(const struct uwb_dev_addr *addr) 559{ 560 struct device *dev; 561 struct uwb_rc *rc = NULL; 562 563 dev = class_find_device(&uwb_rc_class, NULL, addr, find_rc_dev); 564 if (dev) { 565 rc = dev_get_drvdata(dev); 566 put_device(dev); 567 } 568 569 return rc; 570} 571EXPORT_SYMBOL_GPL(uwb_rc_get_by_dev); 572 573/** 574 * Drop a reference on a radio controller 575 * 576 * This is the version that should be done by entities external to the 577 * UWB Radio Control stack (ie: clients of the API). 578 */ 579void uwb_rc_put(struct uwb_rc *rc) 580{ 581 __uwb_rc_put(rc); 582} 583EXPORT_SYMBOL_GPL(uwb_rc_put);