OSDN Git Service

msm: ipa: fix IPA driver processing context delete logic
authorGhanim Fodi <gfodi@codeaurora.org>
Thu, 28 Jul 2016 15:03:56 +0000 (18:03 +0300)
committerGhanim Fodi <gfodi@codeaurora.org>
Tue, 2 Aug 2016 12:20:55 +0000 (15:20 +0300)
During IPA driver processing context delete, a delete to
the referenced header is being done. The header deletion
will also commit the changes to H/W which includes the
processing context commit. This resulted into committing
an invalid process context as it is still in the processing
context list, but points to deleted header.
The fix is to not commit the changes when deleting the header
but only when deleting the processing context.

Change-Id: I9d3c5eec717da0b072144a1027e4582e73aaa6d9
CRs-fixed: 1044710
Signed-off-by: Ghanim Fodi <gfodi@codeaurora.org>
drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
drivers/platform/msm/ipa/ipa_v2/ipa_i.h
drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
drivers/platform/msm/ipa/ipa_v3/ipa_i.h
drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c

index 790a0b4..62e0262 100644 (file)
@@ -581,7 +581,8 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx,
        return 0;
 
 bad_len:
-       hdr_entry->ref_cnt--;
+       if (add_ref_hdr)
+               hdr_entry->ref_cnt--;
        entry->cookie = 0;
        kmem_cache_free(ipa_ctx->hdr_proc_ctx_cache, entry);
        return -EPERM;
@@ -761,7 +762,7 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
        }
 
        if (release_hdr)
-               __ipa_release_hdr(entry->hdr->id);
+               __ipa_del_hdr(entry->hdr->id);
 
        /* move the offset entry to appropriate free list */
        list_move(&entry->offset_entry->link,
@@ -1089,12 +1090,19 @@ int ipa2_reset_hdr(void)
                        &ipa_ctx->hdr_tbl.head_hdr_entry_list, link) {
 
                /* do not remove the default header */
-               if (!strcmp(entry->name, IPA_LAN_RX_HDR_NAME))
+               if (!strcmp(entry->name, IPA_LAN_RX_HDR_NAME)) {
+                       if (entry->is_hdr_proc_ctx) {
+                               mutex_unlock(&ipa_ctx->lock);
+                               WARN_ON(1);
+                               IPAERR("default header is proc ctx\n");
+                               return -EFAULT;
+                       }
                        continue;
+               }
 
                if (ipa_id_find(entry->id) == NULL) {
-                       WARN_ON(1);
                        mutex_unlock(&ipa_ctx->lock);
+                       WARN_ON(1);
                        return -EFAULT;
                }
                if (entry->is_hdr_proc_ctx) {
@@ -1147,8 +1155,8 @@ int ipa2_reset_hdr(void)
                link) {
 
                if (ipa_id_find(ctx_entry->id) == NULL) {
-                       WARN_ON(1);
                        mutex_unlock(&ipa_ctx->lock);
+                       WARN_ON(1);
                        return -EFAULT;
                }
                list_del(&ctx_entry->link);
@@ -1311,8 +1319,8 @@ int ipa2_put_hdr(u32 hdr_hdl)
                goto bail;
        }
 
-       if (entry == NULL || entry->cookie != IPA_COOKIE) {
-               IPAERR("bad params\n");
+       if (entry->cookie != IPA_COOKIE) {
+               IPAERR("invalid header entry\n");
                result = -EINVAL;
                goto bail;
        }
index f94418e..10df305 100644 (file)
@@ -242,7 +242,7 @@ struct ipa_rt_tbl {
  * @is_partial: flag indicating if header table entry is partial
  * @is_hdr_proc_ctx: false - hdr entry resides in hdr table,
  * true - hdr entry resides in DDR and pointed to by proc ctx
- * @phys_base: physical address of entry in SRAM when is_hdr_proc_ctx is true,
+ * @phys_base: physical address of entry in DDR when is_hdr_proc_ctx is true,
  * else 0
  * @proc_ctx: processing context header
  * @offset_entry: entry's offset
index 9d4704d..15476f3 100644 (file)
@@ -1008,6 +1008,10 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name,
        return 0;
 
 ipa_insert_failed:
+       if (entry->hdr)
+               entry->hdr->ref_cnt--;
+       else if (entry->proc_ctx)
+               entry->proc_ctx->ref_cnt--;
        list_del(&entry->link);
        kmem_cache_free(ipa_ctx->rt_rule_cache, entry);
 error:
index 0296472..11da023 100644 (file)
@@ -418,7 +418,8 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx,
        return 0;
 
 bad_len:
-       hdr_entry->ref_cnt--;
+       if (add_ref_hdr)
+               hdr_entry->ref_cnt--;
        entry->cookie = 0;
        kmem_cache_free(ipa3_ctx->hdr_proc_ctx_cache, entry);
        return -EPERM;
@@ -589,7 +590,7 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
        }
 
        if (release_hdr)
-               __ipa3_release_hdr(entry->hdr->id);
+               __ipa3_del_hdr(entry->hdr->id);
 
        /* move the offset entry to appropriate free list */
        list_move(&entry->offset_entry->link,
@@ -893,12 +894,19 @@ int ipa3_reset_hdr(void)
                        &ipa3_ctx->hdr_tbl.head_hdr_entry_list, link) {
 
                /* do not remove the default header */
-               if (!strcmp(entry->name, IPA_LAN_RX_HDR_NAME))
+               if (!strcmp(entry->name, IPA_LAN_RX_HDR_NAME)) {
+                       if (entry->is_hdr_proc_ctx) {
+                               IPAERR("default header is proc ctx\n");
+                               mutex_unlock(&ipa3_ctx->lock);
+                               WARN_ON(1);
+                               return -EFAULT;
+                       }
                        continue;
+               }
 
                if (ipa3_id_find(entry->id) == NULL) {
-                       WARN_ON(1);
                        mutex_unlock(&ipa3_ctx->lock);
+                       WARN_ON(1);
                        return -EFAULT;
                }
                if (entry->is_hdr_proc_ctx) {
@@ -951,8 +959,8 @@ int ipa3_reset_hdr(void)
                link) {
 
                if (ipa3_id_find(ctx_entry->id) == NULL) {
-                       WARN_ON(1);
                        mutex_unlock(&ipa3_ctx->lock);
+                       WARN_ON(1);
                        return -EFAULT;
                }
                list_del(&ctx_entry->link);
@@ -1115,8 +1123,8 @@ int ipa3_put_hdr(u32 hdr_hdl)
                goto bail;
        }
 
-       if (entry == NULL || entry->cookie != IPA_COOKIE) {
-               IPAERR("bad params\n");
+       if (entry->cookie != IPA_COOKIE) {
+               IPAERR("invalid header entry\n");
                result = -EINVAL;
                goto bail;
        }
index cce05cf..97a3117 100644 (file)
@@ -271,7 +271,7 @@ struct ipa3_rt_tbl {
  * @is_partial: flag indicating if header table entry is partial
  * @is_hdr_proc_ctx: false - hdr entry resides in hdr table,
  * true - hdr entry resides in DDR and pointed to by proc ctx
- * @phys_base: physical address of entry in SRAM when is_hdr_proc_ctx is true,
+ * @phys_base: physical address of entry in DDR when is_hdr_proc_ctx is true,
  * else 0
  * @proc_ctx: processing context header
  * @offset_entry: entry's offset
index 138db3d..b06e33a 100644 (file)
@@ -957,6 +957,10 @@ static int __ipa_finish_rt_rule_add(struct ipa3_rt_entry *entry, u32 *rule_hdl,
        return 0;
 
 ipa_insert_failed:
+       if (entry->hdr)
+               entry->hdr->ref_cnt--;
+       else if (entry->proc_ctx)
+               entry->proc_ctx->ref_cnt--;
        idr_remove(&tbl->rule_ids, entry->rule_id);
        list_del(&entry->link);
        kmem_cache_free(ipa3_ctx->rt_rule_cache, entry);
index 4f6097c..6c4d14b 100644 (file)
@@ -1215,7 +1215,10 @@ int ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type,
                (!phys_base && !hdr_base_addr) ||
                !hdr_base_addr ||
                ((is_hdr_proc_ctx == false) && !offset_entry)) {
-               IPAHAL_ERR("failed on validating params");
+               IPAHAL_ERR(
+                       "invalid input: hdr_len:%u phys_base:%pad hdr_base_addr:%u is_hdr_proc_ctx:%d offset_entry:%pK\n"
+                       , hdr_len, &phys_base, hdr_base_addr
+                       , is_hdr_proc_ctx, offset_entry);
                return -EINVAL;
        }