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

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
...@@ -1473,36 +1473,6 @@ ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id) ...@@ -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); 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 * ice_vsi_setup_vector_base - Set up the base vector for the given VSI
* @vsi: ptr to the 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) ...@@ -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) static int ice_vsi_setup_vector_base(struct ice_vsi *vsi)
{ {
struct ice_pf *pf = vsi->back; struct ice_pf *pf = vsi->back;
u16 num_q_vectors, id;
struct device *dev; struct device *dev;
u16 num_q_vectors;
int base; int base;
dev = ice_pf_to_dev(pf); dev = ice_pf_to_dev(pf);
...@@ -1536,12 +1506,20 @@ static int ice_vsi_setup_vector_base(struct ice_vsi *vsi) ...@@ -1536,12 +1506,20 @@ static int ice_vsi_setup_vector_base(struct ice_vsi *vsi)
num_q_vectors = vsi->num_q_vectors; num_q_vectors = vsi->num_q_vectors;
/* reserve slots from OS requested IRQs */ /* reserve slots from OS requested IRQs */
if (vsi->type == ICE_VSI_CTRL && vsi->vf) { 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 { } else {
base = ice_get_res(pf, pf->irq_tracker, num_q_vectors, id = vsi->idx;
vsi->idx);
} }
base = ice_get_res(pf, pf->irq_tracker, num_q_vectors, id);
if (base < 0) { if (base < 0) {
dev_err(dev, "%d MSI-X interrupts available. %s %d failed to get %d MSI-X vectors\n", 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), ice_get_free_res_count(pf->irq_tracker),
...@@ -2611,37 +2589,6 @@ static void ice_set_agg_vsi(struct ice_vsi *vsi) ...@@ -2611,37 +2589,6 @@ static void ice_set_agg_vsi(struct ice_vsi *vsi)
vsi->agg_node->num_vsis); 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) static int ice_vsi_cfg_tc_lan(struct ice_pf *pf, struct ice_vsi *vsi)
{ {
u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
...@@ -2916,7 +2863,13 @@ void ice_vsi_decfg(struct ice_vsi *vsi) ...@@ -2916,7 +2863,13 @@ void ice_vsi_decfg(struct ice_vsi *vsi)
* cleared in the same manner. * cleared in the same manner.
*/ */
if (vsi->type == ICE_VSI_CTRL && vsi->vf) { 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) { } else if (vsi->type != ICE_VSI_VF) {
/* reclaim SW interrupts back to the common pool */ /* reclaim SW interrupts back to the common pool */
ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx); ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);
......
...@@ -1310,3 +1310,35 @@ void ice_vf_set_initialized(struct ice_vf *vf) ...@@ -1310,3 +1310,35 @@ void ice_vf_set_initialized(struct ice_vf *vf)
set_bit(ICE_VF_STATE_INIT, vf->vf_states); set_bit(ICE_VF_STATE_INIT, vf->vf_states);
memset(&vf->vlan_v2_caps, 0, sizeof(vf->vlan_v2_caps)); 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;
}
...@@ -226,6 +226,7 @@ int ...@@ -226,6 +226,7 @@ int
ice_vf_clear_vsi_promisc(struct ice_vf *vf, struct ice_vsi *vsi, u8 promisc_m); 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); int ice_reset_vf(struct ice_vf *vf, u32 flags);
void ice_reset_all_vfs(struct ice_pf *pf); 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 */ #else /* CONFIG_PCI_IOV */
static inline struct ice_vf *ice_get_vf_by_id(struct ice_pf *pf, u16 vf_id) 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) ...@@ -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 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 /* !CONFIG_PCI_IOV */
#endif /* _ICE_VF_LIB_H_ */ #endif /* _ICE_VF_LIB_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment