diff options
author | J. German Rivera <Jose.G.Rivera@freescale.com> | 2013-09-07 18:15:43 (GMT) |
---|---|---|
committer | J. German Rivera <German.Rivera@freescale.com> | 2013-09-07 18:15:43 (GMT) |
commit | 78f1554f2ac9a8a3dd622fa49f4623cddba9e036 (patch) | |
tree | b488208f99a90f1966ba8d7803cd5ddcc287a1fa /drivers/staging | |
parent | 188c08c4064ffc2fa303b8512a673016d1d4071c (diff) | |
parent | db651a6e8e0df939cb977a8799816c04b07506c3 (diff) | |
download | linux-fsl-qoriq-78f1554f2ac9a8a3dd622fa49f4623cddba9e036.tar.xz |
Merge branch 'sdk-v1.4.x' into sdk-kernel-3.8
Conflicts temporarily resolved for:
drivers/net/ethernet/freescale/dpa/dpaa_eth.c
Permanent solution needs to be provided by the author of
commit ec6aa025.
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/fsl_dpa_offload/dpa_stats.c | 262 | ||||
-rw-r--r-- | drivers/staging/fsl_dpa_offload/dpa_stats.h | 1 | ||||
-rw-r--r-- | drivers/staging/fsl_dpa_offload/dpa_stats_ioctl.h | 12 | ||||
-rw-r--r-- | drivers/staging/fsl_dpa_offload/wrp_dpa_stats.c | 81 | ||||
-rw-r--r-- | drivers/staging/fsl_dpa_offload/wrp_dpa_stats.h | 23 |
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 { |