net/dpaa: support flow control
authorShreyansh Jain <shreyansh.jain@nxp.com>
Thu, 28 Sep 2017 12:29:53 +0000 (17:59 +0530)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 6 Oct 2017 00:49:50 +0000 (02:49 +0200)
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
doc/guides/nics/features/dpaa.ini
drivers/net/dpaa/dpaa_ethdev.c

index c09efd8..1ba6b11 100644 (file)
@@ -11,6 +11,7 @@ MTU update           = Y
 Promiscuous mode     = Y
 Allmulticast mode    = Y
 Unicast MAC filter   = Y
+Flow control         = Y
 Basic stats          = Y
 ARMv8                = Y
 Usage doc            = Y
index bcd6013..054d4bb 100644 (file)
@@ -328,6 +328,85 @@ static int dpaa_link_up(struct rte_eth_dev *dev)
        return 0;
 }
 
+static int
+dpaa_flow_ctrl_set(struct rte_eth_dev *dev,
+                  struct rte_eth_fc_conf *fc_conf)
+{
+       struct dpaa_if *dpaa_intf = dev->data->dev_private;
+       struct rte_eth_fc_conf *net_fc;
+
+       PMD_INIT_FUNC_TRACE();
+
+       if (!(dpaa_intf->fc_conf)) {
+               dpaa_intf->fc_conf = rte_zmalloc(NULL,
+                       sizeof(struct rte_eth_fc_conf), MAX_CACHELINE);
+               if (!dpaa_intf->fc_conf) {
+                       DPAA_PMD_ERR("unable to save flow control info");
+                       return -ENOMEM;
+               }
+       }
+       net_fc = dpaa_intf->fc_conf;
+
+       if (fc_conf->high_water < fc_conf->low_water) {
+               DPAA_PMD_ERR("Incorrect Flow Control Configuration");
+               return -EINVAL;
+       }
+
+       if (fc_conf->mode == RTE_FC_NONE) {
+               return 0;
+       } else if (fc_conf->mode == RTE_FC_TX_PAUSE ||
+                fc_conf->mode == RTE_FC_FULL) {
+               fman_if_set_fc_threshold(dpaa_intf->fif, fc_conf->high_water,
+                                        fc_conf->low_water,
+                               dpaa_intf->bp_info->bpid);
+               if (fc_conf->pause_time)
+                       fman_if_set_fc_quanta(dpaa_intf->fif,
+                                             fc_conf->pause_time);
+       }
+
+       /* Save the information in dpaa device */
+       net_fc->pause_time = fc_conf->pause_time;
+       net_fc->high_water = fc_conf->high_water;
+       net_fc->low_water = fc_conf->low_water;
+       net_fc->send_xon = fc_conf->send_xon;
+       net_fc->mac_ctrl_frame_fwd = fc_conf->mac_ctrl_frame_fwd;
+       net_fc->mode = fc_conf->mode;
+       net_fc->autoneg = fc_conf->autoneg;
+
+       return 0;
+}
+
+static int
+dpaa_flow_ctrl_get(struct rte_eth_dev *dev,
+                  struct rte_eth_fc_conf *fc_conf)
+{
+       struct dpaa_if *dpaa_intf = dev->data->dev_private;
+       struct rte_eth_fc_conf *net_fc = dpaa_intf->fc_conf;
+       int ret;
+
+       PMD_INIT_FUNC_TRACE();
+
+       if (net_fc) {
+               fc_conf->pause_time = net_fc->pause_time;
+               fc_conf->high_water = net_fc->high_water;
+               fc_conf->low_water = net_fc->low_water;
+               fc_conf->send_xon = net_fc->send_xon;
+               fc_conf->mac_ctrl_frame_fwd = net_fc->mac_ctrl_frame_fwd;
+               fc_conf->mode = net_fc->mode;
+               fc_conf->autoneg = net_fc->autoneg;
+               return 0;
+       }
+       ret = fman_if_get_fc_threshold(dpaa_intf->fif);
+       if (ret) {
+               fc_conf->mode = RTE_FC_TX_PAUSE;
+               fc_conf->pause_time = fman_if_get_fc_quanta(dpaa_intf->fif);
+       } else {
+               fc_conf->mode = RTE_FC_NONE;
+       }
+
+       return 0;
+}
+
 static int
 dpaa_dev_add_mac_addr(struct rte_eth_dev *dev,
                             struct ether_addr *addr,
@@ -384,6 +463,9 @@ static struct eth_dev_ops dpaa_devops = {
        .rx_queue_release         = dpaa_eth_rx_queue_release,
        .tx_queue_release         = dpaa_eth_tx_queue_release,
 
+       .flow_ctrl_get            = dpaa_flow_ctrl_get,
+       .flow_ctrl_set            = dpaa_flow_ctrl_set,
+
        .link_update              = dpaa_eth_link_update,
        .stats_get                = dpaa_eth_stats_get,
        .stats_reset              = dpaa_eth_stats_reset,
@@ -400,6 +482,33 @@ static struct eth_dev_ops dpaa_devops = {
 
 };
 
+static int dpaa_fc_set_default(struct dpaa_if *dpaa_intf)
+{
+       struct rte_eth_fc_conf *fc_conf;
+       int ret;
+
+       PMD_INIT_FUNC_TRACE();
+
+       if (!(dpaa_intf->fc_conf)) {
+               dpaa_intf->fc_conf = rte_zmalloc(NULL,
+                       sizeof(struct rte_eth_fc_conf), MAX_CACHELINE);
+               if (!dpaa_intf->fc_conf) {
+                       DPAA_PMD_ERR("unable to save flow control info");
+                       return -ENOMEM;
+               }
+       }
+       fc_conf = dpaa_intf->fc_conf;
+       ret = fman_if_get_fc_threshold(dpaa_intf->fif);
+       if (ret) {
+               fc_conf->mode = RTE_FC_TX_PAUSE;
+               fc_conf->pause_time = fman_if_get_fc_quanta(dpaa_intf->fif);
+       } else {
+               fc_conf->mode = RTE_FC_NONE;
+       }
+
+       return 0;
+}
+
 /* Initialise an Rx FQ */
 static int dpaa_rx_queue_init(struct qman_fq *fq,
                              uint32_t fqid)
@@ -553,6 +662,9 @@ dpaa_dev_init(struct rte_eth_dev *eth_dev)
 
        DPAA_PMD_DEBUG("All frame queues created");
 
+       /* Get the initial configuration for flow control */
+       dpaa_fc_set_default(dpaa_intf);
+
        /* reset bpool list, initialize bpool dynamically */
        list_for_each_entry_safe(bp, tmp_bp, &cfg->fman_if->bpool_list, node) {
                list_del(&bp->node);