OSDN Git Service

msm: ipa3: fix GSI ring DMA allocation parameters
authorGhanim Fodi <gfodi@codeaurora.org>
Sun, 28 Aug 2016 18:50:15 +0000 (21:50 +0300)
committerGerrit - the friendly Code Review server <code-review@localhost>
Tue, 30 Aug 2016 08:35:19 +0000 (01:35 -0700)
DMA coherent allocation was done with inappropriate
flags causing memory allocation to fail occasionally.
Use GFP_KERNEL flag as well as fix up some cleanup
actions.

CRs-Fixed: 1060305
Change-Id: I93c9340439dd65c50764dd078071bf66f65a9464
Signed-off-by: Ghanim Fodi <gfodi@codeaurora.org>
drivers/platform/msm/ipa/ipa_v3/ipa_dp.c

index 19eb1ee..9e346f1 100644 (file)
@@ -3836,6 +3836,7 @@ static int ipa_gsi_setup_channel(struct ipa_sys_connect_params *in,
        union __packed gsi_channel_scratch ch_scratch;
        struct ipa_gsi_ep_config *gsi_ep_info;
        dma_addr_t dma_addr;
+       dma_addr_t evt_dma_addr;
        int result;
 
        if (!ep) {
@@ -3844,13 +3845,13 @@ static int ipa_gsi_setup_channel(struct ipa_sys_connect_params *in,
        }
 
        ep->gsi_evt_ring_hdl = ~0;
+       memset(&gsi_evt_ring_props, 0, sizeof(gsi_evt_ring_props));
        /*
         * allocate event ring for all interrupt-policy
         * pipes and IPA consumers pipes
         */
        if (ep->sys->policy != IPA_POLICY_NOINTR_MODE ||
             IPA_CLIENT_IS_CONS(ep->client)) {
-               memset(&gsi_evt_ring_props, 0, sizeof(gsi_evt_ring_props));
                gsi_evt_ring_props.intf = GSI_EVT_CHTYPE_GPI_EV;
                gsi_evt_ring_props.intr = GSI_INTR_IRQ;
                gsi_evt_ring_props.re_size =
@@ -3859,8 +3860,13 @@ static int ipa_gsi_setup_channel(struct ipa_sys_connect_params *in,
                gsi_evt_ring_props.ring_len = IPA_GSI_EVT_RING_LEN;
                gsi_evt_ring_props.ring_base_vaddr =
                        dma_alloc_coherent(ipa3_ctx->pdev, IPA_GSI_EVT_RING_LEN,
-                       &dma_addr, 0);
-               gsi_evt_ring_props.ring_base_addr = dma_addr;
+                       &evt_dma_addr, GFP_KERNEL);
+               if (!gsi_evt_ring_props.ring_base_vaddr) {
+                       IPAERR("fail to dma alloc %u bytes\n",
+                               IPA_GSI_EVT_RING_LEN);
+                       return -ENOMEM;
+               }
+               gsi_evt_ring_props.ring_base_addr = evt_dma_addr;
 
                /* copy mem info */
                ep->gsi_mem_info.evt_ring_len = gsi_evt_ring_props.ring_len;
@@ -3895,7 +3901,7 @@ static int ipa_gsi_setup_channel(struct ipa_sys_connect_params *in,
        if (!gsi_ep_info) {
                IPAERR("Invalid ep number\n");
                result = -EINVAL;
-               goto fail_alloc_evt_ring;
+               goto fail_get_gsi_ep_info;
        } else
                gsi_channel_props.ch_id = gsi_ep_info->ipa_gsi_chan_num;
 
@@ -3914,7 +3920,12 @@ static int ipa_gsi_setup_channel(struct ipa_sys_connect_params *in,
                gsi_channel_props.ring_len = 2 * in->desc_fifo_sz;
        gsi_channel_props.ring_base_vaddr =
                dma_alloc_coherent(ipa3_ctx->pdev, gsi_channel_props.ring_len,
-                       &dma_addr, 0);
+                       &dma_addr, GFP_KERNEL);
+       if (!gsi_channel_props.ring_base_vaddr) {
+               IPAERR("fail to dma alloc %u bytes\n",
+                       gsi_channel_props.ring_len);
+               goto fail_alloc_channel_ring;
+       }
        gsi_channel_props.ring_base_addr = dma_addr;
 
        /* copy mem info */
@@ -3950,7 +3961,7 @@ static int ipa_gsi_setup_channel(struct ipa_sys_connect_params *in,
        result = gsi_write_channel_scratch(ep->gsi_chan_hdl, ch_scratch);
        if (result != GSI_STATUS_SUCCESS) {
                IPAERR("failed to write scratch %d\n", result);
-               goto fail_start_channel;
+               goto fail_write_channel_scratch;
        }
 
        result = gsi_start_channel(ep->gsi_chan_hdl);
@@ -3962,17 +3973,25 @@ static int ipa_gsi_setup_channel(struct ipa_sys_connect_params *in,
        return 0;
 
 fail_start_channel:
+fail_write_channel_scratch:
        if (gsi_dealloc_channel(ep->gsi_chan_hdl)
                != GSI_STATUS_SUCCESS) {
                IPAERR("Failed to dealloc GSI chan.\n");
                BUG();
        }
 fail_alloc_channel:
+       dma_free_coherent(ipa3_ctx->pdev, gsi_channel_props.ring_len,
+                       gsi_channel_props.ring_base_vaddr, dma_addr);
+fail_alloc_channel_ring:
+fail_get_gsi_ep_info:
        if (ep->gsi_evt_ring_hdl != ~0) {
                gsi_dealloc_evt_ring(ep->gsi_evt_ring_hdl);
                ep->gsi_evt_ring_hdl = ~0;
        }
 fail_alloc_evt_ring:
+       if (gsi_evt_ring_props.ring_base_vaddr)
+               dma_free_coherent(ipa3_ctx->pdev, IPA_GSI_EVT_RING_LEN,
+                       gsi_evt_ring_props.ring_base_vaddr, evt_dma_addr);
        IPAERR("Return with err: %d\n", result);
        return result;
 }