summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_stats.c252
1 files changed, 241 insertions, 11 deletions
diff --git a/drivers/staging/fsl_dpa_offload/dpa_stats.c b/drivers/staging/fsl_dpa_offload/dpa_stats.c
index 15ccca2..6ae4e9e6 100644
--- a/drivers/staging/fsl_dpa_offload/dpa_stats.c
+++ b/drivers/staging/fsl_dpa_offload/dpa_stats.c
@@ -37,6 +37,7 @@
#include <linux/of_platform.h>
#include "lnxwrp_fm.h"
#include "dpaa_eth.h"
+#include <linux/fsl_qman.h>
/* DPA offloading layer includes */
#include "dpa_stats.h"
@@ -74,6 +75,12 @@ static int get_cnt_ccnode_hash_stats(struct dpa_stats_req_cb *req_cb,
static int get_cnt_ccnode_index_stats(struct dpa_stats_req_cb *req_cb,
struct dpa_stats_cnt_cb *cnt_cb);
+static int get_cnt_traffic_mng_cq_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb);
+
+static int get_cnt_traffic_mng_ccg_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb);
+
static void async_req_work_func(struct work_struct *work);
/* check that the provided params are valid */
@@ -963,6 +970,16 @@ static void create_cnt_ipsec_stats(struct dpa_stats *dpa_stats)
struct dpa_ipsec_sa_stats, packets_count);
}
+static void create_cnt_traffic_mng_stats(struct dpa_stats *dpa_stats)
+{
+ /* DPA_STATS_CNT_NUM_OF_BYTES */
+ dpa_stats->stats_sel[DPA_STATS_CNT_TRAFFIC_MNG][0] =
+ DPA_STATS_CNT_NUM_OF_BYTES;
+ /* DPA_STATS_CNT_NUM_OF_PACKETS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_TRAFFIC_MNG][1] =
+ DPA_STATS_CNT_NUM_OF_PACKETS;
+}
+
static int copy_key_descriptor(const struct dpa_offload_lookup_key *src,
struct dpa_offload_lookup_key *dst)
{
@@ -1576,6 +1593,79 @@ static int set_cnt_ipsec_cb(struct dpa_stats_cnt_cb *cnt_cb,
return 0;
}
+static int set_cnt_traffic_mng_cb(struct dpa_stats_cnt_cb *cnt_cb,
+ const struct dpa_stats_cnt_params *params)
+{
+ struct dpa_stats *dpa_stats = cnt_cb->dpa_stats;
+ uint32_t cnt_sel = params->traffic_mng_params.cnt_sel;
+ uint32_t cnt_src = params->traffic_mng_params.src;
+ uint64_t frames, bytes;
+ int err = 0;
+
+ if (!dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EFAULT;
+ }
+
+ if (!params->traffic_mng_params.traffic_mng) {
+ log_err("Parameter traffic_mng handle cannot be NULL\n");
+ return -EFAULT;
+ }
+
+ if (cnt_sel == 0 || cnt_sel > DPA_STATS_CNT_NUM_ALL) {
+ log_err("Parameter cnt_sel %d must be in range (1 - %d) for "
+ "counter id %d\n", cnt_sel, DPA_STATS_CNT_NUM_ALL,
+ cnt_cb->id);
+ return -EINVAL;
+ }
+
+ cnt_cb->gen_cb.objs[0] = params->traffic_mng_params.traffic_mng;
+ cnt_cb->members_num = 1;
+
+ /* Check the counter source and the Traffic Manager object */
+ switch (cnt_src) {
+ case DPA_STATS_CNT_TRAFFIC_CLASS:
+ cnt_cb->f_get_cnt_stats = get_cnt_traffic_mng_cq_stats;
+ err = qman_ceetm_cq_get_dequeue_statistics(
+ params->traffic_mng_params.traffic_mng,
+ 0, &frames, &bytes);
+ if (err < 0) {
+ log_err("Invalid Traffic Manager qm_ceetm_cq object for"
+ " counter id %d\n", cnt_cb->id);
+ return -EINVAL;
+ }
+ break;
+ case DPA_STATS_CNT_TRAFFIC_CG:
+ cnt_cb->f_get_cnt_stats = get_cnt_traffic_mng_ccg_stats;
+ err = qman_ceetm_ccg_get_reject_statistics(
+ params->traffic_mng_params.traffic_mng,
+ 0, &frames, &bytes);
+ if (err < 0) {
+ log_err("Invalid Traffic Manager qm_ceetm_ccg object "
+ "for counter id %d\n", cnt_cb->id);
+ return -EINVAL;
+ }
+ break;
+ default:
+ log_err("Parameter src %d must be in range (%d - %d) for "
+ "counter id %d\n", cnt_src, DPA_STATS_CNT_TRAFFIC_CLASS,
+ DPA_STATS_CNT_TRAFFIC_CG, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ /* Decrease one to obtain the mask for all statistics */
+ if (cnt_sel == DPA_STATS_CNT_NUM_ALL)
+ cnt_sel -= 1;
+
+ cnt_sel_to_stats(&cnt_cb->info,
+ dpa_stats->stats_sel[DPA_STATS_CNT_TRAFFIC_MNG], cnt_sel);
+
+ /* Set number of bytes that will be written by this counter */
+ cnt_cb->bytes_num = STATS_VAL_SIZE * cnt_cb->info.stats_num;
+
+ return 0;
+}
+
static int set_cls_cnt_eth_cb(struct dpa_stats_cnt_cb *cnt_cb,
const struct dpa_stats_cls_cnt_params *params)
{
@@ -2138,6 +2228,92 @@ static int set_cls_cnt_ipsec_cb(struct dpa_stats_cnt_cb *cnt_cb,
return 0;
}
+static int set_cls_cnt_traffic_mng_cb(struct dpa_stats_cnt_cb *cnt_cb,
+ const struct dpa_stats_cls_cnt_params *params)
+{
+ struct dpa_stats *dpa_stats = cnt_cb->dpa_stats;
+ uint32_t cnt_sel = params->traffic_mng_params.cnt_sel;
+ uint32_t cnt_src = params->traffic_mng_params.src;
+ uint32_t i = 0;
+ uint64_t frames, bytes;
+ int err = 0;
+
+ if (!dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EFAULT;
+ }
+
+ /* First check the counter src */
+ if (cnt_src > DPA_STATS_CNT_TRAFFIC_CG ||
+ cnt_src < DPA_STATS_CNT_TRAFFIC_CLASS) {
+ log_err("Parameter src %d must be in range (%d - %d) for "
+ "counter id %d\n", cnt_src, DPA_STATS_CNT_TRAFFIC_CLASS,
+ DPA_STATS_CNT_TRAFFIC_CG, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ /* Then check the counter selection */
+ if (cnt_sel == 0 || cnt_sel > DPA_STATS_CNT_NUM_ALL) {
+ log_err("Parameter cnt_sel %d must be in range (1 - %d) for "
+ "counter id %d\n", cnt_sel, DPA_STATS_CNT_NUM_ALL,
+ cnt_cb->id);
+ return -EINVAL;
+ }
+
+ cnt_cb->members_num = params->class_members;
+
+ /* Check the user provided Traffic Manager object */
+ for (i = 0; i < params->class_members; i++) {
+ if (!params->traffic_mng_params.traffic_mng[i]) {
+ log_err("Parameter traffic_mng handle cannot be NULL "
+ "for member %d\n", i);
+ return -EFAULT;
+ }
+ cnt_cb->gen_cb.objs[i] =
+ params->traffic_mng_params.traffic_mng[i];
+
+ switch (cnt_src) {
+ case DPA_STATS_CNT_TRAFFIC_CLASS:
+ cnt_cb->f_get_cnt_stats = get_cnt_traffic_mng_cq_stats;
+ err = qman_ceetm_cq_get_dequeue_statistics(
+ params->traffic_mng_params.traffic_mng[i], 0,
+ &frames, &bytes);
+ if (err < 0) {
+ log_err("Invalid Traffic Manager qm_ceetm_cq "
+ "object for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+ break;
+ case DPA_STATS_CNT_TRAFFIC_CG:
+ cnt_cb->f_get_cnt_stats = get_cnt_traffic_mng_ccg_stats;
+ err = qman_ceetm_ccg_get_reject_statistics(
+ params->traffic_mng_params.traffic_mng[i], 0,
+ &frames, &bytes);
+ if (err < 0) {
+ log_err("Invalid Traffic Manager qm_ceetm_ccg "
+ "object for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+ break;
+ }
+ }
+
+ /* Decrease one to obtain the mask for all statistics */
+ if (cnt_sel == DPA_STATS_CNT_NUM_ALL)
+ cnt_sel -= 1;
+
+ cnt_sel_to_stats(&cnt_cb->info,
+ dpa_stats->stats_sel[DPA_STATS_CNT_TRAFFIC_MNG], cnt_sel);
+
+ /* Set number of bytes that will be written by this counter */
+ cnt_cb->bytes_num = cnt_cb->members_num *
+ STATS_VAL_SIZE * cnt_cb->info.stats_num;
+
+ return 0;
+}
+
int set_classif_tbl_member(const struct dpa_stats_cls_member_params *prm,
int member_index,
struct dpa_stats_cnt_cb *cnt_cb)
@@ -2685,6 +2861,50 @@ static int get_cnt_ipsec_stats(struct dpa_stats_req_cb *req_cb,
return 0;
}
+static int get_cnt_traffic_mng_cq_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb)
+{
+ uint32_t i = 0;
+ uint64_t stats_val[2];
+ int err = 0;
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ /* Retrieve statistics for the current member */
+ err = qman_ceetm_cq_get_dequeue_statistics(
+ cnt_cb->gen_cb.objs[i], 0,
+ stats_val[1], stats_val[0]);
+ if (err < 0) {
+ log_err("Cannot retrieve Traffic Manager Class Queue "
+ "statistics for counter id %d\n", cnt_cb->id);
+ return -EINVAL;
+ }
+ get_cnt_64bit_stats(req_cb, &cnt_cb->info, stats_val, i);
+ }
+ return 0;
+}
+
+static int get_cnt_traffic_mng_ccg_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb)
+{
+ uint32_t i = 0;
+ uint64_t stats_val[2];
+ int err = 0;
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ err = qman_ceetm_ccg_get_reject_statistics(
+ cnt_cb->gen_cb.objs[i], 0,
+ stats_val[1], stats_val[0]);
+ if (err < 0) {
+ log_err("Cannot retrieve Traffic Manager Class "
+ "Congestion Group statistics for counter id "
+ "%d\n", cnt_cb->id);
+ return -EINVAL;
+ }
+ get_cnt_64bit_stats(req_cb, &cnt_cb->info, stats_val, i);
+ }
+ return 0;
+}
+
static void async_req_work_func(struct work_struct *work)
{
struct dpa_stats_req_cb *req_cb = NULL;
@@ -2781,6 +3001,9 @@ int dpa_stats_init(const struct dpa_stats_params *params, int *dpa_stats_id)
/* Map IPSec counters */
create_cnt_ipsec_stats(dpa_stats);
+ /* Map Traffic Manager counters to QMan CEETM statistics */
+ create_cnt_traffic_mng_stats(dpa_stats);
+
gbl_dpa_stats = dpa_stats;
return 0;
@@ -2903,11 +3126,15 @@ int dpa_stats_create_counter(int dpa_stats_id,
}
break;
case DPA_STATS_CNT_TRAFFIC_MNG:
- log_err("Counter of type DPA_STATS_CNT_TRAFFIC_MNG(%d) is not "
- "supported for counter id %d",
- DPA_STATS_CNT_TRAFFIC_MNG, cnt_cb->id);
- mutex_unlock(&cnt_cb->lock);
- return -EINVAL;
+ cnt_cb->type = DPA_STATS_CNT_TRAFFIC_MNG;
+
+ err = set_cnt_traffic_mng_cb(cnt_cb, params);
+ if (err != 0) {
+ log_err("Cannot crate Traffic Manager counter id %d"
+ "\n", cnt_cb->id);
+ goto create_counter_err;
+ }
+ break;
default:
log_err("Unsupported counter type %d for counter id %d\n",
params->type, cnt_cb->id);
@@ -3064,14 +3291,17 @@ int dpa_stats_create_class_counter(int dpa_stats_id,
cnt_cb->id);
goto create_counter_err;
}
-
break;
case DPA_STATS_CNT_TRAFFIC_MNG:
- log_err("Counter of type DPA_STATS_CNT_TRAFFIC_MNG(%d) is not "
- "supported for counter id %d",
- DPA_STATS_CNT_TRAFFIC_MNG, cnt_cb->id);
- mutex_unlock(&cnt_cb->lock);
- return -EINVAL;
+ cnt_cb->type = DPA_STATS_CNT_TRAFFIC_MNG;
+
+ err = set_cls_cnt_traffic_mng_cb(cnt_cb, params);
+ if (err != 0) {
+ log_err("Cannot create Traffic Manager counter id %d"
+ "\n", cnt_cb->id);
+ goto create_counter_err;
+ }
+ break;
default:
log_err("Unsupported counter type %d for counter id %d\n",
params->type, cnt_cb->id);