From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 60257A0547; Fri, 5 Mar 2021 14:45:51 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 786B022A426; Fri, 5 Mar 2021 14:41:15 +0100 (CET) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 6FF7D22A41C for ; Fri, 5 Mar 2021 14:41:13 +0100 (CET) Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 125DelDQ001639 for ; Fri, 5 Mar 2021 05:41:12 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=pfpt0220; bh=95KDmmUfCLeVBm08j4v0T33fXRU886vqHjVCPnAB684=; b=Awn+MpCMEYLKZslXvTWE7vMeFKbay2CGDNkB3T7lxAQF5REoMqG4lYfKTzJNqJ89IGTd AD2dzcALJgY6zNrSr7JtnQbZ+lmWjrBAr4W9gDS9FoiRkBqpftFcYyhLQm1tWhA/ssqM 3JJWfLNE+FG4mouuGXucdxZSyB6wxsn7ASxQQyalmNScKotUmVQU7zOEoAdVsr1pw3nu 8lLeJt0yHHSbGimgj0JnjgVDZ5tn8xK4SKFp6w/PiYx2xo2CRvValQPzCNWA6bpaQubt XLmANL7jBcmmbK3shBR6u8fq1WlpmUbRFELVDG04wr7wNLW0tkusgGIlXHvdddDKF8jX xg== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com with ESMTP id 372s2umrqe-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Fri, 05 Mar 2021 05:41:12 -0800 Received: from SC-EXCH02.marvell.com (10.93.176.82) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Fri, 5 Mar 2021 05:41:11 -0800 Received: from DC5-EXCH01.marvell.com (10.69.176.38) by SC-EXCH02.marvell.com (10.93.176.82) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Fri, 5 Mar 2021 05:41:10 -0800 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Fri, 5 Mar 2021 05:41:10 -0800 Received: from hyd1588t430.marvell.com (unknown [10.29.52.204]) by maili.marvell.com (Postfix) with ESMTP id 0C4F23F703F; Fri, 5 Mar 2021 05:41:07 -0800 (PST) From: Nithin Dabilpuram To: CC: , , , , , , , Nithin Dabilpuram Date: Fri, 5 Mar 2021 19:09:00 +0530 Message-ID: <20210305133918.8005-35-ndabilpuram@marvell.com> X-Mailer: git-send-email 2.8.4 In-Reply-To: <20210305133918.8005-1-ndabilpuram@marvell.com> References: <20210305133918.8005-1-ndabilpuram@marvell.com> MIME-Version: 1.0 Content-Type: text/plain X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.369, 18.0.761 definitions=2021-03-05_08:2021-03-03, 2021-03-05 signatures=0 Subject: [dpdk-dev] [PATCH 34/52] common/cnxk: add nix tm shaper profile add support X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Satha Rao Add support to add/delete/update shaper profile for a given NIX. Also add support to walk through existing shaper profiles. Signed-off-by: Nithin Dabilpuram Signed-off-by: Satha Rao --- drivers/common/cnxk/roc_nix.h | 25 +++++ drivers/common/cnxk/roc_nix_priv.h | 8 ++ drivers/common/cnxk/roc_nix_tm.c | 18 ++++ drivers/common/cnxk/roc_nix_tm_ops.c | 145 ++++++++++++++++++++++++++++ drivers/common/cnxk/roc_nix_tm_utils.c | 167 +++++++++++++++++++++++++++++++++ drivers/common/cnxk/version.map | 5 + 6 files changed, 368 insertions(+) diff --git a/drivers/common/cnxk/roc_nix.h b/drivers/common/cnxk/roc_nix.h index fbbea1b..cadf4ea 100644 --- a/drivers/common/cnxk/roc_nix.h +++ b/drivers/common/cnxk/roc_nix.h @@ -340,17 +340,42 @@ struct roc_nix_tm_node { 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. diff --git a/drivers/common/cnxk/roc_nix_priv.h b/drivers/common/cnxk/roc_nix_priv.h index 2f7c20e..278e7df 100644 --- a/drivers/common/cnxk/roc_nix_priv.h +++ b/drivers/common/cnxk/roc_nix_priv.h @@ -330,6 +330,7 @@ int nix_tm_node_delete(struct roc_nix *roc_nix, uint32_t node_id, 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. @@ -346,7 +347,14 @@ struct nix_tm_shaper_profile *nix_tm_shaper_profile_search(struct nix *nix, 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_ */ diff --git a/drivers/common/cnxk/roc_nix_tm.c b/drivers/common/cnxk/roc_nix_tm.c index 776d6b4..1bfdbf9 100644 --- a/drivers/common/cnxk/roc_nix_tm.c +++ b/drivers/common/cnxk/roc_nix_tm.c @@ -5,6 +5,22 @@ #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) { @@ -532,6 +548,8 @@ nix_tm_conf_init(struct roc_nix *roc_nix) 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++) diff --git a/drivers/common/cnxk/roc_nix_tm_ops.c b/drivers/common/cnxk/roc_nix_tm_ops.c index ede30fa..015f20e 100644 --- a/drivers/common/cnxk/roc_nix_tm_ops.c +++ b/drivers/common/cnxk/roc_nix_tm_ops.c @@ -66,6 +66,151 @@ roc_nix_tm_sq_aura_fc(struct roc_nix_sq *sq, bool enable) 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) { diff --git a/drivers/common/cnxk/roc_nix_tm_utils.c b/drivers/common/cnxk/roc_nix_tm_utils.c index 09cb693..5eb93a7 100644 --- a/drivers/common/cnxk/roc_nix_tm_utils.c +++ b/drivers/common/cnxk/roc_nix_tm_utils.c @@ -77,6 +77,106 @@ nix_tm_node_search(struct nix *nix, uint32_t node_id, enum roc_nix_tm_tree tree) 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) { @@ -183,6 +283,23 @@ nix_tm_sw_xoff_prep(struct nix_tm_node *node, bool enable, 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) { @@ -251,6 +368,34 @@ roc_nix_tm_node_next(struct roc_nix *roc_nix, struct roc_nix_tm_node *__prev) 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) { @@ -272,3 +417,25 @@ nix_tm_node_free(struct nix_tm_node *node) (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); +} diff --git a/drivers/common/cnxk/version.map b/drivers/common/cnxk/version.map index 0f70fff..5acbf4c 100644 --- a/drivers/common/cnxk/version.map +++ b/drivers/common/cnxk/version.map @@ -110,6 +110,11 @@ INTERNAL { 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; -- 2.8.4