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