summaryrefslogtreecommitdiff
path: root/drivers/staging/fsl_dpa_offload
diff options
context:
space:
mode:
authorAurelian Zanoschi <Aurelian.Zanoschi@freescale.com>2013-08-30 08:05:25 (GMT)
committerJ. German Rivera <German.Rivera@freescale.com>2013-09-06 20:51:31 (GMT)
commitdb651a6e8e0df939cb977a8799816c04b07506c3 (patch)
tree609816a459ff89c889bbec0b0c8664d7b08c7633 /drivers/staging/fsl_dpa_offload
parent589a595b9d937d554e0a048f4256db82bda917ca (diff)
downloadlinux-fsl-qoriq-db651a6e8e0df939cb977a8799816c04b07506c3.tar.xz
dpa_offload: Added Traffic Manager user-space counter implementation
Added support for Traffic Manager user-space DPA Stats counter in driver. The Traffic Manager counters can be used both from user-space or kernel-space depending on the user needs. If the counter is created from user-space, all the retrieving mechanism is implemented in user-space and same happens for kernel-space case. The counters is marked as a user-space counter and the kernel will provide for this counter only the offset where the user-space library to write the statistics of the counter. This patch corrects some compilation warnings caused by QMan CEETM API changes. Signed-off-by: Aurelian Zanoschi <Aurelian.Zanoschi@freescale.com> Change-Id: Ia97506a8a95e2c764f5176d35497f0ac95cb97cc Reviewed-on: http://git.am.freescale.net:8181/4447 Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com> Reviewed-by: Chereji Marian-Cornel-R27762 <marian.chereji@freescale.com> Reviewed-by: Rivera Jose-B46482 <German.Rivera@freescale.com>
Diffstat (limited to 'drivers/staging/fsl_dpa_offload')
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_stats.c262
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_stats.h1
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_stats_ioctl.h12
-rw-r--r--drivers/staging/fsl_dpa_offload/wrp_dpa_stats.c81
-rw-r--r--drivers/staging/fsl_dpa_offload/wrp_dpa_stats.h23
5 files changed, 232 insertions, 147 deletions
diff --git a/drivers/staging/fsl_dpa_offload/dpa_stats.c b/drivers/staging/fsl_dpa_offload/dpa_stats.c
index ef6dd1a..6c3605a 100644
--- a/drivers/staging/fsl_dpa_offload/dpa_stats.c
+++ b/drivers/staging/fsl_dpa_offload/dpa_stats.c
@@ -51,6 +51,8 @@
#define CLASSIF_STATS_SHIFT 4
#define WORKQUEUE_MAX_ACTIVE 3
+#define DPA_STATS_US_CNT 0x80000000
+
/* Global dpa_stats component */
struct dpa_stats *gbl_dpa_stats;
@@ -81,6 +83,9 @@ static int get_cnt_traffic_mng_cq_stats(struct dpa_stats_req_cb *req_cb,
static int get_cnt_traffic_mng_ccg_stats(struct dpa_stats_req_cb *req_cb,
struct dpa_stats_cnt_cb *cnt_cb);
+static int get_cnt_us_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 */
@@ -506,8 +511,8 @@ static int init_cnts_resources(struct dpa_stats *dpa_stats)
}
/* Allocate array to store counter ids that are 'in use' */
- dpa_stats->used_cnt_ids = kmalloc(
- config.max_counters * sizeof(uint32_t), GFP_KERNEL);
+ dpa_stats->used_cnt_ids = kcalloc(
+ config.max_counters, sizeof(uint32_t), GFP_KERNEL);
if (!dpa_stats->used_cnt_ids) {
log_err("Cannot allocate memory to store %d \'in use\' counter "
"ids\n", config.max_counters);
@@ -623,10 +628,10 @@ static int init_reqs_resources(struct dpa_stats *dpa_stats)
/* Allocate array to store the counter ids */
for (i = 0; i < DPA_STATS_MAX_NUM_OF_REQUESTS; i++) {
- dpa_stats->reqs_cb[i].config.cnts_ids =
+ dpa_stats->reqs_cb[i].cnts_ids =
kzalloc(DPA_STATS_MAX_NUM_OF_COUNTERS *
sizeof(int), GFP_KERNEL);
- if (!dpa_stats->reqs_cb[i].config.cnts_ids) {
+ if (!dpa_stats->reqs_cb[i].cnts_ids) {
log_err("Cannot allocate memory for array of counter "
"ids\n");
return -ENOMEM;
@@ -664,8 +669,8 @@ static int free_reqs_resources(struct dpa_stats *dpa_stats)
}
/* Release the array of counter ids */
- kfree(req_cb->config.cnts_ids);
- req_cb->config.cnts_ids = NULL;
+ kfree(req_cb->cnts_ids);
+ req_cb->cnts_ids = NULL;
}
}
@@ -725,14 +730,13 @@ static int treat_cnts_request(struct dpa_stats *dpa_stats,
{
struct dpa_stats_cnt_request_params params = req_cb->config;
struct dpa_stats_cnt_cb *cnt_cb = NULL;
- int id = 0, err = 0;
+ int err = 0;
uint32_t i = 0;
for (i = 0; i < params.cnts_ids_len; i++) {
- id = params.cnts_ids[i];
/* Get counter's control block */
- cnt_cb = &dpa_stats->cnts_cb[id];
+ cnt_cb = &dpa_stats->cnts_cb[req_cb->cnts_ids[i]];
/* Acquire counter lock */
mutex_lock(&cnt_cb->lock);
@@ -743,9 +747,9 @@ static int treat_cnts_request(struct dpa_stats *dpa_stats,
err = cnt_cb->f_get_cnt_stats(req_cb, cnt_cb);
if (err < 0) {
log_err("Cannot retrieve the value for counter id %d\n",
- id);
+ req_cb->cnts_ids[i]);
mutex_unlock(&cnt_cb->lock);
- unblock_sched_cnts(dpa_stats, params.cnts_ids,
+ unblock_sched_cnts(dpa_stats, req_cb->cnts_ids,
params.cnts_ids_len);
return err;
}
@@ -760,7 +764,7 @@ static int treat_cnts_request(struct dpa_stats *dpa_stats,
mutex_unlock(&cnt_cb->lock);
}
- unblock_sched_cnts(dpa_stats, params.cnts_ids, params.cnts_ids_len);
+ unblock_sched_cnts(dpa_stats, req_cb->cnts_ids, params.cnts_ids_len);
return 0;
}
@@ -1054,10 +1058,10 @@ 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_BYTES * sizeof(uint64_t);
/* DPA_STATS_CNT_NUM_OF_PACKETS */
dpa_stats->stats_sel[DPA_STATS_CNT_TRAFFIC_MNG][1] =
- DPA_STATS_CNT_NUM_OF_PACKETS;
+ DPA_STATS_CNT_NUM_OF_PACKETS * sizeof(uint64_t);
}
static int copy_key_descriptor(const struct dpa_offload_lookup_key *src,
@@ -1217,6 +1221,39 @@ static void cnt_sel_to_stats(struct stats_info *stats_info,
stats_info->stats_num = cntPos - 1;
}
+static int cnt_gen_sel_to_stats(struct dpa_stats_cnt_cb *cnt_cb,
+ enum dpa_stats_cnt_sel cnt_sel)
+{
+ struct dpa_stats *dpa_stats = cnt_cb->dpa_stats;
+
+ if (cnt_sel == DPA_STATS_CNT_NUM_OF_BYTES) {
+ cnt_cb->info.stats_off[0] =
+ dpa_stats->stats_sel[cnt_cb->type][DPA_STATS_CNT_NUM_OF_BYTES];
+ cnt_cb->info.stats_num = 1;
+ } else if (cnt_sel == DPA_STATS_CNT_NUM_OF_PACKETS) {
+ cnt_cb->info.stats_off[0] =
+ dpa_stats->stats_sel[cnt_cb->type][DPA_STATS_CNT_NUM_OF_PACKETS];
+ cnt_cb->info.stats_num = 1;
+ } else if (cnt_sel == DPA_STATS_CNT_NUM_ALL) {
+ cnt_cb->info.stats_off[0] =
+ dpa_stats->stats_sel[cnt_cb->type][DPA_STATS_CNT_NUM_OF_BYTES];
+ cnt_cb->info.stats_off[1] =
+ dpa_stats->stats_sel[cnt_cb->type][DPA_STATS_CNT_NUM_OF_PACKETS];
+ cnt_cb->info.stats_num = 2;
+ } else {
+ log_err("Parameter cnt_sel %d must be in range (%d - %d) for "
+ "counter id %d\n", cnt_sel, DPA_STATS_CNT_NUM_OF_BYTES,
+ DPA_STATS_CNT_NUM_ALL, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ /* 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;
+}
+
static int set_frag_manip(int td, struct dpa_stats_lookup_key *entry)
{
struct dpa_cls_tbl_action action;
@@ -1665,37 +1702,14 @@ static int set_cnt_ccnode_cb(struct dpa_stats_cnt_cb *cnt_cb,
static int set_cnt_ipsec_cb(struct dpa_stats_cnt_cb *cnt_cb,
const struct dpa_stats_cnt_params *params)
{
- struct dpa_stats *dpa_stats = cnt_cb->dpa_stats;
struct dpa_ipsec_sa_stats stats;
- uint32_t cnt_sel = params->ipsec_params.cnt_sel;
int err = 0;
- if (!dpa_stats) {
+ if (!cnt_cb->dpa_stats) {
log_err("DPA Stats component is not initialized\n");
return -EFAULT;
}
- /* Map IPSec counter selection to statistics */
- if (cnt_sel == DPA_STATS_CNT_NUM_OF_BYTES) {
- cnt_cb->info.stats_off[0] = dpa_stats->stats_sel[
- DPA_STATS_CNT_IPSEC][DPA_STATS_CNT_NUM_OF_BYTES];
- cnt_cb->info.stats_num = 1;
- } else if (cnt_sel == DPA_STATS_CNT_NUM_OF_PACKETS) {
- cnt_cb->info.stats_off[0] = dpa_stats->stats_sel[
- DPA_STATS_CNT_IPSEC][DPA_STATS_CNT_NUM_OF_PACKETS];
- cnt_cb->info.stats_num = 1;
- } else if (cnt_sel == DPA_STATS_CNT_NUM_ALL) {
- cnt_cb->info.stats_off[0] = dpa_stats->stats_sel[
- DPA_STATS_CNT_IPSEC][DPA_STATS_CNT_NUM_OF_BYTES];
- cnt_cb->info.stats_off[1] = dpa_stats->stats_sel[
- DPA_STATS_CNT_IPSEC][DPA_STATS_CNT_NUM_OF_PACKETS];
- cnt_cb->info.stats_num = 2;
- } else {
- log_err("Parameter cnt_sel %d must be in range (%d - %d) for "
- "counter id %d\n", cnt_sel, DPA_STATS_CNT_NUM_OF_BYTES,
- DPA_STATS_CNT_NUM_ALL, cnt_cb->id);
- return -EINVAL;
- }
cnt_cb->ipsec_cb.sa_id[0] = params->ipsec_params.sa_id;
cnt_cb->ipsec_cb.valid[0] = TRUE;
@@ -1709,8 +1723,10 @@ static int set_cnt_ipsec_cb(struct dpa_stats_cnt_cb *cnt_cb,
return -EINVAL;
}
- /* Set number of bytes that will be written by this counter */
- cnt_cb->bytes_num = STATS_VAL_SIZE * cnt_cb->info.stats_num;
+ /* Map IPSec counter selection to statistics */
+ err = cnt_gen_sel_to_stats(cnt_cb, params->ipsec_params.cnt_sel);
+ if (err < 0)
+ return err;
return 0;
}
@@ -1718,41 +1734,50 @@ static int set_cnt_ipsec_cb(struct dpa_stats_cnt_cb *cnt_cb,
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;
u64 frames = 0, bytes = 0;
int err = 0;
+ bool us_cnt = FALSE;
- if (!dpa_stats) {
+ if (!cnt_cb->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;
+ /* Check if this is an users-space counter and if so, reset the flag */
+ if (cnt_sel & DPA_STATS_US_CNT) {
+ us_cnt = TRUE;
+ cnt_sel &= ~DPA_STATS_US_CNT;
+ }
+
+ if (!params->traffic_mng_params.traffic_mng && !us_cnt) {
+ log_err("Parameter traffic_mng handle cannot be NULL for "
+ "counter id %d\n", cnt_cb->id);
+ return -EINVAL;
}
- /* check the counter src */
+ /* Check and store the counter source */
if (cnt_src > DPA_STATS_CNT_TRAFFIC_CG) {
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;
}
-
- /* check the counter selection */
- if (cnt_sel > DPA_STATS_CNT_NUM_ALL) {
- log_err("Parameter cnt_sel %d must be in range (%d - %d) for "
- "counter id %d\n", cnt_sel, DPA_STATS_CNT_NUM_OF_BYTES,
- 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;
+ /* Map Traffic Manager counter selection to statistics */
+ err = cnt_gen_sel_to_stats(cnt_cb, cnt_sel);
+ if (err < 0)
+ return err;
+
+ /* For user-space counters there is a different retrieve function */
+ if (us_cnt) {
+ cnt_cb->f_get_cnt_stats = get_cnt_us_stats;
+ return 0;
+ }
+
/* Check the counter source and the Traffic Manager object */
switch (cnt_src) {
case DPA_STATS_CNT_TRAFFIC_CLASS:
@@ -1777,22 +1802,8 @@ static int set_cnt_traffic_mng_cb(struct dpa_stats_cnt_cb *cnt_cb,
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;
}
- /* Set number of statistics that will be written by this counter */
- if (cnt_sel == DPA_STATS_CNT_NUM_ALL)
- cnt_cb->info.stats_num = 2;
- else
- cnt_cb->info.stats_num = 1;
-
- /* 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;
}
@@ -2438,92 +2449,85 @@ static int set_cls_cnt_ipsec_cb(struct dpa_stats_cnt_cb *cnt_cb,
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;
+ struct dpa_stats_cls_cnt_traffic_mng prm = params->traffic_mng_params;
+ uint32_t cnt_sel = prm.cnt_sel, i;
u64 frames = 0, bytes = 0;
int err = 0;
+ bool us_cnt = FALSE;
- if (!dpa_stats) {
+ if (!cnt_cb->dpa_stats) {
log_err("DPA Stats component is not initialized\n");
return -EFAULT;
}
- /* check the counter selection */
- if (cnt_sel > DPA_STATS_CNT_NUM_ALL) {
- log_err("Parameter cnt_sel %d must be in range (%d - %d) for "
- "counter id %d\n", cnt_sel, DPA_STATS_CNT_NUM_OF_BYTES,
- DPA_STATS_CNT_NUM_ALL, cnt_cb->id);
- return -EINVAL;
+ /* Check if this is an users-space counter and if so, reset the flag */
+ if (cnt_sel & DPA_STATS_US_CNT) {
+ us_cnt = TRUE;
+ cnt_sel &= ~DPA_STATS_US_CNT;
}
cnt_cb->members_num = params->class_members;
- /* check the counter src and set the get function */
- switch (cnt_src) {
+ /* Map Traffic Manager counter selection to statistics */
+ err = cnt_gen_sel_to_stats(cnt_cb, cnt_sel);
+ if (err < 0)
+ return err;
+
+ /* For user-space counters there is a different retrieve function */
+ if (us_cnt) {
+ cnt_cb->f_get_cnt_stats = get_cnt_us_stats;
+ return 0;
+ }
+
+ /* Check the counter source and the Traffic Manager object */
+ switch (prm.src) {
case DPA_STATS_CNT_TRAFFIC_CLASS:
cnt_cb->f_get_cnt_stats = get_cnt_traffic_mng_cq_stats;
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);
+ if (!prm.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];
- /* Check the user provided Traffic Manager object */
+
+ /* Check the provided Traffic Manager object */
err = qman_ceetm_cq_get_dequeue_statistics(
- cnt_cb->gen_cb.objs[i], 0, &frames,
- &bytes);
+ prm.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);
+ log_err("Invalid traffic_mng handle for counter"
+ " id %d\n", cnt_cb->id);
return -EINVAL;
}
+ cnt_cb->gen_cb.objs[i] = prm.traffic_mng[i];
}
break;
-
case DPA_STATS_CNT_TRAFFIC_CG:
cnt_cb->f_get_cnt_stats = get_cnt_traffic_mng_ccg_stats;
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);
+ if (!prm.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];
- /* Check the user provided Traffic Manager object */
+
+ /* Check the provided Traffic Manager object */
err = qman_ceetm_ccg_get_reject_statistics(
- cnt_cb->gen_cb.objs[i], 0, &frames,
- &bytes);
+ prm.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);
+ log_err("Invalid traffic_mng handle for counter"
+ " id %d\n", cnt_cb->id);
return -EINVAL;
}
+ cnt_cb->gen_cb.objs[i] = prm.traffic_mng[i];
}
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,
+ "counter id %d\n", prm.src, DPA_STATS_CNT_TRAFFIC_CLASS,
DPA_STATS_CNT_TRAFFIC_CG, cnt_cb->id);
return -EINVAL;
}
- /* Set number of statistics that will be written by this counter */
- if (cnt_sel == DPA_STATS_CNT_NUM_ALL)
- cnt_cb->info.stats_num = 2;
- else
- cnt_cb->info.stats_num = 1;
-
- /* 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;
}
@@ -3167,6 +3171,23 @@ static int get_cnt_traffic_mng_ccg_stats(struct dpa_stats_req_cb *req_cb,
return 0;
}
+static int get_cnt_us_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb)
+{
+ uint32_t i = 0, j = 0;
+ req_cb->config.cnts_ids[cnt_cb->id] = req_cb->bytes_num;
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ for (j = 0; j < cnt_cb->info.stats_num; j++) {
+ /* Write the memory location */
+ *(uint32_t *)(req_cb->request_area) = 0;
+ /* Update the memory pointer */
+ req_cb->request_area += STATS_VAL_SIZE;
+ }
+ }
+ return 0;
+}
+
static void async_req_work_func(struct work_struct *work)
{
struct dpa_stats_req_cb *req_cb = NULL;
@@ -3847,15 +3868,16 @@ int dpa_stats_get_counters(struct dpa_stats_cnt_request_params params,
return err;
}
- /* Store user-provided request parameters */
- memcpy(req_cb->config.cnts_ids,
- params.cnts_ids, params.cnts_ids_len * sizeof(int));
-
+ req_cb->config.cnts_ids = params.cnts_ids;
req_cb->config.reset_cnts = params.reset_cnts;
req_cb->config.storage_area_offset = params.storage_area_offset;
req_cb->config.cnts_ids_len = params.cnts_ids_len;
req_cb->request_done = request_done;
+ /* Copy user-provided array of counter ids */
+ memcpy(req_cb->cnts_ids,
+ params.cnts_ids, params.cnts_ids_len * sizeof(int));
+
/* Set memory area where the request should write */
req_cb->request_area = dpa_stats->config.storage_area +
params.storage_area_offset;
diff --git a/drivers/staging/fsl_dpa_offload/dpa_stats.h b/drivers/staging/fsl_dpa_offload/dpa_stats.h
index 5843dca..3d682af 100644
--- a/drivers/staging/fsl_dpa_offload/dpa_stats.h
+++ b/drivers/staging/fsl_dpa_offload/dpa_stats.h
@@ -78,6 +78,7 @@ struct dpa_stats_req_cb {
struct work_struct async_req_work; /* Asynchronous request work */
struct dpa_stats_cnt_request_params config;
/* Parameters provided to the request */
+ int *cnts_ids; /* Copy of user-provided array of counter IDs */
uint32_t id; /* Request id */
int index; /* Request index in the 'used_req_ids'*/
void *request_area;
diff --git a/drivers/staging/fsl_dpa_offload/dpa_stats_ioctl.h b/drivers/staging/fsl_dpa_offload/dpa_stats_ioctl.h
index d375a0f..a1bd323 100644
--- a/drivers/staging/fsl_dpa_offload/dpa_stats_ioctl.h
+++ b/drivers/staging/fsl_dpa_offload/dpa_stats_ioctl.h
@@ -240,11 +240,13 @@ struct compat_ioc_dpa_stats_cnts_reset_params {
};
struct compat_dpa_stats_event_params {
- int dpa_stats_id;
- unsigned int storage_area_offset;
- unsigned int cnts_written;
- int bytes_written;
- compat_uptr_t request_done;
+ int dpa_stats_id;
+ unsigned int storage_area_offset;
+ unsigned int cnts_written;
+ int bytes_written;
+ compat_uptr_t us_cnt_ids;
+ unsigned int cnt_ids_len;
+ compat_uptr_t request_done;
};
#endif
#define DPA_STATS_IOC_MAGIC 0xde
diff --git a/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.c b/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.c
index 0fdcdc5..b7fdf18 100644
--- a/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.c
+++ b/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.c
@@ -98,7 +98,8 @@ static int copy_pair_descriptor(struct dpa_offload_lookup_key_pair *src,
static int copy_class_members(void *objs, unsigned int size, void *dst);
static long store_get_cnts_async_params(
- struct ioc_dpa_stats_cnt_request_params *kprm);
+ struct ioc_dpa_stats_cnt_request_params *kprm,
+ struct dpa_stats_async_req_ev **async_request_event);
#ifdef CONFIG_COMPAT
static long wrp_dpa_stats_do_compat_ioctl(struct file *filp,
@@ -289,6 +290,15 @@ ssize_t wrp_dpa_stats_read(struct file *file,
ev_prm.dpa_stats_id = event->params.dpa_stats_id;
ev_prm.storage_area_offset = event->params.storage_area_offset;
ev_prm.request_done = ptr_to_compat(event->params.request_done);
+ ev_prm.us_cnt_ids = event->params.us_cnt_ids;
+ ev_prm.cnt_ids_len = event->params.cnt_ids_len;
+
+ if (copy_to_user((compat_ptr)(ev_prm.us_cnt_ids),
+ event->ks_cnt_ids,
+ (event->params.cnt_ids_len * sizeof(int)))) {
+ kfree(event);
+ return -EFAULT;
+ }
if (copy_to_user(buf + c, &ev_prm, sizeof(ev_prm)) != 0) {
kfree(event);
@@ -498,6 +508,15 @@ void do_ioctl_req_done_cb(int dpa_stats_id,
event->params.cnts_written = cnts_written;
event->params.bytes_written = bytes_written;
event->params.request_done = async_req_ev->request_done;
+#ifdef CONFIG_COMPAT
+ event->ks_cnt_ids = async_req_ev->ks_cnt_ids;
+ event->params.us_cnt_ids = async_req_ev->us_cnt_ids;
+ event->params.cnt_ids_len = async_req_ev->cnt_ids_len;
+#else
+ event->ks_cnt_ids = NULL;
+ event->params.us_cnt_ids = NULL;
+ event->params.cnt_ids_len = 0;
+#endif /* CONFIG_COMPAT */
mutex_unlock(&wrp_dpa_stats.async_req_lock);
@@ -755,9 +774,10 @@ static int do_ioctl_stats_compat_create_counter(void *args)
sizeof(struct dpa_stats_cnt_ipsec));
break;
case DPA_STATS_CNT_TRAFFIC_MNG:
- memcpy(&kprm.cnt_params.traffic_mng_params,
- &uprm.cnt_params.traffic_mng_params,
- sizeof(struct dpa_stats_cnt_traffic_mng));
+ kprm.cnt_params.traffic_mng_params.cnt_sel =
+ uprm.cnt_params.traffic_mng_params.cnt_sel;
+ kprm.cnt_params.traffic_mng_params.src =
+ uprm.cnt_params.traffic_mng_params.src;
break;
default:
break;
@@ -1107,6 +1127,12 @@ static int do_ioctl_stats_compat_create_class_counter(void *args)
if (ret < 0)
return ret;
break;
+ case DPA_STATS_CNT_TRAFFIC_MNG:
+ kprm_cls->traffic_mng_params.cnt_sel =
+ uprm_cls->traffic_mng_params.cnt_sel;
+ kprm_cls->traffic_mng_params.src =
+ uprm_cls->traffic_mng_params.src;
+ break;
default:
break;
}
@@ -1428,7 +1454,7 @@ static int do_ioctl_stats_get_counters(void *args)
/* If counters request is asynchronous */
if (prm.request_done) {
- ret = store_get_cnts_async_params(&prm);
+ ret = store_get_cnts_async_params(&prm, NULL);
if (ret < 0)
return ret;
}
@@ -1440,9 +1466,6 @@ static int do_ioctl_stats_get_counters(void *args)
return ret;
}
- /* Request was sent, release the array of counter ids */
- kfree(prm.req_params.cnts_ids);
-
/* If request is synchronous copy counters length to user space */
if (!prm.request_done) {
if (wrp_dpa_stats.k_mem)
@@ -1462,6 +1485,9 @@ static int do_ioctl_stats_get_counters(void *args)
}
}
+ /* Request was sent, release the array of counter ids */
+ kfree(prm.req_params.cnts_ids);
+
return ret;
}
@@ -1507,9 +1533,14 @@ static int do_ioctl_stats_compat_get_counters(void *args)
/* If counters request is asynchronous */
if (kprm.request_done) {
- ret = store_get_cnts_async_params(&kprm);
+ struct dpa_stats_async_req_ev *async_request_ev = NULL;
+
+ ret = store_get_cnts_async_params(&kprm, &async_request_ev);
if (ret < 0)
return ret;
+ /* Store user-space pointer to array of ids */
+ async_request_ev->us_cnt_ids = uprm.req_params.cnts_ids;
+ async_request_ev->cnt_ids_len = uprm.req_params.cnts_ids_len;
}
ret = dpa_stats_get_counters(kprm.req_params,
@@ -1519,9 +1550,6 @@ static int do_ioctl_stats_compat_get_counters(void *args)
return ret;
}
- /* Request was sent, release the array of counter ids */
- kfree(kprm.req_params.cnts_ids);
-
/* If request is synchronous copy counters length to user space */
if (!kprm.request_done) {
if (wrp_dpa_stats.k_mem)
@@ -1532,16 +1560,28 @@ static int do_ioctl_stats_compat_get_counters(void *args)
kprm.cnts_len)) {
log_err("Cannot copy counter values to storage "
"area\n");
+ kfree(kprm.req_params.cnts_ids);
return -EINVAL;
}
uprm.cnts_len = kprm.cnts_len;
+ if (copy_to_user((compat_ptr)(uprm.req_params.cnts_ids),
+ kprm.req_params.cnts_ids,
+ (kprm.req_params.cnts_ids_len * sizeof(int)))) {
+ log_err("Cannot copy to user the array of requested "
+ "counter ids\n");
+ kfree(kprm.req_params.cnts_ids);
+ return -EINVAL;
+ }
+
if (copy_to_user(args, &uprm, sizeof(uprm))) {
log_err("Cannot copy to user the counter parameters\n");
ret = -EINVAL;
}
}
+ /* Request was sent, release the array of counter ids */
+ kfree(kprm.req_params.cnts_ids);
return ret;
}
@@ -1559,7 +1599,7 @@ static int do_ioctl_stats_reset_counters(void *args)
}
/* Allocate kernel-space memory area to copy the counters ids */
- cnt_ids = kzalloc(prm.cnts_ids_len * sizeof(int), GFP_KERNEL);
+ cnt_ids = kcalloc(prm.cnts_ids_len, sizeof(int), GFP_KERNEL);
if (!cnt_ids) {
log_err("Cannot allocate memory for counter ids array\n");
return -ENOMEM;
@@ -1608,7 +1648,7 @@ static int do_ioctl_stats_compat_reset_counters(void *args)
kprm.cnts_ids_len = uprm.cnts_ids_len;
/* Allocate kernel-space memory area to copy the counters ids */
- kprm.cnts_ids = kzalloc(kprm.cnts_ids_len * sizeof(int), GFP_KERNEL);
+ kprm.cnts_ids = kcalloc(kprm.cnts_ids_len, sizeof(int), GFP_KERNEL);
if (!kprm.cnts_ids) {
log_err("Cannot allocate memory for counter ids array\n");
return -ENOMEM;
@@ -1807,7 +1847,8 @@ static long wrp_dpa_stats_do_compat_ioctl(struct file *filp,
#endif
static long store_get_cnts_async_params(
- struct ioc_dpa_stats_cnt_request_params *kprm)
+ struct ioc_dpa_stats_cnt_request_params *kprm,
+ struct dpa_stats_async_req_ev **async_request_event)
{
struct dpa_stats_async_req_ev *async_req_ev;
struct list_head *async_req_grp;
@@ -1835,11 +1876,17 @@ static long store_get_cnts_async_params(
async_req_ev->request_done = kprm->request_done;
async_req_ev->storage_area_offset =
kprm->req_params.storage_area_offset;
+
+ async_req_ev->ks_cnt_ids = kprm->req_params.cnts_ids;
list_add_tail(&async_req_ev->node, async_req_grp);
mutex_unlock(&wrp_dpa_stats.async_req_lock);
/* Replace the application callback with wrapper function */
kprm->request_done = do_ioctl_req_done_cb;
+
+ /* If calling function requested, return the pointer to async_req_ev */
+ if (async_request_event)
+ *async_request_event = async_req_ev;
return 0;
}
@@ -2041,7 +2088,7 @@ static int copy_pair_descriptor_compatcpy(
static int copy_class_members(void *objs, unsigned int size, void *dst)
{
/* Allocate memory to store the array of objects */
- objs = kmalloc(size * sizeof(void *), GFP_KERNEL);
+ objs = kcalloc(size, sizeof(void *), GFP_KERNEL);
if (!objs) {
log_err("Cannot allocate memory for objects array\n");
return -ENOMEM;
@@ -2445,7 +2492,7 @@ static long dpa_stats_ipsec_cls_compatcpy(struct dpa_stats_cls_cnt_ipsec *kprm,
kprm->cnt_sel = uprm->cnt_sel;
/* Allocate memory to store the sa ids array */
- kprm->sa_id = kmalloc(cls_members * sizeof(int), GFP_KERNEL);
+ kprm->sa_id = kcalloc(cls_members, sizeof(int), GFP_KERNEL);
if (!kprm->sa_id) {
log_err("Cannot allocate memory for SA ids array\n");
return -ENOMEM;
diff --git a/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.h b/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.h
index ef91344..506b02c 100644
--- a/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.h
+++ b/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.h
@@ -36,6 +36,7 @@
/* Other includes */
#include "linux/fs.h"
#include <linux/fsl_dpa_stats.h>
+#include <linux/compat.h>
#define DPA_STATS_CDEV "dpa_stats"
@@ -61,11 +62,17 @@ long wrp_dpa_stats_compat_ioctl(struct file *filp, unsigned int cmd,
#define QUEUE_MAX_EVENTS 2048
struct dpa_stats_event_params {
- int dpa_stats_id;
- unsigned int storage_area_offset;
- unsigned int cnts_written;
- int bytes_written;
- dpa_stats_request_cb request_done;
+ int dpa_stats_id;
+ unsigned int storage_area_offset;
+ unsigned int cnts_written;
+ int bytes_written;
+#ifdef CONFIG_COMPAT
+ compat_uptr_t us_cnt_ids;
+#else
+ int *us_cnt_ids;
+#endif /* CONFIG_COMPAT */
+ unsigned int cnt_ids_len;
+ dpa_stats_request_cb request_done;
};
struct dpa_stats_event_queue {
@@ -77,6 +84,7 @@ struct dpa_stats_event_queue {
struct dpa_stats_event {
struct dpa_stats_event_params params; /* Event data */
struct list_head lh; /* Event queue list head */
+ int *ks_cnt_ids; /* Request array of counter ids from kernel-space */
};
struct dpa_stats_async_req_ev {
@@ -84,6 +92,11 @@ struct dpa_stats_async_req_ev {
unsigned int storage_area_offset; /* Storage offset for this request */
/* Pointers to other async requests in the current set */
struct list_head node;
+#ifdef CONFIG_COMPAT
+ compat_uptr_t us_cnt_ids; /* Request array of counter ids from US */
+#endif /* CONFIG COMPAT */
+ int *ks_cnt_ids; /* Request array of counter ids from KS */
+ unsigned int cnt_ids_len; /* Number of counter ids in array */
};
struct wrp_dpa_stats_cb {