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