From 8e5eb432c74d1342396af35601cb3414a590d5d2 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Thu, 15 Jun 2017 15:39:04 +0530 Subject: [PATCH] msm:ipa: Fix to incorrect structure access Accessing of incorrect structure pointer is causing memory out of bound access, fixed issue by accessing the correct structure pointer. Change-Id: I3c2f5f7a97cac854093ef670184d06db4231f5e1 Acked-by: Ashok Vuyyuru Signed-off-by: Mohammed Javid --- drivers/platform/msm/ipa/ipa_v2/ipa_flt.c | 18 ++++++---- drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c | 39 +++++++++++++++------ drivers/platform/msm/ipa/ipa_v2/ipa_i.h | 18 +++++++--- drivers/platform/msm/ipa/ipa_v2/ipa_rt.c | 37 +++++++++++++------- drivers/platform/msm/ipa/ipa_v3/ipa_flt.c | 35 +++++++++++++++---- drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c | 37 +++++++++++++++----- drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 16 ++++++--- drivers/platform/msm/ipa/ipa_v3/ipa_rt.c | 41 ++++++++++++++--------- 8 files changed, 170 insertions(+), 71 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c index 80514f6c738e..b7f451b7c6fd 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c @@ -1027,7 +1027,7 @@ static int __ipa_add_flt_rule(struct ipa_flt_tbl *tbl, enum ipa_ip_type ip, goto error; } - if (rt_tbl->cookie != IPA_COOKIE) { + if (rt_tbl->cookie != IPA_RT_TBL_COOKIE) { IPAERR("RT table cookie is invalid\n"); goto error; } @@ -1048,7 +1048,7 @@ static int __ipa_add_flt_rule(struct ipa_flt_tbl *tbl, enum ipa_ip_type ip, } INIT_LIST_HEAD(&entry->link); entry->rule = *rule; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_FLT_COOKIE; entry->rt_tbl = rt_tbl; entry->tbl = tbl; if (add_rear) { @@ -1067,13 +1067,19 @@ static int __ipa_add_flt_rule(struct ipa_flt_tbl *tbl, enum ipa_ip_type ip, if (id < 0) { IPAERR("failed to add to tree\n"); WARN_ON(1); + goto ipa_insert_failed; } *rule_hdl = id; entry->id = id; IPADBG_LOW("add flt rule rule_cnt=%d\n", tbl->rule_cnt); return 0; - +ipa_insert_failed: + tbl->rule_cnt--; + if (entry->rt_tbl) + entry->rt_tbl->ref_cnt--; + list_del(&entry->link); + kmem_cache_free(ipa_ctx->flt_rule_cache, entry); error: return -EPERM; } @@ -1089,7 +1095,7 @@ static int __ipa_del_flt_rule(u32 rule_hdl) return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_FLT_COOKIE) { IPAERR("bad params\n"); return -EINVAL; } @@ -1121,7 +1127,7 @@ static int __ipa_mdfy_flt_rule(struct ipa_flt_rule_mdfy *frule, goto error; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_FLT_COOKIE) { IPAERR("bad params\n"); goto error; } @@ -1142,7 +1148,7 @@ static int __ipa_mdfy_flt_rule(struct ipa_flt_rule_mdfy *frule, goto error; } - if (rt_tbl->cookie != IPA_COOKIE) { + if (rt_tbl->cookie != IPA_RT_TBL_COOKIE) { IPAERR("RT table cookie is invalid\n"); goto error; } diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c index 10a49b1e75d8..75e4ff5c3c57 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c @@ -547,7 +547,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, { struct ipa_hdr_entry *hdr_entry; struct ipa_hdr_proc_ctx_entry *entry; - struct ipa_hdr_proc_ctx_offset_entry *offset; + struct ipa_hdr_proc_ctx_offset_entry *offset = NULL; u32 bin; struct ipa_hdr_proc_ctx_tbl *htbl = &ipa_ctx->hdr_proc_ctx_tbl; int id; @@ -563,7 +563,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, } hdr_entry = ipa_id_find(proc_ctx->hdr_hdl); - if (!hdr_entry || (hdr_entry->cookie != IPA_COOKIE)) { + if (!hdr_entry || (hdr_entry->cookie != IPA_HDR_COOKIE)) { IPAERR("hdr_hdl is invalid\n"); return -EINVAL; } @@ -580,7 +580,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, entry->hdr = hdr_entry; if (add_ref_hdr) hdr_entry->ref_cnt++; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_PROC_HDR_COOKIE; needed_len = (proc_ctx->type == IPA_HDR_PROC_NONE) ? sizeof(struct ipa_hdr_proc_ctx_add_hdr_seq) : @@ -640,6 +640,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, if (id < 0) { IPAERR("failed to alloc id\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; proc_ctx->proc_ctx_hdl = id; @@ -647,6 +648,14 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, return 0; +ipa_insert_failed: + if (offset) + list_move(&offset->link, + &htbl->head_free_offset_list[offset->bin]); + entry->offset_entry = NULL; + list_del(&entry->link); + htbl->proc_ctx_cnt--; + bad_len: if (add_ref_hdr) hdr_entry->ref_cnt--; @@ -659,7 +668,7 @@ bad_len: static int __ipa_add_hdr(struct ipa_hdr_add *hdr) { struct ipa_hdr_entry *entry; - struct ipa_hdr_offset_entry *offset; + struct ipa_hdr_offset_entry *offset = NULL; u32 bin; struct ipa_hdr_tbl *htbl = &ipa_ctx->hdr_tbl; int id; @@ -691,7 +700,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) entry->type = hdr->type; entry->is_eth2_ofst_valid = hdr->is_eth2_ofst_valid; entry->eth2_ofst = hdr->eth2_ofst; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_HDR_COOKIE; if (hdr->hdr_len <= ipa_hdr_bin_sz[IPA_HDR_BIN0]) bin = IPA_HDR_BIN0; @@ -780,6 +789,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) if (id < 0) { IPAERR("failed to alloc id\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; hdr->hdr_hdl = id; @@ -804,10 +814,19 @@ fail_add_proc_ctx: entry->ref_cnt--; hdr->hdr_hdl = 0; ipa_id_remove(id); +ipa_insert_failed: + if (entry->is_hdr_proc_ctx) { + dma_unmap_single(ipa_ctx->pdev, entry->phys_base, + entry->hdr_len, DMA_TO_DEVICE); + } else { + if (offset) + list_move(&offset->link, + &htbl->head_free_offset_list[offset->bin]); + entry->offset_entry = NULL; + } htbl->hdr_cnt--; list_del(&entry->link); - dma_unmap_single(ipa_ctx->pdev, entry->phys_base, - entry->hdr_len, DMA_TO_DEVICE); + fail_dma_mapping: entry->is_hdr_proc_ctx = false; bad_hdr_len: @@ -824,7 +843,7 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, struct ipa_hdr_proc_ctx_tbl *htbl = &ipa_ctx->hdr_proc_ctx_tbl; entry = ipa_id_find(proc_ctx_hdl); - if (!entry || (entry->cookie != IPA_COOKIE)) { + if (!entry || (entry->cookie != IPA_PROC_HDR_COOKIE)) { IPAERR("bad parm\n"); return -EINVAL; } @@ -875,7 +894,7 @@ int __ipa_del_hdr(u32 hdr_hdl, bool by_user) return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_HDR_COOKIE) { IPAERR("bad parm\n"); return -EINVAL; } @@ -1444,7 +1463,7 @@ int ipa2_put_hdr(u32 hdr_hdl) goto bail; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_HDR_COOKIE) { IPAERR("invalid header entry\n"); result = -EINVAL; goto bail; diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h index bb11230c960a..70b2a2eeb53f 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h @@ -37,7 +37,15 @@ #define DRV_NAME "ipa" #define NAT_DEV_NAME "ipaNatTable" + #define IPA_COOKIE 0x57831603 +#define IPA_RT_RULE_COOKIE 0x57831604 +#define IPA_RT_TBL_COOKIE 0x57831605 +#define IPA_FLT_COOKIE 0x57831606 +#define IPA_HDR_COOKIE 0x57831607 +#define IPA_PROC_HDR_COOKIE 0x57831608 + + #define MTU_BYTE 1500 #define IPA_MAX_NUM_PIPES 0x14 @@ -223,8 +231,8 @@ struct ipa_smmu_cb_ctx { */ struct ipa_flt_entry { struct list_head link; - struct ipa_flt_rule rule; u32 cookie; + struct ipa_flt_rule rule; struct ipa_flt_tbl *tbl; struct ipa_rt_tbl *rt_tbl; u32 hw_len; @@ -249,13 +257,13 @@ struct ipa_flt_entry { */ struct ipa_rt_tbl { struct list_head link; + u32 cookie; struct list_head head_rt_rule_list; char name[IPA_RESOURCE_NAME_MAX]; u32 idx; u32 rule_cnt; u32 ref_cnt; struct ipa_rt_tbl_set *set; - u32 cookie; bool in_sys; u32 sz; struct ipa_mem_buffer curr_mem; @@ -286,6 +294,7 @@ struct ipa_rt_tbl { */ struct ipa_hdr_entry { struct list_head link; + u32 cookie; u8 hdr[IPA_HDR_MAX_SIZE]; u32 hdr_len; char name[IPA_RESOURCE_NAME_MAX]; @@ -295,7 +304,6 @@ struct ipa_hdr_entry { dma_addr_t phys_base; struct ipa_hdr_proc_ctx_entry *proc_ctx; struct ipa_hdr_offset_entry *offset_entry; - u32 cookie; u32 ref_cnt; int id; u8 is_eth2_ofst_valid; @@ -368,10 +376,10 @@ struct ipa_hdr_proc_ctx_add_hdr_cmd_seq { */ struct ipa_hdr_proc_ctx_entry { struct list_head link; + u32 cookie; enum ipa_hdr_proc_type type; struct ipa_hdr_proc_ctx_offset_entry *offset_entry; struct ipa_hdr_entry *hdr; - u32 cookie; u32 ref_cnt; int id; bool user_deleted; @@ -427,8 +435,8 @@ struct ipa_flt_tbl { */ struct ipa_rt_entry { struct list_head link; - struct ipa_rt_rule rule; u32 cookie; + struct ipa_rt_rule rule; struct ipa_rt_tbl *tbl; struct ipa_hdr_entry *hdr; struct ipa_hdr_proc_ctx_entry *proc_ctx; diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c index f2909110d09f..9ac7b3809895 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c @@ -909,7 +909,7 @@ static struct ipa_rt_tbl *__ipa_add_rt_tbl(enum ipa_ip_type ip, INIT_LIST_HEAD(&entry->link); strlcpy(entry->name, name, IPA_RESOURCE_NAME_MAX); entry->set = set; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_RT_TBL_COOKIE; entry->in_sys = (ip == IPA_IP_v4) ? !ipa_ctx->ip4_rt_tbl_lcl : !ipa_ctx->ip6_rt_tbl_lcl; set->tbl_cnt++; @@ -922,12 +922,16 @@ static struct ipa_rt_tbl *__ipa_add_rt_tbl(enum ipa_ip_type ip, if (id < 0) { IPAERR("failed to add to tree\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; } return entry; +ipa_insert_failed: + set->tbl_cnt--; + list_del(&entry->link); fail_rt_idx_alloc: entry->cookie = 0; kmem_cache_free(ipa_ctx->rt_tbl_cache, entry); @@ -940,7 +944,7 @@ static int __ipa_del_rt_tbl(struct ipa_rt_tbl *entry) enum ipa_ip_type ip = IPA_IP_MAX; u32 id; - if (entry == NULL || (entry->cookie != IPA_COOKIE)) { + if (entry == NULL || (entry->cookie != IPA_RT_TBL_COOKIE)) { IPAERR("bad parms\n"); return -EINVAL; } @@ -954,8 +958,11 @@ static int __ipa_del_rt_tbl(struct ipa_rt_tbl *entry) ip = IPA_IP_v4; else if (entry->set == &ipa_ctx->rt_tbl_set[IPA_IP_v6]) ip = IPA_IP_v6; - else + else { WARN_ON(1); + return -EPERM; + } + if (!entry->in_sys) { list_del(&entry->link); @@ -994,13 +1001,14 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, if (rule->hdr_hdl) { hdr = ipa_id_find(rule->hdr_hdl); - if ((hdr == NULL) || (hdr->cookie != IPA_COOKIE)) { + if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) { IPAERR("rt rule does not point to valid hdr\n"); goto error; } } else if (rule->hdr_proc_ctx_hdl) { proc_ctx = ipa_id_find(rule->hdr_proc_ctx_hdl); - if ((proc_ctx == NULL) || (proc_ctx->cookie != IPA_COOKIE)) { + if ((proc_ctx == NULL) || + (proc_ctx->cookie != IPA_PROC_HDR_COOKIE)) { IPAERR("rt rule does not point to valid proc ctx\n"); goto error; } @@ -1008,7 +1016,7 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, tbl = __ipa_add_rt_tbl(ip, name); - if (tbl == NULL || (tbl->cookie != IPA_COOKIE)) { + if (tbl == NULL || (tbl->cookie != IPA_RT_TBL_COOKIE)) { IPAERR("bad params\n"); goto error; } @@ -1029,7 +1037,7 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, goto error; } INIT_LIST_HEAD(&entry->link); - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_RT_RULE_COOKIE; entry->rule = *rule; entry->tbl = tbl; entry->hdr = hdr; @@ -1123,7 +1131,7 @@ int __ipa_del_rt_rule(u32 rule_hdl) return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_RT_RULE_COOKIE) { IPAERR("bad params\n"); return -EINVAL; } @@ -1358,7 +1366,7 @@ int ipa2_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup) } mutex_lock(&ipa_ctx->lock); entry = __ipa_find_rt_tbl(lookup->ip, lookup->name); - if (entry && entry->cookie == IPA_COOKIE) { + if (entry && entry->cookie == IPA_RT_TBL_COOKIE) { if (entry->ref_cnt == U32_MAX) { IPAERR("fail: ref count crossed limit\n"); goto ret; @@ -1401,7 +1409,7 @@ int ipa2_put_rt_tbl(u32 rt_tbl_hdl) goto ret; } - if ((entry->cookie != IPA_COOKIE) || entry->ref_cnt == 0) { + if ((entry->cookie != IPA_RT_TBL_COOKIE) || entry->ref_cnt == 0) { IPAERR("bad parms\n"); result = -EINVAL; goto ret; @@ -1411,8 +1419,11 @@ int ipa2_put_rt_tbl(u32 rt_tbl_hdl) ip = IPA_IP_v4; else if (entry->set == &ipa_ctx->rt_tbl_set[IPA_IP_v6]) ip = IPA_IP_v6; - else + else { WARN_ON(1); + result = -EINVAL; + goto ret; + } entry->ref_cnt--; if (entry->ref_cnt == 0 && entry->rule_cnt == 0) { @@ -1439,7 +1450,7 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) if (rtrule->rule.hdr_hdl) { hdr = ipa_id_find(rtrule->rule.hdr_hdl); - if ((hdr == NULL) || (hdr->cookie != IPA_COOKIE)) { + if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) { IPAERR("rt rule does not point to valid hdr\n"); goto error; } @@ -1451,7 +1462,7 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) goto error; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_RT_RULE_COOKIE) { IPAERR("bad params\n"); goto error; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c index 41b29335d23b..42632c527bdd 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c @@ -745,7 +745,7 @@ static int __ipa_validate_flt_rule(const struct ipa_flt_rule *rule, goto error; } - if ((*rt_tbl)->cookie != IPA_COOKIE) { + if ((*rt_tbl)->cookie != IPA_RT_TBL_COOKIE) { IPAERR("RT table cookie is invalid\n"); goto error; } @@ -787,7 +787,7 @@ static int __ipa_create_flt_entry(struct ipa3_flt_entry **entry, } INIT_LIST_HEAD(&((*entry)->link)); (*entry)->rule = *rule; - (*entry)->cookie = IPA_COOKIE; + (*entry)->cookie = IPA_FLT_COOKIE; (*entry)->rt_tbl = rt_tbl; (*entry)->tbl = tbl; if (rule->rule_id) { @@ -822,12 +822,18 @@ static int __ipa_finish_flt_rule_add(struct ipa3_flt_tbl *tbl, if (id < 0) { IPAERR("failed to add to tree\n"); WARN_ON(1); + goto ipa_insert_failed; } *rule_hdl = id; entry->id = id; IPADBG_LOW("add flt rule rule_cnt=%d\n", tbl->rule_cnt); return 0; +ipa_insert_failed: + if (entry->rt_tbl) + entry->rt_tbl->ref_cnt--; + tbl->rule_cnt--; + return -EPERM; } static int __ipa_add_flt_rule(struct ipa3_flt_tbl *tbl, enum ipa_ip_type ip, @@ -853,9 +859,16 @@ static int __ipa_add_flt_rule(struct ipa3_flt_tbl *tbl, enum ipa_ip_type ip, list_add(&entry->link, &tbl->head_flt_rule_list); } - __ipa_finish_flt_rule_add(tbl, entry, rule_hdl); + if (__ipa_finish_flt_rule_add(tbl, entry, rule_hdl)) + goto ipa_insert_failed; return 0; +ipa_insert_failed: + list_del(&entry->link); + /* if rule id was allocated from idr, remove it */ + if (!(entry->rule_id & ipahal_get_rule_id_hi_bit())) + idr_remove(&entry->tbl->rule_ids, entry->rule_id); + kmem_cache_free(ipa3_ctx->flt_rule_cache, entry); error: return -EPERM; @@ -887,7 +900,8 @@ static int __ipa_add_flt_rule_after(struct ipa3_flt_tbl *tbl, list_add(&entry->link, &((*add_after_entry)->link)); - __ipa_finish_flt_rule_add(tbl, entry, rule_hdl); + if (__ipa_finish_flt_rule_add(tbl, entry, rule_hdl)) + goto ipa_insert_failed; /* * prepare for next insertion @@ -896,6 +910,13 @@ static int __ipa_add_flt_rule_after(struct ipa3_flt_tbl *tbl, return 0; +ipa_insert_failed: + list_del(&entry->link); + /* if rule id was allocated from idr, remove it */ + if (!(entry->rule_id & ipahal_get_rule_id_hi_bit())) + idr_remove(&entry->tbl->rule_ids, entry->rule_id); + kmem_cache_free(ipa3_ctx->flt_rule_cache, entry); + error: *add_after_entry = NULL; return -EPERM; @@ -912,7 +933,7 @@ static int __ipa_del_flt_rule(u32 rule_hdl) return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_FLT_COOKIE) { IPAERR("bad params\n"); return -EINVAL; } @@ -949,7 +970,7 @@ static int __ipa_mdfy_flt_rule(struct ipa_flt_rule_mdfy *frule, goto error; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_FLT_COOKIE) { IPAERR("bad params\n"); goto error; } @@ -970,7 +991,7 @@ static int __ipa_mdfy_flt_rule(struct ipa_flt_rule_mdfy *frule, goto error; } - if (rt_tbl->cookie != IPA_COOKIE) { + if (rt_tbl->cookie != IPA_RT_TBL_COOKIE) { IPAERR("RT table cookie is invalid\n"); goto error; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c index a5186f1aff35..34bc7dcd63cf 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c @@ -339,7 +339,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, IPAERR("hdr_hdl is invalid\n"); return -EINVAL; } - if (hdr_entry->cookie != IPA_COOKIE) { + if (hdr_entry->cookie != IPA_HDR_COOKIE) { IPAERR("Invalid header cookie %u\n", hdr_entry->cookie); WARN_ON(1); return -EINVAL; @@ -359,7 +359,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, entry->hdr = hdr_entry; if (add_ref_hdr) hdr_entry->ref_cnt++; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_HDR_COOKIE; needed_len = ipahal_get_proc_ctx_needed_len(proc_ctx->type); @@ -417,6 +417,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, if (id < 0) { IPAERR("failed to alloc id\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; proc_ctx->proc_ctx_hdl = id; @@ -424,6 +425,14 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, return 0; +ipa_insert_failed: + if (offset) + list_move(&offset->link, + &htbl->head_free_offset_list[offset->bin]); + entry->offset_entry = NULL; + list_del(&entry->link); + htbl->proc_ctx_cnt--; + bad_len: if (add_ref_hdr) hdr_entry->ref_cnt--; @@ -436,7 +445,7 @@ bad_len: static int __ipa_add_hdr(struct ipa_hdr_add *hdr) { struct ipa3_hdr_entry *entry; - struct ipa_hdr_offset_entry *offset; + struct ipa_hdr_offset_entry *offset = NULL; u32 bin; struct ipa3_hdr_tbl *htbl = &ipa3_ctx->hdr_tbl; int id; @@ -467,7 +476,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) entry->type = hdr->type; entry->is_eth2_ofst_valid = hdr->is_eth2_ofst_valid; entry->eth2_ofst = hdr->eth2_ofst; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_HDR_COOKIE; if (hdr->hdr_len <= ipa_hdr_bin_sz[IPA_HDR_BIN0]) bin = IPA_HDR_BIN0; @@ -546,6 +555,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) if (id < 0) { IPAERR("failed to alloc id\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; hdr->hdr_hdl = id; @@ -570,10 +580,19 @@ fail_add_proc_ctx: entry->ref_cnt--; hdr->hdr_hdl = 0; ipa3_id_remove(id); +ipa_insert_failed: + if (entry->is_hdr_proc_ctx) { + dma_unmap_single(ipa3_ctx->pdev, entry->phys_base, + entry->hdr_len, DMA_TO_DEVICE); + } else { + if (offset) + list_move(&offset->link, + &htbl->head_free_offset_list[offset->bin]); + entry->offset_entry = NULL; + } htbl->hdr_cnt--; list_del(&entry->link); - dma_unmap_single(ipa3_ctx->pdev, entry->phys_base, - entry->hdr_len, DMA_TO_DEVICE); + fail_dma_mapping: entry->is_hdr_proc_ctx = false; @@ -591,7 +610,7 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, struct ipa3_hdr_proc_ctx_tbl *htbl = &ipa3_ctx->hdr_proc_ctx_tbl; entry = ipa3_id_find(proc_ctx_hdl); - if (!entry || (entry->cookie != IPA_COOKIE)) { + if (!entry || (entry->cookie != IPA_HDR_COOKIE)) { IPAERR("bad parm\n"); return -EINVAL; } @@ -642,7 +661,7 @@ int __ipa3_del_hdr(u32 hdr_hdl, bool by_user) return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_HDR_COOKIE) { IPAERR("bad parm\n"); return -EINVAL; } @@ -1188,7 +1207,7 @@ int ipa3_put_hdr(u32 hdr_hdl) goto bail; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_HDR_COOKIE) { IPAERR("invalid header entry\n"); result = -EINVAL; goto bail; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index ac7ef6a21952..cbc53fb6815d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -40,6 +40,12 @@ #define DRV_NAME "ipa" #define NAT_DEV_NAME "ipaNatTable" #define IPA_COOKIE 0x57831603 +#define IPA_RT_RULE_COOKIE 0x57831604 +#define IPA_RT_TBL_COOKIE 0x57831605 +#define IPA_FLT_COOKIE 0x57831606 +#define IPA_HDR_COOKIE 0x57831607 +#define IPA_PROC_HDR_COOKIE 0x57831608 + #define MTU_BYTE 1500 #define IPA_EP_NOT_ALLOCATED (-1) @@ -217,8 +223,8 @@ struct ipa_smmu_cb_ctx { */ struct ipa3_flt_entry { struct list_head link; - struct ipa_flt_rule rule; u32 cookie; + struct ipa_flt_rule rule; struct ipa3_flt_tbl *tbl; struct ipa3_rt_tbl *rt_tbl; u32 hw_len; @@ -246,13 +252,13 @@ struct ipa3_flt_entry { */ struct ipa3_rt_tbl { struct list_head link; + u32 cookie; struct list_head head_rt_rule_list; char name[IPA_RESOURCE_NAME_MAX]; u32 idx; u32 rule_cnt; u32 ref_cnt; struct ipa3_rt_tbl_set *set; - u32 cookie; bool in_sys[IPA_RULE_TYPE_MAX]; u32 sz[IPA_RULE_TYPE_MAX]; struct ipa_mem_buffer curr_mem[IPA_RULE_TYPE_MAX]; @@ -284,6 +290,7 @@ struct ipa3_rt_tbl { */ struct ipa3_hdr_entry { struct list_head link; + u32 cookie; u8 hdr[IPA_HDR_MAX_SIZE]; u32 hdr_len; char name[IPA_RESOURCE_NAME_MAX]; @@ -293,7 +300,6 @@ struct ipa3_hdr_entry { dma_addr_t phys_base; struct ipa3_hdr_proc_ctx_entry *proc_ctx; struct ipa_hdr_offset_entry *offset_entry; - u32 cookie; u32 ref_cnt; int id; u8 is_eth2_ofst_valid; @@ -342,10 +348,10 @@ struct ipa3_hdr_proc_ctx_offset_entry { */ struct ipa3_hdr_proc_ctx_entry { struct list_head link; + u32 cookie; enum ipa_hdr_proc_type type; struct ipa3_hdr_proc_ctx_offset_entry *offset_entry; struct ipa3_hdr_entry *hdr; - u32 cookie; u32 ref_cnt; int id; bool user_deleted; @@ -407,8 +413,8 @@ struct ipa3_flt_tbl { */ struct ipa3_rt_entry { struct list_head link; - struct ipa_rt_rule rule; u32 cookie; + struct ipa_rt_rule rule; struct ipa3_rt_tbl *tbl; struct ipa3_hdr_entry *hdr; struct ipa3_hdr_proc_ctx_entry *proc_ctx; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c index 6197c9f64ca5..2ade584890fb 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c @@ -796,7 +796,7 @@ static struct ipa3_rt_tbl *__ipa_add_rt_tbl(enum ipa_ip_type ip, INIT_LIST_HEAD(&entry->link); strlcpy(entry->name, name, IPA_RESOURCE_NAME_MAX); entry->set = set; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_RT_TBL_COOKIE; entry->in_sys[IPA_RULE_HASHABLE] = (ip == IPA_IP_v4) ? !ipa3_ctx->ip4_rt_tbl_hash_lcl : !ipa3_ctx->ip6_rt_tbl_hash_lcl; @@ -814,12 +814,16 @@ static struct ipa3_rt_tbl *__ipa_add_rt_tbl(enum ipa_ip_type ip, if (id < 0) { IPAERR("failed to add to tree\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; } return entry; - +ipa_insert_failed: + set->tbl_cnt--; + list_del(&entry->link); + idr_destroy(&entry->rule_ids); fail_rt_idx_alloc: entry->cookie = 0; kmem_cache_free(ipa3_ctx->rt_tbl_cache, entry); @@ -833,7 +837,7 @@ static int __ipa_del_rt_tbl(struct ipa3_rt_tbl *entry) u32 id; struct ipa3_rt_tbl_set *rset; - if (entry == NULL || (entry->cookie != IPA_COOKIE)) { + if (entry == NULL || (entry->cookie != IPA_RT_TBL_COOKIE)) { IPAERR("bad parms\n"); return -EINVAL; } @@ -847,8 +851,10 @@ static int __ipa_del_rt_tbl(struct ipa3_rt_tbl *entry) ip = IPA_IP_v4; else if (entry->set == &ipa3_ctx->rt_tbl_set[IPA_IP_v6]) ip = IPA_IP_v6; - else + else { WARN_ON(1); + return -EPERM; + } rset = &ipa3_ctx->reap_rt_tbl_set[ip]; @@ -885,14 +891,14 @@ static int __ipa_rt_validate_hndls(const struct ipa_rt_rule *rule, if (rule->hdr_hdl) { *hdr = ipa3_id_find(rule->hdr_hdl); - if ((*hdr == NULL) || ((*hdr)->cookie != IPA_COOKIE)) { + if ((*hdr == NULL) || ((*hdr)->cookie != IPA_HDR_COOKIE)) { IPAERR("rt rule does not point to valid hdr\n"); return -EPERM; } } else if (rule->hdr_proc_ctx_hdl) { *proc_ctx = ipa3_id_find(rule->hdr_proc_ctx_hdl); if ((*proc_ctx == NULL) || - ((*proc_ctx)->cookie != IPA_COOKIE)) { + ((*proc_ctx)->cookie != IPA_PROC_HDR_COOKIE)) { IPAERR("rt rule does not point to valid proc ctx\n"); return -EPERM; @@ -915,7 +921,7 @@ static int __ipa_create_rt_entry(struct ipa3_rt_entry **entry, goto error; } INIT_LIST_HEAD(&(*entry)->link); - (*(entry))->cookie = IPA_COOKIE; + (*(entry))->cookie = IPA_RT_RULE_COOKIE; (*(entry))->rule = *rule; (*(entry))->tbl = tbl; (*(entry))->hdr = hdr; @@ -983,7 +989,7 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, tbl = __ipa_add_rt_tbl(ip, name); - if (tbl == NULL || (tbl->cookie != IPA_COOKIE)) { + if (tbl == NULL || (tbl->cookie != IPA_RT_TBL_COOKIE)) { IPAERR("failed adding rt tbl name = %s\n", name ? name : ""); goto error; @@ -1118,7 +1124,7 @@ int ipa3_add_rt_rule_after(struct ipa_ioc_add_rt_rule_after *rules) mutex_lock(&ipa3_ctx->lock); tbl = __ipa3_find_rt_tbl(rules->ip, rules->rt_tbl_name); - if (tbl == NULL || (tbl->cookie != IPA_COOKIE)) { + if (tbl == NULL || (tbl->cookie != IPA_RT_TBL_COOKIE)) { IPAERR("failed finding rt tbl name = %s\n", rules->rt_tbl_name ? rules->rt_tbl_name : ""); ret = -EINVAL; @@ -1202,7 +1208,7 @@ int __ipa3_del_rt_rule(u32 rule_hdl) return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_RT_RULE_COOKIE) { IPAERR("bad params\n"); return -EINVAL; } @@ -1440,7 +1446,7 @@ int ipa3_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup) } mutex_lock(&ipa3_ctx->lock); entry = __ipa3_find_rt_tbl(lookup->ip, lookup->name); - if (entry && entry->cookie == IPA_COOKIE) { + if (entry && entry->cookie == IPA_RT_TBL_COOKIE) { if (entry->ref_cnt == U32_MAX) { IPAERR("fail: ref count crossed limit\n"); goto ret; @@ -1483,7 +1489,7 @@ int ipa3_put_rt_tbl(u32 rt_tbl_hdl) goto ret; } - if ((entry->cookie != IPA_COOKIE) || entry->ref_cnt == 0) { + if ((entry->cookie != IPA_RT_TBL_COOKIE) || entry->ref_cnt == 0) { IPAERR("bad parms\n"); result = -EINVAL; goto ret; @@ -1493,8 +1499,10 @@ int ipa3_put_rt_tbl(u32 rt_tbl_hdl) ip = IPA_IP_v4; else if (entry->set == &ipa3_ctx->rt_tbl_set[IPA_IP_v6]) ip = IPA_IP_v6; - else + else { WARN_ON(1); + goto ret; + } entry->ref_cnt--; if (entry->ref_cnt == 0 && entry->rule_cnt == 0) { @@ -1524,13 +1532,14 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) if (rtrule->rule.hdr_hdl) { hdr = ipa3_id_find(rtrule->rule.hdr_hdl); - if ((hdr == NULL) || (hdr->cookie != IPA_COOKIE)) { + if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) { IPAERR("rt rule does not point to valid hdr\n"); goto error; } } else if (rtrule->rule.hdr_proc_ctx_hdl) { proc_ctx = ipa3_id_find(rtrule->rule.hdr_proc_ctx_hdl); - if ((proc_ctx == NULL) || (proc_ctx->cookie != IPA_COOKIE)) { + if ((proc_ctx == NULL) || + (proc_ctx->cookie != IPA_PROC_HDR_COOKIE)) { IPAERR("rt rule does not point to valid proc ctx\n"); goto error; } @@ -1542,7 +1551,7 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) goto error; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_RT_RULE_COOKIE) { IPAERR("bad params\n"); goto error; }