@@ -113,6 +113,8 @@ extern u32 procwrap_un_map(union Trapped_Args *args, void *pr_ctxt);
extern u32 procwrap_begin_dma_to_dsp(union Trapped_Args *args, void *pr_ctxt);
extern u32 procwrap_stop(union Trapped_Args *args, void *pr_ctxt);
extern u32 procwrap_begin_dma_from_dsp(union Trapped_Args *args, void *pr_ctxt);
+extern u32 procwrap_end_dma_to_dsp(union Trapped_Args *args, void *pr_ctxt);
+extern u32 procwrap_end_dma_from_dsp(union Trapped_Args *args, void *pr_ctxt);
/* NODE wrapper functions */
extern u32 nodewrap_allocate(union Trapped_Args *args, void *pr_ctxt);
@@ -474,6 +474,8 @@ extern dsp_status proc_stop(void *hprocessor);
*/
extern dsp_status proc_begin_dma_to_dsp(void *hprocessor,
void *pmpu_addr, u32 ul_size, u32 ul_flags);
+extern dsp_status proc_end_dma_to_dsp(void *hprocessor,
+ void *pmpu_addr, u32 ul_size, u32 ul_flags);
/*
* ======== proc_invalidate_memory ========
@@ -495,6 +497,8 @@ extern dsp_status proc_begin_dma_to_dsp(void *hprocessor,
*/
extern dsp_status proc_begin_dma_from_dsp(void *hprocessor,
void *pmpu_addr, u32 ul_size);
+extern dsp_status proc_end_dma_from_dsp(void *hprocessor,
+ void *pmpu_addr, u32 ul_size);
/*
* ======== proc_map ========
@@ -455,6 +455,8 @@ union Trapped_Args {
#define PROC_BEGINDMATODSP _IOW(DB, DB_IOC(DB_PROC, 14), unsigned long)
#define PROC_STOP _IOWR(DB, DB_IOC(DB_PROC, 15), unsigned long)
#define PROC_BEGINDMAFROMDSP _IOW(DB, DB_IOC(DB_PROC, 16), unsigned long)
+#define PROC_ENDDMATODSP _IOW(DB, DB_IOC(DB_PROC, 17), unsigned long)
+#define PROC_ENDDMAFROMDSP _IOW(DB, DB_IOC(DB_PROC, 18), unsigned long)
/* NODE Module */
#define NODE_ALLOCATE _IOWR(DB, DB_IOC(DB_NODE, 0), unsigned long)
@@ -114,6 +114,8 @@ static struct wcd_cmd proc_cmd[] = {
{procwrap_begin_dma_to_dsp}, /* PROC_BEGINDMATODSP */
{procwrap_stop}, /* PROC_STOP */
{procwrap_begin_dma_from_dsp}, /* PROC_BEGINDMAFROMDSP */
+ {procwrap_end_dma_to_dsp}, /* PROC_ENDDMATODSP */
+ {procwrap_end_dma_from_dsp}, /* PROC_ENDDMAFROMDSP */
};
/* NODE wrapper functions */
@@ -709,6 +711,31 @@ u32 procwrap_begin_dma_from_dsp(union Trapped_Args *args, void *pr_ctxt)
return status;
}
+u32 procwrap_end_dma_to_dsp(union Trapped_Args *args, void *pr_ctxt)
+{
+ dsp_status status;
+
+ if (args->args_proc_flushmemory.ul_flags >
+ PROC_WRITEBACK_INVALIDATE_MEM)
+ return DSP_EINVALIDARG;
+
+ status = proc_end_dma_to_dsp(args->args_proc_flushmemory.hprocessor,
+ args->args_proc_flushmemory.pmpu_addr,
+ args->args_proc_flushmemory.ul_size,
+ args->args_proc_flushmemory.ul_flags);
+ return status;
+}
+
+u32 procwrap_end_dma_from_dsp(union Trapped_Args *args, void *pr_ctxt)
+{
+ dsp_status status;
+
+ status =
+ proc_end_dma_from_dsp(args->args_proc_invalidatememory.hprocessor,
+ args->args_proc_invalidatememory.pmpu_addr,
+ args->args_proc_invalidatememory.ul_size);
+ return status;
+}
/*
* ======== procwrap_enum_resources ========
*/
@@ -700,6 +700,36 @@ out:
return ret;
}
+static int memory_regain_ownership(struct memory_map_info *map_info,
+ unsigned long start, ssize_t len, enum dma_data_direction dir)
+{
+ int ret = 0;
+ unsigned long first_data_page = start >> PAGE_SHIFT;
+ unsigned long last_data_page = ((u32)(start + len - 1) >> PAGE_SHIFT);
+ /* calculating the number of pages this area spans */
+ unsigned long num_pages = last_data_page - first_data_page + 1;
+ struct bridge_dma_map_info *dma_info = &map_info->dma_info;
+
+ if (!dma_info->sg)
+ goto out;
+
+ if (dma_info->dir != dir || dma_info->num_pages != num_pages) {
+ pr_err("%s: dma info doesn't match given params\n", __func__);
+ return -EINVAL;
+ }
+
+ dma_unmap_sg(bridge, dma_info->sg, num_pages, dma_info->dir);
+
+ pr_debug("%s: dma_map_sg unmapped\n", __func__);
+
+ kfree(dma_info->sg);
+
+ map_info->dma_info.sg = NULL;
+
+out:
+ return ret;
+}
+
/* Cache operation against kernel address instead of users */
static int memory_release_ownership(struct memory_map_info *map_info,
unsigned long start, ssize_t len, enum dma_data_direction dir)
@@ -798,6 +828,47 @@ err_out:
return status;
}
+static dsp_status proc_end_dma(void *hprocessor, void *pmpu_addr,
+ u32 ul_size, u32 ul_flags,
+ enum dsp_flushtype ftype)
+{
+ /* Keep STATUS here for future additions to this function */
+ dsp_status status = DSP_SOK;
+ struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
+ struct memory_map_info *map_info;
+
+ DBC_REQUIRE(refs > 0);
+
+ if (!MEM_IS_VALID_HANDLE(p_proc_object, PROC_SIGNATURE)) {
+ status = DSP_EHANDLE;
+ goto err_out;
+ }
+
+ pr_debug("%s: addr 0x%x, size 0x%x, type %d\n", __func__,
+ (u32)pmpu_addr,
+ ul_size, ftype);
+
+ /* find requested memory are in cached mapping information */
+ map_info = find_containing_mapping(p_proc_object, (u32) pmpu_addr,
+ ul_size);
+ if (!map_info) {
+ pr_err("%s: find_containing_mapping failed\n", __func__);
+ status = DSP_EHANDLE;
+ goto err_out;
+ }
+
+ if (memory_regain_ownership(map_info, (u32) pmpu_addr, ul_size,
+ ftype)) {
+ pr_err("%s: InValid address parameters %p %x\n",
+ __func__, pmpu_addr, ul_size);
+ status = DSP_EHANDLE;
+ goto err_out;
+ }
+
+err_out:
+ return status;
+}
+
/*
* ======== proc_flush_memory ========
* Purpose:
@@ -824,6 +895,22 @@ dsp_status proc_begin_dma_from_dsp(void *hprocessor, void *pmpu_addr,
return proc_begin_dma(hprocessor, pmpu_addr, ul_size, 0, dir);
}
+dsp_status proc_end_dma_to_dsp(void *hprocessor, void *pmpu_addr,
+ u32 ul_size, u32 ul_flags)
+{
+ enum dma_data_direction dir = DMA_BIDIRECTIONAL;
+
+ return proc_end_dma(hprocessor, pmpu_addr, ul_size, ul_flags, dir);
+}
+
+dsp_status proc_end_dma_from_dsp(void *hprocessor, void *pmpu_addr,
+ u32 ul_size)
+{
+ enum dma_data_direction dir = DMA_FROM_DEVICE;
+
+ return proc_end_dma(hprocessor, pmpu_addr, ul_size, 0, dir);
+}
+
/*
* ======== proc_get_resource_info ========
* Purpose: