diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-02-29 12:40:20 -0800 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-02-29 12:40:20 -0800 | 
| commit | 87adedeba51a822533649b143232418b9e26d08b (patch) | |
| tree | 71fcb6a3733faec63476c0d6d5b8546972101be8 /drivers/net/ethernet/intel/ice/ice_dpll.c | |
| parent | d4f76f8065681f55b3c69073829fe7e4c70c0818 (diff) | |
| parent | 640f41ed33b5a420e05daf395afae85e6b20c003 (diff) | |
Merge tag 'net-6.8-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Pull networking fixes from Jakub Kicinski:
 "Including fixes from bluetooth, WiFi and netfilter.
  We have one outstanding issue with the stmmac driver, which may be a
  LOCKDEP false positive, not a blocker.
  Current release - regressions:
   - netfilter: nf_tables: re-allow NFPROTO_INET in
     nft_(match/target)_validate()
   - eth: ionic: fix error handling in PCI reset code
  Current release - new code bugs:
   - eth: stmmac: complete meta data only when enabled, fix null-deref
   - kunit: fix again checksum tests on big endian CPUs
  Previous releases - regressions:
   - veth: try harder when allocating queue memory
   - Bluetooth:
      - hci_bcm4377: do not mark valid bd_addr as invalid
      - hci_event: fix handling of HCI_EV_IO_CAPA_REQUEST
  Previous releases - always broken:
   - info leak in __skb_datagram_iter() on netlink socket
   - mptcp:
      - map v4 address to v6 when destroying subflow
      - fix potential wake-up event loss due to sndbuf auto-tuning
      - fix double-free on socket dismantle
   - wifi: nl80211: reject iftype change with mesh ID change
   - fix small out-of-bound read when validating netlink be16/32 types
   - rtnetlink: fix error logic of IFLA_BRIDGE_FLAGS writing back
   - ipv6: fix potential "struct net" ref-leak in inet6_rtm_getaddr()
   - ip_tunnel: prevent perpetual headroom growth with huge number of
     tunnels on top of each other
   - mctp: fix skb leaks on error paths of mctp_local_output()
   - eth: ice: fixes for DPLL state reporting
   - dpll: rely on rcu for netdev_dpll_pin() to prevent UaF
   - eth: dpaa: accept phy-interface-type = '10gbase-r' in the device
     tree"
* tag 'net-6.8-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (73 commits)
  dpll: fix build failure due to rcu_dereference_check() on unknown type
  kunit: Fix again checksum tests on big endian CPUs
  tls: fix use-after-free on failed backlog decryption
  tls: separate no-async decryption request handling from async
  tls: fix peeking with sync+async decryption
  tls: decrement decrypt_pending if no async completion will be called
  gtp: fix use-after-free and null-ptr-deref in gtp_newlink()
  net: hsr: Use correct offset for HSR TLV values in supervisory HSR frames
  igb: extend PTP timestamp adjustments to i211
  rtnetlink: fix error logic of IFLA_BRIDGE_FLAGS writing back
  tools: ynl: fix handling of multiple mcast groups
  selftests: netfilter: add bridge conntrack + multicast test case
  netfilter: bridge: confirm multicast packets before passing them up the stack
  netfilter: nf_tables: allow NFPROTO_INET in nft_(match/target)_validate()
  Bluetooth: qca: Fix triggering coredump implementation
  Bluetooth: hci_qca: Set BDA quirk bit if fwnode exists in DT
  Bluetooth: qca: Fix wrong event type for patch config command
  Bluetooth: Enforce validation on max value of connection interval
  Bluetooth: hci_event: Fix handling of HCI_EV_IO_CAPA_REQUEST
  Bluetooth: mgmt: Fix limited discoverable off timeout
  ...
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_dpll.c')
| -rw-r--r-- | drivers/net/ethernet/intel/ice/ice_dpll.c | 91 | 
1 files changed, 78 insertions, 13 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethernet/intel/ice/ice_dpll.c index b9c5eced6326..adfa1f2a80a6 100644 --- a/drivers/net/ethernet/intel/ice/ice_dpll.c +++ b/drivers/net/ethernet/intel/ice/ice_dpll.c @@ -31,6 +31,26 @@ static const char * const pin_type_name[] = {  };  /** + * ice_dpll_is_reset - check if reset is in progress + * @pf: private board structure + * @extack: error reporting + * + * If reset is in progress, fill extack with error. + * + * Return: + * * false - no reset in progress + * * true - reset in progress + */ +static bool ice_dpll_is_reset(struct ice_pf *pf, struct netlink_ext_ack *extack) +{ +	if (ice_is_reset_in_progress(pf->state)) { +		NL_SET_ERR_MSG(extack, "PF reset in progress"); +		return true; +	} +	return false; +} + +/**   * ice_dpll_pin_freq_set - set pin's frequency   * @pf: private board structure   * @pin: pointer to a pin @@ -109,6 +129,9 @@ ice_dpll_frequency_set(const struct dpll_pin *pin, void *pin_priv,  	struct ice_pf *pf = d->pf;  	int ret; +	if (ice_dpll_is_reset(pf, extack)) +		return -EBUSY; +  	mutex_lock(&pf->dplls.lock);  	ret = ice_dpll_pin_freq_set(pf, p, pin_type, frequency, extack);  	mutex_unlock(&pf->dplls.lock); @@ -254,6 +277,7 @@ ice_dpll_output_frequency_get(const struct dpll_pin *pin, void *pin_priv,   * ice_dpll_pin_enable - enable a pin on dplls   * @hw: board private hw structure   * @pin: pointer to a pin + * @dpll_idx: dpll index to connect to output pin   * @pin_type: type of pin being enabled   * @extack: error reporting   * @@ -266,7 +290,7 @@ ice_dpll_output_frequency_get(const struct dpll_pin *pin, void *pin_priv,   */  static int  ice_dpll_pin_enable(struct ice_hw *hw, struct ice_dpll_pin *pin, -		    enum ice_dpll_pin_type pin_type, +		    u8 dpll_idx, enum ice_dpll_pin_type pin_type,  		    struct netlink_ext_ack *extack)  {  	u8 flags = 0; @@ -280,10 +304,12 @@ ice_dpll_pin_enable(struct ice_hw *hw, struct ice_dpll_pin *pin,  		ret = ice_aq_set_input_pin_cfg(hw, pin->idx, 0, flags, 0, 0);  		break;  	case ICE_DPLL_PIN_TYPE_OUTPUT: +		flags = ICE_AQC_SET_CGU_OUT_CFG_UPDATE_SRC_SEL;  		if (pin->flags[0] & ICE_AQC_GET_CGU_OUT_CFG_ESYNC_EN)  			flags |= ICE_AQC_SET_CGU_OUT_CFG_ESYNC_EN;  		flags |= ICE_AQC_SET_CGU_OUT_CFG_OUT_EN; -		ret = ice_aq_set_output_pin_cfg(hw, pin->idx, flags, 0, 0, 0); +		ret = ice_aq_set_output_pin_cfg(hw, pin->idx, flags, dpll_idx, +						0, 0);  		break;  	default:  		return -EINVAL; @@ -370,7 +396,7 @@ ice_dpll_pin_state_update(struct ice_pf *pf, struct ice_dpll_pin *pin,  	case ICE_DPLL_PIN_TYPE_INPUT:  		ret = ice_aq_get_input_pin_cfg(&pf->hw, pin->idx, NULL, NULL,  					       NULL, &pin->flags[0], -					       &pin->freq, NULL); +					       &pin->freq, &pin->phase_adjust);  		if (ret)  			goto err;  		if (ICE_AQC_GET_CGU_IN_CFG_FLG2_INPUT_EN & pin->flags[0]) { @@ -398,14 +424,27 @@ ice_dpll_pin_state_update(struct ice_pf *pf, struct ice_dpll_pin *pin,  		break;  	case ICE_DPLL_PIN_TYPE_OUTPUT:  		ret = ice_aq_get_output_pin_cfg(&pf->hw, pin->idx, -						&pin->flags[0], NULL, +						&pin->flags[0], &parent,  						&pin->freq, NULL);  		if (ret)  			goto err; -		if (ICE_AQC_SET_CGU_OUT_CFG_OUT_EN & pin->flags[0]) -			pin->state[0] = DPLL_PIN_STATE_CONNECTED; -		else -			pin->state[0] = DPLL_PIN_STATE_DISCONNECTED; + +		parent &= ICE_AQC_GET_CGU_OUT_CFG_DPLL_SRC_SEL; +		if (ICE_AQC_SET_CGU_OUT_CFG_OUT_EN & pin->flags[0]) { +			pin->state[pf->dplls.eec.dpll_idx] = +				parent == pf->dplls.eec.dpll_idx ? +				DPLL_PIN_STATE_CONNECTED : +				DPLL_PIN_STATE_DISCONNECTED; +			pin->state[pf->dplls.pps.dpll_idx] = +				parent == pf->dplls.pps.dpll_idx ? +				DPLL_PIN_STATE_CONNECTED : +				DPLL_PIN_STATE_DISCONNECTED; +		} else { +			pin->state[pf->dplls.eec.dpll_idx] = +				DPLL_PIN_STATE_DISCONNECTED; +			pin->state[pf->dplls.pps.dpll_idx] = +				DPLL_PIN_STATE_DISCONNECTED; +		}  		break;  	case ICE_DPLL_PIN_TYPE_RCLK_INPUT:  		for (parent = 0; parent < pf->dplls.rclk.num_parents; @@ -568,9 +607,13 @@ ice_dpll_pin_state_set(const struct dpll_pin *pin, void *pin_priv,  	struct ice_pf *pf = d->pf;  	int ret; +	if (ice_dpll_is_reset(pf, extack)) +		return -EBUSY; +  	mutex_lock(&pf->dplls.lock);  	if (enable) -		ret = ice_dpll_pin_enable(&pf->hw, p, pin_type, extack); +		ret = ice_dpll_pin_enable(&pf->hw, p, d->dpll_idx, pin_type, +					  extack);  	else  		ret = ice_dpll_pin_disable(&pf->hw, p, pin_type, extack);  	if (!ret) @@ -603,6 +646,11 @@ ice_dpll_output_state_set(const struct dpll_pin *pin, void *pin_priv,  			  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; + +	if (!enable && p->state[d->dpll_idx] == DPLL_PIN_STATE_DISCONNECTED) +		return 0;  	return ice_dpll_pin_state_set(pin, pin_priv, dpll, dpll_priv, enable,  				      extack, ICE_DPLL_PIN_TYPE_OUTPUT); @@ -665,14 +713,16 @@ ice_dpll_pin_state_get(const struct dpll_pin *pin, void *pin_priv,  	struct ice_pf *pf = d->pf;  	int ret; +	if (ice_dpll_is_reset(pf, extack)) +		return -EBUSY; +  	mutex_lock(&pf->dplls.lock);  	ret = ice_dpll_pin_state_update(pf, p, pin_type, extack);  	if (ret)  		goto unlock; -	if (pin_type == ICE_DPLL_PIN_TYPE_INPUT) +	if (pin_type == ICE_DPLL_PIN_TYPE_INPUT || +	    pin_type == ICE_DPLL_PIN_TYPE_OUTPUT)  		*state = p->state[d->dpll_idx]; -	else if (pin_type == ICE_DPLL_PIN_TYPE_OUTPUT) -		*state = p->state[0];  	ret = 0;  unlock:  	mutex_unlock(&pf->dplls.lock); @@ -790,6 +840,9 @@ ice_dpll_input_prio_set(const struct dpll_pin *pin, void *pin_priv,  	struct ice_pf *pf = d->pf;  	int ret; +	if (ice_dpll_is_reset(pf, extack)) +		return -EBUSY; +  	mutex_lock(&pf->dplls.lock);  	ret = ice_dpll_hw_input_prio_set(pf, d, p, prio, extack);  	mutex_unlock(&pf->dplls.lock); @@ -910,6 +963,9 @@ ice_dpll_pin_phase_adjust_set(const struct dpll_pin *pin, void *pin_priv,  	u8 flag, flags_en = 0;  	int ret; +	if (ice_dpll_is_reset(pf, extack)) +		return -EBUSY; +  	mutex_lock(&pf->dplls.lock);  	switch (type) {  	case ICE_DPLL_PIN_TYPE_INPUT: @@ -1069,6 +1125,9 @@ ice_dpll_rclk_state_on_pin_set(const struct dpll_pin *pin, void *pin_priv,  	int ret = -EINVAL;  	u32 hw_idx; +	if (ice_dpll_is_reset(pf, extack)) +		return -EBUSY; +  	mutex_lock(&pf->dplls.lock);  	hw_idx = parent->idx - pf->dplls.base_rclk_idx;  	if (hw_idx >= pf->dplls.num_inputs) @@ -1123,6 +1182,9 @@ ice_dpll_rclk_state_on_pin_get(const struct dpll_pin *pin, void *pin_priv,  	int ret = -EINVAL;  	u32 hw_idx; +	if (ice_dpll_is_reset(pf, extack)) +		return -EBUSY; +  	mutex_lock(&pf->dplls.lock);  	hw_idx = parent->idx - pf->dplls.base_rclk_idx;  	if (hw_idx >= pf->dplls.num_inputs) @@ -1305,8 +1367,10 @@ static void ice_dpll_periodic_work(struct kthread_work *work)  	struct ice_pf *pf = container_of(d, struct ice_pf, dplls);  	struct ice_dpll *de = &pf->dplls.eec;  	struct ice_dpll *dp = &pf->dplls.pps; -	int ret; +	int ret = 0; +	if (ice_is_reset_in_progress(pf->state)) +		goto resched;  	mutex_lock(&pf->dplls.lock);  	ret = ice_dpll_update_state(pf, de, false);  	if (!ret) @@ -1326,6 +1390,7 @@ static void ice_dpll_periodic_work(struct kthread_work *work)  	ice_dpll_notify_changes(de);  	ice_dpll_notify_changes(dp); +resched:  	/* Run twice a second or reschedule if update failed */  	kthread_queue_delayed_work(d->kworker, &d->work,  				   ret ? msecs_to_jiffies(10) :  | 
