void (*free_fn)(void *node);
};
+struct roc_nix_tm_shaper_profile {
+#define ROC_NIX_TM_SHAPER_PROFILE_SZ (128)
+ uint8_t reserved[ROC_NIX_TM_SHAPER_PROFILE_SZ];
+
+ uint32_t id;
+ uint64_t commit_rate;
+ uint64_t commit_sz;
+ uint64_t peak_rate;
+ uint64_t peak_sz;
+ int32_t pkt_len_adj;
+ bool pkt_mode;
+ /* Function to free this memory */
+ void (*free_fn)(void *profile);
+};
+
int __roc_api roc_nix_tm_node_add(struct roc_nix *roc_nix,
struct roc_nix_tm_node *roc_node);
int __roc_api roc_nix_tm_node_delete(struct roc_nix *roc_nix, uint32_t node_id,
bool free);
int __roc_api roc_nix_tm_node_pkt_mode_update(struct roc_nix *roc_nix,
uint32_t node_id, bool pkt_mode);
+int __roc_api roc_nix_tm_shaper_profile_add(
+ struct roc_nix *roc_nix, struct roc_nix_tm_shaper_profile *profile);
+int __roc_api roc_nix_tm_shaper_profile_update(
+ struct roc_nix *roc_nix, struct roc_nix_tm_shaper_profile *profile);
+int __roc_api roc_nix_tm_shaper_profile_delete(struct roc_nix *roc_nix,
+ uint32_t id);
struct roc_nix_tm_node *__roc_api roc_nix_tm_node_get(struct roc_nix *roc_nix,
uint32_t node_id);
struct roc_nix_tm_node *__roc_api
roc_nix_tm_node_next(struct roc_nix *roc_nix, struct roc_nix_tm_node *__prev);
+struct roc_nix_tm_shaper_profile *__roc_api
+roc_nix_tm_shaper_profile_get(struct roc_nix *roc_nix, uint32_t profile_id);
+struct roc_nix_tm_shaper_profile *__roc_api roc_nix_tm_shaper_profile_next(
+ struct roc_nix *roc_nix, struct roc_nix_tm_shaper_profile *__prev);
/*
* TM utilities API.
enum roc_nix_tm_tree tree, bool free);
int nix_tm_free_node_resource(struct nix *nix, struct nix_tm_node *node);
int nix_tm_clear_path_xoff(struct nix *nix, struct nix_tm_node *node);
+void nix_tm_clear_shaper_profiles(struct nix *nix);
/*
* TM priv utils.
uint32_t id);
uint8_t nix_tm_sw_xoff_prep(struct nix_tm_node *node, bool enable,
volatile uint64_t *reg, volatile uint64_t *regval);
+uint64_t nix_tm_shaper_profile_rate_min(struct nix *nix);
+uint64_t nix_tm_shaper_rate_conv(uint64_t value, uint64_t *exponent_p,
+ uint64_t *mantissa_p, uint64_t *div_exp_p);
+uint64_t nix_tm_shaper_burst_conv(uint64_t value, uint64_t *exponent_p,
+ uint64_t *mantissa_p);
struct nix_tm_node *nix_tm_node_alloc(void);
void nix_tm_node_free(struct nix_tm_node *node);
+struct nix_tm_shaper_profile *nix_tm_shaper_profile_alloc(void);
+void nix_tm_shaper_profile_free(struct nix_tm_shaper_profile *profile);
#endif /* _ROC_NIX_PRIV_H_ */
#include "roc_api.h"
#include "roc_priv.h"
+void
+nix_tm_clear_shaper_profiles(struct nix *nix)
+{
+ struct nix_tm_shaper_profile *shaper_profile;
+
+ shaper_profile = TAILQ_FIRST(&nix->shaper_profile_list);
+ while (shaper_profile != NULL) {
+ if (shaper_profile->ref_cnt)
+ plt_warn("Shaper profile %u has non zero references",
+ shaper_profile->id);
+ TAILQ_REMOVE(&nix->shaper_profile_list, shaper_profile, shaper);
+ nix_tm_shaper_profile_free(shaper_profile);
+ shaper_profile = TAILQ_FIRST(&nix->shaper_profile_list);
+ }
+}
+
int
nix_tm_node_add(struct roc_nix *roc_nix, struct nix_tm_node *node)
{
int rc, i;
PLT_STATIC_ASSERT(sizeof(struct nix_tm_node) <= ROC_NIX_TM_NODE_SZ);
+ PLT_STATIC_ASSERT(sizeof(struct nix_tm_shaper_profile) <=
+ ROC_NIX_TM_SHAPER_PROFILE_SZ);
nix->tm_flags = 0;
for (i = 0; i < ROC_NIX_TM_TREE_MAX; i++)
return 0;
}
+static int
+nix_tm_shaper_profile_add(struct roc_nix *roc_nix,
+ struct nix_tm_shaper_profile *profile, int skip_ins)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ uint64_t commit_rate, commit_sz;
+ uint64_t peak_rate, peak_sz;
+ uint32_t id;
+
+ id = profile->id;
+ commit_rate = profile->commit.rate;
+ commit_sz = profile->commit.size;
+ peak_rate = profile->peak.rate;
+ peak_sz = profile->peak.size;
+
+ if (nix_tm_shaper_profile_search(nix, id) && !skip_ins)
+ return NIX_ERR_TM_SHAPER_PROFILE_EXISTS;
+
+ if (profile->pkt_len_adj < NIX_TM_LENGTH_ADJUST_MIN ||
+ profile->pkt_len_adj > NIX_TM_LENGTH_ADJUST_MAX)
+ return NIX_ERR_TM_SHAPER_PKT_LEN_ADJUST;
+
+ /* We cannot support both pkt length adjust and pkt mode */
+ if (profile->pkt_mode && profile->pkt_len_adj)
+ return NIX_ERR_TM_SHAPER_PKT_LEN_ADJUST;
+
+ /* commit rate and burst size can be enabled/disabled */
+ if (commit_rate || commit_sz) {
+ if (commit_sz < NIX_TM_MIN_SHAPER_BURST ||
+ commit_sz > NIX_TM_MAX_SHAPER_BURST)
+ return NIX_ERR_TM_INVALID_COMMIT_SZ;
+ else if (!nix_tm_shaper_rate_conv(commit_rate, NULL, NULL,
+ NULL))
+ return NIX_ERR_TM_INVALID_COMMIT_RATE;
+ }
+
+ /* Peak rate and burst size can be enabled/disabled */
+ if (peak_sz || peak_rate) {
+ if (peak_sz < NIX_TM_MIN_SHAPER_BURST ||
+ peak_sz > NIX_TM_MAX_SHAPER_BURST)
+ return NIX_ERR_TM_INVALID_PEAK_SZ;
+ else if (!nix_tm_shaper_rate_conv(peak_rate, NULL, NULL, NULL))
+ return NIX_ERR_TM_INVALID_PEAK_RATE;
+ }
+
+ if (!skip_ins)
+ TAILQ_INSERT_TAIL(&nix->shaper_profile_list, profile, shaper);
+
+ plt_tm_dbg("Added TM shaper profile %u, "
+ " pir %" PRIu64 " , pbs %" PRIu64 ", cir %" PRIu64
+ ", cbs %" PRIu64 " , adj %u, pkt_mode %u",
+ id, profile->peak.rate, profile->peak.size,
+ profile->commit.rate, profile->commit.size,
+ profile->pkt_len_adj, profile->pkt_mode);
+
+ /* Always use PIR for single rate shaping */
+ if (!peak_rate && commit_rate) {
+ profile->peak.rate = profile->commit.rate;
+ profile->peak.size = profile->commit.size;
+ profile->commit.rate = 0;
+ profile->commit.size = 0;
+ }
+
+ /* update min rate */
+ nix->tm_rate_min = nix_tm_shaper_profile_rate_min(nix);
+ return 0;
+}
+
+int
+roc_nix_tm_shaper_profile_add(struct roc_nix *roc_nix,
+ struct roc_nix_tm_shaper_profile *roc_profile)
+{
+ struct nix_tm_shaper_profile *profile;
+
+ profile = (struct nix_tm_shaper_profile *)roc_profile->reserved;
+
+ profile->ref_cnt = 0;
+ profile->id = roc_profile->id;
+ if (roc_profile->pkt_mode) {
+ /* Each packet accomulate single count, whereas HW
+ * considers each unit as Byte, so we need convert
+ * user pps to bps
+ */
+ profile->commit.rate = roc_profile->commit_rate * 8;
+ profile->peak.rate = roc_profile->peak_rate * 8;
+ } else {
+ profile->commit.rate = roc_profile->commit_rate;
+ profile->peak.rate = roc_profile->peak_rate;
+ }
+ profile->commit.size = roc_profile->commit_sz;
+ profile->peak.size = roc_profile->peak_sz;
+ profile->pkt_len_adj = roc_profile->pkt_len_adj;
+ profile->pkt_mode = roc_profile->pkt_mode;
+ profile->free_fn = roc_profile->free_fn;
+
+ return nix_tm_shaper_profile_add(roc_nix, profile, 0);
+}
+
+int
+roc_nix_tm_shaper_profile_update(struct roc_nix *roc_nix,
+ struct roc_nix_tm_shaper_profile *roc_profile)
+{
+ struct nix_tm_shaper_profile *profile;
+
+ profile = (struct nix_tm_shaper_profile *)roc_profile->reserved;
+
+ if (roc_profile->pkt_mode) {
+ /* Each packet accomulate single count, whereas HW
+ * considers each unit as Byte, so we need convert
+ * user pps to bps
+ */
+ profile->commit.rate = roc_profile->commit_rate * 8;
+ profile->peak.rate = roc_profile->peak_rate * 8;
+ } else {
+ profile->commit.rate = roc_profile->commit_rate;
+ profile->peak.rate = roc_profile->peak_rate;
+ }
+ profile->commit.size = roc_profile->commit_sz;
+ profile->peak.size = roc_profile->peak_sz;
+
+ return nix_tm_shaper_profile_add(roc_nix, profile, 1);
+}
+
+int
+roc_nix_tm_shaper_profile_delete(struct roc_nix *roc_nix, uint32_t id)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ struct nix_tm_shaper_profile *profile;
+
+ profile = nix_tm_shaper_profile_search(nix, id);
+ if (!profile)
+ return NIX_ERR_TM_INVALID_SHAPER_PROFILE;
+
+ if (profile->ref_cnt)
+ return NIX_ERR_TM_SHAPER_PROFILE_IN_USE;
+
+ plt_tm_dbg("Removing TM shaper profile %u", id);
+ TAILQ_REMOVE(&nix->shaper_profile_list, profile, shaper);
+ nix_tm_shaper_profile_free(profile);
+
+ /* update min rate */
+ nix->tm_rate_min = nix_tm_shaper_profile_rate_min(nix);
+ return 0;
+}
+
int
roc_nix_tm_node_add(struct roc_nix *roc_nix, struct roc_nix_tm_node *roc_node)
{
return NULL;
}
+uint64_t
+nix_tm_shaper_rate_conv(uint64_t value, uint64_t *exponent_p,
+ uint64_t *mantissa_p, uint64_t *div_exp_p)
+{
+ uint64_t div_exp, exponent, mantissa;
+
+ /* Boundary checks */
+ if (value < NIX_TM_MIN_SHAPER_RATE || value > NIX_TM_MAX_SHAPER_RATE)
+ return 0;
+
+ if (value <= NIX_TM_SHAPER_RATE(0, 0, 0)) {
+ /* Calculate rate div_exp and mantissa using
+ * the following formula:
+ *
+ * value = (2E6 * (256 + mantissa)
+ * / ((1 << div_exp) * 256))
+ */
+ div_exp = 0;
+ exponent = 0;
+ mantissa = NIX_TM_MAX_RATE_MANTISSA;
+
+ while (value < (NIX_TM_SHAPER_RATE_CONST / (1 << div_exp)))
+ div_exp += 1;
+
+ while (value < ((NIX_TM_SHAPER_RATE_CONST * (256 + mantissa)) /
+ ((1 << div_exp) * 256)))
+ mantissa -= 1;
+ } else {
+ /* Calculate rate exponent and mantissa using
+ * the following formula:
+ *
+ * value = (2E6 * ((256 + mantissa) << exponent)) / 256
+ *
+ */
+ div_exp = 0;
+ exponent = NIX_TM_MAX_RATE_EXPONENT;
+ mantissa = NIX_TM_MAX_RATE_MANTISSA;
+
+ while (value < (NIX_TM_SHAPER_RATE_CONST * (1 << exponent)))
+ exponent -= 1;
+
+ while (value < ((NIX_TM_SHAPER_RATE_CONST *
+ ((256 + mantissa) << exponent)) /
+ 256))
+ mantissa -= 1;
+ }
+
+ if (div_exp > NIX_TM_MAX_RATE_DIV_EXP ||
+ exponent > NIX_TM_MAX_RATE_EXPONENT ||
+ mantissa > NIX_TM_MAX_RATE_MANTISSA)
+ return 0;
+
+ if (div_exp_p)
+ *div_exp_p = div_exp;
+ if (exponent_p)
+ *exponent_p = exponent;
+ if (mantissa_p)
+ *mantissa_p = mantissa;
+
+ /* Calculate real rate value */
+ return NIX_TM_SHAPER_RATE(exponent, mantissa, div_exp);
+}
+
+uint64_t
+nix_tm_shaper_burst_conv(uint64_t value, uint64_t *exponent_p,
+ uint64_t *mantissa_p)
+{
+ uint64_t exponent, mantissa;
+
+ if (value < NIX_TM_MIN_SHAPER_BURST || value > NIX_TM_MAX_SHAPER_BURST)
+ return 0;
+
+ /* Calculate burst exponent and mantissa using
+ * the following formula:
+ *
+ * value = (((256 + mantissa) << (exponent + 1)
+ / 256)
+ *
+ */
+ exponent = NIX_TM_MAX_BURST_EXPONENT;
+ mantissa = NIX_TM_MAX_BURST_MANTISSA;
+
+ while (value < (1ull << (exponent + 1)))
+ exponent -= 1;
+
+ while (value < ((256 + mantissa) << (exponent + 1)) / 256)
+ mantissa -= 1;
+
+ if (exponent > NIX_TM_MAX_BURST_EXPONENT ||
+ mantissa > NIX_TM_MAX_BURST_MANTISSA)
+ return 0;
+
+ if (exponent_p)
+ *exponent_p = exponent;
+ if (mantissa_p)
+ *mantissa_p = mantissa;
+
+ return NIX_TM_SHAPER_BURST(exponent, mantissa);
+}
+
static uint16_t
nix_tm_max_prio(struct nix *nix, uint16_t hw_lvl)
{
return k;
}
+/* Search for min rate in topology */
+uint64_t
+nix_tm_shaper_profile_rate_min(struct nix *nix)
+{
+ struct nix_tm_shaper_profile *profile;
+ uint64_t rate_min = 1E9; /* 1 Gbps */
+
+ TAILQ_FOREACH(profile, &nix->shaper_profile_list, shaper) {
+ if (profile->peak.rate && profile->peak.rate < rate_min)
+ rate_min = profile->peak.rate;
+
+ if (profile->commit.rate && profile->commit.rate < rate_min)
+ rate_min = profile->commit.rate;
+ }
+ return rate_min;
+}
+
uint16_t
nix_tm_resource_avail(struct nix *nix, uint8_t hw_lvl, bool contig)
{
return (struct roc_nix_tm_node *)TAILQ_NEXT(prev, node);
}
+struct roc_nix_tm_shaper_profile *
+roc_nix_tm_shaper_profile_get(struct roc_nix *roc_nix, uint32_t profile_id)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ struct nix_tm_shaper_profile *profile;
+
+ profile = nix_tm_shaper_profile_search(nix, profile_id);
+ return (struct roc_nix_tm_shaper_profile *)profile;
+}
+
+struct roc_nix_tm_shaper_profile *
+roc_nix_tm_shaper_profile_next(struct roc_nix *roc_nix,
+ struct roc_nix_tm_shaper_profile *__prev)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ struct nix_tm_shaper_profile_list *list;
+ struct nix_tm_shaper_profile *prev;
+
+ prev = (struct nix_tm_shaper_profile *)__prev;
+ list = &nix->shaper_profile_list;
+
+ /* HEAD of the list */
+ if (!prev)
+ return (struct roc_nix_tm_shaper_profile *)TAILQ_FIRST(list);
+
+ return (struct roc_nix_tm_shaper_profile *)TAILQ_NEXT(prev, shaper);
+}
+
struct nix_tm_node *
nix_tm_node_alloc(void)
{
(node->free_fn)(node);
}
+
+struct nix_tm_shaper_profile *
+nix_tm_shaper_profile_alloc(void)
+{
+ struct nix_tm_shaper_profile *profile;
+
+ profile = plt_zmalloc(sizeof(struct nix_tm_shaper_profile), 0);
+ if (!profile)
+ return NULL;
+
+ profile->free_fn = plt_free;
+ return profile;
+}
+
+void
+nix_tm_shaper_profile_free(struct nix_tm_shaper_profile *profile)
+{
+ if (!profile || !profile->free_fn)
+ return;
+
+ (profile->free_fn)(profile);
+}
roc_nix_tm_node_name_get;
roc_nix_tm_node_next;
roc_nix_tm_node_pkt_mode_update;
+ roc_nix_tm_shaper_profile_add;
+ roc_nix_tm_shaper_profile_delete;
+ roc_nix_tm_shaper_profile_get;
+ roc_nix_tm_shaper_profile_next;
+ roc_nix_tm_shaper_profile_update;
roc_nix_tm_sq_aura_fc;
roc_nix_tm_sq_flush_spin;
roc_nix_unregister_cq_irqs;