1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * dpll_core.c - DPLL subsystem kernel-space interface implementation. 4 * 5 * Copyright (c) 2023 Meta Platforms, Inc. and affiliates 6 * Copyright (c) 2023 Intel Corporation. 7 */ 8 9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 10 11 #include <linux/device.h> 12 #include <linux/err.h> 13 #include <linux/slab.h> 14 #include <linux/string.h> 15 16 #include "dpll_core.h" 17 #include "dpll_netlink.h" 18 19 /* Mutex lock to protect DPLL subsystem devices and pins */ 20 DEFINE_MUTEX(dpll_lock); 21 22 DEFINE_XARRAY_FLAGS(dpll_device_xa, XA_FLAGS_ALLOC); 23 DEFINE_XARRAY_FLAGS(dpll_pin_xa, XA_FLAGS_ALLOC); 24 25 static u32 dpll_xa_id; 26 27 #define ASSERT_DPLL_REGISTERED(d) \ 28 WARN_ON_ONCE(!xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED)) 29 #define ASSERT_DPLL_NOT_REGISTERED(d) \ 30 WARN_ON_ONCE(xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED)) 31 #define ASSERT_PIN_REGISTERED(p) \ 32 WARN_ON_ONCE(!xa_get_mark(&dpll_pin_xa, (p)->id, DPLL_REGISTERED)) 33 34 struct dpll_device_registration { 35 struct list_head list; 36 const struct dpll_device_ops *ops; 37 void *priv; 38 }; 39 40 struct dpll_pin_registration { 41 struct list_head list; 42 const struct dpll_pin_ops *ops; 43 void *priv; 44 }; 45 46 struct dpll_device *dpll_device_get_by_id(int id) 47 { 48 if (xa_get_mark(&dpll_device_xa, id, DPLL_REGISTERED)) 49 return xa_load(&dpll_device_xa, id); 50 51 return NULL; 52 } 53 54 static struct dpll_pin_registration * 55 dpll_pin_registration_find(struct dpll_pin_ref *ref, 56 const struct dpll_pin_ops *ops, void *priv) 57 { 58 struct dpll_pin_registration *reg; 59 60 list_for_each_entry(reg, &ref->registration_list, list) { 61 if (reg->ops == ops && reg->priv == priv) 62 return reg; 63 } 64 return NULL; 65 } 66 67 static int 68 dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin, 69 const struct dpll_pin_ops *ops, void *priv) 70 { 71 struct dpll_pin_registration *reg; 72 struct dpll_pin_ref *ref; 73 bool ref_exists = false; 74 unsigned long i; 75 int ret; 76 77 xa_for_each(xa_pins, i, ref) { 78 if (ref->pin != pin) 79 continue; 80 reg = dpll_pin_registration_find(ref, ops, priv); 81 if (reg) { 82 refcount_inc(&ref->refcount); 83 return 0; 84 } 85 ref_exists = true; 86 break; 87 } 88 89 if (!ref_exists) { 90 ref = kzalloc(sizeof(*ref), GFP_KERNEL); 91 if (!ref) 92 return -ENOMEM; 93 ref->pin = pin; 94 INIT_LIST_HEAD(&ref->registration_list); 95 ret = xa_insert(xa_pins, pin->pin_idx, ref, GFP_KERNEL); 96 if (ret) { 97 kfree(ref); 98 return ret; 99 } 100 refcount_set(&ref->refcount, 1); 101 } 102 103 reg = kzalloc(sizeof(*reg), GFP_KERNEL); 104 if (!reg) { 105 if (!ref_exists) { 106 xa_erase(xa_pins, pin->pin_idx); 107 kfree(ref); 108 } 109 return -ENOMEM; 110 } 111 reg->ops = ops; 112 reg->priv = priv; 113 if (ref_exists) 114 refcount_inc(&ref->refcount); 115 list_add_tail(®->list, &ref->registration_list); 116 117 return 0; 118 } 119 120 static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin, 121 const struct dpll_pin_ops *ops, void *priv) 122 { 123 struct dpll_pin_registration *reg; 124 struct dpll_pin_ref *ref; 125 unsigned long i; 126 127 xa_for_each(xa_pins, i, ref) { 128 if (ref->pin != pin) 129 continue; 130 reg = dpll_pin_registration_find(ref, ops, priv); 131 if (WARN_ON(!reg)) 132 return -EINVAL; 133 if (refcount_dec_and_test(&ref->refcount)) { 134 list_del(®->list); 135 kfree(reg); 136 xa_erase(xa_pins, i); 137 WARN_ON(!list_empty(&ref->registration_list)); 138 kfree(ref); 139 } 140 return 0; 141 } 142 143 return -EINVAL; 144 } 145 146 static int 147 dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll, 148 const struct dpll_pin_ops *ops, void *priv) 149 { 150 struct dpll_pin_registration *reg; 151 struct dpll_pin_ref *ref; 152 bool ref_exists = false; 153 unsigned long i; 154 int ret; 155 156 xa_for_each(xa_dplls, i, ref) { 157 if (ref->dpll != dpll) 158 continue; 159 reg = dpll_pin_registration_find(ref, ops, priv); 160 if (reg) { 161 refcount_inc(&ref->refcount); 162 return 0; 163 } 164 ref_exists = true; 165 break; 166 } 167 168 if (!ref_exists) { 169 ref = kzalloc(sizeof(*ref), GFP_KERNEL); 170 if (!ref) 171 return -ENOMEM; 172 ref->dpll = dpll; 173 INIT_LIST_HEAD(&ref->registration_list); 174 ret = xa_insert(xa_dplls, dpll->id, ref, GFP_KERNEL); 175 if (ret) { 176 kfree(ref); 177 return ret; 178 } 179 refcount_set(&ref->refcount, 1); 180 } 181 182 reg = kzalloc(sizeof(*reg), GFP_KERNEL); 183 if (!reg) { 184 if (!ref_exists) { 185 xa_erase(xa_dplls, dpll->id); 186 kfree(ref); 187 } 188 return -ENOMEM; 189 } 190 reg->ops = ops; 191 reg->priv = priv; 192 if (ref_exists) 193 refcount_inc(&ref->refcount); 194 list_add_tail(®->list, &ref->registration_list); 195 196 return 0; 197 } 198 199 static void 200 dpll_xa_ref_dpll_del(struct xarray *xa_dplls, struct dpll_device *dpll, 201 const struct dpll_pin_ops *ops, void *priv) 202 { 203 struct dpll_pin_registration *reg; 204 struct dpll_pin_ref *ref; 205 unsigned long i; 206 207 xa_for_each(xa_dplls, i, ref) { 208 if (ref->dpll != dpll) 209 continue; 210 reg = dpll_pin_registration_find(ref, ops, priv); 211 if (WARN_ON(!reg)) 212 return; 213 if (refcount_dec_and_test(&ref->refcount)) { 214 list_del(®->list); 215 kfree(reg); 216 xa_erase(xa_dplls, i); 217 WARN_ON(!list_empty(&ref->registration_list)); 218 kfree(ref); 219 } 220 return; 221 } 222 } 223 224 struct dpll_pin_ref *dpll_xa_ref_dpll_first(struct xarray *xa_refs) 225 { 226 struct dpll_pin_ref *ref; 227 unsigned long i = 0; 228 229 ref = xa_find(xa_refs, &i, ULONG_MAX, XA_PRESENT); 230 WARN_ON(!ref); 231 return ref; 232 } 233 234 static struct dpll_device * 235 dpll_device_alloc(const u64 clock_id, u32 device_idx, struct module *module) 236 { 237 struct dpll_device *dpll; 238 int ret; 239 240 dpll = kzalloc(sizeof(*dpll), GFP_KERNEL); 241 if (!dpll) 242 return ERR_PTR(-ENOMEM); 243 refcount_set(&dpll->refcount, 1); 244 INIT_LIST_HEAD(&dpll->registration_list); 245 dpll->device_idx = device_idx; 246 dpll->clock_id = clock_id; 247 dpll->module = module; 248 ret = xa_alloc_cyclic(&dpll_device_xa, &dpll->id, dpll, xa_limit_32b, 249 &dpll_xa_id, GFP_KERNEL); 250 if (ret < 0) { 251 kfree(dpll); 252 return ERR_PTR(ret); 253 } 254 xa_init_flags(&dpll->pin_refs, XA_FLAGS_ALLOC); 255 256 return dpll; 257 } 258 259 /** 260 * dpll_device_get - find existing or create new dpll device 261 * @clock_id: clock_id of creator 262 * @device_idx: idx given by device driver 263 * @module: reference to registering module 264 * 265 * Get existing object of a dpll device, unique for given arguments. 266 * Create new if doesn't exist yet. 267 * 268 * Context: Acquires a lock (dpll_lock) 269 * Return: 270 * * valid dpll_device struct pointer if succeeded 271 * * ERR_PTR(X) - error 272 */ 273 struct dpll_device * 274 dpll_device_get(u64 clock_id, u32 device_idx, struct module *module) 275 { 276 struct dpll_device *dpll, *ret = NULL; 277 unsigned long index; 278 279 mutex_lock(&dpll_lock); 280 xa_for_each(&dpll_device_xa, index, dpll) { 281 if (dpll->clock_id == clock_id && 282 dpll->device_idx == device_idx && 283 dpll->module == module) { 284 ret = dpll; 285 refcount_inc(&ret->refcount); 286 break; 287 } 288 } 289 if (!ret) 290 ret = dpll_device_alloc(clock_id, device_idx, module); 291 mutex_unlock(&dpll_lock); 292 293 return ret; 294 } 295 EXPORT_SYMBOL_GPL(dpll_device_get); 296 297 /** 298 * dpll_device_put - decrease the refcount and free memory if possible 299 * @dpll: dpll_device struct pointer 300 * 301 * Context: Acquires a lock (dpll_lock) 302 * Drop reference for a dpll device, if all references are gone, delete 303 * dpll device object. 304 */ 305 void dpll_device_put(struct dpll_device *dpll) 306 { 307 mutex_lock(&dpll_lock); 308 if (refcount_dec_and_test(&dpll->refcount)) { 309 ASSERT_DPLL_NOT_REGISTERED(dpll); 310 WARN_ON_ONCE(!xa_empty(&dpll->pin_refs)); 311 xa_destroy(&dpll->pin_refs); 312 xa_erase(&dpll_device_xa, dpll->id); 313 WARN_ON(!list_empty(&dpll->registration_list)); 314 kfree(dpll); 315 } 316 mutex_unlock(&dpll_lock); 317 } 318 EXPORT_SYMBOL_GPL(dpll_device_put); 319 320 static struct dpll_device_registration * 321 dpll_device_registration_find(struct dpll_device *dpll, 322 const struct dpll_device_ops *ops, void *priv) 323 { 324 struct dpll_device_registration *reg; 325 326 list_for_each_entry(reg, &dpll->registration_list, list) { 327 if (reg->ops == ops && reg->priv == priv) 328 return reg; 329 } 330 return NULL; 331 } 332 333 /** 334 * dpll_device_register - register the dpll device in the subsystem 335 * @dpll: pointer to a dpll 336 * @type: type of a dpll 337 * @ops: ops for a dpll device 338 * @priv: pointer to private information of owner 339 * 340 * Make dpll device available for user space. 341 * 342 * Context: Acquires a lock (dpll_lock) 343 * Return: 344 * * 0 on success 345 * * negative - error value 346 */ 347 int dpll_device_register(struct dpll_device *dpll, enum dpll_type type, 348 const struct dpll_device_ops *ops, void *priv) 349 { 350 struct dpll_device_registration *reg; 351 bool first_registration = false; 352 353 if (WARN_ON(!ops)) 354 return -EINVAL; 355 if (WARN_ON(!ops->mode_get)) 356 return -EINVAL; 357 if (WARN_ON(!ops->lock_status_get)) 358 return -EINVAL; 359 if (WARN_ON(type < DPLL_TYPE_PPS || type > DPLL_TYPE_MAX)) 360 return -EINVAL; 361 362 mutex_lock(&dpll_lock); 363 reg = dpll_device_registration_find(dpll, ops, priv); 364 if (reg) { 365 mutex_unlock(&dpll_lock); 366 return -EEXIST; 367 } 368 369 reg = kzalloc(sizeof(*reg), GFP_KERNEL); 370 if (!reg) { 371 mutex_unlock(&dpll_lock); 372 return -ENOMEM; 373 } 374 reg->ops = ops; 375 reg->priv = priv; 376 dpll->type = type; 377 first_registration = list_empty(&dpll->registration_list); 378 list_add_tail(®->list, &dpll->registration_list); 379 if (!first_registration) { 380 mutex_unlock(&dpll_lock); 381 return 0; 382 } 383 384 xa_set_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED); 385 dpll_device_create_ntf(dpll); 386 mutex_unlock(&dpll_lock); 387 388 return 0; 389 } 390 EXPORT_SYMBOL_GPL(dpll_device_register); 391 392 /** 393 * dpll_device_unregister - unregister dpll device 394 * @dpll: registered dpll pointer 395 * @ops: ops for a dpll device 396 * @priv: pointer to private information of owner 397 * 398 * Unregister device, make it unavailable for userspace. 399 * Note: It does not free the memory 400 * Context: Acquires a lock (dpll_lock) 401 */ 402 void dpll_device_unregister(struct dpll_device *dpll, 403 const struct dpll_device_ops *ops, void *priv) 404 { 405 struct dpll_device_registration *reg; 406 407 mutex_lock(&dpll_lock); 408 ASSERT_DPLL_REGISTERED(dpll); 409 dpll_device_delete_ntf(dpll); 410 reg = dpll_device_registration_find(dpll, ops, priv); 411 if (WARN_ON(!reg)) { 412 mutex_unlock(&dpll_lock); 413 return; 414 } 415 list_del(®->list); 416 kfree(reg); 417 418 if (!list_empty(&dpll->registration_list)) { 419 mutex_unlock(&dpll_lock); 420 return; 421 } 422 xa_clear_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED); 423 mutex_unlock(&dpll_lock); 424 } 425 EXPORT_SYMBOL_GPL(dpll_device_unregister); 426 427 static struct dpll_pin * 428 dpll_pin_alloc(u64 clock_id, u32 pin_idx, struct module *module, 429 const struct dpll_pin_properties *prop) 430 { 431 struct dpll_pin *pin; 432 int ret; 433 434 pin = kzalloc(sizeof(*pin), GFP_KERNEL); 435 if (!pin) 436 return ERR_PTR(-ENOMEM); 437 pin->pin_idx = pin_idx; 438 pin->clock_id = clock_id; 439 pin->module = module; 440 if (WARN_ON(prop->type < DPLL_PIN_TYPE_MUX || 441 prop->type > DPLL_PIN_TYPE_MAX)) { 442 ret = -EINVAL; 443 goto err; 444 } 445 pin->prop = prop; 446 refcount_set(&pin->refcount, 1); 447 xa_init_flags(&pin->dpll_refs, XA_FLAGS_ALLOC); 448 xa_init_flags(&pin->parent_refs, XA_FLAGS_ALLOC); 449 ret = xa_alloc(&dpll_pin_xa, &pin->id, pin, xa_limit_16b, GFP_KERNEL); 450 if (ret) 451 goto err; 452 return pin; 453 err: 454 xa_destroy(&pin->dpll_refs); 455 xa_destroy(&pin->parent_refs); 456 kfree(pin); 457 return ERR_PTR(ret); 458 } 459 460 /** 461 * dpll_pin_get - find existing or create new dpll pin 462 * @clock_id: clock_id of creator 463 * @pin_idx: idx given by dev driver 464 * @module: reference to registering module 465 * @prop: dpll pin properties 466 * 467 * Get existing object of a pin (unique for given arguments) or create new 468 * if doesn't exist yet. 469 * 470 * Context: Acquires a lock (dpll_lock) 471 * Return: 472 * * valid allocated dpll_pin struct pointer if succeeded 473 * * ERR_PTR(X) - error 474 */ 475 struct dpll_pin * 476 dpll_pin_get(u64 clock_id, u32 pin_idx, struct module *module, 477 const struct dpll_pin_properties *prop) 478 { 479 struct dpll_pin *pos, *ret = NULL; 480 unsigned long i; 481 482 mutex_lock(&dpll_lock); 483 xa_for_each(&dpll_pin_xa, i, pos) { 484 if (pos->clock_id == clock_id && 485 pos->pin_idx == pin_idx && 486 pos->module == module) { 487 ret = pos; 488 refcount_inc(&ret->refcount); 489 break; 490 } 491 } 492 if (!ret) 493 ret = dpll_pin_alloc(clock_id, pin_idx, module, prop); 494 mutex_unlock(&dpll_lock); 495 496 return ret; 497 } 498 EXPORT_SYMBOL_GPL(dpll_pin_get); 499 500 /** 501 * dpll_pin_put - decrease the refcount and free memory if possible 502 * @pin: pointer to a pin to be put 503 * 504 * Drop reference for a pin, if all references are gone, delete pin object. 505 * 506 * Context: Acquires a lock (dpll_lock) 507 */ 508 void dpll_pin_put(struct dpll_pin *pin) 509 { 510 mutex_lock(&dpll_lock); 511 if (refcount_dec_and_test(&pin->refcount)) { 512 xa_destroy(&pin->dpll_refs); 513 xa_destroy(&pin->parent_refs); 514 xa_erase(&dpll_pin_xa, pin->id); 515 kfree(pin); 516 } 517 mutex_unlock(&dpll_lock); 518 } 519 EXPORT_SYMBOL_GPL(dpll_pin_put); 520 521 static int 522 __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, 523 const struct dpll_pin_ops *ops, void *priv) 524 { 525 int ret; 526 527 ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv); 528 if (ret) 529 return ret; 530 ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv); 531 if (ret) 532 goto ref_pin_del; 533 xa_set_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED); 534 dpll_pin_create_ntf(pin); 535 536 return ret; 537 538 ref_pin_del: 539 dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv); 540 return ret; 541 } 542 543 /** 544 * dpll_pin_register - register the dpll pin in the subsystem 545 * @dpll: pointer to a dpll 546 * @pin: pointer to a dpll pin 547 * @ops: ops for a dpll pin ops 548 * @priv: pointer to private information of owner 549 * 550 * Context: Acquires a lock (dpll_lock) 551 * Return: 552 * * 0 on success 553 * * negative - error value 554 */ 555 int 556 dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, 557 const struct dpll_pin_ops *ops, void *priv) 558 { 559 int ret; 560 561 if (WARN_ON(!ops) || 562 WARN_ON(!ops->state_on_dpll_get) || 563 WARN_ON(!ops->direction_get)) 564 return -EINVAL; 565 if (ASSERT_DPLL_REGISTERED(dpll)) 566 return -EINVAL; 567 568 mutex_lock(&dpll_lock); 569 if (WARN_ON(!(dpll->module == pin->module && 570 dpll->clock_id == pin->clock_id))) 571 ret = -EINVAL; 572 else 573 ret = __dpll_pin_register(dpll, pin, ops, priv); 574 mutex_unlock(&dpll_lock); 575 576 return ret; 577 } 578 EXPORT_SYMBOL_GPL(dpll_pin_register); 579 580 static void 581 __dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, 582 const struct dpll_pin_ops *ops, void *priv) 583 { 584 dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv); 585 dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv); 586 if (xa_empty(&pin->dpll_refs)) 587 xa_clear_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED); 588 } 589 590 /** 591 * dpll_pin_unregister - unregister dpll pin from dpll device 592 * @dpll: registered dpll pointer 593 * @pin: pointer to a pin 594 * @ops: ops for a dpll pin 595 * @priv: pointer to private information of owner 596 * 597 * Note: It does not free the memory 598 * Context: Acquires a lock (dpll_lock) 599 */ 600 void dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, 601 const struct dpll_pin_ops *ops, void *priv) 602 { 603 if (WARN_ON(xa_empty(&dpll->pin_refs))) 604 return; 605 if (WARN_ON(!xa_empty(&pin->parent_refs))) 606 return; 607 608 mutex_lock(&dpll_lock); 609 dpll_pin_delete_ntf(pin); 610 __dpll_pin_unregister(dpll, pin, ops, priv); 611 mutex_unlock(&dpll_lock); 612 } 613 EXPORT_SYMBOL_GPL(dpll_pin_unregister); 614 615 /** 616 * dpll_pin_on_pin_register - register a pin with a parent pin 617 * @parent: pointer to a parent pin 618 * @pin: pointer to a pin 619 * @ops: ops for a dpll pin 620 * @priv: pointer to private information of owner 621 * 622 * Register a pin with a parent pin, create references between them and 623 * between newly registered pin and dplls connected with a parent pin. 624 * 625 * Context: Acquires a lock (dpll_lock) 626 * Return: 627 * * 0 on success 628 * * negative - error value 629 */ 630 int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin, 631 const struct dpll_pin_ops *ops, void *priv) 632 { 633 struct dpll_pin_ref *ref; 634 unsigned long i, stop; 635 int ret; 636 637 if (WARN_ON(parent->prop->type != DPLL_PIN_TYPE_MUX)) 638 return -EINVAL; 639 640 if (WARN_ON(!ops) || 641 WARN_ON(!ops->state_on_pin_get) || 642 WARN_ON(!ops->direction_get)) 643 return -EINVAL; 644 if (ASSERT_PIN_REGISTERED(parent)) 645 return -EINVAL; 646 647 mutex_lock(&dpll_lock); 648 ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv); 649 if (ret) 650 goto unlock; 651 refcount_inc(&pin->refcount); 652 xa_for_each(&parent->dpll_refs, i, ref) { 653 ret = __dpll_pin_register(ref->dpll, pin, ops, priv); 654 if (ret) { 655 stop = i; 656 goto dpll_unregister; 657 } 658 dpll_pin_create_ntf(pin); 659 } 660 mutex_unlock(&dpll_lock); 661 662 return ret; 663 664 dpll_unregister: 665 xa_for_each(&parent->dpll_refs, i, ref) 666 if (i < stop) { 667 __dpll_pin_unregister(ref->dpll, pin, ops, priv); 668 dpll_pin_delete_ntf(pin); 669 } 670 refcount_dec(&pin->refcount); 671 dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv); 672 unlock: 673 mutex_unlock(&dpll_lock); 674 return ret; 675 } 676 EXPORT_SYMBOL_GPL(dpll_pin_on_pin_register); 677 678 /** 679 * dpll_pin_on_pin_unregister - unregister dpll pin from a parent pin 680 * @parent: pointer to a parent pin 681 * @pin: pointer to a pin 682 * @ops: ops for a dpll pin 683 * @priv: pointer to private information of owner 684 * 685 * Context: Acquires a lock (dpll_lock) 686 * Note: It does not free the memory 687 */ 688 void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin, 689 const struct dpll_pin_ops *ops, void *priv) 690 { 691 struct dpll_pin_ref *ref; 692 unsigned long i; 693 694 mutex_lock(&dpll_lock); 695 dpll_pin_delete_ntf(pin); 696 dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv); 697 refcount_dec(&pin->refcount); 698 xa_for_each(&pin->dpll_refs, i, ref) 699 __dpll_pin_unregister(ref->dpll, pin, ops, priv); 700 mutex_unlock(&dpll_lock); 701 } 702 EXPORT_SYMBOL_GPL(dpll_pin_on_pin_unregister); 703 704 static struct dpll_device_registration * 705 dpll_device_registration_first(struct dpll_device *dpll) 706 { 707 struct dpll_device_registration *reg; 708 709 reg = list_first_entry_or_null((struct list_head *)&dpll->registration_list, 710 struct dpll_device_registration, list); 711 WARN_ON(!reg); 712 return reg; 713 } 714 715 void *dpll_priv(struct dpll_device *dpll) 716 { 717 struct dpll_device_registration *reg; 718 719 reg = dpll_device_registration_first(dpll); 720 return reg->priv; 721 } 722 723 const struct dpll_device_ops *dpll_device_ops(struct dpll_device *dpll) 724 { 725 struct dpll_device_registration *reg; 726 727 reg = dpll_device_registration_first(dpll); 728 return reg->ops; 729 } 730 731 static struct dpll_pin_registration * 732 dpll_pin_registration_first(struct dpll_pin_ref *ref) 733 { 734 struct dpll_pin_registration *reg; 735 736 reg = list_first_entry_or_null(&ref->registration_list, 737 struct dpll_pin_registration, list); 738 WARN_ON(!reg); 739 return reg; 740 } 741 742 void *dpll_pin_on_dpll_priv(struct dpll_device *dpll, 743 struct dpll_pin *pin) 744 { 745 struct dpll_pin_registration *reg; 746 struct dpll_pin_ref *ref; 747 748 ref = xa_load(&dpll->pin_refs, pin->pin_idx); 749 if (!ref) 750 return NULL; 751 reg = dpll_pin_registration_first(ref); 752 return reg->priv; 753 } 754 755 void *dpll_pin_on_pin_priv(struct dpll_pin *parent, 756 struct dpll_pin *pin) 757 { 758 struct dpll_pin_registration *reg; 759 struct dpll_pin_ref *ref; 760 761 ref = xa_load(&pin->parent_refs, parent->pin_idx); 762 if (!ref) 763 return NULL; 764 reg = dpll_pin_registration_first(ref); 765 return reg->priv; 766 } 767 768 const struct dpll_pin_ops *dpll_pin_ops(struct dpll_pin_ref *ref) 769 { 770 struct dpll_pin_registration *reg; 771 772 reg = dpll_pin_registration_first(ref); 773 return reg->ops; 774 } 775 776 static int __init dpll_init(void) 777 { 778 int ret; 779 780 ret = genl_register_family(&dpll_nl_family); 781 if (ret) 782 goto error; 783 784 return 0; 785 786 error: 787 mutex_destroy(&dpll_lock); 788 return ret; 789 } 790 791 static void __exit dpll_exit(void) 792 { 793 genl_unregister_family(&dpll_nl_family); 794 mutex_destroy(&dpll_lock); 795 } 796 797 subsys_initcall(dpll_init); 798 module_exit(dpll_exit); 799