mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Petr Oros <poros@redhat.com>
To: netdev@vger.kernel.org
Cc: Petr Oros <poros@redhat.com>,
	Tony Nguyen <anthony.l.nguyen@intel.com>,
	Przemek Kitszel <przemyslaw.kitszel@intel.com>,
	Andrew Lunn <andrew+netdev@lunn.ch>,
	"David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@kernel.org>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>,
	Michal Michalik <michal.michalik@intel.com>,
	Vadim Fedorenko <vadim.fedorenko@linux.dev>,
	Milena Olech <milena.olech@intel.com>,
	intel-wired-lan@lists.osuosl.org, linux-kernel@vger.kernel.org
Subject: [PATCH iwl-net] ice: dpll: refuse pin states that are not valid for the pin
Date: Tue, 10 Nov 2026 15:31:19 +0100	[thread overview]
Message-ID: <20261110143119.2313907-1-poros@redhat.com> (raw)

The DPLL core checks only that a pin may change its state, which states
a pin accepts is left to the driver. The ice callbacks turn the
requested state into an enable flag by comparing it with the one state
that enables the pin, so every other state disables it, including the
one that has no meaning for the pin.

The inputs of the EEC and PPS DPLLs are enabled by selectable, as these
DPLLs select their reference automatically. A request for connected,
which Documentation/driver-api/dpll.rst reserves for manual mode and
for pins with the state-connected-override capability, disables the
input. On an E810:

  # dpll pin set id 1 parent-device 0 state connected
  # dpll pin show id 1
  ... state disconnected on both DPLLs

A recovered clock pin is connected to or disconnected from its parent
pin, and a request for selectable disconnects it:

  # dpll pin set id 2109 parent-pin 2094 state selectable
  # dpll pin show id 2109
  ... state disconnected on parent 2094

Add a helper that translates the state for a pin given the state that
enables it. Disconnected disables the pin and anything else is refused
with -EINVAL and an extack message. Use it for the input and recovered
clock pins, and for the output pins, which already refused selectable
and now tell the user why.

The SMA pins have the same problem. It is left out here, as the rework
of the SMA and U.FL pin control that is queued for net-next refuses the
states these pins cannot serve.

Found with the pin state selftest of the dpllsim series running against
an ice E810.

Fixes: d7999f5ea64bb1 ("ice: implement dpll interface to control cgu")
Signed-off-by: Petr Oros <poros@redhat.com>
---
 drivers/net/ethernet/intel/ice/ice_dpll.c | 61 ++++++++++++++++++++---
 1 file changed, 55 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethernet/intel/ice/ice_dpll.c
index ade1fb3dd06743..b2b515420bc8cd 100644
--- a/drivers/net/ethernet/intel/ice/ice_dpll.c
+++ b/drivers/net/ethernet/intel/ice/ice_dpll.c
@@ -961,6 +961,40 @@ static int ice_dpll_phase_offset_monitor_get(const struct dpll_device *dpll,
 	return 0;
 }
 
+/**
+ * ice_dpll_pin_state_to_enable - translate a requested pin state
+ * @state: pin state requested by the user
+ * @on_state: the state that enables the pin
+ * @enable: on success true to enable the pin, false to disable it
+ * @extack: error reporting
+ *
+ * A pin is enabled by exactly one state: selectable for an input of the
+ * EEC and PPS DPLLs, which select their reference automatically, and
+ * connected for an output and for a recovered clock on its parent pin.
+ * Disconnected disables the pin. No other state has a meaning for the
+ * pin, so it is refused rather than taken for one of the two.
+ *
+ * Return:
+ * * 0 - success, @enable is set
+ * * -EINVAL - @state is not valid for the pin
+ */
+static int
+ice_dpll_pin_state_to_enable(enum dpll_pin_state state,
+			     enum dpll_pin_state on_state, bool *enable,
+			     struct netlink_ext_ack *extack)
+{
+	if (state != on_state && state != DPLL_PIN_STATE_DISCONNECTED) {
+		NL_SET_ERR_MSG_FMT(extack,
+				   "pin state must be %s or disconnected",
+				   on_state == DPLL_PIN_STATE_SELECTABLE ?
+				   "selectable" : "connected");
+		return -EINVAL;
+	}
+	*enable = state == on_state;
+
+	return 0;
+}
+
 /**
  * ice_dpll_pin_state_set - set pin's state on dpll
  * @pin: pointer to a pin
@@ -1027,12 +1061,15 @@ ice_dpll_output_state_set(const struct dpll_pin *pin, void *pin_priv,
 			  enum dpll_pin_state state,
 			  struct netlink_ext_ack *extack)
 {
-	bool enable = state == DPLL_PIN_STATE_CONNECTED;
 	struct ice_dpll_pin *p = pin_priv;
 	struct ice_dpll *d = dpll_priv;
+	bool enable;
+	int ret;
 
-	if (state == DPLL_PIN_STATE_SELECTABLE)
-		return -EINVAL;
+	ret = ice_dpll_pin_state_to_enable(state, DPLL_PIN_STATE_CONNECTED,
+					   &enable, extack);
+	if (ret)
+		return ret;
 	if (!enable && p->state[d->dpll_idx] == DPLL_PIN_STATE_DISCONNECTED)
 		return 0;
 
@@ -1062,7 +1099,13 @@ ice_dpll_input_state_set(const struct dpll_pin *pin, void *pin_priv,
 			 enum dpll_pin_state state,
 			 struct netlink_ext_ack *extack)
 {
-	bool enable = state == DPLL_PIN_STATE_SELECTABLE;
+	bool enable;
+	int ret;
+
+	ret = ice_dpll_pin_state_to_enable(state, DPLL_PIN_STATE_SELECTABLE,
+					   &enable, extack);
+	if (ret)
+		return ret;
 
 	return ice_dpll_pin_state_set(pin, pin_priv, dpll, dpll_priv, enable,
 				      extack, ICE_DPLL_PIN_TYPE_INPUT);
@@ -2518,18 +2561,24 @@ ice_dpll_rclk_state_on_pin_set(const struct dpll_pin *pin, void *pin_priv,
 			       enum dpll_pin_state state,
 			       struct netlink_ext_ack *extack)
 {
-	bool enable = state == DPLL_PIN_STATE_CONNECTED;
 	struct ice_dpll_pin *p = pin_priv;
 	struct ice_pf *pf = p->pf;
 	struct ice_hw *hw;
-	int ret = -EINVAL;
+	bool enable;
 	int hw_idx;
+	int ret;
 
 	hw = &pf->hw;
 
 	if (ice_dpll_is_reset(pf, extack))
 		return -EBUSY;
 
+	ret = ice_dpll_pin_state_to_enable(state, DPLL_PIN_STATE_CONNECTED,
+					   &enable, extack);
+	if (ret)
+		return ret;
+
+	ret = -EINVAL;
 	mutex_lock(&pf->dplls.lock);
 	hw_idx = ice_dpll_pin_get_parent_idx(p, parent_pin);
 	if (hw_idx < 0)
-- 
2.56.0


             reply	other threads:[~2026-11-10 14:31 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-10 14:31 Petr Oros [this message]
2026-11-10 14:48 ` Ivan Vecera

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261110143119.2313907-1-poros@redhat.com \
    --to=poros@redhat.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=anthony.l.nguyen@intel.com \
    --cc=arkadiusz.kubalewski@intel.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@kernel.org \
    --cc=intel-wired-lan@lists.osuosl.org \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=michal.michalik@intel.com \
    --cc=milena.olech@intel.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=przemyslaw.kitszel@intel.com \
    --cc=vadim.fedorenko@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®