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.

dpll: Support dynamic pin index allocation

Allow drivers to register DPLL pins without manually specifying a pin
index.

Currently, drivers must provide a unique pin index when calling
dpll_pin_get(). This works well for hardware-mapped pins but creates
friction for drivers handling virtual pins or those without a strict
hardware indexing scheme.

Introduce DPLL_PIN_IDX_UNSPEC (U32_MAX). When a driver passes this
value as the pin index:
1. The core allocates a unique index using an IDA
2. The allocated index is mapped to a range starting above `INT_MAX`

This separation ensures that dynamically allocated indices never collide
with standard driver-provided hardware indices, which are assumed to be
within the `0` to `INT_MAX` range. The index is automatically freed when
the pin is released in dpll_pin_put().

Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Link: https://patch.msgid.link/20260203174002.705176-5-ivecera@redhat.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Ivan Vecera and committed by
Paolo Abeni
711696b3 2be46758

+48 -2
+46 -2
drivers/dpll/dpll_core.c
··· 10 10 11 11 #include <linux/device.h> 12 12 #include <linux/err.h> 13 + #include <linux/idr.h> 13 14 #include <linux/property.h> 14 15 #include <linux/slab.h> 15 16 #include <linux/string.h> ··· 25 24 DEFINE_XARRAY_FLAGS(dpll_pin_xa, XA_FLAGS_ALLOC); 26 25 27 26 static RAW_NOTIFIER_HEAD(dpll_notifier_chain); 27 + static DEFINE_IDA(dpll_pin_idx_ida); 28 28 29 29 static u32 dpll_device_xa_id; 30 30 static u32 dpll_pin_xa_id; ··· 466 464 } 467 465 EXPORT_SYMBOL_GPL(dpll_device_unregister); 468 466 467 + static int dpll_pin_idx_alloc(u32 *pin_idx) 468 + { 469 + int ret; 470 + 471 + if (!pin_idx) 472 + return -EINVAL; 473 + 474 + /* Alloc unique number from IDA. Number belongs to <0, INT_MAX> range */ 475 + ret = ida_alloc(&dpll_pin_idx_ida, GFP_KERNEL); 476 + if (ret < 0) 477 + return ret; 478 + 479 + /* Map the value to dynamic pin index range <INT_MAX+1, U32_MAX> */ 480 + *pin_idx = (u32)ret + INT_MAX + 1; 481 + 482 + return 0; 483 + } 484 + 485 + static void dpll_pin_idx_free(u32 pin_idx) 486 + { 487 + if (pin_idx <= INT_MAX) 488 + return; /* Not a dynamic pin index */ 489 + 490 + /* Map the index value from dynamic pin index range to IDA range and 491 + * free it. 492 + */ 493 + pin_idx -= (u32)INT_MAX + 1; 494 + ida_free(&dpll_pin_idx_ida, pin_idx); 495 + } 496 + 469 497 static void dpll_pin_prop_free(struct dpll_pin_properties *prop) 470 498 { 471 499 kfree(prop->package_label); ··· 553 521 struct dpll_pin *pin; 554 522 int ret; 555 523 524 + if (pin_idx == DPLL_PIN_IDX_UNSPEC) { 525 + ret = dpll_pin_idx_alloc(&pin_idx); 526 + if (ret) 527 + return ERR_PTR(ret); 528 + } else if (pin_idx > INT_MAX) { 529 + return ERR_PTR(-EINVAL); 530 + } 556 531 pin = kzalloc(sizeof(*pin), GFP_KERNEL); 557 - if (!pin) 558 - return ERR_PTR(-ENOMEM); 532 + if (!pin) { 533 + ret = -ENOMEM; 534 + goto err_pin_alloc; 535 + } 559 536 pin->pin_idx = pin_idx; 560 537 pin->clock_id = clock_id; 561 538 pin->module = module; ··· 592 551 dpll_pin_prop_free(&pin->prop); 593 552 err_pin_prop: 594 553 kfree(pin); 554 + err_pin_alloc: 555 + dpll_pin_idx_free(pin_idx); 595 556 return ERR_PTR(ret); 596 557 } 597 558 ··· 697 654 xa_destroy(&pin->ref_sync_pins); 698 655 dpll_pin_prop_free(&pin->prop); 699 656 fwnode_handle_put(pin->fwnode); 657 + dpll_pin_idx_free(pin->pin_idx); 700 658 kfree_rcu(pin, rcu); 701 659 } 702 660 mutex_unlock(&dpll_lock);
+2
include/linux/dpll.h
··· 240 240 void dpll_device_unregister(struct dpll_device *dpll, 241 241 const struct dpll_device_ops *ops, void *priv); 242 242 243 + #define DPLL_PIN_IDX_UNSPEC U32_MAX 244 + 243 245 struct dpll_pin * 244 246 dpll_pin_get(u64 clock_id, u32 dev_driver_id, struct module *module, 245 247 const struct dpll_pin_properties *prop);