be2net: use max-TXQs limit too while provisioning VF queue pairs
authorSuresh Reddy <suresh.reddy@broadcom.com>
Mon, 6 Jun 2016 11:22:08 +0000 (07:22 -0400)
committerDavid S. Miller <davem@davemloft.net>
Tue, 7 Jun 2016 23:18:19 +0000 (16:18 -0700)
When the PF driver provisions resources for VFs, it currently only looks
at max RSS queues available to calculate the number of VF queue pairs.
This logic breaks when there are less number of TX-queues than RSS-queues.
This patch fixes this problem by using the max-TXQs available in the
PF-pool in the calculations. As a part of this change the
be_calculate_vf_qs() routine is renamed as be_calculate_vf_res() and the
code that calculates limits on other related resources is moved here to
contain all resource calculation code inside one routine.

Signed-off-by: Suresh Reddy <suresh.reddy@broadcom.com>
Signed-off-by: Sathya Perla <sathya.perla@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_cmds.h
drivers/net/ethernet/emulex/benet/be_main.c

index fe3763df3f130ce98ddfc0868debc193144c4b3d..ee0bdb772b215ed568aafadd6da51f8ec3edaa3c 100644 (file)
@@ -444,6 +444,7 @@ struct be_resources {
        u16 max_evt_qs;
        u32 if_cap_flags;
        u32 vf_if_cap_flags;    /* VF if capability flags */
+       u32 flags;
 };
 
 #define be_is_os2bmc_enabled(adapter) (adapter->flags & BE_FLAGS_OS2BMC)
index 22402db275f282f099fe9f329df0c78ec723b7cf..bef92c4027ccc80ded04d1bc91741ba9afc60a05 100644 (file)
@@ -4465,7 +4465,7 @@ static int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc,
 }
 
 /* Mark all fields invalid */
-static void be_reset_nic_desc(struct be_nic_res_desc *nic)
+void be_reset_nic_desc(struct be_nic_res_desc *nic)
 {
        memset(nic, 0, sizeof(*nic));
        nic->unicast_mac_count = 0xFFFF;
@@ -4534,73 +4534,9 @@ int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed,
                                         1, version, domain);
 }
 
-static void be_fill_vf_res_template(struct be_adapter *adapter,
-                                   struct be_resources pool_res,
-                                   u16 num_vfs, u16 num_vf_qs,
-                                   struct be_nic_res_desc *nic_vft)
-{
-       u32 vf_if_cap_flags = pool_res.vf_if_cap_flags;
-       struct be_resources res_mod = {0};
-
-       /* 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) {
-               nic_vft->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT);
-               if (num_vf_qs > 1) {
-                       vf_if_cap_flags |= BE_IF_FLAGS_RSS;
-                       if (pool_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) {
-               nic_vft->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT);
-               vf_if_cap_flags &= ~BE_IF_FLAGS_VLAN_PROMISCUOUS;
-       }
-
-       nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags);
-       nic_vft->rq_count = cpu_to_le16(num_vf_qs);
-       nic_vft->txq_count = cpu_to_le16(num_vf_qs);
-       nic_vft->rssq_count = cpu_to_le16(num_vf_qs);
-       nic_vft->cq_count = cpu_to_le16(pool_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)
-               nic_vft->unicast_mac_count = cpu_to_le16(pool_res.max_uc_mac /
-                                                        (num_vfs + 1));
-
-       if (res_mod.max_vlans == FIELD_MODIFIABLE)
-               nic_vft->vlan_count = cpu_to_le16(pool_res.max_vlans /
-                                                 (num_vfs + 1));
-
-       if (res_mod.max_iface_count == FIELD_MODIFIABLE)
-               nic_vft->iface_count = cpu_to_le16(pool_res.max_iface_count /
-                                                  (num_vfs + 1));
-
-       if (res_mod.max_mcc_count == FIELD_MODIFIABLE)
-               nic_vft->mcc_count = cpu_to_le16(pool_res.max_mcc_count /
-                                                (num_vfs + 1));
-}
-
 int be_cmd_set_sriov_config(struct be_adapter *adapter,
                            struct be_resources pool_res, u16 num_vfs,
-                           u16 num_vf_qs)
+                           struct be_resources *vft_res)
 {
        struct {
                struct be_pcie_res_desc pcie;
@@ -4620,12 +4556,26 @@ int be_cmd_set_sriov_config(struct be_adapter *adapter,
        be_reset_nic_desc(&desc.nic_vft);
        desc.nic_vft.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1;
        desc.nic_vft.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
-       desc.nic_vft.flags = BIT(VFT_SHIFT) | BIT(IMM_SHIFT) | BIT(NOSV_SHIFT);
+       desc.nic_vft.flags = vft_res->flags | BIT(VFT_SHIFT) |
+                            BIT(IMM_SHIFT) | BIT(NOSV_SHIFT);
        desc.nic_vft.pf_num = adapter->pdev->devfn;
        desc.nic_vft.vf_num = 0;
-
-       be_fill_vf_res_template(adapter, pool_res, num_vfs, num_vf_qs,
-                               &desc.nic_vft);
+       desc.nic_vft.cap_flags = cpu_to_le32(vft_res->vf_if_cap_flags);
+       desc.nic_vft.rq_count = cpu_to_le16(vft_res->max_rx_qs);
+       desc.nic_vft.txq_count = cpu_to_le16(vft_res->max_tx_qs);
+       desc.nic_vft.rssq_count = cpu_to_le16(vft_res->max_rss_qs);
+       desc.nic_vft.cq_count = cpu_to_le16(vft_res->max_cq_count);
+
+       if (vft_res->max_uc_mac)
+               desc.nic_vft.unicast_mac_count =
+                                       cpu_to_le16(vft_res->max_uc_mac);
+       if (vft_res->max_vlans)
+               desc.nic_vft.vlan_count = cpu_to_le16(vft_res->max_vlans);
+       if (vft_res->max_iface_count)
+               desc.nic_vft.iface_count =
+                               cpu_to_le16(vft_res->max_iface_count);
+       if (vft_res->max_mcc_count)
+               desc.nic_vft.mcc_count = cpu_to_le16(vft_res->max_mcc_count);
 
        return be_cmd_set_profile_config(adapter, &desc,
                                         2 * RESOURCE_DESC_SIZE_V1, 2, 1, 0);
index d8540ae95e5aeea1dbcee207d6f13374d34852e6..b63ae37aa0c2e1c9ed8b23c2759dcb25d9a74499 100644 (file)
@@ -2461,4 +2461,4 @@ int be_cmd_set_vxlan_port(struct be_adapter *adapter, __be16 port);
 int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op);
 int be_cmd_set_sriov_config(struct be_adapter *adapter,
                            struct be_resources res, u16 num_vfs,
-                           u16 num_vf_qs);
+                           struct be_resources *vft_res);
index ed98ef1ecac38d77edf7bb66c206d0099c0ddfef..860104711ce7be74df90b08ede5916d5aa56c4bd 100644 (file)
@@ -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");