net/i40e: determine number of queues per VF at run time
authorWei Dai <wei.dai@intel.com>
Tue, 9 Jan 2018 08:56:07 +0000 (16:56 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 16 Jan 2018 17:47:49 +0000 (18:47 +0100)
Without this patch, the number of queues per i40e VF is set to 4
by CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF=4 in config/common_base.
It is a fixed value determined at compile time and can't be changed
at run time.
With this patch, the number of queues per i40e VF can be determined
at run time. For example, if the PCI address of an i40e PF is
aaaa:bb.cc, with the EAL parameter -w aaaa:bb.cc,queue-num-per-vf=8,
the number of queues per VF created from this PF is set to 8.
If there is no "queue-num-per-vf" setting in EAL parameters, it uses
the default value of 4. And if the value after the "queue-num-per-vf"
is invalid, it will also use the default value. The valid values can
be 1, 2, 4, 8, or 16.

Signed-off-by: Wei Dai <wei.dai@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
config/common_base
doc/guides/nics/i40e.rst
doc/guides/rel_notes/release_18_02.rst
drivers/net/i40e/i40e_ethdev.c

index 5ee1842..465ebf3 100644 (file)
@@ -203,7 +203,6 @@ CONFIG_RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC=y
 CONFIG_RTE_LIBRTE_I40E_INC_VECTOR=y
 CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC=n
 CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_PF=64
-CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF=4
 CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM=4
 # interval up to 8160 us, aligned to 2 (or default value)
 CONFIG_RTE_LIBRTE_I40E_ITR_INTERVAL=-1
index 2507d5f..c4c10d3 100644 (file)
@@ -115,10 +115,6 @@ Please note that enabling debugging options may affect system performance.
 
   Number of queues reserved for PF.
 
-- ``CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF`` (default ``4``)
-
-  Number of queues reserved for each SR-IOV VF.
-
 - ``CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM`` (default ``4``)
 
   Number of queues reserved for each VMDQ Pool.
@@ -128,6 +124,18 @@ Please note that enabling debugging options may affect system performance.
   Interrupt Throttling interval.
 
 
+Runtime Config Options
+~~~~~~~~~~~~~~~~~~~~~~
+
+- ``Number of Queues per VF`` (default ``4``)
+
+  The number of queue per VF is determined by its host PF. If the PCI address
+  of an i40e PF is aaaa:bb.cc, the number of queues per VF can be configured
+  with EAL parameter like -w aaaa:bb.cc,queue-num-per-vf=n. The value n can be
+  1, 2, 4, 8 or 16. If no such parameter is configured, the number of queues
+  per VF is 4 by default.
+
+
 Driver compilation and testing
 ------------------------------
 
index 8fe5b94..51b43f9 100644 (file)
@@ -53,6 +53,14 @@ New Features
   users. According to the device configuration, it will setup TX->RX loopback
   link or not.
 
+* **Add the support of run time determination of number of queues per i40e VF**
+
+  The number of queue per VF is determined by its host PF. If the PCI address
+  of an i40e PF is aaaa:bb.cc, the number of queues per VF can be configured
+  with EAL parameter like -w aaaa:bb.cc,queue-num-per-vf=n. The value n can be
+  1, 2, 4, 8 or 16. If no such parameter is configured, the number of queues
+  per VF is 4 by default.
+
 * **Added NVGRE and UDP tunnels support in Solarflare network PMD.**
 
   Added support for NVGRE, VXLAN and GENEVE tunnels.
index 04fc3a1..3dc026f 100644 (file)
@@ -3952,6 +3952,69 @@ i40e_get_cap(struct i40e_hw *hw)
        return ret;
 }
 
+#define RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF       4
+#define QUEUE_NUM_PER_VF_ARG                   "queue-num-per-vf"
+RTE_PMD_REGISTER_PARAM_STRING(net_i40e,        QUEUE_NUM_PER_VF_ARG "=1|2|4|8|16");
+
+static int i40e_pf_parse_vf_queue_number_handler(const char *key,
+               const char *value,
+               void *opaque)
+{
+       struct i40e_pf *pf;
+       unsigned long num;
+       char *end;
+
+       pf = (struct i40e_pf *)opaque;
+       RTE_SET_USED(key);
+
+       errno = 0;
+       num = strtoul(value, &end, 0);
+       if (errno != 0 || end == value || *end != 0) {
+               PMD_DRV_LOG(WARNING, "Wrong VF queue number = %s, Now it is "
+                           "kept the value = %hu", value, pf->vf_nb_qp_max);
+               return -(EINVAL);
+       }
+
+       if (num <= I40E_MAX_QP_NUM_PER_VF && rte_is_power_of_2(num))
+               pf->vf_nb_qp_max = (uint16_t)num;
+       else
+               /* here return 0 to make next valid same argument work */
+               PMD_DRV_LOG(WARNING, "Wrong VF queue number = %lu, it must be "
+                           "power of 2 and equal or less than 16 !, Now it is "
+                           "kept the value = %hu", num, pf->vf_nb_qp_max);
+
+       return 0;
+}
+
+static int i40e_pf_config_vf_rxq_number(struct rte_eth_dev *dev)
+{
+       static const char * const valid_keys[] = {QUEUE_NUM_PER_VF_ARG, NULL};
+       struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+       struct rte_kvargs *kvlist;
+
+       /* set default queue number per VF as 4 */
+       pf->vf_nb_qp_max = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF;
+
+       if (dev->device->devargs == NULL)
+               return 0;
+
+       kvlist = rte_kvargs_parse(dev->device->devargs->args, valid_keys);
+       if (kvlist == NULL)
+               return -(EINVAL);
+
+       if (rte_kvargs_count(kvlist, QUEUE_NUM_PER_VF_ARG) > 1)
+               PMD_DRV_LOG(WARNING, "More than one argument \"%s\" and only "
+                           "the first invalid or last valid one is used !",
+                           QUEUE_NUM_PER_VF_ARG);
+
+       rte_kvargs_process(kvlist, QUEUE_NUM_PER_VF_ARG,
+                          i40e_pf_parse_vf_queue_number_handler, pf);
+
+       rte_kvargs_free(kvlist);
+
+       return 0;
+}
+
 static int
 i40e_pf_parameter_init(struct rte_eth_dev *dev)
 {
@@ -3964,6 +4027,9 @@ i40e_pf_parameter_init(struct rte_eth_dev *dev)
                PMD_INIT_LOG(ERR, "HW configuration doesn't support SRIOV");
                return -EINVAL;
        }
+
+       i40e_pf_config_vf_rxq_number(dev);
+
        /* Add the parameter init for LFC */
        pf->fc_conf.pause_time = I40E_DEFAULT_PAUSE_TIME;
        pf->fc_conf.high_water[I40E_MAX_TRAFFIC_CLASS] = I40E_DEFAULT_HIGH_WATER;
@@ -3973,7 +4039,6 @@ i40e_pf_parameter_init(struct rte_eth_dev *dev)
        pf->max_num_vsi = hw->func_caps.num_vsis;
        pf->lan_nb_qp_max = RTE_LIBRTE_I40E_QUEUE_NUM_PER_PF;
        pf->vmdq_nb_qp_max = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM;
-       pf->vf_nb_qp_max = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF;
 
        /* FDir queue/VSI allocation */
        pf->fdir_qp_offset = 0;
@@ -4003,7 +4068,7 @@ i40e_pf_parameter_init(struct rte_eth_dev *dev)
        pf->vf_qp_offset = pf->lan_qp_offset + pf->lan_nb_qps;
        if (hw->func_caps.sr_iov_1_1 && pci_dev->max_vfs) {
                pf->flags |= I40E_FLAG_SRIOV;
-               pf->vf_nb_qps = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF;
+               pf->vf_nb_qps = pf->vf_nb_qp_max;
                pf->vf_num = pci_dev->max_vfs;
                PMD_DRV_LOG(DEBUG,
                        "%u VF VSIs, %u queues per VF VSI, in total %u queues",