aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/msm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-05-23 14:48:48 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-23 14:48:48 -0400
commit1d6da87a3241deb13d073c4125d19ed0e5a0c62c (patch)
tree42b7a9842618dad2afe7db9709cc6217ced03120 /drivers/gpu/drm/msm
parent1f40c49570eb01436786a9b5845c4469a9a1f362 (diff)
parenta39ed680bddb1ead592e22ed812c7e47286bfc03 (diff)
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie: "Here's the main drm pull request for 4.7, it's been a busy one, and I've been a bit more distracted in real life this merge window. Lots more ARM drivers, not sure if it'll ever end. I think I've at least one more coming the next merge window. But changes are all over the place, support for AMD Polaris GPUs is in here, some missing GM108 support for nouveau (found in some Lenovos), a bunch of MST and skylake fixes. I've also noticed a few fixes from Arnd in my inbox, that I'll try and get in asap, but I didn't think they should hold this up. New drivers: - Hisilicon kirin display driver - Mediatek MT8173 display driver - ARC PGU - bitstreamer on Synopsys ARC SDP boards - Allwinner A13 initial RGB output driver - Analogix driver for DisplayPort IP found in exynos and rockchip DRM Core: - UAPI headers fixes and C++ safety - DRM connector reference counting - DisplayID mode parsing for Dell 5K monitors - Removal of struct_mutex from drivers - Connector registration cleanups - MST robustness fixes - MAINTAINERS updates - Lockless GEM object freeing - Generic fbdev deferred IO support panel: - Support for a bunch of new panels i915: - VBT refactoring - PLL computation cleanups - DSI support for BXT - Color manager support - More atomic patches - GEM improvements - GuC fw loading fixes - DP detection fixes - SKL GPU hang fixes - Lots of BXT fixes radeon/amdgpu: - Initial Polaris support - GPUVM/Scheduler/Clock/Power improvements - ASYNC pageflip support - New mesa feature support nouveau: - GM108 support - Power sensor support improvements - GR init + ucode fixes. - Use GPU provided topology information vmwgfx: - Add host messaging support gma500: - Some cleanups and fixes atmel: - Bridge support - Async atomic commit support fsl-dcu: - Timing controller for LCD support - Pixel clock polarity support rcar-du: - Misc fixes exynos: - Pipeline clock support - Exynoss4533 SoC support - HW trigger mode support - export HDMI_PHY clock - DECON5433 fixes - Use generic prime functions - use DMA mapping APIs rockchip: - Lots of little fixes vc4: - Render node support - Gamma ramp support - DPI output support msm: - Mostly cleanups and fixes - Conversion to generic struct fence etnaviv: - Fix for prime buffer handling - Allow hangcheck to be coalesced with other wakeups tegra: - Gamme table size fix" * 'drm-next' of git://people.freedesktop.org/~airlied/linux: (1050 commits) drm/edid: add displayid detailed 1 timings to the modelist. (v1.1) drm/edid: move displayid validation to it's own function. drm/displayid: Iterate over all DisplayID blocks drm/edid: move displayid tiled block parsing into separate function. drm: Nuke ->vblank_disable_allowed drm/vmwgfx: Report vmwgfx version to vmware.log drm/vmwgfx: Add VMWare host messaging capability drm/vmwgfx: Kill some lockdep warnings drm/nouveau/gr/gf100-: fix race condition in fecs/gpccs ucode drm/nouveau/core: recognise GM108 chipsets drm/nouveau/gr/gm107-: fix touching non-existent ppcs in attrib cb setup drm/nouveau/gr/gk104-: share implementation of ppc exception init drm/nouveau/gr/gk104-: move rop_active_fbps init to nonctx drm/nouveau/bios/pll: check BIT table version before trying to parse it drm/nouveau/bios/pll: prevent oops when limits table can't be parsed drm/nouveau/volt/gk104: round up in gk104_volt_set drm/nouveau/fb/gm200: setup mmu debug buffer registers at init() drm/nouveau/fb/gk20a,gm20b: setup mmu debug buffer registers at init() drm/nouveau/fb/gf100-: allocate mmu debug buffers drm/nouveau/fb: allow chipset-specific actions for oneinit() ...
Diffstat (limited to 'drivers/gpu/drm/msm')
-rw-r--r--drivers/gpu/drm/msm/Kconfig7
-rw-r--r--drivers/gpu/drm/msm/Makefile5
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c16
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h2
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.h2
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_cfg.c34
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c12
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_manager.c27
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.c13
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c4
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c4
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c2
-rw-r--r--drivers/gpu/drm/msm/edp/edp_connector.c20
-rw-r--r--drivers/gpu/drm/msm/edp/edp_ctrl.c29
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.h11
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_connector.c26
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c4
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c34
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c16
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c4
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_format.c6
-rw-r--r--drivers/gpu/drm/msm/msm_atomic.c56
-rw-r--r--drivers/gpu/drm/msm/msm_debugfs.c168
-rw-r--r--drivers/gpu/drm/msm/msm_debugfs.h26
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c407
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h64
-rw-r--r--drivers/gpu/drm/msm/msm_fb.c5
-rw-r--r--drivers/gpu/drm/msm/msm_fence.c163
-rw-r--r--drivers/gpu/drm/msm/msm_fence.h46
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c138
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h19
-rw-r--r--drivers/gpu/drm/msm/msm_gem_prime.c2
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c125
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c123
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h9
-rw-r--r--drivers/gpu/drm/msm/msm_rd.c2
37 files changed, 910 insertions, 723 deletions
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 215495c2780c..167a4971f47c 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -23,6 +23,13 @@ config DRM_MSM_REGISTER_LOGGING
23 that can be parsed by envytools demsm tool. If enabled, register 23 that can be parsed by envytools demsm tool. If enabled, register
24 logging can be switched on via msm.reglog=y module param. 24 logging can be switched on via msm.reglog=y module param.
25 25
26config DRM_MSM_HDMI_HDCP
27 bool "Enable HDMI HDCP support in MSM DRM driver"
28 depends on DRM_MSM && QCOM_SCM
29 default y
30 help
31 Choose this option to enable HDCP state machine
32
26config DRM_MSM_DSI 33config DRM_MSM_DSI
27 bool "Enable DSI support in MSM DRM driver" 34 bool "Enable DSI support in MSM DRM driver"
28 depends on DRM_MSM 35 depends on DRM_MSM
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index ddb4c9d097e4..60cb02624dc0 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -10,7 +10,6 @@ msm-y := \
10 hdmi/hdmi_audio.o \ 10 hdmi/hdmi_audio.o \
11 hdmi/hdmi_bridge.o \ 11 hdmi/hdmi_bridge.o \
12 hdmi/hdmi_connector.o \ 12 hdmi/hdmi_connector.o \
13 hdmi/hdmi_hdcp.o \
14 hdmi/hdmi_i2c.o \ 13 hdmi/hdmi_i2c.o \
15 hdmi/hdmi_phy.o \ 14 hdmi/hdmi_phy.o \
16 hdmi/hdmi_phy_8960.o \ 15 hdmi/hdmi_phy_8960.o \
@@ -40,8 +39,10 @@ msm-y := \
40 mdp/mdp5/mdp5_plane.o \ 39 mdp/mdp5/mdp5_plane.o \
41 mdp/mdp5/mdp5_smp.o \ 40 mdp/mdp5/mdp5_smp.o \
42 msm_atomic.o \ 41 msm_atomic.o \
42 msm_debugfs.o \
43 msm_drv.o \ 43 msm_drv.o \
44 msm_fb.o \ 44 msm_fb.o \
45 msm_fence.o \
45 msm_gem.o \ 46 msm_gem.o \
46 msm_gem_prime.o \ 47 msm_gem_prime.o \
47 msm_gem_submit.o \ 48 msm_gem_submit.o \
@@ -56,6 +57,8 @@ msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o
56msm-$(CONFIG_COMMON_CLK) += hdmi/hdmi_pll_8960.o 57msm-$(CONFIG_COMMON_CLK) += hdmi/hdmi_pll_8960.o
57msm-$(CONFIG_COMMON_CLK) += hdmi/hdmi_phy_8996.o 58msm-$(CONFIG_COMMON_CLK) += hdmi/hdmi_phy_8996.o
58 59
60msm-$(CONFIG_DRM_MSM_HDMI_HDCP) += hdmi/hdmi_hdcp.o
61
59msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \ 62msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \
60 mdp/mdp4/mdp4_dsi_encoder.o \ 63 mdp/mdp4/mdp4_dsi_encoder.o \
61 dsi/dsi_cfg.o \ 64 dsi/dsi_cfg.o \
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 4951172ede06..fbe304ee6c80 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -120,8 +120,8 @@ void adreno_recover(struct msm_gpu *gpu)
120 /* reset ringbuffer: */ 120 /* reset ringbuffer: */
121 gpu->rb->cur = gpu->rb->start; 121 gpu->rb->cur = gpu->rb->start;
122 122
123 /* reset completed fence seqno, just discard anything pending: */ 123 /* reset completed fence seqno: */
124 adreno_gpu->memptrs->fence = gpu->submitted_fence; 124 adreno_gpu->memptrs->fence = gpu->fctx->completed_fence;
125 adreno_gpu->memptrs->rptr = 0; 125 adreno_gpu->memptrs->rptr = 0;
126 adreno_gpu->memptrs->wptr = 0; 126 adreno_gpu->memptrs->wptr = 0;
127 127
@@ -133,7 +133,7 @@ void adreno_recover(struct msm_gpu *gpu)
133 } 133 }
134} 134}
135 135
136int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, 136void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
137 struct msm_file_private *ctx) 137 struct msm_file_private *ctx)
138{ 138{
139 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 139 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -168,7 +168,7 @@ int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
168 OUT_PKT2(ring); 168 OUT_PKT2(ring);
169 169
170 OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1); 170 OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1);
171 OUT_RING(ring, submit->fence); 171 OUT_RING(ring, submit->fence->seqno);
172 172
173 if (adreno_is_a3xx(adreno_gpu) || adreno_is_a4xx(adreno_gpu)) { 173 if (adreno_is_a3xx(adreno_gpu) || adreno_is_a4xx(adreno_gpu)) {
174 /* Flush HLSQ lazy updates to make sure there is nothing 174 /* Flush HLSQ lazy updates to make sure there is nothing
@@ -185,7 +185,7 @@ int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
185 OUT_PKT3(ring, CP_EVENT_WRITE, 3); 185 OUT_PKT3(ring, CP_EVENT_WRITE, 3);
186 OUT_RING(ring, CACHE_FLUSH_TS); 186 OUT_RING(ring, CACHE_FLUSH_TS);
187 OUT_RING(ring, rbmemptr(adreno_gpu, fence)); 187 OUT_RING(ring, rbmemptr(adreno_gpu, fence));
188 OUT_RING(ring, submit->fence); 188 OUT_RING(ring, submit->fence->seqno);
189 189
190 /* we could maybe be clever and only CP_COND_EXEC the interrupt: */ 190 /* we could maybe be clever and only CP_COND_EXEC the interrupt: */
191 OUT_PKT3(ring, CP_INTERRUPT, 1); 191 OUT_PKT3(ring, CP_INTERRUPT, 1);
@@ -212,8 +212,6 @@ int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
212#endif 212#endif
213 213
214 gpu->funcs->flush(gpu); 214 gpu->funcs->flush(gpu);
215
216 return 0;
217} 215}
218 216
219void adreno_flush(struct msm_gpu *gpu) 217void adreno_flush(struct msm_gpu *gpu)
@@ -254,7 +252,7 @@ void adreno_show(struct msm_gpu *gpu, struct seq_file *m)
254 adreno_gpu->rev.patchid); 252 adreno_gpu->rev.patchid);
255 253
256 seq_printf(m, "fence: %d/%d\n", adreno_gpu->memptrs->fence, 254 seq_printf(m, "fence: %d/%d\n", adreno_gpu->memptrs->fence,
257 gpu->submitted_fence); 255 gpu->fctx->last_fence);
258 seq_printf(m, "rptr: %d\n", get_rptr(adreno_gpu)); 256 seq_printf(m, "rptr: %d\n", get_rptr(adreno_gpu));
259 seq_printf(m, "wptr: %d\n", adreno_gpu->memptrs->wptr); 257 seq_printf(m, "wptr: %d\n", adreno_gpu->memptrs->wptr);
260 seq_printf(m, "rb wptr: %d\n", get_wptr(gpu->rb)); 258 seq_printf(m, "rb wptr: %d\n", get_wptr(gpu->rb));
@@ -295,7 +293,7 @@ void adreno_dump_info(struct msm_gpu *gpu)
295 adreno_gpu->rev.patchid); 293 adreno_gpu->rev.patchid);
296 294
297 printk("fence: %d/%d\n", adreno_gpu->memptrs->fence, 295 printk("fence: %d/%d\n", adreno_gpu->memptrs->fence,
298 gpu->submitted_fence); 296 gpu->fctx->last_fence);
299 printk("rptr: %d\n", get_rptr(adreno_gpu)); 297 printk("rptr: %d\n", get_rptr(adreno_gpu));
300 printk("wptr: %d\n", adreno_gpu->memptrs->wptr); 298 printk("wptr: %d\n", adreno_gpu->memptrs->wptr);
301 printk("rb wptr: %d\n", get_wptr(gpu->rb)); 299 printk("rb wptr: %d\n", get_wptr(gpu->rb));
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index 1d07511f4d22..a54f6e036b4a 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -238,7 +238,7 @@ int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value);
238int adreno_hw_init(struct msm_gpu *gpu); 238int adreno_hw_init(struct msm_gpu *gpu);
239uint32_t adreno_last_fence(struct msm_gpu *gpu); 239uint32_t adreno_last_fence(struct msm_gpu *gpu);
240void adreno_recover(struct msm_gpu *gpu); 240void adreno_recover(struct msm_gpu *gpu);
241int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, 241void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
242 struct msm_file_private *ctx); 242 struct msm_file_private *ctx);
243void adreno_flush(struct msm_gpu *gpu); 243void adreno_flush(struct msm_gpu *gpu);
244void adreno_idle(struct msm_gpu *gpu); 244void adreno_idle(struct msm_gpu *gpu);
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 749fbb28ec3d..03f115f532c2 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -41,8 +41,6 @@ enum msm_dsi_phy_type {
41/* Regulators for DSI devices */ 41/* Regulators for DSI devices */
42struct dsi_reg_entry { 42struct dsi_reg_entry {
43 char name[32]; 43 char name[32];
44 int min_voltage;
45 int max_voltage;
46 int enable_load; 44 int enable_load;
47 int disable_load; 45 int disable_load;
48}; 46};
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
index e58e9b91b34d..93c1ee094eac 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
@@ -22,9 +22,9 @@ static const struct msm_dsi_config apq8064_dsi_cfg = {
22 .reg_cfg = { 22 .reg_cfg = {
23 .num = 3, 23 .num = 3,
24 .regs = { 24 .regs = {
25 {"vdda", 1200000, 1200000, 100000, 100}, 25 {"vdda", 100000, 100}, /* 1.2 V */
26 {"avdd", 3000000, 3000000, 110000, 100}, 26 {"avdd", 10000, 100}, /* 3.0 V */
27 {"vddio", 1800000, 1800000, 100000, 100}, 27 {"vddio", 100000, 100}, /* 1.8 V */
28 }, 28 },
29 }, 29 },
30 .bus_clk_names = dsi_v2_bus_clk_names, 30 .bus_clk_names = dsi_v2_bus_clk_names,
@@ -40,10 +40,10 @@ static const struct msm_dsi_config msm8974_apq8084_dsi_cfg = {
40 .reg_cfg = { 40 .reg_cfg = {
41 .num = 4, 41 .num = 4,
42 .regs = { 42 .regs = {
43 {"gdsc", -1, -1, -1, -1}, 43 {"gdsc", -1, -1},
44 {"vdd", 3000000, 3000000, 150000, 100}, 44 {"vdd", 150000, 100}, /* 3.0 V */
45 {"vdda", 1200000, 1200000, 100000, 100}, 45 {"vdda", 100000, 100}, /* 1.2 V */
46 {"vddio", 1800000, 1800000, 100000, 100}, 46 {"vddio", 100000, 100}, /* 1.8 V */
47 }, 47 },
48 }, 48 },
49 .bus_clk_names = dsi_6g_bus_clk_names, 49 .bus_clk_names = dsi_6g_bus_clk_names,
@@ -59,9 +59,9 @@ static const struct msm_dsi_config msm8916_dsi_cfg = {
59 .reg_cfg = { 59 .reg_cfg = {
60 .num = 3, 60 .num = 3,
61 .regs = { 61 .regs = {
62 {"gdsc", -1, -1, -1, -1}, 62 {"gdsc", -1, -1},
63 {"vdda", 1200000, 1200000, 100000, 100}, 63 {"vdda", 100000, 100}, /* 1.2 V */
64 {"vddio", 1800000, 1800000, 100000, 100}, 64 {"vddio", 100000, 100}, /* 1.8 V */
65 }, 65 },
66 }, 66 },
67 .bus_clk_names = dsi_8916_bus_clk_names, 67 .bus_clk_names = dsi_8916_bus_clk_names,
@@ -73,13 +73,13 @@ static const struct msm_dsi_config msm8994_dsi_cfg = {
73 .reg_cfg = { 73 .reg_cfg = {
74 .num = 7, 74 .num = 7,
75 .regs = { 75 .regs = {
76 {"gdsc", -1, -1, -1, -1}, 76 {"gdsc", -1, -1},
77 {"vdda", 1250000, 1250000, 100000, 100}, 77 {"vdda", 100000, 100}, /* 1.25 V */
78 {"vddio", 1800000, 1800000, 100000, 100}, 78 {"vddio", 100000, 100}, /* 1.8 V */
79 {"vcca", 1000000, 1000000, 10000, 100}, 79 {"vcca", 10000, 100}, /* 1.0 V */
80 {"vdd", 1800000, 1800000, 100000, 100}, 80 {"vdd", 100000, 100}, /* 1.8 V */
81 {"lab_reg", -1, -1, -1, -1}, 81 {"lab_reg", -1, -1},
82 {"ibb_reg", -1, -1, -1, -1}, 82 {"ibb_reg", -1, -1},
83 }, 83 },
84 }, 84 },
85 .bus_clk_names = dsi_6g_bus_clk_names, 85 .bus_clk_names = dsi_6g_bus_clk_names,
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 4282ec6bbaaf..a3e47ad83eb3 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -325,18 +325,6 @@ static int dsi_regulator_init(struct msm_dsi_host *msm_host)
325 return ret; 325 return ret;
326 } 326 }
327 327
328 for (i = 0; i < num; i++) {
329 if (regulator_can_change_voltage(s[i].consumer)) {
330 ret = regulator_set_voltage(s[i].consumer,
331 regs[i].min_voltage, regs[i].max_voltage);
332 if (ret < 0) {
333 pr_err("regulator %d set voltage failed, %d\n",
334 i, ret);
335 return ret;
336 }
337 }
338 }
339
340 return 0; 328 return 0;
341} 329}
342 330
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 58ba7ec17f51..c8d1f19c9a6d 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -198,9 +198,13 @@ static enum drm_connector_status dsi_mgr_connector_detect(
198 198
199static void dsi_mgr_connector_destroy(struct drm_connector *connector) 199static void dsi_mgr_connector_destroy(struct drm_connector *connector)
200{ 200{
201 struct dsi_connector *dsi_connector = to_dsi_connector(connector);
202
201 DBG(""); 203 DBG("");
202 drm_connector_unregister(connector); 204
203 drm_connector_cleanup(connector); 205 drm_connector_cleanup(connector);
206
207 kfree(dsi_connector);
204} 208}
205 209
206static void dsi_dual_connector_fix_modes(struct drm_connector *connector) 210static void dsi_dual_connector_fix_modes(struct drm_connector *connector)
@@ -538,12 +542,9 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id)
538 struct dsi_connector *dsi_connector; 542 struct dsi_connector *dsi_connector;
539 int ret, i; 543 int ret, i;
540 544
541 dsi_connector = devm_kzalloc(msm_dsi->dev->dev, 545 dsi_connector = kzalloc(sizeof(*dsi_connector), GFP_KERNEL);
542 sizeof(*dsi_connector), GFP_KERNEL); 546 if (!dsi_connector)
543 if (!dsi_connector) { 547 return ERR_PTR(-ENOMEM);
544 ret = -ENOMEM;
545 goto fail;
546 }
547 548
548 dsi_connector->id = id; 549 dsi_connector->id = id;
549 550
@@ -552,7 +553,7 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id)
552 ret = drm_connector_init(msm_dsi->dev, connector, 553 ret = drm_connector_init(msm_dsi->dev, connector,
553 &dsi_mgr_connector_funcs, DRM_MODE_CONNECTOR_DSI); 554 &dsi_mgr_connector_funcs, DRM_MODE_CONNECTOR_DSI);
554 if (ret) 555 if (ret)
555 goto fail; 556 return ERR_PTR(ret);
556 557
557 drm_connector_helper_add(connector, &dsi_mgr_conn_helper_funcs); 558 drm_connector_helper_add(connector, &dsi_mgr_conn_helper_funcs);
558 559
@@ -565,21 +566,11 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id)
565 connector->interlace_allowed = 0; 566 connector->interlace_allowed = 0;
566 connector->doublescan_allowed = 0; 567 connector->doublescan_allowed = 0;
567 568
568 ret = drm_connector_register(connector);
569 if (ret)
570 goto fail;
571
572 for (i = 0; i < MSM_DSI_ENCODER_NUM; i++) 569 for (i = 0; i < MSM_DSI_ENCODER_NUM; i++)
573 drm_mode_connector_attach_encoder(connector, 570 drm_mode_connector_attach_encoder(connector,
574 msm_dsi->encoders[i]); 571 msm_dsi->encoders[i]);
575 572
576 return connector; 573 return connector;
577
578fail:
579 if (connector)
580 dsi_mgr_connector_destroy(connector);
581
582 return ERR_PTR(ret);
583} 574}
584 575
585/* initialize bridge */ 576/* initialize bridge */
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index 91a95fb04a4a..e2f42d8ea294 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -177,19 +177,6 @@ static int dsi_phy_regulator_init(struct msm_dsi_phy *phy)
177 return ret; 177 return ret;
178 } 178 }
179 179
180 for (i = 0; i < num; i++) {
181 if (regulator_can_change_voltage(s[i].consumer)) {
182 ret = regulator_set_voltage(s[i].consumer,
183 regs[i].min_voltage, regs[i].max_voltage);
184 if (ret < 0) {
185 dev_err(dev,
186 "regulator %d set voltage failed, %d\n",
187 i, ret);
188 return ret;
189 }
190 }
191 }
192
193 return 0; 180 return 0;
194} 181}
195 182
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c
index 2e9ba118d50a..f4bc11af849a 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c
@@ -138,8 +138,8 @@ const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs = {
138 .reg_cfg = { 138 .reg_cfg = {
139 .num = 2, 139 .num = 2,
140 .regs = { 140 .regs = {
141 {"vddio", 1800000, 1800000, 100000, 100}, 141 {"vddio", 100000, 100}, /* 1.8 V */
142 {"vcca", 1000000, 1000000, 10000, 100}, 142 {"vcca", 10000, 100}, /* 1.0 V */
143 }, 143 },
144 }, 144 },
145 .ops = { 145 .ops = {
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
index edf74110ced7..96d1852af418 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
@@ -138,7 +138,7 @@ const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_cfgs = {
138 .reg_cfg = { 138 .reg_cfg = {
139 .num = 1, 139 .num = 1,
140 .regs = { 140 .regs = {
141 {"vddio", 1800000, 1800000, 100000, 100}, 141 {"vddio", 100000, 100},
142 }, 142 },
143 }, 143 },
144 .ops = { 144 .ops = {
@@ -153,7 +153,7 @@ const struct msm_dsi_phy_cfg dsi_phy_28nm_lp_cfgs = {
153 .reg_cfg = { 153 .reg_cfg = {
154 .num = 1, 154 .num = 1,
155 .regs = { 155 .regs = {
156 {"vddio", 1800000, 1800000, 100000, 100}, 156 {"vddio", 100000, 100}, /* 1.8 V */
157 }, 157 },
158 }, 158 },
159 .ops = { 159 .ops = {
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
index 197b039ca1f1..213355a3e767 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
@@ -185,7 +185,7 @@ const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs = {
185 .reg_cfg = { 185 .reg_cfg = {
186 .num = 1, 186 .num = 1,
187 .regs = { 187 .regs = {
188 {"vddio", 1800000, 1800000, 100000, 100}, 188 {"vddio", 100000, 100}, /* 1.8 V */
189 }, 189 },
190 }, 190 },
191 .ops = { 191 .ops = {
diff --git a/drivers/gpu/drm/msm/edp/edp_connector.c b/drivers/gpu/drm/msm/edp/edp_connector.c
index b4d1b469862a..72360cd038c0 100644
--- a/drivers/gpu/drm/msm/edp/edp_connector.c
+++ b/drivers/gpu/drm/msm/edp/edp_connector.c
@@ -37,7 +37,7 @@ static void edp_connector_destroy(struct drm_connector *connector)
37 struct edp_connector *edp_connector = to_edp_connector(connector); 37 struct edp_connector *edp_connector = to_edp_connector(connector);
38 38
39 DBG(""); 39 DBG("");
40 drm_connector_unregister(connector); 40
41 drm_connector_cleanup(connector); 41 drm_connector_cleanup(connector);
42 42
43 kfree(edp_connector); 43 kfree(edp_connector);
@@ -124,10 +124,8 @@ struct drm_connector *msm_edp_connector_init(struct msm_edp *edp)
124 int ret; 124 int ret;
125 125
126 edp_connector = kzalloc(sizeof(*edp_connector), GFP_KERNEL); 126 edp_connector = kzalloc(sizeof(*edp_connector), GFP_KERNEL);
127 if (!edp_connector) { 127 if (!edp_connector)
128 ret = -ENOMEM; 128 return ERR_PTR(-ENOMEM);
129 goto fail;
130 }
131 129
132 edp_connector->edp = edp; 130 edp_connector->edp = edp;
133 131
@@ -136,7 +134,7 @@ struct drm_connector *msm_edp_connector_init(struct msm_edp *edp)
136 ret = drm_connector_init(edp->dev, connector, &edp_connector_funcs, 134 ret = drm_connector_init(edp->dev, connector, &edp_connector_funcs,
137 DRM_MODE_CONNECTOR_eDP); 135 DRM_MODE_CONNECTOR_eDP);
138 if (ret) 136 if (ret)
139 goto fail; 137 return ERR_PTR(ret);
140 138
141 drm_connector_helper_add(connector, &edp_connector_helper_funcs); 139 drm_connector_helper_add(connector, &edp_connector_helper_funcs);
142 140
@@ -147,17 +145,7 @@ struct drm_connector *msm_edp_connector_init(struct msm_edp *edp)
147 connector->interlace_allowed = false; 145 connector->interlace_allowed = false;
148 connector->doublescan_allowed = false; 146 connector->doublescan_allowed = false;
149 147
150 ret = drm_connector_register(connector);
151 if (ret)
152 goto fail;
153
154 drm_mode_connector_attach_encoder(connector, edp->encoder); 148 drm_mode_connector_attach_encoder(connector, edp->encoder);
155 149
156 return connector; 150 return connector;
157
158fail:
159 if (connector)
160 edp_connector_destroy(connector);
161
162 return ERR_PTR(ret);
163} 151}
diff --git a/drivers/gpu/drm/msm/edp/edp_ctrl.c b/drivers/gpu/drm/msm/edp/edp_ctrl.c
index 81200e9be382..149bfe7ddd82 100644
--- a/drivers/gpu/drm/msm/edp/edp_ctrl.c
+++ b/drivers/gpu/drm/msm/edp/edp_ctrl.c
@@ -21,8 +21,6 @@
21#include "edp.h" 21#include "edp.h"
22#include "edp.xml.h" 22#include "edp.xml.h"
23 23
24#define VDDA_MIN_UV 1800000 /* uV units */
25#define VDDA_MAX_UV 1800000 /* uV units */
26#define VDDA_UA_ON_LOAD 100000 /* uA units */ 24#define VDDA_UA_ON_LOAD 100000 /* uA units */
27#define VDDA_UA_OFF_LOAD 100 /* uA units */ 25#define VDDA_UA_OFF_LOAD 100 /* uA units */
28 26
@@ -67,7 +65,7 @@ struct edp_ctrl {
67 void __iomem *base; 65 void __iomem *base;
68 66
69 /* regulators */ 67 /* regulators */
70 struct regulator *vdda_vreg; 68 struct regulator *vdda_vreg; /* 1.8 V */
71 struct regulator *lvl_vreg; 69 struct regulator *lvl_vreg;
72 70
73 /* clocks */ 71 /* clocks */
@@ -302,21 +300,24 @@ static void edp_clk_disable(struct edp_ctrl *ctrl, u32 clk_mask)
302static int edp_regulator_init(struct edp_ctrl *ctrl) 300static int edp_regulator_init(struct edp_ctrl *ctrl)
303{ 301{
304 struct device *dev = &ctrl->pdev->dev; 302 struct device *dev = &ctrl->pdev->dev;
303 int ret;
305 304
306 DBG(""); 305 DBG("");
307 ctrl->vdda_vreg = devm_regulator_get(dev, "vdda"); 306 ctrl->vdda_vreg = devm_regulator_get(dev, "vdda");
308 if (IS_ERR(ctrl->vdda_vreg)) { 307 ret = PTR_ERR_OR_ZERO(ctrl->vdda_vreg);
309 pr_err("%s: Could not get vdda reg, ret = %ld\n", __func__, 308 if (ret) {
310 PTR_ERR(ctrl->vdda_vreg)); 309 pr_err("%s: Could not get vdda reg, ret = %d\n", __func__,
310 ret);
311 ctrl->vdda_vreg = NULL; 311 ctrl->vdda_vreg = NULL;
312 return PTR_ERR(ctrl->vdda_vreg); 312 return ret;
313 } 313 }
314 ctrl->lvl_vreg = devm_regulator_get(dev, "lvl-vdd"); 314 ctrl->lvl_vreg = devm_regulator_get(dev, "lvl-vdd");
315 if (IS_ERR(ctrl->lvl_vreg)) { 315 ret = PTR_ERR_OR_ZERO(ctrl->lvl_vreg);
316 pr_err("Could not get lvl-vdd reg, %ld", 316 if (ret) {
317 PTR_ERR(ctrl->lvl_vreg)); 317 pr_err("%s: Could not get lvl-vdd reg, ret = %d\n", __func__,
318 ret);
318 ctrl->lvl_vreg = NULL; 319 ctrl->lvl_vreg = NULL;
319 return PTR_ERR(ctrl->lvl_vreg); 320 return ret;
320 } 321 }
321 322
322 return 0; 323 return 0;
@@ -326,12 +327,6 @@ static int edp_regulator_enable(struct edp_ctrl *ctrl)
326{ 327{
327 int ret; 328 int ret;
328 329
329 ret = regulator_set_voltage(ctrl->vdda_vreg, VDDA_MIN_UV, VDDA_MAX_UV);
330 if (ret) {
331 pr_err("%s:vdda_vreg set_voltage failed, %d\n", __func__, ret);
332 goto vdda_set_fail;
333 }
334
335 ret = regulator_set_load(ctrl->vdda_vreg, VDDA_UA_ON_LOAD); 330 ret = regulator_set_load(ctrl->vdda_vreg, VDDA_UA_ON_LOAD);
336 if (ret < 0) { 331 if (ret < 0) {
337 pr_err("%s: vdda_vreg set regulator mode failed.\n", __func__); 332 pr_err("%s: vdda_vreg set regulator mode failed.\n", __func__);
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 65428cf233ce..bc7ba0bdee07 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -243,10 +243,21 @@ struct i2c_adapter *msm_hdmi_i2c_init(struct hdmi *hdmi);
243/* 243/*
244 * hdcp 244 * hdcp
245 */ 245 */
246#ifdef CONFIG_DRM_MSM_HDMI_HDCP
246struct hdmi_hdcp_ctrl *msm_hdmi_hdcp_init(struct hdmi *hdmi); 247struct hdmi_hdcp_ctrl *msm_hdmi_hdcp_init(struct hdmi *hdmi);
247void msm_hdmi_hdcp_destroy(struct hdmi *hdmi); 248void msm_hdmi_hdcp_destroy(struct hdmi *hdmi);
248void msm_hdmi_hdcp_on(struct hdmi_hdcp_ctrl *hdcp_ctrl); 249void msm_hdmi_hdcp_on(struct hdmi_hdcp_ctrl *hdcp_ctrl);
249void msm_hdmi_hdcp_off(struct hdmi_hdcp_ctrl *hdcp_ctrl); 250void msm_hdmi_hdcp_off(struct hdmi_hdcp_ctrl *hdcp_ctrl);
250void msm_hdmi_hdcp_irq(struct hdmi_hdcp_ctrl *hdcp_ctrl); 251void msm_hdmi_hdcp_irq(struct hdmi_hdcp_ctrl *hdcp_ctrl);
252#else
253static inline struct hdmi_hdcp_ctrl *msm_hdmi_hdcp_init(struct hdmi *hdmi)
254{
255 return ERR_PTR(-ENXIO);
256}
257static inline void msm_hdmi_hdcp_destroy(struct hdmi *hdmi) {}
258static inline void msm_hdmi_hdcp_on(struct hdmi_hdcp_ctrl *hdcp_ctrl) {}
259static inline void msm_hdmi_hdcp_off(struct hdmi_hdcp_ctrl *hdcp_ctrl) {}
260static inline void msm_hdmi_hdcp_irq(struct hdmi_hdcp_ctrl *hdcp_ctrl) {}
261#endif
251 262
252#endif /* __HDMI_CONNECTOR_H__ */ 263#endif /* __HDMI_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
index 26129bff2dd6..b15d72683112 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
@@ -112,6 +112,9 @@ static int gpio_config(struct hdmi *hdmi, bool on)
112 for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) { 112 for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) {
113 struct hdmi_gpio_data gpio = config->gpios[i]; 113 struct hdmi_gpio_data gpio = config->gpios[i];
114 114
115 if (gpio.num == -1)
116 continue;
117
115 if (gpio.output) { 118 if (gpio.output) {
116 int value = gpio.value ? 0 : 1; 119 int value = gpio.value ? 0 : 1;
117 120
@@ -126,8 +129,10 @@ static int gpio_config(struct hdmi *hdmi, bool on)
126 129
127 return 0; 130 return 0;
128err: 131err:
129 while (i--) 132 while (i--) {
130 gpio_free(config->gpios[i].num); 133 if (config->gpios[i].num != -1)
134 gpio_free(config->gpios[i].num);
135 }
131 136
132 return ret; 137 return ret;
133} 138}
@@ -341,7 +346,6 @@ static void hdmi_connector_destroy(struct drm_connector *connector)
341 346
342 hdp_disable(hdmi_connector); 347 hdp_disable(hdmi_connector);
343 348
344 drm_connector_unregister(connector);
345 drm_connector_cleanup(connector); 349 drm_connector_cleanup(connector);
346 350
347 kfree(hdmi_connector); 351 kfree(hdmi_connector);
@@ -433,10 +437,8 @@ struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)
433 int ret; 437 int ret;
434 438
435 hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL); 439 hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL);
436 if (!hdmi_connector) { 440 if (!hdmi_connector)
437 ret = -ENOMEM; 441 return ERR_PTR(-ENOMEM);
438 goto fail;
439 }
440 442
441 hdmi_connector->hdmi = hdmi; 443 hdmi_connector->hdmi = hdmi;
442 INIT_WORK(&hdmi_connector->hpd_work, msm_hdmi_hotplug_work); 444 INIT_WORK(&hdmi_connector->hpd_work, msm_hdmi_hotplug_work);
@@ -453,21 +455,13 @@ struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)
453 connector->interlace_allowed = 0; 455 connector->interlace_allowed = 0;
454 connector->doublescan_allowed = 0; 456 connector->doublescan_allowed = 0;
455 457
456 drm_connector_register(connector);
457
458 ret = hpd_enable(hdmi_connector); 458 ret = hpd_enable(hdmi_connector);
459 if (ret) { 459 if (ret) {
460 dev_err(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret); 460 dev_err(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret);
461 goto fail; 461 return ERR_PTR(ret);
462 } 462 }
463 463
464 drm_mode_connector_attach_encoder(connector, hdmi->encoder); 464 drm_mode_connector_attach_encoder(connector, hdmi->encoder);
465 465
466 return connector; 466 return connector;
467
468fail:
469 if (connector)
470 hdmi_connector_destroy(connector);
471
472 return ERR_PTR(ret);
473} 467}
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
index e233acf52334..9527dafc3e69 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
@@ -121,7 +121,7 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
121 if (!file || (event->base.file_priv == file)) { 121 if (!file || (event->base.file_priv == file)) {
122 mdp4_crtc->event = NULL; 122 mdp4_crtc->event = NULL;
123 DBG("%s: send event: %p", mdp4_crtc->name, event); 123 DBG("%s: send event: %p", mdp4_crtc->name, event);
124 drm_send_vblank_event(dev, mdp4_crtc->id, event); 124 drm_crtc_send_vblank_event(crtc, event);
125 } 125 }
126 } 126 }
127 spin_unlock_irqrestore(&dev->event_lock, flags); 127 spin_unlock_irqrestore(&dev->event_lock, flags);
@@ -427,7 +427,7 @@ static int mdp4_crtc_cursor_set(struct drm_crtc *crtc,
427 } 427 }
428 428
429 if (handle) { 429 if (handle) {
430 cursor_bo = drm_gem_object_lookup(dev, file_priv, handle); 430 cursor_bo = drm_gem_object_lookup(file_priv, handle);
431 if (!cursor_bo) 431 if (!cursor_bo)
432 return -ENOENT; 432 return -ENOENT;
433 } else { 433 } else {
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
index 76e1dfb5d25e..67442d50a6c2 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
@@ -50,30 +50,6 @@ static int mdp4_hw_init(struct msm_kms *kms)
50 50
51 mdp4_kms->rev = minor; 51 mdp4_kms->rev = minor;
52 52
53 if (mdp4_kms->dsi_pll_vdda) {
54 if ((mdp4_kms->rev == 2) || (mdp4_kms->rev == 4)) {
55 ret = regulator_set_voltage(mdp4_kms->dsi_pll_vdda,
56 1200000, 1200000);
57 if (ret) {
58 dev_err(dev->dev,
59 "failed to set dsi_pll_vdda voltage: %d\n", ret);
60 goto out;
61 }
62 }
63 }
64
65 if (mdp4_kms->dsi_pll_vddio) {
66 if (mdp4_kms->rev == 2) {
67 ret = regulator_set_voltage(mdp4_kms->dsi_pll_vddio,
68 1800000, 1800000);
69 if (ret) {
70 dev_err(dev->dev,
71 "failed to set dsi_pll_vddio voltage: %d\n", ret);
72 goto out;
73 }
74 }
75 }
76
77 if (mdp4_kms->rev > 1) { 53 if (mdp4_kms->rev > 1) {
78 mdp4_write(mdp4_kms, REG_MDP4_CS_CONTROLLER0, 0x0707ffff); 54 mdp4_write(mdp4_kms, REG_MDP4_CS_CONTROLLER0, 0x0707ffff);
79 mdp4_write(mdp4_kms, REG_MDP4_CS_CONTROLLER1, 0x03073f3f); 55 mdp4_write(mdp4_kms, REG_MDP4_CS_CONTROLLER1, 0x03073f3f);
@@ -485,16 +461,6 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
485 goto fail; 461 goto fail;
486 } 462 }
487 463
488 mdp4_kms->dsi_pll_vdda =
489 devm_regulator_get_optional(&pdev->dev, "dsi_pll_vdda");
490 if (IS_ERR(mdp4_kms->dsi_pll_vdda))
491 mdp4_kms->dsi_pll_vdda = NULL;
492
493 mdp4_kms->dsi_pll_vddio =
494 devm_regulator_get_optional(&pdev->dev, "dsi_pll_vddio");
495 if (IS_ERR(mdp4_kms->dsi_pll_vddio))
496 mdp4_kms->dsi_pll_vddio = NULL;
497
498 /* NOTE: driver for this regulator still missing upstream.. use 464 /* NOTE: driver for this regulator still missing upstream.. use
499 * _get_exclusive() and ignore the error if it does not exist 465 * _get_exclusive() and ignore the error if it does not exist
500 * (and hope that the bootloader left it on for us) 466 * (and hope that the bootloader left it on for us)
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
index b2828717be2a..c5d045d5680d 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
@@ -37,8 +37,6 @@ struct mdp4_kms {
37 37
38 void __iomem *mmio; 38 void __iomem *mmio;
39 39
40 struct regulator *dsi_pll_vdda;
41 struct regulator *dsi_pll_vddio;
42 struct regulator *vdd; 40 struct regulator *vdd;
43 41
44 struct clk *clk; 42 struct clk *clk;
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c
index e73e1742b250..2648cd7631ef 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c
@@ -48,7 +48,6 @@ static void mdp4_lvds_connector_destroy(struct drm_connector *connector)
48 struct mdp4_lvds_connector *mdp4_lvds_connector = 48 struct mdp4_lvds_connector *mdp4_lvds_connector =
49 to_mdp4_lvds_connector(connector); 49 to_mdp4_lvds_connector(connector);
50 50
51 drm_connector_unregister(connector);
52 drm_connector_cleanup(connector); 51 drm_connector_cleanup(connector);
53 52
54 kfree(mdp4_lvds_connector); 53 kfree(mdp4_lvds_connector);
@@ -121,13 +120,10 @@ struct drm_connector *mdp4_lvds_connector_init(struct drm_device *dev,
121{ 120{
122 struct drm_connector *connector = NULL; 121 struct drm_connector *connector = NULL;
123 struct mdp4_lvds_connector *mdp4_lvds_connector; 122 struct mdp4_lvds_connector *mdp4_lvds_connector;
124 int ret;
125 123
126 mdp4_lvds_connector = kzalloc(sizeof(*mdp4_lvds_connector), GFP_KERNEL); 124 mdp4_lvds_connector = kzalloc(sizeof(*mdp4_lvds_connector), GFP_KERNEL);
127 if (!mdp4_lvds_connector) { 125 if (!mdp4_lvds_connector)
128 ret = -ENOMEM; 126 return ERR_PTR(-ENOMEM);
129 goto fail;
130 }
131 127
132 mdp4_lvds_connector->encoder = encoder; 128 mdp4_lvds_connector->encoder = encoder;
133 mdp4_lvds_connector->panel_node = panel_node; 129 mdp4_lvds_connector->panel_node = panel_node;
@@ -143,15 +139,7 @@ struct drm_connector *mdp4_lvds_connector_init(struct drm_device *dev,
143 connector->interlace_allowed = 0; 139 connector->interlace_allowed = 0;
144 connector->doublescan_allowed = 0; 140 connector->doublescan_allowed = 0;
145 141
146 drm_connector_register(connector);
147
148 drm_mode_connector_attach_encoder(connector, encoder); 142 drm_mode_connector_attach_encoder(connector, encoder);
149 143
150 return connector; 144 return connector;
151
152fail:
153 if (connector)
154 mdp4_lvds_connector_destroy(connector);
155
156 return ERR_PTR(ret);
157} 145}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index 9673b9520b6a..88fe256c1931 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -149,7 +149,7 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
149 if (!file || (event->base.file_priv == file)) { 149 if (!file || (event->base.file_priv == file)) {
150 mdp5_crtc->event = NULL; 150 mdp5_crtc->event = NULL;
151 DBG("%s: send event: %p", mdp5_crtc->name, event); 151 DBG("%s: send event: %p", mdp5_crtc->name, event);
152 drm_send_vblank_event(dev, mdp5_crtc->id, event); 152 drm_crtc_send_vblank_event(crtc, event);
153 } 153 }
154 } 154 }
155 spin_unlock_irqrestore(&dev->event_lock, flags); 155 spin_unlock_irqrestore(&dev->event_lock, flags);
@@ -518,7 +518,7 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
518 goto set_cursor; 518 goto set_cursor;
519 } 519 }
520 520
521 cursor_bo = drm_gem_object_lookup(dev, file, handle); 521 cursor_bo = drm_gem_object_lookup(file, handle);
522 if (!cursor_bo) 522 if (!cursor_bo)
523 return -ENOENT; 523 return -ENOENT;
524 524
diff --git a/drivers/gpu/drm/msm/mdp/mdp_format.c b/drivers/gpu/drm/msm/mdp/mdp_format.c
index 1c2caffc97e4..b4a8aa4490ee 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_format.c
+++ b/drivers/gpu/drm/msm/mdp/mdp_format.c
@@ -105,6 +105,12 @@ static const struct mdp_format formats[] = {
105 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), 105 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false),
106 FMT(XRGB8888, 8, 8, 8, 8, 1, 0, 2, 3, false, true, 4, 4, 106 FMT(XRGB8888, 8, 8, 8, 8, 1, 0, 2, 3, false, true, 4, 4,
107 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), 107 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false),
108 FMT(XBGR8888, 8, 8, 8, 8, 2, 0, 1, 3, false, true, 4, 4,
109 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false),
110 FMT(RGBX8888, 8, 8, 8, 8, 3, 1, 0, 2, false, true, 4, 4,
111 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false),
112 FMT(BGRX8888, 8, 8, 8, 8, 3, 2, 0, 1, false, true, 4, 4,
113 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false),
108 FMT(RGB888, 0, 8, 8, 8, 1, 0, 2, 0, false, true, 3, 3, 114 FMT(RGB888, 0, 8, 8, 8, 1, 0, 2, 0, false, true, 3, 3,
109 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), 115 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false),
110 FMT(BGR888, 0, 8, 8, 8, 2, 0, 1, 0, false, true, 3, 3, 116 FMT(BGR888, 0, 8, 8, 8, 2, 0, 1, 0, false, true, 3, 3,
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 7eb253bc24df..e3892c263f27 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -18,16 +18,16 @@
18#include "msm_drv.h" 18#include "msm_drv.h"
19#include "msm_kms.h" 19#include "msm_kms.h"
20#include "msm_gem.h" 20#include "msm_gem.h"
21#include "msm_fence.h"
21 22
22struct msm_commit { 23struct msm_commit {
23 struct drm_device *dev; 24 struct drm_device *dev;
24 struct drm_atomic_state *state; 25 struct drm_atomic_state *state;
25 uint32_t fence; 26 struct work_struct work;
26 struct msm_fence_cb fence_cb;
27 uint32_t crtc_mask; 27 uint32_t crtc_mask;
28}; 28};
29 29
30static void fence_cb(struct msm_fence_cb *cb); 30static void commit_worker(struct work_struct *work);
31 31
32/* block until specified crtcs are no longer pending update, and 32/* block until specified crtcs are no longer pending update, and
33 * atomically mark them as pending update 33 * atomically mark them as pending update
@@ -69,11 +69,7 @@ static struct msm_commit *commit_init(struct drm_atomic_state *state)
69 c->dev = state->dev; 69 c->dev = state->dev;
70 c->state = state; 70 c->state = state;
71 71
72 /* TODO we might need a way to indicate to run the cb on a 72 INIT_WORK(&c->work, commit_worker);
73 * different wq so wait_for_vblanks() doesn't block retiring
74 * bo's..
75 */
76 INIT_FENCE_CB(&c->fence_cb, fence_cb);
77 73
78 return c; 74 return c;
79} 75}
@@ -114,13 +110,15 @@ static void msm_atomic_wait_for_commit_done(struct drm_device *dev,
114/* The (potentially) asynchronous part of the commit. At this point 110/* The (potentially) asynchronous part of the commit. At this point
115 * nothing can fail short of armageddon. 111 * nothing can fail short of armageddon.
116 */ 112 */
117static void complete_commit(struct msm_commit *c) 113static void complete_commit(struct msm_commit *c, bool async)
118{ 114{
119 struct drm_atomic_state *state = c->state; 115 struct drm_atomic_state *state = c->state;
120 struct drm_device *dev = state->dev; 116 struct drm_device *dev = state->dev;
121 struct msm_drm_private *priv = dev->dev_private; 117 struct msm_drm_private *priv = dev->dev_private;
122 struct msm_kms *kms = priv->kms; 118 struct msm_kms *kms = priv->kms;
123 119
120 drm_atomic_helper_wait_for_fences(dev, state);
121
124 kms->funcs->prepare_commit(kms, state); 122 kms->funcs->prepare_commit(kms, state);
125 123
126 drm_atomic_helper_commit_modeset_disables(dev, state); 124 drm_atomic_helper_commit_modeset_disables(dev, state);
@@ -153,17 +151,9 @@ static void complete_commit(struct msm_commit *c)
153 commit_destroy(c); 151 commit_destroy(c);
154} 152}
155 153
156static void fence_cb(struct msm_fence_cb *cb) 154static void commit_worker(struct work_struct *work)
157{
158 struct msm_commit *c =
159 container_of(cb, struct msm_commit, fence_cb);
160 complete_commit(c);
161}
162
163static void add_fb(struct msm_commit *c, struct drm_framebuffer *fb)
164{ 155{
165 struct drm_gem_object *obj = msm_framebuffer_bo(fb, 0); 156 complete_commit(container_of(work, struct msm_commit, work), true);
166 c->fence = max(c->fence, msm_gem_fence(to_msm_bo(obj), MSM_PREP_READ));
167} 157}
168 158
169int msm_atomic_check(struct drm_device *dev, 159int msm_atomic_check(struct drm_device *dev,
@@ -190,21 +180,20 @@ int msm_atomic_check(struct drm_device *dev,
190 * drm_atomic_helper_commit - commit validated state object 180 * drm_atomic_helper_commit - commit validated state object
191 * @dev: DRM device 181 * @dev: DRM device
192 * @state: the driver state object 182 * @state: the driver state object
193 * @async: asynchronous commit 183 * @nonblock: nonblocking commit
194 * 184 *
195 * This function commits a with drm_atomic_helper_check() pre-validated state 185 * This function commits a with drm_atomic_helper_check() pre-validated state
196 * object. This can still fail when e.g. the framebuffer reservation fails. For 186 * object. This can still fail when e.g. the framebuffer reservation fails.
197 * now this doesn't implement asynchronous commits.
198 * 187 *
199 * RETURNS 188 * RETURNS
200 * Zero for success or -errno. 189 * Zero for success or -errno.
201 */ 190 */
202int msm_atomic_commit(struct drm_device *dev, 191int msm_atomic_commit(struct drm_device *dev,
203 struct drm_atomic_state *state, bool async) 192 struct drm_atomic_state *state, bool nonblock)
204{ 193{
194 struct msm_drm_private *priv = dev->dev_private;
205 int nplanes = dev->mode_config.num_total_plane; 195 int nplanes = dev->mode_config.num_total_plane;
206 int ncrtcs = dev->mode_config.num_crtc; 196 int ncrtcs = dev->mode_config.num_crtc;
207 ktime_t timeout;
208 struct msm_commit *c; 197 struct msm_commit *c;
209 int i, ret; 198 int i, ret;
210 199
@@ -238,8 +227,12 @@ int msm_atomic_commit(struct drm_device *dev,
238 if (!plane) 227 if (!plane)
239 continue; 228 continue;
240 229
241 if ((plane->state->fb != new_state->fb) && new_state->fb) 230 if ((plane->state->fb != new_state->fb) && new_state->fb) {
242 add_fb(c, new_state->fb); 231 struct drm_gem_object *obj = msm_framebuffer_bo(new_state->fb, 0);
232 struct msm_gem_object *msm_obj = to_msm_bo(obj);
233
234 new_state->fence = reservation_object_get_excl_rcu(msm_obj->resv);
235 }
243 } 236 }
244 237
245 /* 238 /*
@@ -276,17 +269,12 @@ int msm_atomic_commit(struct drm_device *dev,
276 * current layout. 269 * current layout.
277 */ 270 */
278 271
279 if (async) { 272 if (nonblock) {
280 msm_queue_fence_cb(dev, &c->fence_cb, c->fence); 273 queue_work(priv->atomic_wq, &c->work);
281 return 0; 274 return 0;
282 } 275 }
283 276
284 timeout = ktime_add_ms(ktime_get(), 1000); 277 complete_commit(c, false);
285
286 /* uninterruptible wait */
287 msm_wait_fence(dev, c->fence, &timeout, false);
288
289 complete_commit(c);
290 278
291 return 0; 279 return 0;
292 280
diff --git a/drivers/gpu/drm/msm/msm_debugfs.c b/drivers/gpu/drm/msm/msm_debugfs.c
new file mode 100644
index 000000000000..663f2b6ef091
--- /dev/null
+++ b/drivers/gpu/drm/msm/msm_debugfs.c
@@ -0,0 +1,168 @@
1/*
2 * Copyright (C) 2013-2016 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifdef CONFIG_DEBUG_FS
19#include "msm_drv.h"
20#include "msm_gpu.h"
21
22static int msm_gpu_show(struct drm_device *dev, struct seq_file *m)
23{
24 struct msm_drm_private *priv = dev->dev_private;
25 struct msm_gpu *gpu = priv->gpu;
26
27 if (gpu) {
28 seq_printf(m, "%s Status:\n", gpu->name);
29 gpu->funcs->show(gpu, m);
30 }
31
32 return 0;
33}
34
35static int msm_gem_show(struct drm_device *dev, struct seq_file *m)
36{
37 struct msm_drm_private *priv = dev->dev_private;
38 struct msm_gpu *gpu = priv->gpu;
39
40 if (gpu) {
41 seq_printf(m, "Active Objects (%s):\n", gpu->name);
42 msm_gem_describe_objects(&gpu->active_list, m);
43 }
44
45 seq_printf(m, "Inactive Objects:\n");
46 msm_gem_describe_objects(&priv->inactive_list, m);
47
48 return 0;
49}
50
51static int msm_mm_show(struct drm_device *dev, struct seq_file *m)
52{
53 return drm_mm_dump_table(m, &dev->vma_offset_manager->vm_addr_space_mm);
54}
55
56static int msm_fb_show(struct drm_device *dev, struct seq_file *m)
57{
58 struct msm_drm_private *priv = dev->dev_private;
59 struct drm_framebuffer *fb, *fbdev_fb = NULL;
60
61 if (priv->fbdev) {
62 seq_printf(m, "fbcon ");
63 fbdev_fb = priv->fbdev->fb;
64 msm_framebuffer_describe(fbdev_fb, m);
65 }
66
67 mutex_lock(&dev->mode_config.fb_lock);
68 list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
69 if (fb == fbdev_fb)
70 continue;
71
72 seq_printf(m, "user ");
73 msm_framebuffer_describe(fb, m);
74 }
75 mutex_unlock(&dev->mode_config.fb_lock);
76
77 return 0;
78}
79
80static int show_locked(struct seq_file *m, void *arg)
81{
82 struct drm_info_node *node = (struct drm_info_node *) m->private;
83 struct drm_device *dev = node->minor->dev;
84 int (*show)(struct drm_device *dev, struct seq_file *m) =
85 node->info_ent->data;
86 int ret;
87
88 ret = mutex_lock_interruptible(&dev->struct_mutex);
89 if (ret)
90 return ret;
91
92 ret = show(dev, m);
93
94 mutex_unlock(&dev->struct_mutex);
95
96 return ret;
97}
98
99static struct drm_info_list msm_debugfs_list[] = {
100 {"gpu", show_locked, 0, msm_gpu_show},
101 {"gem", show_locked, 0, msm_gem_show},
102 { "mm", show_locked, 0, msm_mm_show },
103 { "fb", show_locked, 0, msm_fb_show },
104};
105
106static int late_init_minor(struct drm_minor *minor)
107{
108 int ret;
109
110 if (!minor)
111 return 0;
112
113 ret = msm_rd_debugfs_init(minor);
114 if (ret) {
115 dev_err(minor->dev->dev, "could not install rd debugfs\n");
116 return ret;
117 }
118
119 ret = msm_perf_debugfs_init(minor);
120 if (ret) {
121 dev_err(minor->dev->dev, "could not install perf debugfs\n");
122 return ret;
123 }
124
125 return 0;
126}
127
128int msm_debugfs_late_init(struct drm_device *dev)
129{
130 int ret;
131 ret = late_init_minor(dev->primary);
132 if (ret)
133 return ret;
134 ret = late_init_minor(dev->render);
135 if (ret)
136 return ret;
137 ret = late_init_minor(dev->control);
138 return ret;
139}
140
141int msm_debugfs_init(struct drm_minor *minor)
142{
143 struct drm_device *dev = minor->dev;
144 int ret;
145
146 ret = drm_debugfs_create_files(msm_debugfs_list,
147 ARRAY_SIZE(msm_debugfs_list),
148 minor->debugfs_root, minor);
149
150 if (ret) {
151 dev_err(dev->dev, "could not install msm_debugfs_list\n");
152 return ret;
153 }
154
155 return 0;
156}
157
158void msm_debugfs_cleanup(struct drm_minor *minor)
159{
160 drm_debugfs_remove_files(msm_debugfs_list,
161 ARRAY_SIZE(msm_debugfs_list), minor);
162 if (!minor->dev->dev_private)
163 return;
164 msm_rd_debugfs_cleanup(minor);
165 msm_perf_debugfs_cleanup(minor);
166}
167#endif
168
diff --git a/drivers/gpu/drm/msm/msm_debugfs.h b/drivers/gpu/drm/msm/msm_debugfs.h
new file mode 100644
index 000000000000..6110c972fd15
--- /dev/null
+++ b/drivers/gpu/drm/msm/msm_debugfs.h
@@ -0,0 +1,26 @@
1/*
2 * Copyright (C) 2016 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef __MSM_DEBUGFS_H__
19#define __MSM_DEBUGFS_H__
20
21#ifdef CONFIG_DEBUG_FS
22int msm_debugfs_init(struct drm_minor *minor);
23void msm_debugfs_cleanup(struct drm_minor *minor);
24#endif
25
26#endif /* __MSM_DEBUGFS_H__ */
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index c03b96709179..9c654092ef78 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -16,6 +16,8 @@
16 */ 16 */
17 17
18#include "msm_drv.h" 18#include "msm_drv.h"
19#include "msm_debugfs.h"
20#include "msm_fence.h"
19#include "msm_gpu.h" 21#include "msm_gpu.h"
20#include "msm_kms.h" 22#include "msm_kms.h"
21 23
@@ -173,13 +175,11 @@ static int vblank_ctrl_queue_work(struct msm_drm_private *priv,
173 return 0; 175 return 0;
174} 176}
175 177
176/* 178static int msm_drm_uninit(struct device *dev)
177 * DRM operations:
178 */
179
180static int msm_unload(struct drm_device *dev)
181{ 179{
182 struct msm_drm_private *priv = dev->dev_private; 180 struct platform_device *pdev = to_platform_device(dev);
181 struct drm_device *ddev = platform_get_drvdata(pdev);
182 struct msm_drm_private *priv = ddev->dev_private;
183 struct msm_kms *kms = priv->kms; 183 struct msm_kms *kms = priv->kms;
184 struct msm_gpu *gpu = priv->gpu; 184 struct msm_gpu *gpu = priv->gpu;
185 struct msm_vblank_ctrl *vbl_ctrl = &priv->vblank_ctrl; 185 struct msm_vblank_ctrl *vbl_ctrl = &priv->vblank_ctrl;
@@ -195,31 +195,37 @@ static int msm_unload(struct drm_device *dev)
195 kfree(vbl_ev); 195 kfree(vbl_ev);
196 } 196 }
197 197
198 drm_kms_helper_poll_fini(dev); 198 drm_kms_helper_poll_fini(ddev);
199
200 drm_connector_unregister_all(ddev);
201
202 drm_dev_unregister(ddev);
199 203
200#ifdef CONFIG_DRM_FBDEV_EMULATION 204#ifdef CONFIG_DRM_FBDEV_EMULATION
201 if (fbdev && priv->fbdev) 205 if (fbdev && priv->fbdev)
202 msm_fbdev_free(dev); 206 msm_fbdev_free(ddev);
203#endif 207#endif
204 drm_mode_config_cleanup(dev); 208 drm_mode_config_cleanup(ddev);
205 drm_vblank_cleanup(dev);
206 209
207 pm_runtime_get_sync(dev->dev); 210 pm_runtime_get_sync(dev);
208 drm_irq_uninstall(dev); 211 drm_irq_uninstall(ddev);
209 pm_runtime_put_sync(dev->dev); 212 pm_runtime_put_sync(dev);
210 213
211 flush_workqueue(priv->wq); 214 flush_workqueue(priv->wq);
212 destroy_workqueue(priv->wq); 215 destroy_workqueue(priv->wq);
213 216
217 flush_workqueue(priv->atomic_wq);
218 destroy_workqueue(priv->atomic_wq);
219
214 if (kms) { 220 if (kms) {
215 pm_runtime_disable(dev->dev); 221 pm_runtime_disable(dev);
216 kms->funcs->destroy(kms); 222 kms->funcs->destroy(kms);
217 } 223 }
218 224
219 if (gpu) { 225 if (gpu) {
220 mutex_lock(&dev->struct_mutex); 226 mutex_lock(&ddev->struct_mutex);
221 gpu->funcs->pm_suspend(gpu); 227 gpu->funcs->pm_suspend(gpu);
222 mutex_unlock(&dev->struct_mutex); 228 mutex_unlock(&ddev->struct_mutex);
223 gpu->funcs->destroy(gpu); 229 gpu->funcs->destroy(gpu);
224 } 230 }
225 231
@@ -227,13 +233,14 @@ static int msm_unload(struct drm_device *dev)
227 DEFINE_DMA_ATTRS(attrs); 233 DEFINE_DMA_ATTRS(attrs);
228 dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs); 234 dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
229 drm_mm_takedown(&priv->vram.mm); 235 drm_mm_takedown(&priv->vram.mm);
230 dma_free_attrs(dev->dev, priv->vram.size, NULL, 236 dma_free_attrs(dev, priv->vram.size, NULL,
231 priv->vram.paddr, &attrs); 237 priv->vram.paddr, &attrs);
232 } 238 }
233 239
234 component_unbind_all(dev->dev, dev); 240 component_unbind_all(dev, ddev);
235 241
236 dev->dev_private = NULL; 242 ddev->dev_private = NULL;
243 drm_dev_unref(ddev);
237 244
238 kfree(priv); 245 kfree(priv);
239 246
@@ -321,50 +328,60 @@ static int msm_init_vram(struct drm_device *dev)
321 return ret; 328 return ret;
322} 329}
323 330
324static int msm_load(struct drm_device *dev, unsigned long flags) 331static int msm_drm_init(struct device *dev, struct drm_driver *drv)
325{ 332{
326 struct platform_device *pdev = dev->platformdev; 333 struct platform_device *pdev = to_platform_device(dev);
334 struct drm_device *ddev;
327 struct msm_drm_private *priv; 335 struct msm_drm_private *priv;
328 struct msm_kms *kms; 336 struct msm_kms *kms;
329 int ret; 337 int ret;
330 338
339 ddev = drm_dev_alloc(drv, dev);
340 if (!ddev) {
341 dev_err(dev, "failed to allocate drm_device\n");
342 return -ENOMEM;
343 }
344
345 platform_set_drvdata(pdev, ddev);
346 ddev->platformdev = pdev;
347
331 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 348 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
332 if (!priv) { 349 if (!priv) {
333 dev_err(dev->dev, "failed to allocate private data\n"); 350 drm_dev_unref(ddev);
334 return -ENOMEM; 351 return -ENOMEM;
335 } 352 }
336 353
337 dev->dev_private = priv; 354 ddev->dev_private = priv;
338 355
339 priv->wq = alloc_ordered_workqueue("msm", 0); 356 priv->wq = alloc_ordered_workqueue("msm", 0);
340 init_waitqueue_head(&priv->fence_event); 357 priv->atomic_wq = alloc_ordered_workqueue("msm:atomic", 0);
341 init_waitqueue_head(&priv->pending_crtcs_event); 358 init_waitqueue_head(&priv->pending_crtcs_event);
342 359
343 INIT_LIST_HEAD(&priv->inactive_list); 360 INIT_LIST_HEAD(&priv->inactive_list);
344 INIT_LIST_HEAD(&priv->fence_cbs);
345 INIT_LIST_HEAD(&priv->vblank_ctrl.event_list); 361 INIT_LIST_HEAD(&priv->vblank_ctrl.event_list);
346 INIT_WORK(&priv->vblank_ctrl.work, vblank_ctrl_worker); 362 INIT_WORK(&priv->vblank_ctrl.work, vblank_ctrl_worker);
347 spin_lock_init(&priv->vblank_ctrl.lock); 363 spin_lock_init(&priv->vblank_ctrl.lock);
348 364
349 drm_mode_config_init(dev); 365 drm_mode_config_init(ddev);
350
351 platform_set_drvdata(pdev, dev);
352 366
353 /* Bind all our sub-components: */ 367 /* Bind all our sub-components: */
354 ret = component_bind_all(dev->dev, dev); 368 ret = component_bind_all(dev, ddev);
355 if (ret) 369 if (ret) {
370 kfree(priv);
371 drm_dev_unref(ddev);
356 return ret; 372 return ret;
373 }
357 374
358 ret = msm_init_vram(dev); 375 ret = msm_init_vram(ddev);
359 if (ret) 376 if (ret)
360 goto fail; 377 goto fail;
361 378
362 switch (get_mdp_ver(pdev)) { 379 switch (get_mdp_ver(pdev)) {
363 case 4: 380 case 4:
364 kms = mdp4_kms_init(dev); 381 kms = mdp4_kms_init(ddev);
365 break; 382 break;
366 case 5: 383 case 5:
367 kms = mdp5_kms_init(dev); 384 kms = mdp5_kms_init(ddev);
368 break; 385 break;
369 default: 386 default:
370 kms = ERR_PTR(-ENODEV); 387 kms = ERR_PTR(-ENODEV);
@@ -378,7 +395,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
378 * and (for example) use dmabuf/prime to share buffers with 395 * and (for example) use dmabuf/prime to share buffers with
379 * imx drm driver on iMX5 396 * imx drm driver on iMX5
380 */ 397 */
381 dev_err(dev->dev, "failed to load kms\n"); 398 dev_err(dev, "failed to load kms\n");
382 ret = PTR_ERR(kms); 399 ret = PTR_ERR(kms);
383 goto fail; 400 goto fail;
384 } 401 }
@@ -386,50 +403,64 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
386 priv->kms = kms; 403 priv->kms = kms;
387 404
388 if (kms) { 405 if (kms) {
389 pm_runtime_enable(dev->dev); 406 pm_runtime_enable(dev);
390 ret = kms->funcs->hw_init(kms); 407 ret = kms->funcs->hw_init(kms);
391 if (ret) { 408 if (ret) {
392 dev_err(dev->dev, "kms hw init failed: %d\n", ret); 409 dev_err(dev, "kms hw init failed: %d\n", ret);
393 goto fail; 410 goto fail;
394 } 411 }
395 } 412 }
396 413
397 dev->mode_config.funcs = &mode_config_funcs; 414 ddev->mode_config.funcs = &mode_config_funcs;
398 415
399 ret = drm_vblank_init(dev, priv->num_crtcs); 416 ret = drm_vblank_init(ddev, priv->num_crtcs);
400 if (ret < 0) { 417 if (ret < 0) {
401 dev_err(dev->dev, "failed to initialize vblank\n"); 418 dev_err(dev, "failed to initialize vblank\n");
402 goto fail; 419 goto fail;
403 } 420 }
404 421
405 pm_runtime_get_sync(dev->dev); 422 pm_runtime_get_sync(dev);
406 ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0)); 423 ret = drm_irq_install(ddev, platform_get_irq(pdev, 0));
407 pm_runtime_put_sync(dev->dev); 424 pm_runtime_put_sync(dev);
408 if (ret < 0) { 425 if (ret < 0) {
409 dev_err(dev->dev, "failed to install IRQ handler\n"); 426 dev_err(dev, "failed to install IRQ handler\n");
427 goto fail;
428 }
429
430 ret = drm_dev_register(ddev, 0);
431 if (ret)
432 goto fail;
433
434 ret = drm_connector_register_all(ddev);
435 if (ret) {
436 dev_err(dev, "failed to register connectors\n");
410 goto fail; 437 goto fail;
411 } 438 }
412 439
413 drm_mode_config_reset(dev); 440 drm_mode_config_reset(ddev);
414 441
415#ifdef CONFIG_DRM_FBDEV_EMULATION 442#ifdef CONFIG_DRM_FBDEV_EMULATION
416 if (fbdev) 443 if (fbdev)
417 priv->fbdev = msm_fbdev_init(dev); 444 priv->fbdev = msm_fbdev_init(ddev);
418#endif 445#endif
419 446
420 ret = msm_debugfs_late_init(dev); 447 ret = msm_debugfs_late_init(ddev);
421 if (ret) 448 if (ret)
422 goto fail; 449 goto fail;
423 450
424 drm_kms_helper_poll_init(dev); 451 drm_kms_helper_poll_init(ddev);
425 452
426 return 0; 453 return 0;
427 454
428fail: 455fail:
429 msm_unload(dev); 456 msm_drm_uninit(dev);
430 return ret; 457 return ret;
431} 458}
432 459
460/*
461 * DRM operations:
462 */
463
433static void load_gpu(struct drm_device *dev) 464static void load_gpu(struct drm_device *dev)
434{ 465{
435 static DEFINE_MUTEX(init_lock); 466 static DEFINE_MUTEX(init_lock);
@@ -465,7 +496,6 @@ static void msm_preclose(struct drm_device *dev, struct drm_file *file)
465{ 496{
466 struct msm_drm_private *priv = dev->dev_private; 497 struct msm_drm_private *priv = dev->dev_private;
467 struct msm_file_private *ctx = file->driver_priv; 498 struct msm_file_private *ctx = file->driver_priv;
468 struct msm_kms *kms = priv->kms;
469 499
470 mutex_lock(&dev->struct_mutex); 500 mutex_lock(&dev->struct_mutex);
471 if (ctx == priv->lastctx) 501 if (ctx == priv->lastctx)
@@ -536,265 +566,6 @@ static void msm_disable_vblank(struct drm_device *dev, unsigned int pipe)
536} 566}
537 567
538/* 568/*
539 * DRM debugfs:
540 */
541
542#ifdef CONFIG_DEBUG_FS
543static int msm_gpu_show(struct drm_device *dev, struct seq_file *m)
544{
545 struct msm_drm_private *priv = dev->dev_private;
546 struct msm_gpu *gpu = priv->gpu;
547
548 if (gpu) {
549 seq_printf(m, "%s Status:\n", gpu->name);
550 gpu->funcs->show(gpu, m);
551 }
552
553 return 0;
554}
555
556static int msm_gem_show(struct drm_device *dev, struct seq_file *m)
557{
558 struct msm_drm_private *priv = dev->dev_private;
559 struct msm_gpu *gpu = priv->gpu;
560
561 if (gpu) {
562 seq_printf(m, "Active Objects (%s):\n", gpu->name);
563 msm_gem_describe_objects(&gpu->active_list, m);
564 }
565
566 seq_printf(m, "Inactive Objects:\n");
567 msm_gem_describe_objects(&priv->inactive_list, m);
568
569 return 0;
570}
571
572static int msm_mm_show(struct drm_device *dev, struct seq_file *m)
573{
574 return drm_mm_dump_table(m, &dev->vma_offset_manager->vm_addr_space_mm);
575}
576
577static int msm_fb_show(struct drm_device *dev, struct seq_file *m)
578{
579 struct msm_drm_private *priv = dev->dev_private;
580 struct drm_framebuffer *fb, *fbdev_fb = NULL;
581
582 if (priv->fbdev) {
583 seq_printf(m, "fbcon ");
584 fbdev_fb = priv->fbdev->fb;
585 msm_framebuffer_describe(fbdev_fb, m);
586 }
587
588 mutex_lock(&dev->mode_config.fb_lock);
589 list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
590 if (fb == fbdev_fb)
591 continue;
592
593 seq_printf(m, "user ");
594 msm_framebuffer_describe(fb, m);
595 }
596 mutex_unlock(&dev->mode_config.fb_lock);
597
598 return 0;
599}
600
601static int show_locked(struct seq_file *m, void *arg)
602{
603 struct drm_info_node *node = (struct drm_info_node *) m->private;
604 struct drm_device *dev = node->minor->dev;
605 int (*show)(struct drm_device *dev, struct seq_file *m) =
606 node->info_ent->data;
607 int ret;
608
609 ret = mutex_lock_interruptible(&dev->struct_mutex);
610 if (ret)
611 return ret;
612
613 ret = show(dev, m);
614
615 mutex_unlock(&dev->struct_mutex);
616
617 return ret;
618}
619
620static struct drm_info_list msm_debugfs_list[] = {
621 {"gpu", show_locked, 0, msm_gpu_show},
622 {"gem", show_locked, 0, msm_gem_show},
623 { "mm", show_locked, 0, msm_mm_show },
624 { "fb", show_locked, 0, msm_fb_show },
625};
626
627static int late_init_minor(struct drm_minor *minor)
628{
629 int ret;
630
631 if (!minor)
632 return 0;
633
634 ret = msm_rd_debugfs_init(minor);
635 if (ret) {
636 dev_err(minor->dev->dev, "could not install rd debugfs\n");
637 return ret;
638 }
639
640 ret = msm_perf_debugfs_init(minor);
641 if (ret) {
642 dev_err(minor->dev->dev, "could not install perf debugfs\n");
643 return ret;
644 }
645
646 return 0;
647}
648
649int msm_debugfs_late_init(struct drm_device *dev)
650{
651 int ret;
652 ret = late_init_minor(dev->primary);
653 if (ret)
654 return ret;
655 ret = late_init_minor(dev->render);
656 if (ret)
657 return ret;
658 ret = late_init_minor(dev->control);
659 return ret;
660}
661
662static int msm_debugfs_init(struct drm_minor *minor)
663{
664 struct drm_device *dev = minor->dev;
665 int ret;
666
667 ret = drm_debugfs_create_files(msm_debugfs_list,
668 ARRAY_SIZE(msm_debugfs_list),
669 minor->debugfs_root, minor);
670
671 if (ret) {
672 dev_err(dev->dev, "could not install msm_debugfs_list\n");
673 return ret;
674 }
675
676 return 0;
677}
678
679static void msm_debugfs_cleanup(struct drm_minor *minor)
680{
681 drm_debugfs_remove_files(msm_debugfs_list,
682 ARRAY_SIZE(msm_debugfs_list), minor);
683 if (!minor->dev->dev_private)
684 return;
685 msm_rd_debugfs_cleanup(minor);
686 msm_perf_debugfs_cleanup(minor);
687}
688#endif
689
690/*
691 * Fences:
692 */
693
694int msm_wait_fence(struct drm_device *dev, uint32_t fence,
695 ktime_t *timeout , bool interruptible)
696{
697 struct msm_drm_private *priv = dev->dev_private;
698 int ret;
699
700 if (!priv->gpu)
701 return 0;
702
703 if (fence > priv->gpu->submitted_fence) {
704 DRM_ERROR("waiting on invalid fence: %u (of %u)\n",
705 fence, priv->gpu->submitted_fence);
706 return -EINVAL;
707 }
708
709 if (!timeout) {
710 /* no-wait: */
711 ret = fence_completed(dev, fence) ? 0 : -EBUSY;
712 } else {
713 ktime_t now = ktime_get();
714 unsigned long remaining_jiffies;
715
716 if (ktime_compare(*timeout, now) < 0) {
717 remaining_jiffies = 0;
718 } else {
719 ktime_t rem = ktime_sub(*timeout, now);
720 struct timespec ts = ktime_to_timespec(rem);
721 remaining_jiffies = timespec_to_jiffies(&ts);
722 }
723
724 if (interruptible)
725 ret = wait_event_interruptible_timeout(priv->fence_event,
726 fence_completed(dev, fence),
727 remaining_jiffies);
728 else
729 ret = wait_event_timeout(priv->fence_event,
730 fence_completed(dev, fence),
731 remaining_jiffies);
732
733 if (ret == 0) {
734 DBG("timeout waiting for fence: %u (completed: %u)",
735 fence, priv->completed_fence);
736 ret = -ETIMEDOUT;
737 } else if (ret != -ERESTARTSYS) {
738 ret = 0;
739 }
740 }
741
742 return ret;
743}
744
745int msm_queue_fence_cb(struct drm_device *dev,
746 struct msm_fence_cb *cb, uint32_t fence)
747{
748 struct msm_drm_private *priv = dev->dev_private;
749 int ret = 0;
750
751 mutex_lock(&dev->struct_mutex);
752 if (!list_empty(&cb->work.entry)) {
753 ret = -EINVAL;
754 } else if (fence > priv->completed_fence) {
755 cb->fence = fence;
756 list_add_tail(&cb->work.entry, &priv->fence_cbs);
757 } else {
758 queue_work(priv->wq, &cb->work);
759 }
760 mutex_unlock(&dev->struct_mutex);
761
762 return ret;
763}
764
765/* called from workqueue */
766void msm_update_fence(struct drm_device *dev, uint32_t fence)
767{
768 struct msm_drm_private *priv = dev->dev_private;
769
770 mutex_lock(&dev->struct_mutex);
771 priv->completed_fence = max(fence, priv->completed_fence);
772
773 while (!list_empty(&priv->fence_cbs)) {
774 struct msm_fence_cb *cb;
775
776 cb = list_first_entry(&priv->fence_cbs,
777 struct msm_fence_cb, work.entry);
778
779 if (cb->fence > priv->completed_fence)
780 break;
781
782 list_del_init(&cb->work.entry);
783 queue_work(priv->wq, &cb->work);
784 }
785
786 mutex_unlock(&dev->struct_mutex);
787
788 wake_up_all(&priv->fence_event);
789}
790
791void __msm_fence_worker(struct work_struct *work)
792{
793 struct msm_fence_cb *cb = container_of(work, struct msm_fence_cb, work);
794 cb->func(cb);
795}
796
797/*
798 * DRM ioctls: 569 * DRM ioctls:
799 */ 570 */
800 571
@@ -851,7 +622,7 @@ static int msm_ioctl_gem_cpu_prep(struct drm_device *dev, void *data,
851 return -EINVAL; 622 return -EINVAL;
852 } 623 }
853 624
854 obj = drm_gem_object_lookup(dev, file, args->handle); 625 obj = drm_gem_object_lookup(file, args->handle);
855 if (!obj) 626 if (!obj)
856 return -ENOENT; 627 return -ENOENT;
857 628
@@ -869,7 +640,7 @@ static int msm_ioctl_gem_cpu_fini(struct drm_device *dev, void *data,
869 struct drm_gem_object *obj; 640 struct drm_gem_object *obj;
870 int ret; 641 int ret;
871 642
872 obj = drm_gem_object_lookup(dev, file, args->handle); 643 obj = drm_gem_object_lookup(file, args->handle);
873 if (!obj) 644 if (!obj)
874 return -ENOENT; 645 return -ENOENT;
875 646
@@ -890,7 +661,7 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data,
890 if (args->pad) 661 if (args->pad)
891 return -EINVAL; 662 return -EINVAL;
892 663
893 obj = drm_gem_object_lookup(dev, file, args->handle); 664 obj = drm_gem_object_lookup(file, args->handle);
894 if (!obj) 665 if (!obj)
895 return -ENOENT; 666 return -ENOENT;
896 667
@@ -904,6 +675,7 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data,
904static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, 675static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,
905 struct drm_file *file) 676 struct drm_file *file)
906{ 677{
678 struct msm_drm_private *priv = dev->dev_private;
907 struct drm_msm_wait_fence *args = data; 679 struct drm_msm_wait_fence *args = data;
908 ktime_t timeout = to_ktime(args->timeout); 680 ktime_t timeout = to_ktime(args->timeout);
909 681
@@ -912,7 +684,10 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,
912 return -EINVAL; 684 return -EINVAL;
913 } 685 }
914 686
915 return msm_wait_fence(dev, args->fence, &timeout, true); 687 if (!priv->gpu)
688 return 0;
689
690 return msm_wait_fence(priv->gpu->fctx, args->fence, &timeout, true);
916} 691}
917 692
918static const struct drm_ioctl_desc msm_ioctls[] = { 693static const struct drm_ioctl_desc msm_ioctls[] = {
@@ -952,8 +727,6 @@ static struct drm_driver msm_driver = {
952 DRIVER_RENDER | 727 DRIVER_RENDER |
953 DRIVER_ATOMIC | 728 DRIVER_ATOMIC |
954 DRIVER_MODESET, 729 DRIVER_MODESET,
955 .load = msm_load,
956 .unload = msm_unload,
957 .open = msm_open, 730 .open = msm_open,
958 .preclose = msm_preclose, 731 .preclose = msm_preclose,
959 .lastclose = msm_lastclose, 732 .lastclose = msm_lastclose,
@@ -1053,12 +826,12 @@ static int add_components(struct device *dev, struct component_match **matchptr,
1053 826
1054static int msm_drm_bind(struct device *dev) 827static int msm_drm_bind(struct device *dev)
1055{ 828{
1056 return drm_platform_init(&msm_driver, to_platform_device(dev)); 829 return msm_drm_init(dev, &msm_driver);
1057} 830}
1058 831
1059static void msm_drm_unbind(struct device *dev) 832static void msm_drm_unbind(struct device *dev)
1060{ 833{
1061 drm_put_dev(platform_get_drvdata(to_platform_device(dev))); 834 msm_drm_uninit(dev);
1062} 835}
1063 836
1064static const struct component_master_ops msm_drm_ops = { 837static const struct component_master_ops msm_drm_ops = {
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 870dbe58c259..5b2963f32291 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -49,6 +49,8 @@ struct msm_mmu;
49struct msm_rd_state; 49struct msm_rd_state;
50struct msm_perf_state; 50struct msm_perf_state;
51struct msm_gem_submit; 51struct msm_gem_submit;
52struct msm_fence_context;
53struct msm_fence_cb;
52 54
53#define NUM_DOMAINS 2 /* one for KMS, then one per gpu core (?) */ 55#define NUM_DOMAINS 2 /* one for KMS, then one per gpu core (?) */
54 56
@@ -100,9 +102,6 @@ struct msm_drm_private {
100 102
101 struct drm_fb_helper *fbdev; 103 struct drm_fb_helper *fbdev;
102 104
103 uint32_t next_fence, completed_fence;
104 wait_queue_head_t fence_event;
105
106 struct msm_rd_state *rd; 105 struct msm_rd_state *rd;
107 struct msm_perf_state *perf; 106 struct msm_perf_state *perf;
108 107
@@ -110,9 +109,7 @@ struct msm_drm_private {
110 struct list_head inactive_list; 109 struct list_head inactive_list;
111 110
112 struct workqueue_struct *wq; 111 struct workqueue_struct *wq;
113 112 struct workqueue_struct *atomic_wq;
114 /* callbacks deferred until bo is inactive: */
115 struct list_head fence_cbs;
116 113
117 /* crtcs pending async atomic updates: */ 114 /* crtcs pending async atomic updates: */
118 uint32_t pending_crtcs; 115 uint32_t pending_crtcs;
@@ -157,33 +154,14 @@ struct msm_format {
157 uint32_t pixel_format; 154 uint32_t pixel_format;
158}; 155};
159 156
160/* callback from wq once fence has passed: */
161struct msm_fence_cb {
162 struct work_struct work;
163 uint32_t fence;
164 void (*func)(struct msm_fence_cb *cb);
165};
166
167void __msm_fence_worker(struct work_struct *work);
168
169#define INIT_FENCE_CB(_cb, _func) do { \
170 INIT_WORK(&(_cb)->work, __msm_fence_worker); \
171 (_cb)->func = _func; \
172 } while (0)
173
174int msm_atomic_check(struct drm_device *dev, 157int msm_atomic_check(struct drm_device *dev,
175 struct drm_atomic_state *state); 158 struct drm_atomic_state *state);
176int msm_atomic_commit(struct drm_device *dev, 159int msm_atomic_commit(struct drm_device *dev,
177 struct drm_atomic_state *state, bool async); 160 struct drm_atomic_state *state, bool nonblock);
178 161
179int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu); 162int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);
180 163
181int msm_wait_fence(struct drm_device *dev, uint32_t fence, 164void msm_gem_submit_free(struct msm_gem_submit *submit);
182 ktime_t *timeout, bool interruptible);
183int msm_queue_fence_cb(struct drm_device *dev,
184 struct msm_fence_cb *cb, uint32_t fence);
185void msm_update_fence(struct drm_device *dev, uint32_t fence);
186
187int msm_ioctl_gem_submit(struct drm_device *dev, void *data, 165int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
188 struct drm_file *file); 166 struct drm_file *file);
189 167
@@ -213,13 +191,12 @@ int msm_gem_prime_pin(struct drm_gem_object *obj);
213void msm_gem_prime_unpin(struct drm_gem_object *obj); 191void msm_gem_prime_unpin(struct drm_gem_object *obj);
214void *msm_gem_vaddr_locked(struct drm_gem_object *obj); 192void *msm_gem_vaddr_locked(struct drm_gem_object *obj);
215void *msm_gem_vaddr(struct drm_gem_object *obj); 193void *msm_gem_vaddr(struct drm_gem_object *obj);
216int msm_gem_queue_inactive_cb(struct drm_gem_object *obj, 194int msm_gem_sync_object(struct drm_gem_object *obj,
217 struct msm_fence_cb *cb); 195 struct msm_fence_context *fctx, bool exclusive);
218void msm_gem_move_to_active(struct drm_gem_object *obj, 196void msm_gem_move_to_active(struct drm_gem_object *obj,
219 struct msm_gpu *gpu, bool write, uint32_t fence); 197 struct msm_gpu *gpu, bool exclusive, struct fence *fence);
220void msm_gem_move_to_inactive(struct drm_gem_object *obj); 198void msm_gem_move_to_inactive(struct drm_gem_object *obj);
221int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, 199int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout);
222 ktime_t *timeout);
223int msm_gem_cpu_fini(struct drm_gem_object *obj); 200int msm_gem_cpu_fini(struct drm_gem_object *obj);
224void msm_gem_free_object(struct drm_gem_object *obj); 201void msm_gem_free_object(struct drm_gem_object *obj);
225int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, 202int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
@@ -227,7 +204,7 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
227struct drm_gem_object *msm_gem_new(struct drm_device *dev, 204struct drm_gem_object *msm_gem_new(struct drm_device *dev,
228 uint32_t size, uint32_t flags); 205 uint32_t size, uint32_t flags);
229struct drm_gem_object *msm_gem_import(struct drm_device *dev, 206struct drm_gem_object *msm_gem_import(struct drm_device *dev,
230 uint32_t size, struct sg_table *sgt); 207 struct dma_buf *dmabuf, struct sg_table *sgt);
231 208
232int msm_framebuffer_prepare(struct drm_framebuffer *fb, int id); 209int msm_framebuffer_prepare(struct drm_framebuffer *fb, int id);
233void msm_framebuffer_cleanup(struct drm_framebuffer *fb, int id); 210void msm_framebuffer_cleanup(struct drm_framebuffer *fb, int id);
@@ -303,12 +280,6 @@ u32 msm_readl(const void __iomem *addr);
303#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) 280#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
304#define VERB(fmt, ...) if (0) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) 281#define VERB(fmt, ...) if (0) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
305 282
306static inline bool fence_completed(struct drm_device *dev, uint32_t fence)
307{
308 struct msm_drm_private *priv = dev->dev_private;
309 return priv->completed_fence >= fence;
310}
311
312static inline int align_pitch(int width, int bpp) 283static inline int align_pitch(int width, int bpp)
313{ 284{
314 int bytespp = (bpp + 7) / 8; 285 int bytespp = (bpp + 7) / 8;
@@ -327,5 +298,20 @@ static inline int align_pitch(int width, int bpp)
327/* for conditionally setting boolean flag(s): */ 298/* for conditionally setting boolean flag(s): */
328#define COND(bool, val) ((bool) ? (val) : 0) 299#define COND(bool, val) ((bool) ? (val) : 0)
329 300
301static inline unsigned long timeout_to_jiffies(const ktime_t *timeout)
302{
303 ktime_t now = ktime_get();
304 unsigned long remaining_jiffies;
305
306 if (ktime_compare(*timeout, now) < 0) {
307 remaining_jiffies = 0;
308 } else {
309 ktime_t rem = ktime_sub(*timeout, now);
310 struct timespec ts = ktime_to_timespec(rem);
311 remaining_jiffies = timespec_to_jiffies(&ts);
312 }
313
314 return remaining_jiffies;
315}
330 316
331#endif /* __MSM_DRV_H__ */ 317#endif /* __MSM_DRV_H__ */
diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c
index a474d6cf5d9f..461dc8b873f0 100644
--- a/drivers/gpu/drm/msm/msm_fb.c
+++ b/drivers/gpu/drm/msm/msm_fb.c
@@ -77,7 +77,7 @@ void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m)
77 77
78 seq_printf(m, "fb: %dx%d@%4.4s (%2d, ID:%d)\n", 78 seq_printf(m, "fb: %dx%d@%4.4s (%2d, ID:%d)\n",
79 fb->width, fb->height, (char *)&fb->pixel_format, 79 fb->width, fb->height, (char *)&fb->pixel_format,
80 fb->refcount.refcount.counter, fb->base.id); 80 drm_framebuffer_read_refcount(fb), fb->base.id);
81 81
82 for (i = 0; i < n; i++) { 82 for (i = 0; i < n; i++) {
83 seq_printf(m, " %d: offset=%d pitch=%d, obj: ", 83 seq_printf(m, " %d: offset=%d pitch=%d, obj: ",
@@ -145,8 +145,7 @@ struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev,
145 int ret, i, n = drm_format_num_planes(mode_cmd->pixel_format); 145 int ret, i, n = drm_format_num_planes(mode_cmd->pixel_format);
146 146
147 for (i = 0; i < n; i++) { 147 for (i = 0; i < n; i++) {
148 bos[i] = drm_gem_object_lookup(dev, file, 148 bos[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
149 mode_cmd->handles[i]);
150 if (!bos[i]) { 149 if (!bos[i]) {
151 ret = -ENXIO; 150 ret = -ENXIO;
152 goto out_unref; 151 goto out_unref;
diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c
new file mode 100644
index 000000000000..a9b9b1c95a2e
--- /dev/null
+++ b/drivers/gpu/drm/msm/msm_fence.c
@@ -0,0 +1,163 @@
1/*
2 * Copyright (C) 2013-2016 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <linux/fence.h>
19
20#include "msm_drv.h"
21#include "msm_fence.h"
22
23
24struct msm_fence_context *
25msm_fence_context_alloc(struct drm_device *dev, const char *name)
26{
27 struct msm_fence_context *fctx;
28
29 fctx = kzalloc(sizeof(*fctx), GFP_KERNEL);
30 if (!fctx)
31 return ERR_PTR(-ENOMEM);
32
33 fctx->dev = dev;
34 fctx->name = name;
35 fctx->context = fence_context_alloc(1);
36 init_waitqueue_head(&fctx->event);
37 spin_lock_init(&fctx->spinlock);
38
39 return fctx;
40}
41
42void msm_fence_context_free(struct msm_fence_context *fctx)
43{
44 kfree(fctx);
45}
46
47static inline bool fence_completed(struct msm_fence_context *fctx, uint32_t fence)
48{
49 return (int32_t)(fctx->completed_fence - fence) >= 0;
50}
51
52/* legacy path for WAIT_FENCE ioctl: */
53int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence,
54 ktime_t *timeout, bool interruptible)
55{
56 int ret;
57
58 if (fence > fctx->last_fence) {
59 DRM_ERROR("%s: waiting on invalid fence: %u (of %u)\n",
60 fctx->name, fence, fctx->last_fence);
61 return -EINVAL;
62 }
63
64 if (!timeout) {
65 /* no-wait: */
66 ret = fence_completed(fctx, fence) ? 0 : -EBUSY;
67 } else {
68 unsigned long remaining_jiffies = timeout_to_jiffies(timeout);
69
70 if (interruptible)
71 ret = wait_event_interruptible_timeout(fctx->event,
72 fence_completed(fctx, fence),
73 remaining_jiffies);
74 else
75 ret = wait_event_timeout(fctx->event,
76 fence_completed(fctx, fence),
77 remaining_jiffies);
78
79 if (ret == 0) {
80 DBG("timeout waiting for fence: %u (completed: %u)",
81 fence, fctx->completed_fence);
82 ret = -ETIMEDOUT;
83 } else if (ret != -ERESTARTSYS) {
84 ret = 0;
85 }
86 }
87
88 return ret;
89}
90
91/* called from workqueue */
92void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence)
93{
94 spin_lock(&fctx->spinlock);
95 fctx->completed_fence = max(fence, fctx->completed_fence);
96 spin_unlock(&fctx->spinlock);
97
98 wake_up_all(&fctx->event);
99}
100
101struct msm_fence {
102 struct msm_fence_context *fctx;
103 struct fence base;
104};
105
106static inline struct msm_fence *to_msm_fence(struct fence *fence)
107{
108 return container_of(fence, struct msm_fence, base);
109}
110
111static const char *msm_fence_get_driver_name(struct fence *fence)
112{
113 return "msm";
114}
115
116static const char *msm_fence_get_timeline_name(struct fence *fence)
117{
118 struct msm_fence *f = to_msm_fence(fence);
119 return f->fctx->name;
120}
121
122static bool msm_fence_enable_signaling(struct fence *fence)
123{
124 return true;
125}
126
127static bool msm_fence_signaled(struct fence *fence)
128{
129 struct msm_fence *f = to_msm_fence(fence);
130 return fence_completed(f->fctx, f->base.seqno);
131}
132
133static void msm_fence_release(struct fence *fence)
134{
135 struct msm_fence *f = to_msm_fence(fence);
136 kfree_rcu(f, base.rcu);
137}
138
139static const struct fence_ops msm_fence_ops = {
140 .get_driver_name = msm_fence_get_driver_name,
141 .get_timeline_name = msm_fence_get_timeline_name,
142 .enable_signaling = msm_fence_enable_signaling,
143 .signaled = msm_fence_signaled,
144 .wait = fence_default_wait,
145 .release = msm_fence_release,
146};
147
148struct fence *
149msm_fence_alloc(struct msm_fence_context *fctx)
150{
151 struct msm_fence *f;
152
153 f = kzalloc(sizeof(*f), GFP_KERNEL);
154 if (!f)
155 return ERR_PTR(-ENOMEM);
156
157 f->fctx = fctx;
158
159 fence_init(&f->base, &msm_fence_ops, &fctx->spinlock,
160 fctx->context, ++fctx->last_fence);
161
162 return &f->base;
163}
diff --git a/drivers/gpu/drm/msm/msm_fence.h b/drivers/gpu/drm/msm/msm_fence.h
new file mode 100644
index 000000000000..ceb5b3d314b4
--- /dev/null
+++ b/drivers/gpu/drm/msm/msm_fence.h
@@ -0,0 +1,46 @@
1/*
2 * Copyright (C) 2013-2016 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef __MSM_FENCE_H__
19#define __MSM_FENCE_H__
20
21#include "msm_drv.h"
22
23struct msm_fence_context {
24 struct drm_device *dev;
25 const char *name;
26 unsigned context;
27 /* last_fence == completed_fence --> no pending work */
28 uint32_t last_fence; /* last assigned fence */
29 uint32_t completed_fence; /* last completed fence */
30 wait_queue_head_t event;
31 spinlock_t spinlock;
32};
33
34struct msm_fence_context * msm_fence_context_alloc(struct drm_device *dev,
35 const char *name);
36void msm_fence_context_free(struct msm_fence_context *fctx);
37
38int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence,
39 ktime_t *timeout, bool interruptible);
40int msm_queue_fence_cb(struct msm_fence_context *fctx,
41 struct msm_fence_cb *cb, uint32_t fence);
42void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence);
43
44struct fence * msm_fence_alloc(struct msm_fence_context *fctx);
45
46#endif
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 3cedb8d5c855..7daf4054dd2b 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -21,6 +21,7 @@
21#include <linux/pfn_t.h> 21#include <linux/pfn_t.h>
22 22
23#include "msm_drv.h" 23#include "msm_drv.h"
24#include "msm_fence.h"
24#include "msm_gem.h" 25#include "msm_gem.h"
25#include "msm_gpu.h" 26#include "msm_gpu.h"
26#include "msm_mmu.h" 27#include "msm_mmu.h"
@@ -373,7 +374,7 @@ int msm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
373 int ret = 0; 374 int ret = 0;
374 375
375 /* GEM does all our handle to object mapping */ 376 /* GEM does all our handle to object mapping */
376 obj = drm_gem_object_lookup(dev, file, handle); 377 obj = drm_gem_object_lookup(file, handle);
377 if (obj == NULL) { 378 if (obj == NULL) {
378 ret = -ENOENT; 379 ret = -ENOENT;
379 goto fail; 380 goto fail;
@@ -410,27 +411,62 @@ void *msm_gem_vaddr(struct drm_gem_object *obj)
410 return ret; 411 return ret;
411} 412}
412 413
413/* setup callback for when bo is no longer busy.. 414/* must be called before _move_to_active().. */
414 * TODO probably want to differentiate read vs write.. 415int msm_gem_sync_object(struct drm_gem_object *obj,
415 */ 416 struct msm_fence_context *fctx, bool exclusive)
416int msm_gem_queue_inactive_cb(struct drm_gem_object *obj,
417 struct msm_fence_cb *cb)
418{ 417{
419 struct msm_gem_object *msm_obj = to_msm_bo(obj); 418 struct msm_gem_object *msm_obj = to_msm_bo(obj);
420 uint32_t fence = msm_gem_fence(msm_obj, 419 struct reservation_object_list *fobj;
421 MSM_PREP_READ | MSM_PREP_WRITE); 420 struct fence *fence;
422 return msm_queue_fence_cb(obj->dev, cb, fence); 421 int i, ret;
422
423 if (!exclusive) {
424 /* NOTE: _reserve_shared() must happen before _add_shared_fence(),
425 * which makes this a slightly strange place to call it. OTOH this
426 * is a convenient can-fail point to hook it in. (And similar to
427 * how etnaviv and nouveau handle this.)
428 */
429 ret = reservation_object_reserve_shared(msm_obj->resv);
430 if (ret)
431 return ret;
432 }
433
434 fobj = reservation_object_get_list(msm_obj->resv);
435 if (!fobj || (fobj->shared_count == 0)) {
436 fence = reservation_object_get_excl(msm_obj->resv);
437 /* don't need to wait on our own fences, since ring is fifo */
438 if (fence && (fence->context != fctx->context)) {
439 ret = fence_wait(fence, true);
440 if (ret)
441 return ret;
442 }
443 }
444
445 if (!exclusive || !fobj)
446 return 0;
447
448 for (i = 0; i < fobj->shared_count; i++) {
449 fence = rcu_dereference_protected(fobj->shared[i],
450 reservation_object_held(msm_obj->resv));
451 if (fence->context != fctx->context) {
452 ret = fence_wait(fence, true);
453 if (ret)
454 return ret;
455 }
456 }
457
458 return 0;
423} 459}
424 460
425void msm_gem_move_to_active(struct drm_gem_object *obj, 461void msm_gem_move_to_active(struct drm_gem_object *obj,
426 struct msm_gpu *gpu, bool write, uint32_t fence) 462 struct msm_gpu *gpu, bool exclusive, struct fence *fence)
427{ 463{
428 struct msm_gem_object *msm_obj = to_msm_bo(obj); 464 struct msm_gem_object *msm_obj = to_msm_bo(obj);
429 msm_obj->gpu = gpu; 465 msm_obj->gpu = gpu;
430 if (write) 466 if (exclusive)
431 msm_obj->write_fence = fence; 467 reservation_object_add_excl_fence(msm_obj->resv, fence);
432 else 468 else
433 msm_obj->read_fence = fence; 469 reservation_object_add_shared_fence(msm_obj->resv, fence);
434 list_del_init(&msm_obj->mm_list); 470 list_del_init(&msm_obj->mm_list);
435 list_add_tail(&msm_obj->mm_list, &gpu->active_list); 471 list_add_tail(&msm_obj->mm_list, &gpu->active_list);
436} 472}
@@ -444,30 +480,30 @@ void msm_gem_move_to_inactive(struct drm_gem_object *obj)
444 WARN_ON(!mutex_is_locked(&dev->struct_mutex)); 480 WARN_ON(!mutex_is_locked(&dev->struct_mutex));
445 481
446 msm_obj->gpu = NULL; 482 msm_obj->gpu = NULL;
447 msm_obj->read_fence = 0;
448 msm_obj->write_fence = 0;
449 list_del_init(&msm_obj->mm_list); 483 list_del_init(&msm_obj->mm_list);
450 list_add_tail(&msm_obj->mm_list, &priv->inactive_list); 484 list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
451} 485}
452 486
453int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout) 487int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)
454{ 488{
455 struct drm_device *dev = obj->dev;
456 struct msm_gem_object *msm_obj = to_msm_bo(obj); 489 struct msm_gem_object *msm_obj = to_msm_bo(obj);
457 int ret = 0; 490 bool write = !!(op & MSM_PREP_WRITE);
458 491
459 if (is_active(msm_obj)) { 492 if (op & MSM_PREP_NOSYNC) {
460 uint32_t fence = msm_gem_fence(msm_obj, op); 493 if (!reservation_object_test_signaled_rcu(msm_obj->resv, write))
461 494 return -EBUSY;
462 if (op & MSM_PREP_NOSYNC) 495 } else {
463 timeout = NULL; 496 int ret;
464 497
465 ret = msm_wait_fence(dev, fence, timeout, true); 498 ret = reservation_object_wait_timeout_rcu(msm_obj->resv, write,
499 true, timeout_to_jiffies(timeout));
500 if (ret <= 0)
501 return ret == 0 ? -ETIMEDOUT : ret;
466 } 502 }
467 503
468 /* TODO cache maintenance */ 504 /* TODO cache maintenance */
469 505
470 return ret; 506 return 0;
471} 507}
472 508
473int msm_gem_cpu_fini(struct drm_gem_object *obj) 509int msm_gem_cpu_fini(struct drm_gem_object *obj)
@@ -477,18 +513,46 @@ int msm_gem_cpu_fini(struct drm_gem_object *obj)
477} 513}
478 514
479#ifdef CONFIG_DEBUG_FS 515#ifdef CONFIG_DEBUG_FS
516static void describe_fence(struct fence *fence, const char *type,
517 struct seq_file *m)
518{
519 if (!fence_is_signaled(fence))
520 seq_printf(m, "\t%9s: %s %s seq %u\n", type,
521 fence->ops->get_driver_name(fence),
522 fence->ops->get_timeline_name(fence),
523 fence->seqno);
524}
525
480void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m) 526void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
481{ 527{
482 struct drm_device *dev = obj->dev;
483 struct msm_gem_object *msm_obj = to_msm_bo(obj); 528 struct msm_gem_object *msm_obj = to_msm_bo(obj);
529 struct reservation_object *robj = msm_obj->resv;
530 struct reservation_object_list *fobj;
531 struct fence *fence;
484 uint64_t off = drm_vma_node_start(&obj->vma_node); 532 uint64_t off = drm_vma_node_start(&obj->vma_node);
485 533
486 WARN_ON(!mutex_is_locked(&dev->struct_mutex)); 534 WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
487 seq_printf(m, "%08x: %c(r=%u,w=%u) %2d (%2d) %08llx %p %zu\n", 535
536 seq_printf(m, "%08x: %c %2d (%2d) %08llx %p %zu\n",
488 msm_obj->flags, is_active(msm_obj) ? 'A' : 'I', 537 msm_obj->flags, is_active(msm_obj) ? 'A' : 'I',
489 msm_obj->read_fence, msm_obj->write_fence,
490 obj->name, obj->refcount.refcount.counter, 538 obj->name, obj->refcount.refcount.counter,
491 off, msm_obj->vaddr, obj->size); 539 off, msm_obj->vaddr, obj->size);
540
541 rcu_read_lock();
542 fobj = rcu_dereference(robj->fence);
543 if (fobj) {
544 unsigned int i, shared_count = fobj->shared_count;
545
546 for (i = 0; i < shared_count; i++) {
547 fence = rcu_dereference(fobj->shared[i]);
548 describe_fence(fence, "Shared", m);
549 }
550 }
551
552 fence = rcu_dereference(robj->fence_excl);
553 if (fence)
554 describe_fence(fence, "Exclusive", m);
555 rcu_read_unlock();
492} 556}
493 557
494void msm_gem_describe_objects(struct list_head *list, struct seq_file *m) 558void msm_gem_describe_objects(struct list_head *list, struct seq_file *m)
@@ -583,6 +647,7 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
583 647
584static int msm_gem_new_impl(struct drm_device *dev, 648static int msm_gem_new_impl(struct drm_device *dev,
585 uint32_t size, uint32_t flags, 649 uint32_t size, uint32_t flags,
650 struct reservation_object *resv,
586 struct drm_gem_object **obj) 651 struct drm_gem_object **obj)
587{ 652{
588 struct msm_drm_private *priv = dev->dev_private; 653 struct msm_drm_private *priv = dev->dev_private;
@@ -622,8 +687,12 @@ static int msm_gem_new_impl(struct drm_device *dev,
622 687
623 msm_obj->flags = flags; 688 msm_obj->flags = flags;
624 689
625 msm_obj->resv = &msm_obj->_resv; 690 if (resv) {
626 reservation_object_init(msm_obj->resv); 691 msm_obj->resv = resv;
692 } else {
693 msm_obj->resv = &msm_obj->_resv;
694 reservation_object_init(msm_obj->resv);
695 }
627 696
628 INIT_LIST_HEAD(&msm_obj->submit_entry); 697 INIT_LIST_HEAD(&msm_obj->submit_entry);
629 list_add_tail(&msm_obj->mm_list, &priv->inactive_list); 698 list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
@@ -643,7 +712,7 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev,
643 712
644 size = PAGE_ALIGN(size); 713 size = PAGE_ALIGN(size);
645 714
646 ret = msm_gem_new_impl(dev, size, flags, &obj); 715 ret = msm_gem_new_impl(dev, size, flags, NULL, &obj);
647 if (ret) 716 if (ret)
648 goto fail; 717 goto fail;
649 718
@@ -665,10 +734,11 @@ fail:
665} 734}
666 735
667struct drm_gem_object *msm_gem_import(struct drm_device *dev, 736struct drm_gem_object *msm_gem_import(struct drm_device *dev,
668 uint32_t size, struct sg_table *sgt) 737 struct dma_buf *dmabuf, struct sg_table *sgt)
669{ 738{
670 struct msm_gem_object *msm_obj; 739 struct msm_gem_object *msm_obj;
671 struct drm_gem_object *obj; 740 struct drm_gem_object *obj;
741 uint32_t size;
672 int ret, npages; 742 int ret, npages;
673 743
674 /* if we don't have IOMMU, don't bother pretending we can import: */ 744 /* if we don't have IOMMU, don't bother pretending we can import: */
@@ -677,9 +747,9 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev,
677 return ERR_PTR(-EINVAL); 747 return ERR_PTR(-EINVAL);
678 } 748 }
679 749
680 size = PAGE_ALIGN(size); 750 size = PAGE_ALIGN(dmabuf->size);
681 751
682 ret = msm_gem_new_impl(dev, size, MSM_BO_WC, &obj); 752 ret = msm_gem_new_impl(dev, size, MSM_BO_WC, dmabuf->resv, &obj);
683 if (ret) 753 if (ret)
684 goto fail; 754 goto fail;
685 755
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index 6fc59bfeedeb..9facd4b6ffd9 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -39,7 +39,6 @@ struct msm_gem_object {
39 */ 39 */
40 struct list_head mm_list; 40 struct list_head mm_list;
41 struct msm_gpu *gpu; /* non-null if active */ 41 struct msm_gpu *gpu; /* non-null if active */
42 uint32_t read_fence, write_fence;
43 42
44 /* Transiently in the process of submit ioctl, objects associated 43 /* Transiently in the process of submit ioctl, objects associated
45 * with the submit are on submit->bo_list.. this only lasts for 44 * with the submit are on submit->bo_list.. this only lasts for
@@ -73,19 +72,6 @@ static inline bool is_active(struct msm_gem_object *msm_obj)
73 return msm_obj->gpu != NULL; 72 return msm_obj->gpu != NULL;
74} 73}
75 74
76static inline uint32_t msm_gem_fence(struct msm_gem_object *msm_obj,
77 uint32_t op)
78{
79 uint32_t fence = 0;
80
81 if (op & MSM_PREP_READ)
82 fence = msm_obj->write_fence;
83 if (op & MSM_PREP_WRITE)
84 fence = max(fence, msm_obj->read_fence);
85
86 return fence;
87}
88
89#define MAX_CMDS 4 75#define MAX_CMDS 4
90 76
91/* Created per submit-ioctl, to track bo's and cmdstream bufs, etc, 77/* Created per submit-ioctl, to track bo's and cmdstream bufs, etc,
@@ -99,8 +85,9 @@ struct msm_gem_submit {
99 struct list_head node; /* node in gpu submit_list */ 85 struct list_head node; /* node in gpu submit_list */
100 struct list_head bo_list; 86 struct list_head bo_list;
101 struct ww_acquire_ctx ticket; 87 struct ww_acquire_ctx ticket;
102 uint32_t fence; 88 struct fence *fence;
103 bool valid; 89 struct pid *pid; /* submitting process */
90 bool valid; /* true if no cmdstream patching needed */
104 unsigned int nr_cmds; 91 unsigned int nr_cmds;
105 unsigned int nr_bos; 92 unsigned int nr_bos;
106 struct { 93 struct {
diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c
index 121975b07cd4..6b90890faffe 100644
--- a/drivers/gpu/drm/msm/msm_gem_prime.c
+++ b/drivers/gpu/drm/msm/msm_gem_prime.c
@@ -55,7 +55,7 @@ int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
55struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, 55struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev,
56 struct dma_buf_attachment *attach, struct sg_table *sg) 56 struct dma_buf_attachment *attach, struct sg_table *sg)
57{ 57{
58 return msm_gem_import(dev, attach->dmabuf->size, sg); 58 return msm_gem_import(dev, attach->dmabuf, sg);
59} 59}
60 60
61int msm_gem_prime_pin(struct drm_gem_object *obj) 61int msm_gem_prime_pin(struct drm_gem_object *obj)
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 23d25283616c..b89ca5174863 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -24,7 +24,7 @@
24 */ 24 */
25 25
26/* make sure these don't conflict w/ MSM_SUBMIT_BO_x */ 26/* make sure these don't conflict w/ MSM_SUBMIT_BO_x */
27#define BO_VALID 0x8000 27#define BO_VALID 0x8000 /* is current addr in cmdstream correct/valid? */
28#define BO_LOCKED 0x4000 28#define BO_LOCKED 0x4000
29#define BO_PINNED 0x2000 29#define BO_PINNED 0x2000
30 30
@@ -35,21 +35,31 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev,
35 int sz = sizeof(*submit) + (nr * sizeof(submit->bos[0])); 35 int sz = sizeof(*submit) + (nr * sizeof(submit->bos[0]));
36 36
37 submit = kmalloc(sz, GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); 37 submit = kmalloc(sz, GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
38 if (submit) { 38 if (!submit)
39 submit->dev = dev; 39 return NULL;
40 submit->gpu = gpu;
41 40
42 /* initially, until copy_from_user() and bo lookup succeeds: */ 41 submit->dev = dev;
43 submit->nr_bos = 0; 42 submit->gpu = gpu;
44 submit->nr_cmds = 0; 43 submit->pid = get_pid(task_pid(current));
45 44
46 INIT_LIST_HEAD(&submit->bo_list); 45 /* initially, until copy_from_user() and bo lookup succeeds: */
47 ww_acquire_init(&submit->ticket, &reservation_ww_class); 46 submit->nr_bos = 0;
48 } 47 submit->nr_cmds = 0;
48
49 INIT_LIST_HEAD(&submit->bo_list);
50 ww_acquire_init(&submit->ticket, &reservation_ww_class);
49 51
50 return submit; 52 return submit;
51} 53}
52 54
55void msm_gem_submit_free(struct msm_gem_submit *submit)
56{
57 fence_put(submit->fence);
58 list_del(&submit->node);
59 put_pid(submit->pid);
60 kfree(submit);
61}
62
53static int submit_lookup_objects(struct msm_gem_submit *submit, 63static int submit_lookup_objects(struct msm_gem_submit *submit,
54 struct drm_msm_gem_submit *args, struct drm_file *file) 64 struct drm_msm_gem_submit *args, struct drm_file *file)
55{ 65{
@@ -131,16 +141,13 @@ static void submit_unlock_unpin_bo(struct msm_gem_submit *submit, int i)
131} 141}
132 142
133/* This is where we make sure all the bo's are reserved and pin'd: */ 143/* This is where we make sure all the bo's are reserved and pin'd: */
134static int submit_validate_objects(struct msm_gem_submit *submit) 144static int submit_lock_objects(struct msm_gem_submit *submit)
135{ 145{
136 int contended, slow_locked = -1, i, ret = 0; 146 int contended, slow_locked = -1, i, ret = 0;
137 147
138retry: 148retry:
139 submit->valid = true;
140
141 for (i = 0; i < submit->nr_bos; i++) { 149 for (i = 0; i < submit->nr_bos; i++) {
142 struct msm_gem_object *msm_obj = submit->bos[i].obj; 150 struct msm_gem_object *msm_obj = submit->bos[i].obj;
143 uint32_t iova;
144 151
145 if (slow_locked == i) 152 if (slow_locked == i)
146 slow_locked = -1; 153 slow_locked = -1;
@@ -154,30 +161,6 @@ retry:
154 goto fail; 161 goto fail;
155 submit->bos[i].flags |= BO_LOCKED; 162 submit->bos[i].flags |= BO_LOCKED;
156 } 163 }
157
158
159 /* if locking succeeded, pin bo: */
160 ret = msm_gem_get_iova_locked(&msm_obj->base,
161 submit->gpu->id, &iova);
162
163 /* this would break the logic in the fail path.. there is no
164 * reason for this to happen, but just to be on the safe side
165 * let's notice if this starts happening in the future:
166 */
167 WARN_ON(ret == -EDEADLK);
168
169 if (ret)
170 goto fail;
171
172 submit->bos[i].flags |= BO_PINNED;
173
174 if (iova == submit->bos[i].iova) {
175 submit->bos[i].flags |= BO_VALID;
176 } else {
177 submit->bos[i].iova = iova;
178 submit->bos[i].flags &= ~BO_VALID;
179 submit->valid = false;
180 }
181 } 164 }
182 165
183 ww_acquire_done(&submit->ticket); 166 ww_acquire_done(&submit->ticket);
@@ -206,6 +189,54 @@ fail:
206 return ret; 189 return ret;
207} 190}
208 191
192static int submit_fence_sync(struct msm_gem_submit *submit)
193{
194 int i, ret = 0;
195
196 for (i = 0; i < submit->nr_bos; i++) {
197 struct msm_gem_object *msm_obj = submit->bos[i].obj;
198 bool write = submit->bos[i].flags & MSM_SUBMIT_BO_WRITE;
199
200 ret = msm_gem_sync_object(&msm_obj->base, submit->gpu->fctx, write);
201 if (ret)
202 break;
203 }
204
205 return ret;
206}
207
208static int submit_pin_objects(struct msm_gem_submit *submit)
209{
210 int i, ret = 0;
211
212 submit->valid = true;
213
214 for (i = 0; i < submit->nr_bos; i++) {
215 struct msm_gem_object *msm_obj = submit->bos[i].obj;
216 uint32_t iova;
217
218 /* if locking succeeded, pin bo: */
219 ret = msm_gem_get_iova_locked(&msm_obj->base,
220 submit->gpu->id, &iova);
221
222 if (ret)
223 break;
224
225 submit->bos[i].flags |= BO_PINNED;
226
227 if (iova == submit->bos[i].iova) {
228 submit->bos[i].flags |= BO_VALID;
229 } else {
230 submit->bos[i].iova = iova;
231 /* iova changed, so address in cmdstream is not valid: */
232 submit->bos[i].flags &= ~BO_VALID;
233 submit->valid = false;
234 }
235 }
236
237 return ret;
238}
239
209static int submit_bo(struct msm_gem_submit *submit, uint32_t idx, 240static int submit_bo(struct msm_gem_submit *submit, uint32_t idx,
210 struct msm_gem_object **obj, uint32_t *iova, bool *valid) 241 struct msm_gem_object **obj, uint32_t *iova, bool *valid)
211{ 242{
@@ -297,7 +328,7 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
297 return 0; 328 return 0;
298} 329}
299 330
300static void submit_cleanup(struct msm_gem_submit *submit, bool fail) 331static void submit_cleanup(struct msm_gem_submit *submit)
301{ 332{
302 unsigned i; 333 unsigned i;
303 334
@@ -344,7 +375,15 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
344 if (ret) 375 if (ret)
345 goto out; 376 goto out;
346 377
347 ret = submit_validate_objects(submit); 378 ret = submit_lock_objects(submit);
379 if (ret)
380 goto out;
381
382 ret = submit_fence_sync(submit);
383 if (ret)
384 goto out;
385
386 ret = submit_pin_objects(submit);
348 if (ret) 387 if (ret)
349 goto out; 388 goto out;
350 389
@@ -410,10 +449,12 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
410 449
411 ret = msm_gpu_submit(gpu, submit, ctx); 450 ret = msm_gpu_submit(gpu, submit, ctx);
412 451
413 args->fence = submit->fence; 452 args->fence = submit->fence->seqno;
414 453
415out: 454out:
416 submit_cleanup(submit, !!ret); 455 submit_cleanup(submit);
456 if (ret)
457 msm_gem_submit_free(submit);
417 mutex_unlock(&dev->struct_mutex); 458 mutex_unlock(&dev->struct_mutex);
418 return ret; 459 return ret;
419} 460}
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 6b02ada6579a..36ed53e661fe 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -18,6 +18,7 @@
18#include "msm_gpu.h" 18#include "msm_gpu.h"
19#include "msm_gem.h" 19#include "msm_gem.h"
20#include "msm_mmu.h" 20#include "msm_mmu.h"
21#include "msm_fence.h"
21 22
22 23
23/* 24/*
@@ -265,22 +266,38 @@ static void inactive_start(struct msm_gpu *gpu)
265 * Hangcheck detection for locked gpu: 266 * Hangcheck detection for locked gpu:
266 */ 267 */
267 268
268static void retire_submits(struct msm_gpu *gpu, uint32_t fence); 269static void retire_submits(struct msm_gpu *gpu);
269 270
270static void recover_worker(struct work_struct *work) 271static void recover_worker(struct work_struct *work)
271{ 272{
272 struct msm_gpu *gpu = container_of(work, struct msm_gpu, recover_work); 273 struct msm_gpu *gpu = container_of(work, struct msm_gpu, recover_work);
273 struct drm_device *dev = gpu->dev; 274 struct drm_device *dev = gpu->dev;
275 struct msm_gem_submit *submit;
276 uint32_t fence = gpu->funcs->last_fence(gpu);
274 277
275 dev_err(dev->dev, "%s: hangcheck recover!\n", gpu->name); 278 msm_update_fence(gpu->fctx, fence + 1);
276 279
277 mutex_lock(&dev->struct_mutex); 280 mutex_lock(&dev->struct_mutex);
278 if (msm_gpu_active(gpu)) {
279 struct msm_gem_submit *submit;
280 uint32_t fence = gpu->funcs->last_fence(gpu);
281 281
282 dev_err(dev->dev, "%s: hangcheck recover!\n", gpu->name);
283 list_for_each_entry(submit, &gpu->submit_list, node) {
284 if (submit->fence->seqno == (fence + 1)) {
285 struct task_struct *task;
286
287 rcu_read_lock();
288 task = pid_task(submit->pid, PIDTYPE_PID);
289 if (task) {
290 dev_err(dev->dev, "%s: offending task: %s\n",
291 gpu->name, task->comm);
292 }
293 rcu_read_unlock();
294 break;
295 }
296 }
297
298 if (msm_gpu_active(gpu)) {
282 /* retire completed submits, plus the one that hung: */ 299 /* retire completed submits, plus the one that hung: */
283 retire_submits(gpu, fence + 1); 300 retire_submits(gpu);
284 301
285 inactive_cancel(gpu); 302 inactive_cancel(gpu);
286 gpu->funcs->recover(gpu); 303 gpu->funcs->recover(gpu);
@@ -290,6 +307,7 @@ static void recover_worker(struct work_struct *work)
290 gpu->funcs->submit(gpu, submit, NULL); 307 gpu->funcs->submit(gpu, submit, NULL);
291 } 308 }
292 } 309 }
310
293 mutex_unlock(&dev->struct_mutex); 311 mutex_unlock(&dev->struct_mutex);
294 312
295 msm_gpu_retire(gpu); 313 msm_gpu_retire(gpu);
@@ -312,7 +330,7 @@ static void hangcheck_handler(unsigned long data)
312 if (fence != gpu->hangcheck_fence) { 330 if (fence != gpu->hangcheck_fence) {
313 /* some progress has been made.. ya! */ 331 /* some progress has been made.. ya! */
314 gpu->hangcheck_fence = fence; 332 gpu->hangcheck_fence = fence;
315 } else if (fence < gpu->submitted_fence) { 333 } else if (fence < gpu->fctx->last_fence) {
316 /* no progress and not done.. hung! */ 334 /* no progress and not done.. hung! */
317 gpu->hangcheck_fence = fence; 335 gpu->hangcheck_fence = fence;
318 dev_err(dev->dev, "%s: hangcheck detected gpu lockup!\n", 336 dev_err(dev->dev, "%s: hangcheck detected gpu lockup!\n",
@@ -320,12 +338,12 @@ static void hangcheck_handler(unsigned long data)
320 dev_err(dev->dev, "%s: completed fence: %u\n", 338 dev_err(dev->dev, "%s: completed fence: %u\n",
321 gpu->name, fence); 339 gpu->name, fence);
322 dev_err(dev->dev, "%s: submitted fence: %u\n", 340 dev_err(dev->dev, "%s: submitted fence: %u\n",
323 gpu->name, gpu->submitted_fence); 341 gpu->name, gpu->fctx->last_fence);
324 queue_work(priv->wq, &gpu->recover_work); 342 queue_work(priv->wq, &gpu->recover_work);
325 } 343 }
326 344
327 /* if still more pending work, reset the hangcheck timer: */ 345 /* if still more pending work, reset the hangcheck timer: */
328 if (gpu->submitted_fence > gpu->hangcheck_fence) 346 if (gpu->fctx->last_fence > gpu->hangcheck_fence)
329 hangcheck_timer_reset(gpu); 347 hangcheck_timer_reset(gpu);
330 348
331 /* workaround for missing irq: */ 349 /* workaround for missing irq: */
@@ -431,7 +449,22 @@ out:
431 * Cmdstream submission/retirement: 449 * Cmdstream submission/retirement:
432 */ 450 */
433 451
434static void retire_submits(struct msm_gpu *gpu, uint32_t fence) 452static void retire_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
453{
454 int i;
455
456 for (i = 0; i < submit->nr_bos; i++) {
457 struct msm_gem_object *msm_obj = submit->bos[i].obj;
458 /* move to inactive: */
459 msm_gem_move_to_inactive(&msm_obj->base);
460 msm_gem_put_iova(&msm_obj->base, gpu->id);
461 drm_gem_object_unreference(&msm_obj->base);
462 }
463
464 msm_gem_submit_free(submit);
465}
466
467static void retire_submits(struct msm_gpu *gpu)
435{ 468{
436 struct drm_device *dev = gpu->dev; 469 struct drm_device *dev = gpu->dev;
437 470
@@ -443,9 +476,8 @@ static void retire_submits(struct msm_gpu *gpu, uint32_t fence)
443 submit = list_first_entry(&gpu->submit_list, 476 submit = list_first_entry(&gpu->submit_list,
444 struct msm_gem_submit, node); 477 struct msm_gem_submit, node);
445 478
446 if (submit->fence <= fence) { 479 if (fence_is_signaled(submit->fence)) {
447 list_del(&submit->node); 480 retire_submit(gpu, submit);
448 kfree(submit);
449 } else { 481 } else {
450 break; 482 break;
451 } 483 }
@@ -458,29 +490,10 @@ static void retire_worker(struct work_struct *work)
458 struct drm_device *dev = gpu->dev; 490 struct drm_device *dev = gpu->dev;
459 uint32_t fence = gpu->funcs->last_fence(gpu); 491 uint32_t fence = gpu->funcs->last_fence(gpu);
460 492
461 msm_update_fence(gpu->dev, fence); 493 msm_update_fence(gpu->fctx, fence);
462 494
463 mutex_lock(&dev->struct_mutex); 495 mutex_lock(&dev->struct_mutex);
464 496 retire_submits(gpu);
465 retire_submits(gpu, fence);
466
467 while (!list_empty(&gpu->active_list)) {
468 struct msm_gem_object *obj;
469
470 obj = list_first_entry(&gpu->active_list,
471 struct msm_gem_object, mm_list);
472
473 if ((obj->read_fence <= fence) &&
474 (obj->write_fence <= fence)) {
475 /* move to inactive: */
476 msm_gem_move_to_inactive(&obj->base);
477 msm_gem_put_iova(&obj->base, gpu->id);
478 drm_gem_object_unreference(&obj->base);
479 } else {
480 break;
481 }
482 }
483
484 mutex_unlock(&dev->struct_mutex); 497 mutex_unlock(&dev->struct_mutex);
485 498
486 if (!msm_gpu_active(gpu)) 499 if (!msm_gpu_active(gpu))
@@ -505,9 +518,12 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
505 518
506 WARN_ON(!mutex_is_locked(&dev->struct_mutex)); 519 WARN_ON(!mutex_is_locked(&dev->struct_mutex));
507 520
508 submit->fence = ++priv->next_fence; 521 submit->fence = msm_fence_alloc(gpu->fctx);
509 522 if (IS_ERR(submit->fence)) {
510 gpu->submitted_fence = submit->fence; 523 ret = PTR_ERR(submit->fence);
524 submit->fence = NULL;
525 return ret;
526 }
511 527
512 inactive_cancel(gpu); 528 inactive_cancel(gpu);
513 529
@@ -515,40 +531,34 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
515 531
516 msm_rd_dump_submit(submit); 532 msm_rd_dump_submit(submit);
517 533
518 gpu->submitted_fence = submit->fence;
519
520 update_sw_cntrs(gpu); 534 update_sw_cntrs(gpu);
521 535
522 for (i = 0; i < submit->nr_bos; i++) { 536 for (i = 0; i < submit->nr_bos; i++) {
523 struct msm_gem_object *msm_obj = submit->bos[i].obj; 537 struct msm_gem_object *msm_obj = submit->bos[i].obj;
538 uint32_t iova;
524 539
525 /* can't happen yet.. but when we add 2d support we'll have 540 /* can't happen yet.. but when we add 2d support we'll have
526 * to deal w/ cross-ring synchronization: 541 * to deal w/ cross-ring synchronization:
527 */ 542 */
528 WARN_ON(is_active(msm_obj) && (msm_obj->gpu != gpu)); 543 WARN_ON(is_active(msm_obj) && (msm_obj->gpu != gpu));
529 544
530 if (!is_active(msm_obj)) { 545 /* submit takes a reference to the bo and iova until retired: */
531 uint32_t iova; 546 drm_gem_object_reference(&msm_obj->base);
532 547 msm_gem_get_iova_locked(&msm_obj->base,
533 /* ring takes a reference to the bo and iova: */ 548 submit->gpu->id, &iova);
534 drm_gem_object_reference(&msm_obj->base);
535 msm_gem_get_iova_locked(&msm_obj->base,
536 submit->gpu->id, &iova);
537 }
538
539 if (submit->bos[i].flags & MSM_SUBMIT_BO_READ)
540 msm_gem_move_to_active(&msm_obj->base, gpu, false, submit->fence);
541 549
542 if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE) 550 if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE)
543 msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence); 551 msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence);
552 else if (submit->bos[i].flags & MSM_SUBMIT_BO_READ)
553 msm_gem_move_to_active(&msm_obj->base, gpu, false, submit->fence);
544 } 554 }
545 555
546 ret = gpu->funcs->submit(gpu, submit, ctx); 556 gpu->funcs->submit(gpu, submit, ctx);
547 priv->lastctx = ctx; 557 priv->lastctx = ctx;
548 558
549 hangcheck_timer_reset(gpu); 559 hangcheck_timer_reset(gpu);
550 560
551 return ret; 561 return 0;
552} 562}
553 563
554/* 564/*
@@ -580,6 +590,12 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
580 gpu->funcs = funcs; 590 gpu->funcs = funcs;
581 gpu->name = name; 591 gpu->name = name;
582 gpu->inactive = true; 592 gpu->inactive = true;
593 gpu->fctx = msm_fence_context_alloc(drm, name);
594 if (IS_ERR(gpu->fctx)) {
595 ret = PTR_ERR(gpu->fctx);
596 gpu->fctx = NULL;
597 goto fail;
598 }
583 599
584 INIT_LIST_HEAD(&gpu->active_list); 600 INIT_LIST_HEAD(&gpu->active_list);
585 INIT_WORK(&gpu->retire_work, retire_worker); 601 INIT_WORK(&gpu->retire_work, retire_worker);
@@ -700,4 +716,7 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
700 716
701 if (gpu->mmu) 717 if (gpu->mmu)
702 gpu->mmu->funcs->destroy(gpu->mmu); 718 gpu->mmu->funcs->destroy(gpu->mmu);
719
720 if (gpu->fctx)
721 msm_fence_context_free(gpu->fctx);
703} 722}
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 2bbe85a3d6f6..c9022837a1a4 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -22,6 +22,7 @@
22#include <linux/regulator/consumer.h> 22#include <linux/regulator/consumer.h>
23 23
24#include "msm_drv.h" 24#include "msm_drv.h"
25#include "msm_fence.h"
25#include "msm_ringbuffer.h" 26#include "msm_ringbuffer.h"
26 27
27struct msm_gem_submit; 28struct msm_gem_submit;
@@ -46,7 +47,7 @@ struct msm_gpu_funcs {
46 int (*hw_init)(struct msm_gpu *gpu); 47 int (*hw_init)(struct msm_gpu *gpu);
47 int (*pm_suspend)(struct msm_gpu *gpu); 48 int (*pm_suspend)(struct msm_gpu *gpu);
48 int (*pm_resume)(struct msm_gpu *gpu); 49 int (*pm_resume)(struct msm_gpu *gpu);
49 int (*submit)(struct msm_gpu *gpu, struct msm_gem_submit *submit, 50 void (*submit)(struct msm_gpu *gpu, struct msm_gem_submit *submit,
50 struct msm_file_private *ctx); 51 struct msm_file_private *ctx);
51 void (*flush)(struct msm_gpu *gpu); 52 void (*flush)(struct msm_gpu *gpu);
52 void (*idle)(struct msm_gpu *gpu); 53 void (*idle)(struct msm_gpu *gpu);
@@ -77,13 +78,15 @@ struct msm_gpu {
77 const struct msm_gpu_perfcntr *perfcntrs; 78 const struct msm_gpu_perfcntr *perfcntrs;
78 uint32_t num_perfcntrs; 79 uint32_t num_perfcntrs;
79 80
81 /* ringbuffer: */
80 struct msm_ringbuffer *rb; 82 struct msm_ringbuffer *rb;
81 uint32_t rb_iova; 83 uint32_t rb_iova;
82 84
83 /* list of GEM active objects: */ 85 /* list of GEM active objects: */
84 struct list_head active_list; 86 struct list_head active_list;
85 87
86 uint32_t submitted_fence; 88 /* fencing: */
89 struct msm_fence_context *fctx;
87 90
88 /* is gpu powered/active? */ 91 /* is gpu powered/active? */
89 int active_cnt; 92 int active_cnt;
@@ -125,7 +128,7 @@ struct msm_gpu {
125 128
126static inline bool msm_gpu_active(struct msm_gpu *gpu) 129static inline bool msm_gpu_active(struct msm_gpu *gpu)
127{ 130{
128 return gpu->submitted_fence > gpu->funcs->last_fence(gpu); 131 return gpu->fctx->last_fence > gpu->funcs->last_fence(gpu);
129} 132}
130 133
131/* Perf-Counters: 134/* Perf-Counters:
diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c
index 9a78c48817c6..b48f73ac6389 100644
--- a/drivers/gpu/drm/msm/msm_rd.c
+++ b/drivers/gpu/drm/msm/msm_rd.c
@@ -296,7 +296,7 @@ void msm_rd_dump_submit(struct msm_gem_submit *submit)
296 296
297 n = snprintf(msg, sizeof(msg), "%.*s/%d: fence=%u", 297 n = snprintf(msg, sizeof(msg), "%.*s/%d: fence=%u",
298 TASK_COMM_LEN, current->comm, task_pid_nr(current), 298 TASK_COMM_LEN, current->comm, task_pid_nr(current),
299 submit->fence); 299 submit->fence->seqno);
300 300
301 rd_write_section(rd, RD_CMD, msg, ALIGN(n, 4)); 301 rd_write_section(rd, RD_CMD, msg, ALIGN(n, 4));
302 302