Commit 369bb5a2 authored by Piotr Raczynski's avatar Piotr Raczynski Committed by Tony Nguyen
Browse files

ice: refactor VF control VSI interrupt handling



All VF control VSIs share the same interrupt vector. Currently, a helper
function dedicated for that directly sets ice_vsi::base_vector.

Use helper that returns pointer to first found VF control VSI instead.

Reviewed-by: default avatarJacob Keller <jacob.e.keller@intel.com>
Reviewed-by: default avatarSimon Horman <simon.horman@corigine.com>
Tested-by: default avatarRafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: default avatarPiotr Raczynski <piotr.raczynski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 05018936
Loading
Loading
Loading
Loading
+19 −66
Original line number Diff line number Diff line
@@ -1473,36 +1473,6 @@ ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id)
	return ice_search_res(res, needed, id);
}

/**
 * ice_get_vf_ctrl_res - Get VF control VSI resource
 * @pf: pointer to the PF structure
 * @vsi: the VSI to allocate a resource for
 *
 * Look up whether another VF has already allocated the control VSI resource.
 * If so, re-use this resource so that we share it among all VFs.
 *
 * Otherwise, allocate the resource and return it.
 */
static int ice_get_vf_ctrl_res(struct ice_pf *pf, struct ice_vsi *vsi)
{
	struct ice_vf *vf;
	unsigned int bkt;
	int base;

	rcu_read_lock();
	ice_for_each_vf_rcu(pf, bkt, vf) {
		if (vf != vsi->vf && vf->ctrl_vsi_idx != ICE_NO_VSI) {
			base = pf->vsi[vf->ctrl_vsi_idx]->base_vector;
			rcu_read_unlock();
			return base;
		}
	}
	rcu_read_unlock();

	return ice_get_res(pf, pf->irq_tracker, vsi->num_q_vectors,
			   ICE_RES_VF_CTRL_VEC_ID);
}

/**
 * ice_vsi_setup_vector_base - Set up the base vector for the given VSI
 * @vsi: ptr to the VSI
@@ -1516,8 +1486,8 @@ static int ice_get_vf_ctrl_res(struct ice_pf *pf, struct ice_vsi *vsi)
static int ice_vsi_setup_vector_base(struct ice_vsi *vsi)
{
	struct ice_pf *pf = vsi->back;
	u16 num_q_vectors, id;
	struct device *dev;
	u16 num_q_vectors;
	int base;

	dev = ice_pf_to_dev(pf);
@@ -1536,12 +1506,20 @@ static int ice_vsi_setup_vector_base(struct ice_vsi *vsi)
	num_q_vectors = vsi->num_q_vectors;
	/* reserve slots from OS requested IRQs */
	if (vsi->type == ICE_VSI_CTRL && vsi->vf) {
		base = ice_get_vf_ctrl_res(pf, vsi);
		struct ice_vsi *ctrl_vsi = ice_get_vf_ctrl_vsi(pf, vsi);

		/* reuse VF control VSI interrupt vector */
		if (ctrl_vsi) {
			vsi->base_vector = ctrl_vsi->base_vector;
			return 0;
		}

		id = ICE_RES_VF_CTRL_VEC_ID;
	} else {
		base = ice_get_res(pf, pf->irq_tracker, num_q_vectors,
				   vsi->idx);
		id = vsi->idx;
	}

	base = ice_get_res(pf, pf->irq_tracker, num_q_vectors, id);
	if (base < 0) {
		dev_err(dev, "%d MSI-X interrupts available. %s %d failed to get %d MSI-X vectors\n",
			ice_get_free_res_count(pf->irq_tracker),
@@ -2611,37 +2589,6 @@ static void ice_set_agg_vsi(struct ice_vsi *vsi)
		vsi->agg_node->num_vsis);
}

/**
 * ice_free_vf_ctrl_res - Free the VF control VSI resource
 * @pf: pointer to PF structure
 * @vsi: the VSI to free resources for
 *
 * Check if the VF control VSI resource is still in use. If no VF is using it
 * any more, release the VSI resource. Otherwise, leave it to be cleaned up
 * once no other VF uses it.
 */
static void ice_free_vf_ctrl_res(struct ice_pf *pf,  struct ice_vsi *vsi)
{
	struct ice_vf *vf;
	unsigned int bkt;

	rcu_read_lock();
	ice_for_each_vf_rcu(pf, bkt, vf) {
		if (vf != vsi->vf && vf->ctrl_vsi_idx != ICE_NO_VSI) {
			rcu_read_unlock();
			return;
		}
	}
	rcu_read_unlock();

	/* No other VFs left that have control VSI. It is now safe to reclaim
	 * SW interrupts back to the common pool.
	 */
	ice_free_res(pf->irq_tracker, vsi->base_vector,
		     ICE_RES_VF_CTRL_VEC_ID);
	pf->num_avail_sw_msix += vsi->num_q_vectors;
}

static int ice_vsi_cfg_tc_lan(struct ice_pf *pf, struct ice_vsi *vsi)
{
	u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
@@ -2916,7 +2863,13 @@ void ice_vsi_decfg(struct ice_vsi *vsi)
	 * cleared in the same manner.
	 */
	if (vsi->type == ICE_VSI_CTRL && vsi->vf) {
		ice_free_vf_ctrl_res(pf, vsi);
		struct ice_vsi *ctrl_vsi = ice_get_vf_ctrl_vsi(pf, vsi);

		if (!ctrl_vsi) {
			ice_free_res(pf->irq_tracker, vsi->base_vector,
				     ICE_RES_VF_CTRL_VEC_ID);
			pf->num_avail_sw_msix += vsi->num_q_vectors;
		}
	} else if (vsi->type != ICE_VSI_VF) {
		/* reclaim SW interrupts back to the common pool */
		ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);
+32 −0
Original line number Diff line number Diff line
@@ -1310,3 +1310,35 @@ void ice_vf_set_initialized(struct ice_vf *vf)
	set_bit(ICE_VF_STATE_INIT, vf->vf_states);
	memset(&vf->vlan_v2_caps, 0, sizeof(vf->vlan_v2_caps));
}

/**
 * ice_get_vf_ctrl_vsi - Get first VF control VSI pointer
 * @pf: the PF private structure
 * @vsi: pointer to the VSI
 *
 * Return first found VF control VSI other than the vsi
 * passed by parameter. This function is used to determine
 * whether new resources have to be allocated for control VSI
 * or they can be shared with existing one.
 *
 * Return found VF control VSI pointer other itself. Return
 * NULL Otherwise.
 *
 */
struct ice_vsi *ice_get_vf_ctrl_vsi(struct ice_pf *pf, struct ice_vsi *vsi)
{
	struct ice_vsi *ctrl_vsi = NULL;
	struct ice_vf *vf;
	unsigned int bkt;

	rcu_read_lock();
	ice_for_each_vf_rcu(pf, bkt, vf) {
		if (vf != vsi->vf && vf->ctrl_vsi_idx != ICE_NO_VSI) {
			ctrl_vsi = pf->vsi[vf->ctrl_vsi_idx];
			break;
		}
	}

	rcu_read_unlock();
	return ctrl_vsi;
}
+7 −0
Original line number Diff line number Diff line
@@ -226,6 +226,7 @@ int
ice_vf_clear_vsi_promisc(struct ice_vf *vf, struct ice_vsi *vsi, u8 promisc_m);
int ice_reset_vf(struct ice_vf *vf, u32 flags);
void ice_reset_all_vfs(struct ice_pf *pf);
struct ice_vsi *ice_get_vf_ctrl_vsi(struct ice_pf *pf, struct ice_vsi *vsi);
#else /* CONFIG_PCI_IOV */
static inline struct ice_vf *ice_get_vf_by_id(struct ice_pf *pf, u16 vf_id)
{
@@ -290,6 +291,12 @@ static inline int ice_reset_vf(struct ice_vf *vf, u32 flags)
static inline void ice_reset_all_vfs(struct ice_pf *pf)
{
}

static inline struct ice_vsi *
ice_get_vf_ctrl_vsi(struct ice_pf *pf, struct ice_vsi *vsi)
{
	return NULL;
}
#endif /* !CONFIG_PCI_IOV */

#endif /* _ICE_VF_LIB_H_ */