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 xa_init_flags(&pin->ref_sync_pins, XA_FLAGS_ALLOC); 510 ret = xa_alloc_cyclic(&dpll_pin_xa, &pin->id, pin, xa_limit_32b, 511 &dpll_pin_xa_id, GFP_KERNEL); 512 if (ret < 0) 513 goto err_xa_alloc; 514 return pin; 515 err_xa_alloc: 516 xa_destroy(&pin->dpll_refs); 517 xa_destroy(&pin->parent_refs); 518 xa_destroy(&pin->ref_sync_pins); 519 dpll_pin_prop_free(&pin->prop); 520 err_pin_prop: 521 kfree(pin); 522 return ERR_PTR(ret); 523 } 524 525 static void dpll_netdev_pin_assign(struct net_device *dev, struct dpll_pin *dpll_pin) 526 { 527 rtnl_lock(); 528 rcu_assign_pointer(dev->dpll_pin, dpll_pin); 529 rtnl_unlock(); 530 } 531 532 void dpll_netdev_pin_set(struct net_device *dev, struct dpll_pin *dpll_pin) 533 { 534 WARN_ON(!dpll_pin); 535 dpll_netdev_pin_assign(dev, dpll_pin); 536 } 537 EXPORT_SYMBOL(dpll_netdev_pin_set); 538 539 void dpll_netdev_pin_clear(struct net_device *dev) 540 { 541 dpll_netdev_pin_assign(dev, NULL); 542 } 543 EXPORT_SYMBOL(dpll_netdev_pin_clear); 544 545 /** 546 * dpll_pin_get - find existing or create new dpll pin 547 * @clock_id: clock_id of creator 548 * @pin_idx: idx given by dev driver 549 * @module: reference to registering module 550 * @prop: dpll pin properties 551 * 552 * Get existing object of a pin (unique for given arguments) or create new 553 * if doesn't exist yet. 554 * 555 * Context: Acquires a lock (dpll_lock) 556 * Return: 557 * * valid allocated dpll_pin struct pointer if succeeded 558 * * ERR_PTR(X) - error 559 */ 560 struct dpll_pin * 561 dpll_pin_get(u64 clock_id, u32 pin_idx, struct module *module, 562 const struct dpll_pin_properties *prop) 563 { 564 struct dpll_pin *pos, *ret = NULL; 565 unsigned long i; 566 567 mutex_lock(&dpll_lock); 568 xa_for_each(&dpll_pin_xa, i, pos) { 569 if (pos->clock_id == clock_id && 570 pos->pin_idx == pin_idx && 571 pos->module == module) { 572 ret = pos; 573 refcount_inc(&ret->refcount); 574 break; 575 } 576 } 577 if (!ret) 578 ret = dpll_pin_alloc(clock_id, pin_idx, module, prop); 579 mutex_unlock(&dpll_lock); 580 581 return ret; 582 } 583 EXPORT_SYMBOL_GPL(dpll_pin_get); 584 585 /** 586 * dpll_pin_put - decrease the refcount and free memory if possible 587 * @pin: pointer to a pin to be put 588 * 589 * Drop reference for a pin, if all references are gone, delete pin object. 590 * 591 * Context: Acquires a lock (dpll_lock) 592 */ 593 void dpll_pin_put(struct dpll_pin *pin) 594 { 595 mutex_lock(&dpll_lock); 596 if (refcount_dec_and_test(&pin->refcount)) { 597 xa_erase(&dpll_pin_xa, pin->id); 598 xa_destroy(&pin->dpll_refs); 599 xa_destroy(&pin->parent_refs); 600 xa_destroy(&pin->ref_sync_pins); 601 dpll_pin_prop_free(&pin->prop); 602 kfree_rcu(pin, rcu); 603 } 604 mutex_unlock(&dpll_lock); 605 } 606 EXPORT_SYMBOL_GPL(dpll_pin_put); 607 608 static int 609 __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, 610 const struct dpll_pin_ops *ops, void *priv, void *cookie) 611 { 612 int ret; 613 614 ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv, cookie); 615 if (ret) 616 return ret; 617 ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv, cookie); 618 if (ret) 619 goto ref_pin_del; 620 xa_set_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED); 621 dpll_pin_create_ntf(pin); 622 623 return ret; 624 625 ref_pin_del: 626 dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie); 627 return ret; 628 } 629 630 /** 631 * dpll_pin_register - register the dpll pin in the subsystem 632 * @dpll: pointer to a dpll 633 * @pin: pointer to a dpll pin 634 * @ops: ops for a dpll pin ops 635 * @priv: pointer to private information of owner 636 * 637 * Context: Acquires a lock (dpll_lock) 638 * Return: 639 * * 0 on success 640 * * negative - error value 641 */ 642 int 643 dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, 644 const struct dpll_pin_ops *ops, void *priv) 645 { 646 int ret; 647 648 if (WARN_ON(!ops) || 649 WARN_ON(!ops->state_on_dpll_get) || 650 WARN_ON(!ops->direction_get)) 651 return -EINVAL; 652 653 mutex_lock(&dpll_lock); 654 if (WARN_ON(!(dpll->module == pin->module && 655 dpll->clock_id == pin->clock_id))) 656 ret = -EINVAL; 657 else 658 ret = __dpll_pin_register(dpll, pin, ops, priv, NULL); 659 mutex_unlock(&dpll_lock); 660 661 return ret; 662 } 663 EXPORT_SYMBOL_GPL(dpll_pin_register); 664 665 static void dpll_pin_ref_sync_pair_del(u32 ref_sync_pin_id) 666 { 667 struct dpll_pin *pin, *ref_sync_pin; 668 unsigned long i; 669 670 xa_for_each(&dpll_pin_xa, i, pin) { 671 ref_sync_pin = xa_load(&pin->ref_sync_pins, ref_sync_pin_id); 672 if (ref_sync_pin) { 673 xa_erase(&pin->ref_sync_pins, ref_sync_pin_id); 674 __dpll_pin_change_ntf(pin); 675 } 676 } 677 } 678 679 static void 680 __dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, 681 const struct dpll_pin_ops *ops, void *priv, void *cookie) 682 { 683 ASSERT_DPLL_PIN_REGISTERED(pin); 684 dpll_pin_ref_sync_pair_del(pin->id); 685 dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie); 686 dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv, cookie); 687 if (xa_empty(&pin->dpll_refs)) 688 xa_clear_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED); 689 } 690 691 /** 692 * dpll_pin_unregister - unregister dpll pin from dpll device 693 * @dpll: registered dpll pointer 694 * @pin: pointer to a pin 695 * @ops: ops for a dpll pin 696 * @priv: pointer to private information of owner 697 * 698 * Note: It does not free the memory 699 * Context: Acquires a lock (dpll_lock) 700 */ 701 void dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, 702 const struct dpll_pin_ops *ops, void *priv) 703 { 704 if (WARN_ON(xa_empty(&dpll->pin_refs))) 705 return; 706 if (WARN_ON(!xa_empty(&pin->parent_refs))) 707 return; 708 709 mutex_lock(&dpll_lock); 710 dpll_pin_delete_ntf(pin); 711 __dpll_pin_unregister(dpll, pin, ops, priv, NULL); 712 mutex_unlock(&dpll_lock); 713 } 714 EXPORT_SYMBOL_GPL(dpll_pin_unregister); 715 716 /** 717 * dpll_pin_on_pin_register - register a pin with a parent pin 718 * @parent: pointer to a parent pin 719 * @pin: pointer to a pin 720 * @ops: ops for a dpll pin 721 * @priv: pointer to private information of owner 722 * 723 * Register a pin with a parent pin, create references between them and 724 * between newly registered pin and dplls connected with a parent pin. 725 * 726 * Context: Acquires a lock (dpll_lock) 727 * Return: 728 * * 0 on success 729 * * negative - error value 730 */ 731 int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin, 732 const struct dpll_pin_ops *ops, void *priv) 733 { 734 struct dpll_pin_ref *ref; 735 unsigned long i, stop; 736 int ret; 737 738 if (WARN_ON(parent->prop.type != DPLL_PIN_TYPE_MUX)) 739 return -EINVAL; 740 741 if (WARN_ON(!ops) || 742 WARN_ON(!ops->state_on_pin_get) || 743 WARN_ON(!ops->direction_get)) 744 return -EINVAL; 745 746 mutex_lock(&dpll_lock); 747 ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv, pin); 748 if (ret) 749 goto unlock; 750 refcount_inc(&pin->refcount); 751 xa_for_each(&parent->dpll_refs, i, ref) { 752 ret = __dpll_pin_register(ref->dpll, pin, ops, priv, parent); 753 if (ret) { 754 stop = i; 755 goto dpll_unregister; 756 } 757 dpll_pin_create_ntf(pin); 758 } 759 mutex_unlock(&dpll_lock); 760 761 return ret; 762 763 dpll_unregister: 764 xa_for_each(&parent->dpll_refs, i, ref) 765 if (i < stop) { 766 __dpll_pin_unregister(ref->dpll, pin, ops, priv, 767 parent); 768 dpll_pin_delete_ntf(pin); 769 } 770 refcount_dec(&pin->refcount); 771 dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin); 772 unlock: 773 mutex_unlock(&dpll_lock); 774 return ret; 775 } 776 EXPORT_SYMBOL_GPL(dpll_pin_on_pin_register); 777 778 /** 779 * dpll_pin_on_pin_unregister - unregister dpll pin from a parent pin 780 * @parent: pointer to a parent pin 781 * @pin: pointer to a pin 782 * @ops: ops for a dpll pin 783 * @priv: pointer to private information of owner 784 * 785 * Context: Acquires a lock (dpll_lock) 786 * Note: It does not free the memory 787 */ 788 void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin, 789 const struct dpll_pin_ops *ops, void *priv) 790 { 791 struct dpll_pin_ref *ref; 792 unsigned long i; 793 794 mutex_lock(&dpll_lock); 795 dpll_pin_delete_ntf(pin); 796 dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin); 797 refcount_dec(&pin->refcount); 798 xa_for_each(&pin->dpll_refs, i, ref) 799 __dpll_pin_unregister(ref->dpll, pin, ops, priv, parent); 800 mutex_unlock(&dpll_lock); 801 } 802 EXPORT_SYMBOL_GPL(dpll_pin_on_pin_unregister); 803 804 /** 805 * dpll_pin_ref_sync_pair_add - create a reference sync signal pin pair 806 * @pin: pin which produces the base frequency 807 * @ref_sync_pin: pin which produces the sync signal 808 * 809 * Once pins are paired, the user-space configuration of reference sync pair 810 * is possible. 811 * Context: Acquires a lock (dpll_lock) 812 * Return: 813 * * 0 on success 814 * * negative - error value 815 */ 816 int dpll_pin_ref_sync_pair_add(struct dpll_pin *pin, 817 struct dpll_pin *ref_sync_pin) 818 { 819 int ret; 820 821 mutex_lock(&dpll_lock); 822 ret = xa_insert(&pin->ref_sync_pins, ref_sync_pin->id, 823 ref_sync_pin, GFP_KERNEL); 824 __dpll_pin_change_ntf(pin); 825 mutex_unlock(&dpll_lock); 826 827 return ret; 828 } 829 EXPORT_SYMBOL_GPL(dpll_pin_ref_sync_pair_add); 830 831 static struct dpll_device_registration * 832 dpll_device_registration_first(struct dpll_device *dpll) 833 { 834 struct dpll_device_registration *reg; 835 836 reg = list_first_entry_or_null((struct list_head *)&dpll->registration_list, 837 struct dpll_device_registration, list); 838 WARN_ON(!reg); 839 return reg; 840 } 841 842 void *dpll_priv(struct dpll_device *dpll) 843 { 844 struct dpll_device_registration *reg; 845 846 reg = dpll_device_registration_first(dpll); 847 return reg->priv; 848 } 849 850 const struct dpll_device_ops *dpll_device_ops(struct dpll_device *dpll) 851 { 852 struct dpll_device_registration *reg; 853 854 reg = dpll_device_registration_first(dpll); 855 return reg->ops; 856 } 857 858 static struct dpll_pin_registration * 859 dpll_pin_registration_first(struct dpll_pin_ref *ref) 860 { 861 struct dpll_pin_registration *reg; 862 863 reg = list_first_entry_or_null(&ref->registration_list, 864 struct dpll_pin_registration, list); 865 WARN_ON(!reg); 866 return reg; 867 } 868 869 void *dpll_pin_on_dpll_priv(struct dpll_device *dpll, 870 struct dpll_pin *pin) 871 { 872 struct dpll_pin_registration *reg; 873 struct dpll_pin_ref *ref; 874 875 ref = xa_load(&dpll->pin_refs, pin->pin_idx); 876 if (!ref) 877 return NULL; 878 reg = dpll_pin_registration_first(ref); 879 return reg->priv; 880 } 881 882 void *dpll_pin_on_pin_priv(struct dpll_pin *parent, 883 struct dpll_pin *pin) 884 { 885 struct dpll_pin_registration *reg; 886 struct dpll_pin_ref *ref; 887 888 ref = xa_load(&pin->parent_refs, parent->pin_idx); 889 if (!ref) 890 return NULL; 891 reg = dpll_pin_registration_first(ref); 892 return reg->priv; 893 } 894 895 const struct dpll_pin_ops *dpll_pin_ops(struct dpll_pin_ref *ref) 896 { 897 struct dpll_pin_registration *reg; 898 899 reg = dpll_pin_registration_first(ref); 900 return reg->ops; 901 } 902 903 static int __init dpll_init(void) 904 { 905 int ret; 906 907 ret = genl_register_family(&dpll_nl_family); 908 if (ret) 909 goto error; 910 911 return 0; 912 913 error: 914 mutex_destroy(&dpll_lock); 915 return ret; 916 } 917 918 static void __exit dpll_exit(void) 919 { 920 genl_unregister_family(&dpll_nl_family); 921 mutex_destroy(&dpll_lock); 922 } 923 924 subsys_initcall(dpll_init); 925 module_exit(dpll_exit); 926