diff options
Diffstat (limited to 'drivers/net/ethernet/emulex/benet/be_main.c')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 82 |
1 files changed, 68 insertions, 14 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index ed98ef1ecac3..860104711ce7 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -3810,17 +3810,20 @@ static void be_disable_vxlan_offloads(struct be_adapter *adapter) } #endif -static u16 be_calculate_vf_qs(struct be_adapter *adapter, u16 num_vfs) +static void be_calculate_vf_res(struct be_adapter *adapter, u16 num_vfs, + struct be_resources *vft_res) { struct be_resources res = adapter->pool_res; + u32 vf_if_cap_flags = res.vf_if_cap_flags; + struct be_resources res_mod = {0}; u16 num_vf_qs = 1; /* Distribute the queue resources among the PF and it's VFs * Do not distribute queue resources in multi-channel configuration. */ if (num_vfs && !be_is_mc(adapter)) { - /* Divide the qpairs evenly among the VFs and the PF, capped - * at VF-EQ-count. Any remainder qpairs belong to the PF. + /* Divide the rx queues evenly among the VFs and the PF, capped + * at VF-EQ-count. Any remainder queues belong to the PF. */ num_vf_qs = min(SH_VF_MAX_NIC_EQS, res.max_rss_qs / (num_vfs + 1)); @@ -3832,13 +3835,62 @@ static u16 be_calculate_vf_qs(struct be_adapter *adapter, u16 num_vfs) if (num_vfs >= MAX_RSS_IFACES) num_vf_qs = 1; } - return num_vf_qs; + + /* Resource with fields set to all '1's by GET_PROFILE_CONFIG cmd, + * which are modifiable using SET_PROFILE_CONFIG cmd. + */ + be_cmd_get_profile_config(adapter, &res_mod, RESOURCE_MODIFIABLE, 0); + + /* If RSS IFACE capability flags are modifiable for a VF, set the + * capability flag as valid and set RSS and DEFQ_RSS IFACE flags if + * more than 1 RSSQ is available for a VF. + * Otherwise, provision only 1 queue pair for VF. + */ + if (res_mod.vf_if_cap_flags & BE_IF_FLAGS_RSS) { + vft_res->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT); + if (num_vf_qs > 1) { + vf_if_cap_flags |= BE_IF_FLAGS_RSS; + if (res.if_cap_flags & BE_IF_FLAGS_DEFQ_RSS) + vf_if_cap_flags |= BE_IF_FLAGS_DEFQ_RSS; + } else { + vf_if_cap_flags &= ~(BE_IF_FLAGS_RSS | + BE_IF_FLAGS_DEFQ_RSS); + } + } else { + num_vf_qs = 1; + } + + if (res_mod.vf_if_cap_flags & BE_IF_FLAGS_VLAN_PROMISCUOUS) { + vft_res->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT); + vf_if_cap_flags &= ~BE_IF_FLAGS_VLAN_PROMISCUOUS; + } + + vft_res->vf_if_cap_flags = vf_if_cap_flags; + vft_res->max_rx_qs = num_vf_qs; + vft_res->max_rss_qs = num_vf_qs; + vft_res->max_tx_qs = res.max_tx_qs / (num_vfs + 1); + vft_res->max_cq_count = res.max_cq_count / (num_vfs + 1); + + /* Distribute unicast MACs, VLANs, IFACE count and MCCQ count equally + * among the PF and it's VFs, if the fields are changeable + */ + if (res_mod.max_uc_mac == FIELD_MODIFIABLE) + vft_res->max_uc_mac = res.max_uc_mac / (num_vfs + 1); + + if (res_mod.max_vlans == FIELD_MODIFIABLE) + vft_res->max_vlans = res.max_vlans / (num_vfs + 1); + + if (res_mod.max_iface_count == FIELD_MODIFIABLE) + vft_res->max_iface_count = res.max_iface_count / (num_vfs + 1); + + if (res_mod.max_mcc_count == FIELD_MODIFIABLE) + vft_res->max_mcc_count = res.max_mcc_count / (num_vfs + 1); } static int be_clear(struct be_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; - u16 num_vf_qs; + struct be_resources vft_res = {0}; be_cancel_worker(adapter); @@ -3850,11 +3902,12 @@ static int be_clear(struct be_adapter *adapter) */ if (skyhawk_chip(adapter) && be_physfn(adapter) && !pci_vfs_assigned(pdev)) { - num_vf_qs = be_calculate_vf_qs(adapter, - pci_sriov_get_totalvfs(pdev)); + be_calculate_vf_res(adapter, + pci_sriov_get_totalvfs(pdev), + &vft_res); be_cmd_set_sriov_config(adapter, adapter->pool_res, pci_sriov_get_totalvfs(pdev), - num_vf_qs); + &vft_res); } #ifdef CONFIG_BE2NET_VXLAN @@ -4144,7 +4197,7 @@ static int be_get_sriov_config(struct be_adapter *adapter) static void be_alloc_sriov_res(struct be_adapter *adapter) { int old_vfs = pci_num_vf(adapter->pdev); - u16 num_vf_qs; + struct be_resources vft_res = {0}; int status; be_get_sriov_config(adapter); @@ -4158,9 +4211,9 @@ static void be_alloc_sriov_res(struct be_adapter *adapter) * Also, this is done by FW in Lancer chip. */ if (skyhawk_chip(adapter) && be_max_vfs(adapter) && !old_vfs) { - num_vf_qs = be_calculate_vf_qs(adapter, 0); + be_calculate_vf_res(adapter, 0, &vft_res); status = be_cmd_set_sriov_config(adapter, adapter->pool_res, 0, - num_vf_qs); + &vft_res); if (status) dev_err(&adapter->pdev->dev, "Failed to optimize SRIOV resources\n"); @@ -5552,7 +5605,7 @@ err: static int be_pci_sriov_configure(struct pci_dev *pdev, int num_vfs) { struct be_adapter *adapter = pci_get_drvdata(pdev); - u16 num_vf_qs; + struct be_resources vft_res = {0}; int status; if (!num_vfs) @@ -5575,9 +5628,10 @@ static int be_pci_sriov_configure(struct pci_dev *pdev, int num_vfs) * Also, this is done by FW in Lancer chip. */ if (skyhawk_chip(adapter) && !pci_num_vf(pdev)) { - num_vf_qs = be_calculate_vf_qs(adapter, adapter->num_vfs); + be_calculate_vf_res(adapter, adapter->num_vfs, + &vft_res); status = be_cmd_set_sriov_config(adapter, adapter->pool_res, - adapter->num_vfs, num_vf_qs); + adapter->num_vfs, &vft_res); if (status) dev_err(&pdev->dev, "Failed to optimize SR-IOV resources\n"); |