summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorKalyan Thota <kalyant@codeaurora.org>2015-11-19 20:41:24 +0530
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:48:04 -0700
commit87345f4cdeb15fe0f6851e4b76cab5dea021d2ec (patch)
treee045a07b7de91699f4d0e709938a4a02f9e38ef1 /drivers
parentdfe5ee688c976df4714b01f42543480873db15f9 (diff)
msm: mdss: use DMA_BIDIRECTIONAL for 8937
Simultaneous buffer maps with read and write permissions are possible due to the asynchronous nature of MDSS driver. Client stages the same buffer on MDP & ROTATOR. It calls the map API for both at the same time. Due to concurrency, the source buffer is mapped by MDP before and is ref-counted. ROTATOR API called later never updates the permission which is required for dst buffer. This leads to permission fault. Requesting the map with DMA_BIDIRECTIONAL flag to fix the issue. Change-Id: Ieb819820b19d163fee541dd571c5a58dc78be7d3 Signed-off-by: Kalyan Thota <kalyant@codeaurora.org> [cip@codeaurora.org: Resolved merge conflict] Signed-off-by: Clarence Ip <cip@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/fbdev/msm/mdss.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.c1
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_splash_logo.c5
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_util.c9
-rw-r--r--drivers/video/fbdev/msm/mdss_smmu.h19
5 files changed, 26 insertions, 9 deletions
diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h
index 2a5f3dd17e2d..32be03f3225b 100644
--- a/drivers/video/fbdev/msm/mdss.h
+++ b/drivers/video/fbdev/msm/mdss.h
@@ -155,6 +155,7 @@ enum mdss_hw_quirk {
MDSS_QUIRK_DOWNSCALE_HANG,
MDSS_QUIRK_DSC_RIGHT_ONLY_PU,
MDSS_QUIRK_DSC_2SLICE_PU_THRPUT,
+ MDSS_QUIRK_DMA_BI_DIR,
MDSS_QUIRK_MAX,
};
diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c
index 7eaaf3481bff..39b1c4c2c766 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp.c
@@ -1289,6 +1289,7 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata)
set_bit(MDSS_CAPS_YUV_CONFIG, mdata->mdss_caps_map);
mdss_mdp_init_default_prefill_factors(mdata);
set_bit(MDSS_QOS_OTLIM, mdata->mdss_qos_map);
+ mdss_set_quirk(mdata, MDSS_QUIRK_DMA_BI_DIR);
break;
default:
mdata->max_target_zorder = 4; /* excluding base layer */
diff --git a/drivers/video/fbdev/msm/mdss_mdp_splash_logo.c b/drivers/video/fbdev/msm/mdss_mdp_splash_logo.c
index 4596b46464ca..7cc94447efdc 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_splash_logo.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_splash_logo.c
@@ -88,7 +88,7 @@ static int mdss_mdp_splash_alloc_memory(struct msm_fb_data_type *mfd,
}
sinfo->size = buf_size;
- dma_buf_begin_cpu_access(sinfo->dma_buf, 0, size, DMA_FROM_DEVICE);
+ dma_buf_begin_cpu_access(sinfo->dma_buf, 0, size, DMA_BIDIRECTIONAL);
sinfo->splash_buffer = dma_buf_kmap(sinfo->dma_buf, 0);
if (IS_ERR(sinfo->splash_buffer)) {
pr_err("ion kernel memory mapping failed\n");
@@ -132,7 +132,8 @@ static void mdss_mdp_splash_free_memory(struct msm_fb_data_type *mfd)
if (!mdata || !mdata->iclient || !sinfo->dma_buf)
return;
- dma_buf_end_cpu_access(sinfo->dma_buf, 0, sinfo->size, DMA_FROM_DEVICE);
+ dma_buf_end_cpu_access(sinfo->dma_buf, 0, sinfo->size,
+ DMA_BIDIRECTIONAL);
dma_buf_kunmap(sinfo->dma_buf, 0, sinfo->splash_buffer);
mdss_smmu_unmap_dma_buf(sinfo->table, MDSS_IOMMU_DOMAIN_UNSECURE, 0,
diff --git a/drivers/video/fbdev/msm/mdss_mdp_util.c b/drivers/video/fbdev/msm/mdss_mdp_util.c
index 74813f201dbb..6142f009c8f5 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_util.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_util.c
@@ -1047,7 +1047,8 @@ static int mdss_mdp_put_img(struct mdss_mdp_img_data *data, bool rotator,
}
if (!data->skip_detach) {
dma_buf_unmap_attachment(data->srcp_attachment,
- data->srcp_table, dir);
+ data->srcp_table,
+ mdss_smmu_dma_data_direction(dir));
dma_buf_detach(data->srcp_dma_buf,
data->srcp_attachment);
dma_buf_put(data->srcp_dma_buf);
@@ -1121,7 +1122,8 @@ static int mdss_mdp_get_img(struct msmfb_data *img,
}
data->srcp_table =
- dma_buf_map_attachment(data->srcp_attachment, dir);
+ dma_buf_map_attachment(data->srcp_attachment,
+ mdss_smmu_dma_data_direction(dir));
if (IS_ERR(data->srcp_table)) {
ret = PTR_ERR(data->srcp_table);
goto err_detach;
@@ -1252,7 +1254,8 @@ static int mdss_mdp_map_buffer(struct mdss_mdp_img_data *data, bool rotator,
return ret;
err_unmap:
- dma_buf_unmap_attachment(data->srcp_attachment, data->srcp_table, dir);
+ dma_buf_unmap_attachment(data->srcp_attachment, data->srcp_table,
+ mdss_smmu_dma_data_direction(dir));
dma_buf_detach(data->srcp_dma_buf, data->srcp_attachment);
dma_buf_put(data->srcp_dma_buf);
return ret;
diff --git a/drivers/video/fbdev/msm/mdss_smmu.h b/drivers/video/fbdev/msm/mdss_smmu.h
index a12e759c90ab..a7b95f5742b6 100644
--- a/drivers/video/fbdev/msm/mdss_smmu.h
+++ b/drivers/video/fbdev/msm/mdss_smmu.h
@@ -41,6 +41,14 @@ struct mdss_smmu_domain {
void mdss_smmu_register(struct device *dev);
int mdss_smmu_init(struct mdss_data_type *mdata, struct device *dev);
+static inline int mdss_smmu_dma_data_direction(int dir)
+{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+
+ return (mdss_has_quirk(mdata, MDSS_QUIRK_DMA_BI_DIR)) ?
+ DMA_BIDIRECTIONAL : dir;
+}
+
static inline bool is_mdss_smmu_compatible_device(const char *str)
{
/* check the prefix */
@@ -177,7 +185,8 @@ static inline int mdss_smmu_map_dma_buf(struct dma_buf *dma_buf,
return -ENOSYS;
return mdata->smmu_ops.smmu_map_dma_buf(dma_buf, table,
- domain, iova, size, dir);
+ domain, iova, size,
+ mdss_smmu_dma_data_direction(dir));
}
static inline void mdss_smmu_unmap_dma_buf(struct sg_table *table, int domain,
@@ -185,7 +194,8 @@ static inline void mdss_smmu_unmap_dma_buf(struct sg_table *table, int domain,
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
if (mdata->smmu_ops.smmu_unmap_dma_buf)
- mdata->smmu_ops.smmu_unmap_dma_buf(table, domain, dir, dma_buf);
+ mdata->smmu_ops.smmu_unmap_dma_buf(table, domain,
+ mdss_smmu_dma_data_direction(dir), dma_buf);
}
static inline int mdss_smmu_dma_alloc_coherent(struct device *dev, size_t size,
@@ -246,7 +256,8 @@ static inline int mdss_smmu_dsi_map_buffer(phys_addr_t phys,
return -ENOSYS;
return mdata->smmu_ops.smmu_dsi_map_buffer(phys, domain, size,
- dma_addr, cpu_addr, dir);
+ dma_addr, cpu_addr,
+ mdss_smmu_dma_data_direction(dir));
}
static inline void mdss_smmu_dsi_unmap_buffer(dma_addr_t dma_addr, int domain,
@@ -255,7 +266,7 @@ static inline void mdss_smmu_dsi_unmap_buffer(dma_addr_t dma_addr, int domain,
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
if (mdata->smmu_ops.smmu_dsi_unmap_buffer)
mdata->smmu_ops.smmu_dsi_unmap_buffer(dma_addr, domain,
- size, dir);
+ size, mdss_smmu_dma_data_direction(dir));
}
static inline void mdss_smmu_deinit(struct mdss_data_type *mdata)