[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251211194756.234043-3-ivecera@redhat.com>
Date: Thu, 11 Dec 2025 20:47:45 +0100
From: Ivan Vecera <ivecera@...hat.com>
To: netdev@...r.kernel.org,
Andrew Lunn <andrew+netdev@...n.ch>,
"David S. Miller" <davem@...emloft.net>,
Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>,
Paolo Abeni <pabeni@...hat.com>,
Rob Herring <robh@...nel.org>,
Krzysztof Kozlowski <krzk+dt@...nel.org>,
Conor Dooley <conor+dt@...nel.org>,
Vadim Fedorenko <vadim.fedorenko@...ux.dev>,
Arkadiusz Kubalewski <arkadiusz.kubalewski@...el.com>,
Grzegorz Nitka <grzegorz.nitka@...el.com>,
Jiri Pirko <jiri@...nulli.us>,
Petr Oros <poros@...hat.com>,
Michal Schmidt <mschmidt@...hat.com>,
Prathosh Satish <Prathosh.Satish@...rochip.com>,
Tony Nguyen <anthony.l.nguyen@...el.com>,
Przemek Kitszel <przemyslaw.kitszel@...el.com>,
Saeed Mahameed <saeedm@...dia.com>,
Leon Romanovsky <leon@...nel.org>,
Tariq Toukan <tariqt@...dia.com>,
Mark Bloch <mbloch@...dia.com>,
Richard Cochran <richardcochran@...il.com>,
Jonathan Lemon <jonathan.lemon@...il.com>,
Simon Horman <horms@...nel.org>,
Alexander Lobakin <aleksander.lobakin@...el.com>,
Willem de Bruijn <willemb@...gle.com>,
Stefan Wahren <wahrenst@....net>,
devicetree@...r.kernel.org,
linux-kernel@...r.kernel.org,
intel-wired-lan@...ts.osuosl.org,
linux-rdma@...r.kernel.org
Subject: [PATCH RFC net-next 02/13] dpll: Allow registering pin with firmware node
Extend the DPLL core to support associating a DPLL pin with a firmware
node (fwnode). This association is required to allow other subsystems
(such as network drivers) to locate and request specific DPLL pins
defined in the Device Tree or ACPI.
Modify dpll_pin_get() to accept an optional fwnode_handle parameter.
If provided, the fwnode is stored in the dpll_pin structure, and its
reference count is incremented. The reference is released in dpll_pin_put().
Add fwnode_dpll_pin_find() as an exported symbol. This helper allows
drivers to search for a registered DPLL pin using its associated fwnode
handle. The caller should use dpll_pin_put() to release dpll pin
returned by fwnode_dpll_pin_find().
Update all existing callers of dpll_pin_get() in the ice, mlx5, ptp_ocp,
and zl3073x drivers to pass NULL for the new argument, preserving existing
behavior.
Signed-off-by: Ivan Vecera <ivecera@...hat.com>
---
drivers/dpll/dpll_core.c | 46 +++++++++++++++++--
drivers/dpll/dpll_core.h | 2 +
drivers/dpll/zl3073x/dpll.c | 2 +-
drivers/net/ethernet/intel/ice/ice_dpll.c | 2 +-
.../net/ethernet/mellanox/mlx5/core/dpll.c | 3 +-
drivers/ptp/ptp_ocp.c | 3 +-
include/linux/dpll.h | 12 ++++-
7 files changed, 61 insertions(+), 9 deletions(-)
diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
index a461095efd8ac..773783fd14f71 100644
--- a/drivers/dpll/dpll_core.c
+++ b/drivers/dpll/dpll_core.c
@@ -10,6 +10,7 @@
#include <linux/device.h>
#include <linux/err.h>
+#include <linux/property.h>
#include <linux/slab.h>
#include <linux/string.h>
@@ -484,7 +485,8 @@ static int dpll_pin_prop_dup(const struct dpll_pin_properties *src,
static struct dpll_pin *
dpll_pin_alloc(u64 clock_id, u32 pin_idx, struct module *module,
- const struct dpll_pin_properties *prop)
+ const struct dpll_pin_properties *prop,
+ struct fwnode_handle *fwnode)
{
struct dpll_pin *pin;
int ret;
@@ -511,6 +513,7 @@ dpll_pin_alloc(u64 clock_id, u32 pin_idx, struct module *module,
&dpll_pin_xa_id, GFP_KERNEL);
if (ret < 0)
goto err_xa_alloc;
+ pin->fwnode = fwnode_handle_get(fwnode);
return pin;
err_xa_alloc:
xa_destroy(&pin->dpll_refs);
@@ -548,6 +551,7 @@ EXPORT_SYMBOL(dpll_netdev_pin_clear);
* @pin_idx: idx given by dev driver
* @module: reference to registering module
* @prop: dpll pin properties
+ * @fwnode: optional reference to firmware node
*
* Get existing object of a pin (unique for given arguments) or create new
* if doesn't exist yet.
@@ -559,7 +563,8 @@ EXPORT_SYMBOL(dpll_netdev_pin_clear);
*/
struct dpll_pin *
dpll_pin_get(u64 clock_id, u32 pin_idx, struct module *module,
- const struct dpll_pin_properties *prop)
+ const struct dpll_pin_properties *prop,
+ struct fwnode_handle *fwnode)
{
struct dpll_pin *pos, *ret = NULL;
unsigned long i;
@@ -568,14 +573,15 @@ dpll_pin_get(u64 clock_id, u32 pin_idx, struct module *module,
xa_for_each(&dpll_pin_xa, i, pos) {
if (pos->clock_id == clock_id &&
pos->pin_idx == pin_idx &&
- pos->module == module) {
+ pos->module == module &&
+ pos->fwnode == fwnode) {
ret = pos;
refcount_inc(&ret->refcount);
break;
}
}
if (!ret)
- ret = dpll_pin_alloc(clock_id, pin_idx, module, prop);
+ ret = dpll_pin_alloc(clock_id, pin_idx, module, prop, fwnode);
mutex_unlock(&dpll_lock);
return ret;
@@ -599,12 +605,44 @@ void dpll_pin_put(struct dpll_pin *pin)
xa_destroy(&pin->parent_refs);
xa_destroy(&pin->ref_sync_pins);
dpll_pin_prop_free(&pin->prop);
+ fwnode_handle_put(pin->fwnode);
kfree_rcu(pin, rcu);
}
mutex_unlock(&dpll_lock);
}
EXPORT_SYMBOL_GPL(dpll_pin_put);
+/**
+ * fwnode_dpll_pin_find - find dpll pin by firmware node reference
+ * @fwnode: reference to firmware node
+ *
+ * Get existing object of a pin that is associated with given firmware node
+ * reference.
+ *
+ * Context: Acquires a lock (dpll_lock)
+ * Return:
+ * * valid dpll_pin struct pointer if succeeded
+ * * ERR_PTR(X) - error
+ */
+struct dpll_pin *fwnode_dpll_pin_find(struct fwnode_handle *fwnode)
+{
+ struct dpll_pin *pin, *ret = NULL;
+ unsigned long index;
+
+ mutex_lock(&dpll_lock);
+ xa_for_each(&dpll_pin_xa, index, pin) {
+ if (pin->fwnode == fwnode) {
+ ret = pin;
+ refcount_inc(&ret->refcount);
+ break;
+ }
+ }
+ mutex_unlock(&dpll_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(fwnode_dpll_pin_find);
+
static int
__dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
const struct dpll_pin_ops *ops, void *priv, void *cookie)
diff --git a/drivers/dpll/dpll_core.h b/drivers/dpll/dpll_core.h
index 8ce969bbeb64e..d3e17ff0ecef0 100644
--- a/drivers/dpll/dpll_core.h
+++ b/drivers/dpll/dpll_core.h
@@ -42,6 +42,7 @@ struct dpll_device {
* @pin_idx: index of a pin given by dev driver
* @clock_id: clock_id of creator
* @module: module of creator
+ * @fwnode: optional reference to firmware node
* @dpll_refs: hold referencees to dplls pin was registered with
* @parent_refs: hold references to parent pins pin was registered with
* @ref_sync_pins: hold references to pins for Reference SYNC feature
@@ -54,6 +55,7 @@ struct dpll_pin {
u32 pin_idx;
u64 clock_id;
struct module *module;
+ struct fwnode_handle *fwnode;
struct xarray dpll_refs;
struct xarray parent_refs;
struct xarray ref_sync_pins;
diff --git a/drivers/dpll/zl3073x/dpll.c b/drivers/dpll/zl3073x/dpll.c
index 9879d85d29af0..cf2ad3031e5d7 100644
--- a/drivers/dpll/zl3073x/dpll.c
+++ b/drivers/dpll/zl3073x/dpll.c
@@ -1368,7 +1368,7 @@ zl3073x_dpll_pin_register(struct zl3073x_dpll_pin *pin, u32 index)
/* Create or get existing DPLL pin */
pin->dpll_pin = dpll_pin_get(zldpll->dev->clock_id, index, THIS_MODULE,
- &props->dpll_props);
+ &props->dpll_props, NULL);
if (IS_ERR(pin->dpll_pin)) {
rc = PTR_ERR(pin->dpll_pin);
goto err_pin_get;
diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethernet/intel/ice/ice_dpll.c
index 53b54e395a2ed..1c28af5a2d5e0 100644
--- a/drivers/net/ethernet/intel/ice/ice_dpll.c
+++ b/drivers/net/ethernet/intel/ice/ice_dpll.c
@@ -2840,7 +2840,7 @@ ice_dpll_get_pins(struct ice_pf *pf, struct ice_dpll_pin *pins,
for (i = 0; i < count; i++) {
pins[i].pin = dpll_pin_get(clock_id, i + start_idx, THIS_MODULE,
- &pins[i].prop);
+ &pins[i].prop, NULL);
if (IS_ERR(pins[i].pin)) {
ret = PTR_ERR(pins[i].pin);
goto release_pins;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c
index 1e5522a194839..9e71164f463df 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c
@@ -451,7 +451,8 @@ static int mlx5_dpll_probe(struct auxiliary_device *adev,
/* Multiple mdev instances might share one DPLL pin. */
mdpll->dpll_pin = dpll_pin_get(clock_id, mlx5_get_dev_index(mdev),
- THIS_MODULE, &mlx5_dpll_pin_properties);
+ THIS_MODULE, &mlx5_dpll_pin_properties,
+ NULL);
if (IS_ERR(mdpll->dpll_pin)) {
err = PTR_ERR(mdpll->dpll_pin);
goto err_unregister_dpll_device;
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index 65fe05cac8c42..fd7d1132afdf0 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -4800,7 +4800,8 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto out;
for (i = 0; i < OCP_SMA_NUM; i++) {
- bp->sma[i].dpll_pin = dpll_pin_get(clkid, i, THIS_MODULE, &bp->sma[i].dpll_prop);
+ bp->sma[i].dpll_pin = dpll_pin_get(clkid, i, THIS_MODULE,
+ &bp->sma[i].dpll_prop, NULL);
if (IS_ERR(bp->sma[i].dpll_pin)) {
err = PTR_ERR(bp->sma[i].dpll_pin);
goto out_dpll;
diff --git a/include/linux/dpll.h b/include/linux/dpll.h
index 562f520b23c27..315245dbdfb96 100644
--- a/include/linux/dpll.h
+++ b/include/linux/dpll.h
@@ -16,6 +16,7 @@
struct dpll_device;
struct dpll_pin;
struct dpll_pin_esync;
+struct fwnode_handle;
struct dpll_device_ops {
int (*mode_get)(const struct dpll_device *dpll, void *dpll_priv,
@@ -173,6 +174,8 @@ void dpll_netdev_pin_clear(struct net_device *dev);
size_t dpll_netdev_pin_handle_size(const struct net_device *dev);
int dpll_netdev_add_pin_handle(struct sk_buff *msg,
const struct net_device *dev);
+
+struct dpll_pin *fwnode_dpll_pin_find(struct fwnode_handle *fwnode);
#else
static inline void
dpll_netdev_pin_set(struct net_device *dev, struct dpll_pin *dpll_pin) { }
@@ -188,6 +191,12 @@ dpll_netdev_add_pin_handle(struct sk_buff *msg, const struct net_device *dev)
{
return 0;
}
+
+static inline struct dpll_pin *
+fwnode_dpll_pin_find(struct fwnode_handle *fwnode)
+{
+ return NULL;
+}
#endif
struct dpll_device *
@@ -203,7 +212,8 @@ void dpll_device_unregister(struct dpll_device *dpll,
struct dpll_pin *
dpll_pin_get(u64 clock_id, u32 dev_driver_id, struct module *module,
- const struct dpll_pin_properties *prop);
+ const struct dpll_pin_properties *prop,
+ struct fwnode_handle *fwnode);
int dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
const struct dpll_pin_ops *ops, void *priv);
--
2.51.2
Powered by blists - more mailing lists