net/cxgbe: query firmware for max queues available
authorRahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Fri, 29 Jun 2018 19:23:53 +0000 (00:53 +0530)
committerFerruh Yigit <ferruh.yigit@intel.com>
Wed, 4 Jul 2018 20:52:21 +0000 (22:52 +0200)
Query firmware for max Tx and Rx queues that can be allocated.
Move the code to determine max queues to common place for both
PF and VF.

Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
drivers/net/cxgbe/base/common.h
drivers/net/cxgbe/base/t4_hw.c
drivers/net/cxgbe/base/t4fw_interface.h
drivers/net/cxgbe/cxgbe.h
drivers/net/cxgbe/cxgbe_main.c
drivers/net/cxgbe/cxgbevf_main.c

index ea3e112..157201d 100644 (file)
@@ -210,6 +210,14 @@ struct rss_params {
        } u;
 };
 
+/*
+ * Maximum resources provisioned for a PCI PF.
+ */
+struct pf_resources {
+       unsigned int neq;      /* N egress Qs */
+       unsigned int niqflint; /* N ingress Qs/w free list(s) & intr */
+};
+
 /*
  * Maximum resources provisioned for a PCI VF.
  */
@@ -233,6 +241,7 @@ struct adapter_params {
        struct pci_params pci;
        struct devlog_params devlog;
        struct rss_params rss;
+       struct pf_resources pfres;
        struct vf_resources vfres;
        enum pcie_memwin drv_memwin;
 
@@ -466,6 +475,7 @@ void t4_write_indirect(struct adapter *adap, unsigned int addr_reg,
                       unsigned int nregs, unsigned int start_idx);
 
 int t4_get_vpd_params(struct adapter *adapter, struct vpd_params *p);
+int t4_get_pfres(struct adapter *adapter);
 int t4_read_flash(struct adapter *adapter, unsigned int addr,
                  unsigned int nwords, u32 *data, int byte_oriented);
 int t4_flash_cfg_addr(struct adapter *adapter);
index 0893b7b..628b280 100644 (file)
@@ -2480,6 +2480,46 @@ int t4_get_core_clock(struct adapter *adapter, struct vpd_params *p)
        return 0;
 }
 
+/**
+ * t4_get_pfres - retrieve VF resource limits
+ * @adapter: the adapter
+ *
+ * Retrieves configured resource limits and capabilities for a physical
+ * function.  The results are stored in @adapter->pfres.
+ */
+int t4_get_pfres(struct adapter *adapter)
+{
+       struct pf_resources *pfres = &adapter->params.pfres;
+       struct fw_pfvf_cmd cmd, rpl;
+       u32 word;
+       int v;
+
+       /*
+        * Execute PFVF Read command to get VF resource limits; bail out early
+        * with error on command failure.
+        */
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_PFVF_CMD) |
+                                   F_FW_CMD_REQUEST |
+                                   F_FW_CMD_READ |
+                                   V_FW_PFVF_CMD_PFN(adapter->pf) |
+                                   V_FW_PFVF_CMD_VFN(0));
+       cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
+       v = t4_wr_mbox(adapter, adapter->mbox, &cmd, sizeof(cmd), &rpl);
+       if (v != FW_SUCCESS)
+               return v;
+
+       /*
+        * Extract PF resource limits and return success.
+        */
+       word = be32_to_cpu(rpl.niqflint_niq);
+       pfres->niqflint = G_FW_PFVF_CMD_NIQFLINT(word);
+
+       word = be32_to_cpu(rpl.type_to_neq);
+       pfres->neq = G_FW_PFVF_CMD_NEQ(word);
+       return 0;
+}
+
 /* serial flash and firmware constants and flash config file constants */
 enum {
        SF_ATTEMPTS = 10,             /* max retries for SF operations */
index 7b2f2d3..a17ebea 100644 (file)
@@ -744,6 +744,12 @@ struct fw_pfvf_cmd {
        __be32 r4;
 };
 
+#define S_FW_PFVF_CMD_PFN              8
+#define V_FW_PFVF_CMD_PFN(x)           ((x) << S_FW_PFVF_CMD_PFN)
+
+#define S_FW_PFVF_CMD_VFN              0
+#define V_FW_PFVF_CMD_VFN(x)           ((x) << S_FW_PFVF_CMD_VFN)
+
 #define S_FW_PFVF_CMD_NIQFLINT          20
 #define M_FW_PFVF_CMD_NIQFLINT          0xfff
 #define G_FW_PFVF_CMD_NIQFLINT(x)       \
index 70f974f..5e6f5c9 100644 (file)
@@ -63,5 +63,6 @@ void cxgbe_enable_rx_queues(struct port_info *pi);
 void print_port_info(struct adapter *adap);
 void print_adapter_info(struct adapter *adap);
 int cxgbe_get_devargs(struct rte_devargs *devargs, const char *key);
+void configure_max_ethqsets(struct adapter *adapter);
 
 #endif /* _CXGBE_H_ */
index c3f0053..c3938e8 100644 (file)
@@ -513,7 +513,7 @@ void cfg_queues(struct rte_eth_dev *eth_dev)
                 * We default up to # of cores queues per 1G/10G port.
                 */
                if (nb_ports)
-                       q_per_port = (MAX_ETH_QSETS -
+                       q_per_port = (s->max_ethqsets -
                                     (adap->params.nports - nb_ports)) /
                                     nb_ports;
 
@@ -537,8 +537,6 @@ void cfg_queues(struct rte_eth_dev *eth_dev)
                        qidx += pi->n_rx_qsets;
                }
 
-               s->max_ethqsets = qidx;
-
                for (i = 0; i < ARRAY_SIZE(s->ethrxq); i++) {
                        struct sge_eth_rxq *r = &s->ethrxq[i];
 
@@ -770,6 +768,40 @@ static void configure_pcie_ext_tag(struct adapter *adapter)
        }
 }
 
+/* Figure out how many Queue Sets we can support */
+void configure_max_ethqsets(struct adapter *adapter)
+{
+       unsigned int ethqsets;
+
+       /*
+        * We need to reserve an Ingress Queue for the Asynchronous Firmware
+        * Event Queue.
+        *
+        * For each Queue Set, we'll need the ability to allocate two Egress
+        * Contexts -- one for the Ingress Queue Free List and one for the TX
+        * Ethernet Queue.
+        */
+       if (is_pf4(adapter)) {
+               struct pf_resources *pfres = &adapter->params.pfres;
+
+               ethqsets = pfres->niqflint - 1;
+               if (pfres->neq < ethqsets * 2)
+                       ethqsets = pfres->neq / 2;
+       } else {
+               struct vf_resources *vfres = &adapter->params.vfres;
+
+               ethqsets = vfres->niqflint - 1;
+               if (vfres->nethctrl != ethqsets)
+                       ethqsets = min(vfres->nethctrl, ethqsets);
+               if (vfres->neq < ethqsets * 2)
+                       ethqsets = vfres->neq / 2;
+       }
+
+       if (ethqsets > MAX_ETH_QSETS)
+               ethqsets = MAX_ETH_QSETS;
+       adapter->sge.max_ethqsets = ethqsets;
+}
+
 /*
  * Tweak configuration based on system architecture, etc.  Most of these have
  * defaults assigned to them by Firmware Configuration Files (if we're using
@@ -1051,6 +1083,17 @@ static int adap_init0(struct adapter *adap)
                goto bye;
        }
 
+       /* Now that we've successfully configured and initialized the adapter
+        * (or found it already initialized), we can ask the Firmware what
+        * resources it has provisioned for us.
+        */
+       ret = t4_get_pfres(adap);
+       if (ret) {
+               dev_err(adap->pdev_dev,
+                       "Unable to retrieve resource provisioning info\n");
+               goto bye;
+       }
+
        /* Find out what ports are available to us. */
        v = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
            V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_PORTVEC);
@@ -1201,6 +1244,7 @@ static int adap_init0(struct adapter *adap)
        t4_init_tp_params(adap);
        configure_pcie_ext_tag(adap);
        configure_vlan_types(adap);
+       configure_max_ethqsets(adap);
 
        adap->params.drv_memwin = MEMWIN_NIC;
        adap->flags |= FW_OK;
index 5b3fb53..4214d03 100644 (file)
@@ -20,7 +20,7 @@
 static void size_nports_qsets(struct adapter *adapter)
 {
        struct vf_resources *vfres = &adapter->params.vfres;
-       unsigned int ethqsets, pmask_nports;
+       unsigned int pmask_nports;
 
        /*
         * The number of "ports" which we support is equal to the number of
@@ -49,23 +49,7 @@ static void size_nports_qsets(struct adapter *adapter)
                adapter->params.nports = pmask_nports;
        }
 
-       /*
-        * We need to reserve an Ingress Queue for the Asynchronous Firmware
-        * Event Queue.
-        *
-        * For each Queue Set, we'll need the ability to allocate two Egress
-        * Contexts -- one for the Ingress Queue Free List and one for the TX
-        * Ethernet Queue.
-        */
-       ethqsets = vfres->niqflint - 1;
-       if (vfres->nethctrl != ethqsets)
-               ethqsets = min(vfres->nethctrl, ethqsets);
-       if (vfres->neq < ethqsets * 2)
-               ethqsets = vfres->neq / 2;
-       if (ethqsets > MAX_ETH_QSETS)
-               ethqsets = MAX_ETH_QSETS;
-       adapter->sge.max_ethqsets = ethqsets;
-
+       configure_max_ethqsets(adapter);
        if (adapter->sge.max_ethqsets < adapter->params.nports) {
                dev_warn(adapter->pdev_dev, "only using %d of %d available"
                         " virtual interfaces (too few Queue Sets)\n",