net/i40e: support adding TM shaper profile
[dpdk.git] / drivers / net / i40e / i40e_tm.c
index 9fc2f45..5780815 100644 (file)
  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <rte_malloc.h>
+
 #include "base/i40e_prototype.h"
 #include "i40e_ethdev.h"
 
 static int i40e_tm_capabilities_get(struct rte_eth_dev *dev,
                                    struct rte_tm_capabilities *cap,
                                    struct rte_tm_error *error);
+static int i40e_shaper_profile_add(struct rte_eth_dev *dev,
+                                  uint32_t shaper_profile_id,
+                                  struct rte_tm_shaper_params *profile,
+                                  struct rte_tm_error *error);
 
 const struct rte_tm_ops i40e_tm_ops = {
        .capabilities_get = i40e_tm_capabilities_get,
+       .shaper_profile_add = i40e_shaper_profile_add,
 };
 
 int
@@ -54,6 +61,30 @@ i40e_tm_ops_get(struct rte_eth_dev *dev __rte_unused,
        return 0;
 }
 
+void
+i40e_tm_conf_init(struct rte_eth_dev *dev)
+{
+       struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+       /* initialize shaper profile list */
+       TAILQ_INIT(&pf->tm_conf.shaper_profile_list);
+}
+
+void
+i40e_tm_conf_uninit(struct rte_eth_dev *dev)
+{
+       struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+       struct i40e_tm_shaper_profile *shaper_profile;
+
+       /* Remove all shaper profiles */
+       while ((shaper_profile =
+              TAILQ_FIRST(&pf->tm_conf.shaper_profile_list))) {
+               TAILQ_REMOVE(&pf->tm_conf.shaper_profile_list,
+                            shaper_profile, node);
+               rte_free(shaper_profile);
+       }
+}
+
 static inline uint16_t
 i40e_tc_nb_get(struct rte_eth_dev *dev)
 {
@@ -135,3 +166,91 @@ i40e_tm_capabilities_get(struct rte_eth_dev *dev,
 
        return 0;
 }
+
+static inline struct i40e_tm_shaper_profile *
+i40e_shaper_profile_search(struct rte_eth_dev *dev,
+                          uint32_t shaper_profile_id)
+{
+       struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+       struct i40e_shaper_profile_list *shaper_profile_list =
+               &pf->tm_conf.shaper_profile_list;
+       struct i40e_tm_shaper_profile *shaper_profile;
+
+       TAILQ_FOREACH(shaper_profile, shaper_profile_list, node) {
+               if (shaper_profile_id == shaper_profile->shaper_profile_id)
+                       return shaper_profile;
+       }
+
+       return NULL;
+}
+
+static int
+i40e_shaper_profile_param_check(struct rte_tm_shaper_params *profile,
+                               struct rte_tm_error *error)
+{
+       /* min rate not supported */
+       if (profile->committed.rate) {
+               error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE;
+               error->message = "committed rate not supported";
+               return -EINVAL;
+       }
+       /* min bucket size not supported */
+       if (profile->committed.size) {
+               error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_SIZE;
+               error->message = "committed bucket size not supported";
+               return -EINVAL;
+       }
+       /* max bucket size not supported */
+       if (profile->peak.size) {
+               error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE;
+               error->message = "peak bucket size not supported";
+               return -EINVAL;
+       }
+       /* length adjustment not supported */
+       if (profile->pkt_length_adjust) {
+               error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PKT_ADJUST_LEN;
+               error->message = "packet length adjustment not supported";
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int
+i40e_shaper_profile_add(struct rte_eth_dev *dev,
+                       uint32_t shaper_profile_id,
+                       struct rte_tm_shaper_params *profile,
+                       struct rte_tm_error *error)
+{
+       struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+       struct i40e_tm_shaper_profile *shaper_profile;
+       int ret;
+
+       if (!profile || !error)
+               return -EINVAL;
+
+       ret = i40e_shaper_profile_param_check(profile, error);
+       if (ret)
+               return ret;
+
+       shaper_profile = i40e_shaper_profile_search(dev, shaper_profile_id);
+
+       if (shaper_profile) {
+               error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
+               error->message = "profile ID exist";
+               return -EINVAL;
+       }
+
+       shaper_profile = rte_zmalloc("i40e_tm_shaper_profile",
+                                    sizeof(struct i40e_tm_shaper_profile),
+                                    0);
+       if (!shaper_profile)
+               return -ENOMEM;
+       shaper_profile->shaper_profile_id = shaper_profile_id;
+       (void)rte_memcpy(&shaper_profile->profile, profile,
+                        sizeof(struct rte_tm_shaper_params));
+       TAILQ_INSERT_TAIL(&pf->tm_conf.shaper_profile_list,
+                         shaper_profile, node);
+
+       return 0;
+}