Merge branch 'ice-vf-resource-tracking'
Jacob Keller says: ==================== Intel Wired LAN Driver Updates 2023-10-19 (ice, igb, ixgbe) This series contains improvements to the ice driver related to VF MSI-X resource tracking, as well as other minor cleanups. Dan fixes code in igb and ixgbe where the conversion to list_for_each_entry failed to account for logic which assumed a NULL pointer after iteration. Jacob makes ice_get_pf_c827_idx static, and refactors ice_find_netlist_node based on feedback that got missed before the function merged. Michal adds a switch rule to drop all traffic received by an inactive LAG port. He also implements ops to allow individual control of MSI-X vectors for SR-IOV VFs. Przemek removes some unused fields in struct ice_flow_entry, and modifies the ice driver to cache the VF PCI device inside struct ice_vf rather than performing lookup at run time. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -554,6 +554,8 @@ struct ice_pf {
|
||||
* MSIX vectors allowed on this PF.
|
||||
*/
|
||||
u16 sriov_base_vector;
|
||||
unsigned long *sriov_irq_bm; /* bitmap to track irq usage */
|
||||
u16 sriov_irq_size; /* size of the irq_bm bitmap */
|
||||
|
||||
u16 ctrl_vsi_idx; /* control VSI index in pf->vsi array */
|
||||
|
||||
|
||||
@@ -473,41 +473,41 @@ ice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd,
|
||||
* @node_part_number: node part number to look for
|
||||
* @node_handle: output parameter if node found - optional
|
||||
*
|
||||
* Find and return the node handle for a given node type and part number in the
|
||||
* netlist. When found ICE_SUCCESS is returned, ICE_ERR_DOES_NOT_EXIST
|
||||
* otherwise. If node_handle provided, it would be set to found node handle.
|
||||
* Scan the netlist for a node handle of the given node type and part number.
|
||||
*
|
||||
* If node_handle is non-NULL it will be modified on function exit. It is only
|
||||
* valid if the function returns zero, and should be ignored on any non-zero
|
||||
* return value.
|
||||
*
|
||||
* Returns: 0 if the node is found, -ENOENT if no handle was found, and
|
||||
* a negative error code on failure to access the AQ.
|
||||
*/
|
||||
static int ice_find_netlist_node(struct ice_hw *hw, u8 node_type_ctx,
|
||||
u8 node_part_number, u16 *node_handle)
|
||||
{
|
||||
struct ice_aqc_get_link_topo cmd;
|
||||
u8 rec_node_part_number;
|
||||
u16 rec_node_handle;
|
||||
u8 idx;
|
||||
|
||||
for (idx = 0; idx < ICE_MAX_NETLIST_SIZE; idx++) {
|
||||
struct ice_aqc_get_link_topo cmd = {};
|
||||
u8 rec_node_part_number;
|
||||
int status;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
cmd.addr.topo_params.node_type_ctx =
|
||||
(node_type_ctx << ICE_AQC_LINK_TOPO_NODE_TYPE_S);
|
||||
FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_TYPE_M,
|
||||
node_type_ctx);
|
||||
cmd.addr.topo_params.index = idx;
|
||||
|
||||
status = ice_aq_get_netlist_node(hw, &cmd,
|
||||
&rec_node_part_number,
|
||||
&rec_node_handle);
|
||||
node_handle);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (rec_node_part_number == node_part_number) {
|
||||
if (node_handle)
|
||||
*node_handle = rec_node_handle;
|
||||
if (rec_node_part_number == node_part_number)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOTBLK;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -73,7 +73,7 @@ ice_eswitch_br_ingress_rule_setup(struct ice_adv_rule_info *rule_info,
|
||||
rule_info->sw_act.vsi_handle = vf_vsi_idx;
|
||||
rule_info->sw_act.flag |= ICE_FLTR_RX;
|
||||
rule_info->sw_act.src = pf_id;
|
||||
rule_info->priority = 5;
|
||||
rule_info->priority = 2;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -84,7 +84,7 @@ ice_eswitch_br_egress_rule_setup(struct ice_adv_rule_info *rule_info,
|
||||
rule_info->sw_act.flag |= ICE_FLTR_TX;
|
||||
rule_info->flags_info.act = ICE_SINGLE_ACT_LAN_ENABLE;
|
||||
rule_info->flags_info.act_valid = true;
|
||||
rule_info->priority = 5;
|
||||
rule_info->priority = 2;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -207,7 +207,7 @@ ice_eswitch_br_guard_rule_create(struct ice_hw *hw, u16 vsi_idx,
|
||||
rule_info.allow_pass_l2 = true;
|
||||
rule_info.sw_act.vsi_handle = vsi_idx;
|
||||
rule_info.sw_act.fltr_act = ICE_NOP;
|
||||
rule_info.priority = 5;
|
||||
rule_info.priority = 2;
|
||||
|
||||
err = ice_add_adv_rule(hw, list, lkups_cnt, &rule_info, rule);
|
||||
if (err)
|
||||
|
||||
@@ -1318,7 +1318,6 @@ ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk,
|
||||
|
||||
list_del(&entry->l_entry);
|
||||
|
||||
devm_kfree(ice_hw_to_dev(hw), entry->entry);
|
||||
devm_kfree(ice_hw_to_dev(hw), entry);
|
||||
|
||||
return 0;
|
||||
@@ -1645,10 +1644,8 @@ ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
|
||||
*entry_h = ICE_FLOW_ENTRY_HNDL(e);
|
||||
|
||||
out:
|
||||
if (status && e) {
|
||||
devm_kfree(ice_hw_to_dev(hw), e->entry);
|
||||
if (status)
|
||||
devm_kfree(ice_hw_to_dev(hw), e);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -350,11 +350,8 @@ struct ice_flow_entry {
|
||||
|
||||
u64 id;
|
||||
struct ice_flow_prof *prof;
|
||||
/* Flow entry's content */
|
||||
void *entry;
|
||||
enum ice_flow_priority priority;
|
||||
u16 vsi_handle;
|
||||
u16 entry_sz;
|
||||
};
|
||||
|
||||
#define ICE_FLOW_ENTRY_HNDL(e) ((u64)(uintptr_t)e)
|
||||
|
||||
@@ -19,8 +19,11 @@ static const u8 lacp_train_pkt[LACP_TRAIN_PKT_LEN] = { 0, 0, 0, 0, 0, 0,
|
||||
static const u8 ice_dflt_vsi_rcp[ICE_RECIPE_LEN] = {
|
||||
0x05, 0, 0, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0x85, 0, 0x01, 0, 0, 0, 0xff, 0xff, 0x08, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
0, 0, 0, 0, 0, 0, 0x30 };
|
||||
static const u8 ice_lport_rcp[ICE_RECIPE_LEN] = {
|
||||
0x05, 0, 0, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0x85, 0, 0x16, 0, 0, 0, 0xff, 0xff, 0x07, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0x30 };
|
||||
|
||||
/**
|
||||
* ice_lag_set_primary - set PF LAG state as Primary
|
||||
@@ -173,18 +176,22 @@ static struct ice_lag *ice_lag_find_primary(struct ice_lag *lag)
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_lag_cfg_dflt_fltr - Add/Remove default VSI rule for LAG
|
||||
* ice_lag_cfg_fltr - Add/Remove rule for LAG
|
||||
* @lag: lag struct for local interface
|
||||
* @act: rule action
|
||||
* @recipe_id: recipe id for the new rule
|
||||
* @rule_idx: pointer to rule index
|
||||
* @add: boolean on whether we are adding filters
|
||||
*/
|
||||
static int
|
||||
ice_lag_cfg_dflt_fltr(struct ice_lag *lag, bool add)
|
||||
ice_lag_cfg_fltr(struct ice_lag *lag, u32 act, u16 recipe_id, u16 *rule_idx,
|
||||
bool add)
|
||||
{
|
||||
struct ice_sw_rule_lkup_rx_tx *s_rule;
|
||||
u16 s_rule_sz, vsi_num;
|
||||
struct ice_hw *hw;
|
||||
u32 act, opc;
|
||||
u8 *eth_hdr;
|
||||
u32 opc;
|
||||
int err;
|
||||
|
||||
hw = &lag->pf->hw;
|
||||
@@ -193,7 +200,7 @@ ice_lag_cfg_dflt_fltr(struct ice_lag *lag, bool add)
|
||||
s_rule_sz = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule);
|
||||
s_rule = kzalloc(s_rule_sz, GFP_KERNEL);
|
||||
if (!s_rule) {
|
||||
dev_err(ice_pf_to_dev(lag->pf), "error allocating rule for LAG default VSI\n");
|
||||
dev_err(ice_pf_to_dev(lag->pf), "error allocating rule for LAG\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -201,19 +208,17 @@ ice_lag_cfg_dflt_fltr(struct ice_lag *lag, bool add)
|
||||
eth_hdr = s_rule->hdr_data;
|
||||
ice_fill_eth_hdr(eth_hdr);
|
||||
|
||||
act = (vsi_num << ICE_SINGLE_ACT_VSI_ID_S) &
|
||||
act |= (vsi_num << ICE_SINGLE_ACT_VSI_ID_S) &
|
||||
ICE_SINGLE_ACT_VSI_ID_M;
|
||||
act |= ICE_SINGLE_ACT_VSI_FORWARDING |
|
||||
ICE_SINGLE_ACT_VALID_BIT | ICE_SINGLE_ACT_LAN_ENABLE;
|
||||
|
||||
s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX);
|
||||
s_rule->recipe_id = cpu_to_le16(lag->pf_recipe);
|
||||
s_rule->recipe_id = cpu_to_le16(recipe_id);
|
||||
s_rule->src = cpu_to_le16(hw->port_info->lport);
|
||||
s_rule->act = cpu_to_le32(act);
|
||||
s_rule->hdr_len = cpu_to_le16(DUMMY_ETH_HDR_LEN);
|
||||
opc = ice_aqc_opc_add_sw_rules;
|
||||
} else {
|
||||
s_rule->index = cpu_to_le16(lag->pf_rule_id);
|
||||
s_rule->index = cpu_to_le16(*rule_idx);
|
||||
opc = ice_aqc_opc_remove_sw_rules;
|
||||
}
|
||||
|
||||
@@ -222,15 +227,46 @@ ice_lag_cfg_dflt_fltr(struct ice_lag *lag, bool add)
|
||||
goto dflt_fltr_free;
|
||||
|
||||
if (add)
|
||||
lag->pf_rule_id = le16_to_cpu(s_rule->index);
|
||||
*rule_idx = le16_to_cpu(s_rule->index);
|
||||
else
|
||||
lag->pf_rule_id = 0;
|
||||
*rule_idx = 0;
|
||||
|
||||
dflt_fltr_free:
|
||||
kfree(s_rule);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_lag_cfg_dflt_fltr - Add/Remove default VSI rule for LAG
|
||||
* @lag: lag struct for local interface
|
||||
* @add: boolean on whether to add filter
|
||||
*/
|
||||
static int
|
||||
ice_lag_cfg_dflt_fltr(struct ice_lag *lag, bool add)
|
||||
{
|
||||
u32 act = ICE_SINGLE_ACT_VSI_FORWARDING |
|
||||
ICE_SINGLE_ACT_VALID_BIT | ICE_SINGLE_ACT_LAN_ENABLE;
|
||||
|
||||
return ice_lag_cfg_fltr(lag, act, lag->pf_recipe,
|
||||
&lag->pf_rule_id, add);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_lag_cfg_drop_fltr - Add/Remove lport drop rule
|
||||
* @lag: lag struct for local interface
|
||||
* @add: boolean on whether to add filter
|
||||
*/
|
||||
static int
|
||||
ice_lag_cfg_drop_fltr(struct ice_lag *lag, bool add)
|
||||
{
|
||||
u32 act = ICE_SINGLE_ACT_VSI_FORWARDING |
|
||||
ICE_SINGLE_ACT_VALID_BIT |
|
||||
ICE_SINGLE_ACT_DROP;
|
||||
|
||||
return ice_lag_cfg_fltr(lag, act, lag->lport_recipe,
|
||||
&lag->lport_rule_idx, add);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_lag_cfg_pf_fltrs - set filters up for new active port
|
||||
* @lag: local interfaces lag struct
|
||||
@@ -257,13 +293,18 @@ ice_lag_cfg_pf_fltrs(struct ice_lag *lag, void *ptr)
|
||||
if (bonding_info->slave.state && lag->pf_rule_id) {
|
||||
if (ice_lag_cfg_dflt_fltr(lag, false))
|
||||
dev_err(dev, "Error removing old default VSI filter\n");
|
||||
if (ice_lag_cfg_drop_fltr(lag, true))
|
||||
dev_err(dev, "Error adding new drop filter\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* interface becoming active - add new default VSI rule */
|
||||
if (!bonding_info->slave.state && !lag->pf_rule_id)
|
||||
if (!bonding_info->slave.state && !lag->pf_rule_id) {
|
||||
if (ice_lag_cfg_dflt_fltr(lag, true))
|
||||
dev_err(dev, "Error adding new default VSI filter\n");
|
||||
if (lag->lport_rule_idx && ice_lag_cfg_drop_fltr(lag, false))
|
||||
dev_err(dev, "Error removing old drop filter\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1179,6 +1220,7 @@ static void ice_lag_changeupper_event(struct ice_lag *lag, void *ptr)
|
||||
swid = primary_lag->pf->hw.port_info->sw_id;
|
||||
ice_lag_set_swid(swid, lag, true);
|
||||
ice_lag_add_prune_list(primary_lag, lag->pf);
|
||||
ice_lag_cfg_drop_fltr(lag, true);
|
||||
}
|
||||
/* add filter for primary control packets */
|
||||
ice_lag_cfg_cp_fltr(lag, true);
|
||||
@@ -1929,11 +1971,16 @@ int ice_init_lag(struct ice_pf *pf)
|
||||
goto lag_error;
|
||||
}
|
||||
|
||||
err = ice_create_lag_recipe(&pf->hw, &lag->pf_recipe, ice_dflt_vsi_rcp,
|
||||
1);
|
||||
err = ice_create_lag_recipe(&pf->hw, &lag->pf_recipe,
|
||||
ice_dflt_vsi_rcp, 1);
|
||||
if (err)
|
||||
goto lag_error;
|
||||
|
||||
err = ice_create_lag_recipe(&pf->hw, &lag->lport_recipe,
|
||||
ice_lport_rcp, 3);
|
||||
if (err)
|
||||
goto free_rcp_res;
|
||||
|
||||
/* associate recipes to profiles */
|
||||
for (n = 0; n < ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER; n++) {
|
||||
err = ice_aq_get_recipe_to_profile(&pf->hw, n,
|
||||
@@ -1942,7 +1989,8 @@ int ice_init_lag(struct ice_pf *pf)
|
||||
continue;
|
||||
|
||||
if (recipe_bits & BIT(ICE_SW_LKUP_DFLT)) {
|
||||
recipe_bits |= BIT(lag->pf_recipe);
|
||||
recipe_bits |= BIT(lag->pf_recipe) |
|
||||
BIT(lag->lport_recipe);
|
||||
ice_aq_map_recipe_to_profile(&pf->hw, n,
|
||||
(u8 *)&recipe_bits, NULL);
|
||||
}
|
||||
@@ -1953,6 +2001,9 @@ int ice_init_lag(struct ice_pf *pf)
|
||||
dev_dbg(dev, "INIT LAG complete\n");
|
||||
return 0;
|
||||
|
||||
free_rcp_res:
|
||||
ice_free_hw_res(&pf->hw, ICE_AQC_RES_TYPE_RECIPE, 1,
|
||||
&pf->lag->pf_recipe);
|
||||
lag_error:
|
||||
kfree(lag);
|
||||
pf->lag = NULL;
|
||||
@@ -1982,6 +2033,8 @@ void ice_deinit_lag(struct ice_pf *pf)
|
||||
|
||||
ice_free_hw_res(&pf->hw, ICE_AQC_RES_TYPE_RECIPE, 1,
|
||||
&pf->lag->pf_recipe);
|
||||
ice_free_hw_res(&pf->hw, ICE_AQC_RES_TYPE_RECIPE, 1,
|
||||
&pf->lag->lport_recipe);
|
||||
|
||||
kfree(lag);
|
||||
|
||||
|
||||
@@ -39,8 +39,10 @@ struct ice_lag {
|
||||
u8 bonded:1; /* currently bonded */
|
||||
u8 primary:1; /* this is primary */
|
||||
u16 pf_recipe;
|
||||
u16 lport_recipe;
|
||||
u16 pf_rule_id;
|
||||
u16 cp_rule_idx;
|
||||
u16 lport_rule_idx;
|
||||
u8 role;
|
||||
};
|
||||
|
||||
|
||||
@@ -229,7 +229,7 @@ static void ice_vsi_set_num_qs(struct ice_vsi *vsi)
|
||||
* of queues vectors, subtract 1 (ICE_NONQ_VECS_VF) from the
|
||||
* original vector count
|
||||
*/
|
||||
vsi->num_q_vectors = pf->vfs.num_msix_per - ICE_NONQ_VECS_VF;
|
||||
vsi->num_q_vectors = vf->num_msix - ICE_NONQ_VECS_VF;
|
||||
break;
|
||||
case ICE_VSI_CTRL:
|
||||
vsi->alloc_txq = 1;
|
||||
|
||||
@@ -5541,7 +5541,7 @@ static void ice_pci_err_resume(struct pci_dev *pdev)
|
||||
return;
|
||||
}
|
||||
|
||||
ice_restore_all_vfs_msi_state(pdev);
|
||||
ice_restore_all_vfs_msi_state(pf);
|
||||
|
||||
ice_do_reset(pf, ICE_RESET_PFR);
|
||||
ice_service_task_restart(pf);
|
||||
@@ -5635,6 +5635,8 @@ static struct pci_driver ice_driver = {
|
||||
#endif /* CONFIG_PM */
|
||||
.shutdown = ice_shutdown,
|
||||
.sriov_configure = ice_sriov_configure,
|
||||
.sriov_get_vf_total_msix = ice_sriov_get_vf_total_msix,
|
||||
.sriov_set_msix_vec_count = ice_sriov_set_msix_vec_count,
|
||||
.err_handler = &ice_pci_err_handler
|
||||
};
|
||||
|
||||
|
||||
@@ -3564,7 +3564,7 @@ int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx)
|
||||
* * 0 - success
|
||||
* * negative - failure
|
||||
*/
|
||||
int ice_get_pf_c827_idx(struct ice_hw *hw, u8 *idx)
|
||||
static int ice_get_pf_c827_idx(struct ice_hw *hw, u8 *idx)
|
||||
{
|
||||
struct ice_aqc_get_link_topo cmd;
|
||||
u8 node_part_number;
|
||||
|
||||
@@ -271,7 +271,6 @@ int ice_read_sma_ctrl_e810t(struct ice_hw *hw, u8 *data);
|
||||
int ice_write_sma_ctrl_e810t(struct ice_hw *hw, u8 data);
|
||||
int ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data);
|
||||
bool ice_is_pca9575_present(struct ice_hw *hw);
|
||||
int ice_get_pf_c827_idx(struct ice_hw *hw, u8 *idx);
|
||||
enum dpll_pin_type ice_cgu_get_pin_type(struct ice_hw *hw, u8 pin, bool input);
|
||||
struct dpll_pin_frequency *
|
||||
ice_cgu_get_pin_freq_supp(struct ice_hw *hw, u8 pin, bool input, u8 *num);
|
||||
|
||||
@@ -64,7 +64,7 @@ static void ice_free_vf_res(struct ice_vf *vf)
|
||||
vf->num_mac = 0;
|
||||
}
|
||||
|
||||
last_vector_idx = vf->first_vector_idx + pf->vfs.num_msix_per - 1;
|
||||
last_vector_idx = vf->first_vector_idx + vf->num_msix - 1;
|
||||
|
||||
/* clear VF MDD event information */
|
||||
memset(&vf->mdd_tx_events, 0, sizeof(vf->mdd_tx_events));
|
||||
@@ -102,7 +102,7 @@ static void ice_dis_vf_mappings(struct ice_vf *vf)
|
||||
wr32(hw, VPINT_ALLOC_PCI(vf->vf_id), 0);
|
||||
|
||||
first = vf->first_vector_idx;
|
||||
last = first + pf->vfs.num_msix_per - 1;
|
||||
last = first + vf->num_msix - 1;
|
||||
for (v = first; v <= last; v++) {
|
||||
u32 reg;
|
||||
|
||||
@@ -138,6 +138,8 @@ static int ice_sriov_free_msix_res(struct ice_pf *pf)
|
||||
if (!pf)
|
||||
return -EINVAL;
|
||||
|
||||
bitmap_free(pf->sriov_irq_bm);
|
||||
pf->sriov_irq_size = 0;
|
||||
pf->sriov_base_vector = 0;
|
||||
|
||||
return 0;
|
||||
@@ -244,22 +246,6 @@ static struct ice_vsi *ice_vf_vsi_setup(struct ice_vf *vf)
|
||||
return vsi;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_calc_vf_first_vector_idx - Calculate MSIX vector index in the PF space
|
||||
* @pf: pointer to PF structure
|
||||
* @vf: pointer to VF that the first MSIX vector index is being calculated for
|
||||
*
|
||||
* This returns the first MSIX vector index in PF space that is used by this VF.
|
||||
* This index is used when accessing PF relative registers such as
|
||||
* GLINT_VECT2FUNC and GLINT_DYN_CTL.
|
||||
* This will always be the OICR index in the AVF driver so any functionality
|
||||
* using vf->first_vector_idx for queue configuration will have to increment by
|
||||
* 1 to avoid meddling with the OICR index.
|
||||
*/
|
||||
static int ice_calc_vf_first_vector_idx(struct ice_pf *pf, struct ice_vf *vf)
|
||||
{
|
||||
return pf->sriov_base_vector + vf->vf_id * pf->vfs.num_msix_per;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_ena_vf_msix_mappings - enable VF MSIX mappings in hardware
|
||||
@@ -280,12 +266,12 @@ static void ice_ena_vf_msix_mappings(struct ice_vf *vf)
|
||||
|
||||
hw = &pf->hw;
|
||||
pf_based_first_msix = vf->first_vector_idx;
|
||||
pf_based_last_msix = (pf_based_first_msix + pf->vfs.num_msix_per) - 1;
|
||||
pf_based_last_msix = (pf_based_first_msix + vf->num_msix) - 1;
|
||||
|
||||
device_based_first_msix = pf_based_first_msix +
|
||||
pf->hw.func_caps.common_cap.msix_vector_first_id;
|
||||
device_based_last_msix =
|
||||
(device_based_first_msix + pf->vfs.num_msix_per) - 1;
|
||||
(device_based_first_msix + vf->num_msix) - 1;
|
||||
device_based_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
|
||||
|
||||
reg = (((device_based_first_msix << VPINT_ALLOC_FIRST_S) &
|
||||
@@ -526,6 +512,52 @@ static int ice_set_per_vf_res(struct ice_pf *pf, u16 num_vfs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_sriov_get_irqs - get irqs for SR-IOV usacase
|
||||
* @pf: pointer to PF structure
|
||||
* @needed: number of irqs to get
|
||||
*
|
||||
* This returns the first MSI-X vector index in PF space that is used by this
|
||||
* VF. This index is used when accessing PF relative registers such as
|
||||
* GLINT_VECT2FUNC and GLINT_DYN_CTL.
|
||||
* This will always be the OICR index in the AVF driver so any functionality
|
||||
* using vf->first_vector_idx for queue configuration_id: id of VF which will
|
||||
* use this irqs
|
||||
*
|
||||
* Only SRIOV specific vectors are tracked in sriov_irq_bm. SRIOV vectors are
|
||||
* allocated from the end of global irq index. First bit in sriov_irq_bm means
|
||||
* last irq index etc. It simplifies extension of SRIOV vectors.
|
||||
* They will be always located from sriov_base_vector to the last irq
|
||||
* index. While increasing/decreasing sriov_base_vector can be moved.
|
||||
*/
|
||||
static int ice_sriov_get_irqs(struct ice_pf *pf, u16 needed)
|
||||
{
|
||||
int res = bitmap_find_next_zero_area(pf->sriov_irq_bm,
|
||||
pf->sriov_irq_size, 0, needed, 0);
|
||||
/* conversion from number in bitmap to global irq index */
|
||||
int index = pf->sriov_irq_size - res - needed;
|
||||
|
||||
if (res >= pf->sriov_irq_size || index < pf->sriov_base_vector)
|
||||
return -ENOENT;
|
||||
|
||||
bitmap_set(pf->sriov_irq_bm, res, needed);
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_sriov_free_irqs - free irqs used by the VF
|
||||
* @pf: pointer to PF structure
|
||||
* @vf: pointer to VF structure
|
||||
*/
|
||||
static void ice_sriov_free_irqs(struct ice_pf *pf, struct ice_vf *vf)
|
||||
{
|
||||
/* Move back from first vector index to first index in bitmap */
|
||||
int bm_i = pf->sriov_irq_size - vf->first_vector_idx - vf->num_msix;
|
||||
|
||||
bitmap_clear(pf->sriov_irq_bm, bm_i, vf->num_msix);
|
||||
vf->first_vector_idx = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_init_vf_vsi_res - initialize/setup VF VSI resources
|
||||
* @vf: VF to initialize/setup the VSI for
|
||||
@@ -539,7 +571,9 @@ static int ice_init_vf_vsi_res(struct ice_vf *vf)
|
||||
struct ice_vsi *vsi;
|
||||
int err;
|
||||
|
||||
vf->first_vector_idx = ice_calc_vf_first_vector_idx(pf, vf);
|
||||
vf->first_vector_idx = ice_sriov_get_irqs(pf, vf->num_msix);
|
||||
if (vf->first_vector_idx < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
vsi = ice_vf_vsi_setup(vf);
|
||||
if (!vsi)
|
||||
@@ -789,14 +823,19 @@ static const struct ice_vf_ops ice_sriov_vf_ops = {
|
||||
*/
|
||||
static int ice_create_vf_entries(struct ice_pf *pf, u16 num_vfs)
|
||||
{
|
||||
struct pci_dev *pdev = pf->pdev;
|
||||
struct ice_vfs *vfs = &pf->vfs;
|
||||
struct pci_dev *vfdev = NULL;
|
||||
struct ice_vf *vf;
|
||||
u16 vf_id;
|
||||
int err;
|
||||
u16 vf_pdev_id;
|
||||
int err, pos;
|
||||
|
||||
lockdep_assert_held(&vfs->table_lock);
|
||||
|
||||
for (vf_id = 0; vf_id < num_vfs; vf_id++) {
|
||||
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
|
||||
pci_read_config_word(pdev, pos + PCI_SRIOV_VF_DID, &vf_pdev_id);
|
||||
|
||||
for (u16 vf_id = 0; vf_id < num_vfs; vf_id++) {
|
||||
vf = kzalloc(sizeof(*vf), GFP_KERNEL);
|
||||
if (!vf) {
|
||||
err = -ENOMEM;
|
||||
@@ -812,11 +851,28 @@ static int ice_create_vf_entries(struct ice_pf *pf, u16 num_vfs)
|
||||
|
||||
ice_initialize_vf_entry(vf);
|
||||
|
||||
do {
|
||||
vfdev = pci_get_device(pdev->vendor, vf_pdev_id, vfdev);
|
||||
} while (vfdev && vfdev->physfn != pdev);
|
||||
vf->vfdev = vfdev;
|
||||
vf->vf_sw_id = pf->first_sw;
|
||||
|
||||
pci_dev_get(vfdev);
|
||||
|
||||
/* set default number of MSI-X */
|
||||
vf->num_msix = pf->vfs.num_msix_per;
|
||||
vf->num_vf_qs = pf->vfs.num_qps_per;
|
||||
ice_vc_set_default_allowlist(vf);
|
||||
|
||||
hash_add_rcu(vfs->table, &vf->entry, vf_id);
|
||||
}
|
||||
|
||||
/* Decrement of refcount done by pci_get_device() inside the loop does
|
||||
* not touch the last iteration's vfdev, so it has to be done manually
|
||||
* to balance pci_dev_get() added within the loop.
|
||||
*/
|
||||
pci_dev_put(vfdev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_entries:
|
||||
@@ -831,10 +887,16 @@ err_free_entries:
|
||||
*/
|
||||
static int ice_ena_vfs(struct ice_pf *pf, u16 num_vfs)
|
||||
{
|
||||
int total_vectors = pf->hw.func_caps.common_cap.num_msix_vectors;
|
||||
struct device *dev = ice_pf_to_dev(pf);
|
||||
struct ice_hw *hw = &pf->hw;
|
||||
int ret;
|
||||
|
||||
pf->sriov_irq_bm = bitmap_zalloc(total_vectors, GFP_KERNEL);
|
||||
if (!pf->sriov_irq_bm)
|
||||
return -ENOMEM;
|
||||
pf->sriov_irq_size = total_vectors;
|
||||
|
||||
/* Disable global interrupt 0 so we don't try to handle the VFLR. */
|
||||
wr32(hw, GLINT_DYN_CTL(pf->oicr_irq.index),
|
||||
ICE_ITR_NONE << GLINT_DYN_CTL_ITR_INDX_S);
|
||||
@@ -893,6 +955,7 @@ err_unroll_intr:
|
||||
/* rearm interrupts here */
|
||||
ice_irq_dynamic_ena(hw, NULL, NULL);
|
||||
clear_bit(ICE_OICR_INTR_DIS, pf->state);
|
||||
bitmap_free(pf->sriov_irq_bm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -956,6 +1019,175 @@ static int ice_check_sriov_allowed(struct ice_pf *pf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_sriov_get_vf_total_msix - return number of MSI-X used by VFs
|
||||
* @pdev: pointer to pci_dev struct
|
||||
*
|
||||
* The function is called via sysfs ops
|
||||
*/
|
||||
u32 ice_sriov_get_vf_total_msix(struct pci_dev *pdev)
|
||||
{
|
||||
struct ice_pf *pf = pci_get_drvdata(pdev);
|
||||
|
||||
return pf->sriov_irq_size - ice_get_max_used_msix_vector(pf);
|
||||
}
|
||||
|
||||
static int ice_sriov_move_base_vector(struct ice_pf *pf, int move)
|
||||
{
|
||||
if (pf->sriov_base_vector - move < ice_get_max_used_msix_vector(pf))
|
||||
return -ENOMEM;
|
||||
|
||||
pf->sriov_base_vector -= move;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ice_sriov_remap_vectors(struct ice_pf *pf, u16 restricted_id)
|
||||
{
|
||||
u16 vf_ids[ICE_MAX_SRIOV_VFS];
|
||||
struct ice_vf *tmp_vf;
|
||||
int to_remap = 0, bkt;
|
||||
|
||||
/* For better irqs usage try to remap irqs of VFs
|
||||
* that aren't running yet
|
||||
*/
|
||||
ice_for_each_vf(pf, bkt, tmp_vf) {
|
||||
/* skip VF which is changing the number of MSI-X */
|
||||
if (restricted_id == tmp_vf->vf_id ||
|
||||
test_bit(ICE_VF_STATE_ACTIVE, tmp_vf->vf_states))
|
||||
continue;
|
||||
|
||||
ice_dis_vf_mappings(tmp_vf);
|
||||
ice_sriov_free_irqs(pf, tmp_vf);
|
||||
|
||||
vf_ids[to_remap] = tmp_vf->vf_id;
|
||||
to_remap += 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < to_remap; i++) {
|
||||
tmp_vf = ice_get_vf_by_id(pf, vf_ids[i]);
|
||||
if (!tmp_vf)
|
||||
continue;
|
||||
|
||||
tmp_vf->first_vector_idx =
|
||||
ice_sriov_get_irqs(pf, tmp_vf->num_msix);
|
||||
/* there is no need to rebuild VSI as we are only changing the
|
||||
* vector indexes not amount of MSI-X or queues
|
||||
*/
|
||||
ice_ena_vf_mappings(tmp_vf);
|
||||
ice_put_vf(tmp_vf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_sriov_set_msix_vec_count
|
||||
* @vf_dev: pointer to pci_dev struct of VF device
|
||||
* @msix_vec_count: new value for MSI-X amount on this VF
|
||||
*
|
||||
* Set requested MSI-X, queues and registers for @vf_dev.
|
||||
*
|
||||
* First do some sanity checks like if there are any VFs, if the new value
|
||||
* is correct etc. Then disable old mapping (MSI-X and queues registers), change
|
||||
* MSI-X and queues, rebuild VSI and enable new mapping.
|
||||
*
|
||||
* If it is possible (driver not binded to VF) try to remap also other VFs to
|
||||
* linearize irqs register usage.
|
||||
*/
|
||||
int ice_sriov_set_msix_vec_count(struct pci_dev *vf_dev, int msix_vec_count)
|
||||
{
|
||||
struct pci_dev *pdev = pci_physfn(vf_dev);
|
||||
struct ice_pf *pf = pci_get_drvdata(pdev);
|
||||
u16 prev_msix, prev_queues, queues;
|
||||
bool needs_rebuild = false;
|
||||
struct ice_vf *vf;
|
||||
int id;
|
||||
|
||||
if (!ice_get_num_vfs(pf))
|
||||
return -ENOENT;
|
||||
|
||||
if (!msix_vec_count)
|
||||
return 0;
|
||||
|
||||
queues = msix_vec_count;
|
||||
/* add 1 MSI-X for OICR */
|
||||
msix_vec_count += 1;
|
||||
|
||||
if (queues > min(ice_get_avail_txq_count(pf),
|
||||
ice_get_avail_rxq_count(pf)))
|
||||
return -EINVAL;
|
||||
|
||||
if (msix_vec_count < ICE_MIN_INTR_PER_VF)
|
||||
return -EINVAL;
|
||||
|
||||
/* Transition of PCI VF function number to function_id */
|
||||
for (id = 0; id < pci_num_vf(pdev); id++) {
|
||||
if (vf_dev->devfn == pci_iov_virtfn_devfn(pdev, id))
|
||||
break;
|
||||
}
|
||||
|
||||
if (id == pci_num_vf(pdev))
|
||||
return -ENOENT;
|
||||
|
||||
vf = ice_get_vf_by_id(pf, id);
|
||||
|
||||
if (!vf)
|
||||
return -ENOENT;
|
||||
|
||||
prev_msix = vf->num_msix;
|
||||
prev_queues = vf->num_vf_qs;
|
||||
|
||||
if (ice_sriov_move_base_vector(pf, msix_vec_count - prev_msix)) {
|
||||
ice_put_vf(vf);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
ice_dis_vf_mappings(vf);
|
||||
ice_sriov_free_irqs(pf, vf);
|
||||
|
||||
/* Remap all VFs beside the one is now configured */
|
||||
ice_sriov_remap_vectors(pf, vf->vf_id);
|
||||
|
||||
vf->num_msix = msix_vec_count;
|
||||
vf->num_vf_qs = queues;
|
||||
vf->first_vector_idx = ice_sriov_get_irqs(pf, vf->num_msix);
|
||||
if (vf->first_vector_idx < 0)
|
||||
goto unroll;
|
||||
|
||||
ice_vf_vsi_release(vf);
|
||||
if (vf->vf_ops->create_vsi(vf)) {
|
||||
/* Try to rebuild with previous values */
|
||||
needs_rebuild = true;
|
||||
goto unroll;
|
||||
}
|
||||
|
||||
dev_info(ice_pf_to_dev(pf),
|
||||
"Changing VF %d resources to %d vectors and %d queues\n",
|
||||
vf->vf_id, vf->num_msix, vf->num_vf_qs);
|
||||
|
||||
ice_ena_vf_mappings(vf);
|
||||
ice_put_vf(vf);
|
||||
|
||||
return 0;
|
||||
|
||||
unroll:
|
||||
dev_info(ice_pf_to_dev(pf),
|
||||
"Can't set %d vectors on VF %d, falling back to %d\n",
|
||||
vf->num_msix, vf->vf_id, prev_msix);
|
||||
|
||||
vf->num_msix = prev_msix;
|
||||
vf->num_vf_qs = prev_queues;
|
||||
vf->first_vector_idx = ice_sriov_get_irqs(pf, vf->num_msix);
|
||||
if (vf->first_vector_idx < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (needs_rebuild)
|
||||
vf->vf_ops->create_vsi(vf);
|
||||
|
||||
ice_ena_vf_mappings(vf);
|
||||
ice_put_vf(vf);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_sriov_configure - Enable or change number of VFs via sysfs
|
||||
* @pdev: pointer to a pci_dev structure
|
||||
@@ -1709,31 +1941,16 @@ void ice_print_vfs_mdd_events(struct ice_pf *pf)
|
||||
|
||||
/**
|
||||
* ice_restore_all_vfs_msi_state - restore VF MSI state after PF FLR
|
||||
* @pdev: pointer to a pci_dev structure
|
||||
* @pf: pointer to the PF structure
|
||||
*
|
||||
* Called when recovering from a PF FLR to restore interrupt capability to
|
||||
* the VFs.
|
||||
*/
|
||||
void ice_restore_all_vfs_msi_state(struct pci_dev *pdev)
|
||||
void ice_restore_all_vfs_msi_state(struct ice_pf *pf)
|
||||
{
|
||||
u16 vf_id;
|
||||
int pos;
|
||||
struct ice_vf *vf;
|
||||
u32 bkt;
|
||||
|
||||
if (!pci_num_vf(pdev))
|
||||
return;
|
||||
|
||||
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
|
||||
if (pos) {
|
||||
struct pci_dev *vfdev;
|
||||
|
||||
pci_read_config_word(pdev, pos + PCI_SRIOV_VF_DID,
|
||||
&vf_id);
|
||||
vfdev = pci_get_device(pdev->vendor, vf_id, NULL);
|
||||
while (vfdev) {
|
||||
if (vfdev->is_virtfn && vfdev->physfn == pdev)
|
||||
pci_restore_msi_state(vfdev);
|
||||
vfdev = pci_get_device(pdev->vendor, vf_id,
|
||||
vfdev);
|
||||
}
|
||||
}
|
||||
ice_for_each_vf(pf, bkt, vf)
|
||||
pci_restore_msi_state(vf->vfdev);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ int
|
||||
ice_get_vf_cfg(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi);
|
||||
|
||||
void ice_free_vfs(struct ice_pf *pf);
|
||||
void ice_restore_all_vfs_msi_state(struct pci_dev *pdev);
|
||||
void ice_restore_all_vfs_msi_state(struct ice_pf *pf);
|
||||
|
||||
int
|
||||
ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
|
||||
@@ -60,6 +60,8 @@ void ice_print_vfs_mdd_events(struct ice_pf *pf);
|
||||
void ice_print_vf_rx_mdd_event(struct ice_vf *vf);
|
||||
bool
|
||||
ice_vc_validate_pattern(struct ice_vf *vf, struct virtchnl_proto_hdrs *proto);
|
||||
u32 ice_sriov_get_vf_total_msix(struct pci_dev *pdev);
|
||||
int ice_sriov_set_msix_vec_count(struct pci_dev *vf_dev, int msix_vec_count);
|
||||
#else /* CONFIG_PCI_IOV */
|
||||
static inline void ice_process_vflr_event(struct ice_pf *pf) { }
|
||||
static inline void ice_free_vfs(struct ice_pf *pf) { }
|
||||
@@ -67,7 +69,7 @@ static inline
|
||||
void ice_vf_lan_overflow_event(struct ice_pf *pf, struct ice_rq_event_info *event) { }
|
||||
static inline void ice_print_vfs_mdd_events(struct ice_pf *pf) { }
|
||||
static inline void ice_print_vf_rx_mdd_event(struct ice_vf *vf) { }
|
||||
static inline void ice_restore_all_vfs_msi_state(struct pci_dev *pdev) { }
|
||||
static inline void ice_restore_all_vfs_msi_state(struct ice_pf *pf) { }
|
||||
|
||||
static inline int
|
||||
ice_sriov_configure(struct pci_dev __always_unused *pdev,
|
||||
@@ -142,5 +144,16 @@ ice_get_vf_stats(struct net_device __always_unused *netdev,
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline u32 ice_sriov_get_vf_total_msix(struct pci_dev *pdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ice_sriov_set_msix_vec_count(struct pci_dev *vf_dev, int msix_vec_count)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif /* CONFIG_PCI_IOV */
|
||||
#endif /* _ICE_SRIOV_H_ */
|
||||
|
||||
@@ -56,6 +56,8 @@ static void ice_release_vf(struct kref *ref)
|
||||
{
|
||||
struct ice_vf *vf = container_of(ref, struct ice_vf, refcnt);
|
||||
|
||||
pci_dev_put(vf->vfdev);
|
||||
|
||||
vf->vf_ops->free(vf);
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ struct ice_vfs {
|
||||
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 */
|
||||
u16 num_msix_per; /* default MSI-X vectors per VF */
|
||||
unsigned long last_printed_mdd_jiffies; /* MDD message rate limit */
|
||||
};
|
||||
|
||||
@@ -82,7 +82,7 @@ struct ice_vf {
|
||||
struct rcu_head rcu;
|
||||
struct kref refcnt;
|
||||
struct ice_pf *pf;
|
||||
|
||||
struct pci_dev *vfdev;
|
||||
/* Used during virtchnl message handling and NDO ops against the VF
|
||||
* that will trigger a VFR
|
||||
*/
|
||||
@@ -136,6 +136,8 @@ struct ice_vf {
|
||||
|
||||
/* devlink port data */
|
||||
struct devlink_port devlink_port;
|
||||
|
||||
u16 num_msix; /* num of MSI-X configured on this VF */
|
||||
};
|
||||
|
||||
/* Flags for controlling behavior of ice_reset_vf */
|
||||
|
||||
@@ -501,7 +501,7 @@ static int ice_vc_get_vf_res_msg(struct ice_vf *vf, u8 *msg)
|
||||
vfres->num_vsis = 1;
|
||||
/* Tx and Rx queue are equal for VF */
|
||||
vfres->num_queue_pairs = vsi->num_txq;
|
||||
vfres->max_vectors = vf->pf->vfs.num_msix_per;
|
||||
vfres->max_vectors = vf->num_msix;
|
||||
vfres->rss_key_size = ICE_VSIQF_HKEY_ARRAY_SIZE;
|
||||
vfres->rss_lut_size = ICE_LUT_VSI_SIZE;
|
||||
vfres->max_mtu = ice_vc_get_max_frame_size(vf);
|
||||
|
||||
@@ -7856,7 +7856,8 @@ static int igb_set_vf_mac_filter(struct igb_adapter *adapter, const int vf,
|
||||
{
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
struct vf_data_storage *vf_data = &adapter->vf_data[vf];
|
||||
struct vf_mac_filter *entry = NULL;
|
||||
struct vf_mac_filter *entry;
|
||||
bool found = false;
|
||||
int ret = 0;
|
||||
|
||||
if ((vf_data->flags & IGB_VF_FLAG_PF_SET_MAC) &&
|
||||
@@ -7887,11 +7888,13 @@ static int igb_set_vf_mac_filter(struct igb_adapter *adapter, const int vf,
|
||||
case E1000_VF_MAC_FILTER_ADD:
|
||||
/* try to find empty slot in the list */
|
||||
list_for_each_entry(entry, &adapter->vf_macs.l, l) {
|
||||
if (entry->free)
|
||||
if (entry->free) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry && entry->free) {
|
||||
if (found) {
|
||||
entry->free = false;
|
||||
entry->vf = vf;
|
||||
ether_addr_copy(entry->vf_mac, addr);
|
||||
|
||||
@@ -640,6 +640,7 @@ static int ixgbe_set_vf_macvlan(struct ixgbe_adapter *adapter,
|
||||
int vf, int index, unsigned char *mac_addr)
|
||||
{
|
||||
struct vf_macvlans *entry;
|
||||
bool found = false;
|
||||
int retval = 0;
|
||||
|
||||
if (index <= 1) {
|
||||
@@ -661,22 +662,22 @@ static int ixgbe_set_vf_macvlan(struct ixgbe_adapter *adapter,
|
||||
if (!index)
|
||||
return 0;
|
||||
|
||||
entry = NULL;
|
||||
|
||||
list_for_each_entry(entry, &adapter->vf_mvs.l, l) {
|
||||
if (entry->free)
|
||||
if (entry->free) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we traversed the entire list and didn't find a free entry
|
||||
* then we're out of space on the RAR table. Also entry may
|
||||
* be NULL because the original memory allocation for the list
|
||||
* failed, which is not fatal but does mean we can't support
|
||||
* VF requests for MACVLAN because we couldn't allocate
|
||||
* memory for the list management required.
|
||||
* then we're out of space on the RAR table. It's also possible
|
||||
* for the &adapter->vf_mvs.l list to be empty because the original
|
||||
* memory allocation for the list failed, which is not fatal but does
|
||||
* mean we can't support VF requests for MACVLAN because we couldn't
|
||||
* allocate memory for the list management required.
|
||||
*/
|
||||
if (!entry || !entry->free)
|
||||
if (!found)
|
||||
return -ENOSPC;
|
||||
|
||||
retval = ixgbe_add_mac_filter(adapter, mac_addr, vf);
|
||||
|
||||
Reference in New Issue
Block a user