+static struct rte_sched_subport_profile_params *
+subport_profile_get(struct rte_eth_dev *dev, struct tm_node *np)
+{
+ struct pmd_internals *p = dev->data->dev_private;
+ struct tm_params *t = &p->soft.tm.params;
+ uint32_t subport_id = tm_node_subport_id(dev, np->parent_node);
+
+ if (subport_id >= TM_MAX_SUBPORT_PROFILE)
+ return NULL;
+
+ return &t->subport_profile[subport_id];
+}
+
+static void
+subport_profile_mark(struct rte_eth_dev *dev,
+ uint32_t subport_id,
+ uint32_t subport_profile_id)
+{
+ struct pmd_internals *p = dev->data->dev_private;
+ struct tm_params *t = &p->soft.tm.params;
+
+ t->subport_to_profile[subport_id] = subport_profile_id;
+}
+
+static void
+subport_profile_install(struct rte_eth_dev *dev,
+ struct rte_sched_subport_profile_params *sp,
+ uint32_t subport_profile_id)
+{
+ struct pmd_internals *p = dev->data->dev_private;
+ struct tm_params *t = &p->soft.tm.params;
+
+ memcpy(&t->subport_profile[subport_profile_id],
+ sp, sizeof(*sp));
+ t->n_subport_profiles++;
+}
+
+static int
+subport_profile_free_exists(struct rte_eth_dev *dev,
+ uint32_t *subport_profile_id)
+{
+ struct pmd_internals *p = dev->data->dev_private;
+ struct tm_params *t = &p->soft.tm.params;
+
+ if (t->n_subport_profiles < TM_MAX_SUBPORT_PROFILE) {
+ *subport_profile_id = t->n_subport_profiles;
+ return 1;
+ }
+
+ return 0;
+}
+
+static void
+subport_profile_build(struct rte_eth_dev *dev, struct tm_node *np,
+ struct rte_sched_subport_profile_params *sp)
+{
+ uint32_t i;
+ memset(sp, 0, sizeof(*sp));
+
+ sp->tb_rate = np->shaper_profile->params.peak.rate;
+ sp->tb_size = np->shaper_profile->params.peak.size;
+
+ for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) {
+ struct tm_shared_shaper *ss;
+ struct tm_shaper_profile *ssp;
+
+ ss = tm_subport_tc_shared_shaper_get(dev, np, i);
+ ssp = (ss) ? tm_shaper_profile_search(dev,
+ ss->shaper_profile_id) :
+ np->shaper_profile;
+ sp->tc_rate[i] = ssp->params.peak.rate;
+ }
+
+ /* Traffic Class (TC) */
+ sp->tc_period = SUBPORT_TC_PERIOD;
+}
+
+static int
+subport_profiles_generate(struct rte_eth_dev *dev)
+{
+ struct pmd_internals *p = dev->data->dev_private;
+ struct tm_hierarchy *h = &p->soft.tm.h;
+ struct tm_node_list *nl = &h->nodes;
+ struct tm_node *ns;
+ uint32_t subport_id;
+
+ /* Objective: Fill in the following fields in struct tm_params:
+ * - subport_profiles
+ * - n_subport_profiles
+ * - subport_to_profile
+ */
+
+ subport_id = 0;
+ TAILQ_FOREACH(ns, nl, node) {
+ if (ns->level != TM_NODE_LEVEL_SUBPORT)
+ continue;
+
+ struct rte_sched_subport_profile_params sp;
+ uint32_t pos;
+
+ memset(&sp, 0, sizeof(sp));
+
+ subport_profile_build(dev, ns, &sp);
+
+ if (!subport_profile_exists(dev, &sp, &pos)) {
+ if (!subport_profile_free_exists(dev, &pos))
+ return -1;
+
+ subport_profile_install(dev, &sp, pos);
+ }
+
+ subport_profile_mark(dev, subport_id, pos);
+
+ subport_id++;
+ }
+
+ return 0;
+}
+
+