Merge "msm: mdss: IOMMU ref count implementation"
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index afa0bc1..b1c0343 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -198,6 +198,7 @@
int handoff_pending;
struct mdss_prefill_data prefill_data;
bool ulps;
+ int iommu_ref_cnt;
};
extern struct mdss_data_type *mdss_res;
@@ -220,7 +221,8 @@
void mdss_enable_irq(struct mdss_hw *hw);
void mdss_disable_irq(struct mdss_hw *hw);
void mdss_disable_irq_nosync(struct mdss_hw *hw);
-int mdss_bus_bandwidth_ctrl(int enable);
+void mdss_bus_bandwidth_ctrl(int enable);
+int mdss_iommu_ctrl(int enable);
static inline struct ion_client *mdss_get_ionclient(void)
{
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index 457deb7..56701d4 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -1031,7 +1031,7 @@
if (is_mdss_iommu_attached()) {
- int ret = msm_iommu_map_contig_buffer(tp->dmap,
+ ret = msm_iommu_map_contig_buffer(tp->dmap,
mdss_get_iommu_domain(domain), 0,
size, SZ_4K, 0, &(addr));
if (IS_ERR_VALUE(ret)) {
@@ -1240,7 +1240,7 @@
{
struct dcs_cmd_req *req;
int ret = -EINVAL;
-
+ int rc = 0;
mutex_lock(&ctrl->cmd_mutex);
req = mdss_dsi_cmdlist_get(ctrl);
@@ -1263,20 +1263,21 @@
* also, axi bus bandwidth need since dsi controller will
* fetch dcs commands from axi bus
*/
- ret = mdss_bus_bandwidth_ctrl(1);
- if (ret) {
- pr_err("bus bandwidth request failed ret=%d\n", ret);
- goto need_lock;
- }
-
+ mdss_bus_bandwidth_ctrl(1);
pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid);
mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 1);
+ rc = mdss_iommu_ctrl(1);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("IOMMU attach failed\n");
+ mutex_unlock(&ctrl->cmd_mutex);
+ return rc;
+ }
if (req->flags & CMD_REQ_RX)
ret = mdss_dsi_cmdlist_rx(ctrl, req);
else
ret = mdss_dsi_cmdlist_tx(ctrl, req);
-
+ mdss_iommu_ctrl(0);
mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 0);
mdss_bus_bandwidth_ctrl(0);
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index bf151f4..00a8006 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -620,6 +620,37 @@
return clk_rate;
}
+int mdss_iommu_ctrl(int enable)
+{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+ int rc = 0;
+
+ mutex_lock(&mdp_iommu_lock);
+ pr_debug("%pS: enable %d mdata->iommu_ref_cnt %d\n",
+ __builtin_return_address(0), enable, mdata->iommu_ref_cnt);
+
+ if (enable) {
+
+ if (mdata->iommu_ref_cnt == 0)
+ rc = mdss_iommu_attach(mdata);
+ mdata->iommu_ref_cnt++;
+ } else {
+ if (mdata->iommu_ref_cnt) {
+ mdata->iommu_ref_cnt--;
+ if (mdata->iommu_ref_cnt == 0)
+ rc = mdss_iommu_dettach(mdata);
+ } else {
+ pr_err("unbalanced iommu ref\n");
+ }
+ }
+ mutex_unlock(&mdp_iommu_lock);
+
+ if (IS_ERR_VALUE(rc))
+ return rc;
+ else
+ return mdata->iommu_ref_cnt;
+}
+
/**
* mdss_bus_bandwidth_ctrl() -- place bus bandwidth request
* @enable: value of enable or disable
@@ -629,27 +660,16 @@
* Bus bandwidth is required by mdp.For dsi, it only requires to send
* dcs coammnd. It returns error if bandwidth request fails.
*/
-int mdss_bus_bandwidth_ctrl(int enable)
+void mdss_bus_bandwidth_ctrl(int enable)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
static int bus_bw_cnt;
int changed = 0;
- int rc = 0;
mutex_lock(&bus_bw_lock);
if (enable) {
- if (bus_bw_cnt == 0) {
+ if (bus_bw_cnt == 0)
changed++;
- if (!mdata->handoff_pending) {
- rc = mdss_iommu_attach(mdata);
- if (rc) {
- pr_err("iommu attach failed rc=%d\n",
- rc);
- goto end;
- }
- }
- }
-
bus_bw_cnt++;
} else {
if (bus_bw_cnt) {
@@ -668,7 +688,6 @@
if (!enable) {
msm_bus_scale_client_update_request(
mdata->bus_hdl, 0);
- mdss_iommu_dettach(mdata);
pm_runtime_put(&mdata->pdev->dev);
} else {
pm_runtime_get_sync(&mdata->pdev->dev);
@@ -677,9 +696,7 @@
}
}
-end:
mutex_unlock(&bus_bw_lock);
- return rc;
}
EXPORT_SYMBOL(mdss_bus_bandwidth_ctrl);
@@ -687,7 +704,7 @@
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
static int mdp_clk_cnt;
- int changed = 0, rc;
+ int changed = 0;
mutex_lock(&mdp_clk_lock);
if (enable) {
@@ -720,9 +737,7 @@
if (mdata->vsync_ena)
mdss_mdp_clk_update(MDSS_CLK_MDP_VSYNC, enable);
- rc = mdss_bus_bandwidth_ctrl(enable);
- if (rc)
- pr_err("bus bandwidth control failed rc=%d", rc);
+ mdss_bus_bandwidth_ctrl(enable);
if (!enable)
pm_runtime_put(&mdata->pdev->dev);
@@ -809,7 +824,6 @@
struct mdss_iommu_map_type *iomap;
int i, rc = 0;
- mutex_lock(&mdp_iommu_lock);
MDSS_XLOG(mdata->iommu_attached);
if (mdata->iommu_attached) {
@@ -840,8 +854,6 @@
mdata->iommu_attached = true;
end:
- mutex_unlock(&mdp_iommu_lock);
-
return rc;
}
@@ -851,12 +863,10 @@
struct mdss_iommu_map_type *iomap;
int i;
- mutex_lock(&mdp_iommu_lock);
MDSS_XLOG(mdata->iommu_attached);
if (!mdata->iommu_attached) {
pr_debug("mdp iommu already dettached\n");
- mutex_unlock(&mdp_iommu_lock);
return 0;
}
@@ -873,7 +883,6 @@
}
mdata->iommu_attached = false;
- mutex_unlock(&mdp_iommu_lock);
return 0;
}
@@ -2560,7 +2569,6 @@
mdata->fs_ena = true;
} else {
pr_debug("Disable MDP FS\n");
- mdss_iommu_dettach(mdata);
if (mdata->fs_ena) {
regulator_disable(mdata->fs);
if (!mdata->ulps) {
@@ -2591,20 +2599,24 @@
pr_debug("called on=%d\n", on);
if (on) {
pm_runtime_get_sync(dev);
- rc = mdss_iommu_attach(mdata);
- if (rc) {
+ rc = mdss_iommu_ctrl(1);
+ if (IS_ERR_VALUE(rc)) {
pr_err("mdss iommu attach failed rc=%d\n", rc);
- goto end;
+ return rc;
}
mdss_hw_init(mdata);
mdata->ulps = false;
+ rc = mdss_iommu_ctrl(0);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("iommu dettach failed ret=%d\n", rc);
+ return rc;
+ }
} else {
mdata->ulps = true;
pm_runtime_put_sync(dev);
}
-end:
- return rc;
+ return 0;
}
static inline int mdss_mdp_suspend_sub(struct mdss_data_type *mdata)
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index 991eb06..b91c524 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -189,6 +189,7 @@
{
unsigned long flags;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+ int rc;
if (!ctx->panel_on)
return;
@@ -201,6 +202,12 @@
if (cancel_delayed_work_sync(&ctx->ulps_work))
pr_debug("deleted pending ulps work\n");
+ rc = mdss_iommu_ctrl(1);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("IOMMU attach failed\n");
+ mutex_unlock(&ctx->clk_mtx);
+ return;
+ }
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
if (ctx->ulps) {
@@ -243,6 +250,7 @@
mdss_mdp_hist_intr_setup(&mdata->hist_intr, MDSS_IRQ_SUSPEND);
mdss_mdp_ctl_intf_event
(ctx->ctl, MDSS_EVENT_PANEL_CLK_CTRL, (void *)0);
+ mdss_iommu_ctrl(0);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
if (ctx->panel_on)
schedule_delayed_work(&ctx->ulps_work, ULPS_ENTER_TIME);
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index eff708c..e5bba31 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -333,6 +333,8 @@
frame_rate = 24;
msleep((1000/frame_rate) + 1);
}
+
+ mdss_iommu_ctrl(0);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
ctx->timegen_en = false;
@@ -717,6 +719,12 @@
pr_debug("enabling timing gen for intf=%d\n", ctl->intf_num);
+ rc = mdss_iommu_ctrl(1);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("IOMMU attach failed\n");
+ return rc;
+ }
+
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num);
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index 02e7b75..7bf03eb 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -442,6 +442,7 @@
rc = 0;
}
+ mdss_iommu_ctrl(0);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false); /* clock off */
ctx->comp_cnt--;
@@ -501,6 +502,11 @@
INIT_COMPLETION(ctx->wb_comp);
mdss_mdp_irq_enable(ctx->intr_type, ctx->intf_num);
+ ret = mdss_iommu_ctrl(1);
+ if (IS_ERR_VALUE(ret)) {
+ pr_err("IOMMU attach failed\n");
+ return ret;
+ }
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_START, 1);
wmb();
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index fdfa2b0..a475212 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -702,14 +702,16 @@
int num_planes,
u32 flags)
{
- int i, rc;
+ int i, rc, ret;
if ((num_planes <= 0) || (num_planes > MAX_PLANES))
return -EINVAL;
- rc = mdss_bus_bandwidth_ctrl(1);
- if (rc)
- goto end;
+ ret = mdss_iommu_ctrl(1);
+ if (IS_ERR_VALUE(ret)) {
+ pr_err("Iommu attach failed");
+ return ret;
+ }
memset(data, 0, sizeof(*data));
for (i = 0; i < num_planes; i++) {
@@ -724,31 +726,38 @@
break;
}
}
- mdss_bus_bandwidth_ctrl(0);
+
+ ret = mdss_iommu_ctrl(0);
+ if (IS_ERR_VALUE(ret)) {
+ pr_err("Iommu dettach failed");
+ return ret;
+ }
data->num_planes = i;
-
-end:
return rc;
}
int mdss_mdp_overlay_free_buf(struct mdss_mdp_data *data)
{
- int i;
- int rc;
+ int i, rc;
- rc = mdss_bus_bandwidth_ctrl(1);
- if (rc)
- goto end;
+ rc = mdss_iommu_ctrl(1);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("Iommu attach failed");
+ return rc;
+ }
for (i = 0; i < data->num_planes && data->p[i].len; i++)
mdss_mdp_put_img(&data->p[i]);
- mdss_bus_bandwidth_ctrl(0);
+
+ rc = mdss_iommu_ctrl(0);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("Iommu dettach failed");
+ return rc;
+ }
data->num_planes = 0;
-
-end:
- return rc;
+ return 0;
}
/**
@@ -919,13 +928,6 @@
if (!mdp5_data->mdata->batfet)
mdss_mdp_batfet_ctrl(mdp5_data->mdata, true);
- if (!mfd->panel_info->cont_splash_enabled) {
- rc = mdss_iommu_attach(mdp5_data->mdata);
- if (rc) {
- pr_err("mdss iommu attach failed rc=%d\n", rc);
- goto end;
- }
- }
mdss_mdp_release_splash_pipe(mfd);
return 0;
}
@@ -948,13 +950,18 @@
*/
if (!is_mdss_iommu_attached()) {
if (!mfd->panel_info->cont_splash_enabled) {
- rc = mdss_iommu_attach(mdss_res);
- if (rc) {
- pr_err("mdss iommu attach failed rc=%d\n", rc);
+ rc = mdss_iommu_ctrl(1);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("iommu attach failed rc=%d\n", rc);
+ goto pm_error;
+ }
+ mdss_hw_init(mdss_res);
+ rc = mdss_iommu_ctrl(0);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("iommu dettach failed rc=%d\n", rc);
goto pm_error;
}
}
- mdss_hw_init(mdss_res);
}
rc = mdss_mdp_ctl_start(ctl, false);
@@ -1385,14 +1392,6 @@
flags = (pipe->flags & MDP_SECURE_OVERLAY_SESSION);
flags |= (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION);
- if (!mfd->panel_info->cont_splash_enabled) {
- ret = mdss_iommu_attach(mdata);
- if (ret) {
- pr_err("mdss iommu attach failed ret=%d\n", ret);
- goto end;
- }
- }
-
src_data = &pipe->back_buf;
if (src_data->num_planes) {
pr_warn("dropped buffer pnum=%d play=%d addr=0x%x\n",
@@ -1405,7 +1404,6 @@
pr_err("src_data pmem error\n");
}
-end:
mdss_mdp_pipe_unmap(pipe);
return ret;
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c
index 6953469..ff8c6b8 100755
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -692,7 +692,6 @@
struct msmfb_overlay_data *req)
{
struct mdss_mdp_rotator_session *rot;
- struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
int ret;
u32 flgs;
@@ -712,9 +711,6 @@
goto dst_buf_fail;
}
- if (!mfd->panel_info->cont_splash_enabled)
- mdss_iommu_attach(mdp5_data->mdata);
-
mdss_mdp_overlay_free_buf(&rot->src_buf);
ret = mdss_mdp_overlay_get_buf(mfd, &rot->src_buf, &req->data, 1, flgs);
if (ret) {
diff --git a/drivers/video/msm/mdss/mdss_mdp_splash_logo.c b/drivers/video/msm/mdss/mdss_mdp_splash_logo.c
index 838f58f..c478d38 100644
--- a/drivers/video/msm/mdss/mdss_mdp_splash_logo.c
+++ b/drivers/video/msm/mdss/mdss_mdp_splash_logo.c
@@ -109,7 +109,7 @@
{
struct iommu_domain *domain;
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
- int rc;
+ int rc, ret;
/*
* iommu dynamic attach for following conditions.
@@ -139,9 +139,9 @@
if (rc) {
pr_debug("iommu memory mapping failed rc=%d\n", rc);
} else {
- rc = mdss_iommu_attach(mdss_res);
- if (rc) {
- pr_debug("mdss iommu attach failed\n");
+ ret = mdss_iommu_ctrl(1);
+ if (IS_ERR_VALUE(ret)) {
+ pr_err("mdss iommu attach failed\n");
iommu_unmap(domain, mdp5_data->splash_mem_addr,
mdp5_data->splash_mem_size);
} else {
@@ -156,6 +156,7 @@
{
struct iommu_domain *domain;
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ int ret;
if (mfd->splash_info.iommu_dynamic_attached) {
domain = msm_get_iommu_domain(mdss_get_iommu_domain(
@@ -167,6 +168,10 @@
iommu_unmap(domain, mdp5_data->splash_mem_addr,
mdp5_data->splash_mem_size);
+ ret = mdss_iommu_ctrl(0);
+ if (IS_ERR_VALUE(ret))
+ pr_err("mdss iommu dettach failed\n");
+
mfd->splash_info.iommu_dynamic_attached = false;
}
}
@@ -246,12 +251,6 @@
}
mdss_mdp_footswitch_ctrl_splash(0);
- if (!is_mdss_iommu_attached()) {
- rc = mdss_iommu_attach(mdss_res);
- if (rc)
- pr_err("iommu attach failed rc=%d\n", rc);
- }
-
end:
return rc;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index 0e59a26..6f5da1d 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -403,7 +403,7 @@
struct mdss_mdp_wb *wb = mfd_to_wb(mfd);
struct mdss_mdp_wb_data *node;
struct mdss_mdp_img_data *buf;
- int ret;
+ int ret, rc;
if (!list_empty(&wb->register_queue)) {
list_for_each_entry(node, &wb->register_queue, registered_entry)
@@ -427,7 +427,17 @@
buf = &node->buf_data.p[0];
if (wb->is_secure)
buf->flags |= MDP_SECURE_OVERLAY_SESSION;
+ rc = mdss_iommu_ctrl(1);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("IOMMU attach failed\n");
+ goto register_fail;
+ }
ret = mdss_mdp_get_img(data, buf);
+ rc = mdss_iommu_ctrl(0);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("IOMMU dettach failed\n");
+ goto register_fail;
+ }
if (IS_ERR_VALUE(ret)) {
pr_err("error getting buffer info\n");
goto register_fail;
@@ -471,7 +481,6 @@
{
struct mdss_mdp_wb *wb = mfd_to_wb(mfd);
struct mdss_mdp_wb_data *node = NULL;
- struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
int ret = 0;
if (!wb) {
@@ -481,14 +490,6 @@
pr_debug("fb%d queue\n", wb->fb_ndx);
- if (!mfd->panel_info->cont_splash_enabled) {
- ret = mdss_iommu_attach(mdp5_data->mdata);
- if (ret) {
- pr_err("mdss iommu attach failed rc=%d", ret);
- return ret;
- }
- }
-
mutex_lock(&wb->lock);
if (local)
node = get_local_node(wb, data);
@@ -711,6 +712,7 @@
{
struct msmfb_data data;
int ret = -ENOSYS, hint = 0;
+ int rc;
switch (cmd) {
case MSMFB_WRITEBACK_INIT:
@@ -741,7 +743,17 @@
}
break;
case MSMFB_WRITEBACK_TERMINATE:
+ rc = mdss_iommu_ctrl(1);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("IOMMU attach failed\n");
+ return rc;
+ }
ret = mdss_mdp_wb_terminate(mfd);
+ rc = mdss_iommu_ctrl(0);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("IOMMU dettach failed\n");
+ return rc;
+ }
break;
case MSMFB_WRITEBACK_SET_MIRRORING_HINT:
if (!copy_from_user(&hint, arg, sizeof(hint))) {
@@ -854,19 +866,29 @@
EXPORT_SYMBOL(msm_fb_writeback_set_secure);
/**
- * msm_fb_writeback_iommu_ref() - Power ON/OFF mdp clock
- * @enable - true/false to Power ON/OFF mdp clock
+ * msm_fb_writeback_iommu_ref() - Add/Remove vote on MDSS IOMMU being attached.
+ * @enable - true adds vote on MDSS IOMMU, false removes the vote.
*
- * Call to enable mdp clock at start of mdp_mmap/mdp_munmap API and
- * to disable mdp clock at end of these API's to ensure iommu is in
- * proper state while driver map/un-map any buffers.
+ * Call to vote on MDSS IOMMU being enabled. To ensure buffers are properly
+ * mapped to IOMMU context bank.
*/
int msm_fb_writeback_iommu_ref(struct fb_info *info, int enable)
{
- if (enable)
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
- else
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+ int ret;
+
+ if (enable) {
+ ret = mdss_iommu_ctrl(1);
+ if (IS_ERR_VALUE(ret)) {
+ pr_err("IOMMU attach failed\n");
+ return ret;
+ }
+ } else {
+ ret = mdss_iommu_ctrl(0);
+ if (IS_ERR_VALUE(ret)) {
+ pr_err("IOMMU dettach failed\n");
+ return ret;
+ }
+ }
return 0;
}