summaryrefslogtreecommitdiff
path: root/drivers/staging/fsl_dpa_offload/dpa_stats.c
diff options
context:
space:
mode:
authorAurelian Zanoschi <Aurelian.Zanoschi@freescale.com>2013-05-10 06:49:06 (GMT)
committerFleming Andrew-AFLEMING <AFLEMING@freescale.com>2013-07-05 21:41:20 (GMT)
commit9de95d4efaeb6f86f53050e5ea4e1254cde53980 (patch)
treec6191c33e1353f0b6fb01f4069a8f1ea43804bdd /drivers/staging/fsl_dpa_offload/dpa_stats.c
parente8a66453a9b71d4d5290bd4962cc6ec2fda1b848 (diff)
downloadlinux-fsl-qoriq-9de95d4efaeb6f86f53050e5ea4e1254cde53980.tar.xz
dpa_offload: Added the implementation for Traffic Manager counter into DPA Stats
Added the Traffic Manager counter implementation into DPA Stats component. For getting the Class Queue or the Class Congestion Group counter values, the component will call QMan functions qman_ceetm_cq_get_dequeu_statistics, respectively qman_ceetm_ccg_get_reject_statistics. For both Traffic Manager Class or Congestion Group the values returned can be the number of bytes or the number of frames dequeued from a Class Queue, respectively rejected in all Class Queues that belong to the Congestion Group. Change-Id: I3d1e0b0c5a2e206de68d5745e02727b0e2aa0fad Signed-off-by: Aurelian Zanoschi <Aurelian.Zanoschi@freescale.com> Reviewed-on: http://git.am.freescale.net:8181/2877 Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com> Reviewed-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
Diffstat (limited to 'drivers/staging/fsl_dpa_offload/dpa_stats.c')
-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);