Skip to content

Commit

Permalink
Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/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>
  • Loading branch information
David S. Miller committed Mar 4, 2022
2 parents f2ecfa0 + 3d5985a commit 4ee508f
Show file tree
Hide file tree
Showing 13 changed files with 872 additions and 554 deletions.
13 changes: 2 additions & 11 deletions drivers/net/ethernet/intel/ice/ice.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/intel/ice/ice_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand Down
161 changes: 94 additions & 67 deletions drivers/net/ethernet/intel/ice/ice_eswitch.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}
}

Expand All @@ -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;

lockdep_assert_held(&pf->vfs.table_lock);

ice_for_each_vf(pf, i) {
struct ice_vsi *vsi = pf->vf[i].repr->src_vsi;
struct ice_vf *vf = &pf->vf[i];
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,
Expand All @@ -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;
}

Expand All @@ -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;
}
Expand All @@ -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;

Expand All @@ -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
Expand All @@ -316,15 +331,16 @@ 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;

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);
}
}

Expand Down Expand Up @@ -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);
}

/**
Expand All @@ -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);
}

/**
Expand All @@ -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;

lockdep_assert_held(&pf->vfs.table_lock);

ice_for_each_vf(pf, i)
napi_enable(&pf->vf[i].repr->q_vector->napi);
ice_for_each_vf(pf, bkt, vf)
napi_enable(&vf->repr->q_vector->napi);
}

/**
Expand All @@ -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;

lockdep_assert_held(&pf->vfs.table_lock);

ice_for_each_vf(pf, i)
napi_disable(&pf->vf[i].repr->q_vector->napi);
ice_for_each_vf(pf, bkt, vf)
napi_disable(&vf->repr->q_vector->napi);
}

/**
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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);
}
}

Expand Down
20 changes: 12 additions & 8 deletions drivers/net/ethernet/intel/ice/ice_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

ice_for_each_vf(pf, i) {
struct ice_vf *vf = &pf->vf[i];
bool active = false;
struct ice_vf *vf;
unsigned int bkt;

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;
}

/**
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 4ee508f

Please sign in to comment.