Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'dpll-core-improvements-and-ice-e825-c-synce-support'

Ivan Vecera says:

====================
dpll: Core improvements and ice E825-C SyncE support

This series introduces Synchronous Ethernet (SyncE) support for the Intel
E825-C Ethernet controller. Unlike previous generations where DPLL
connections were implicitly assumed, the E825-C architecture relies
on the platform firmware (ACPI) to describe the physical connections
between the Ethernet controller and external DPLLs (such as the ZL3073x).

To accommodate this, the series extends the DPLL subsystem to support
firmware node (fwnode) associations, asynchronous discovery via notifiers,
and dynamic pin management. Additionally, a significant refactor of
the DPLL reference counting logic is included to ensure robustness and
debuggability.

DPLL Core Extensions:
* Firmware Node Association: Pins can now be associated with a struct
fwnode_handle after allocation via dpll_pin_fwnode_set(). This allows
drivers to link pin objects with their corresponding DT/ACPI nodes.
* Asynchronous Notifiers: A raw notifier chain is added to the DPLL core.
This allows the Ethernet driver to subscribe to events and react when
the platform DPLL driver registers the parent pins, resolving probe
ordering dependencies.
* Dynamic Indexing: Drivers can now request DPLL_PIN_IDX_UNSPEC to have
the core automatically allocate a unique pin index.

Reference Counting & Debugging:
* Refactor: The reference counting logic in the core is consolidated.
Internal list management helpers now automatically handle hold/put
operations, removing fragile open-coded logic in the registration paths.
* Reference Tracking: A new Kconfig option DPLL_REFCNT_TRACKER is added.
This allows developers to instrument and debug reference leaks by
recording stack traces for every get/put operation.

Driver Updates:
* zl3073x: Updated to associate pins with fwnode handles using the new
setter and support the 'mux' pin type.
* ice: Implements the E825-C specific hardware configuration for SyncE
(CGU registers). It utilizes the new notifier and fwnode APIs to
dynamically discover and attach to the platform DPLLs.

Patch Summary:
Patch 1: DPLL Core (fwnode association).
Patch 2: Driver zl3073x (Set fwnode).
Patch 3-4: DPLL Core (Notifiers and dynamic IDs).
Patch 5: Driver zl3073x (Mux type).
Patch 6: DPLL Core (Refcount refactor).
Patch 7-8: Refcount tracking infrastructure and driver updates.
Patch 9: Driver ice (E825-C SyncE logic).
====================

Link: https://patch.msgid.link/20260203174002.705176-1-ivecera@redhat.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+1350 -150
+15
drivers/dpll/Kconfig
··· 8 8 config DPLL 9 9 bool 10 10 11 + config DPLL_REFCNT_TRACKER 12 + bool "DPLL reference count tracking" 13 + depends on DEBUG_KERNEL && STACKTRACE_SUPPORT && DPLL 14 + select REF_TRACKER 15 + help 16 + Enable reference count tracking for DPLL devices and pins. 17 + This helps debugging reference leaks and use-after-free bugs 18 + by recording stack traces for each get/put operation. 19 + 20 + The tracking information is exposed via debugfs at: 21 + /sys/kernel/debug/ref_tracker/dpll_device_* 22 + /sys/kernel/debug/ref_tracker/dpll_pin_* 23 + 24 + If unsure, say N. 25 + 11 26 source "drivers/dpll/zl3073x/Kconfig" 12 27 13 28 endmenu
+259 -29
drivers/dpll/dpll_core.c
··· 10 10 11 11 #include <linux/device.h> 12 12 #include <linux/err.h> 13 + #include <linux/idr.h> 14 + #include <linux/property.h> 13 15 #include <linux/slab.h> 14 16 #include <linux/string.h> 15 17 ··· 23 21 24 22 DEFINE_XARRAY_FLAGS(dpll_device_xa, XA_FLAGS_ALLOC); 25 23 DEFINE_XARRAY_FLAGS(dpll_pin_xa, XA_FLAGS_ALLOC); 24 + 25 + static RAW_NOTIFIER_HEAD(dpll_notifier_chain); 26 + static DEFINE_IDA(dpll_pin_idx_ida); 26 27 27 28 static u32 dpll_device_xa_id; 28 29 static u32 dpll_pin_xa_id; ··· 41 36 struct list_head list; 42 37 const struct dpll_device_ops *ops; 43 38 void *priv; 39 + dpll_tracker tracker; 44 40 }; 45 41 46 42 struct dpll_pin_registration { ··· 49 43 const struct dpll_pin_ops *ops; 50 44 void *priv; 51 45 void *cookie; 46 + dpll_tracker tracker; 52 47 }; 48 + 49 + static int call_dpll_notifiers(unsigned long action, void *info) 50 + { 51 + lockdep_assert_held(&dpll_lock); 52 + return raw_notifier_call_chain(&dpll_notifier_chain, action, info); 53 + } 54 + 55 + void dpll_device_notify(struct dpll_device *dpll, unsigned long action) 56 + { 57 + struct dpll_device_notifier_info info = { 58 + .dpll = dpll, 59 + .id = dpll->id, 60 + .idx = dpll->device_idx, 61 + .clock_id = dpll->clock_id, 62 + .type = dpll->type, 63 + }; 64 + 65 + call_dpll_notifiers(action, &info); 66 + } 67 + 68 + void dpll_pin_notify(struct dpll_pin *pin, unsigned long action) 69 + { 70 + struct dpll_pin_notifier_info info = { 71 + .pin = pin, 72 + .id = pin->id, 73 + .idx = pin->pin_idx, 74 + .clock_id = pin->clock_id, 75 + .fwnode = pin->fwnode, 76 + .prop = &pin->prop, 77 + }; 78 + 79 + call_dpll_notifiers(action, &info); 80 + } 81 + 82 + static void dpll_device_tracker_alloc(struct dpll_device *dpll, 83 + dpll_tracker *tracker) 84 + { 85 + #ifdef CONFIG_DPLL_REFCNT_TRACKER 86 + ref_tracker_alloc(&dpll->refcnt_tracker, tracker, GFP_KERNEL); 87 + #endif 88 + } 89 + 90 + static void dpll_device_tracker_free(struct dpll_device *dpll, 91 + dpll_tracker *tracker) 92 + { 93 + #ifdef CONFIG_DPLL_REFCNT_TRACKER 94 + ref_tracker_free(&dpll->refcnt_tracker, tracker); 95 + #endif 96 + } 97 + 98 + static void __dpll_device_hold(struct dpll_device *dpll, dpll_tracker *tracker) 99 + { 100 + dpll_device_tracker_alloc(dpll, tracker); 101 + refcount_inc(&dpll->refcount); 102 + } 103 + 104 + static void __dpll_device_put(struct dpll_device *dpll, dpll_tracker *tracker) 105 + { 106 + dpll_device_tracker_free(dpll, tracker); 107 + if (refcount_dec_and_test(&dpll->refcount)) { 108 + ASSERT_DPLL_NOT_REGISTERED(dpll); 109 + WARN_ON_ONCE(!xa_empty(&dpll->pin_refs)); 110 + xa_destroy(&dpll->pin_refs); 111 + xa_erase(&dpll_device_xa, dpll->id); 112 + WARN_ON(!list_empty(&dpll->registration_list)); 113 + ref_tracker_dir_exit(&dpll->refcnt_tracker); 114 + kfree(dpll); 115 + } 116 + } 117 + 118 + static void dpll_pin_tracker_alloc(struct dpll_pin *pin, dpll_tracker *tracker) 119 + { 120 + #ifdef CONFIG_DPLL_REFCNT_TRACKER 121 + ref_tracker_alloc(&pin->refcnt_tracker, tracker, GFP_KERNEL); 122 + #endif 123 + } 124 + 125 + static void dpll_pin_tracker_free(struct dpll_pin *pin, dpll_tracker *tracker) 126 + { 127 + #ifdef CONFIG_DPLL_REFCNT_TRACKER 128 + ref_tracker_free(&pin->refcnt_tracker, tracker); 129 + #endif 130 + } 131 + 132 + static void __dpll_pin_hold(struct dpll_pin *pin, dpll_tracker *tracker) 133 + { 134 + dpll_pin_tracker_alloc(pin, tracker); 135 + refcount_inc(&pin->refcount); 136 + } 137 + 138 + static void dpll_pin_idx_free(u32 pin_idx); 139 + static void dpll_pin_prop_free(struct dpll_pin_properties *prop); 140 + 141 + static void __dpll_pin_put(struct dpll_pin *pin, dpll_tracker *tracker) 142 + { 143 + dpll_pin_tracker_free(pin, tracker); 144 + if (refcount_dec_and_test(&pin->refcount)) { 145 + xa_erase(&dpll_pin_xa, pin->id); 146 + xa_destroy(&pin->dpll_refs); 147 + xa_destroy(&pin->parent_refs); 148 + xa_destroy(&pin->ref_sync_pins); 149 + dpll_pin_prop_free(&pin->prop); 150 + fwnode_handle_put(pin->fwnode); 151 + dpll_pin_idx_free(pin->pin_idx); 152 + ref_tracker_dir_exit(&pin->refcnt_tracker); 153 + kfree_rcu(pin, rcu); 154 + } 155 + } 53 156 54 157 struct dpll_device *dpll_device_get_by_id(int id) 55 158 { ··· 229 114 reg->ops = ops; 230 115 reg->priv = priv; 231 116 reg->cookie = cookie; 117 + __dpll_pin_hold(pin, &reg->tracker); 232 118 if (ref_exists) 233 119 refcount_inc(&ref->refcount); 234 120 list_add_tail(&reg->list, &ref->registration_list); ··· 252 136 if (WARN_ON(!reg)) 253 137 return -EINVAL; 254 138 list_del(&reg->list); 139 + __dpll_pin_put(pin, &reg->tracker); 255 140 kfree(reg); 256 141 if (refcount_dec_and_test(&ref->refcount)) { 257 142 xa_erase(xa_pins, i); ··· 310 193 reg->ops = ops; 311 194 reg->priv = priv; 312 195 reg->cookie = cookie; 196 + __dpll_device_hold(dpll, &reg->tracker); 313 197 if (ref_exists) 314 198 refcount_inc(&ref->refcount); 315 199 list_add_tail(&reg->list, &ref->registration_list); ··· 333 215 if (WARN_ON(!reg)) 334 216 return; 335 217 list_del(&reg->list); 218 + __dpll_device_put(dpll, &reg->tracker); 336 219 kfree(reg); 337 220 if (refcount_dec_and_test(&ref->refcount)) { 338 221 xa_erase(xa_dplls, i); ··· 375 256 return ERR_PTR(ret); 376 257 } 377 258 xa_init_flags(&dpll->pin_refs, XA_FLAGS_ALLOC); 259 + ref_tracker_dir_init(&dpll->refcnt_tracker, 128, "dpll_device"); 378 260 379 261 return dpll; 380 262 } ··· 385 265 * @clock_id: clock_id of creator 386 266 * @device_idx: idx given by device driver 387 267 * @module: reference to registering module 268 + * @tracker: tracking object for the acquired reference 388 269 * 389 270 * Get existing object of a dpll device, unique for given arguments. 390 271 * Create new if doesn't exist yet. ··· 396 275 * * ERR_PTR(X) - error 397 276 */ 398 277 struct dpll_device * 399 - dpll_device_get(u64 clock_id, u32 device_idx, struct module *module) 278 + dpll_device_get(u64 clock_id, u32 device_idx, struct module *module, 279 + dpll_tracker *tracker) 400 280 { 401 281 struct dpll_device *dpll, *ret = NULL; 402 282 unsigned long index; ··· 407 285 if (dpll->clock_id == clock_id && 408 286 dpll->device_idx == device_idx && 409 287 dpll->module == module) { 288 + __dpll_device_hold(dpll, tracker); 410 289 ret = dpll; 411 - refcount_inc(&ret->refcount); 412 290 break; 413 291 } 414 292 } 415 - if (!ret) 293 + if (!ret) { 416 294 ret = dpll_device_alloc(clock_id, device_idx, module); 295 + if (!IS_ERR(ret)) 296 + dpll_device_tracker_alloc(ret, tracker); 297 + } 298 + 417 299 mutex_unlock(&dpll_lock); 418 300 419 301 return ret; ··· 427 301 /** 428 302 * dpll_device_put - decrease the refcount and free memory if possible 429 303 * @dpll: dpll_device struct pointer 304 + * @tracker: tracking object for the acquired reference 430 305 * 431 306 * Context: Acquires a lock (dpll_lock) 432 307 * Drop reference for a dpll device, if all references are gone, delete 433 308 * dpll device object. 434 309 */ 435 - void dpll_device_put(struct dpll_device *dpll) 310 + void dpll_device_put(struct dpll_device *dpll, dpll_tracker *tracker) 436 311 { 437 312 mutex_lock(&dpll_lock); 438 - if (refcount_dec_and_test(&dpll->refcount)) { 439 - ASSERT_DPLL_NOT_REGISTERED(dpll); 440 - WARN_ON_ONCE(!xa_empty(&dpll->pin_refs)); 441 - xa_destroy(&dpll->pin_refs); 442 - xa_erase(&dpll_device_xa, dpll->id); 443 - WARN_ON(!list_empty(&dpll->registration_list)); 444 - kfree(dpll); 445 - } 313 + __dpll_device_put(dpll, tracker); 446 314 mutex_unlock(&dpll_lock); 447 315 } 448 316 EXPORT_SYMBOL_GPL(dpll_device_put); ··· 498 378 reg->ops = ops; 499 379 reg->priv = priv; 500 380 dpll->type = type; 381 + __dpll_device_hold(dpll, &reg->tracker); 501 382 first_registration = list_empty(&dpll->registration_list); 502 383 list_add_tail(&reg->list, &dpll->registration_list); 503 384 if (!first_registration) { ··· 538 417 return; 539 418 } 540 419 list_del(&reg->list); 420 + __dpll_device_put(dpll, &reg->tracker); 541 421 kfree(reg); 542 422 543 423 if (!list_empty(&dpll->registration_list)) { ··· 549 427 mutex_unlock(&dpll_lock); 550 428 } 551 429 EXPORT_SYMBOL_GPL(dpll_device_unregister); 430 + 431 + static int dpll_pin_idx_alloc(u32 *pin_idx) 432 + { 433 + int ret; 434 + 435 + if (!pin_idx) 436 + return -EINVAL; 437 + 438 + /* Alloc unique number from IDA. Number belongs to <0, INT_MAX> range */ 439 + ret = ida_alloc(&dpll_pin_idx_ida, GFP_KERNEL); 440 + if (ret < 0) 441 + return ret; 442 + 443 + /* Map the value to dynamic pin index range <INT_MAX+1, U32_MAX> */ 444 + *pin_idx = (u32)ret + INT_MAX + 1; 445 + 446 + return 0; 447 + } 448 + 449 + static void dpll_pin_idx_free(u32 pin_idx) 450 + { 451 + if (pin_idx <= INT_MAX) 452 + return; /* Not a dynamic pin index */ 453 + 454 + /* Map the index value from dynamic pin index range to IDA range and 455 + * free it. 456 + */ 457 + pin_idx -= (u32)INT_MAX + 1; 458 + ida_free(&dpll_pin_idx_ida, pin_idx); 459 + } 552 460 553 461 static void dpll_pin_prop_free(struct dpll_pin_properties *prop) 554 462 { ··· 637 485 struct dpll_pin *pin; 638 486 int ret; 639 487 488 + if (pin_idx == DPLL_PIN_IDX_UNSPEC) { 489 + ret = dpll_pin_idx_alloc(&pin_idx); 490 + if (ret) 491 + return ERR_PTR(ret); 492 + } else if (pin_idx > INT_MAX) { 493 + return ERR_PTR(-EINVAL); 494 + } 640 495 pin = kzalloc(sizeof(*pin), GFP_KERNEL); 641 - if (!pin) 642 - return ERR_PTR(-ENOMEM); 496 + if (!pin) { 497 + ret = -ENOMEM; 498 + goto err_pin_alloc; 499 + } 643 500 pin->pin_idx = pin_idx; 644 501 pin->clock_id = clock_id; 645 502 pin->module = module; ··· 668 507 &dpll_pin_xa_id, GFP_KERNEL); 669 508 if (ret < 0) 670 509 goto err_xa_alloc; 510 + ref_tracker_dir_init(&pin->refcnt_tracker, 128, "dpll_pin"); 671 511 return pin; 672 512 err_xa_alloc: 673 513 xa_destroy(&pin->dpll_refs); ··· 677 515 dpll_pin_prop_free(&pin->prop); 678 516 err_pin_prop: 679 517 kfree(pin); 518 + err_pin_alloc: 519 + dpll_pin_idx_free(pin_idx); 680 520 return ERR_PTR(ret); 681 521 } 682 522 ··· 702 538 } 703 539 EXPORT_SYMBOL(dpll_netdev_pin_clear); 704 540 541 + int register_dpll_notifier(struct notifier_block *nb) 542 + { 543 + int ret; 544 + 545 + mutex_lock(&dpll_lock); 546 + ret = raw_notifier_chain_register(&dpll_notifier_chain, nb); 547 + mutex_unlock(&dpll_lock); 548 + return ret; 549 + } 550 + EXPORT_SYMBOL_GPL(register_dpll_notifier); 551 + 552 + int unregister_dpll_notifier(struct notifier_block *nb) 553 + { 554 + int ret; 555 + 556 + mutex_lock(&dpll_lock); 557 + ret = raw_notifier_chain_unregister(&dpll_notifier_chain, nb); 558 + mutex_unlock(&dpll_lock); 559 + return ret; 560 + } 561 + EXPORT_SYMBOL_GPL(unregister_dpll_notifier); 562 + 705 563 /** 706 564 * dpll_pin_get - find existing or create new dpll pin 707 565 * @clock_id: clock_id of creator 708 566 * @pin_idx: idx given by dev driver 709 567 * @module: reference to registering module 710 568 * @prop: dpll pin properties 569 + * @tracker: tracking object for the acquired reference 711 570 * 712 571 * Get existing object of a pin (unique for given arguments) or create new 713 572 * if doesn't exist yet. ··· 742 555 */ 743 556 struct dpll_pin * 744 557 dpll_pin_get(u64 clock_id, u32 pin_idx, struct module *module, 745 - const struct dpll_pin_properties *prop) 558 + const struct dpll_pin_properties *prop, dpll_tracker *tracker) 746 559 { 747 560 struct dpll_pin *pos, *ret = NULL; 748 561 unsigned long i; ··· 752 565 if (pos->clock_id == clock_id && 753 566 pos->pin_idx == pin_idx && 754 567 pos->module == module) { 568 + __dpll_pin_hold(pos, tracker); 755 569 ret = pos; 756 - refcount_inc(&ret->refcount); 757 570 break; 758 571 } 759 572 } 760 - if (!ret) 573 + if (!ret) { 761 574 ret = dpll_pin_alloc(clock_id, pin_idx, module, prop); 575 + if (!IS_ERR(ret)) 576 + dpll_pin_tracker_alloc(ret, tracker); 577 + } 762 578 mutex_unlock(&dpll_lock); 763 579 764 580 return ret; ··· 771 581 /** 772 582 * dpll_pin_put - decrease the refcount and free memory if possible 773 583 * @pin: pointer to a pin to be put 584 + * @tracker: tracking object for the acquired reference 774 585 * 775 586 * Drop reference for a pin, if all references are gone, delete pin object. 776 587 * 777 588 * Context: Acquires a lock (dpll_lock) 778 589 */ 779 - void dpll_pin_put(struct dpll_pin *pin) 590 + void dpll_pin_put(struct dpll_pin *pin, dpll_tracker *tracker) 780 591 { 781 592 mutex_lock(&dpll_lock); 782 - if (refcount_dec_and_test(&pin->refcount)) { 783 - xa_erase(&dpll_pin_xa, pin->id); 784 - xa_destroy(&pin->dpll_refs); 785 - xa_destroy(&pin->parent_refs); 786 - xa_destroy(&pin->ref_sync_pins); 787 - dpll_pin_prop_free(&pin->prop); 788 - kfree_rcu(pin, rcu); 789 - } 593 + __dpll_pin_put(pin, tracker); 790 594 mutex_unlock(&dpll_lock); 791 595 } 792 596 EXPORT_SYMBOL_GPL(dpll_pin_put); 597 + 598 + /** 599 + * dpll_pin_fwnode_set - set dpll pin firmware node reference 600 + * @pin: pointer to a dpll pin 601 + * @fwnode: firmware node handle 602 + * 603 + * Set firmware node handle for the given dpll pin. 604 + */ 605 + void dpll_pin_fwnode_set(struct dpll_pin *pin, struct fwnode_handle *fwnode) 606 + { 607 + mutex_lock(&dpll_lock); 608 + fwnode_handle_put(pin->fwnode); /* Drop fwnode previously set */ 609 + pin->fwnode = fwnode_handle_get(fwnode); 610 + mutex_unlock(&dpll_lock); 611 + } 612 + EXPORT_SYMBOL_GPL(dpll_pin_fwnode_set); 613 + 614 + /** 615 + * fwnode_dpll_pin_find - find dpll pin by firmware node reference 616 + * @fwnode: reference to firmware node 617 + * @tracker: tracking object for the acquired reference 618 + * 619 + * Get existing object of a pin that is associated with given firmware node 620 + * reference. 621 + * 622 + * Context: Acquires a lock (dpll_lock) 623 + * Return: 624 + * * valid dpll_pin pointer on success 625 + * * NULL when no such pin exists 626 + */ 627 + struct dpll_pin *fwnode_dpll_pin_find(struct fwnode_handle *fwnode, 628 + dpll_tracker *tracker) 629 + { 630 + struct dpll_pin *pin, *ret = NULL; 631 + unsigned long index; 632 + 633 + mutex_lock(&dpll_lock); 634 + xa_for_each(&dpll_pin_xa, index, pin) { 635 + if (pin->fwnode == fwnode) { 636 + __dpll_pin_hold(pin, tracker); 637 + ret = pin; 638 + break; 639 + } 640 + } 641 + mutex_unlock(&dpll_lock); 642 + 643 + return ret; 644 + } 645 + EXPORT_SYMBOL_GPL(fwnode_dpll_pin_find); 793 646 794 647 static int 795 648 __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, ··· 976 743 ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv, pin); 977 744 if (ret) 978 745 goto unlock; 979 - refcount_inc(&pin->refcount); 980 746 xa_for_each(&parent->dpll_refs, i, ref) { 981 747 ret = __dpll_pin_register(ref->dpll, pin, ops, priv, parent); 982 748 if (ret) { ··· 995 763 parent); 996 764 dpll_pin_delete_ntf(pin); 997 765 } 998 - refcount_dec(&pin->refcount); 999 766 dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin); 1000 767 unlock: 1001 768 mutex_unlock(&dpll_lock); ··· 1021 790 mutex_lock(&dpll_lock); 1022 791 dpll_pin_delete_ntf(pin); 1023 792 dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin); 1024 - refcount_dec(&pin->refcount); 1025 793 xa_for_each(&pin->dpll_refs, i, ref) 1026 794 __dpll_pin_unregister(ref->dpll, pin, ops, priv, parent); 1027 795 mutex_unlock(&dpll_lock);
+11
drivers/dpll/dpll_core.h
··· 10 10 #include <linux/dpll.h> 11 11 #include <linux/list.h> 12 12 #include <linux/refcount.h> 13 + #include <linux/ref_tracker.h> 13 14 #include "dpll_nl.h" 14 15 15 16 #define DPLL_REGISTERED XA_MARK_1 ··· 24 23 * @type: type of a dpll 25 24 * @pin_refs: stores pins registered within a dpll 26 25 * @refcount: refcount 26 + * @refcnt_tracker: ref_tracker directory for debugging reference leaks 27 27 * @registration_list: list of registered ops and priv data of dpll owners 28 28 **/ 29 29 struct dpll_device { ··· 35 33 enum dpll_type type; 36 34 struct xarray pin_refs; 37 35 refcount_t refcount; 36 + struct ref_tracker_dir refcnt_tracker; 38 37 struct list_head registration_list; 39 38 }; 40 39 ··· 45 42 * @pin_idx: index of a pin given by dev driver 46 43 * @clock_id: clock_id of creator 47 44 * @module: module of creator 45 + * @fwnode: optional reference to firmware node 48 46 * @dpll_refs: hold referencees to dplls pin was registered with 49 47 * @parent_refs: hold references to parent pins pin was registered with 50 48 * @ref_sync_pins: hold references to pins for Reference SYNC feature 51 49 * @prop: pin properties copied from the registerer 52 50 * @refcount: refcount 51 + * @refcnt_tracker: ref_tracker directory for debugging reference leaks 53 52 * @rcu: rcu_head for kfree_rcu() 54 53 **/ 55 54 struct dpll_pin { ··· 59 54 u32 pin_idx; 60 55 u64 clock_id; 61 56 struct module *module; 57 + struct fwnode_handle *fwnode; 62 58 struct xarray dpll_refs; 63 59 struct xarray parent_refs; 64 60 struct xarray ref_sync_pins; 65 61 struct dpll_pin_properties prop; 66 62 refcount_t refcount; 63 + struct ref_tracker_dir refcnt_tracker; 67 64 struct rcu_head rcu; 68 65 }; 69 66 ··· 96 89 extern struct xarray dpll_device_xa; 97 90 extern struct xarray dpll_pin_xa; 98 91 extern struct mutex dpll_lock; 92 + 93 + void dpll_device_notify(struct dpll_device *dpll, unsigned long action); 94 + void dpll_pin_notify(struct dpll_pin *pin, unsigned long action); 95 + 99 96 #endif
+6
drivers/dpll/dpll_netlink.c
··· 761 761 762 762 int dpll_device_create_ntf(struct dpll_device *dpll) 763 763 { 764 + dpll_device_notify(dpll, DPLL_DEVICE_CREATED); 764 765 return dpll_device_event_send(DPLL_CMD_DEVICE_CREATE_NTF, dpll); 765 766 } 766 767 767 768 int dpll_device_delete_ntf(struct dpll_device *dpll) 768 769 { 770 + dpll_device_notify(dpll, DPLL_DEVICE_DELETED); 769 771 return dpll_device_event_send(DPLL_CMD_DEVICE_DELETE_NTF, dpll); 770 772 } 771 773 772 774 static int 773 775 __dpll_device_change_ntf(struct dpll_device *dpll) 774 776 { 777 + dpll_device_notify(dpll, DPLL_DEVICE_CHANGED); 775 778 return dpll_device_event_send(DPLL_CMD_DEVICE_CHANGE_NTF, dpll); 776 779 } 777 780 ··· 832 829 833 830 int dpll_pin_create_ntf(struct dpll_pin *pin) 834 831 { 832 + dpll_pin_notify(pin, DPLL_PIN_CREATED); 835 833 return dpll_pin_event_send(DPLL_CMD_PIN_CREATE_NTF, pin); 836 834 } 837 835 838 836 int dpll_pin_delete_ntf(struct dpll_pin *pin) 839 837 { 838 + dpll_pin_notify(pin, DPLL_PIN_DELETED); 840 839 return dpll_pin_event_send(DPLL_CMD_PIN_DELETE_NTF, pin); 841 840 } 842 841 843 842 int __dpll_pin_change_ntf(struct dpll_pin *pin) 844 843 { 844 + dpll_pin_notify(pin, DPLL_PIN_CHANGED); 845 845 return dpll_pin_event_send(DPLL_CMD_PIN_CHANGE_NTF, pin); 846 846 } 847 847
+9 -6
drivers/dpll/zl3073x/dpll.c
··· 29 29 * @list: this DPLL pin list entry 30 30 * @dpll: DPLL the pin is registered to 31 31 * @dpll_pin: pointer to registered dpll_pin 32 + * @tracker: tracking object for the acquired reference 32 33 * @label: package label 33 34 * @dir: pin direction 34 35 * @id: pin id ··· 45 44 struct list_head list; 46 45 struct zl3073x_dpll *dpll; 47 46 struct dpll_pin *dpll_pin; 47 + dpll_tracker tracker; 48 48 char label[8]; 49 49 enum dpll_pin_direction dir; 50 50 u8 id; ··· 1482 1480 1483 1481 /* Create or get existing DPLL pin */ 1484 1482 pin->dpll_pin = dpll_pin_get(zldpll->dev->clock_id, index, THIS_MODULE, 1485 - &props->dpll_props); 1483 + &props->dpll_props, &pin->tracker); 1486 1484 if (IS_ERR(pin->dpll_pin)) { 1487 1485 rc = PTR_ERR(pin->dpll_pin); 1488 1486 goto err_pin_get; 1489 1487 } 1488 + dpll_pin_fwnode_set(pin->dpll_pin, props->fwnode); 1490 1489 1491 1490 if (zl3073x_dpll_is_input_pin(pin)) 1492 1491 ops = &zl3073x_dpll_input_pin_ops; ··· 1505 1502 return 0; 1506 1503 1507 1504 err_register: 1508 - dpll_pin_put(pin->dpll_pin); 1505 + dpll_pin_put(pin->dpll_pin, &pin->tracker); 1509 1506 err_prio_get: 1510 1507 pin->dpll_pin = NULL; 1511 1508 err_pin_get: ··· 1536 1533 /* Unregister the pin */ 1537 1534 dpll_pin_unregister(zldpll->dpll_dev, pin->dpll_pin, ops, pin); 1538 1535 1539 - dpll_pin_put(pin->dpll_pin); 1536 + dpll_pin_put(pin->dpll_pin, &pin->tracker); 1540 1537 pin->dpll_pin = NULL; 1541 1538 } 1542 1539 ··· 1710 1707 dpll_mode_refsel); 1711 1708 1712 1709 zldpll->dpll_dev = dpll_device_get(zldev->clock_id, zldpll->id, 1713 - THIS_MODULE); 1710 + THIS_MODULE, &zldpll->tracker); 1714 1711 if (IS_ERR(zldpll->dpll_dev)) { 1715 1712 rc = PTR_ERR(zldpll->dpll_dev); 1716 1713 zldpll->dpll_dev = NULL; ··· 1722 1719 zl3073x_prop_dpll_type_get(zldev, zldpll->id), 1723 1720 &zl3073x_dpll_device_ops, zldpll); 1724 1721 if (rc) { 1725 - dpll_device_put(zldpll->dpll_dev); 1722 + dpll_device_put(zldpll->dpll_dev, &zldpll->tracker); 1726 1723 zldpll->dpll_dev = NULL; 1727 1724 } 1728 1725 ··· 1745 1742 1746 1743 dpll_device_unregister(zldpll->dpll_dev, &zl3073x_dpll_device_ops, 1747 1744 zldpll); 1748 - dpll_device_put(zldpll->dpll_dev); 1745 + dpll_device_put(zldpll->dpll_dev, &zldpll->tracker); 1749 1746 zldpll->dpll_dev = NULL; 1750 1747 } 1751 1748
+2
drivers/dpll/zl3073x/dpll.h
··· 18 18 * @check_count: periodic check counter 19 19 * @phase_monitor: is phase offset monitor enabled 20 20 * @dpll_dev: pointer to registered DPLL device 21 + * @tracker: tracking object for the acquired reference 21 22 * @lock_status: last saved DPLL lock status 22 23 * @pins: list of pins 23 24 * @change_work: device change notification work ··· 32 31 u8 check_count; 33 32 bool phase_monitor; 34 33 struct dpll_device *dpll_dev; 34 + dpll_tracker tracker; 35 35 enum dpll_lock_status lock_status; 36 36 struct list_head pins; 37 37 struct work_struct change_work;
+2
drivers/dpll/zl3073x/prop.c
··· 249 249 props->dpll_props.type = DPLL_PIN_TYPE_INT_OSCILLATOR; 250 250 else if (!strcmp(type, "synce")) 251 251 props->dpll_props.type = DPLL_PIN_TYPE_SYNCE_ETH_PORT; 252 + else if (!strcmp(type, "mux")) 253 + props->dpll_props.type = DPLL_PIN_TYPE_MUX; 252 254 else 253 255 dev_warn(zldev->dev, 254 256 "Unknown or unsupported pin type '%s'\n",
+662 -96
drivers/net/ethernet/intel/ice/ice_dpll.c
··· 5 5 #include "ice_lib.h" 6 6 #include "ice_trace.h" 7 7 #include <linux/dpll.h> 8 + #include <linux/property.h> 8 9 9 10 #define ICE_CGU_STATE_ACQ_ERR_THRESHOLD 50 10 11 #define ICE_DPLL_PIN_IDX_INVALID 0xff ··· 530 529 } 531 530 532 531 /** 532 + * ice_dpll_pin_store_state - updates the state of pin in SW bookkeeping 533 + * @pin: pointer to a pin 534 + * @parent: parent pin index 535 + * @state: pin state (connected or disconnected) 536 + */ 537 + static void 538 + ice_dpll_pin_store_state(struct ice_dpll_pin *pin, int parent, bool state) 539 + { 540 + pin->state[parent] = state ? DPLL_PIN_STATE_CONNECTED : 541 + DPLL_PIN_STATE_DISCONNECTED; 542 + } 543 + 544 + /** 545 + * ice_dpll_rclk_update_e825c - updates the state of rclk pin on e825c device 546 + * @pf: private board struct 547 + * @pin: pointer to a pin 548 + * 549 + * Update struct holding pin states info, states are separate for each parent 550 + * 551 + * Context: Called under pf->dplls.lock 552 + * Return: 553 + * * 0 - OK 554 + * * negative - error 555 + */ 556 + static int ice_dpll_rclk_update_e825c(struct ice_pf *pf, 557 + struct ice_dpll_pin *pin) 558 + { 559 + u8 rclk_bits; 560 + int err; 561 + u32 reg; 562 + 563 + if (pf->dplls.rclk.num_parents > ICE_SYNCE_CLK_NUM) 564 + return -EINVAL; 565 + 566 + err = ice_read_cgu_reg(&pf->hw, ICE_CGU_R10, &reg); 567 + if (err) 568 + return err; 569 + 570 + rclk_bits = FIELD_GET(ICE_CGU_R10_SYNCE_S_REF_CLK, reg); 571 + ice_dpll_pin_store_state(pin, ICE_SYNCE_CLK0, rclk_bits == 572 + (pf->ptp.port.port_num + ICE_CGU_BYPASS_MUX_OFFSET_E825C)); 573 + 574 + err = ice_read_cgu_reg(&pf->hw, ICE_CGU_R11, &reg); 575 + if (err) 576 + return err; 577 + 578 + rclk_bits = FIELD_GET(ICE_CGU_R11_SYNCE_S_BYP_CLK, reg); 579 + ice_dpll_pin_store_state(pin, ICE_SYNCE_CLK1, rclk_bits == 580 + (pf->ptp.port.port_num + ICE_CGU_BYPASS_MUX_OFFSET_E825C)); 581 + 582 + return 0; 583 + } 584 + 585 + /** 586 + * ice_dpll_rclk_update - updates the state of rclk pin on a device 587 + * @pf: private board struct 588 + * @pin: pointer to a pin 589 + * @port_num: port number 590 + * 591 + * Update struct holding pin states info, states are separate for each parent 592 + * 593 + * Context: Called under pf->dplls.lock 594 + * Return: 595 + * * 0 - OK 596 + * * negative - error 597 + */ 598 + static int ice_dpll_rclk_update(struct ice_pf *pf, struct ice_dpll_pin *pin, 599 + u8 port_num) 600 + { 601 + int ret; 602 + 603 + for (u8 parent = 0; parent < pf->dplls.rclk.num_parents; parent++) { 604 + u8 p = parent; 605 + 606 + ret = ice_aq_get_phy_rec_clk_out(&pf->hw, &p, &port_num, 607 + &pin->flags[parent], NULL); 608 + if (ret) 609 + return ret; 610 + 611 + ice_dpll_pin_store_state(pin, parent, 612 + ICE_AQC_GET_PHY_REC_CLK_OUT_OUT_EN & 613 + pin->flags[parent]); 614 + } 615 + 616 + return 0; 617 + } 618 + 619 + /** 533 620 * ice_dpll_sw_pins_update - update status of all SW pins 534 621 * @pf: private board struct 535 622 * ··· 757 668 } 758 669 break; 759 670 case ICE_DPLL_PIN_TYPE_RCLK_INPUT: 760 - for (parent = 0; parent < pf->dplls.rclk.num_parents; 761 - parent++) { 762 - u8 p = parent; 763 - 764 - ret = ice_aq_get_phy_rec_clk_out(&pf->hw, &p, 765 - &port_num, 766 - &pin->flags[parent], 767 - NULL); 671 + if (pf->hw.mac_type == ICE_MAC_GENERIC_3K_E825) { 672 + ret = ice_dpll_rclk_update_e825c(pf, pin); 768 673 if (ret) 769 674 goto err; 770 - if (ICE_AQC_GET_PHY_REC_CLK_OUT_OUT_EN & 771 - pin->flags[parent]) 772 - pin->state[parent] = DPLL_PIN_STATE_CONNECTED; 773 - else 774 - pin->state[parent] = 775 - DPLL_PIN_STATE_DISCONNECTED; 675 + } else { 676 + ret = ice_dpll_rclk_update(pf, pin, port_num); 677 + if (ret) 678 + goto err; 776 679 } 777 680 break; 778 681 case ICE_DPLL_PIN_TYPE_SOFTWARE: ··· 1924 1843 } 1925 1844 1926 1845 /** 1846 + * ice_dpll_synce_update_e825c - setting PHY recovered clock pins on e825c 1847 + * @hw: Pointer to the HW struct 1848 + * @ena: true if enable, false in disable 1849 + * @port_num: port number 1850 + * @output: output pin, we have two in E825C 1851 + * 1852 + * DPLL subsystem callback. Set proper signals to recover clock from port. 1853 + * 1854 + * Context: Called under pf->dplls.lock 1855 + * Return: 1856 + * * 0 - success 1857 + * * negative - error 1858 + */ 1859 + static int ice_dpll_synce_update_e825c(struct ice_hw *hw, bool ena, 1860 + u32 port_num, enum ice_synce_clk output) 1861 + { 1862 + int err; 1863 + 1864 + /* configure the mux to deliver proper signal to DPLL from the MUX */ 1865 + err = ice_tspll_cfg_bypass_mux_e825c(hw, ena, port_num, output); 1866 + if (err) 1867 + return err; 1868 + 1869 + err = ice_tspll_cfg_synce_ethdiv_e825c(hw, output); 1870 + if (err) 1871 + return err; 1872 + 1873 + dev_dbg(ice_hw_to_dev(hw), "CLK_SYNCE%u recovered clock: pin %s\n", 1874 + output, str_enabled_disabled(ena)); 1875 + 1876 + return 0; 1877 + } 1878 + 1879 + /** 1927 1880 * ice_dpll_output_esync_set - callback for setting embedded sync 1928 1881 * @pin: pointer to a pin 1929 1882 * @pin_priv: private data pointer passed on pin registration ··· 2378 2263 state, extack); 2379 2264 } 2380 2265 2266 + static int 2267 + ice_dpll_pin_get_parent_num(struct ice_dpll_pin *pin, 2268 + const struct dpll_pin *parent) 2269 + { 2270 + int i; 2271 + 2272 + for (i = 0; i < pin->num_parents; i++) 2273 + if (pin->pf->dplls.inputs[pin->parent_idx[i]].pin == parent) 2274 + return i; 2275 + 2276 + return -ENOENT; 2277 + } 2278 + 2279 + static int 2280 + ice_dpll_pin_get_parent_idx(struct ice_dpll_pin *pin, 2281 + const struct dpll_pin *parent) 2282 + { 2283 + int num = ice_dpll_pin_get_parent_num(pin, parent); 2284 + 2285 + return num < 0 ? num : pin->parent_idx[num]; 2286 + } 2287 + 2381 2288 /** 2382 2289 * ice_dpll_rclk_state_on_pin_set - set a state on rclk pin 2383 2290 * @pin: pointer to a pin ··· 2423 2286 enum dpll_pin_state state, 2424 2287 struct netlink_ext_ack *extack) 2425 2288 { 2426 - struct ice_dpll_pin *p = pin_priv, *parent = parent_pin_priv; 2427 2289 bool enable = state == DPLL_PIN_STATE_CONNECTED; 2290 + struct ice_dpll_pin *p = pin_priv; 2428 2291 struct ice_pf *pf = p->pf; 2292 + struct ice_hw *hw; 2429 2293 int ret = -EINVAL; 2430 - u32 hw_idx; 2294 + int hw_idx; 2295 + 2296 + hw = &pf->hw; 2431 2297 2432 2298 if (ice_dpll_is_reset(pf, extack)) 2433 2299 return -EBUSY; 2434 2300 2435 2301 mutex_lock(&pf->dplls.lock); 2436 - hw_idx = parent->idx - pf->dplls.base_rclk_idx; 2437 - if (hw_idx >= pf->dplls.num_inputs) 2302 + hw_idx = ice_dpll_pin_get_parent_idx(p, parent_pin); 2303 + if (hw_idx < 0) 2438 2304 goto unlock; 2305 + hw_idx -= pf->dplls.base_rclk_idx; 2439 2306 2440 2307 if ((enable && p->state[hw_idx] == DPLL_PIN_STATE_CONNECTED) || 2441 2308 (!enable && p->state[hw_idx] == DPLL_PIN_STATE_DISCONNECTED)) { 2442 2309 NL_SET_ERR_MSG_FMT(extack, 2443 2310 "pin:%u state:%u on parent:%u already set", 2444 - p->idx, state, parent->idx); 2311 + p->idx, state, 2312 + ice_dpll_pin_get_parent_num(p, parent_pin)); 2445 2313 goto unlock; 2446 2314 } 2447 - ret = ice_aq_set_phy_rec_clk_out(&pf->hw, hw_idx, enable, 2448 - &p->freq); 2315 + 2316 + ret = hw->mac_type == ICE_MAC_GENERIC_3K_E825 ? 2317 + ice_dpll_synce_update_e825c(hw, enable, 2318 + pf->ptp.port.port_num, 2319 + (enum ice_synce_clk)hw_idx) : 2320 + ice_aq_set_phy_rec_clk_out(hw, hw_idx, enable, &p->freq); 2449 2321 if (ret) 2450 2322 NL_SET_ERR_MSG_FMT(extack, 2451 2323 "err:%d %s failed to set pin state:%u for pin:%u on parent:%u", 2452 2324 ret, 2453 - libie_aq_str(pf->hw.adminq.sq_last_status), 2454 - state, p->idx, parent->idx); 2325 + libie_aq_str(hw->adminq.sq_last_status), 2326 + state, p->idx, 2327 + ice_dpll_pin_get_parent_num(p, parent_pin)); 2455 2328 unlock: 2456 2329 mutex_unlock(&pf->dplls.lock); 2457 2330 ··· 2491 2344 enum dpll_pin_state *state, 2492 2345 struct netlink_ext_ack *extack) 2493 2346 { 2494 - struct ice_dpll_pin *p = pin_priv, *parent = parent_pin_priv; 2347 + struct ice_dpll_pin *p = pin_priv; 2495 2348 struct ice_pf *pf = p->pf; 2496 2349 int ret = -EINVAL; 2497 - u32 hw_idx; 2350 + int hw_idx; 2498 2351 2499 2352 if (ice_dpll_is_reset(pf, extack)) 2500 2353 return -EBUSY; 2501 2354 2502 2355 mutex_lock(&pf->dplls.lock); 2503 - hw_idx = parent->idx - pf->dplls.base_rclk_idx; 2504 - if (hw_idx >= pf->dplls.num_inputs) 2356 + hw_idx = ice_dpll_pin_get_parent_idx(p, parent_pin); 2357 + if (hw_idx < 0) 2505 2358 goto unlock; 2506 2359 2507 2360 ret = ice_dpll_pin_state_update(pf, p, ICE_DPLL_PIN_TYPE_RCLK_INPUT, ··· 2961 2814 int i; 2962 2815 2963 2816 for (i = 0; i < count; i++) 2964 - dpll_pin_put(pins[i].pin); 2817 + if (!IS_ERR_OR_NULL(pins[i].pin)) 2818 + dpll_pin_put(pins[i].pin, &pins[i].tracker); 2965 2819 } 2966 2820 2967 2821 /** ··· 2984 2836 ice_dpll_get_pins(struct ice_pf *pf, struct ice_dpll_pin *pins, 2985 2837 int start_idx, int count, u64 clock_id) 2986 2838 { 2839 + u32 pin_index; 2987 2840 int i, ret; 2988 2841 2989 2842 for (i = 0; i < count; i++) { 2990 - pins[i].pin = dpll_pin_get(clock_id, i + start_idx, THIS_MODULE, 2991 - &pins[i].prop); 2843 + pin_index = start_idx; 2844 + if (start_idx != DPLL_PIN_IDX_UNSPEC) 2845 + pin_index += i; 2846 + pins[i].pin = dpll_pin_get(clock_id, pin_index, THIS_MODULE, 2847 + &pins[i].prop, &pins[i].tracker); 2992 2848 if (IS_ERR(pins[i].pin)) { 2993 2849 ret = PTR_ERR(pins[i].pin); 2994 2850 goto release_pins; ··· 3003 2851 3004 2852 release_pins: 3005 2853 while (--i >= 0) 3006 - dpll_pin_put(pins[i].pin); 2854 + dpll_pin_put(pins[i].pin, &pins[i].tracker); 3007 2855 return ret; 3008 2856 } 3009 2857 ··· 3096 2944 3097 2945 /** 3098 2946 * ice_dpll_deinit_direct_pins - deinitialize direct pins 2947 + * @pf: board private structure 3099 2948 * @cgu: if cgu is present and controlled by this NIC 3100 2949 * @pins: pointer to pins array 3101 2950 * @count: number of pins ··· 3108 2955 * Release pins resources to the dpll subsystem. 3109 2956 */ 3110 2957 static void 3111 - ice_dpll_deinit_direct_pins(bool cgu, struct ice_dpll_pin *pins, int count, 2958 + ice_dpll_deinit_direct_pins(struct ice_pf *pf, bool cgu, 2959 + struct ice_dpll_pin *pins, int count, 3112 2960 const struct dpll_pin_ops *ops, 3113 2961 struct dpll_device *first, 3114 2962 struct dpll_device *second) ··· 3178 3024 { 3179 3025 struct ice_dpll_pin *rclk = &pf->dplls.rclk; 3180 3026 struct ice_vsi *vsi = ice_get_main_vsi(pf); 3181 - struct dpll_pin *parent; 3027 + struct ice_dpll_pin *parent; 3182 3028 int i; 3183 3029 3184 3030 for (i = 0; i < rclk->num_parents; i++) { 3185 - parent = pf->dplls.inputs[rclk->parent_idx[i]].pin; 3186 - if (!parent) 3031 + parent = &pf->dplls.inputs[rclk->parent_idx[i]]; 3032 + if (IS_ERR_OR_NULL(parent->pin)) 3187 3033 continue; 3188 - dpll_pin_on_pin_unregister(parent, rclk->pin, 3034 + dpll_pin_on_pin_unregister(parent->pin, rclk->pin, 3189 3035 &ice_dpll_rclk_ops, rclk); 3190 3036 } 3191 3037 if (WARN_ON_ONCE(!vsi || !vsi->netdev)) 3192 3038 return; 3193 3039 dpll_netdev_pin_clear(vsi->netdev); 3194 - dpll_pin_put(rclk->pin); 3040 + dpll_pin_put(rclk->pin, &rclk->tracker); 3041 + } 3042 + 3043 + static bool ice_dpll_is_fwnode_pin(struct ice_dpll_pin *pin) 3044 + { 3045 + return !IS_ERR_OR_NULL(pin->fwnode); 3046 + } 3047 + 3048 + static void ice_dpll_pin_notify_work(struct work_struct *work) 3049 + { 3050 + struct ice_dpll_pin_work *w = container_of(work, 3051 + struct ice_dpll_pin_work, 3052 + work); 3053 + struct ice_dpll_pin *pin, *parent = w->pin; 3054 + struct ice_pf *pf = parent->pf; 3055 + int ret; 3056 + 3057 + wait_for_completion(&pf->dplls.dpll_init); 3058 + if (!test_bit(ICE_FLAG_DPLL, pf->flags)) 3059 + goto out; /* DPLL initialization failed */ 3060 + 3061 + switch (w->action) { 3062 + case DPLL_PIN_CREATED: 3063 + if (!IS_ERR_OR_NULL(parent->pin)) { 3064 + /* We have already our pin registered */ 3065 + goto out; 3066 + } 3067 + 3068 + /* Grab reference on fwnode pin */ 3069 + parent->pin = fwnode_dpll_pin_find(parent->fwnode, 3070 + &parent->tracker); 3071 + if (IS_ERR_OR_NULL(parent->pin)) { 3072 + dev_err(ice_pf_to_dev(pf), 3073 + "Cannot get fwnode pin reference\n"); 3074 + goto out; 3075 + } 3076 + 3077 + /* Register rclk pin */ 3078 + pin = &pf->dplls.rclk; 3079 + ret = dpll_pin_on_pin_register(parent->pin, pin->pin, 3080 + &ice_dpll_rclk_ops, pin); 3081 + if (ret) { 3082 + dev_err(ice_pf_to_dev(pf), 3083 + "Failed to register pin: %pe\n", ERR_PTR(ret)); 3084 + dpll_pin_put(parent->pin, &parent->tracker); 3085 + parent->pin = NULL; 3086 + goto out; 3087 + } 3088 + break; 3089 + case DPLL_PIN_DELETED: 3090 + if (IS_ERR_OR_NULL(parent->pin)) { 3091 + /* We have already our pin unregistered */ 3092 + goto out; 3093 + } 3094 + 3095 + /* Unregister rclk pin */ 3096 + pin = &pf->dplls.rclk; 3097 + dpll_pin_on_pin_unregister(parent->pin, pin->pin, 3098 + &ice_dpll_rclk_ops, pin); 3099 + 3100 + /* Drop fwnode pin reference */ 3101 + dpll_pin_put(parent->pin, &parent->tracker); 3102 + parent->pin = NULL; 3103 + break; 3104 + default: 3105 + break; 3106 + } 3107 + out: 3108 + kfree(w); 3109 + } 3110 + 3111 + static int ice_dpll_pin_notify(struct notifier_block *nb, unsigned long action, 3112 + void *data) 3113 + { 3114 + struct ice_dpll_pin *pin = container_of(nb, struct ice_dpll_pin, nb); 3115 + struct dpll_pin_notifier_info *info = data; 3116 + struct ice_dpll_pin_work *work; 3117 + 3118 + if (action != DPLL_PIN_CREATED && action != DPLL_PIN_DELETED) 3119 + return NOTIFY_DONE; 3120 + 3121 + /* Check if the reported pin is this one */ 3122 + if (pin->fwnode != info->fwnode) 3123 + return NOTIFY_DONE; /* Not this pin */ 3124 + 3125 + work = kzalloc(sizeof(*work), GFP_KERNEL); 3126 + if (!work) 3127 + return NOTIFY_DONE; 3128 + 3129 + INIT_WORK(&work->work, ice_dpll_pin_notify_work); 3130 + work->action = action; 3131 + work->pin = pin; 3132 + 3133 + queue_work(pin->pf->dplls.wq, &work->work); 3134 + 3135 + return NOTIFY_OK; 3195 3136 } 3196 3137 3197 3138 /** 3198 - * ice_dpll_init_rclk_pins - initialize recovered clock pin 3139 + * ice_dpll_init_pin_common - initialize pin 3199 3140 * @pf: board private structure 3200 3141 * @pin: pin to register 3201 3142 * @start_idx: on which index shall allocation start in dpll subsystem 3202 3143 * @ops: callback ops registered with the pins 3203 3144 * 3204 - * Allocate resource for recovered clock pin in dpll subsystem. Register the 3205 - * pin with the parents it has in the info. Register pin with the pf's main vsi 3206 - * netdev. 3145 + * Allocate resource for given pin in dpll subsystem. Register the pin with 3146 + * the parents it has in the info. 3207 3147 * 3208 3148 * Return: 3209 3149 * * 0 - success 3210 3150 * * negative - registration failure reason 3211 3151 */ 3212 3152 static int 3213 - ice_dpll_init_rclk_pins(struct ice_pf *pf, struct ice_dpll_pin *pin, 3214 - int start_idx, const struct dpll_pin_ops *ops) 3153 + ice_dpll_init_pin_common(struct ice_pf *pf, struct ice_dpll_pin *pin, 3154 + int start_idx, const struct dpll_pin_ops *ops) 3215 3155 { 3216 - struct ice_vsi *vsi = ice_get_main_vsi(pf); 3217 - struct dpll_pin *parent; 3156 + struct ice_dpll_pin *parent; 3218 3157 int ret, i; 3219 3158 3220 - if (WARN_ON((!vsi || !vsi->netdev))) 3221 - return -EINVAL; 3222 - ret = ice_dpll_get_pins(pf, pin, start_idx, ICE_DPLL_RCLK_NUM_PER_PF, 3223 - pf->dplls.clock_id); 3159 + ret = ice_dpll_get_pins(pf, pin, start_idx, 1, pf->dplls.clock_id); 3224 3160 if (ret) 3225 3161 return ret; 3226 - for (i = 0; i < pf->dplls.rclk.num_parents; i++) { 3227 - parent = pf->dplls.inputs[pf->dplls.rclk.parent_idx[i]].pin; 3228 - if (!parent) { 3229 - ret = -ENODEV; 3230 - goto unregister_pins; 3162 + 3163 + for (i = 0; i < pin->num_parents; i++) { 3164 + parent = &pf->dplls.inputs[pin->parent_idx[i]]; 3165 + if (IS_ERR_OR_NULL(parent->pin)) { 3166 + if (!ice_dpll_is_fwnode_pin(parent)) { 3167 + ret = -ENODEV; 3168 + goto unregister_pins; 3169 + } 3170 + parent->pin = fwnode_dpll_pin_find(parent->fwnode, 3171 + &parent->tracker); 3172 + if (IS_ERR_OR_NULL(parent->pin)) { 3173 + dev_info(ice_pf_to_dev(pf), 3174 + "Mux pin not registered yet\n"); 3175 + continue; 3176 + } 3231 3177 } 3232 - ret = dpll_pin_on_pin_register(parent, pf->dplls.rclk.pin, 3233 - ops, &pf->dplls.rclk); 3178 + ret = dpll_pin_on_pin_register(parent->pin, pin->pin, ops, pin); 3234 3179 if (ret) 3235 3180 goto unregister_pins; 3236 3181 } 3237 - dpll_netdev_pin_set(vsi->netdev, pf->dplls.rclk.pin); 3238 3182 3239 3183 return 0; 3240 3184 3241 3185 unregister_pins: 3242 3186 while (i) { 3243 - parent = pf->dplls.inputs[pf->dplls.rclk.parent_idx[--i]].pin; 3244 - dpll_pin_on_pin_unregister(parent, pf->dplls.rclk.pin, 3245 - &ice_dpll_rclk_ops, &pf->dplls.rclk); 3187 + parent = &pf->dplls.inputs[pin->parent_idx[--i]]; 3188 + if (IS_ERR_OR_NULL(parent->pin)) 3189 + continue; 3190 + dpll_pin_on_pin_unregister(parent->pin, pin->pin, ops, pin); 3246 3191 } 3247 - ice_dpll_release_pins(pin, ICE_DPLL_RCLK_NUM_PER_PF); 3192 + ice_dpll_release_pins(pin, 1); 3193 + 3248 3194 return ret; 3195 + } 3196 + 3197 + /** 3198 + * ice_dpll_init_rclk_pin - initialize recovered clock pin 3199 + * @pf: board private structure 3200 + * @start_idx: on which index shall allocation start in dpll subsystem 3201 + * @ops: callback ops registered with the pins 3202 + * 3203 + * Allocate resource for recovered clock pin in dpll subsystem. Register the 3204 + * pin with the parents it has in the info. 3205 + * 3206 + * Return: 3207 + * * 0 - success 3208 + * * negative - registration failure reason 3209 + */ 3210 + static int 3211 + ice_dpll_init_rclk_pin(struct ice_pf *pf, int start_idx, 3212 + const struct dpll_pin_ops *ops) 3213 + { 3214 + struct ice_vsi *vsi = ice_get_main_vsi(pf); 3215 + int ret; 3216 + 3217 + ret = ice_dpll_init_pin_common(pf, &pf->dplls.rclk, start_idx, ops); 3218 + if (ret) 3219 + return ret; 3220 + 3221 + dpll_netdev_pin_set(vsi->netdev, pf->dplls.rclk.pin); 3222 + 3223 + return 0; 3224 + } 3225 + 3226 + static void 3227 + ice_dpll_deinit_fwnode_pin(struct ice_dpll_pin *pin) 3228 + { 3229 + unregister_dpll_notifier(&pin->nb); 3230 + flush_workqueue(pin->pf->dplls.wq); 3231 + if (!IS_ERR_OR_NULL(pin->pin)) { 3232 + dpll_pin_put(pin->pin, &pin->tracker); 3233 + pin->pin = NULL; 3234 + } 3235 + fwnode_handle_put(pin->fwnode); 3236 + pin->fwnode = NULL; 3237 + } 3238 + 3239 + static void 3240 + ice_dpll_deinit_fwnode_pins(struct ice_pf *pf, struct ice_dpll_pin *pins, 3241 + int start_idx) 3242 + { 3243 + int i; 3244 + 3245 + for (i = 0; i < pf->dplls.rclk.num_parents; i++) 3246 + ice_dpll_deinit_fwnode_pin(&pins[start_idx + i]); 3247 + destroy_workqueue(pf->dplls.wq); 3249 3248 } 3250 3249 3251 3250 /** ··· 3420 3113 struct ice_dpll *dp = &d->pps; 3421 3114 3422 3115 ice_dpll_deinit_rclk_pin(pf); 3116 + if (pf->hw.mac_type == ICE_MAC_GENERIC_3K_E825) 3117 + ice_dpll_deinit_fwnode_pins(pf, pf->dplls.inputs, 0); 3423 3118 if (cgu) { 3424 3119 ice_dpll_unregister_pins(dp->dpll, inputs, &ice_dpll_input_ops, 3425 3120 num_inputs); ··· 3436 3127 &ice_dpll_output_ops, num_outputs); 3437 3128 ice_dpll_release_pins(outputs, num_outputs); 3438 3129 if (!pf->dplls.generic) { 3439 - ice_dpll_deinit_direct_pins(cgu, pf->dplls.ufl, 3130 + ice_dpll_deinit_direct_pins(pf, cgu, pf->dplls.ufl, 3440 3131 ICE_DPLL_PIN_SW_NUM, 3441 3132 &ice_dpll_pin_ufl_ops, 3442 3133 pf->dplls.pps.dpll, 3443 3134 pf->dplls.eec.dpll); 3444 - ice_dpll_deinit_direct_pins(cgu, pf->dplls.sma, 3135 + ice_dpll_deinit_direct_pins(pf, cgu, pf->dplls.sma, 3445 3136 ICE_DPLL_PIN_SW_NUM, 3446 3137 &ice_dpll_pin_sma_ops, 3447 3138 pf->dplls.pps.dpll, 3448 3139 pf->dplls.eec.dpll); 3449 3140 } 3450 3141 } 3142 + } 3143 + 3144 + static struct fwnode_handle * 3145 + ice_dpll_pin_node_get(struct ice_pf *pf, const char *name) 3146 + { 3147 + struct fwnode_handle *fwnode = dev_fwnode(ice_pf_to_dev(pf)); 3148 + int index; 3149 + 3150 + index = fwnode_property_match_string(fwnode, "dpll-pin-names", name); 3151 + if (index < 0) 3152 + return ERR_PTR(-ENOENT); 3153 + 3154 + return fwnode_find_reference(fwnode, "dpll-pins", index); 3155 + } 3156 + 3157 + static int 3158 + ice_dpll_init_fwnode_pin(struct ice_dpll_pin *pin, const char *name) 3159 + { 3160 + struct ice_pf *pf = pin->pf; 3161 + int ret; 3162 + 3163 + pin->fwnode = ice_dpll_pin_node_get(pf, name); 3164 + if (IS_ERR(pin->fwnode)) { 3165 + dev_err(ice_pf_to_dev(pf), 3166 + "Failed to find %s firmware node: %pe\n", name, 3167 + pin->fwnode); 3168 + pin->fwnode = NULL; 3169 + return -ENODEV; 3170 + } 3171 + 3172 + dev_dbg(ice_pf_to_dev(pf), "Found fwnode node for %s\n", name); 3173 + 3174 + pin->pin = fwnode_dpll_pin_find(pin->fwnode, &pin->tracker); 3175 + if (IS_ERR_OR_NULL(pin->pin)) { 3176 + dev_info(ice_pf_to_dev(pf), 3177 + "DPLL pin for %pfwp not registered yet\n", 3178 + pin->fwnode); 3179 + pin->pin = NULL; 3180 + } 3181 + 3182 + pin->nb.notifier_call = ice_dpll_pin_notify; 3183 + ret = register_dpll_notifier(&pin->nb); 3184 + if (ret) { 3185 + dev_err(ice_pf_to_dev(pf), 3186 + "Failed to subscribe for DPLL notifications\n"); 3187 + 3188 + if (!IS_ERR_OR_NULL(pin->pin)) { 3189 + dpll_pin_put(pin->pin, &pin->tracker); 3190 + pin->pin = NULL; 3191 + } 3192 + fwnode_handle_put(pin->fwnode); 3193 + pin->fwnode = NULL; 3194 + 3195 + return ret; 3196 + } 3197 + 3198 + return ret; 3199 + } 3200 + 3201 + /** 3202 + * ice_dpll_init_fwnode_pins - initialize pins from device tree 3203 + * @pf: board private structure 3204 + * @pins: pointer to pins array 3205 + * @start_idx: starting index for pins 3206 + * @count: number of pins to initialize 3207 + * 3208 + * Initialize input pins for E825 RCLK support. The parent pins (rclk0, rclk1) 3209 + * are expected to be defined by the system firmware (ACPI). This function 3210 + * allocates them in the dpll subsystem and stores their indices for later 3211 + * registration with the rclk pin. 3212 + * 3213 + * Return: 3214 + * * 0 - success 3215 + * * negative - initialization failure reason 3216 + */ 3217 + static int 3218 + ice_dpll_init_fwnode_pins(struct ice_pf *pf, struct ice_dpll_pin *pins, 3219 + int start_idx) 3220 + { 3221 + char pin_name[8]; 3222 + int i, ret; 3223 + 3224 + pf->dplls.wq = create_singlethread_workqueue("ice_dpll_wq"); 3225 + if (!pf->dplls.wq) 3226 + return -ENOMEM; 3227 + 3228 + for (i = 0; i < pf->dplls.rclk.num_parents; i++) { 3229 + pins[start_idx + i].pf = pf; 3230 + snprintf(pin_name, sizeof(pin_name), "rclk%u", i); 3231 + ret = ice_dpll_init_fwnode_pin(&pins[start_idx + i], pin_name); 3232 + if (ret) 3233 + goto error; 3234 + } 3235 + 3236 + return 0; 3237 + error: 3238 + while (i--) 3239 + ice_dpll_deinit_fwnode_pin(&pins[start_idx + i]); 3240 + 3241 + destroy_workqueue(pf->dplls.wq); 3242 + 3243 + return ret; 3244 + } 3245 + 3246 + /** 3247 + * ice_dpll_init_pins_e825 - init pins and register pins with a dplls 3248 + * @pf: board private structure 3249 + * @cgu: if cgu is present and controlled by this NIC 3250 + * 3251 + * Initialize directly connected pf's pins within pf's dplls in a Linux dpll 3252 + * subsystem. 3253 + * 3254 + * Return: 3255 + * * 0 - success 3256 + * * negative - initialization failure reason 3257 + */ 3258 + static int ice_dpll_init_pins_e825(struct ice_pf *pf) 3259 + { 3260 + int ret; 3261 + 3262 + ret = ice_dpll_init_fwnode_pins(pf, pf->dplls.inputs, 0); 3263 + if (ret) 3264 + return ret; 3265 + 3266 + ret = ice_dpll_init_rclk_pin(pf, DPLL_PIN_IDX_UNSPEC, 3267 + &ice_dpll_rclk_ops); 3268 + if (ret) { 3269 + /* Inform DPLL notifier works that DPLL init was finished 3270 + * unsuccessfully (ICE_DPLL_FLAG not set). 3271 + */ 3272 + complete_all(&pf->dplls.dpll_init); 3273 + ice_dpll_deinit_fwnode_pins(pf, pf->dplls.inputs, 0); 3274 + } 3275 + 3276 + return ret; 3451 3277 } 3452 3278 3453 3279 /** ··· 3599 3155 */ 3600 3156 static int ice_dpll_init_pins(struct ice_pf *pf, bool cgu) 3601 3157 { 3158 + const struct dpll_pin_ops *output_ops; 3159 + const struct dpll_pin_ops *input_ops; 3602 3160 int ret, count; 3603 3161 3162 + input_ops = &ice_dpll_input_ops; 3163 + output_ops = &ice_dpll_output_ops; 3164 + 3604 3165 ret = ice_dpll_init_direct_pins(pf, cgu, pf->dplls.inputs, 0, 3605 - pf->dplls.num_inputs, 3606 - &ice_dpll_input_ops, 3607 - pf->dplls.eec.dpll, pf->dplls.pps.dpll); 3166 + pf->dplls.num_inputs, input_ops, 3167 + pf->dplls.eec.dpll, 3168 + pf->dplls.pps.dpll); 3608 3169 if (ret) 3609 3170 return ret; 3610 3171 count = pf->dplls.num_inputs; 3611 3172 if (cgu) { 3612 3173 ret = ice_dpll_init_direct_pins(pf, cgu, pf->dplls.outputs, 3613 - count, 3614 - pf->dplls.num_outputs, 3615 - &ice_dpll_output_ops, 3616 - pf->dplls.eec.dpll, 3174 + count, pf->dplls.num_outputs, 3175 + output_ops, pf->dplls.eec.dpll, 3617 3176 pf->dplls.pps.dpll); 3618 3177 if (ret) 3619 3178 goto deinit_inputs; ··· 3652 3205 } else { 3653 3206 count += pf->dplls.num_outputs + 2 * ICE_DPLL_PIN_SW_NUM; 3654 3207 } 3655 - ret = ice_dpll_init_rclk_pins(pf, &pf->dplls.rclk, count + pf->hw.pf_id, 3656 - &ice_dpll_rclk_ops); 3208 + 3209 + ret = ice_dpll_init_rclk_pin(pf, count + pf->ptp.port.port_num, 3210 + &ice_dpll_rclk_ops); 3657 3211 if (ret) 3658 3212 goto deinit_ufl; 3659 3213 3660 3214 return 0; 3661 3215 deinit_ufl: 3662 - ice_dpll_deinit_direct_pins(cgu, pf->dplls.ufl, 3663 - ICE_DPLL_PIN_SW_NUM, 3664 - &ice_dpll_pin_ufl_ops, 3665 - pf->dplls.pps.dpll, pf->dplls.eec.dpll); 3216 + ice_dpll_deinit_direct_pins(pf, cgu, pf->dplls.ufl, ICE_DPLL_PIN_SW_NUM, 3217 + &ice_dpll_pin_ufl_ops, pf->dplls.pps.dpll, 3218 + pf->dplls.eec.dpll); 3666 3219 deinit_sma: 3667 - ice_dpll_deinit_direct_pins(cgu, pf->dplls.sma, 3668 - ICE_DPLL_PIN_SW_NUM, 3669 - &ice_dpll_pin_sma_ops, 3670 - pf->dplls.pps.dpll, pf->dplls.eec.dpll); 3220 + ice_dpll_deinit_direct_pins(pf, cgu, pf->dplls.sma, ICE_DPLL_PIN_SW_NUM, 3221 + &ice_dpll_pin_sma_ops, pf->dplls.pps.dpll, 3222 + pf->dplls.eec.dpll); 3671 3223 deinit_outputs: 3672 - ice_dpll_deinit_direct_pins(cgu, pf->dplls.outputs, 3224 + ice_dpll_deinit_direct_pins(pf, cgu, pf->dplls.outputs, 3673 3225 pf->dplls.num_outputs, 3674 - &ice_dpll_output_ops, pf->dplls.pps.dpll, 3226 + output_ops, pf->dplls.pps.dpll, 3675 3227 pf->dplls.eec.dpll); 3676 3228 deinit_inputs: 3677 - ice_dpll_deinit_direct_pins(cgu, pf->dplls.inputs, pf->dplls.num_inputs, 3678 - &ice_dpll_input_ops, pf->dplls.pps.dpll, 3229 + ice_dpll_deinit_direct_pins(pf, cgu, pf->dplls.inputs, 3230 + pf->dplls.num_inputs, 3231 + input_ops, pf->dplls.pps.dpll, 3679 3232 pf->dplls.eec.dpll); 3680 3233 return ret; 3681 3234 } ··· 3686 3239 * @d: pointer to ice_dpll 3687 3240 * @cgu: if cgu is present and controlled by this NIC 3688 3241 * 3689 - * If cgu is owned unregister the dpll from dpll subsystem. 3690 - * Release resources of dpll device from dpll subsystem. 3242 + * If cgu is owned, unregister the DPLL from DPLL subsystem. 3243 + * Release resources of DPLL device from DPLL subsystem. 3691 3244 */ 3692 3245 static void 3693 3246 ice_dpll_deinit_dpll(struct ice_pf *pf, struct ice_dpll *d, bool cgu) 3694 3247 { 3695 3248 if (cgu) 3696 3249 dpll_device_unregister(d->dpll, d->ops, d); 3697 - dpll_device_put(d->dpll); 3250 + dpll_device_put(d->dpll, &d->tracker); 3698 3251 } 3699 3252 3700 3253 /** ··· 3704 3257 * @cgu: if cgu is present and controlled by this NIC 3705 3258 * @type: type of dpll being initialized 3706 3259 * 3707 - * Allocate dpll instance for this board in dpll subsystem, if cgu is controlled 3708 - * by this NIC, register dpll with the callback ops. 3260 + * Allocate DPLL instance for this board in dpll subsystem, if cgu is controlled 3261 + * by this NIC, register DPLL with the callback ops. 3709 3262 * 3710 3263 * Return: 3711 3264 * * 0 - success ··· 3718 3271 u64 clock_id = pf->dplls.clock_id; 3719 3272 int ret; 3720 3273 3721 - d->dpll = dpll_device_get(clock_id, d->dpll_idx, THIS_MODULE); 3274 + d->dpll = dpll_device_get(clock_id, d->dpll_idx, THIS_MODULE, 3275 + &d->tracker); 3722 3276 if (IS_ERR(d->dpll)) { 3723 3277 ret = PTR_ERR(d->dpll); 3724 3278 dev_err(ice_pf_to_dev(pf), ··· 3735 3287 ice_dpll_update_state(pf, d, true); 3736 3288 ret = dpll_device_register(d->dpll, type, ops, d); 3737 3289 if (ret) { 3738 - dpll_device_put(d->dpll); 3290 + dpll_device_put(d->dpll, &d->tracker); 3291 + d->dpll = NULL; 3739 3292 return ret; 3740 3293 } 3741 3294 d->ops = ops; ··· 3955 3506 } 3956 3507 3957 3508 /** 3509 + * ice_dpll_init_info_pin_on_pin_e825c - initializes rclk pin information 3510 + * @pf: board private structure 3511 + * 3512 + * Init information for rclk pin, cache them in pf->dplls.rclk. 3513 + * 3514 + * Return: 3515 + * * 0 - success 3516 + */ 3517 + static int ice_dpll_init_info_pin_on_pin_e825c(struct ice_pf *pf) 3518 + { 3519 + struct ice_dpll_pin *rclk_pin = &pf->dplls.rclk; 3520 + 3521 + rclk_pin->prop.type = DPLL_PIN_TYPE_SYNCE_ETH_PORT; 3522 + rclk_pin->prop.capabilities |= DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE; 3523 + rclk_pin->pf = pf; 3524 + 3525 + return 0; 3526 + } 3527 + 3528 + /** 3958 3529 * ice_dpll_init_info_rclk_pin - initializes rclk pin information 3959 3530 * @pf: board private structure 3960 3531 * ··· 4100 3631 case ICE_DPLL_PIN_TYPE_OUTPUT: 4101 3632 return ice_dpll_init_info_direct_pins(pf, pin_type); 4102 3633 case ICE_DPLL_PIN_TYPE_RCLK_INPUT: 4103 - return ice_dpll_init_info_rclk_pin(pf); 3634 + if (pf->hw.mac_type == ICE_MAC_GENERIC_3K_E825) 3635 + return ice_dpll_init_info_pin_on_pin_e825c(pf); 3636 + else 3637 + return ice_dpll_init_info_rclk_pin(pf); 4104 3638 case ICE_DPLL_PIN_TYPE_SOFTWARE: 4105 3639 return ice_dpll_init_info_sw_pins(pf); 4106 3640 default: ··· 4123 3651 kfree(pf->dplls.outputs); 4124 3652 kfree(pf->dplls.eec.input_prio); 4125 3653 kfree(pf->dplls.pps.input_prio); 3654 + } 3655 + 3656 + /** 3657 + * ice_dpll_init_info_e825c - prepare pf's dpll information structure for e825c 3658 + * device 3659 + * @pf: board private structure 3660 + * 3661 + * Acquire (from HW) and set basic DPLL information (on pf->dplls struct). 3662 + * 3663 + * Return: 3664 + * * 0 - success 3665 + * * negative - init failure reason 3666 + */ 3667 + static int ice_dpll_init_info_e825c(struct ice_pf *pf) 3668 + { 3669 + struct ice_dplls *d = &pf->dplls; 3670 + int ret = 0; 3671 + int i; 3672 + 3673 + d->clock_id = ice_generate_clock_id(pf); 3674 + d->num_inputs = ICE_SYNCE_CLK_NUM; 3675 + 3676 + d->inputs = kcalloc(d->num_inputs, sizeof(*d->inputs), GFP_KERNEL); 3677 + if (!d->inputs) 3678 + return -ENOMEM; 3679 + 3680 + ret = ice_get_cgu_rclk_pin_info(&pf->hw, &d->base_rclk_idx, 3681 + &pf->dplls.rclk.num_parents); 3682 + if (ret) 3683 + goto deinit_info; 3684 + 3685 + for (i = 0; i < pf->dplls.rclk.num_parents; i++) 3686 + pf->dplls.rclk.parent_idx[i] = d->base_rclk_idx + i; 3687 + 3688 + ret = ice_dpll_init_pins_info(pf, ICE_DPLL_PIN_TYPE_RCLK_INPUT); 3689 + if (ret) 3690 + goto deinit_info; 3691 + dev_dbg(ice_pf_to_dev(pf), 3692 + "%s - success, inputs: %u, outputs: %u, rclk-parents: %u\n", 3693 + __func__, d->num_inputs, d->num_outputs, d->rclk.num_parents); 3694 + return 0; 3695 + deinit_info: 3696 + ice_dpll_deinit_info(pf); 3697 + return ret; 4126 3698 } 4127 3699 4128 3700 /** ··· 4288 3772 ice_dpll_deinit_worker(pf); 4289 3773 4290 3774 ice_dpll_deinit_pins(pf, cgu); 4291 - ice_dpll_deinit_dpll(pf, &pf->dplls.pps, cgu); 4292 - ice_dpll_deinit_dpll(pf, &pf->dplls.eec, cgu); 3775 + if (!IS_ERR_OR_NULL(pf->dplls.pps.dpll)) 3776 + ice_dpll_deinit_dpll(pf, &pf->dplls.pps, cgu); 3777 + if (!IS_ERR_OR_NULL(pf->dplls.eec.dpll)) 3778 + ice_dpll_deinit_dpll(pf, &pf->dplls.eec, cgu); 4293 3779 ice_dpll_deinit_info(pf); 4294 3780 mutex_destroy(&pf->dplls.lock); 4295 3781 } 4296 3782 4297 3783 /** 4298 - * ice_dpll_init - initialize support for dpll subsystem 3784 + * ice_dpll_init_e825 - initialize support for dpll subsystem 4299 3785 * @pf: board private structure 4300 3786 * 4301 3787 * Set up the device dplls, register them and pins connected within Linux dpll ··· 4306 3788 * 4307 3789 * Context: Initializes pf->dplls.lock mutex. 4308 3790 */ 4309 - void ice_dpll_init(struct ice_pf *pf) 3791 + static void ice_dpll_init_e825(struct ice_pf *pf) 3792 + { 3793 + struct ice_dplls *d = &pf->dplls; 3794 + int err; 3795 + 3796 + mutex_init(&d->lock); 3797 + init_completion(&d->dpll_init); 3798 + 3799 + err = ice_dpll_init_info_e825c(pf); 3800 + if (err) 3801 + goto err_exit; 3802 + err = ice_dpll_init_pins_e825(pf); 3803 + if (err) 3804 + goto deinit_info; 3805 + set_bit(ICE_FLAG_DPLL, pf->flags); 3806 + complete_all(&d->dpll_init); 3807 + 3808 + return; 3809 + 3810 + deinit_info: 3811 + ice_dpll_deinit_info(pf); 3812 + err_exit: 3813 + mutex_destroy(&d->lock); 3814 + dev_warn(ice_pf_to_dev(pf), "DPLLs init failure err:%d\n", err); 3815 + } 3816 + 3817 + /** 3818 + * ice_dpll_init_e810 - initialize support for dpll subsystem 3819 + * @pf: board private structure 3820 + * 3821 + * Set up the device dplls, register them and pins connected within Linux dpll 3822 + * subsystem. Allow userspace to obtain state of DPLL and handling of DPLL 3823 + * configuration requests. 3824 + * 3825 + * Context: Initializes pf->dplls.lock mutex. 3826 + */ 3827 + static void ice_dpll_init_e810(struct ice_pf *pf) 4310 3828 { 4311 3829 bool cgu = ice_is_feature_supported(pf, ICE_F_CGU); 4312 3830 struct ice_dplls *d = &pf->dplls; ··· 4381 3827 err_exit: 4382 3828 mutex_destroy(&d->lock); 4383 3829 dev_warn(ice_pf_to_dev(pf), "DPLLs init failure err:%d\n", err); 3830 + } 3831 + 3832 + void ice_dpll_init(struct ice_pf *pf) 3833 + { 3834 + switch (pf->hw.mac_type) { 3835 + case ICE_MAC_GENERIC_3K_E825: 3836 + ice_dpll_init_e825(pf); 3837 + break; 3838 + default: 3839 + ice_dpll_init_e810(pf); 3840 + break; 3841 + } 4384 3842 }
+30
drivers/net/ethernet/intel/ice/ice_dpll.h
··· 20 20 ICE_DPLL_PIN_SW_NUM 21 21 }; 22 22 23 + struct ice_dpll_pin_work { 24 + struct work_struct work; 25 + unsigned long action; 26 + struct ice_dpll_pin *pin; 27 + }; 28 + 23 29 /** ice_dpll_pin - store info about pins 24 30 * @pin: dpll pin structure 25 31 * @pf: pointer to pf, which has registered the dpll_pin 32 + * @tracker: reference count tracker 26 33 * @idx: ice pin private idx 27 34 * @num_parents: hols number of parent pins 28 35 * @parent_idx: hold indexes of parent pins ··· 44 37 struct ice_dpll_pin { 45 38 struct dpll_pin *pin; 46 39 struct ice_pf *pf; 40 + dpll_tracker tracker; 41 + struct fwnode_handle *fwnode; 42 + struct notifier_block nb; 47 43 u8 idx; 48 44 u8 num_parents; 49 45 u8 parent_idx[ICE_DPLL_RCLK_NUM_MAX]; ··· 68 58 /** ice_dpll - store info required for DPLL control 69 59 * @dpll: pointer to dpll dev 70 60 * @pf: pointer to pf, which has registered the dpll_device 61 + * @tracker: reference count tracker 71 62 * @dpll_idx: index of dpll on the NIC 72 63 * @input_idx: currently selected input index 73 64 * @prev_input_idx: previously selected input index ··· 87 76 struct ice_dpll { 88 77 struct dpll_device *dpll; 89 78 struct ice_pf *pf; 79 + dpll_tracker tracker; 90 80 u8 dpll_idx; 91 81 u8 input_idx; 92 82 u8 prev_input_idx; ··· 126 114 struct ice_dplls { 127 115 struct kthread_worker *kworker; 128 116 struct kthread_delayed_work work; 117 + struct workqueue_struct *wq; 129 118 struct mutex lock; 119 + struct completion dpll_init; 130 120 struct ice_dpll eec; 131 121 struct ice_dpll pps; 132 122 struct ice_dpll_pin *inputs; ··· 157 143 #endif 158 144 159 145 #endif 146 + 147 + #define ICE_CGU_R10 0x28 148 + #define ICE_CGU_R10_SYNCE_CLKO_SEL GENMASK(8, 5) 149 + #define ICE_CGU_R10_SYNCE_CLKODIV_M1 GENMASK(13, 9) 150 + #define ICE_CGU_R10_SYNCE_CLKODIV_LOAD BIT(14) 151 + #define ICE_CGU_R10_SYNCE_DCK_RST BIT(15) 152 + #define ICE_CGU_R10_SYNCE_ETHCLKO_SEL GENMASK(18, 16) 153 + #define ICE_CGU_R10_SYNCE_ETHDIV_M1 GENMASK(23, 19) 154 + #define ICE_CGU_R10_SYNCE_ETHDIV_LOAD BIT(24) 155 + #define ICE_CGU_R10_SYNCE_DCK2_RST BIT(25) 156 + #define ICE_CGU_R10_SYNCE_S_REF_CLK GENMASK(31, 27) 157 + 158 + #define ICE_CGU_R11 0x2C 159 + #define ICE_CGU_R11_SYNCE_S_BYP_CLK GENMASK(6, 1) 160 + 161 + #define ICE_CGU_BYPASS_MUX_OFFSET_E825C 3
+3
drivers/net/ethernet/intel/ice/ice_lib.c
··· 3989 3989 break; 3990 3990 } 3991 3991 3992 + if (pf->hw.mac_type == ICE_MAC_GENERIC_3K_E825) 3993 + ice_set_feature_support(pf, ICE_F_PHY_RCLK); 3994 + 3992 3995 if (pf->hw.mac_type == ICE_MAC_E830) { 3993 3996 ice_set_feature_support(pf, ICE_F_MBX_LIMIT); 3994 3997 ice_set_feature_support(pf, ICE_F_GCS);
+32
drivers/net/ethernet/intel/ice/ice_ptp.c
··· 1341 1341 if (pf->hw.reset_ongoing) 1342 1342 return; 1343 1343 1344 + if (hw->mac_type == ICE_MAC_GENERIC_3K_E825) { 1345 + int pin, err; 1346 + 1347 + if (!test_bit(ICE_FLAG_DPLL, pf->flags)) 1348 + return; 1349 + 1350 + mutex_lock(&pf->dplls.lock); 1351 + for (pin = 0; pin < ICE_SYNCE_CLK_NUM; pin++) { 1352 + enum ice_synce_clk clk_pin; 1353 + bool active; 1354 + u8 port_num; 1355 + 1356 + port_num = ptp_port->port_num; 1357 + clk_pin = (enum ice_synce_clk)pin; 1358 + err = ice_tspll_bypass_mux_active_e825c(hw, 1359 + port_num, 1360 + &active, 1361 + clk_pin); 1362 + if (WARN_ON_ONCE(err)) { 1363 + mutex_unlock(&pf->dplls.lock); 1364 + return; 1365 + } 1366 + 1367 + err = ice_tspll_cfg_synce_ethdiv_e825c(hw, clk_pin); 1368 + if (active && WARN_ON_ONCE(err)) { 1369 + mutex_unlock(&pf->dplls.lock); 1370 + return; 1371 + } 1372 + } 1373 + mutex_unlock(&pf->dplls.lock); 1374 + } 1375 + 1344 1376 switch (hw->mac_type) { 1345 1377 case ICE_MAC_E810: 1346 1378 case ICE_MAC_E830:
+8 -1
drivers/net/ethernet/intel/ice/ice_ptp_hw.c
··· 5903 5903 *base_idx = SI_REF1P; 5904 5904 else 5905 5905 ret = -ENODEV; 5906 - 5906 + break; 5907 + case ICE_DEV_ID_E825C_BACKPLANE: 5908 + case ICE_DEV_ID_E825C_QSFP: 5909 + case ICE_DEV_ID_E825C_SFP: 5910 + case ICE_DEV_ID_E825C_SGMII: 5911 + *pin_num = ICE_SYNCE_CLK_NUM; 5912 + *base_idx = 0; 5913 + ret = 0; 5907 5914 break; 5908 5915 default: 5909 5916 ret = -ENODEV;
+217
drivers/net/ethernet/intel/ice/ice_tspll.c
··· 624 624 625 625 return err; 626 626 } 627 + 628 + /** 629 + * ice_tspll_bypass_mux_active_e825c - check if the given port is set active 630 + * @hw: Pointer to the HW struct 631 + * @port: Number of the port 632 + * @active: Output flag showing if port is active 633 + * @output: Output pin, we have two in E825C 634 + * 635 + * Check if given port is selected as recovered clock source for given output. 636 + * 637 + * Return: 638 + * * 0 - success 639 + * * negative - error 640 + */ 641 + int ice_tspll_bypass_mux_active_e825c(struct ice_hw *hw, u8 port, bool *active, 642 + enum ice_synce_clk output) 643 + { 644 + u8 active_clk; 645 + u32 val; 646 + int err; 647 + 648 + switch (output) { 649 + case ICE_SYNCE_CLK0: 650 + err = ice_read_cgu_reg(hw, ICE_CGU_R10, &val); 651 + if (err) 652 + return err; 653 + active_clk = FIELD_GET(ICE_CGU_R10_SYNCE_S_REF_CLK, val); 654 + break; 655 + case ICE_SYNCE_CLK1: 656 + err = ice_read_cgu_reg(hw, ICE_CGU_R11, &val); 657 + if (err) 658 + return err; 659 + active_clk = FIELD_GET(ICE_CGU_R11_SYNCE_S_BYP_CLK, val); 660 + break; 661 + default: 662 + return -EINVAL; 663 + } 664 + 665 + if (active_clk == port % hw->ptp.ports_per_phy + 666 + ICE_CGU_BYPASS_MUX_OFFSET_E825C) 667 + *active = true; 668 + else 669 + *active = false; 670 + 671 + return 0; 672 + } 673 + 674 + /** 675 + * ice_tspll_cfg_bypass_mux_e825c - configure reference clock mux 676 + * @hw: Pointer to the HW struct 677 + * @ena: true to enable the reference, false if disable 678 + * @port_num: Number of the port 679 + * @output: Output pin, we have two in E825C 680 + * 681 + * Set reference clock source and output clock selection. 682 + * 683 + * Context: Called under pf->dplls.lock 684 + * Return: 685 + * * 0 - success 686 + * * negative - error 687 + */ 688 + int ice_tspll_cfg_bypass_mux_e825c(struct ice_hw *hw, bool ena, u32 port_num, 689 + enum ice_synce_clk output) 690 + { 691 + u8 first_mux; 692 + int err; 693 + u32 r10; 694 + 695 + err = ice_read_cgu_reg(hw, ICE_CGU_R10, &r10); 696 + if (err) 697 + return err; 698 + 699 + if (!ena) 700 + first_mux = ICE_CGU_NET_REF_CLK0; 701 + else 702 + first_mux = port_num + ICE_CGU_BYPASS_MUX_OFFSET_E825C; 703 + 704 + r10 &= ~(ICE_CGU_R10_SYNCE_DCK_RST | ICE_CGU_R10_SYNCE_DCK2_RST); 705 + 706 + switch (output) { 707 + case ICE_SYNCE_CLK0: 708 + r10 &= ~(ICE_CGU_R10_SYNCE_ETHCLKO_SEL | 709 + ICE_CGU_R10_SYNCE_ETHDIV_LOAD | 710 + ICE_CGU_R10_SYNCE_S_REF_CLK); 711 + r10 |= FIELD_PREP(ICE_CGU_R10_SYNCE_S_REF_CLK, first_mux); 712 + r10 |= FIELD_PREP(ICE_CGU_R10_SYNCE_ETHCLKO_SEL, 713 + ICE_CGU_REF_CLK_BYP0_DIV); 714 + break; 715 + case ICE_SYNCE_CLK1: 716 + { 717 + u32 val; 718 + 719 + err = ice_read_cgu_reg(hw, ICE_CGU_R11, &val); 720 + if (err) 721 + return err; 722 + val &= ~ICE_CGU_R11_SYNCE_S_BYP_CLK; 723 + val |= FIELD_PREP(ICE_CGU_R11_SYNCE_S_BYP_CLK, first_mux); 724 + err = ice_write_cgu_reg(hw, ICE_CGU_R11, val); 725 + if (err) 726 + return err; 727 + r10 &= ~(ICE_CGU_R10_SYNCE_CLKODIV_LOAD | 728 + ICE_CGU_R10_SYNCE_CLKO_SEL); 729 + r10 |= FIELD_PREP(ICE_CGU_R10_SYNCE_CLKO_SEL, 730 + ICE_CGU_REF_CLK_BYP1_DIV); 731 + break; 732 + } 733 + default: 734 + return -EINVAL; 735 + } 736 + 737 + err = ice_write_cgu_reg(hw, ICE_CGU_R10, r10); 738 + if (err) 739 + return err; 740 + 741 + return 0; 742 + } 743 + 744 + /** 745 + * ice_tspll_get_div_e825c - get the divider for the given speed 746 + * @link_speed: link speed of the port 747 + * @divider: output value, calculated divider 748 + * 749 + * Get CGU divider value based on the link speed. 750 + * 751 + * Return: 752 + * * 0 - success 753 + * * negative - error 754 + */ 755 + static int ice_tspll_get_div_e825c(u16 link_speed, unsigned int *divider) 756 + { 757 + switch (link_speed) { 758 + case ICE_AQ_LINK_SPEED_100GB: 759 + case ICE_AQ_LINK_SPEED_50GB: 760 + case ICE_AQ_LINK_SPEED_25GB: 761 + *divider = 10; 762 + break; 763 + case ICE_AQ_LINK_SPEED_40GB: 764 + case ICE_AQ_LINK_SPEED_10GB: 765 + *divider = 4; 766 + break; 767 + case ICE_AQ_LINK_SPEED_5GB: 768 + case ICE_AQ_LINK_SPEED_2500MB: 769 + case ICE_AQ_LINK_SPEED_1000MB: 770 + *divider = 2; 771 + break; 772 + case ICE_AQ_LINK_SPEED_100MB: 773 + *divider = 1; 774 + break; 775 + default: 776 + return -EOPNOTSUPP; 777 + } 778 + 779 + return 0; 780 + } 781 + 782 + /** 783 + * ice_tspll_cfg_synce_ethdiv_e825c - set the divider on the mux 784 + * @hw: Pointer to the HW struct 785 + * @output: Output pin, we have two in E825C 786 + * 787 + * Set the correct CGU divider for RCLKA or RCLKB. 788 + * 789 + * Context: Called under pf->dplls.lock 790 + * Return: 791 + * * 0 - success 792 + * * negative - error 793 + */ 794 + int ice_tspll_cfg_synce_ethdiv_e825c(struct ice_hw *hw, 795 + enum ice_synce_clk output) 796 + { 797 + unsigned int divider; 798 + u16 link_speed; 799 + u32 val; 800 + int err; 801 + 802 + link_speed = hw->port_info->phy.link_info.link_speed; 803 + if (!link_speed) 804 + return 0; 805 + 806 + err = ice_tspll_get_div_e825c(link_speed, &divider); 807 + if (err) 808 + return err; 809 + 810 + err = ice_read_cgu_reg(hw, ICE_CGU_R10, &val); 811 + if (err) 812 + return err; 813 + 814 + /* programmable divider value (from 2 to 16) minus 1 for ETHCLKOUT */ 815 + switch (output) { 816 + case ICE_SYNCE_CLK0: 817 + val &= ~(ICE_CGU_R10_SYNCE_ETHDIV_M1 | 818 + ICE_CGU_R10_SYNCE_ETHDIV_LOAD); 819 + val |= FIELD_PREP(ICE_CGU_R10_SYNCE_ETHDIV_M1, divider - 1); 820 + err = ice_write_cgu_reg(hw, ICE_CGU_R10, val); 821 + if (err) 822 + return err; 823 + val |= ICE_CGU_R10_SYNCE_ETHDIV_LOAD; 824 + break; 825 + case ICE_SYNCE_CLK1: 826 + val &= ~(ICE_CGU_R10_SYNCE_CLKODIV_M1 | 827 + ICE_CGU_R10_SYNCE_CLKODIV_LOAD); 828 + val |= FIELD_PREP(ICE_CGU_R10_SYNCE_CLKODIV_M1, divider - 1); 829 + err = ice_write_cgu_reg(hw, ICE_CGU_R10, val); 830 + if (err) 831 + return err; 832 + val |= ICE_CGU_R10_SYNCE_CLKODIV_LOAD; 833 + break; 834 + default: 835 + return -EINVAL; 836 + } 837 + 838 + err = ice_write_cgu_reg(hw, ICE_CGU_R10, val); 839 + if (err) 840 + return err; 841 + 842 + return 0; 843 + }
+12 -1
drivers/net/ethernet/intel/ice/ice_tspll.h
··· 21 21 u32 frac_n_div; 22 22 }; 23 23 24 + #define ICE_CGU_NET_REF_CLK0 0x0 25 + #define ICE_CGU_REF_CLK_BYP0 0x5 26 + #define ICE_CGU_REF_CLK_BYP0_DIV 0x0 27 + #define ICE_CGU_REF_CLK_BYP1 0x4 28 + #define ICE_CGU_REF_CLK_BYP1_DIV 0x1 29 + 24 30 #define ICE_TSPLL_CK_REFCLKFREQ_E825 0x1F 25 31 #define ICE_TSPLL_NDIVRATIO_E825 5 26 32 #define ICE_TSPLL_FBDIV_INTGR_E825 256 27 33 28 34 int ice_tspll_cfg_pps_out_e825c(struct ice_hw *hw, bool enable); 29 35 int ice_tspll_init(struct ice_hw *hw); 30 - 36 + int ice_tspll_bypass_mux_active_e825c(struct ice_hw *hw, u8 port, bool *active, 37 + enum ice_synce_clk output); 38 + int ice_tspll_cfg_bypass_mux_e825c(struct ice_hw *hw, bool ena, u32 port_num, 39 + enum ice_synce_clk output); 40 + int ice_tspll_cfg_synce_ethdiv_e825c(struct ice_hw *hw, 41 + enum ice_synce_clk output); 31 42 #endif /* _ICE_TSPLL_H_ */
+6
drivers/net/ethernet/intel/ice/ice_type.h
··· 349 349 NUM_ICE_CLK_SRC 350 350 }; 351 351 352 + enum ice_synce_clk { 353 + ICE_SYNCE_CLK0, 354 + ICE_SYNCE_CLK1, 355 + ICE_SYNCE_CLK_NUM 356 + }; 357 + 352 358 struct ice_ts_func_info { 353 359 /* Function specific info */ 354 360 enum ice_tspll_freq time_ref;
+10 -6
drivers/net/ethernet/mellanox/mlx5/core/dpll.c
··· 9 9 */ 10 10 struct mlx5_dpll { 11 11 struct dpll_device *dpll; 12 + dpll_tracker dpll_tracker; 12 13 struct dpll_pin *dpll_pin; 14 + dpll_tracker pin_tracker; 13 15 struct mlx5_core_dev *mdev; 14 16 struct workqueue_struct *wq; 15 17 struct delayed_work work; ··· 440 438 auxiliary_set_drvdata(adev, mdpll); 441 439 442 440 /* Multiple mdev instances might share one DPLL device. */ 443 - mdpll->dpll = dpll_device_get(clock_id, 0, THIS_MODULE); 441 + mdpll->dpll = dpll_device_get(clock_id, 0, THIS_MODULE, 442 + &mdpll->dpll_tracker); 444 443 if (IS_ERR(mdpll->dpll)) { 445 444 err = PTR_ERR(mdpll->dpll); 446 445 goto err_free_mdpll; ··· 454 451 455 452 /* Multiple mdev instances might share one DPLL pin. */ 456 453 mdpll->dpll_pin = dpll_pin_get(clock_id, mlx5_get_dev_index(mdev), 457 - THIS_MODULE, &mlx5_dpll_pin_properties); 454 + THIS_MODULE, &mlx5_dpll_pin_properties, 455 + &mdpll->pin_tracker); 458 456 if (IS_ERR(mdpll->dpll_pin)) { 459 457 err = PTR_ERR(mdpll->dpll_pin); 460 458 goto err_unregister_dpll_device; ··· 483 479 dpll_pin_unregister(mdpll->dpll, mdpll->dpll_pin, 484 480 &mlx5_dpll_pins_ops, mdpll); 485 481 err_put_dpll_pin: 486 - dpll_pin_put(mdpll->dpll_pin); 482 + dpll_pin_put(mdpll->dpll_pin, &mdpll->pin_tracker); 487 483 err_unregister_dpll_device: 488 484 dpll_device_unregister(mdpll->dpll, &mlx5_dpll_device_ops, mdpll); 489 485 err_put_dpll_device: 490 - dpll_device_put(mdpll->dpll); 486 + dpll_device_put(mdpll->dpll, &mdpll->dpll_tracker); 491 487 err_free_mdpll: 492 488 kfree(mdpll); 493 489 return err; ··· 503 499 destroy_workqueue(mdpll->wq); 504 500 dpll_pin_unregister(mdpll->dpll, mdpll->dpll_pin, 505 501 &mlx5_dpll_pins_ops, mdpll); 506 - dpll_pin_put(mdpll->dpll_pin); 502 + dpll_pin_put(mdpll->dpll_pin, &mdpll->pin_tracker); 507 503 dpll_device_unregister(mdpll->dpll, &mlx5_dpll_device_ops, mdpll); 508 - dpll_device_put(mdpll->dpll); 504 + dpll_device_put(mdpll->dpll, &mdpll->dpll_tracker); 509 505 kfree(mdpll); 510 506 511 507 mlx5_dpll_synce_status_set(mdev,
+11 -7
drivers/ptp/ptp_ocp.c
··· 285 285 u8 default_fcn; 286 286 struct dpll_pin *dpll_pin; 287 287 struct dpll_pin_properties dpll_prop; 288 + dpll_tracker tracker; 288 289 }; 289 290 290 291 struct ocp_attr_group { ··· 384 383 struct ptp_ocp_sma_connector sma[OCP_SMA_NUM]; 385 384 const struct ocp_sma_op *sma_op; 386 385 struct dpll_device *dpll; 386 + dpll_tracker tracker; 387 387 int signals_nr; 388 388 int freq_in_nr; 389 389 }; ··· 4790 4788 devlink_register(devlink); 4791 4789 4792 4790 clkid = pci_get_dsn(pdev); 4793 - bp->dpll = dpll_device_get(clkid, 0, THIS_MODULE); 4791 + bp->dpll = dpll_device_get(clkid, 0, THIS_MODULE, &bp->tracker); 4794 4792 if (IS_ERR(bp->dpll)) { 4795 4793 err = PTR_ERR(bp->dpll); 4796 4794 dev_err(&pdev->dev, "dpll_device_alloc failed\n"); ··· 4802 4800 goto out; 4803 4801 4804 4802 for (i = 0; i < OCP_SMA_NUM; i++) { 4805 - bp->sma[i].dpll_pin = dpll_pin_get(clkid, i, THIS_MODULE, &bp->sma[i].dpll_prop); 4803 + bp->sma[i].dpll_pin = dpll_pin_get(clkid, i, THIS_MODULE, 4804 + &bp->sma[i].dpll_prop, 4805 + &bp->sma[i].tracker); 4806 4806 if (IS_ERR(bp->sma[i].dpll_pin)) { 4807 4807 err = PTR_ERR(bp->sma[i].dpll_pin); 4808 4808 goto out_dpll; ··· 4813 4809 err = dpll_pin_register(bp->dpll, bp->sma[i].dpll_pin, &dpll_pins_ops, 4814 4810 &bp->sma[i]); 4815 4811 if (err) { 4816 - dpll_pin_put(bp->sma[i].dpll_pin); 4812 + dpll_pin_put(bp->sma[i].dpll_pin, &bp->sma[i].tracker); 4817 4813 goto out_dpll; 4818 4814 } 4819 4815 } ··· 4823 4819 out_dpll: 4824 4820 while (i--) { 4825 4821 dpll_pin_unregister(bp->dpll, bp->sma[i].dpll_pin, &dpll_pins_ops, &bp->sma[i]); 4826 - dpll_pin_put(bp->sma[i].dpll_pin); 4822 + dpll_pin_put(bp->sma[i].dpll_pin, &bp->sma[i].tracker); 4827 4823 } 4828 - dpll_device_put(bp->dpll); 4824 + dpll_device_put(bp->dpll, &bp->tracker); 4829 4825 out: 4830 4826 ptp_ocp_detach(bp); 4831 4827 out_disable: ··· 4846 4842 for (i = 0; i < OCP_SMA_NUM; i++) { 4847 4843 if (bp->sma[i].dpll_pin) { 4848 4844 dpll_pin_unregister(bp->dpll, bp->sma[i].dpll_pin, &dpll_pins_ops, &bp->sma[i]); 4849 - dpll_pin_put(bp->sma[i].dpll_pin); 4845 + dpll_pin_put(bp->sma[i].dpll_pin, &bp->sma[i].tracker); 4850 4846 } 4851 4847 } 4852 4848 dpll_device_unregister(bp->dpll, &dpll_ops, bp); 4853 - dpll_device_put(bp->dpll); 4849 + dpll_device_put(bp->dpll, &bp->tracker); 4854 4850 devlink_unregister(devlink); 4855 4851 ptp_ocp_detach(bp); 4856 4852 pci_disable_device(pdev);
+55 -4
include/linux/dpll.h
··· 11 11 #include <linux/device.h> 12 12 #include <linux/netlink.h> 13 13 #include <linux/netdevice.h> 14 + #include <linux/notifier.h> 14 15 #include <linux/rtnetlink.h> 15 16 16 17 struct dpll_device; 17 18 struct dpll_pin; 18 19 struct dpll_pin_esync; 20 + struct fwnode_handle; 21 + struct ref_tracker; 19 22 20 23 struct dpll_device_ops { 21 24 int (*mode_get)(const struct dpll_device *dpll, void *dpll_priv, ··· 174 171 u32 phase_gran; 175 172 }; 176 173 174 + #ifdef CONFIG_DPLL_REFCNT_TRACKER 175 + typedef struct ref_tracker *dpll_tracker; 176 + #else 177 + typedef struct {} dpll_tracker; 178 + #endif 179 + 180 + #define DPLL_DEVICE_CREATED 1 181 + #define DPLL_DEVICE_DELETED 2 182 + #define DPLL_DEVICE_CHANGED 3 183 + #define DPLL_PIN_CREATED 4 184 + #define DPLL_PIN_DELETED 5 185 + #define DPLL_PIN_CHANGED 6 186 + 187 + struct dpll_device_notifier_info { 188 + struct dpll_device *dpll; 189 + u32 id; 190 + u32 idx; 191 + u64 clock_id; 192 + enum dpll_type type; 193 + }; 194 + 195 + struct dpll_pin_notifier_info { 196 + struct dpll_pin *pin; 197 + u32 id; 198 + u32 idx; 199 + u64 clock_id; 200 + const struct fwnode_handle *fwnode; 201 + const struct dpll_pin_properties *prop; 202 + }; 203 + 177 204 #if IS_ENABLED(CONFIG_DPLL) 178 205 void dpll_netdev_pin_set(struct net_device *dev, struct dpll_pin *dpll_pin); 179 206 void dpll_netdev_pin_clear(struct net_device *dev); ··· 211 178 size_t dpll_netdev_pin_handle_size(const struct net_device *dev); 212 179 int dpll_netdev_add_pin_handle(struct sk_buff *msg, 213 180 const struct net_device *dev); 181 + 182 + struct dpll_pin *fwnode_dpll_pin_find(struct fwnode_handle *fwnode, 183 + dpll_tracker *tracker); 214 184 #else 215 185 static inline void 216 186 dpll_netdev_pin_set(struct net_device *dev, struct dpll_pin *dpll_pin) { } ··· 229 193 { 230 194 return 0; 231 195 } 196 + 197 + static inline struct dpll_pin * 198 + fwnode_dpll_pin_find(struct fwnode_handle *fwnode, dpll_tracker *tracker) 199 + { 200 + return NULL; 201 + } 232 202 #endif 233 203 234 204 struct dpll_device * 235 - dpll_device_get(u64 clock_id, u32 dev_driver_id, struct module *module); 205 + dpll_device_get(u64 clock_id, u32 dev_driver_id, struct module *module, 206 + dpll_tracker *tracker); 236 207 237 - void dpll_device_put(struct dpll_device *dpll); 208 + void dpll_device_put(struct dpll_device *dpll, dpll_tracker *tracker); 238 209 239 210 int dpll_device_register(struct dpll_device *dpll, enum dpll_type type, 240 211 const struct dpll_device_ops *ops, void *priv); ··· 249 206 void dpll_device_unregister(struct dpll_device *dpll, 250 207 const struct dpll_device_ops *ops, void *priv); 251 208 209 + #define DPLL_PIN_IDX_UNSPEC U32_MAX 210 + 252 211 struct dpll_pin * 253 212 dpll_pin_get(u64 clock_id, u32 dev_driver_id, struct module *module, 254 - const struct dpll_pin_properties *prop); 213 + const struct dpll_pin_properties *prop, dpll_tracker *tracker); 255 214 256 215 int dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, 257 216 const struct dpll_pin_ops *ops, void *priv); ··· 261 216 void dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, 262 217 const struct dpll_pin_ops *ops, void *priv); 263 218 264 - void dpll_pin_put(struct dpll_pin *pin); 219 + void dpll_pin_put(struct dpll_pin *pin, dpll_tracker *tracker); 220 + 221 + void dpll_pin_fwnode_set(struct dpll_pin *pin, struct fwnode_handle *fwnode); 265 222 266 223 int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin, 267 224 const struct dpll_pin_ops *ops, void *priv); ··· 277 230 int dpll_device_change_ntf(struct dpll_device *dpll); 278 231 279 232 int dpll_pin_change_ntf(struct dpll_pin *pin); 233 + 234 + int register_dpll_notifier(struct notifier_block *nb); 235 + 236 + int unregister_dpll_notifier(struct notifier_block *nb); 280 237 281 238 #endif