Skip to content

Commit

Permalink
net/ice: fix crash on closing representor ports
Browse files Browse the repository at this point in the history
[ upstream commit 1d704031642926688c453331b13690a4151e5276 ]

The data resource in struct rte_eth_dev is cleared and points to NULL
when the DCF port is closed.

If the DCF representor port is closed after the DCF port is closed,
a segmentation fault occurs because the representor port accesses the
data resource released by the DCF port.

This patch fixes this issue by synchronizing the state of DCF ports and
representor ports to the peer in real time when their state changes.

Fixes: c7e1a1a ("net/ice: refactor DCF VLAN handling")

Signed-off-by: Mingjin Ye <mingjinx.ye@intel.com>
Acked-by: Qi Zhang <qi.z.zhang@intel.com>
  • Loading branch information
yemj-odc authored and kevintraynor committed Nov 16, 2023
1 parent 52086d7 commit cd14285
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 6 deletions.
30 changes: 27 additions & 3 deletions drivers/net/ice/ice_dcf_ethdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,26 @@ ice_dcf_free_repr_info(struct ice_dcf_adapter *dcf_adapter)
}
}

int
ice_dcf_handle_vf_repr_close(struct ice_dcf_adapter *dcf_adapter,
uint16_t vf_id)
{
struct ice_dcf_repr_info *vf_rep_info;

if (dcf_adapter->num_reprs >= vf_id) {
PMD_DRV_LOG(ERR, "Invalid VF id: %d", vf_id);
return -1;
}

if (!dcf_adapter->repr_infos)
return 0;

vf_rep_info = &dcf_adapter->repr_infos[vf_id];
vf_rep_info->vf_rep_eth_dev = NULL;

return 0;
}

static int
ice_dcf_init_repr_info(struct ice_dcf_adapter *dcf_adapter)
{
Expand All @@ -892,11 +912,10 @@ ice_dcf_dev_close(struct rte_eth_dev *dev)
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
return 0;

ice_dcf_vf_repr_notify_all(adapter, false);
(void)ice_dcf_dev_stop(dev);

ice_free_queues(dev);

ice_dcf_free_repr_info(adapter);
ice_dcf_uninit_parent_adapter(dev);
ice_dcf_uninit_hw(dev, &adapter->real_hw);

Expand Down Expand Up @@ -1073,7 +1092,7 @@ ice_dcf_dev_reset(struct rte_eth_dev *dev)
ice_dcf_reset_hw(dev, hw);
}

ret = ice_dcf_dev_uninit(dev);
ret = ice_dcf_dev_close(dev);
if (ret)
return ret;

Expand Down Expand Up @@ -1141,12 +1160,17 @@ ice_dcf_dev_init(struct rte_eth_dev *eth_dev)

ice_dcf_stats_reset(eth_dev);

ice_dcf_vf_repr_notify_all(adapter, true);

return 0;
}

static int
ice_dcf_dev_uninit(struct rte_eth_dev *eth_dev)
{
struct ice_dcf_adapter *adapter = eth_dev->data->dev_private;

ice_dcf_free_repr_info(adapter);
ice_dcf_dev_close(eth_dev);

return 0;
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ice/ice_dcf_ethdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ struct ice_dcf_vf_repr {
struct rte_ether_addr mac_addr;
uint16_t switch_domain_id;
uint16_t vf_id;
bool dcf_valid;

struct ice_dcf_vlan outer_vlan_info; /* DCF always handle outer VLAN */
};
Expand All @@ -64,6 +65,8 @@ int ice_dcf_vf_repr_init(struct rte_eth_dev *vf_rep_eth_dev, void *init_param);
int ice_dcf_vf_repr_uninit(struct rte_eth_dev *vf_rep_eth_dev);
int ice_dcf_vf_repr_init_vlan(struct rte_eth_dev *vf_rep_eth_dev);
void ice_dcf_vf_repr_stop_all(struct ice_dcf_adapter *dcf_adapter);
void ice_dcf_vf_repr_notify_all(struct ice_dcf_adapter *dcf_adapter, bool valid);
int ice_dcf_handle_vf_repr_close(struct ice_dcf_adapter *dcf_adapter, uint16_t vf_id);
bool ice_dcf_adminq_need_retry(struct ice_adapter *ad);

#endif /* _ICE_DCF_ETHDEV_H_ */
46 changes: 43 additions & 3 deletions drivers/net/ice/ice_dcf_vf_representor.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,28 @@ ice_dcf_vf_repr_dev_stop(struct rte_eth_dev *dev)
return 0;
}

static void
ice_dcf_vf_repr_notify_one(struct rte_eth_dev *dev, bool valid)
{
struct ice_dcf_vf_repr *repr = dev->data->dev_private;

repr->dcf_valid = valid;
}

static int
ice_dcf_vf_repr_dev_close(struct rte_eth_dev *dev)
{
struct ice_dcf_vf_repr *repr = dev->data->dev_private;
struct ice_dcf_adapter *dcf_adapter;
int err;

if (repr->dcf_valid) {
dcf_adapter = repr->dcf_eth_dev->data->dev_private;
err = ice_dcf_handle_vf_repr_close(dcf_adapter, repr->vf_id);
if (err)
PMD_DRV_LOG(ERR, "VF representor invalid");
}

return ice_dcf_vf_repr_uninit(dev);
}

Expand Down Expand Up @@ -111,14 +130,15 @@ ice_dcf_vf_repr_link_update(__rte_unused struct rte_eth_dev *ethdev,
static __rte_always_inline struct ice_dcf_hw *
ice_dcf_vf_repr_hw(struct ice_dcf_vf_repr *repr)
{
struct ice_dcf_adapter *dcf_adapter =
repr->dcf_eth_dev->data->dev_private;
struct ice_dcf_adapter *dcf_adapter;

if (!dcf_adapter) {
if (!repr->dcf_valid) {
PMD_DRV_LOG(ERR, "DCF for VF representor has been released\n");
return NULL;
}

dcf_adapter = repr->dcf_eth_dev->data->dev_private;

return &dcf_adapter->real_hw;
}

Expand Down Expand Up @@ -414,6 +434,7 @@ ice_dcf_vf_repr_init(struct rte_eth_dev *vf_rep_eth_dev, void *init_param)
repr->dcf_eth_dev = param->dcf_eth_dev;
repr->switch_domain_id = param->switch_domain_id;
repr->vf_id = param->vf_id;
repr->dcf_valid = true;
repr->outer_vlan_info.port_vlan_ena = false;
repr->outer_vlan_info.stripping_ena = false;
repr->outer_vlan_info.tpid = RTE_ETHER_TYPE_VLAN;
Expand Down Expand Up @@ -488,3 +509,22 @@ ice_dcf_vf_repr_stop_all(struct ice_dcf_adapter *dcf_adapter)
vf_rep_eth_dev->data->dev_started = 0;
}
}

void
ice_dcf_vf_repr_notify_all(struct ice_dcf_adapter *dcf_adapter, bool valid)
{
uint16_t vf_id;
struct rte_eth_dev *vf_rep_eth_dev;

if (!dcf_adapter->repr_infos)
return;

for (vf_id = 0; vf_id < dcf_adapter->real_hw.num_vfs; vf_id++) {
vf_rep_eth_dev = dcf_adapter->repr_infos[vf_id].vf_rep_eth_dev;

if (!vf_rep_eth_dev)
continue;

ice_dcf_vf_repr_notify_one(vf_rep_eth_dev, valid);
}
}

0 comments on commit cd14285

Please sign in to comment.