Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue

Tony Nguyen says:

====================
100GbE Intel Wired LAN Driver Updates 2022-03-03

Jacob Keller says:

This series refactors the ice networking driver VF storage from a simple
static array to a hash table. It also introduces krefs and proper locking
and protection to prevent common use-after-free and concurrency issues.

There are two motivations for this work. First is to make the ice driver
more resilient by preventing a whole class of use-after-free bugs that can
occur around concurrent access to VF structures while removing VFs.

The second is to prepare the ice driver for future virtualization work to
support Scalable IOV, an alternative VF implementation compared to Single
Root IOV. The new VF implementation will allow for more dynamic VF creation
and removal, necessitating a more robust implementation for VF storage that
can't rely on the existing mechanisms to prevent concurrent access
violations.

The first few patches are cleanup and preparatory work needed to make the
conversion to the hash table safe. Following this preparatory work is a
patch to migrate the VF structures and variables to a new sub-structure for
code clarity. Next introduce new interface functions to abstract the VF
storage. Finally, the driver is actually converted to the hash table and
kref implementation.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2022-03-04 09:45:51 +00:00
commit 4ee508ff78
13 changed files with 880 additions and 562 deletions

View File

@ -109,7 +109,6 @@
/* All VF control VSIs share the same IRQ, so assign a unique ID for them */
#define ICE_RES_VF_CTRL_VEC_ID (ICE_RES_RDMA_VEC_ID - 1)
#define ICE_INVAL_Q_INDEX 0xffff
#define ICE_INVAL_VFID 256
#define ICE_MAX_RXQS_PER_TC 256 /* Used when setting VSI context per TC Rx queues */
@ -333,7 +332,7 @@ struct ice_vsi {
u16 vsi_num; /* HW (absolute) index of this VSI */
u16 idx; /* software index in pf->vsi[] */
s16 vf_id; /* VF ID for SR-IOV VSIs */
struct ice_vf *vf; /* VF associated with this VSI */
u16 ethtype; /* Ethernet protocol for pause frame */
u16 num_gfltr;
@ -529,15 +528,7 @@ struct ice_pf {
struct ice_vsi **vsi; /* VSIs created by the driver */
struct ice_sw *first_sw; /* first switch created by firmware */
u16 eswitch_mode; /* current mode of eswitch */
/* Virtchnl/SR-IOV config info */
struct ice_vf *vf;
u16 num_alloc_vfs; /* actual number of VFs allocated */
u16 num_vfs_supported; /* num VFs supported for this PF */
u16 num_qps_per_vf;
u16 num_msix_per_vf;
/* used to ratelimit the MDD event logging */
unsigned long last_printed_mdd_jiffies;
DECLARE_BITMAP(malvfs, ICE_MAX_VF_COUNT);
struct ice_vfs vfs;
DECLARE_BITMAP(features, ICE_F_MAX);
DECLARE_BITMAP(state, ICE_STATE_NBITS);
DECLARE_BITMAP(flags, ICE_PF_FLAGS_NBITS);

View File

@ -323,7 +323,7 @@ ice_setup_tx_ctx(struct ice_tx_ring *ring, struct ice_tlan_ctx *tlan_ctx, u16 pf
break;
case ICE_VSI_VF:
/* Firmware expects vmvf_num to be absolute VF ID */
tlan_ctx->vmvf_num = hw->func_caps.vf_base_id + vsi->vf_id;
tlan_ctx->vmvf_num = hw->func_caps.vf_base_id + vsi->vf->vf_id;
tlan_ctx->vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_VF;
break;
case ICE_VSI_SWITCHDEV_CTRL:
@ -429,7 +429,7 @@ static int ice_setup_rx_ctx(struct ice_rx_ring *ring)
*/
if (ice_is_dvm_ena(hw))
if (vsi->type == ICE_VSI_VF &&
ice_vf_is_port_vlan_ena(&vsi->back->vf[vsi->vf_id]))
ice_vf_is_port_vlan_ena(vsi->vf))
rlan_ctx.l2tsel = 1;
else
rlan_ctx.l2tsel = 0;

View File

@ -176,10 +176,20 @@ static void ice_eswitch_remap_rings_to_vectors(struct ice_pf *pf)
int q_id;
ice_for_each_txq(vsi, q_id) {
struct ice_repr *repr = pf->vf[q_id].repr;
struct ice_q_vector *q_vector = repr->q_vector;
struct ice_tx_ring *tx_ring = vsi->tx_rings[q_id];
struct ice_rx_ring *rx_ring = vsi->rx_rings[q_id];
struct ice_q_vector *q_vector;
struct ice_tx_ring *tx_ring;
struct ice_rx_ring *rx_ring;
struct ice_repr *repr;
struct ice_vf *vf;
vf = ice_get_vf_by_id(pf, q_id);
if (WARN_ON(!vf))
continue;
repr = vf->repr;
q_vector = repr->q_vector;
tx_ring = vsi->tx_rings[q_id];
rx_ring = vsi->rx_rings[q_id];
q_vector->vsi = vsi;
q_vector->reg_idx = vsi->q_vectors[0]->reg_idx;
@ -199,6 +209,38 @@ static void ice_eswitch_remap_rings_to_vectors(struct ice_pf *pf)
rx_ring->q_vector = q_vector;
rx_ring->next = NULL;
rx_ring->netdev = repr->netdev;
ice_put_vf(vf);
}
}
/**
* ice_eswitch_release_reprs - clear PR VSIs configuration
* @pf: poiner to PF struct
* @ctrl_vsi: pointer to switchdev control VSI
*/
static void
ice_eswitch_release_reprs(struct ice_pf *pf, struct ice_vsi *ctrl_vsi)
{
struct ice_vf *vf;
unsigned int bkt;
lockdep_assert_held(&pf->vfs.table_lock);
ice_for_each_vf(pf, bkt, vf) {
struct ice_vsi *vsi = vf->repr->src_vsi;
/* Skip VFs that aren't configured */
if (!vf->repr->dst)
continue;
ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof);
metadata_dst_free(vf->repr->dst);
vf->repr->dst = NULL;
ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr.addr,
ICE_FWD_TO_VSI);
netif_napi_del(&vf->repr->q_vector->napi);
}
}
@ -210,11 +252,13 @@ static int ice_eswitch_setup_reprs(struct ice_pf *pf)
{
struct ice_vsi *ctrl_vsi = pf->switchdev.control_vsi;
int max_vsi_num = 0;
int i;
struct ice_vf *vf;
unsigned int bkt;
ice_for_each_vf(pf, i) {
struct ice_vsi *vsi = pf->vf[i].repr->src_vsi;
struct ice_vf *vf = &pf->vf[i];
lockdep_assert_held(&pf->vfs.table_lock);
ice_for_each_vf(pf, bkt, vf) {
struct ice_vsi *vsi = vf->repr->src_vsi;
ice_remove_vsi_fltr(&pf->hw, vsi->idx);
vf->repr->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX,
@ -231,6 +275,7 @@ static int ice_eswitch_setup_reprs(struct ice_pf *pf)
vf->hw_lan_addr.addr,
ICE_FWD_TO_VSI);
metadata_dst_free(vf->repr->dst);
vf->repr->dst = NULL;
goto err;
}
@ -239,6 +284,7 @@ static int ice_eswitch_setup_reprs(struct ice_pf *pf)
vf->hw_lan_addr.addr,
ICE_FWD_TO_VSI);
metadata_dst_free(vf->repr->dst);
vf->repr->dst = NULL;
ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof);
goto err;
}
@ -252,8 +298,8 @@ static int ice_eswitch_setup_reprs(struct ice_pf *pf)
netif_keep_dst(vf->repr->netdev);
}
ice_for_each_vf(pf, i) {
struct ice_repr *repr = pf->vf[i].repr;
ice_for_each_vf(pf, bkt, vf) {
struct ice_repr *repr = vf->repr;
struct ice_vsi *vsi = repr->src_vsi;
struct metadata_dst *dst;
@ -266,42 +312,11 @@ static int ice_eswitch_setup_reprs(struct ice_pf *pf)
return 0;
err:
for (i = i - 1; i >= 0; i--) {
struct ice_vsi *vsi = pf->vf[i].repr->src_vsi;
struct ice_vf *vf = &pf->vf[i];
ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof);
metadata_dst_free(vf->repr->dst);
ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr.addr,
ICE_FWD_TO_VSI);
}
ice_eswitch_release_reprs(pf, ctrl_vsi);
return -ENODEV;
}
/**
* ice_eswitch_release_reprs - clear PR VSIs configuration
* @pf: poiner to PF struct
* @ctrl_vsi: pointer to switchdev control VSI
*/
static void
ice_eswitch_release_reprs(struct ice_pf *pf, struct ice_vsi *ctrl_vsi)
{
int i;
ice_for_each_vf(pf, i) {
struct ice_vsi *vsi = pf->vf[i].repr->src_vsi;
struct ice_vf *vf = &pf->vf[i];
ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof);
metadata_dst_free(vf->repr->dst);
ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr.addr,
ICE_FWD_TO_VSI);
netif_napi_del(&vf->repr->q_vector->napi);
}
}
/**
* ice_eswitch_update_repr - reconfigure VF port representor
* @vsi: VF VSI for which port representor is configured
@ -316,7 +331,7 @@ void ice_eswitch_update_repr(struct ice_vsi *vsi)
if (!ice_is_switchdev_running(pf))
return;
vf = &pf->vf[vsi->vf_id];
vf = vsi->vf;
repr = vf->repr;
repr->src_vsi = vsi;
repr->dst->u.port_info.port_id = vsi->vsi_num;
@ -324,7 +339,8 @@ void ice_eswitch_update_repr(struct ice_vsi *vsi)
ret = ice_vsi_update_security(vsi, ice_vsi_ctx_clear_antispoof);
if (ret) {
ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr.addr, ICE_FWD_TO_VSI);
dev_err(ice_pf_to_dev(pf), "Failed to update VF %d port representor", vsi->vf_id);
dev_err(ice_pf_to_dev(pf), "Failed to update VF %d port representor",
vsi->vf->vf_id);
}
}
@ -408,7 +424,7 @@ static void ice_eswitch_release_env(struct ice_pf *pf)
static struct ice_vsi *
ice_eswitch_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)
{
return ice_vsi_setup(pf, pi, ICE_VSI_SWITCHDEV_CTRL, ICE_INVAL_VFID, NULL);
return ice_vsi_setup(pf, pi, ICE_VSI_SWITCHDEV_CTRL, NULL, NULL);
}
/**
@ -417,10 +433,13 @@ ice_eswitch_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)
*/
static void ice_eswitch_napi_del(struct ice_pf *pf)
{
int i;
struct ice_vf *vf;
unsigned int bkt;
ice_for_each_vf(pf, i)
netif_napi_del(&pf->vf[i].repr->q_vector->napi);
lockdep_assert_held(&pf->vfs.table_lock);
ice_for_each_vf(pf, bkt, vf)
netif_napi_del(&vf->repr->q_vector->napi);
}
/**
@ -429,10 +448,13 @@ static void ice_eswitch_napi_del(struct ice_pf *pf)
*/
static void ice_eswitch_napi_enable(struct ice_pf *pf)
{
int i;
struct ice_vf *vf;
unsigned int bkt;
ice_for_each_vf(pf, i)
napi_enable(&pf->vf[i].repr->q_vector->napi);
lockdep_assert_held(&pf->vfs.table_lock);
ice_for_each_vf(pf, bkt, vf)
napi_enable(&vf->repr->q_vector->napi);
}
/**
@ -441,10 +463,13 @@ static void ice_eswitch_napi_enable(struct ice_pf *pf)
*/
static void ice_eswitch_napi_disable(struct ice_pf *pf)
{
int i;
struct ice_vf *vf;
unsigned int bkt;
ice_for_each_vf(pf, i)
napi_disable(&pf->vf[i].repr->q_vector->napi);
lockdep_assert_held(&pf->vfs.table_lock);
ice_for_each_vf(pf, bkt, vf)
napi_disable(&vf->repr->q_vector->napi);
}
/**
@ -522,7 +547,7 @@ ice_eswitch_mode_set(struct devlink *devlink, u16 mode,
if (pf->eswitch_mode == mode)
return 0;
if (pf->num_alloc_vfs) {
if (ice_has_vfs(pf)) {
dev_info(ice_pf_to_dev(pf), "Changing eswitch mode is allowed only if there is no VFs created");
NL_SET_ERR_MSG_MOD(extack, "Changing eswitch mode is allowed only if there is no VFs created");
return -EOPNOTSUPP;
@ -613,16 +638,17 @@ int ice_eswitch_configure(struct ice_pf *pf)
*/
static void ice_eswitch_start_all_tx_queues(struct ice_pf *pf)
{
struct ice_repr *repr;
int i;
struct ice_vf *vf;
unsigned int bkt;
lockdep_assert_held(&pf->vfs.table_lock);
if (test_bit(ICE_DOWN, pf->state))
return;
ice_for_each_vf(pf, i) {
repr = pf->vf[i].repr;
if (repr)
ice_repr_start_tx_queues(repr);
ice_for_each_vf(pf, bkt, vf) {
if (vf->repr)
ice_repr_start_tx_queues(vf->repr);
}
}
@ -632,16 +658,17 @@ static void ice_eswitch_start_all_tx_queues(struct ice_pf *pf)
*/
void ice_eswitch_stop_all_tx_queues(struct ice_pf *pf)
{
struct ice_repr *repr;
int i;
struct ice_vf *vf;
unsigned int bkt;
lockdep_assert_held(&pf->vfs.table_lock);
if (test_bit(ICE_DOWN, pf->state))
return;
ice_for_each_vf(pf, i) {
repr = pf->vf[i].repr;
if (repr)
ice_repr_stop_tx_queues(repr);
ice_for_each_vf(pf, bkt, vf) {
if (vf->repr)
ice_repr_stop_tx_queues(vf->repr);
}
}

View File

@ -316,16 +316,20 @@ ice_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
*/
static bool ice_active_vfs(struct ice_pf *pf)
{
unsigned int i;
bool active = false;
struct ice_vf *vf;
unsigned int bkt;
ice_for_each_vf(pf, i) {
struct ice_vf *vf = &pf->vf[i];
if (test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))
return true;
rcu_read_lock();
ice_for_each_vf_rcu(pf, bkt, vf) {
if (test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
active = true;
break;
}
}
rcu_read_unlock();
return false;
return active;
}
/**
@ -1298,7 +1302,7 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags)
}
if (test_bit(ICE_FLAG_VF_VLAN_PRUNING, change_flags) &&
pf->num_alloc_vfs) {
ice_has_vfs(pf)) {
dev_err(dev, "vf-vlan-pruning: VLAN pruning cannot be changed while VFs are active.\n");
/* toggle bit back to previous state */
change_bit(ICE_FLAG_VF_VLAN_PRUNING, pf->flags);

View File

@ -166,21 +166,19 @@ static void ice_vsi_set_num_desc(struct ice_vsi *vsi)
/**
* ice_vsi_set_num_qs - Set number of queues, descriptors and vectors for a VSI
* @vsi: the VSI being configured
* @vf_id: ID of the VF being configured
* @vf: the VF associated with this VSI, if any
*
* Return 0 on success and a negative value on error
*/
static void ice_vsi_set_num_qs(struct ice_vsi *vsi, u16 vf_id)
static void ice_vsi_set_num_qs(struct ice_vsi *vsi, struct ice_vf *vf)
{
enum ice_vsi_type vsi_type = vsi->type;
struct ice_pf *pf = vsi->back;
struct ice_vf *vf = NULL;
if (vsi->type == ICE_VSI_VF)
vsi->vf_id = vf_id;
else
vsi->vf_id = ICE_INVAL_VFID;
if (WARN_ON(vsi_type == ICE_VSI_VF && !vf))
return;
switch (vsi->type) {
switch (vsi_type) {
case ICE_VSI_PF:
if (vsi->req_txq) {
vsi->alloc_txq = vsi->req_txq;
@ -217,22 +215,21 @@ static void ice_vsi_set_num_qs(struct ice_vsi *vsi, u16 vf_id)
/* The number of queues for ctrl VSI is equal to number of VFs.
* Each ring is associated to the corresponding VF_PR netdev.
*/
vsi->alloc_txq = pf->num_alloc_vfs;
vsi->alloc_rxq = pf->num_alloc_vfs;
vsi->alloc_txq = ice_get_num_vfs(pf);
vsi->alloc_rxq = vsi->alloc_txq;
vsi->num_q_vectors = 1;
break;
case ICE_VSI_VF:
vf = &pf->vf[vsi->vf_id];
if (vf->num_req_qs)
vf->num_vf_qs = vf->num_req_qs;
vsi->alloc_txq = vf->num_vf_qs;
vsi->alloc_rxq = vf->num_vf_qs;
/* pf->num_msix_per_vf includes (VF miscellaneous vector +
/* pf->vfs.num_msix_per includes (VF miscellaneous vector +
* data queue interrupts). Since vsi->num_q_vectors is number
* of queues vectors, subtract 1 (ICE_NONQ_VECS_VF) from the
* original vector count
*/
vsi->num_q_vectors = pf->num_msix_per_vf - ICE_NONQ_VECS_VF;
vsi->num_q_vectors = pf->vfs.num_msix_per - ICE_NONQ_VECS_VF;
break;
case ICE_VSI_CTRL:
vsi->alloc_txq = 1;
@ -248,7 +245,7 @@ static void ice_vsi_set_num_qs(struct ice_vsi *vsi, u16 vf_id)
vsi->alloc_rxq = 1;
break;
default:
dev_warn(ice_pf_to_dev(pf), "Unknown VSI type %d\n", vsi->type);
dev_warn(ice_pf_to_dev(pf), "Unknown VSI type %d\n", vsi_type);
break;
}
@ -299,7 +296,7 @@ void ice_vsi_delete(struct ice_vsi *vsi)
return;
if (vsi->type == ICE_VSI_VF)
ctxt->vf_num = vsi->vf_id;
ctxt->vf_num = vsi->vf->vf_id;
ctxt->vsi_num = vsi->vsi_num;
memcpy(&ctxt->info, &vsi->info, sizeof(ctxt->info));
@ -384,8 +381,7 @@ int ice_vsi_clear(struct ice_vsi *vsi)
pf->vsi[vsi->idx] = NULL;
if (vsi->idx < pf->next_vsi && vsi->type != ICE_VSI_CTRL)
pf->next_vsi = vsi->idx;
if (vsi->idx < pf->next_vsi && vsi->type == ICE_VSI_CTRL &&
vsi->vf_id != ICE_INVAL_VFID)
if (vsi->idx < pf->next_vsi && vsi->type == ICE_VSI_CTRL && vsi->vf)
pf->next_vsi = vsi->idx;
ice_vsi_free_arrays(vsi);
@ -437,13 +433,16 @@ static irqreturn_t ice_eswitch_msix_clean_rings(int __always_unused irq, void *d
{
struct ice_q_vector *q_vector = (struct ice_q_vector *)data;
struct ice_pf *pf = q_vector->vsi->back;
int i;
struct ice_vf *vf;
unsigned int bkt;
if (!q_vector->tx.tx_ring && !q_vector->rx.rx_ring)
return IRQ_HANDLED;
ice_for_each_vf(pf, i)
napi_schedule(&pf->vf[i].repr->q_vector->napi);
rcu_read_lock();
ice_for_each_vf_rcu(pf, bkt, vf)
napi_schedule(&vf->repr->q_vector->napi);
rcu_read_unlock();
return IRQ_HANDLED;
}
@ -453,17 +452,24 @@ static irqreturn_t ice_eswitch_msix_clean_rings(int __always_unused irq, void *d
* @pf: board private structure
* @vsi_type: type of VSI
* @ch: ptr to channel
* @vf_id: ID of the VF being configured
* @vf: VF for ICE_VSI_VF and ICE_VSI_CTRL
*
* The VF pointer is used for ICE_VSI_VF and ICE_VSI_CTRL. For ICE_VSI_CTRL,
* it may be NULL in the case there is no association with a VF. For
* ICE_VSI_VF the VF pointer *must not* be NULL.
*
* returns a pointer to a VSI on success, NULL on failure.
*/
static struct ice_vsi *
ice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type vsi_type,
struct ice_channel *ch, u16 vf_id)
struct ice_channel *ch, struct ice_vf *vf)
{
struct device *dev = ice_pf_to_dev(pf);
struct ice_vsi *vsi = NULL;
if (WARN_ON(vsi_type == ICE_VSI_VF && !vf))
return NULL;
/* Need to protect the allocation of the VSIs at the PF level */
mutex_lock(&pf->sw_mutex);
@ -485,9 +491,9 @@ ice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type vsi_type,
set_bit(ICE_VSI_DOWN, vsi->state);
if (vsi_type == ICE_VSI_VF)
ice_vsi_set_num_qs(vsi, vf_id);
ice_vsi_set_num_qs(vsi, vf);
else if (vsi_type != ICE_VSI_CHNL)
ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID);
ice_vsi_set_num_qs(vsi, NULL);
switch (vsi->type) {
case ICE_VSI_SWITCHDEV_CTRL:
@ -510,10 +516,16 @@ ice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type vsi_type,
/* Setup ctrl VSI MSIX irq handler */
vsi->irq_handler = ice_msix_clean_ctrl_vsi;
/* For the PF control VSI this is NULL, for the VF control VSI
* this will be the first VF to allocate it.
*/
vsi->vf = vf;
break;
case ICE_VSI_VF:
if (ice_vsi_alloc_arrays(vsi))
goto err_rings;
vsi->vf = vf;
break;
case ICE_VSI_CHNL:
if (!ch)
@ -531,7 +543,7 @@ ice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type vsi_type,
goto unlock_pf;
}
if (vsi->type == ICE_VSI_CTRL && vf_id == ICE_INVAL_VFID) {
if (vsi->type == ICE_VSI_CTRL && !vf) {
/* Use the last VSI slot as the index for PF control VSI */
vsi->idx = pf->num_alloc_vsi - 1;
pf->ctrl_vsi_idx = vsi->idx;
@ -546,8 +558,8 @@ ice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type vsi_type,
pf->next_vsi);
}
if (vsi->type == ICE_VSI_CTRL && vf_id != ICE_INVAL_VFID)
pf->vf[vf_id].ctrl_vsi_idx = vsi->idx;
if (vsi->type == ICE_VSI_CTRL && vf)
vf->ctrl_vsi_idx = vsi->idx;
goto unlock_pf;
err_rings:
@ -1130,7 +1142,7 @@ static int ice_vsi_init(struct ice_vsi *vsi, bool init_vsi)
case ICE_VSI_VF:
ctxt->flags = ICE_AQ_VSI_TYPE_VF;
/* VF number here is the absolute VF number (0-255) */
ctxt->vf_num = vsi->vf_id + hw->func_caps.vf_base_id;
ctxt->vf_num = vsi->vf->vf_id + hw->func_caps.vf_base_id;
break;
default:
ret = -ENODEV;
@ -1321,6 +1333,36 @@ 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
@ -1353,20 +1395,8 @@ 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_id != ICE_INVAL_VFID) {
int i;
ice_for_each_vf(pf, i) {
struct ice_vf *vf = &pf->vf[i];
if (i != vsi->vf_id && vf->ctrl_vsi_idx != ICE_NO_VSI) {
base = pf->vsi[vf->ctrl_vsi_idx]->base_vector;
break;
}
}
if (i == pf->num_alloc_vfs)
base = ice_get_res(pf, pf->irq_tracker, num_q_vectors,
ICE_RES_VF_CTRL_VEC_ID);
if (vsi->type == ICE_VSI_CTRL && vsi->vf) {
base = ice_get_vf_ctrl_res(pf, vsi);
} else {
base = ice_get_res(pf, pf->irq_tracker, num_q_vectors,
vsi->idx);
@ -2218,7 +2248,7 @@ ice_vsi_set_q_vectors_reg_idx(struct ice_vsi *vsi)
}
if (vsi->type == ICE_VSI_VF) {
struct ice_vf *vf = &vsi->back->vf[vsi->vf_id];
struct ice_vf *vf = vsi->vf;
q_vector->reg_idx = ice_calc_vf_reg_idx(vf, q_vector);
} else {
@ -2403,9 +2433,8 @@ static void ice_set_agg_vsi(struct ice_vsi *vsi)
* @pf: board private structure
* @pi: pointer to the port_info instance
* @vsi_type: VSI type
* @vf_id: defines VF ID to which this VSI connects. This field is meant to be
* used only for ICE_VSI_VF VSI type. For other VSI types, should
* fill-in ICE_INVAL_VFID as input.
* @vf: pointer to VF to which this VSI connects. This field is used primarily
* for the ICE_VSI_VF type. Other VSI types should pass NULL.
* @ch: ptr to channel
*
* This allocates the sw VSI structure and its queue resources.
@ -2415,7 +2444,8 @@ static void ice_set_agg_vsi(struct ice_vsi *vsi)
*/
struct ice_vsi *
ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
enum ice_vsi_type vsi_type, u16 vf_id, struct ice_channel *ch)
enum ice_vsi_type vsi_type, struct ice_vf *vf,
struct ice_channel *ch)
{
u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
struct device *dev = ice_pf_to_dev(pf);
@ -2423,11 +2453,11 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
int ret, i;
if (vsi_type == ICE_VSI_CHNL)
vsi = ice_vsi_alloc(pf, vsi_type, ch, ICE_INVAL_VFID);
vsi = ice_vsi_alloc(pf, vsi_type, ch, NULL);
else if (vsi_type == ICE_VSI_VF || vsi_type == ICE_VSI_CTRL)
vsi = ice_vsi_alloc(pf, vsi_type, NULL, vf_id);
vsi = ice_vsi_alloc(pf, vsi_type, NULL, vf);
else
vsi = ice_vsi_alloc(pf, vsi_type, NULL, ICE_INVAL_VFID);
vsi = ice_vsi_alloc(pf, vsi_type, NULL, NULL);
if (!vsi) {
dev_err(dev, "could not allocate VSI\n");
@ -2439,9 +2469,6 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
if (vsi->type == ICE_VSI_PF)
vsi->ethtype = ETH_P_PAUSE;
if (vsi->type == ICE_VSI_VF || vsi->type == ICE_VSI_CTRL)
vsi->vf_id = vf_id;
ice_alloc_fd_res(vsi);
if (vsi_type != ICE_VSI_CHNL) {
@ -2861,6 +2888,37 @@ void ice_napi_del(struct ice_vsi *vsi)
netif_napi_del(&vsi->q_vectors[v_idx]->napi);
}
/**
* 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;
}
/**
* ice_vsi_release - Delete a VSI and free its resources
* @vsi: the VSI being removed
@ -2904,23 +2962,8 @@ int ice_vsi_release(struct ice_vsi *vsi)
* many interrupts each VF needs. SR-IOV MSIX resources are also
* cleared in the same manner.
*/
if (vsi->type == ICE_VSI_CTRL && vsi->vf_id != ICE_INVAL_VFID) {
int i;
ice_for_each_vf(pf, i) {
struct ice_vf *vf = &pf->vf[i];
if (i != vsi->vf_id && vf->ctrl_vsi_idx != ICE_NO_VSI)
break;
}
if (i == pf->num_alloc_vfs) {
/* No other VFs left that have control VSI, 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;
}
if (vsi->type == ICE_VSI_CTRL && vsi->vf) {
ice_free_vf_ctrl_res(pf, vsi);
} 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);
@ -3104,7 +3147,6 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
struct ice_coalesce_stored *coalesce;
int prev_num_q_vectors = 0;
struct ice_vf *vf = NULL;
enum ice_vsi_type vtype;
struct ice_pf *pf;
int ret, i;
@ -3114,8 +3156,8 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
pf = vsi->back;
vtype = vsi->type;
if (vtype == ICE_VSI_VF)
vf = &pf->vf[vsi->vf_id];
if (WARN_ON(vtype == ICE_VSI_VF) && !vsi->vf)
return -EINVAL;
ice_vsi_init_vlan_ops(vsi);
@ -3154,9 +3196,9 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
ice_vsi_clear_rings(vsi);
ice_vsi_free_arrays(vsi);
if (vtype == ICE_VSI_VF)
ice_vsi_set_num_qs(vsi, vf->vf_id);
ice_vsi_set_num_qs(vsi, vsi->vf);
else
ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID);
ice_vsi_set_num_qs(vsi, NULL);
ret = ice_vsi_alloc_arrays(vsi);
if (ret < 0)
@ -4013,9 +4055,14 @@ static u16 ice_vsi_num_zero_vlans(struct ice_vsi *vsi)
#define ICE_DVM_NUM_ZERO_VLAN_FLTRS 2
#define ICE_SVM_NUM_ZERO_VLAN_FLTRS 1
/* no VLAN 0 filter is created when a port VLAN is active */
if (vsi->type == ICE_VSI_VF &&
ice_vf_is_port_vlan_ena(&vsi->back->vf[vsi->vf_id]))
return 0;
if (vsi->type == ICE_VSI_VF) {
if (WARN_ON(!vsi->vf))
return 0;
if (ice_vf_is_port_vlan_ena(vsi->vf))
return 0;
}
if (ice_is_dvm_ena(&vsi->back->hw))
return ICE_DVM_NUM_ZERO_VLAN_FLTRS;
else

View File

@ -52,7 +52,8 @@ void ice_vsi_cfg_netdev_tc(struct ice_vsi *vsi, u8 ena_tc);
struct ice_vsi *
ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
enum ice_vsi_type vsi_type, u16 vf_id, struct ice_channel *ch);
enum ice_vsi_type vsi_type, struct ice_vf *vf,
struct ice_channel *ch);
void ice_napi_del(struct ice_vsi *vsi);

View File

@ -505,7 +505,8 @@ ice_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type)
{
struct ice_hw *hw = &pf->hw;
struct ice_vsi *vsi;
unsigned int i;
struct ice_vf *vf;
unsigned int bkt;
dev_dbg(ice_pf_to_dev(pf), "reset_type=%d\n", reset_type);
@ -520,8 +521,10 @@ ice_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type)
ice_vc_notify_reset(pf);
/* Disable VFs until reset is completed */
ice_for_each_vf(pf, i)
ice_set_vf_state_qs_dis(&pf->vf[i]);
mutex_lock(&pf->vfs.table_lock);
ice_for_each_vf(pf, bkt, vf)
ice_set_vf_state_qs_dis(vf);
mutex_unlock(&pf->vfs.table_lock);
if (ice_is_eswitch_mode_switchdev(pf)) {
if (reset_type != ICE_RESET_PFR)
@ -1666,7 +1669,8 @@ static void ice_handle_mdd_event(struct ice_pf *pf)
{
struct device *dev = ice_pf_to_dev(pf);
struct ice_hw *hw = &pf->hw;
unsigned int i;
struct ice_vf *vf;
unsigned int bkt;
u32 reg;
if (!test_and_clear_bit(ICE_MDD_EVENT_PENDING, pf->state)) {
@ -1754,47 +1758,46 @@ static void ice_handle_mdd_event(struct ice_pf *pf)
/* Check to see if one of the VFs caused an MDD event, and then
* increment counters and set print pending
*/
ice_for_each_vf(pf, i) {
struct ice_vf *vf = &pf->vf[i];
reg = rd32(hw, VP_MDET_TX_PQM(i));
mutex_lock(&pf->vfs.table_lock);
ice_for_each_vf(pf, bkt, vf) {
reg = rd32(hw, VP_MDET_TX_PQM(vf->vf_id));
if (reg & VP_MDET_TX_PQM_VALID_M) {
wr32(hw, VP_MDET_TX_PQM(i), 0xFFFF);
wr32(hw, VP_MDET_TX_PQM(vf->vf_id), 0xFFFF);
vf->mdd_tx_events.count++;
set_bit(ICE_MDD_VF_PRINT_PENDING, pf->state);
if (netif_msg_tx_err(pf))
dev_info(dev, "Malicious Driver Detection event TX_PQM detected on VF %d\n",
i);
vf->vf_id);
}
reg = rd32(hw, VP_MDET_TX_TCLAN(i));
reg = rd32(hw, VP_MDET_TX_TCLAN(vf->vf_id));
if (reg & VP_MDET_TX_TCLAN_VALID_M) {
wr32(hw, VP_MDET_TX_TCLAN(i), 0xFFFF);
wr32(hw, VP_MDET_TX_TCLAN(vf->vf_id), 0xFFFF);
vf->mdd_tx_events.count++;
set_bit(ICE_MDD_VF_PRINT_PENDING, pf->state);
if (netif_msg_tx_err(pf))
dev_info(dev, "Malicious Driver Detection event TX_TCLAN detected on VF %d\n",
i);
vf->vf_id);
}
reg = rd32(hw, VP_MDET_TX_TDPU(i));
reg = rd32(hw, VP_MDET_TX_TDPU(vf->vf_id));
if (reg & VP_MDET_TX_TDPU_VALID_M) {
wr32(hw, VP_MDET_TX_TDPU(i), 0xFFFF);
wr32(hw, VP_MDET_TX_TDPU(vf->vf_id), 0xFFFF);
vf->mdd_tx_events.count++;
set_bit(ICE_MDD_VF_PRINT_PENDING, pf->state);
if (netif_msg_tx_err(pf))
dev_info(dev, "Malicious Driver Detection event TX_TDPU detected on VF %d\n",
i);
vf->vf_id);
}
reg = rd32(hw, VP_MDET_RX(i));
reg = rd32(hw, VP_MDET_RX(vf->vf_id));
if (reg & VP_MDET_RX_VALID_M) {
wr32(hw, VP_MDET_RX(i), 0xFFFF);
wr32(hw, VP_MDET_RX(vf->vf_id), 0xFFFF);
vf->mdd_rx_events.count++;
set_bit(ICE_MDD_VF_PRINT_PENDING, pf->state);
if (netif_msg_rx_err(pf))
dev_info(dev, "Malicious Driver Detection event RX detected on VF %d\n",
i);
vf->vf_id);
/* Since the queue is disabled on VF Rx MDD events, the
* PF can be configured to reset the VF through ethtool
@ -1805,12 +1808,13 @@ static void ice_handle_mdd_event(struct ice_pf *pf)
* reset, so print the event prior to reset.
*/
ice_print_vf_rx_mdd_event(vf);
mutex_lock(&pf->vf[i].cfg_lock);
ice_reset_vf(&pf->vf[i], false);
mutex_unlock(&pf->vf[i].cfg_lock);
mutex_lock(&vf->cfg_lock);
ice_reset_vf(vf, false);
mutex_unlock(&vf->cfg_lock);
}
}
}
mutex_unlock(&pf->vfs.table_lock);
ice_print_vfs_mdd_events(pf);
}
@ -2439,7 +2443,7 @@ static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename)
/* skip this unused q_vector */
continue;
}
if (vsi->type == ICE_VSI_CTRL && vsi->vf_id != ICE_INVAL_VFID)
if (vsi->type == ICE_VSI_CTRL && vsi->vf)
err = devm_request_irq(dev, irq_num, vsi->irq_handler,
IRQF_SHARED, q_vector->name,
q_vector);
@ -3386,14 +3390,14 @@ void ice_fill_rss_lut(u8 *lut, u16 rss_table_size, u16 rss_size)
static struct ice_vsi *
ice_pf_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)
{
return ice_vsi_setup(pf, pi, ICE_VSI_PF, ICE_INVAL_VFID, NULL);
return ice_vsi_setup(pf, pi, ICE_VSI_PF, NULL, NULL);
}
static struct ice_vsi *
ice_chnl_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
struct ice_channel *ch)
{
return ice_vsi_setup(pf, pi, ICE_VSI_CHNL, ICE_INVAL_VFID, ch);
return ice_vsi_setup(pf, pi, ICE_VSI_CHNL, NULL, ch);
}
/**
@ -3407,7 +3411,7 @@ ice_chnl_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
static struct ice_vsi *
ice_ctrl_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)
{
return ice_vsi_setup(pf, pi, ICE_VSI_CTRL, ICE_INVAL_VFID, NULL);
return ice_vsi_setup(pf, pi, ICE_VSI_CTRL, NULL, NULL);
}
/**
@ -3421,7 +3425,7 @@ ice_ctrl_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)
struct ice_vsi *
ice_lb_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)
{
return ice_vsi_setup(pf, pi, ICE_VSI_LB, ICE_INVAL_VFID, NULL);
return ice_vsi_setup(pf, pi, ICE_VSI_LB, NULL, NULL);
}
/**
@ -3680,6 +3684,7 @@ static void ice_deinit_pf(struct ice_pf *pf)
mutex_destroy(&pf->sw_mutex);
mutex_destroy(&pf->tc_mutex);
mutex_destroy(&pf->avail_q_mutex);
mutex_destroy(&pf->vfs.table_lock);
if (pf->avail_txqs) {
bitmap_free(pf->avail_txqs);
@ -3712,7 +3717,7 @@ static void ice_set_pf_caps(struct ice_pf *pf)
clear_bit(ICE_FLAG_SRIOV_CAPABLE, pf->flags);
if (func_caps->common_cap.sr_iov_1_1) {
set_bit(ICE_FLAG_SRIOV_CAPABLE, pf->flags);
pf->num_vfs_supported = min_t(int, func_caps->num_allocd_vfs,
pf->vfs.num_supported = min_t(int, func_caps->num_allocd_vfs,
ICE_MAX_VF_COUNT);
}
clear_bit(ICE_FLAG_RSS_ENA, pf->flags);
@ -3779,6 +3784,9 @@ static int ice_init_pf(struct ice_pf *pf)
return -ENOMEM;
}
mutex_init(&pf->vfs.table_lock);
hash_init(pf->vfs.table);
return 0;
}

View File

@ -284,6 +284,8 @@ static int ice_repr_add(struct ice_vf *vf)
devlink_port_type_eth_set(&vf->devlink_port, repr->netdev);
ice_vc_change_ops_to_repr(&vf->vc_ops);
return 0;
err_netdev:
@ -311,6 +313,9 @@ static int ice_repr_add(struct ice_vf *vf)
*/
static void ice_repr_rem(struct ice_vf *vf)
{
if (!vf->repr)
return;
ice_devlink_destroy_vf_port(vf);
kfree(vf->repr->q_vector);
vf->repr->q_vector = NULL;
@ -323,38 +328,8 @@ static void ice_repr_rem(struct ice_vf *vf)
#endif
kfree(vf->repr);
vf->repr = NULL;
}
/**
* ice_repr_add_for_all_vfs - add port representor for all VFs
* @pf: pointer to PF structure
*/
int ice_repr_add_for_all_vfs(struct ice_pf *pf)
{
int err;
int i;
ice_for_each_vf(pf, i) {
struct ice_vf *vf = &pf->vf[i];
err = ice_repr_add(vf);
if (err)
goto err;
ice_vc_change_ops_to_repr(&vf->vc_ops);
}
return 0;
err:
for (i = i - 1; i >= 0; i--) {
struct ice_vf *vf = &pf->vf[i];
ice_repr_rem(vf);
ice_vc_set_dflt_vf_ops(&vf->vc_ops);
}
return err;
ice_vc_set_dflt_vf_ops(&vf->vc_ops);
}
/**
@ -363,14 +338,39 @@ int ice_repr_add_for_all_vfs(struct ice_pf *pf)
*/
void ice_repr_rem_from_all_vfs(struct ice_pf *pf)
{
int i;
struct ice_vf *vf;
unsigned int bkt;
ice_for_each_vf(pf, i) {
struct ice_vf *vf = &pf->vf[i];
lockdep_assert_held(&pf->vfs.table_lock);
ice_for_each_vf(pf, bkt, vf)
ice_repr_rem(vf);
ice_vc_set_dflt_vf_ops(&vf->vc_ops);
}
/**
* ice_repr_add_for_all_vfs - add port representor for all VFs
* @pf: pointer to PF structure
*/
int ice_repr_add_for_all_vfs(struct ice_pf *pf)
{
struct ice_vf *vf;
unsigned int bkt;
int err;
lockdep_assert_held(&pf->vfs.table_lock);
ice_for_each_vf(pf, bkt, vf) {
err = ice_repr_add(vf);
if (err)
goto err;
}
return 0;
err:
ice_repr_rem_from_all_vfs(pf);
return err;
}
/**

View File

@ -1165,7 +1165,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
struct ice_vsi *ctrl_vsi = rx_ring->vsi;
if (rx_desc->wb.rxdid == FDIR_DESC_RXDID &&
ctrl_vsi->vf_id != ICE_INVAL_VFID)
ctrl_vsi->vf)
ice_vc_fdir_irq_handler(ctrl_vsi, rx_desc);
ice_put_rx_buf(rx_ring, NULL, 0);
cleaned_count++;

View File

@ -34,9 +34,10 @@ void ice_vf_vsi_init_vlan_ops(struct ice_vsi *vsi)
{
struct ice_vsi_vlan_ops *vlan_ops;
struct ice_pf *pf = vsi->back;
struct ice_vf *vf;
struct ice_vf *vf = vsi->vf;
vf = &pf->vf[vsi->vf_id];
if (WARN_ON(!vf))
return;
if (ice_is_dvm_ena(&pf->hw)) {
vlan_ops = &vsi->outer_vlan_ops;
@ -126,9 +127,14 @@ void ice_vf_vsi_init_vlan_ops(struct ice_vsi *vsi)
*/
void ice_vf_vsi_cfg_dvm_legacy_vlan_mode(struct ice_vsi *vsi)
{
struct ice_vf *vf = &vsi->back->vf[vsi->vf_id];
struct device *dev = ice_pf_to_dev(vf->pf);
struct ice_vsi_vlan_ops *vlan_ops;
struct ice_vf *vf = vsi->vf;
struct device *dev;
if (WARN_ON(!vf))
return;
dev = ice_pf_to_dev(vf->pf);
if (!ice_is_dvm_ena(&vsi->back->hw) || ice_vf_is_port_vlan_ena(vf))
return;
@ -192,7 +198,10 @@ void ice_vf_vsi_cfg_dvm_legacy_vlan_mode(struct ice_vsi *vsi)
*/
void ice_vf_vsi_cfg_svm_legacy_vlan_mode(struct ice_vsi *vsi)
{
struct ice_vf *vf = &vsi->back->vf[vsi->vf_id];
struct ice_vf *vf = vsi->vf;
if (WARN_ON(!vf))
return;
if (ice_is_dvm_ena(&vsi->back->hw) || ice_vf_is_port_vlan_ena(vf))
return;

View File

@ -1288,15 +1288,16 @@ ice_vc_fdir_irq_handler(struct ice_vsi *ctrl_vsi,
union ice_32b_rx_flex_desc *rx_desc)
{
struct ice_pf *pf = ctrl_vsi->back;
struct ice_vf *vf = ctrl_vsi->vf;
struct ice_vf_fdir_ctx *ctx_done;
struct ice_vf_fdir_ctx *ctx_irq;
struct ice_vf_fdir *fdir;
unsigned long flags;
struct device *dev;
struct ice_vf *vf;
int ret;
vf = &pf->vf[ctrl_vsi->vf_id];
if (WARN_ON(!vf))
return;
fdir = &vf->fdir;
ctx_done = &fdir->ctx_done;
@ -1571,15 +1572,16 @@ ice_vc_del_fdir_fltr_post(struct ice_vf *vf, struct ice_vf_fdir_ctx *ctx,
*/
void ice_flush_fdir_ctx(struct ice_pf *pf)
{
int i;
struct ice_vf *vf;
unsigned int bkt;
if (!test_and_clear_bit(ICE_FD_VF_FLUSH_CTX, pf->state))
return;
ice_for_each_vf(pf, i) {
mutex_lock(&pf->vfs.table_lock);
ice_for_each_vf(pf, bkt, vf) {
struct device *dev = ice_pf_to_dev(pf);
enum virtchnl_fdir_prgm_status status;
struct ice_vf *vf = &pf->vf[i];
struct ice_vf_fdir_ctx *ctx;
unsigned long flags;
int ret;
@ -1633,6 +1635,7 @@ void ice_flush_fdir_ctx(struct ice_pf *pf)
ctx->flags &= ~ICE_VF_FDIR_CTX_VALID;
spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags);
}
mutex_unlock(&pf->vfs.table_lock);
}
/**

File diff suppressed because it is too large Load Diff

View File

@ -39,8 +39,50 @@
#define ICE_MAX_VF_RESET_TRIES 40
#define ICE_MAX_VF_RESET_SLEEP_MS 20
#define ice_for_each_vf(pf, i) \
for ((i) = 0; (i) < (pf)->num_alloc_vfs; (i)++)
/* VF Hash Table access functions
*
* These functions provide abstraction for interacting with the VF hash table.
* In general, direct access to the hash table should be avoided outside of
* these functions where possible.
*
* The VF entries in the hash table are protected by reference counting to
* track lifetime of accesses from the table. The ice_get_vf_by_id() function
* obtains a reference to the VF structure which must be dropped by using
* ice_put_vf().
*/
/**
* ice_for_each_vf - Iterate over each VF entry
* @pf: pointer to the PF private structure
* @bkt: bucket index used for iteration
* @vf: pointer to the VF entry currently being processed in the loop.
*
* The bkt variable is an unsigned integer iterator used to traverse the VF
* entries. It is *not* guaranteed to be the VF's vf_id. Do not assume it is.
* Use vf->vf_id to get the id number if needed.
*
* The caller is expected to be under the table_lock mutex for the entire
* loop. Use this iterator if your loop is long or if it might sleep.
*/
#define ice_for_each_vf(pf, bkt, vf) \
hash_for_each((pf)->vfs.table, (bkt), (vf), entry)
/**
* ice_for_each_vf_rcu - Iterate over each VF entry protected by RCU
* @pf: pointer to the PF private structure
* @bkt: bucket index used for iteration
* @vf: pointer to the VF entry currently being processed in the loop.
*
* The bkt variable is an unsigned integer iterator used to traverse the VF
* entries. It is *not* guaranteed to be the VF's vf_id. Do not assume it is.
* Use vf->vf_id to get the id number if needed.
*
* The caller is expected to be under rcu_read_lock() for the entire loop.
* Only use this iterator if your loop is short and you can guarantee it does
* not sleep.
*/
#define ice_for_each_vf_rcu(pf, bkt, vf) \
hash_for_each_rcu((pf)->vfs.table, (bkt), (vf), entry)
/* Specific VF states */
enum ice_vf_states {
@ -104,8 +146,22 @@ struct ice_vc_vf_ops {
int (*dis_vlan_insertion_v2_msg)(struct ice_vf *vf, u8 *msg);
};
/* Virtchnl/SR-IOV config info */
struct ice_vfs {
DECLARE_HASHTABLE(table, 8); /* table of VF entries */
struct mutex table_lock; /* Lock for protecting the hash table */
u16 num_supported; /* max supported VFs on this PF */
u16 num_qps_per; /* number of queue pairs per VF */
u16 num_msix_per; /* number of MSI-X vectors per VF */
unsigned long last_printed_mdd_jiffies; /* MDD message rate limit */
DECLARE_BITMAP(malvfs, ICE_MAX_VF_COUNT); /* malicious VF indicator */
};
/* VF information structure */
struct ice_vf {
struct hlist_node entry;
struct rcu_head rcu;
struct kref refcnt;
struct ice_pf *pf;
/* Used during virtchnl message handling and NDO ops against the VF
@ -162,6 +218,10 @@ struct ice_vf {
};
#ifdef CONFIG_PCI_IOV
struct ice_vf *ice_get_vf_by_id(struct ice_pf *pf, u16 vf_id);
void ice_put_vf(struct ice_vf *vf);
bool ice_has_vfs(struct ice_pf *pf);
u16 ice_get_num_vfs(struct ice_pf *pf);
struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf);
void ice_process_vflr_event(struct ice_pf *pf);
int ice_sriov_configure(struct pci_dev *pdev, int num_vfs);
@ -221,6 +281,25 @@ ice_vc_send_msg_to_vf(struct ice_vf *vf, u32 v_opcode,
bool ice_vc_isvalid_vsi_id(struct ice_vf *vf, u16 vsi_id);
bool ice_vf_is_port_vlan_ena(struct ice_vf *vf);
#else /* CONFIG_PCI_IOV */
static inline struct ice_vf *ice_get_vf_by_id(struct ice_pf *pf, u16 vf_id)
{
return NULL;
}
static inline void ice_put_vf(struct ice_vf *vf)
{
}
static inline bool ice_has_vfs(struct ice_pf *pf)
{
return false;
}
static inline u16 ice_get_num_vfs(struct ice_pf *pf)
{
return 0;
}
static inline void ice_process_vflr_event(struct ice_pf *pf) { }
static inline void ice_free_vfs(struct ice_pf *pf) { }
static inline