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