summaryrefslogtreecommitdiff
path: root/drivers/staging/fsl_dpa_offload
diff options
context:
space:
mode:
authorAnca Jeanina FLOAREA <anca.floarea@freescale.com>2013-08-02 11:56:08 (GMT)
committerSchmitt Richard-B43082 <B43082@freescale.com>2013-08-08 20:29:58 (GMT)
commitaf2dcedf4b69a94ed42689be537d3f66e3bb2cbd (patch)
tree65ee71fdb6eb6be5e85bfa1ff10712b758a85fe6 /drivers/staging/fsl_dpa_offload
parent56fefd712b54327e340ece05a7f115a1d5af5fff (diff)
downloadlinux-fsl-qoriq-af2dcedf4b69a94ed42689be537d3f66e3bb2cbd.tar.xz
dpa_offload: Add support in DPA Stats for miss statistics
Added support in DPA Stats to retrieve the statistics for the miss-entry of either a Classification Node or a Classification Table. The user can request statistics for miss-entry by providing the key set to NULL. The Classification counter API was changed in order to allow the user to provide NULL instead of a valid key. Signed-off-by: Anca Jeanina FLOAREA <anca.floarea@freescale.com> Change-Id: Id871766e5cc7b494c934096829e12af15ded7544 Reviewed-on: http://git.am.freescale.net:8181/3830 Reviewed-by: Zanoschi Aurelian-B43522 <Aurelian.Zanoschi@freescale.com> Reviewed-by: Chereji Marian-Cornel-R27762 <marian.chereji@freescale.com> Reviewed-by: Schmitt Richard-B43082 <B43082@freescale.com> Tested-by: Schmitt Richard-B43082 <B43082@freescale.com>
Diffstat (limited to 'drivers/staging/fsl_dpa_offload')
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_stats.c563
-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.c950
4 files changed, 1023 insertions, 503 deletions
diff --git a/drivers/staging/fsl_dpa_offload/dpa_stats.c b/drivers/staging/fsl_dpa_offload/dpa_stats.c
index b911732..f82fcc3 100644
--- a/drivers/staging/fsl_dpa_offload/dpa_stats.c
+++ b/drivers/staging/fsl_dpa_offload/dpa_stats.c
@@ -114,6 +114,46 @@ static int check_dpa_stats_params(const struct dpa_stats_params *params)
return 0;
}
+static int set_cnt_classif_tbl_retrieve_func(struct dpa_stats_cnt_cb *cnt_cb)
+{
+ switch (cnt_cb->tbl_cb.type) {
+ case DPA_CLS_TBL_HASH:
+ cnt_cb->f_get_cnt_stats = get_cnt_cls_tbl_hash_stats;
+ break;
+ case DPA_CLS_TBL_INDEXED:
+ cnt_cb->f_get_cnt_stats = get_cnt_cls_tbl_index_stats;
+ break;
+ case DPA_CLS_TBL_EXACT_MATCH:
+ cnt_cb->f_get_cnt_stats = get_cnt_cls_tbl_match_stats;
+ break;
+ default:
+ log_err("Unsupported DPA Classifier table type %d\n",
+ cnt_cb->tbl_cb.type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int set_cnt_classif_node_retrieve_func(struct dpa_stats_cnt_cb *cnt_cb,
+ enum dpa_stats_classif_node_type ccnode_type)
+{
+ switch (ccnode_type) {
+ case DPA_CLS_TBL_HASH:
+ cnt_cb->f_get_cnt_stats = get_cnt_ccnode_hash_stats;
+ break;
+ case DPA_CLS_TBL_INDEXED:
+ cnt_cb->f_get_cnt_stats = get_cnt_ccnode_index_stats;
+ break;
+ case DPA_CLS_TBL_EXACT_MATCH:
+ cnt_cb->f_get_cnt_stats = get_cnt_ccnode_match_stats;
+ break;
+ default:
+ log_err("Unsupported Classification Node type %d", ccnode_type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
static int check_tbl_cls_counter(struct dpa_stats_cnt_cb *cnt_cb,
struct dpa_stats_lookup_key *entry)
{
@@ -132,7 +172,6 @@ static int check_tbl_cls_counter(struct dpa_stats_cnt_cb *cnt_cb,
dump_lookup_key(&entry->key);
return -EIO;
}
- cnt_cb->f_get_cnt_stats = get_cnt_cls_tbl_hash_stats;
break;
case DPA_CLS_TBL_INDEXED:
err = FM_PCD_MatchTableGetKeyStatistics(
@@ -145,7 +184,6 @@ static int check_tbl_cls_counter(struct dpa_stats_cnt_cb *cnt_cb,
dump_lookup_key(&entry->key);
return -EIO;
}
- cnt_cb->f_get_cnt_stats = get_cnt_cls_tbl_index_stats;
break;
case DPA_CLS_TBL_EXACT_MATCH:
err = FM_PCD_MatchTableFindNGetKeyStatistics(entry->cc_node,
@@ -159,7 +197,6 @@ static int check_tbl_cls_counter(struct dpa_stats_cnt_cb *cnt_cb,
dump_lookup_key(&entry->key);
return -EINVAL;
}
- cnt_cb->f_get_cnt_stats = get_cnt_cls_tbl_match_stats;
break;
default:
log_err("Unsupported DPA Classifier table type %d\n",
@@ -189,7 +226,6 @@ static int check_ccnode_counter(struct dpa_stats_cnt_cb *cnt_cb,
dump_lookup_key(key);
return -EIO;
}
- cnt_cb->f_get_cnt_stats = get_cnt_ccnode_hash_stats;
break;
case DPA_STATS_CLASSIF_NODE_INDEXED:
err = FM_PCD_MatchTableGetKeyStatistics(
@@ -203,7 +239,6 @@ static int check_ccnode_counter(struct dpa_stats_cnt_cb *cnt_cb,
dump_lookup_key(key);
return -EIO;
}
- cnt_cb->f_get_cnt_stats = get_cnt_ccnode_index_stats;
break;
case DPA_STATS_CLASSIF_NODE_EXACT_MATCH:
err = FM_PCD_MatchTableFindNGetKeyStatistics(
@@ -217,7 +252,6 @@ static int check_ccnode_counter(struct dpa_stats_cnt_cb *cnt_cb,
dump_lookup_key(key);
return -EINVAL;
}
- cnt_cb->f_get_cnt_stats = get_cnt_ccnode_match_stats;
break;
default:
log_err("Unsupported Classification Node type %d",
@@ -227,6 +261,47 @@ static int check_ccnode_counter(struct dpa_stats_cnt_cb *cnt_cb,
return 0;
}
+static int check_ccnode_miss_counter(void *cc_node, uint32_t id,
+ enum dpa_stats_classif_node_type ccnode_type)
+{
+ t_FmPcdCcKeyStatistics stats;
+ int err;
+
+ switch (ccnode_type) {
+ case DPA_STATS_CLASSIF_NODE_HASH:
+ err = FM_PCD_HashTableGetMissStatistics(cc_node, &stats);
+ if (err != 0) {
+ log_err("Check failed for Classification Node counter "
+ "id %d due to incorrect parameters: handle="
+ "0x%p\n", id, cc_node);
+ return -EIO;
+ }
+ break;
+ case DPA_STATS_CLASSIF_NODE_INDEXED:
+ err = FM_PCD_MatchTableGetMissStatistics(cc_node, &stats);
+ if (err != 0) {
+ log_err("Check failed for Classification Node counter "
+ "id %d due to incorrect parameters: handle=0x%p"
+ "\n", id, cc_node);
+ return -EIO;
+ }
+ break;
+ case DPA_STATS_CLASSIF_NODE_EXACT_MATCH:
+ err = FM_PCD_MatchTableGetMissStatistics(cc_node, &stats);
+ if (err != 0) {
+ log_err("Check failed for Classification Node counter "
+ "id %d due to incorrect parameters: handle=0x%p"
+ "\n", id, cc_node);
+ return -EINVAL;
+ }
+ break;
+ default:
+ log_err("Unsupported Classification Node type %d", ccnode_type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
static int get_new_cnt(struct dpa_stats *dpa_stats,
struct dpa_stats_cnt_cb **cnt_cb)
{
@@ -344,8 +419,7 @@ static int put_cnt(struct dpa_stats *dpa_stats, struct dpa_stats_cnt_cb *cnt_cb)
}
/* Mark the Counter id as 'not used' */
- dpa_stats->used_cnt_ids[cnt_cb->index] =
- DPA_OFFLD_INVALID_OBJECT_ID;
+ dpa_stats->used_cnt_ids[cnt_cb->index] = DPA_OFFLD_INVALID_OBJECT_ID;
/* Clear all 'cnt_cb' information */
cnt_cb->index = DPA_OFFLD_INVALID_OBJECT_ID;
@@ -627,7 +701,7 @@ static int free_resources(void)
/* Sanity check */
if (!gbl_dpa_stats) {
log_err("DPA Stats component is not initialized\n");
- return;
+ return 0;
}
dpa_stats = gbl_dpa_stats;
@@ -1149,11 +1223,20 @@ static int set_frag_manip(int td, struct dpa_stats_lookup_key *entry)
struct t_FmPcdManipStats stats;
int err = 0;
- err = dpa_classif_table_lookup_by_key(td, &entry->key, &action);
- if (err != 0) {
- log_err("Cannot retrieve next action parameters from table "
- "%d\n", td);
- return -EINVAL;
+ if (entry->miss_key) {
+ err = dpa_classif_get_miss_action(td, &action);
+ if (err != 0) {
+ log_err("Cannot retrieve miss action parameters from "
+ "table %d\n", td);
+ return -EINVAL;
+ }
+ } else {
+ err = dpa_classif_table_lookup_by_key(td, &entry->key, &action);
+ if (err != 0) {
+ log_err("Cannot retrieve next action parameters from "
+ "table %d\n", td);
+ return -EINVAL;
+ }
}
if (action.type != DPA_CLS_TBL_ACTION_ENQ) {
@@ -1175,7 +1258,6 @@ static int set_frag_manip(int td, struct dpa_stats_lookup_key *entry)
log_err("Invalid Fragmentation manip handle\n");
return -EINVAL;
}
-
return 0;
}
@@ -1447,13 +1529,6 @@ static int set_cnt_classif_tbl_cb(struct dpa_stats_cnt_cb *cnt_cb,
return -EINVAL;
}
- /* Copy the key descriptor */
- err = copy_key_descriptor(&prm.key, &cnt_tbl_cb->keys[0].key);
- if (err != 0) {
- log_err("Cannot copy key descriptor from user parameters\n");
- return -EINVAL;
- }
-
/* Store CcNode handle and set number of keys to one */
cnt_tbl_cb->keys[0].cc_node = cls_tbl.cc_node;
cnt_tbl_cb->keys[0].valid = TRUE;
@@ -1462,11 +1537,35 @@ static int set_cnt_classif_tbl_cb(struct dpa_stats_cnt_cb *cnt_cb,
/* Store DPA Classifier Table type */
cnt_tbl_cb->type = cls_tbl.type;
- /* Check the Classifier Table counter */
- err = check_tbl_cls_counter(cnt_cb, &cnt_tbl_cb->keys[0]);
+ /* Set retrieve function depending on table type */
+ err = set_cnt_classif_tbl_retrieve_func(cnt_cb);
if (err != 0)
return -EINVAL;
+ /* Determine if counter is for 'miss' entry or for a valid key */
+ if (!prm.key) {
+ cnt_tbl_cb->keys[0].miss_key = TRUE;
+
+ /* Check the Classifier Table counter parameters for "miss" */
+ err = check_ccnode_miss_counter(cnt_tbl_cb->keys[0].cc_node,
+ cnt_cb->id, cnt_tbl_cb->type);
+ if (err != 0)
+ return -EINVAL;
+ } else {
+ /* Copy the key descriptor */
+ err = copy_key_descriptor(prm.key, &cnt_tbl_cb->keys[0].key);
+ if (err != 0) {
+ log_err("Cannot copy key descriptor from user "
+ "parameters\n");
+ return -EINVAL;
+ }
+
+ /* Check the Classifier Table counter */
+ err = check_tbl_cls_counter(cnt_cb, &cnt_tbl_cb->keys[0]);
+ if (err != 0)
+ return -EINVAL;
+ }
+
if (frag_stats) {
err = set_frag_manip(prm.td, &cnt_tbl_cb->keys[0]);
if (err < 0) {
@@ -1518,23 +1617,40 @@ static int set_cnt_ccnode_cb(struct dpa_stats_cnt_cb *cnt_cb,
return -EFAULT;
}
- /* Copy the key descriptor */
- err = copy_key_descriptor(&prm.key, &cnt_cb->ccnode_cb.keys[0]);
- if (err != 0) {
- log_err("Cannot copy key descriptor from user parameters\n");
- return -EINVAL;
- }
-
/* Store CcNode handle and set number of keys to one */
cnt_cb->ccnode_cb.cc_node = prm.cc_node;
cnt_cb->members_num = 1;
- /* Check the Classifier Node counter parameters */
- err = check_ccnode_counter(cnt_cb,
- prm.ccnode_type, &cnt_cb->ccnode_cb.keys[0]);
+ /* Set retrieve function depending on counter type */
+ err = set_cnt_classif_node_retrieve_func(cnt_cb, prm.ccnode_type);
if (err != 0)
return -EINVAL;
+ if (!params->classif_node_params.key) {
+ /* Set the key byte to NULL, to mark it for 'miss' entry */
+ cnt_cb->ccnode_cb.keys[0].byte = NULL;
+
+ /* Check the Classifier Node counter parameters for 'miss' */
+ err = check_ccnode_miss_counter(cnt_cb->ccnode_cb.cc_node,
+ cnt_cb->id, prm.ccnode_type);
+ if (err != 0)
+ return -EINVAL;
+ } else {
+ /* Copy the key descriptor */
+ err = copy_key_descriptor(prm.key, &cnt_cb->ccnode_cb.keys[0]);
+ if (err != 0) {
+ log_err("Cannot copy key descriptor from user "
+ "parameters\n");
+ return -EINVAL;
+ }
+
+ /* Check the Classifier Node counter parameters */
+ err = check_ccnode_counter(cnt_cb, prm.ccnode_type,
+ &cnt_cb->ccnode_cb.keys[0]);
+ if (err != 0)
+ return -EINVAL;
+ }
+
/* Map Classif Node counter selection to CcNode statistics */
cnt_sel_to_stats(&cnt_cb->info,
dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE],
@@ -1899,36 +2015,49 @@ static int set_cls_cnt_plcr_cb(struct dpa_stats_cnt_cb *cnt_cb,
}
static int set_cls_cnt_classif_tbl_pair(
- struct dpa_stats_cnt_classif_tbl_cb *cnt_tbl_cb, int td,
+ struct dpa_stats_cnt_cb *cnt_cb, int td,
const struct dpa_offload_lookup_key_pair *pair,
struct dpa_stats_lookup_key *lookup_key)
{
+ struct dpa_stats_cnt_classif_tbl_cb *cnt_tbl_cb = &cnt_cb->tbl_cb;
struct dpa_cls_tbl_params cls_tbl;
struct dpa_offload_lookup_key tbl_key;
struct dpa_cls_tbl_action action;
int err = 0;
- /* Check that key byte is not NULL */
- if (!pair->first_key.byte) {
- log_err("First key descriptor byte of the user pair cannot be "
- "NULL for table descriptor %d\n", td);
- return -EFAULT;
- }
+ /* If either the entire 'pair' or the first key is NULL, then retrieve
+ * the action associated with the 'miss action '*/
+ if ((!pair) || (pair && !pair->first_key)) {
+ err = dpa_classif_get_miss_action(td, &action);
+ if (err != 0) {
+ log_err("Cannot retrieve miss action parameters for "
+ "table descriptor %d\n", td);
+ return -EINVAL;
+ }
+ } else {
+ /* Check that key byte is not NULL */
+ if (!pair->first_key->byte) {
+ log_err("First key descriptor byte of the user pair "
+ "cannot be NULL for table descriptor %d\n", td);
+ return -EFAULT;
+ }
- /* Copy first key descriptor parameters*/
- err = copy_key_descriptor(&pair->first_key, &tbl_key);
- if (err != 0) {
- log_err("Cannot copy first key descriptor of the user pair\n");
- return -EINVAL;
- }
+ /* Copy first key descriptor parameters*/
+ err = copy_key_descriptor(pair->first_key, &tbl_key);
+ if (err != 0) {
+ log_err("Cannot copy second key descriptor of "
+ "the user pair\n");
+ return -EINVAL;
+ }
- /* Use the first key of the pair to lookup in the classifier
- * table the next table connected on a "next-action" */
- err = dpa_classif_table_lookup_by_key(td, &tbl_key, &action);
- if (err != 0) {
- log_err("Cannot retrieve next action parameters for table "
- "descriptor %d\n", td);
- return -EINVAL;
+ /* Use the first key of the pair to lookup in the classifier
+ * table the next table connected on a "next-action" */
+ err = dpa_classif_table_lookup_by_key(td, &tbl_key, &action);
+ if (err != 0) {
+ log_err("Cannot retrieve next action parameters for "
+ "table descriptor %d\n", td);
+ return -EINVAL;
+ }
}
if (action.type != DPA_CLS_TBL_ACTION_NEXT_TABLE) {
@@ -1948,23 +2077,41 @@ static int set_cls_cnt_classif_tbl_pair(
/* Store DPA Classifier Table type */
cnt_tbl_cb->type = cls_tbl.type;
+ /* Set retrieve function depending on table type */
+ set_cnt_classif_tbl_retrieve_func(cnt_cb);
+
/* Store CcNode handle */
lookup_key->cc_node = cls_tbl.cc_node;
- /* Set as lookup key the second key descriptor from the pair */
- err = copy_key_descriptor(&pair->second_key, &lookup_key->key);
- if (err != 0) {
- log_err("Cannot copy second key descriptor of the user pair\n");
- return -EINVAL;
+ if (!pair || (pair && !pair->second_key)) {
+ /* Set as the key as "for miss" */
+ lookup_key->miss_key = TRUE;
+
+ /* Check the Classifier Table counter parameters for "miss" */
+ err = check_ccnode_miss_counter(lookup_key->cc_node,
+ cnt_cb->id, cnt_tbl_cb->type);
+ } else {
+ lookup_key->miss_key = FALSE;
+
+ /* Set as lookup key the second key descriptor from the pair */
+ err = copy_key_descriptor(pair->second_key, &lookup_key->key);
+ if (err != 0) {
+ log_err("Cannot copy second key descriptor of "
+ "the user pair\n");
+ return -EINVAL;
+ }
+
+ /* Check the Classifier Table counter */
+ err = check_tbl_cls_counter(cnt_cb, lookup_key);
}
- return 0;
+ return err;
}
static int set_cls_cnt_classif_tbl_cb(struct dpa_stats_cnt_cb *cnt_cb,
const struct dpa_stats_cls_cnt_params *params)
{
- struct dpa_stats_cnt_classif_tbl_cb *cnt_tbl_cb = &cnt_cb->tbl_cb;
+ struct dpa_stats_cnt_classif_tbl_cb *tbl_cb = &cnt_cb->tbl_cb;
struct dpa_stats_cls_cnt_classif_tbl prm = params->classif_tbl_params;
struct dpa_stats *dpa_stats = cnt_cb->dpa_stats;
struct dpa_cls_tbl_params cls_tbl;
@@ -2004,11 +2151,17 @@ static int set_cls_cnt_classif_tbl_cb(struct dpa_stats_cnt_cb *cnt_cb,
return -EINVAL;
}
- cnt_tbl_cb->td = params->classif_tbl_params.td;
+ tbl_cb->td = params->classif_tbl_params.td;
cnt_cb->members_num = params->class_members;
switch (prm.key_type) {
case DPA_STATS_CLASSIF_SINGLE_KEY:
+ if (!prm.keys) {
+ log_err("Pointer to the array of keys cannot be NULL "
+ "for counter id %d\n", cnt_cb->id);
+ return -EINVAL;
+ }
+
/* Get CcNode from table descriptor */
err = dpa_classif_table_get_params(prm.td, &cls_tbl);
if (err != 0) {
@@ -2018,21 +2171,37 @@ static int set_cls_cnt_classif_tbl_cb(struct dpa_stats_cnt_cb *cnt_cb,
}
/* Store DPA Classifier Table type */
- cnt_tbl_cb->type = cls_tbl.type;
+ tbl_cb->type = cls_tbl.type;
+
+ /* Set retrieve function depending on table type */
+ set_cnt_classif_tbl_retrieve_func(cnt_cb);
for (i = 0; i < params->class_members; i++) {
/* Store CcNode handle */
- cnt_tbl_cb->keys[i].cc_node = cls_tbl.cc_node;
+ tbl_cb->keys[i].cc_node = cls_tbl.cc_node;
+
+ /* Determine if key represents a 'miss' entry */
+ if (!prm.keys[i]) {
+ tbl_cb->keys[i].miss_key = TRUE;
+ tbl_cb->keys[i].valid = TRUE;
+
+ err = check_ccnode_miss_counter(
+ tbl_cb->keys[i].cc_node,
+ cnt_cb->id, tbl_cb->type);
+ if (err != 0)
+ return -EINVAL;
+ continue;
+ }
- if (!prm.keys[i].byte) {
+ if (!prm.keys[i]->byte) {
/* Key is not valid for now */
- cnt_tbl_cb->keys[i].valid = FALSE;
+ tbl_cb->keys[i].valid = FALSE;
continue;
}
/* Copy the key descriptor */
- err = copy_key_descriptor(&prm.keys[i],
- &cnt_tbl_cb->keys[i].key);
+ err = copy_key_descriptor(prm.keys[i],
+ &tbl_cb->keys[i].key);
if (err != 0) {
log_err("Cannot copy key descriptor from user "
"parameters\n");
@@ -2040,37 +2209,39 @@ static int set_cls_cnt_classif_tbl_cb(struct dpa_stats_cnt_cb *cnt_cb,
}
/* Check the Classifier Table counter */
- err = check_tbl_cls_counter(cnt_cb,
- &cnt_tbl_cb->keys[i]);
+ err = check_tbl_cls_counter(cnt_cb, &tbl_cb->keys[i]);
if (err != 0)
return -EINVAL;
- cnt_tbl_cb->keys[i].valid = TRUE;
+ tbl_cb->keys[i].valid = TRUE;
}
break;
case DPA_STATS_CLASSIF_PAIR_KEY:
+ if (!prm.pairs) {
+ log_err("Pointer to the array of pairs cannot be NULL "
+ "for counter id %d\n", cnt_cb->id);
+ return -EINVAL;
+ }
+
for (i = 0; i < params->class_members; i++) {
- if (!prm.pairs[i].first_key.byte) {
- /* Key is not valid for now */
- cnt_tbl_cb->keys[i].valid = FALSE;
- continue;
+ if (prm.pairs[i]) {
+ if (prm.pairs[i]->first_key) {
+ if (!prm.pairs[i]->first_key->byte) {
+ /* Key is not valid for now */
+ tbl_cb->keys[i].valid = FALSE;
+ continue;
+ }
+ }
}
- err = set_cls_cnt_classif_tbl_pair(cnt_tbl_cb, prm.td,
- &prm.pairs[i], &cnt_tbl_cb->keys[i]);
+ err = set_cls_cnt_classif_tbl_pair(cnt_cb, prm.td,
+ prm.pairs[i], &tbl_cb->keys[i]);
if (err != 0) {
log_err("Cannot set classifier table pair key "
"for counter id %d\n", cnt_cb->id);
return -EINVAL;
}
-
- /* Check the Classifier Table counter */
- err = check_tbl_cls_counter(cnt_cb,
- &cnt_tbl_cb->keys[i]);
- if (err != 0)
- return -EINVAL;
-
- cnt_tbl_cb->keys[i].valid = TRUE;
+ tbl_cb->keys[i].valid = TRUE;
}
break;
default:
@@ -2084,7 +2255,7 @@ static int set_cls_cnt_classif_tbl_cb(struct dpa_stats_cnt_cb *cnt_cb,
if (frag_stats) {
/* For every valid key, retrieve the hmcd */
for (i = 0; i < params->class_members; i++) {
- if (!cnt_tbl_cb->keys[i].valid)
+ if (!tbl_cb->keys[i].valid)
continue;
err = set_frag_manip(prm.td, &cnt_cb->tbl_cb.keys[i]);
@@ -2140,24 +2311,46 @@ static int set_cls_cnt_ccnode_cb(struct dpa_stats_cnt_cb *cnt_cb,
return -EFAULT;
}
+ if (!prm.keys) {
+ log_err("Pointer to the array of keys cannot be NULL "
+ "for counter id %d\n", cnt_cb->id);
+ return -EINVAL;
+ }
+
cnt_cb->ccnode_cb.cc_node = prm.cc_node;
cnt_cb->members_num = params->class_members;
+ /* Set retrieve function depending on counter type */
+ err = set_cnt_classif_node_retrieve_func(cnt_cb, prm.ccnode_type);
+ if (err != 0)
+ return -EINVAL;
+
for (i = 0; i < params->class_members; i++) {
- /* Copy the key descriptor */
- err = copy_key_descriptor(&prm.keys[i],
- &cnt_cb->ccnode_cb.keys[i]);
- if (err != 0) {
- log_err("Cannot copy key descriptor from user "
- "parameters\n");
- return -EINVAL;
- }
+ if (!prm.keys[i]) {
+ /* Set the key byte to NULL, to mark it for 'miss' */
+ cnt_cb->ccnode_cb.keys[i].byte = NULL;
- /* Check the Classifier Node counter parameters */
- err = check_ccnode_counter(cnt_cb,
- prm.ccnode_type, &cnt_cb->ccnode_cb.keys[i]);
- if (err != 0)
- return -EINVAL;
+ /* Check the Classifier Node counter parameters */
+ err = check_ccnode_miss_counter(prm.cc_node,
+ cnt_cb->id, prm.ccnode_type);
+ if (err != 0)
+ return -EINVAL;
+ } else {
+ /* Copy the key descriptor */
+ err = copy_key_descriptor(prm.keys[i],
+ &cnt_cb->ccnode_cb.keys[i]);
+ if (err != 0) {
+ log_err("Cannot copy key descriptor from user "
+ "parameters\n");
+ return -EINVAL;
+ }
+
+ /* Check the Classifier Node counter parameters */
+ err = check_ccnode_counter(cnt_cb, prm.ccnode_type,
+ &cnt_cb->ccnode_cb.keys[i]);
+ if (err != 0)
+ return -EINVAL;
+ }
}
/* Map Classif Node counter selection to CcNode statistics */
@@ -2321,8 +2514,7 @@ static int set_cls_cnt_traffic_mng_cb(struct dpa_stats_cnt_cb *cnt_cb,
}
int set_classif_tbl_member(const struct dpa_stats_cls_member_params *prm,
- int member_index,
- struct dpa_stats_cnt_cb *cnt_cb)
+ int mbr_idx, struct dpa_stats_cnt_cb *cnt_cb)
{
struct dpa_stats_cnt_classif_tbl_cb *tbl_cb = &cnt_cb->tbl_cb;
uint32_t i = 0;
@@ -2337,67 +2529,80 @@ int set_classif_tbl_member(const struct dpa_stats_cls_member_params *prm,
}
/* Check that member index does not exceeds class size */
- if (member_index < 0 || member_index >= cnt_cb->members_num) {
+ if (mbr_idx < 0 || mbr_idx >= cnt_cb->members_num) {
log_err("Parameter member_index %d must be in range (0 - %d) "
- "for counter id %d\n", member_index,
+ "for counter id %d\n", mbr_idx,
cnt_cb->members_num - 1, cnt_cb->id);
return -EINVAL;
}
/* Release the old key memory */
- kfree(tbl_cb->keys[member_index].key.byte);
- tbl_cb->keys[member_index].key.byte = NULL;
+ kfree(tbl_cb->keys[mbr_idx].key.byte);
+ tbl_cb->keys[mbr_idx].key.byte = NULL;
- kfree(tbl_cb->keys[member_index].key.mask);
- tbl_cb->keys[member_index].key.mask = NULL;
+ kfree(tbl_cb->keys[mbr_idx].key.mask);
+ tbl_cb->keys[mbr_idx].key.mask = NULL;
/* Reset the statistics */
for (i = 0; i < cnt_cb->info.stats_num; i++) {
- cnt_cb->info.stats[member_index][i] = 0;
- cnt_cb->info.last_stats[member_index][i] = 0;
- }
-
- if ((prm->type == DPA_STATS_CLS_MEMBER_SINGLE_KEY && !prm->key.byte) ||
- (prm->type == DPA_STATS_CLS_MEMBER_PAIR_KEY &&
- !prm->pair.first_key.byte)) {
- /* Mark the key as invalid */
- tbl_cb->keys[member_index].valid = FALSE;
- return 0;
- } else {
- tbl_cb->keys[member_index].valid = TRUE;
-
- if (prm->type == DPA_STATS_CLS_MEMBER_SINGLE_KEY) {
+ cnt_cb->info.stats[mbr_idx][i] = 0;
+ cnt_cb->info.last_stats[mbr_idx][i] = 0;
+ }
+
+ if (prm->type == DPA_STATS_CLS_MEMBER_SINGLE_KEY) {
+ if (!prm->key) {
+ /* Mark the key as 'miss' entry */
+ tbl_cb->keys[mbr_idx].miss_key = TRUE;
+ tbl_cb->keys[mbr_idx].valid = TRUE;
+ return 0;
+ } else if (!prm->key->byte) {
+ /* Mark the key as invalid */
+ tbl_cb->keys[mbr_idx].valid = FALSE;
+ tbl_cb->keys[mbr_idx].miss_key = FALSE;
+ return 0;
+ } else {
/* Copy the key descriptor */
- err = copy_key_descriptor(&prm->key,
- &tbl_cb->keys[member_index].key);
+ err = copy_key_descriptor(prm->key,
+ &tbl_cb->keys[mbr_idx].key);
if (err != 0) {
log_err("Cannot copy key descriptor from user "
"parameters\n");
return -EINVAL;
}
- } else {
- err = set_cls_cnt_classif_tbl_pair(tbl_cb, tbl_cb->td,
- &prm->pair, &tbl_cb->keys[member_index]);
- if (err != 0) {
- log_err("Cannot configure the pair key for "
- "counter id %d of member %d\n",
- cnt_cb->id, member_index);
- return -EINVAL;
- }
}
- if (cnt_cb->f_get_cnt_stats != get_cnt_cls_tbl_frag_stats) {
+ } else {
+ if (prm->pair)
+ if (prm->pair->first_key)
+ if (!prm->pair->first_key->byte) {
+ /* Mark the key as invalid */
+ tbl_cb->keys[mbr_idx].valid = FALSE;
+ tbl_cb->keys[mbr_idx].miss_key = FALSE;
+ return 0;
+ }
+ err = set_cls_cnt_classif_tbl_pair(cnt_cb, tbl_cb->td,
+ prm->pair, &tbl_cb->keys[mbr_idx]);
+ if (err != 0) {
+ log_err("Cannot configure the pair key for counter id "
+ "%d of member %d\n", cnt_cb->id, mbr_idx);
+ return -EINVAL;
+ }
+ }
+
+ tbl_cb->keys[mbr_idx].valid = TRUE;
+
+ if (cnt_cb->f_get_cnt_stats != get_cnt_cls_tbl_frag_stats) {
+ if (!tbl_cb->keys[mbr_idx].miss_key) {
err = check_tbl_cls_counter(cnt_cb,
- &tbl_cb->keys[member_index]);
+ &tbl_cb->keys[mbr_idx]);
if (err != 0)
return -EINVAL;
- } else{
- err = set_frag_manip(tbl_cb->td,
- &tbl_cb->keys[member_index]);
- if (err < 0) {
- log_err("Invalid Fragmentation manip handle for"
- " counter id %d\n", cnt_cb->id);
- return -EINVAL;
- }
+ }
+ } else{
+ err = set_frag_manip(tbl_cb->td, &tbl_cb->keys[mbr_idx]);
+ if (err < 0) {
+ log_err("Invalid Fragmentation manip handle for"
+ " counter id %d\n", cnt_cb->id);
+ return -EINVAL;
}
}
@@ -2648,11 +2853,19 @@ static int get_cnt_cls_tbl_match_stats(struct dpa_stats_req_cb *req_cb,
cnt_cb->info.stats_num;
continue;
}
- err = FM_PCD_MatchTableFindNGetKeyStatistics(
- cnt_cb->tbl_cb.keys[i].cc_node,
- cnt_cb->tbl_cb.keys[i].key.size,
- cnt_cb->tbl_cb.keys[i].key.byte,
- cnt_cb->tbl_cb.keys[i].key.mask, &stats);
+
+ if (cnt_cb->tbl_cb.keys[i].miss_key) {
+ err = FM_PCD_MatchTableGetMissStatistics(
+ cnt_cb->tbl_cb.keys[i].cc_node, &stats);
+ } else {
+ err = FM_PCD_MatchTableFindNGetKeyStatistics(
+ cnt_cb->tbl_cb.keys[i].cc_node,
+ cnt_cb->tbl_cb.keys[i].key.size,
+ cnt_cb->tbl_cb.keys[i].key.byte,
+ cnt_cb->tbl_cb.keys[i].key.mask,
+ &stats);
+ }
+
if (err != 0) {
log_err("Cannot retrieve Classifier Exact Match Table "
"statistics for counter id %d\n", cnt_cb->id);
@@ -2682,11 +2895,17 @@ static int get_cnt_cls_tbl_hash_stats(struct dpa_stats_req_cb *req_cb,
cnt_cb->info.stats_num;
continue;
}
- err = FM_PCD_HashTableFindNGetKeyStatistics(
- cnt_cb->tbl_cb.keys[i].cc_node,
- cnt_cb->tbl_cb.keys[i].key.size,
- cnt_cb->tbl_cb.keys[i].key.byte,
- &stats);
+
+ if (cnt_cb->tbl_cb.keys[i].miss_key) {
+ err = FM_PCD_HashTableGetMissStatistics(
+ cnt_cb->tbl_cb.keys[i].cc_node, &stats);
+ } else {
+ err = FM_PCD_HashTableFindNGetKeyStatistics(
+ cnt_cb->tbl_cb.keys[i].cc_node,
+ cnt_cb->tbl_cb.keys[i].key.size,
+ cnt_cb->tbl_cb.keys[i].key.byte,
+ &stats);
+ }
if (err != 0) {
log_err("Cannot retrieve Classifier Hash Table "
"statistics for counter id %d\n", cnt_cb->id);
@@ -2716,10 +2935,17 @@ static int get_cnt_cls_tbl_index_stats(struct dpa_stats_req_cb *req_cb,
cnt_cb->info.stats_num;
continue;
}
- err = FM_PCD_MatchTableGetKeyStatistics(
- cnt_cb->tbl_cb.keys[i].cc_node,
- cnt_cb->tbl_cb.keys[i].key.byte[0],
- &stats);
+
+ if (cnt_cb->tbl_cb.keys[i].miss_key) {
+ err = FM_PCD_MatchTableGetMissStatistics(
+ cnt_cb->tbl_cb.keys[i].cc_node, &stats);
+ } else {
+ err = FM_PCD_MatchTableGetKeyStatistics(
+ cnt_cb->tbl_cb.keys[i].cc_node,
+ cnt_cb->tbl_cb.keys[i].key.byte[0],
+ &stats);
+ }
+
if (err != 0) {
log_err("Cannot retrieve Classifier Indexed Table "
"statistics for counter id %d\n", cnt_cb->id);
@@ -2772,11 +2998,16 @@ static int get_cnt_ccnode_match_stats(struct dpa_stats_req_cb *req_cb,
int err = 0;
for (i = 0; i < cnt_cb->members_num; i++) {
- err = FM_PCD_MatchTableFindNGetKeyStatistics(
+ if (!cnt_cb->ccnode_cb.keys[i].byte) {
+ err = FM_PCD_MatchTableGetMissStatistics(
+ cnt_cb->ccnode_cb.cc_node, &stats);
+ } else {
+ err = FM_PCD_MatchTableFindNGetKeyStatistics(
cnt_cb->ccnode_cb.cc_node,
cnt_cb->ccnode_cb.keys[i].size,
cnt_cb->ccnode_cb.keys[i].byte,
cnt_cb->ccnode_cb.keys[i].mask, &stats);
+ }
if (err != 0) {
log_err("Cannot retrieve Classification Cc Node Exact "
"Match statistics for counter id %d\n",
@@ -2797,10 +3028,16 @@ static int get_cnt_ccnode_hash_stats(struct dpa_stats_req_cb *req_cb,
int err = 0;
for (i = 0; i < cnt_cb->members_num; i++) {
- err = FM_PCD_HashTableFindNGetKeyStatistics(
+ if (!cnt_cb->ccnode_cb.keys[i].byte) {
+ err = FM_PCD_HashTableGetMissStatistics(
+ cnt_cb->ccnode_cb.cc_node, &stats);
+ } else {
+ err = FM_PCD_HashTableFindNGetKeyStatistics(
cnt_cb->ccnode_cb.cc_node,
cnt_cb->ccnode_cb.keys[i].size,
cnt_cb->ccnode_cb.keys[i].byte, &stats);
+ }
+
if (err != 0) {
log_err("Cannot retrieve Classification Cc Node Hash "
"statistics for counter id %d\n", cnt_cb->id);
@@ -2820,9 +3057,14 @@ static int get_cnt_ccnode_index_stats(struct dpa_stats_req_cb *req_cb,
int err = 0;
for (i = 0; i < cnt_cb->members_num; i++) {
- err = FM_PCD_MatchTableGetKeyStatistics(
+ if (!cnt_cb->ccnode_cb.keys[i].byte) {
+ err = FM_PCD_MatchTableGetMissStatistics(
+ cnt_cb->ccnode_cb.cc_node, &stats);
+ } else {
+ err = FM_PCD_MatchTableGetKeyStatistics(
cnt_cb->ccnode_cb.cc_node,
cnt_cb->ccnode_cb.keys[i].byte[0], &stats);
+ }
if (err != 0) {
log_err("Cannot retrieve Classification Cc Node Index "
"statistics for counter id %d\n", cnt_cb->id);
@@ -3269,6 +3511,7 @@ int dpa_stats_create_class_counter(int dpa_stats_id,
break;
case DPA_STATS_CNT_CLASSIF_TBL:
cnt_cb->type = DPA_STATS_CNT_CLASSIF_TBL;
+ cnt_cb->f_get_cnt_stats = get_cnt_cls_tbl_match_stats;
err = set_cls_cnt_classif_tbl_cb(cnt_cb, params);
if (err != 0) {
@@ -3392,7 +3635,7 @@ int dpa_stats_modify_class_counter(int dpa_stats_cnt_id,
}
if (params->type == DPA_STATS_CLS_MEMBER_SINGLE_KEY ||
- params->type == DPA_STATS_CLS_MEMBER_PAIR_KEY) {
+ params->type == DPA_STATS_CLS_MEMBER_PAIR_KEY) {
/* Modify classifier table class member */
err = set_classif_tbl_member(params, member_index, cnt_cb);
if (err < 0) {
diff --git a/drivers/staging/fsl_dpa_offload/dpa_stats.h b/drivers/staging/fsl_dpa_offload/dpa_stats.h
index a429258..5843dca 100644
--- a/drivers/staging/fsl_dpa_offload/dpa_stats.h
+++ b/drivers/staging/fsl_dpa_offload/dpa_stats.h
@@ -114,6 +114,7 @@ struct dpa_stats_lookup_key {
struct dpa_offload_lookup_key key; /* Key descriptor */
bool valid; /* Lookup key is valid */
void *frag; /* Fragmentation handle corresponding to this key */
+ bool miss_key; /* Provide statistics for miss entry */
};
/* DPA Stats Classif Table control block */
diff --git a/drivers/staging/fsl_dpa_offload/dpa_stats_ioctl.h b/drivers/staging/fsl_dpa_offload/dpa_stats_ioctl.h
index 070a6f0..d375a0f 100644
--- a/drivers/staging/fsl_dpa_offload/dpa_stats_ioctl.h
+++ b/drivers/staging/fsl_dpa_offload/dpa_stats_ioctl.h
@@ -116,14 +116,14 @@ struct compat_ioc_dpa_offld_lookup_key {
struct dpa_stats_compat_cnt_classif_tbl {
int td;
- struct compat_ioc_dpa_offld_lookup_key key;
+ compat_uptr_t key;
unsigned int cnt_sel;
};
struct dpa_stats_compat_cnt_classif_node {
compat_uptr_t cc_node;
enum dpa_stats_classif_node_type ccnode_type;
- struct compat_ioc_dpa_offld_lookup_key key;
+ compat_uptr_t key;
unsigned int cnt_sel;
};
@@ -202,15 +202,15 @@ struct compat_ioc_dpa_stats_cls_cnt_params {
};
struct compat_ioc_dpa_offld_lookup_key_pair {
- struct compat_ioc_dpa_offld_lookup_key first_key;
- struct compat_ioc_dpa_offld_lookup_key second_key;
+ compat_uptr_t first_key;
+ compat_uptr_t second_key;
};
struct dpa_stats_compat_cls_member_params {
enum dpa_stats_cls_member_type type;
union {
- struct compat_ioc_dpa_offld_lookup_key key;
- struct compat_ioc_dpa_offld_lookup_key_pair pair;
+ compat_uptr_t key;
+ compat_uptr_t pair;
int sa_id;
};
};
diff --git a/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.c b/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.c
index 5c2cb90..0fdcdc5 100644
--- a/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.c
+++ b/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.c
@@ -90,7 +90,10 @@ static long wrp_dpa_stats_do_ioctl(struct file *filp,
unsigned int cmd, unsigned long args);
static int copy_key_descriptor(struct dpa_offload_lookup_key *src,
- struct dpa_offload_lookup_key *dst);
+ struct dpa_offload_lookup_key **dst);
+
+static int copy_pair_descriptor(struct dpa_offload_lookup_key_pair *src,
+ struct dpa_offload_lookup_key_pair **dst);
static int copy_class_members(void *objs, unsigned int size, void *dst);
@@ -103,8 +106,12 @@ static long wrp_dpa_stats_do_compat_ioctl(struct file *filp,
unsigned long args);
static int copy_key_descriptor_compatcpy(
- struct dpa_offload_lookup_key *kprm,
- const struct compat_ioc_dpa_offld_lookup_key *uprm);
+ struct dpa_offload_lookup_key **kprm,
+ compat_uptr_t uparam);
+
+static int copy_pair_descriptor_compatcpy(
+ struct dpa_offload_lookup_key_pair **ks_pair,
+ struct compat_ioc_dpa_offld_lookup_key_pair pair);
static void dpa_stats_init_compatcpy(
struct ioc_dpa_stats_params *kprm,
@@ -625,39 +632,70 @@ static long do_ioctl_stats_free(void *args)
static int do_ioctl_stats_create_counter(void *args)
{
struct ioc_dpa_stats_cnt_params prm;
- struct dpa_offload_lookup_key key;
+ struct dpa_offload_lookup_key *us_key = NULL;
long ret = 0;
if (copy_from_user(&prm, args, sizeof(prm))) {
- log_err("Cannot copy from user the counter parameters\n");
+ log_err("Could not copy counter parameters\n");
return -EINVAL;
}
- if (prm.cnt_params.type == DPA_STATS_CNT_CLASSIF_NODE)
- ret = copy_key_descriptor(
- &prm.cnt_params.classif_node_params.key, &key);
- else if (prm.cnt_params.type == DPA_STATS_CNT_CLASSIF_TBL)
- ret = copy_key_descriptor(
- &prm.cnt_params.classif_tbl_params.key, &key);
- if (ret != 0) {
- log_err("Cannot copy the key descriptor\n");
- return -EINVAL;
+ if (prm.cnt_params.type == DPA_STATS_CNT_CLASSIF_NODE &&
+ prm.cnt_params.classif_node_params.key) {
+ /* Save user-space provided key */
+ us_key = prm.cnt_params.classif_node_params.key;
+
+ /* Override user-space pointers with kernel memory */
+ ret = copy_key_descriptor(us_key,
+ &prm.cnt_params.classif_node_params.key);
+ if (ret != 0) {
+ log_err("Could not copy the key descriptor\n");
+ kfree(prm.cnt_params.classif_node_params.key);
+ return ret;
+ }
+ }
+
+ if (prm.cnt_params.type == DPA_STATS_CNT_CLASSIF_TBL &&
+ prm.cnt_params.classif_tbl_params.key) {
+ /* Save user-space provided key */
+ us_key = prm.cnt_params.classif_tbl_params.key;
+
+ /* Override user-space pointers with kernel memory */
+ ret = copy_key_descriptor(us_key,
+ &prm.cnt_params.classif_tbl_params.key);
+ if (ret != 0) {
+ log_err("Could not copy the key descriptor\n");
+ kfree(prm.cnt_params.classif_tbl_params.key);
+ return ret;
+ }
}
ret = dpa_stats_create_counter(prm.stats_id,
&prm.cnt_params, &prm.cnt_id);
- if (ret < 0)
- return ret;
- if (copy_to_user(args, &prm, sizeof(prm))) {
- log_err("Cannot copy to user the counter parameters\n");
- ret = -EINVAL;
+ if (prm.cnt_params.type == DPA_STATS_CNT_CLASSIF_NODE &&
+ prm.cnt_params.classif_node_params.key) {
+ /* Release kernel-allocated memory */
+ kfree(prm.cnt_params.classif_node_params.key->byte);
+ kfree(prm.cnt_params.classif_node_params.key->mask);
+ kfree(prm.cnt_params.classif_node_params.key);
+ /* Restore user-provided key */
+ prm.cnt_params.classif_node_params.key = us_key;
}
- if (prm.cnt_params.type == DPA_STATS_CNT_CLASSIF_NODE ||
- prm.cnt_params.type == DPA_STATS_CNT_CLASSIF_TBL) {
- kfree(key.byte);
- kfree(key.mask);
+ if (prm.cnt_params.type == DPA_STATS_CNT_CLASSIF_TBL &&
+ prm.cnt_params.classif_tbl_params.key) {
+ /* Release kernel-allocated memory */
+ kfree(prm.cnt_params.classif_tbl_params.key->byte);
+ kfree(prm.cnt_params.classif_tbl_params.key->mask);
+ kfree(prm.cnt_params.classif_tbl_params.key);
+ /* Restore user-provided key */
+ prm.cnt_params.classif_tbl_params.key = us_key;
+ }
+
+ if (copy_to_user(args, &prm, sizeof(prm))) {
+ log_err("Could not copy to user the Counter ID\n");
+ ret = -EINVAL;
}
return ret;
@@ -702,14 +740,14 @@ static int do_ioctl_stats_compat_create_counter(void *args)
&kprm.cnt_params.classif_tbl_params,
&uprm.cnt_params.classif_tbl_params);
if (ret < 0)
- return ret;
+ goto compat_create_counter_cleanup;
break;
case DPA_STATS_CNT_CLASSIF_NODE:
ret = dpa_stats_ccnode_cnt_compatcpy(
&kprm.cnt_params.classif_node_params,
&uprm.cnt_params.classif_node_params);
if (ret < 0)
- return ret;
+ goto compat_create_counter_cleanup;
break;
case DPA_STATS_CNT_IPSEC:
memcpy(&kprm.cnt_params.ipsec_params,
@@ -728,7 +766,7 @@ static int do_ioctl_stats_compat_create_counter(void *args)
ret = dpa_stats_create_counter(kprm.stats_id,
&kprm.cnt_params, &kprm.cnt_id);
if (ret < 0)
- return ret;
+ goto compat_create_counter_cleanup;
uprm.cnt_id = kprm.cnt_id;
@@ -737,14 +775,20 @@ static int do_ioctl_stats_compat_create_counter(void *args)
ret = -EINVAL;
}
- if (kprm.cnt_params.type == DPA_STATS_CNT_CLASSIF_NODE) {
- kfree(kprm.cnt_params.classif_node_params.key.byte);
- kfree(kprm.cnt_params.classif_node_params.key.mask);
- } else if (kprm.cnt_params.type == DPA_STATS_CNT_CLASSIF_TBL) {
- kfree(kprm.cnt_params.classif_tbl_params.key.byte);
- kfree(kprm.cnt_params.classif_tbl_params.key.mask);
+compat_create_counter_cleanup:
+ if (kprm.cnt_params.type == DPA_STATS_CNT_CLASSIF_NODE &&
+ compat_ptr(uprm.cnt_params.classif_node_params.key)) {
+ kfree(kprm.cnt_params.classif_node_params.key->byte);
+ kfree(kprm.cnt_params.classif_node_params.key->mask);
+ kfree(kprm.cnt_params.classif_node_params.key);
}
+ if (kprm.cnt_params.type == DPA_STATS_CNT_CLASSIF_TBL &&
+ compat_ptr(uprm.cnt_params.classif_tbl_params.key)) {
+ kfree(kprm.cnt_params.classif_tbl_params.key->byte);
+ kfree(kprm.cnt_params.classif_tbl_params.key->mask);
+ kfree(kprm.cnt_params.classif_tbl_params.key);
+ }
return ret;
}
#endif
@@ -754,9 +798,10 @@ static int do_ioctl_stats_create_class_counter(void *args)
struct ioc_dpa_stats_cls_cnt_params prm;
struct dpa_stats_cls_cnt_classif_node *cnode;
struct dpa_stats_cls_cnt_classif_tbl *tbl;
- struct dpa_offload_lookup_key key;
- struct dpa_stats_cnt_eth_src *eth_src = NULL;
- uint32_t i = 0, eth_src_size = 0;
+ struct dpa_offload_lookup_key **us_keys = NULL;
+ struct dpa_offload_lookup_key_pair **us_pairs = NULL;
+ uint32_t i = 0;
+ unsigned int cls_mbrs;
void *cls_objs = NULL;
int *sa_ids = NULL;
long ret = 0;
@@ -766,13 +811,14 @@ static int do_ioctl_stats_create_class_counter(void *args)
return -EINVAL;
}
+ cls_mbrs = prm.cnt_params.class_members;
+
switch (prm.cnt_params.type) {
- case DPA_STATS_CNT_ETH:
- eth_src_size = prm.cnt_params.class_members *
- sizeof(struct dpa_stats_cnt_eth_src);
+ case DPA_STATS_CNT_ETH: {
+ struct dpa_stats_cnt_eth_src *eth_src = NULL;
/* Allocate memory to store the sources array */
- eth_src = kmalloc(eth_src_size, GFP_KERNEL);
+ eth_src = kmalloc(sizeof(*eth_src) * cls_mbrs, GFP_KERNEL);
if (!eth_src) {
log_err("Cannot allocate memory for Ethernet sources "
"array\n");
@@ -781,17 +827,17 @@ static int do_ioctl_stats_create_class_counter(void *args)
if (copy_from_user(eth_src,
prm.cnt_params.eth_params.src,
- eth_src_size)) {
+ sizeof(*eth_src) * cls_mbrs)) {
log_err("Cannot copy array of Ethernet sources\n");
kfree(eth_src);
return -EBUSY;
}
prm.cnt_params.eth_params.src = eth_src;
break;
+ }
case DPA_STATS_CNT_REASS:
- ret = copy_class_members(cls_objs,
- prm.cnt_params.class_members,
- prm.cnt_params.reass_params.reass);
+ ret = copy_class_members(cls_objs, cls_mbrs,
+ prm.cnt_params.reass_params.reass);
if (ret < 0) {
log_err("Cannot copy array of Reassembly objects\n");
kfree(cls_objs);
@@ -799,8 +845,7 @@ static int do_ioctl_stats_create_class_counter(void *args)
}
break;
case DPA_STATS_CNT_FRAG:
- ret = copy_class_members(cls_objs,
- prm.cnt_params.class_members,
+ ret = copy_class_members(cls_objs, cls_mbrs,
prm.cnt_params.frag_params.frag);
if (ret < 0) {
log_err("Cannot copy array of Fragmentation objects\n");
@@ -809,8 +854,7 @@ static int do_ioctl_stats_create_class_counter(void *args)
}
break;
case DPA_STATS_CNT_POLICER:
- ret = copy_class_members(cls_objs,
- prm.cnt_params.class_members,
+ ret = copy_class_members(cls_objs, cls_mbrs,
prm.cnt_params.plcr_params.plcr);
if (ret < 0) {
log_err("Cannot copy array of Policer objects\n");
@@ -822,36 +866,50 @@ static int do_ioctl_stats_create_class_counter(void *args)
tbl = &prm.cnt_params.classif_tbl_params;
if (tbl->key_type == DPA_STATS_CLASSIF_SINGLE_KEY) {
- for (i = 0; i < prm.cnt_params.class_members; i++) {
- if (!tbl->keys[i].byte)
- continue;
+ /* Save array of user-space provided key pointers */
+ us_keys = tbl->keys;
+
+ /* Override user-space pointers with kernel memory */
+ tbl->keys = kzalloc(cls_mbrs *
+ sizeof(**tbl->keys), GFP_KERNEL);
+ if (!tbl->keys) {
+ log_err("Cannot allocate kernel memory for "
+ "lookup keys array\n");
+ return -ENOMEM;
+ }
- ret = copy_key_descriptor(&tbl->keys[i], &key);
+ for (i = 0; i < cls_mbrs; i++) {
+ if (!us_keys[i])
+ continue;
+ ret = copy_key_descriptor(us_keys[i],
+ &tbl->keys[i]);
if (ret != 0) {
- log_err("Cannot copy the key descriptor"
- "\n");
- return -EINVAL;
+ log_err("Cannot copy key descriptor\n");
+ goto create_cls_counter_cleanup;
}
}
} else if (tbl->key_type == DPA_STATS_CLASSIF_PAIR_KEY) {
- for (i = 0; i < prm.cnt_params.class_members; i++) {
- if (!tbl->pairs[i].first_key.byte)
- continue;
-
- ret = copy_key_descriptor(
- &tbl->pairs[i].first_key, &key);
- if (ret != 0) {
- log_err("Cannot copy the first key "
- "descriptor of pair-key\n");
- return -EINVAL;
- }
+ /* Save array of user-space provided pairs pointers */
+ us_pairs = tbl->pairs;
+
+ /* Override user-space pointers with kernel memory */
+ tbl->pairs = kzalloc(cls_mbrs *
+ sizeof(**tbl->pairs), GFP_KERNEL);
+ if (!tbl->pairs) {
+ log_err("Cannot allocate kernel memory for "
+ "lookup pairs array\n");
+ return -ENOMEM;
+ }
- ret = copy_key_descriptor(
- &tbl->pairs[i].second_key, &key);
+ for (i = 0; i < cls_mbrs; i++) {
+ if (!us_pairs[i])
+ continue;
+ ret = copy_pair_descriptor(us_pairs[i],
+ &tbl->pairs[i]);
if (ret != 0) {
- log_err("Cannot copy the second key "
- "descriptor of pair-key\n");
- return -EINVAL;
+ log_err("Could not copy the "
+ "pair key descriptor\n");
+ goto create_cls_counter_cleanup;
}
}
}
@@ -859,11 +917,28 @@ static int do_ioctl_stats_create_class_counter(void *args)
case DPA_STATS_CNT_CLASSIF_NODE:
cnode = &prm.cnt_params.classif_node_params;
- for (i = 0; i < prm.cnt_params.class_members; i++) {
- ret = copy_key_descriptor(&cnode->keys[i], &key);
+ if (!cnode->keys) {
+ log_err("Pointer to array of keys can't be NULL\n");
+ return -EINVAL;
+ }
+ /* Save array of user-space provided key pointers */
+ us_keys = cnode->keys;
+
+ /* Override user-space pointers with kernel memory */
+ cnode->keys = kzalloc(cls_mbrs *
+ sizeof(**cnode->keys), GFP_KERNEL);
+ if (!cnode->keys) {
+ log_err("No more memory to store array of keys\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < cls_mbrs; i++) {
+ if (!us_keys[i])
+ continue;
+ ret = copy_key_descriptor(us_keys[i], &cnode->keys[i]);
if (ret != 0) {
log_err("Cannot copy the key descriptor\n");
- return -EINVAL;
+ goto create_cls_counter_cleanup;
}
}
break;
@@ -891,17 +966,10 @@ static int do_ioctl_stats_create_class_counter(void *args)
ret = dpa_stats_create_class_counter(prm.stats_id,
&prm.cnt_params, &prm.cnt_id);
- if (ret < 0)
- return ret;
-
- if (copy_to_user(args, &prm, sizeof(prm))) {
- log_err("Cannot copy to user class counter parameters\n");
- ret = -EINVAL;
- }
-
+create_cls_counter_cleanup:
switch (prm.cnt_params.type) {
case DPA_STATS_CNT_ETH:
- kfree(eth_src);
+ kfree(prm.cnt_params.eth_params.src);
break;
case DPA_STATS_CNT_REASS:
case DPA_STATS_CNT_FRAG:
@@ -911,25 +979,53 @@ static int do_ioctl_stats_create_class_counter(void *args)
case DPA_STATS_CNT_CLASSIF_TBL:
tbl = &prm.cnt_params.classif_tbl_params;
- for (i = 0; i < prm.cnt_params.class_members; i++) {
- if (tbl->key_type == DPA_STATS_CLASSIF_SINGLE_KEY) {
- kfree(tbl->keys[i].byte);
- kfree(tbl->keys[i].mask);
+ if (tbl->key_type == DPA_STATS_CLASSIF_SINGLE_KEY) {
+ for (i = 0; i < cls_mbrs; i++) {
+ if (!tbl->keys[i])
+ continue;
+ /* Free allocated memory */
+ kfree(tbl->keys[i]->byte);
+ kfree(tbl->keys[i]->mask);
+ kfree(tbl->keys[i]);
}
+ /* Restore user-space pointers */
+ tbl->keys = us_keys;
+ }
+
+ if (tbl->key_type == DPA_STATS_CLASSIF_PAIR_KEY) {
+ for (i = 0; i < cls_mbrs; i++) {
+ if (!tbl->pairs[i])
+ continue;
- if (tbl->key_type == DPA_STATS_CLASSIF_PAIR_KEY) {
- kfree(tbl->pairs[i].first_key.byte);
- kfree(tbl->pairs[i].first_key.mask);
- kfree(tbl->pairs[i].second_key.byte);
- kfree(tbl->pairs[i].second_key.mask);
+ if (tbl->pairs[i]->first_key) {
+ kfree(tbl->pairs[i]->first_key->byte);
+ kfree(tbl->pairs[i]->first_key->mask);
+ kfree(tbl->pairs[i]->first_key);
+ }
+
+ if (tbl->pairs[i]->second_key) {
+ kfree(tbl->pairs[i]->second_key->byte);
+ kfree(tbl->pairs[i]->second_key->mask);
+ kfree(tbl->pairs[i]->second_key);
+ }
}
+ /* Restore user-space pointers */
+ tbl->keys = us_keys;
}
break;
case DPA_STATS_CNT_CLASSIF_NODE:
- for (i = 0; i < prm.cnt_params.class_members; i++) {
- kfree(prm.cnt_params.classif_node_params.keys[i].byte);
- kfree(prm.cnt_params.classif_node_params.keys[i].mask);
+ cnode = &prm.cnt_params.classif_node_params;
+
+ for (i = 0; i < cls_mbrs; i++) {
+ if (!cnode->keys[i])
+ continue;
+ /* Free allocated memory */
+ kfree(cnode->keys[i]->byte);
+ kfree(cnode->keys[i]->mask);
+ kfree(cnode->keys[i]);
}
+ /* Restore user-space pointers */
+ tbl->keys = us_keys;
break;
case DPA_STATS_CNT_IPSEC:
kfree(sa_ids);
@@ -939,6 +1035,11 @@ static int do_ioctl_stats_create_class_counter(void *args)
break;
}
+ if (copy_to_user(args, &prm, sizeof(prm))) {
+ log_err("Cannot copy to user class counter parameters\n");
+ ret = -EINVAL;
+ }
+
return ret;
}
@@ -988,46 +1089,18 @@ static int do_ioctl_stats_compat_create_class_counter(void *args)
return ret;
break;
case DPA_STATS_CNT_CLASSIF_TBL:
- {
- struct dpa_stats_cls_cnt_classif_tbl *tbl =
- &kprm_cls->classif_tbl_params;
-
- ret = dpa_stats_tbl_cls_compatcpy(tbl,
+ ret = dpa_stats_tbl_cls_compatcpy(&kprm_cls->classif_tbl_params,
&uprm_cls->classif_tbl_params, kprm_cls->class_members);
if (!ret)
break;
-
- if (tbl->key_type == DPA_STATS_CLASSIF_SINGLE_KEY) {
- for (i = 0; i < kprm_cls->class_members; i++) {
- kfree(tbl->keys[i].byte);
- kfree(tbl->keys[i].mask);
- }
- kfree(tbl->keys);
-
- } else if (tbl->key_type == DPA_STATS_CLASSIF_PAIR_KEY) {
- for (i = 0; i < kprm_cls->class_members; i++) {
- kfree(tbl->pairs[i].first_key.byte);
- kfree(tbl->pairs[i].first_key.mask);
- kfree(tbl->pairs[i].second_key.byte);
- kfree(tbl->pairs[i].second_key.mask);
- }
- kfree(tbl->pairs);
- }
- return ret;
- }
+ goto compat_create_cls_counter_cleanup;
case DPA_STATS_CNT_CLASSIF_NODE:
ret = dpa_stats_ccnode_cls_compatcpy(
- &kprm_cls->classif_node_params,
- &uprm_cls->ccnode_params,
- kprm_cls->class_members);
+ &kprm_cls->classif_node_params,
+ &uprm_cls->ccnode_params, kprm_cls->class_members);
if (!ret)
break;
- for (i = 0; i < kprm_cls->class_members; i++) {
- kfree(kprm_cls->classif_node_params.keys[i].byte);
- kfree(kprm_cls->classif_node_params.keys[i].mask);
- }
- kfree(kprm_cls->classif_node_params.keys);
- return ret;
+ goto compat_create_cls_counter_cleanup;
case DPA_STATS_CNT_IPSEC:
ret = dpa_stats_ipsec_cls_compatcpy(&kprm_cls->ipsec_params,
&uprm_cls->ipsec_params, kprm_cls->class_members);
@@ -1038,10 +1111,10 @@ static int do_ioctl_stats_compat_create_class_counter(void *args)
break;
}
- ret = dpa_stats_create_class_counter(
- kprm.stats_id, kprm_cls, &kprm.cnt_id);
+ ret = dpa_stats_create_class_counter(kprm.stats_id,
+ kprm_cls, &kprm.cnt_id);
if (ret < 0)
- return ret;
+ goto compat_create_cls_counter_cleanup;
uprm.cnt_id = kprm.cnt_id;
@@ -1050,6 +1123,7 @@ static int do_ioctl_stats_compat_create_class_counter(void *args)
ret = -EINVAL;
}
+compat_create_cls_counter_cleanup:
switch (uprm.cnt_params.type) {
case DPA_STATS_CNT_ETH:
kfree(kprm_cls->eth_params.src);
@@ -1070,17 +1144,29 @@ static int do_ioctl_stats_compat_create_class_counter(void *args)
if (tbl->key_type == DPA_STATS_CLASSIF_SINGLE_KEY) {
for (i = 0; i < kprm_cls->class_members; i++) {
- kfree(tbl->keys[i].byte);
- kfree(tbl->keys[i].mask);
+ if (!tbl->keys[i])
+ continue;
+ kfree(tbl->keys[i]->byte);
+ kfree(tbl->keys[i]->mask);
+ kfree(tbl->keys[i]);
}
kfree(tbl->keys);
} else if (tbl->key_type == DPA_STATS_CLASSIF_PAIR_KEY) {
for (i = 0; i < kprm_cls->class_members; i++) {
- kfree(tbl->pairs[i].first_key.byte);
- kfree(tbl->pairs[i].first_key.mask);
- kfree(tbl->pairs[i].second_key.byte);
- kfree(tbl->pairs[i].second_key.mask);
+ if (!tbl->pairs[i])
+ continue;
+ if (tbl->pairs[i]->first_key) {
+ kfree(tbl->pairs[i]->first_key->byte);
+ kfree(tbl->pairs[i]->first_key->mask);
+ kfree(tbl->pairs[i]->first_key);
+ }
+ if (tbl->pairs[i]->second_key) {
+ kfree(tbl->pairs[i]->second_key->byte);
+ kfree(tbl->pairs[i]->second_key->mask);
+ kfree(tbl->pairs[i]->second_key);
+ }
+ kfree(tbl->pairs[i]);
}
kfree(tbl->pairs);
}
@@ -1088,11 +1174,15 @@ static int do_ioctl_stats_compat_create_class_counter(void *args)
}
case DPA_STATS_CNT_CLASSIF_NODE:
for (i = 0; i < kprm_cls->class_members; i++) {
- kfree(kprm_cls->classif_node_params.keys[i].byte);
- kfree(kprm_cls->classif_node_params.keys[i].mask);
+ if (!kprm_cls->classif_node_params.keys[i])
+ continue;
+ kfree(kprm_cls->classif_node_params.keys[i]->byte);
+ kfree(kprm_cls->classif_node_params.keys[i]->mask);
+ kfree(kprm_cls->classif_node_params.keys[i]);
}
kfree(kprm_cls->classif_node_params.keys);
break;
+
case DPA_STATS_CNT_IPSEC:
kfree(kprm_cls->ipsec_params.sa_id);
break;
@@ -1108,8 +1198,9 @@ static int do_ioctl_stats_compat_create_class_counter(void *args)
static int do_ioctl_stats_modify_class_counter(void *args)
{
struct ioc_dpa_stats_cls_member_params prm;
- struct dpa_offload_lookup_key key;
- int ret;
+ struct dpa_offload_lookup_key *us_key = NULL;
+ struct dpa_offload_lookup_key_pair *us_pair = NULL;
+ int ret = 0;
if (copy_from_user(&prm, args, sizeof(prm))) {
log_err("Cannot copy from user the class counter parameters\n");
@@ -1118,32 +1209,32 @@ static int do_ioctl_stats_modify_class_counter(void *args)
switch (prm.params.type) {
case DPA_STATS_CLS_MEMBER_SINGLE_KEY:
- if (prm.params.key.byte) {
- ret = copy_key_descriptor(&prm.params.key, &key);
- if (ret != 0) {
- log_err("Cannot copy the key descriptor\n");
- return -EINVAL;
- }
+ if (!prm.params.key)
+ break;
+
+ /* Save user-space provided key */
+ us_key = prm.params.key;
+
+ /* Override user-space pointers with kernel memory */
+ ret = copy_key_descriptor(us_key, &prm.params.key);
+ if (ret != 0) {
+ log_err("Could not copy the key descriptor\n");
+ goto modify_counter_cleanup;
}
+
break;
case DPA_STATS_CLS_MEMBER_PAIR_KEY:
- if (prm.params.pair.first_key.byte &&
- prm.params.pair.first_key.mask) {
- ret = copy_key_descriptor(
- &prm.params.pair.first_key, &key);
- if (ret != 0) {
- log_err("Cannot copy the first key descriptor "
- "of the pair-key\n");
- return -EINVAL;
- }
+ if (!prm.params.pair)
+ break;
- ret = copy_key_descriptor(
- &prm.params.pair.second_key, &key);
- if (ret != 0) {
- log_err("Cannot copy the second key descriptor "
- "of the pair-key\n");
- return -EINVAL;
- }
+ /* Save array of user-space provided pairs pointers */
+ us_pair = prm.params.pair;
+
+ /* Override user-space pointers with kernel memory */
+ ret = copy_pair_descriptor(us_pair, &prm.params.pair);
+ if (ret != 0) {
+ log_err("Could not copy the pair key descriptor\n");
+ goto modify_counter_cleanup;
}
break;
case DPA_STATS_CLS_MEMBER_SA_ID:
@@ -1154,32 +1245,53 @@ static int do_ioctl_stats_modify_class_counter(void *args)
ret = dpa_stats_modify_class_counter(prm.cnt_id,
&prm.params, prm.member_index);
- if (ret < 0)
- return ret;
-
+modify_counter_cleanup:
switch (prm.params.type) {
case DPA_STATS_CLS_MEMBER_SINGLE_KEY:
- kfree(prm.params.key.byte);
- kfree(prm.params.key.mask);
+ if (prm.params.key) {
+ /* Release kernel-allocated memory */
+ kfree(prm.params.key->byte);
+ kfree(prm.params.key->mask);
+ kfree(prm.params.key);
+ /* Restore user-provided key */
+ prm.params.key = us_key;
+ }
break;
case DPA_STATS_CLS_MEMBER_PAIR_KEY:
- kfree(prm.params.pair.first_key.byte);
- kfree(prm.params.pair.first_key.mask);
- kfree(prm.params.pair.second_key.byte);
- kfree(prm.params.pair.second_key.mask);
+ if (prm.params.pair) {
+ if (prm.params.pair->first_key) {
+ /* Release kernel-allocated memory */
+ kfree(prm.params.pair->first_key->byte);
+ kfree(prm.params.pair->first_key->mask);
+ kfree(prm.params.pair->first_key);
+ }
+ if (prm.params.pair->second_key) {
+ /* Release kernel-allocated memory */
+ kfree(prm.params.pair->second_key->byte);
+ kfree(prm.params.pair->second_key->mask);
+ kfree(prm.params.pair->second_key);
+ }
+ kfree(prm.params.pair);
+ /* Restore user-provided key */
+ prm.params.pair->first_key = us_pair->first_key;
+ prm.params.pair->second_key = us_pair->second_key;
+ prm.params.pair = us_pair;
+ }
break;
case DPA_STATS_CLS_MEMBER_SA_ID:
break;
default:
+ log_err("Invalid class member type\n");
break;
}
if (copy_to_user(args, &prm, sizeof(prm))) {
- log_err("Cannot copy to user the class counter result\n");
- return -EBUSY;
+ log_err("Could not write "
+ "dpa_stats_modify_class_counter result\n");
+ ret = -EBUSY;
}
- return 0;
+ return ret;
}
#ifdef CONFIG_COMPAT
@@ -1187,10 +1299,11 @@ static int do_ioctl_stats_compat_modify_class_counter(void *args)
{
struct ioc_dpa_stats_cls_member_params kprm;
struct compat_ioc_dpa_stats_cls_member_params uprm;
+ struct compat_ioc_dpa_offld_lookup_key_pair pair;
int ret;
if (copy_from_user(&uprm, args, sizeof(uprm))) {
- log_err("Cannot copy from user the class counter parameters\n");
+ log_err("Cannot copy from user the modify counter parameters\n");
return -EINVAL;
}
@@ -1201,35 +1314,35 @@ static int do_ioctl_stats_compat_modify_class_counter(void *args)
switch (kprm.params.type) {
case DPA_STATS_CLS_MEMBER_SINGLE_KEY:
- if (compat_ptr(uprm.params.key.byte)) {
- ret = copy_key_descriptor_compatcpy(
- &kprm.params.key,
- &uprm.params.key);
- if (ret < 0) {
- log_err("Cannot copy the key descriptor\n");
- return ret;
- }
-
+ if (!compat_ptr(uprm.params.key))
+ break;
+ /* Copy user-provided key descriptor */
+ ret = copy_key_descriptor_compatcpy(&kprm.params.key,
+ uprm.params.key);
+ if (ret < 0) {
+ log_err("Cannot copy the key descriptor\n");
+ goto compat_modify_counter_cleanup;
}
break;
case DPA_STATS_CLS_MEMBER_PAIR_KEY:
- if (compat_ptr(uprm.params.pair.first_key.byte)) {
- ret = copy_key_descriptor_compatcpy(
- &kprm.params.pair.first_key,
- &uprm.params.pair.first_key);
- if (ret < 0)
- return ret;
+ if (!compat_ptr(uprm.params.pair))
+ break;
- ret = copy_key_descriptor_compatcpy(
- &kprm.params.pair.second_key,
- &uprm.params.pair.second_key);
- if (ret != 0) {
- log_err("Cannot copy the key descriptor of the "
- "pair-key\n");
- return -EINVAL;
- }
+ if (copy_from_user(&pair, compat_ptr(uprm.params.pair),
+ (sizeof(pair)))) {
+ log_err("Cannot copy from user array of "
+ "lookup pairs\n");
+ return -EBUSY;
+ }
+
+ /* Copy user-provided lookup pair descriptor */
+ ret = copy_pair_descriptor_compatcpy(&kprm.params.pair, pair);
+ if (ret < 0) {
+ log_err("Cannot copy the pair key descriptor\n");
+ goto compat_modify_counter_cleanup;
}
break;
+
case DPA_STATS_CLS_MEMBER_SA_ID:
kprm.params.sa_id = uprm.params.sa_id;
break;
@@ -1238,34 +1351,45 @@ static int do_ioctl_stats_compat_modify_class_counter(void *args)
}
ret = dpa_stats_modify_class_counter(kprm.cnt_id,
- &kprm.params, kprm.member_index);
+ &kprm.params, kprm.member_index);
if (ret < 0)
- return ret;
+ goto compat_modify_counter_cleanup;
uprm.cnt_id = kprm.cnt_id;
+ if (copy_to_user(args, &uprm, sizeof(uprm))) {
+ log_err("Cannot copy to user class counter result\n");
+ return -EBUSY;
+ }
+
+compat_modify_counter_cleanup:
switch (kprm.params.type) {
case DPA_STATS_CLS_MEMBER_SINGLE_KEY:
- kfree(kprm.params.key.byte);
- kfree(kprm.params.key.mask);
+ if (!kprm.params.key)
+ break;
+ kfree(kprm.params.key->byte);
+ kfree(kprm.params.key->mask);
+ kfree(kprm.params.key);
break;
case DPA_STATS_CLS_MEMBER_PAIR_KEY:
- kfree(kprm.params.pair.first_key.byte);
- kfree(kprm.params.pair.first_key.mask);
- kfree(kprm.params.pair.second_key.byte);
- kfree(kprm.params.pair.second_key.mask);
+ if (!kprm.params.pair)
+ break;
+ if (kprm.params.pair->first_key) {
+ kfree(kprm.params.pair->first_key->byte);
+ kfree(kprm.params.pair->first_key->mask);
+ kfree(kprm.params.pair->first_key);
+ }
+ if (kprm.params.pair->second_key) {
+ kfree(kprm.params.pair->second_key->byte);
+ kfree(kprm.params.pair->second_key->mask);
+ kfree(kprm.params.pair->second_key);
+ }
break;
case DPA_STATS_CLS_MEMBER_SA_ID:
break;
default:
break;
}
-
- if (copy_to_user(args, &uprm, sizeof(uprm))) {
- log_err("Cannot copy to user class counter result\n");
- return -EBUSY;
- }
-
return 0;
}
#endif
@@ -1720,89 +1844,196 @@ static long store_get_cnts_async_params(
}
static int copy_key_descriptor(struct dpa_offload_lookup_key *src,
- struct dpa_offload_lookup_key *tmp)
+ struct dpa_offload_lookup_key **ks_key)
{
- if (!src->byte) {
- log_err("Key descriptor byte from user cannot be NULL\n");
- return -EINVAL;
- }
+ struct dpa_offload_lookup_key *tmp = NULL;
- /* Allocate memory to store the key byte array */
- tmp->byte = kmalloc(src->size, GFP_KERNEL);
- if (!tmp->byte) {
- log_err("Cannot allocate memory for key descriptor byte\n");
+ /* Allocate kernel memory for key descriptor */
+ tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+ if (!tmp) {
+ log_err("Cannot allocate kernel memory for key descriptor\n");
return -ENOMEM;
}
- if (copy_from_user(tmp->byte, src->byte, src->size)) {
- log_err("Cannot copy from user the key descriptor byte\n");
- kfree(tmp->byte);
- return -EBUSY;
+ if (src->byte) {
+ /* Allocate memory to store the key byte array */
+ tmp->byte = kmalloc(src->size, GFP_KERNEL);
+ if (!tmp->byte) {
+ log_err("Cannot allocate memory for key "
+ "descriptor byte\n");
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(tmp->byte, src->byte, src->size)) {
+ log_err("Cannot copy from user the key "
+ "descriptor byte\n");
+ kfree(tmp->byte);
+ kfree(tmp);
+ return -EBUSY;
+ }
}
- src->byte = tmp->byte;
if (src->mask) {
/* Allocate memory to store the key mask array */
tmp->mask = kmalloc(src->size, GFP_KERNEL);
if (!tmp->mask) {
- log_err("Cannot allocate memory for key descriptor "
- "mask\n");
+ log_err("Cannot allocate memory for key "
+ "descriptor mask\n");
kfree(tmp->byte);
+ kfree(tmp);
return -ENOMEM;
}
if (copy_from_user(tmp->mask, src->mask, src->size)) {
- log_err("Cannot copy from user the key descriptor "
- "mask\n");
+ log_err("Cannot copy from user the "
+ "key descriptor mask\n");
kfree(tmp->byte);
kfree(tmp->mask);
+ kfree(tmp);
return -EBUSY;
}
- src->mask = tmp->mask;
}
+
+ tmp->size = src->size;
+ *ks_key = tmp;
+ return 0;
+}
+
+static int copy_pair_descriptor(struct dpa_offload_lookup_key_pair *src,
+ struct dpa_offload_lookup_key_pair **ks_pair)
+{
+ struct dpa_offload_lookup_key_pair *tmp;
+ int ret = 0;
+
+ /* Allocate kernel memory for pair descriptor*/
+ tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+ if (!tmp) {
+ log_err("Cannot allocate kernel memory for pair descriptor\n");
+ return -ENOMEM;
+ }
+
+ if (src->first_key) {
+ ret = copy_key_descriptor(src->first_key, &tmp->first_key);
+ if (ret != 0) {
+ log_err("Could not copy the first key descriptor\n");
+ kfree(tmp);
+ return ret;
+ }
+ }
+
+ if (src->second_key) {
+ ret = copy_key_descriptor(src->second_key, &tmp->second_key);
+ if (ret != 0) {
+ log_err("Could not copy the second key descriptor\n");
+ kfree(tmp);
+ return ret;
+ }
+ }
+ *ks_pair = tmp;
return 0;
}
#ifdef CONFIG_COMPAT
static int copy_key_descriptor_compatcpy(
- struct dpa_offload_lookup_key *kparam,
- const struct compat_ioc_dpa_offld_lookup_key *uparam)
+ struct dpa_offload_lookup_key **ks_key, compat_uptr_t uparam)
{
- BUG_ON(uparam->size <= 0);
+ struct compat_ioc_dpa_offld_lookup_key key;
+ struct dpa_offload_lookup_key *kparam;
- kparam->size = uparam->size;
+ if (copy_from_user(&key, (compat_ptr)(uparam),
+ sizeof(struct compat_ioc_dpa_offld_lookup_key))) {
+ log_err("Cannot copy from user key descriptor\n");
+ return -EBUSY;
+ }
- /* Allocate memory to store the key byte array */
- kparam->byte = kmalloc(kparam->size, GFP_KERNEL);
- if (!kparam->byte) {
- log_err("Cannot allocate memory for key descriptor byte\n");
+ /* Allocate kernel memory for key descriptor */
+ kparam = kzalloc(sizeof(*kparam), GFP_KERNEL);
+ if (!kparam) {
+ log_err("Cannot allocate kernel memory for key descriptor\n");
return -ENOMEM;
}
- if (copy_from_user(kparam->byte, compat_ptr(uparam->byte),
- uparam->size)) {
- log_err("Cannot copy from user the key descriptor byte\n");
- return -EBUSY;
+ if (compat_ptr(key.byte)) {
+ /* Allocate memory to store the key byte array */
+ kparam->byte = kmalloc(key.size, GFP_KERNEL);
+ if (!kparam->byte) {
+ log_err("Cannot allocate memory for key descriptor "
+ "byte\n");
+ kfree(kparam);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(kparam->byte,
+ compat_ptr(key.byte), key.size)) {
+ log_err("Cannot copy from user the key descriptor "
+ "byte\n");
+ kfree(kparam->byte);
+ kfree(kparam);
+ return -EBUSY;
+ }
}
- if (compat_ptr(uparam->mask)) {
+
+ if (compat_ptr(key.mask)) {
/* Allocate memory to store the key mask array */
- kparam->mask = kmalloc(kparam->size, GFP_KERNEL);
+ kparam->mask = kmalloc(key.size, GFP_KERNEL);
if (!kparam->mask) {
log_err("Cannot allocate memory for key descriptor "
"mask\n");
kfree(kparam->byte);
+ kfree(kparam);
return -ENOMEM;
}
- if (copy_from_user(kparam->mask, compat_ptr(uparam->mask),
- uparam->size)) {
+ if (copy_from_user(kparam->mask,
+ compat_ptr(key.mask), key.size)) {
log_err("Cannot copy from user the key descriptor "
"mask\n");
+ kfree(kparam->byte);
+ kfree(kparam->mask);
+ kfree(kparam);
return -EBUSY;
}
- } else
- kparam->mask = NULL;
+ }
+ kparam->size = key.size;
+ *ks_key = kparam;
+ return 0;
+}
+
+static int copy_pair_descriptor_compatcpy(
+ struct dpa_offload_lookup_key_pair **ks_pair,
+ struct compat_ioc_dpa_offld_lookup_key_pair pair)
+{
+ struct dpa_offload_lookup_key_pair *kpair;
+ int ret = 0;
+ /* Allocate kernel memory for lookup pair descriptor */
+ kpair = kzalloc(sizeof(*kpair), GFP_KERNEL);
+ if (!kpair) {
+ log_err("Cannot allocate kernel memory for pair descriptor\n");
+ return -ENOMEM;
+ }
+
+ if (compat_ptr(pair.first_key)) {
+ /* Copy user-provided key descriptor */
+ ret = copy_key_descriptor_compatcpy(
+ &kpair->first_key, pair.first_key);
+ if (ret != 0) {
+ log_err("Cannot copy first key of the pair\n");
+ kfree(kpair);
+ return ret;
+ }
+ }
+
+ if (compat_ptr(pair.second_key)) {
+ ret = copy_key_descriptor_compatcpy(
+ &kpair->second_key, pair.second_key);
+ if (ret != 0) {
+ log_err("Cannot copy second key of the pair\n");
+ kfree(kpair);
+ return ret;
+ }
+ }
+ *ks_pair = kpair;
return 0;
}
#endif
@@ -1859,12 +2090,25 @@ static void dpa_stats_plcr_cnt_compatcpy(struct dpa_stats_cnt_plcr *kprm,
kprm->cnt_sel = uprm->cnt_sel;
}
+
static long dpa_stats_tbl_cnt_compatcpy(struct dpa_stats_cnt_classif_tbl *kprm,
struct dpa_stats_compat_cnt_classif_tbl *uprm)
{
kprm->td = uprm->td;
kprm->cnt_sel = uprm->cnt_sel;
- return copy_key_descriptor_compatcpy(&kprm->key, &uprm->key);
+ /* If different than NULL, it will be overwritten */
+ kprm->key = compat_ptr(uprm->key);
+
+ if (compat_ptr(uprm->key)) {
+ /* Allocate memory for kernel-space key descriptor */
+ kprm->key = kmalloc(sizeof(*kprm->key), GFP_KERNEL);
+ if (!kprm->key) {
+ log_err("Cannot allocate memory for key descriptor\n");
+ return -ENOMEM;
+ }
+ return copy_key_descriptor_compatcpy(&kprm->key, uprm->key);
+ }
+ return 0;
}
static long dpa_stats_ccnode_cnt_compatcpy(
@@ -1874,7 +2118,19 @@ static long dpa_stats_ccnode_cnt_compatcpy(
kprm->cnt_sel = uprm->cnt_sel;
kprm->ccnode_type = uprm->ccnode_type;
kprm->cc_node = compat_get_id2ptr(uprm->cc_node, FM_MAP_TYPE_PCD_NODE);
- return copy_key_descriptor_compatcpy(&kprm->key, &uprm->key);
+ /* If different than NULL, it will be overwritten */
+ kprm->key = compat_ptr(uprm->key);
+
+ if (compat_ptr(uprm->key)) {
+ /* Allocate memory for kernel-space key descriptor */
+ kprm->key = kmalloc(sizeof(*kprm->key), GFP_KERNEL);
+ if (!kprm->key) {
+ log_err("Cannot allocate memory for key descriptor\n");
+ return -ENOMEM;
+ }
+ return copy_key_descriptor_compatcpy(&kprm->key, uprm->key);
+ }
+ return 0;
}
static long dpa_stats_eth_cls_compatcpy(struct dpa_stats_cls_cnt_eth *kprm,
@@ -2016,102 +2272,117 @@ static long dpa_stats_tbl_cls_compatcpy(
struct dpa_stats_compat_cls_cnt_classif_tbl *uprm,
uint32_t cls_members)
{
- struct compat_ioc_dpa_offld_lookup_key *keys;
- struct compat_ioc_dpa_offld_lookup_key_pair *pairs;
- uint32_t size = 0, i;
+ struct compat_ioc_dpa_offld_lookup_key_pair pair;
+ compat_uptr_t *us_keys;
+ uint32_t i;
long ret;
kprm->cnt_sel = uprm->cnt_sel;
kprm->td = uprm->td;
kprm->key_type = uprm->key_type;
+ /* Allocate memory to store array of user-space keys descriptors */
+ us_keys = kzalloc(sizeof(compat_uptr_t) * cls_members, GFP_KERNEL);
+ if (!us_keys) {
+ log_err("Cannot allocate memory array of lookup keys\n");
+ return -ENOMEM;
+ }
+
if (kprm->key_type == DPA_STATS_CLASSIF_SINGLE_KEY) {
- size = sizeof(struct dpa_offload_lookup_key) * cls_members;
- kprm->keys = kzalloc(size, GFP_KERNEL);
- if (!kprm->keys) {
- log_err("Cannot allocate kernel memory for lookup keys "
- "array\n");
- return -ENOMEM;
+ if (copy_from_user(us_keys, compat_ptr(uprm->keys),
+ (sizeof(compat_uptr_t) * cls_members))) {
+ log_err("Cannot copy from user-space array of keys "
+ "descriptors\n");
+ kfree(us_keys);
+ return -EBUSY;
}
- size = sizeof(struct compat_ioc_dpa_offld_lookup_key) *
- cls_members;
- keys = kzalloc(size, GFP_KERNEL);
- if (!keys) {
- log_err("Cannot allocate memory for lookup keys "
+ /* Allocate memory for array of kernel-space keys descriptors */
+ kprm->keys = kzalloc((sizeof(*kprm->keys) * cls_members),
+ GFP_KERNEL);
+ if (!kprm->keys) {
+ log_err("Cannot allocate kernel memory for lookup keys "
"array\n");
+ kfree(us_keys);
return -ENOMEM;
}
-
- if (copy_from_user(keys, (compat_ptr)(uprm->keys), size)) {
- log_err("Cannot copy from user array of lookup keys\n");
- kfree(keys);
- return -EBUSY;
- }
-
for (i = 0; i < cls_members; i++) {
- if (!compat_ptr(keys[i].byte))
+ if (!compat_ptr(us_keys[i]))
continue;
-
+ /* Copy user-provided key descriptor */
ret = copy_key_descriptor_compatcpy(&kprm->keys[i],
- &keys[i]);
+ us_keys[i]);
if (ret != 0) {
log_err("Cannot copy the key descriptor\n");
- kfree(keys);
- return -EINVAL;
+ kfree(us_keys);
+ return ret;
}
}
- kfree(keys);
- } else if (kprm->key_type == DPA_STATS_CLASSIF_PAIR_KEY) {
- size = sizeof(struct dpa_offload_lookup_key_pair) * cls_members;
- kprm->pairs = kzalloc(size, GFP_KERNEL);
- if (!kprm->pairs) {
- log_err("Cannot allocate kernel memory for pair lookup "
- "keys array\n");
- return -ENOMEM;
+ kfree(us_keys);
+ }
+
+ if (kprm->key_type == DPA_STATS_CLASSIF_PAIR_KEY) {
+ if (copy_from_user(us_keys, compat_ptr(uprm->pairs),
+ (sizeof(compat_uptr_t) * cls_members))) {
+ log_err("Cannot copy from user-space array of pairs "
+ "descriptors\n");
+ kfree(us_keys);
+ return -EBUSY;
}
- size = sizeof(struct compat_ioc_dpa_offld_lookup_key_pair) *
- cls_members;
- pairs = kzalloc(size, GFP_KERNEL);
- if (!pairs) {
- log_err("Cannot allocate memory for pair lookup keys "
+ /* Allocate memory for array of kernel-space pairs descriptors*/
+ kprm->pairs = kzalloc((sizeof(*kprm->pairs) * cls_members),
+ GFP_KERNEL);
+ if (!kprm->pairs) {
+ log_err("Cannot allocate kernel memory for lookup pairs"
"array\n");
+ kfree(us_keys);
return -ENOMEM;
}
- if (copy_from_user(pairs, (compat_ptr)(uprm->pairs), size)) {
- log_err("Cannot copy from user array of pair lookup "
- "keys\n");
- kfree(pairs);
- return -EBUSY;
- }
-
for (i = 0; i < cls_members; i++) {
- if (!compat_ptr(pairs[i].first_key.byte))
+ if (!compat_ptr(us_keys[i]))
continue;
- ret = copy_key_descriptor_compatcpy(
- &kprm->pairs[i].first_key,
- &pairs[i].first_key);
- if (ret != 0) {
- log_err("Cannot copy the key descriptor for the"
- " first lookup key\n");
- kfree(pairs);
- return -EINVAL;
+ /* Allocate memory for kernel pair descriptor */
+ kprm->pairs[i] = kzalloc(sizeof(*kprm->pairs[i]),
+ GFP_KERNEL);
+ if (!kprm->pairs[i]) {
+ log_err("Cannot allocate kernel memory for pair"
+ " descriptor\n");
+ return -ENOMEM;
}
- ret = copy_key_descriptor_compatcpy(
- &kprm->pairs[i].second_key,
- &pairs[i].second_key);
- if (ret != 0) {
- log_err("Cannot copy the key descriptor for the"
- " second lookup key\n", uprm->td);
- kfree(pairs);
- return -EINVAL;
+ if (copy_from_user(&pair, compat_ptr(us_keys[i]),
+ (sizeof(pair)))) {
+ log_err("Cannot copy pair descriptor\n");
+ return -EBUSY;
+ }
+
+ if (compat_ptr(pair.first_key)) {
+ /* Copy user-provided first key descriptor */
+ ret = copy_key_descriptor_compatcpy(
+ &kprm->pairs[i]->first_key,
+ pair.first_key);
+ if (ret != 0) {
+ log_err("Cannot copy first key\n");
+ kfree(us_keys);
+ return ret;
+ }
+ }
+
+ if (compat_ptr(pair.second_key)) {
+ /* Copy user-provided second key descriptor */
+ ret = copy_key_descriptor_compatcpy(
+ &kprm->pairs[i]->second_key,
+ pair.second_key);
+ if (ret != 0) {
+ log_err("Cannot copy second key\n");
+ kfree(us_keys);
+ return ret;
+ }
}
}
- kfree(pairs);
}
return 0;
}
@@ -2121,45 +2392,50 @@ static long dpa_stats_ccnode_cls_compatcpy(
struct dpa_stats_compat_cls_cnt_classif_node *uprm,
uint32_t cls_members)
{
- struct compat_ioc_dpa_offld_lookup_key *keys;
- uint32_t size, i;
+ compat_uptr_t *us_keys;
+ uint32_t i;
long ret = 0;
kprm->cc_node = compat_get_id2ptr(uprm->cc_node, FM_MAP_TYPE_PCD_NODE);
kprm->cnt_sel = uprm->cnt_sel;
kprm->ccnode_type = uprm->ccnode_type;
- size = sizeof(struct dpa_offload_lookup_key) * cls_members;
- kprm->keys = kzalloc(size, GFP_KERNEL);
- if (!kprm->keys) {
- log_err("Cannot allocate kernel memory for lookup keys "
- "array\n");
+ /* Allocate memory to store array of user-space keys descriptors */
+ us_keys = kzalloc(sizeof(compat_uptr_t) * cls_members, GFP_KERNEL);
+ if (!us_keys) {
+ log_err("Cannot allocate memory array of lookup keys\n");
return -ENOMEM;
}
- size = sizeof(struct compat_ioc_dpa_offld_lookup_key) * cls_members;
- keys = kzalloc(size, GFP_KERNEL);
- if (!keys) {
- log_err("Cannot allocate memory for lookup keys array\n");
- return -ENOMEM;
- }
-
- if (copy_from_user(keys, (compat_ptr)(uprm->keys), size)) {
- log_err("Cannot copy from user array of lookup keys\n");
- kfree(keys);
+ if (copy_from_user(us_keys, compat_ptr(uprm->keys),
+ (sizeof(compat_uptr_t) * cls_members))) {
+ log_err("Cannot copy from user-space array of keys "
+ "descriptors\n");
+ kfree(us_keys);
return -EBUSY;
}
+ /* Allocate memory to store array of kernel-space keys descriptors */
+ kprm->keys = kzalloc((sizeof(*kprm->keys) * cls_members), GFP_KERNEL);
+ if (!kprm->keys) {
+ log_err("Cannot allocate kernel memory for lookup keys "
+ "array\n");
+ kfree(us_keys);
+ return -ENOMEM;
+ }
for (i = 0; i < cls_members; i++) {
- ret = copy_key_descriptor_compatcpy(&kprm->keys[i], &keys[i]);
+ if (!compat_ptr(us_keys[i]))
+ continue;
+ /* Copy user-provided key descriptor */
+ ret = copy_key_descriptor_compatcpy(&kprm->keys[i], us_keys[i]);
if (ret != 0) {
log_err("Cannot copy the key descriptor\n");
- kfree(keys);
- return -EINVAL;
+ kfree(us_keys);
+ return ret;
}
}
- kfree(keys);
- return ret;
+ kfree(us_keys);
+ return 0;
}
static long dpa_stats_ipsec_cls_compatcpy(struct dpa_stats_cls_cnt_ipsec *kprm,