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 memcpy(dst, src, sizeof(*dst)); 447 if (src->freq_supported && src->freq_supported_num) { 448 size_t freq_size = src->freq_supported_num * 449 sizeof(*src->freq_supported); 450 dst->freq_supported = kmemdup(src->freq_supported, 451 freq_size, GFP_KERNEL); 452 if (!src->freq_supported) 453 return -ENOMEM; 454 } 455 if (src->board_label) { 456 dst->board_label = kstrdup(src->board_label, GFP_KERNEL); 457 if (!dst->board_label) 458 goto err_board_label; 459 } 460 if (src->panel_label) { 461 dst->panel_label = kstrdup(src->panel_label, GFP_KERNEL); 462 if (!dst->panel_label) 463 goto err_panel_label; 464 } 465 if (src->package_label) { 466 dst->package_label = kstrdup(src->package_label, GFP_KERNEL); 467 if (!dst->package_label) 468 goto err_package_label; 469 } 470 471 return 0; 472 473 err_package_label: 474 kfree(dst->panel_label); 475 err_panel_label: 476 kfree(dst->board_label); 477 err_board_label: 478 kfree(dst->freq_supported); 479 return -ENOMEM; 480 } 481 482 static struct dpll_pin * 483 dpll_pin_alloc(u64 clock_id, u32 pin_idx, struct module *module, 484 const struct dpll_pin_properties *prop) 485 { 486 struct dpll_pin *pin; 487 int ret; 488 489 pin = kzalloc(sizeof(*pin), GFP_KERNEL); 490 if (!pin) 491 return ERR_PTR(-ENOMEM); 492 pin->pin_idx = pin_idx; 493 pin->clock_id = clock_id; 494 pin->module = module; 495 if (WARN_ON(prop->type < DPLL_PIN_TYPE_MUX || 496 prop->type > DPLL_PIN_TYPE_MAX)) { 497 ret = -EINVAL; 498 goto err_pin_prop; 499 } 500 ret = dpll_pin_prop_dup(prop, &pin->prop); 501 if (ret) 502 goto err_pin_prop; 503 refcount_set(&pin->refcount, 1); 504 xa_init_flags(&pin->dpll_refs, XA_FLAGS_ALLOC); 505 xa_init_flags(&pin->parent_refs, XA_FLAGS_ALLOC); 506 ret = xa_alloc_cyclic(&dpll_pin_xa, &pin->id, pin, xa_limit_32b, 507 &dpll_pin_xa_id, GFP_KERNEL); 508 if (ret) 509 goto err_xa_alloc; 510 return pin; 511 err_xa_alloc: 512 xa_destroy(&pin->dpll_refs); 513 xa_destroy(&pin->parent_refs); 514 dpll_pin_prop_free(&pin->prop); 515 err_pin_prop: 516 kfree(pin); 517 return ERR_PTR(ret); 518 } 519 520 static void dpll_netdev_pin_assign(struct net_device *dev, struct dpll_pin *dpll_pin) 521 { 522 rtnl_lock(); 523 rcu_assign_pointer(dev->dpll_pin, dpll_pin); 524 rtnl_unlock(); 525 } 526 527 void dpll_netdev_pin_set(struct net_device *dev, struct dpll_pin *dpll_pin) 528 { 529 WARN_ON(!dpll_pin); 530 dpll_netdev_pin_assign(dev, dpll_pin); 531 } 532 EXPORT_SYMBOL(dpll_netdev_pin_set); 533 534 void dpll_netdev_pin_clear(struct net_device *dev) 535 { 536 dpll_netdev_pin_assign(dev, NULL); 537 } 538 EXPORT_SYMBOL(dpll_netdev_pin_clear); 539 540 /** 541 * dpll_pin_get - find existing or create new dpll pin 542 * @clock_id: clock_id of creator 543 * @pin_idx: idx given by dev driver 544 * @module: reference to registering module 545 * @prop: dpll pin properties 546 * 547 * Get existing object of a pin (unique for given arguments) or create new 548 * if doesn't exist yet. 549 * 550 * Context: Acquires a lock (dpll_lock) 551 * Return: 552 * * valid allocated dpll_pin struct pointer if succeeded 553 * * ERR_PTR(X) - error 554 */ 555 struct dpll_pin * 556 dpll_pin_get(u64 clock_id, u32 pin_idx, struct module *module, 557 const struct dpll_pin_properties *prop) 558 { 559 struct dpll_pin *pos, *ret = NULL; 560 unsigned long i; 561 562 mutex_lock(&dpll_lock); 563 xa_for_each(&dpll_pin_xa, i, pos) { 564 if (pos->clock_id == clock_id && 565 pos->pin_idx == pin_idx && 566 pos->module == module) { 567 ret = pos; 568 refcount_inc(&ret->refcount); 569 break; 570 } 571 } 572 if (!ret) 573 ret = dpll_pin_alloc(clock_id, pin_idx, module, prop); 574 mutex_unlock(&dpll_lock); 575 576 return ret; 577 } 578 EXPORT_SYMBOL_GPL(dpll_pin_get); 579 580 /** 581 * dpll_pin_put - decrease the refcount and free memory if possible 582 * @pin: pointer to a pin to be put 583 * 584 * Drop reference for a pin, if all references are gone, delete pin object. 585 * 586 * Context: Acquires a lock (dpll_lock) 587 */ 588 void dpll_pin_put(struct dpll_pin *pin) 589 { 590 mutex_lock(&dpll_lock); 591 if (refcount_dec_and_test(&pin->refcount)) { 592 xa_erase(&dpll_pin_xa, pin->id); 593 xa_destroy(&pin->dpll_refs); 594 xa_destroy(&pin->parent_refs); 595 dpll_pin_prop_free(&pin->prop); 596 kfree_rcu(pin, rcu); 597 } 598 mutex_unlock(&dpll_lock); 599 } 600 EXPORT_SYMBOL_GPL(dpll_pin_put); 601 602 static int 603 __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, 604 const struct dpll_pin_ops *ops, void *priv, void *cookie) 605 { 606 int ret; 607 608 ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv, cookie); 609 if (ret) 610 return ret; 611 ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv, cookie); 612 if (ret) 613 goto ref_pin_del; 614 xa_set_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED); 615 dpll_pin_create_ntf(pin); 616 617 return ret; 618 619 ref_pin_del: 620 dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie); 621 return ret; 622 } 623 624 /** 625 * dpll_pin_register - register the dpll pin in the subsystem 626 * @dpll: pointer to a dpll 627 * @pin: pointer to a dpll pin 628 * @ops: ops for a dpll pin ops 629 * @priv: pointer to private information of owner 630 * 631 * Context: Acquires a lock (dpll_lock) 632 * Return: 633 * * 0 on success 634 * * negative - error value 635 */ 636 int 637 dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, 638 const struct dpll_pin_ops *ops, void *priv) 639 { 640 int ret; 641 642 if (WARN_ON(!ops) || 643 WARN_ON(!ops->state_on_dpll_get) || 644 WARN_ON(!ops->direction_get)) 645 return -EINVAL; 646 647 mutex_lock(&dpll_lock); 648 if (WARN_ON(!(dpll->module == pin->module && 649 dpll->clock_id == pin->clock_id))) 650 ret = -EINVAL; 651 else 652 ret = __dpll_pin_register(dpll, pin, ops, priv, NULL); 653 mutex_unlock(&dpll_lock); 654 655 return ret; 656 } 657 EXPORT_SYMBOL_GPL(dpll_pin_register); 658 659 static void 660 __dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, 661 const struct dpll_pin_ops *ops, void *priv, void *cookie) 662 { 663 ASSERT_DPLL_PIN_REGISTERED(pin); 664 dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie); 665 dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv, cookie); 666 if (xa_empty(&pin->dpll_refs)) 667 xa_clear_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED); 668 } 669 670 /** 671 * dpll_pin_unregister - unregister dpll pin from dpll device 672 * @dpll: registered dpll pointer 673 * @pin: pointer to a pin 674 * @ops: ops for a dpll pin 675 * @priv: pointer to private information of owner 676 * 677 * Note: It does not free the memory 678 * Context: Acquires a lock (dpll_lock) 679 */ 680 void dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, 681 const struct dpll_pin_ops *ops, void *priv) 682 { 683 if (WARN_ON(xa_empty(&dpll->pin_refs))) 684 return; 685 if (WARN_ON(!xa_empty(&pin->parent_refs))) 686 return; 687 688 mutex_lock(&dpll_lock); 689 dpll_pin_delete_ntf(pin); 690 __dpll_pin_unregister(dpll, pin, ops, priv, NULL); 691 mutex_unlock(&dpll_lock); 692 } 693 EXPORT_SYMBOL_GPL(dpll_pin_unregister); 694 695 /** 696 * dpll_pin_on_pin_register - register a pin with a parent pin 697 * @parent: pointer to a parent pin 698 * @pin: pointer to a pin 699 * @ops: ops for a dpll pin 700 * @priv: pointer to private information of owner 701 * 702 * Register a pin with a parent pin, create references between them and 703 * between newly registered pin and dplls connected with a parent pin. 704 * 705 * Context: Acquires a lock (dpll_lock) 706 * Return: 707 * * 0 on success 708 * * negative - error value 709 */ 710 int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin, 711 const struct dpll_pin_ops *ops, void *priv) 712 { 713 struct dpll_pin_ref *ref; 714 unsigned long i, stop; 715 int ret; 716 717 if (WARN_ON(parent->prop.type != DPLL_PIN_TYPE_MUX)) 718 return -EINVAL; 719 720 if (WARN_ON(!ops) || 721 WARN_ON(!ops->state_on_pin_get) || 722 WARN_ON(!ops->direction_get)) 723 return -EINVAL; 724 725 mutex_lock(&dpll_lock); 726 ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv, pin); 727 if (ret) 728 goto unlock; 729 refcount_inc(&pin->refcount); 730 xa_for_each(&parent->dpll_refs, i, ref) { 731 ret = __dpll_pin_register(ref->dpll, pin, ops, priv, parent); 732 if (ret) { 733 stop = i; 734 goto dpll_unregister; 735 } 736 dpll_pin_create_ntf(pin); 737 } 738 mutex_unlock(&dpll_lock); 739 740 return ret; 741 742 dpll_unregister: 743 xa_for_each(&parent->dpll_refs, i, ref) 744 if (i < stop) { 745 __dpll_pin_unregister(ref->dpll, pin, ops, priv, 746 parent); 747 dpll_pin_delete_ntf(pin); 748 } 749 refcount_dec(&pin->refcount); 750 dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin); 751 unlock: 752 mutex_unlock(&dpll_lock); 753 return ret; 754 } 755 EXPORT_SYMBOL_GPL(dpll_pin_on_pin_register); 756 757 /** 758 * dpll_pin_on_pin_unregister - unregister dpll pin from a parent pin 759 * @parent: pointer to a parent pin 760 * @pin: pointer to a pin 761 * @ops: ops for a dpll pin 762 * @priv: pointer to private information of owner 763 * 764 * Context: Acquires a lock (dpll_lock) 765 * Note: It does not free the memory 766 */ 767 void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin, 768 const struct dpll_pin_ops *ops, void *priv) 769 { 770 struct dpll_pin_ref *ref; 771 unsigned long i; 772 773 mutex_lock(&dpll_lock); 774 dpll_pin_delete_ntf(pin); 775 dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin); 776 refcount_dec(&pin->refcount); 777 xa_for_each(&pin->dpll_refs, i, ref) 778 __dpll_pin_unregister(ref->dpll, pin, ops, priv, parent); 779 mutex_unlock(&dpll_lock); 780 } 781 EXPORT_SYMBOL_GPL(dpll_pin_on_pin_unregister); 782 783 static struct dpll_device_registration * 784 dpll_device_registration_first(struct dpll_device *dpll) 785 { 786 struct dpll_device_registration *reg; 787 788 reg = list_first_entry_or_null((struct list_head *)&dpll->registration_list, 789 struct dpll_device_registration, list); 790 WARN_ON(!reg); 791 return reg; 792 } 793 794 void *dpll_priv(struct dpll_device *dpll) 795 { 796 struct dpll_device_registration *reg; 797 798 reg = dpll_device_registration_first(dpll); 799 return reg->priv; 800 } 801 802 const struct dpll_device_ops *dpll_device_ops(struct dpll_device *dpll) 803 { 804 struct dpll_device_registration *reg; 805 806 reg = dpll_device_registration_first(dpll); 807 return reg->ops; 808 } 809 810 static struct dpll_pin_registration * 811 dpll_pin_registration_first(struct dpll_pin_ref *ref) 812 { 813 struct dpll_pin_registration *reg; 814 815 reg = list_first_entry_or_null(&ref->registration_list, 816 struct dpll_pin_registration, list); 817 WARN_ON(!reg); 818 return reg; 819 } 820 821 void *dpll_pin_on_dpll_priv(struct dpll_device *dpll, 822 struct dpll_pin *pin) 823 { 824 struct dpll_pin_registration *reg; 825 struct dpll_pin_ref *ref; 826 827 ref = xa_load(&dpll->pin_refs, pin->pin_idx); 828 if (!ref) 829 return NULL; 830 reg = dpll_pin_registration_first(ref); 831 return reg->priv; 832 } 833 834 void *dpll_pin_on_pin_priv(struct dpll_pin *parent, 835 struct dpll_pin *pin) 836 { 837 struct dpll_pin_registration *reg; 838 struct dpll_pin_ref *ref; 839 840 ref = xa_load(&pin->parent_refs, parent->pin_idx); 841 if (!ref) 842 return NULL; 843 reg = dpll_pin_registration_first(ref); 844 return reg->priv; 845 } 846 847 const struct dpll_pin_ops *dpll_pin_ops(struct dpll_pin_ref *ref) 848 { 849 struct dpll_pin_registration *reg; 850 851 reg = dpll_pin_registration_first(ref); 852 return reg->ops; 853 } 854 855 static int __init dpll_init(void) 856 { 857 int ret; 858 859 ret = genl_register_family(&dpll_nl_family); 860 if (ret) 861 goto error; 862 863 return 0; 864 865 error: 866 mutex_destroy(&dpll_lock); 867 return ret; 868 } 869 870 static void __exit dpll_exit(void) 871 { 872 genl_unregister_family(&dpll_nl_family); 873 mutex_destroy(&dpll_lock); 874 } 875 876 subsys_initcall(dpll_init); 877 module_exit(dpll_exit); 878