Commit a6a0974a authored by Dave Ertman's avatar Dave Ertman Committed by Tony Nguyen
Browse files

ice: Prevent set_channel from changing queues while RDMA active



The PF controls the set of queues that the RDMA auxiliary_driver requests
resources from.  The set_channel command will alter that pool and trigger a
reconfiguration of the VSI, which breaks RDMA functionality.

Prevent set_channel from executing when RDMA driver bound to auxiliary
device.

Adding a locked variable to pass down the call chain to avoid double
locking the device_lock.

Fixes: 348048e7 ("ice: Implement iidc operations")
Signed-off-by: default avatarDave Ertman <david.m.ertman@intel.com>
Tested-by: Gurucharan G <gurucharanx.g@intel.com> (A Contingent worker at Intel)
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 7083df59
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -880,7 +880,7 @@ void ice_set_ethtool_repr_ops(struct net_device *netdev);
void ice_set_ethtool_safe_mode_ops(struct net_device *netdev);
u16 ice_get_avail_txq_count(struct ice_pf *pf);
u16 ice_get_avail_rxq_count(struct ice_pf *pf);
int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx);
int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx, bool locked);
void ice_update_vsi_stats(struct ice_vsi *vsi);
void ice_update_pf_stats(struct ice_pf *pf);
void
+13 −10
Original line number Diff line number Diff line
@@ -441,7 +441,7 @@ int ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked)
		goto out;
	}

	ice_pf_dcb_recfg(pf);
	ice_pf_dcb_recfg(pf, false);

out:
	/* enable previously downed VSIs */
@@ -731,12 +731,13 @@ static int ice_dcb_noncontig_cfg(struct ice_pf *pf)
/**
 * ice_pf_dcb_recfg - Reconfigure all VEBs and VSIs
 * @pf: pointer to the PF struct
 * @locked: is adev device lock held
 *
 * Assumed caller has already disabled all VSIs before
 * calling this function. Reconfiguring DCB based on
 * local_dcbx_cfg.
 */
void ice_pf_dcb_recfg(struct ice_pf *pf)
void ice_pf_dcb_recfg(struct ice_pf *pf, bool locked)
{
	struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg;
	struct iidc_event *event;
@@ -783,6 +784,7 @@ void ice_pf_dcb_recfg(struct ice_pf *pf)
		if (vsi->type == ICE_VSI_PF)
			ice_dcbnl_set_all(vsi);
	}
	if (!locked) {
		/* Notify the AUX drivers that TC change is finished */
		event = kzalloc(sizeof(*event), GFP_KERNEL);
		if (!event)
@@ -792,6 +794,7 @@ void ice_pf_dcb_recfg(struct ice_pf *pf)
		ice_send_event_to_aux(pf, event);
		kfree(event);
	}
}

/**
 * ice_init_pf_dcb - initialize DCB for a PF
@@ -1044,7 +1047,7 @@ ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf,
	}

	/* changes in configuration update VSI */
	ice_pf_dcb_recfg(pf);
	ice_pf_dcb_recfg(pf, false);

	/* enable previously downed VSIs */
	ice_dcb_ena_dis_vsi(pf, true, true);
+2 −2
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ u8 ice_dcb_get_tc(struct ice_vsi *vsi, int queue_index);
int
ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked);
int ice_dcb_bwchk(struct ice_pf *pf, struct ice_dcbx_cfg *dcbcfg);
void ice_pf_dcb_recfg(struct ice_pf *pf);
void ice_pf_dcb_recfg(struct ice_pf *pf, bool locked);
void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi);
int ice_init_pf_dcb(struct ice_pf *pf, bool locked);
void ice_update_dcb_stats(struct ice_pf *pf);
@@ -128,7 +128,7 @@ static inline u8 ice_get_pfc_mode(struct ice_pf *pf)
	return 0;
}

static inline void ice_pf_dcb_recfg(struct ice_pf *pf) { }
static inline void ice_pf_dcb_recfg(struct ice_pf *pf, bool locked) { }
static inline void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi) { }
static inline void ice_update_dcb_stats(struct ice_pf *pf) { }
static inline void
+24 −4
Original line number Diff line number Diff line
@@ -3641,7 +3641,9 @@ static int ice_set_channels(struct net_device *dev, struct ethtool_channels *ch)
	struct ice_vsi *vsi = np->vsi;
	struct ice_pf *pf = vsi->back;
	int new_rx = 0, new_tx = 0;
	bool locked = false;
	u32 curr_combined;
	int ret = 0;

	/* do not support changing channels in Safe Mode */
	if (ice_is_safe_mode(pf)) {
@@ -3705,15 +3707,33 @@ static int ice_set_channels(struct net_device *dev, struct ethtool_channels *ch)
		return -EINVAL;
	}

	ice_vsi_recfg_qs(vsi, new_rx, new_tx);
	if (pf->adev) {
		mutex_lock(&pf->adev_mutex);
		device_lock(&pf->adev->dev);
		locked = true;
		if (pf->adev->dev.driver) {
			netdev_err(dev, "Cannot change channels when RDMA is active\n");
			ret = -EBUSY;
			goto adev_unlock;
		}
	}

	ice_vsi_recfg_qs(vsi, new_rx, new_tx, locked);

	if (!netif_is_rxfh_configured(dev))
		return ice_vsi_set_dflt_rss_lut(vsi, new_rx);
	if (!netif_is_rxfh_configured(dev)) {
		ret = ice_vsi_set_dflt_rss_lut(vsi, new_rx);
		goto adev_unlock;
	}

	/* Update rss_size due to change in Rx queues */
	vsi->rss_size = ice_get_valid_rss_size(&pf->hw, new_rx);

	return 0;
adev_unlock:
	if (locked) {
		device_unlock(&pf->adev->dev);
		mutex_unlock(&pf->adev_mutex);
	}
	return ret;
}

/**
+3 −2
Original line number Diff line number Diff line
@@ -4195,12 +4195,13 @@ bool ice_is_wol_supported(struct ice_hw *hw)
 * @vsi: VSI being changed
 * @new_rx: new number of Rx queues
 * @new_tx: new number of Tx queues
 * @locked: is adev device_lock held
 *
 * Only change the number of queues if new_tx, or new_rx is non-0.
 *
 * Returns 0 on success.
 */
int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx)
int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx, bool locked)
{
	struct ice_pf *pf = vsi->back;
	int err = 0, timeout = 50;
@@ -4229,7 +4230,7 @@ int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx)

	ice_vsi_close(vsi);
	ice_vsi_rebuild(vsi, false);
	ice_pf_dcb_recfg(pf);
	ice_pf_dcb_recfg(pf, locked);
	ice_vsi_open(vsi);
done:
	clear_bit(ICE_CFG_BUSY, pf->state);