diff options
-rw-r--r-- | drivers/staging/fsl_dpa_offload/dpa_stats.c | 252 |
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); |