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