net/axgbe: support RSS RETA/hash query and update
authorChandu Babu N <chandu@amd.com>
Fri, 29 May 2020 11:49:20 +0000 (17:19 +0530)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 5 Jun 2020 14:48:22 +0000 (16:48 +0200)
add support for RSS reta/hash query and update function

Signed-off-by: Chandu Babu N <chandu@amd.com>
Acked-by: Amaranath Somalapuram <asomalap@amd.com>
doc/guides/nics/features/axgbe.ini
drivers/net/axgbe/axgbe_dev.c
drivers/net/axgbe/axgbe_ethdev.c
drivers/net/axgbe/axgbe_ethdev.h

index 0becaa0..34df0d1 100644 (file)
@@ -11,6 +11,8 @@ Scattered Rx         = Y
 Promiscuous mode     = Y
 Allmulticast mode    = Y
 RSS hash             = Y
+RSS key update       = Y
+RSS reta update      = Y
 CRC offload          = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
index 5f0f195..af62eae 100644 (file)
@@ -614,7 +614,7 @@ static int axgbe_write_rss_reg(struct axgbe_port *pdata, unsigned int type,
        return -EBUSY;
 }
 
-static int axgbe_write_rss_hash_key(struct axgbe_port *pdata)
+int axgbe_write_rss_hash_key(struct axgbe_port *pdata)
 {
        struct rte_eth_rss_conf *rss_conf;
        unsigned int key_regs = sizeof(pdata->rss_key) / sizeof(u32);
@@ -638,7 +638,7 @@ static int axgbe_write_rss_hash_key(struct axgbe_port *pdata)
        return 0;
 }
 
-static int axgbe_write_rss_lookup_table(struct axgbe_port *pdata)
+int axgbe_write_rss_lookup_table(struct axgbe_port *pdata)
 {
        unsigned int i;
        int ret;
@@ -683,6 +683,7 @@ static void axgbe_rss_options(struct axgbe_port *pdata)
        uint64_t rss_hf;
 
        rss_conf = &pdata->eth_dev->data->dev_conf.rx_adv_conf.rss_conf;
+       pdata->rss_hf = rss_conf->rss_hf;
        rss_hf = rss_conf->rss_hf;
 
        if (rss_hf & (ETH_RSS_IPV4 | ETH_RSS_IPV6))
index 8670588..619250f 100644 (file)
@@ -60,6 +60,16 @@ axgbe_dev_xstats_get_names_by_id(struct rte_eth_dev *dev,
                                 const uint64_t *ids,
                                 unsigned int size);
 static int axgbe_dev_xstats_reset(struct rte_eth_dev *dev);
+static int axgbe_dev_rss_reta_update(struct rte_eth_dev *dev,
+                         struct rte_eth_rss_reta_entry64 *reta_conf,
+                         uint16_t reta_size);
+static int axgbe_dev_rss_reta_query(struct rte_eth_dev *dev,
+                        struct rte_eth_rss_reta_entry64 *reta_conf,
+                        uint16_t reta_size);
+static int axgbe_dev_rss_hash_update(struct rte_eth_dev *dev,
+                                    struct rte_eth_rss_conf *rss_conf);
+static int axgbe_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
+                                      struct rte_eth_rss_conf *rss_conf);
 static int  axgbe_dev_info_get(struct rte_eth_dev *dev,
                               struct rte_eth_dev_info *dev_info);
 static int axgbe_flow_ctrl_get(struct rte_eth_dev *dev,
@@ -201,6 +211,10 @@ static const struct eth_dev_ops axgbe_eth_dev_ops = {
        .xstats_get_names     = axgbe_dev_xstats_get_names,
        .xstats_get_names_by_id = axgbe_dev_xstats_get_names_by_id,
        .xstats_get_by_id     = axgbe_dev_xstats_get_by_id,
+       .reta_update          = axgbe_dev_rss_reta_update,
+       .reta_query           = axgbe_dev_rss_reta_query,
+       .rss_hash_update      = axgbe_dev_rss_hash_update,
+       .rss_hash_conf_get    = axgbe_dev_rss_hash_conf_get,
        .dev_infos_get        = axgbe_dev_info_get,
        .rx_queue_setup       = axgbe_dev_rx_queue_setup,
        .rx_queue_release     = axgbe_dev_rx_queue_release,
@@ -450,6 +464,136 @@ axgbe_dev_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
        return 0;
 }
 
+static int
+axgbe_dev_rss_reta_update(struct rte_eth_dev *dev,
+                         struct rte_eth_rss_reta_entry64 *reta_conf,
+                         uint16_t reta_size)
+{
+       struct axgbe_port *pdata = dev->data->dev_private;
+       unsigned int i, idx, shift;
+       int ret;
+
+       if (!pdata->rss_enable) {
+               PMD_DRV_LOG(ERR, "RSS not enabled\n");
+               return -ENOTSUP;
+       }
+
+       if (reta_size == 0 || reta_size > AXGBE_RSS_MAX_TABLE_SIZE) {
+               PMD_DRV_LOG(ERR, "reta_size %d is not supported\n", reta_size);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < reta_size; i++) {
+               idx = i / RTE_RETA_GROUP_SIZE;
+               shift = i % RTE_RETA_GROUP_SIZE;
+               if ((reta_conf[idx].mask & (1ULL << shift)) == 0)
+                       continue;
+               pdata->rss_table[i] = reta_conf[idx].reta[shift];
+       }
+
+       /* Program the lookup table */
+       ret = axgbe_write_rss_lookup_table(pdata);
+       return ret;
+}
+
+static int
+axgbe_dev_rss_reta_query(struct rte_eth_dev *dev,
+                        struct rte_eth_rss_reta_entry64 *reta_conf,
+                        uint16_t reta_size)
+{
+       struct axgbe_port *pdata = dev->data->dev_private;
+       unsigned int i, idx, shift;
+
+       if (!pdata->rss_enable) {
+               PMD_DRV_LOG(ERR, "RSS not enabled\n");
+               return -ENOTSUP;
+       }
+
+       if (reta_size == 0 || reta_size > AXGBE_RSS_MAX_TABLE_SIZE) {
+               PMD_DRV_LOG(ERR, "reta_size %d is not supported\n", reta_size);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < reta_size; i++) {
+               idx = i / RTE_RETA_GROUP_SIZE;
+               shift = i % RTE_RETA_GROUP_SIZE;
+               if ((reta_conf[idx].mask & (1ULL << shift)) == 0)
+                       continue;
+               reta_conf[idx].reta[shift] = pdata->rss_table[i];
+       }
+       return 0;
+}
+
+static int
+axgbe_dev_rss_hash_update(struct rte_eth_dev *dev,
+                         struct rte_eth_rss_conf *rss_conf)
+{
+       struct axgbe_port *pdata = dev->data->dev_private;
+       int ret;
+
+       if (!pdata->rss_enable) {
+               PMD_DRV_LOG(ERR, "RSS not enabled\n");
+               return -ENOTSUP;
+       }
+
+       if (rss_conf == NULL) {
+               PMD_DRV_LOG(ERR, "rss_conf value isn't valid\n");
+               return -EINVAL;
+       }
+
+       if (rss_conf->rss_key != NULL &&
+           rss_conf->rss_key_len == AXGBE_RSS_HASH_KEY_SIZE) {
+               rte_memcpy(pdata->rss_key, rss_conf->rss_key,
+                      AXGBE_RSS_HASH_KEY_SIZE);
+               /* Program the hash key */
+               ret = axgbe_write_rss_hash_key(pdata);
+               if (ret != 0)
+                       return ret;
+       }
+
+       pdata->rss_hf = rss_conf->rss_hf & AXGBE_RSS_OFFLOAD;
+
+       if (pdata->rss_hf & (ETH_RSS_IPV4 | ETH_RSS_IPV6))
+               AXGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, IP2TE, 1);
+       if (pdata->rss_hf &
+           (ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_NONFRAG_IPV6_TCP))
+               AXGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, TCP4TE, 1);
+       if (pdata->rss_hf &
+           (ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_NONFRAG_IPV6_UDP))
+               AXGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, UDP4TE, 1);
+
+       /* Set the RSS options */
+       AXGMAC_IOWRITE(pdata, MAC_RSSCR, pdata->rss_options);
+
+       return 0;
+}
+
+static int
+axgbe_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
+                           struct rte_eth_rss_conf *rss_conf)
+{
+       struct axgbe_port *pdata = dev->data->dev_private;
+
+       if (!pdata->rss_enable) {
+               PMD_DRV_LOG(ERR, "RSS not enabled\n");
+               return -ENOTSUP;
+       }
+
+       if (rss_conf == NULL) {
+               PMD_DRV_LOG(ERR, "rss_conf value isn't valid\n");
+               return -EINVAL;
+       }
+
+       if (rss_conf->rss_key != NULL &&
+           rss_conf->rss_key_len >= AXGBE_RSS_HASH_KEY_SIZE) {
+               rte_memcpy(rss_conf->rss_key, pdata->rss_key,
+                      AXGBE_RSS_HASH_KEY_SIZE);
+       }
+       rss_conf->rss_key_len = AXGBE_RSS_HASH_KEY_SIZE;
+       rss_conf->rss_hf = pdata->rss_hf;
+       return 0;
+}
+
 static void
 axgbe_dev_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
 {
index f10ec4a..cedce5a 100644 (file)
@@ -594,6 +594,7 @@ struct axgbe_port {
        uint32_t rss_table[AXGBE_RSS_MAX_TABLE_SIZE];
        uint32_t rss_options;
        int rss_enable;
+       uint64_t rss_hf;
 
        /* Hardware features of the device */
        struct axgbe_hw_features hw_feat;
@@ -653,5 +654,7 @@ void axgbe_init_function_ptrs_i2c(struct axgbe_i2c_if *i2c_if);
 void axgbe_set_mac_addn_addr(struct axgbe_port *pdata, u8 *addr,
                             uint32_t index);
 void axgbe_set_mac_hash_table(struct axgbe_port *pdata, u8 *addr, bool add);
+int axgbe_write_rss_lookup_table(struct axgbe_port *pdata);
+int axgbe_write_rss_hash_key(struct axgbe_port *pdata);
 
 #endif /* RTE_ETH_AXGBE_H_ */