Commit 86a0348d authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 20c6e05b a41654c3
......@@ -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);
......
This diff is collapsed.
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment