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 return -EEXIST; 88 ref_exists = true; 89 break; 90 } 91 92 if (!ref_exists) { 93 ref = kzalloc(sizeof(*ref), GFP_KERNEL); 94 if (!ref) 95 return -ENOMEM; 96 ref->pin = pin; 97 INIT_LIST_HEAD(&ref->registration_list); 98 ret = xa_insert(xa_pins, pin->pin_idx, ref, GFP_KERNEL); 99 if (ret) { 100 kfree(ref); 101 return ret; 102 } 103 refcount_set(&ref->refcount, 1); 104 } 105 106 reg = kzalloc(sizeof(*reg), GFP_KERNEL); 107 if (!reg) { 108 if (!ref_exists) { 109 xa_erase(xa_pins, pin->pin_idx); 110 kfree(ref); 111 } 112 return -ENOMEM; 113 } 114 reg->ops = ops; 115 reg->priv = priv; 116 reg->cookie = cookie; 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 void *cookie) 127 { 128 struct dpll_pin_registration *reg; 129 struct dpll_pin_ref *ref; 130 unsigned long i; 131 132 xa_for_each(xa_pins, i, ref) { 133 if (ref->pin != pin) 134 continue; 135 reg = dpll_pin_registration_find(ref, ops, priv, cookie); 136 if (WARN_ON(!reg)) 137 return -EINVAL; 138 list_del(®->list); 139 kfree(reg); 140 if (refcount_dec_and_test(&ref->refcount)) { 141 xa_erase(xa_pins, i); 142 WARN_ON(!list_empty(&ref->registration_list)); 143 kfree(ref); 144 } 145 return 0; 146 } 147 148 return -EINVAL; 149 } 150 151 static int 152 dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll, 153 const struct dpll_pin_ops *ops, void *priv, void *cookie) 154 { 155 struct dpll_pin_registration *reg; 156 struct dpll_pin_ref *ref; 157 bool ref_exists = false; 158 unsigned long i; 159 int ret; 160 161 xa_for_each(xa_dplls, i, ref) { 162 if (ref->dpll != dpll) 163 continue; 164 reg = dpll_pin_registration_find(ref, ops, priv, cookie); 165 if (reg) 166 return -EEXIST; 167 ref_exists = true; 168 break; 169 } 170 171 if (!ref_exists) { 172 ref = kzalloc(sizeof(*ref), GFP_KERNEL); 173 if (!ref) 174 return -ENOMEM; 175 ref->dpll = dpll; 176 INIT_LIST_HEAD(&ref->registration_list); 177 ret = xa_insert(xa_dplls, dpll->id, ref, GFP_KERNEL); 178 if (ret) { 179 kfree(ref); 180 return ret; 181 } 182 refcount_set(&ref->refcount, 1); 183 } 184 185 reg = kzalloc(sizeof(*reg), GFP_KERNEL); 186 if (!reg) { 187 if (!ref_exists) { 188 xa_erase(xa_dplls, dpll->id); 189 kfree(ref); 190 } 191 return -ENOMEM; 192 } 193 reg->ops = ops; 194 reg->priv = priv; 195 reg->cookie = cookie; 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, void *cookie) 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, cookie); 215 if (WARN_ON(!reg)) 216 return; 217 list_del(®->list); 218 kfree(reg); 219 if (refcount_dec_and_test(&ref->refcount)) { 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 if (WARN_ON(src->freq_supported && !src->freq_supported_num)) 443 return -EINVAL; 444 445 memcpy(dst, src, sizeof(*dst)); 446 if (src->freq_supported) { 447 size_t freq_size = src->freq_supported_num * 448 sizeof(*src->freq_supported); 449 dst->freq_supported = kmemdup(src->freq_supported, 450 freq_size, GFP_KERNEL); 451 if (!dst->freq_supported) 452 return -ENOMEM; 453 } 454 if (src->board_label) { 455 dst->board_label = kstrdup(src->board_label, GFP_KERNEL); 456 if (!dst->board_label) 457 goto err_board_label; 458 } 459 if (src->panel_label) { 460 dst->panel_label = kstrdup(src->panel_label, GFP_KERNEL); 461 if (!dst->panel_label) 462 goto err_panel_label; 463 } 464 if (src->package_label) { 465 dst->package_label = kstrdup(src->package_label, GFP_KERNEL); 466 if (!dst->package_label) 467 goto err_package_label; 468 } 469 470 return 0; 471 472 err_package_label: 473 kfree(dst->panel_label); 474 err_panel_label: 475 kfree(dst->board_label); 476 err_board_label: 477 kfree(dst->freq_supported); 478 return -ENOMEM; 479 } 480 481 static struct dpll_pin * 482 dpll_pin_alloc(u64 clock_id, u32 pin_idx, struct module *module, 483 const struct dpll_pin_properties *prop) 484 { 485 struct dpll_pin *pin; 486 int ret; 487 488 pin = kzalloc(sizeof(*pin), GFP_KERNEL); 489 if (!pin) 490 return ERR_PTR(-ENOMEM); 491 pin->pin_idx = pin_idx; 492 pin->clock_id = clock_id; 493 pin->module = module; 494 if (WARN_ON(prop->type < DPLL_PIN_TYPE_MUX || 495 prop->type > DPLL_PIN_TYPE_MAX)) { 496 ret = -EINVAL; 497 goto err_pin_prop; 498 } 499 ret = dpll_pin_prop_dup(prop, &pin->prop); 500 if (ret) 501 goto err_pin_prop; 502 refcount_set(&pin->refcount, 1); 503 xa_init_flags(&pin->dpll_refs, XA_FLAGS_ALLOC); 504 xa_init_flags(&pin->parent_refs, XA_FLAGS_ALLOC); 505 xa_init_flags(&pin->ref_sync_pins, 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 < 0) 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 xa_destroy(&pin->ref_sync_pins); 515 dpll_pin_prop_free(&pin->prop); 516 err_pin_prop: 517 kfree(pin); 518 return ERR_PTR(ret); 519 } 520 521 static void dpll_netdev_pin_assign(struct net_device *dev, struct dpll_pin *dpll_pin) 522 { 523 rtnl_lock(); 524 rcu_assign_pointer(dev->dpll_pin, dpll_pin); 525 rtnl_unlock(); 526 } 527 528 void dpll_netdev_pin_set(struct net_device *dev, struct dpll_pin *dpll_pin) 529 { 530 WARN_ON(!dpll_pin); 531 dpll_netdev_pin_assign(dev, dpll_pin); 532 } 533 EXPORT_SYMBOL(dpll_netdev_pin_set); 534 535 void dpll_netdev_pin_clear(struct net_device *dev) 536 { 537 dpll_netdev_pin_assign(dev, NULL); 538 } 539 EXPORT_SYMBOL(dpll_netdev_pin_clear); 540 541 /** 542 * dpll_pin_get - find existing or create new dpll pin 543 * @clock_id: clock_id of creator 544 * @pin_idx: idx given by dev driver 545 * @module: reference to registering module 546 * @prop: dpll pin properties 547 * 548 * Get existing object of a pin (unique for given arguments) or create new 549 * if doesn't exist yet. 550 * 551 * Context: Acquires a lock (dpll_lock) 552 * Return: 553 * * valid allocated dpll_pin struct pointer if succeeded 554 * * ERR_PTR(X) - error 555 */ 556 struct dpll_pin * 557 dpll_pin_get(u64 clock_id, u32 pin_idx, struct module *module, 558 const struct dpll_pin_properties *prop) 559 { 560 struct dpll_pin *pos, *ret = NULL; 561 unsigned long i; 562 563 mutex_lock(&dpll_lock); 564 xa_for_each(&dpll_pin_xa, i, pos) { 565 if (pos->clock_id == clock_id && 566 pos->pin_idx == pin_idx && 567 pos->module == module) { 568 ret = pos; 569 refcount_inc(&ret->refcount); 570 break; 571 } 572 } 573 if (!ret) 574 ret = dpll_pin_alloc(clock_id, pin_idx, module, prop); 575 mutex_unlock(&dpll_lock); 576 577 return ret; 578 } 579 EXPORT_SYMBOL_GPL(dpll_pin_get); 580 581 /** 582 * dpll_pin_put - decrease the refcount and free memory if possible 583 * @pin: pointer to a pin to be put 584 * 585 * Drop reference for a pin, if all references are gone, delete pin object. 586 * 587 * Context: Acquires a lock (dpll_lock) 588 */ 589 void dpll_pin_put(struct dpll_pin *pin) 590 { 591 mutex_lock(&dpll_lock); 592 if (refcount_dec_and_test(&pin->refcount)) { 593 xa_erase(&dpll_pin_xa, pin->id); 594 xa_destroy(&pin->dpll_refs); 595 xa_destroy(&pin->parent_refs); 596 xa_destroy(&pin->ref_sync_pins); 597 dpll_pin_prop_free(&pin->prop); 598 kfree_rcu(pin, rcu); 599 } 600 mutex_unlock(&dpll_lock); 601 } 602 EXPORT_SYMBOL_GPL(dpll_pin_put); 603 604 static int 605 __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, 606 const struct dpll_pin_ops *ops, void *priv, void *cookie) 607 { 608 int ret; 609 610 ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv, cookie); 611 if (ret) 612 return ret; 613 ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv, cookie); 614 if (ret) 615 goto ref_pin_del; 616 xa_set_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED); 617 dpll_pin_create_ntf(pin); 618 619 return ret; 620 621 ref_pin_del: 622 dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie); 623 return ret; 624 } 625 626 /** 627 * dpll_pin_register - register the dpll pin in the subsystem 628 * @dpll: pointer to a dpll 629 * @pin: pointer to a dpll pin 630 * @ops: ops for a dpll pin ops 631 * @priv: pointer to private information of owner 632 * 633 * Context: Acquires a lock (dpll_lock) 634 * Return: 635 * * 0 on success 636 * * negative - error value 637 */ 638 int 639 dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, 640 const struct dpll_pin_ops *ops, void *priv) 641 { 642 int ret; 643 644 if (WARN_ON(!ops) || 645 WARN_ON(!ops->state_on_dpll_get) || 646 WARN_ON(!ops->direction_get)) 647 return -EINVAL; 648 649 mutex_lock(&dpll_lock); 650 if (WARN_ON(!(dpll->module == pin->module && 651 dpll->clock_id == pin->clock_id))) 652 ret = -EINVAL; 653 else 654 ret = __dpll_pin_register(dpll, pin, ops, priv, NULL); 655 mutex_unlock(&dpll_lock); 656 657 return ret; 658 } 659 EXPORT_SYMBOL_GPL(dpll_pin_register); 660 661 static void dpll_pin_ref_sync_pair_del(u32 ref_sync_pin_id) 662 { 663 struct dpll_pin *pin, *ref_sync_pin; 664 unsigned long i; 665 666 xa_for_each(&dpll_pin_xa, i, pin) { 667 ref_sync_pin = xa_load(&pin->ref_sync_pins, ref_sync_pin_id); 668 if (ref_sync_pin) { 669 xa_erase(&pin->ref_sync_pins, ref_sync_pin_id); 670 __dpll_pin_change_ntf(pin); 671 } 672 } 673 } 674 675 static void 676 __dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, 677 const struct dpll_pin_ops *ops, void *priv, void *cookie) 678 { 679 ASSERT_DPLL_PIN_REGISTERED(pin); 680 dpll_pin_ref_sync_pair_del(pin->id); 681 dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie); 682 dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv, cookie); 683 if (xa_empty(&pin->dpll_refs)) 684 xa_clear_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED); 685 } 686 687 /** 688 * dpll_pin_unregister - unregister dpll pin from dpll device 689 * @dpll: registered dpll pointer 690 * @pin: pointer to a pin 691 * @ops: ops for a dpll pin 692 * @priv: pointer to private information of owner 693 * 694 * Note: It does not free the memory 695 * Context: Acquires a lock (dpll_lock) 696 */ 697 void dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, 698 const struct dpll_pin_ops *ops, void *priv) 699 { 700 if (WARN_ON(xa_empty(&dpll->pin_refs))) 701 return; 702 if (WARN_ON(!xa_empty(&pin->parent_refs))) 703 return; 704 705 mutex_lock(&dpll_lock); 706 dpll_pin_delete_ntf(pin); 707 __dpll_pin_unregister(dpll, pin, ops, priv, NULL); 708 mutex_unlock(&dpll_lock); 709 } 710 EXPORT_SYMBOL_GPL(dpll_pin_unregister); 711 712 /** 713 * dpll_pin_on_pin_register - register a pin with a parent pin 714 * @parent: pointer to a parent pin 715 * @pin: pointer to a pin 716 * @ops: ops for a dpll pin 717 * @priv: pointer to private information of owner 718 * 719 * Register a pin with a parent pin, create references between them and 720 * between newly registered pin and dplls connected with a parent pin. 721 * 722 * Context: Acquires a lock (dpll_lock) 723 * Return: 724 * * 0 on success 725 * * negative - error value 726 */ 727 int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin, 728 const struct dpll_pin_ops *ops, void *priv) 729 { 730 struct dpll_pin_ref *ref; 731 unsigned long i, stop; 732 int ret; 733 734 if (WARN_ON(parent->prop.type != DPLL_PIN_TYPE_MUX)) 735 return -EINVAL; 736 737 if (WARN_ON(!ops) || 738 WARN_ON(!ops->state_on_pin_get) || 739 WARN_ON(!ops->direction_get)) 740 return -EINVAL; 741 742 mutex_lock(&dpll_lock); 743 ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv, pin); 744 if (ret) 745 goto unlock; 746 refcount_inc(&pin->refcount); 747 xa_for_each(&parent->dpll_refs, i, ref) { 748 ret = __dpll_pin_register(ref->dpll, pin, ops, priv, parent); 749 if (ret) { 750 stop = i; 751 goto dpll_unregister; 752 } 753 dpll_pin_create_ntf(pin); 754 } 755 mutex_unlock(&dpll_lock); 756 757 return ret; 758 759 dpll_unregister: 760 xa_for_each(&parent->dpll_refs, i, ref) 761 if (i < stop) { 762 __dpll_pin_unregister(ref->dpll, pin, ops, priv, 763 parent); 764 dpll_pin_delete_ntf(pin); 765 } 766 refcount_dec(&pin->refcount); 767 dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin); 768 unlock: 769 mutex_unlock(&dpll_lock); 770 return ret; 771 } 772 EXPORT_SYMBOL_GPL(dpll_pin_on_pin_register); 773 774 /** 775 * dpll_pin_on_pin_unregister - unregister dpll pin from a parent pin 776 * @parent: pointer to a parent pin 777 * @pin: pointer to a pin 778 * @ops: ops for a dpll pin 779 * @priv: pointer to private information of owner 780 * 781 * Context: Acquires a lock (dpll_lock) 782 * Note: It does not free the memory 783 */ 784 void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin, 785 const struct dpll_pin_ops *ops, void *priv) 786 { 787 struct dpll_pin_ref *ref; 788 unsigned long i; 789 790 mutex_lock(&dpll_lock); 791 dpll_pin_delete_ntf(pin); 792 dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin); 793 refcount_dec(&pin->refcount); 794 xa_for_each(&pin->dpll_refs, i, ref) 795 __dpll_pin_unregister(ref->dpll, pin, ops, priv, parent); 796 mutex_unlock(&dpll_lock); 797 } 798 EXPORT_SYMBOL_GPL(dpll_pin_on_pin_unregister); 799 800 /** 801 * dpll_pin_ref_sync_pair_add - create a reference sync signal pin pair 802 * @pin: pin which produces the base frequency 803 * @ref_sync_pin: pin which produces the sync signal 804 * 805 * Once pins are paired, the user-space configuration of reference sync pair 806 * is possible. 807 * Context: Acquires a lock (dpll_lock) 808 * Return: 809 * * 0 on success 810 * * negative - error value 811 */ 812 int dpll_pin_ref_sync_pair_add(struct dpll_pin *pin, 813 struct dpll_pin *ref_sync_pin) 814 { 815 int ret; 816 817 mutex_lock(&dpll_lock); 818 ret = xa_insert(&pin->ref_sync_pins, ref_sync_pin->id, 819 ref_sync_pin, GFP_KERNEL); 820 __dpll_pin_change_ntf(pin); 821 mutex_unlock(&dpll_lock); 822 823 return ret; 824 } 825 EXPORT_SYMBOL_GPL(dpll_pin_ref_sync_pair_add); 826 827 static struct dpll_device_registration * 828 dpll_device_registration_first(struct dpll_device *dpll) 829 { 830 struct dpll_device_registration *reg; 831 832 reg = list_first_entry_or_null((struct list_head *)&dpll->registration_list, 833 struct dpll_device_registration, list); 834 WARN_ON(!reg); 835 return reg; 836 } 837 838 void *dpll_priv(struct dpll_device *dpll) 839 { 840 struct dpll_device_registration *reg; 841 842 reg = dpll_device_registration_first(dpll); 843 return reg->priv; 844 } 845 846 const struct dpll_device_ops *dpll_device_ops(struct dpll_device *dpll) 847 { 848 struct dpll_device_registration *reg; 849 850 reg = dpll_device_registration_first(dpll); 851 return reg->ops; 852 } 853 854 static struct dpll_pin_registration * 855 dpll_pin_registration_first(struct dpll_pin_ref *ref) 856 { 857 struct dpll_pin_registration *reg; 858 859 reg = list_first_entry_or_null(&ref->registration_list, 860 struct dpll_pin_registration, list); 861 WARN_ON(!reg); 862 return reg; 863 } 864 865 void *dpll_pin_on_dpll_priv(struct dpll_device *dpll, 866 struct dpll_pin *pin) 867 { 868 struct dpll_pin_registration *reg; 869 struct dpll_pin_ref *ref; 870 871 ref = xa_load(&dpll->pin_refs, pin->pin_idx); 872 if (!ref) 873 return NULL; 874 reg = dpll_pin_registration_first(ref); 875 return reg->priv; 876 } 877 878 void *dpll_pin_on_pin_priv(struct dpll_pin *parent, 879 struct dpll_pin *pin) 880 { 881 struct dpll_pin_registration *reg; 882 struct dpll_pin_ref *ref; 883 884 ref = xa_load(&pin->parent_refs, parent->pin_idx); 885 if (!ref) 886 return NULL; 887 reg = dpll_pin_registration_first(ref); 888 return reg->priv; 889 } 890 891 const struct dpll_pin_ops *dpll_pin_ops(struct dpll_pin_ref *ref) 892 { 893 struct dpll_pin_registration *reg; 894 895 reg = dpll_pin_registration_first(ref); 896 return reg->ops; 897 } 898 899 static int __init dpll_init(void) 900 { 901 int ret; 902 903 ret = genl_register_family(&dpll_nl_family); 904 if (ret) 905 goto error; 906 907 return 0; 908 909 error: 910 mutex_destroy(&dpll_lock); 911 return ret; 912 } 913 914 static void __exit dpll_exit(void) 915 { 916 genl_unregister_family(&dpll_nl_family); 917 mutex_destroy(&dpll_lock); 918 } 919 920 subsys_initcall(dpll_init); 921 module_exit(dpll_exit); 922