Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/exynos: add drm_iommu_attach_device_if_possible()

Every CRTC drivers in Exynos DRM implements the code which checks
whether IOMMU is supported or not, and if supported enable it.
Making new helper for it generalize each CRTC drivers.

Signed-off-by: Hyungwon Hwang <human.hwang@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>

authored by

Hyungwon Hwang and committed by
Inki Dae
fc2e013f 3f46d807

+47 -46
+8 -17
drivers/gpu/drm/exynos/exynos7_drm_decon.c
··· 89 89 DRM_DEBUG_KMS("vblank wait timed out.\n"); 90 90 } 91 91 92 - static void decon_clear_channel(struct decon_context *ctx) 92 + static void decon_clear_channels(struct exynos_drm_crtc *crtc) 93 93 { 94 + struct decon_context *ctx = crtc->ctx; 94 95 unsigned int win, ch_enabled = 0; 95 96 96 97 DRM_DEBUG_KMS("%s\n", __FILE__); ··· 121 120 struct drm_device *drm_dev) 122 121 { 123 122 struct exynos_drm_private *priv = drm_dev->dev_private; 123 + int ret; 124 124 125 125 ctx->drm_dev = drm_dev; 126 126 ctx->pipe = priv->pipe++; 127 127 128 - /* attach this sub driver to iommu mapping if supported. */ 129 - if (is_drm_iommu_supported(ctx->drm_dev)) { 130 - int ret; 128 + ret = drm_iommu_attach_device_if_possible(ctx->crtc, drm_dev, ctx->dev); 129 + if (ret) 130 + priv->pipe--; 131 131 132 - /* 133 - * If any channel is already active, iommu will throw 134 - * a PAGE FAULT when enabled. So clear any channel if enabled. 135 - */ 136 - decon_clear_channel(ctx); 137 - ret = drm_iommu_attach_device(ctx->drm_dev, ctx->dev); 138 - if (ret) { 139 - DRM_ERROR("drm_iommu_attach failed.\n"); 140 - return ret; 141 - } 142 - } 143 - 144 - return 0; 132 + return ret; 145 133 } 146 134 147 135 static void decon_ctx_remove(struct decon_context *ctx) ··· 623 633 .wait_for_vblank = decon_wait_for_vblank, 624 634 .win_commit = decon_win_commit, 625 635 .win_disable = decon_win_disable, 636 + .clear_channels = decon_clear_channels, 626 637 }; 627 638 628 639
+1
drivers/gpu/drm/exynos/exynos_drm_drv.h
··· 177 177 void (*win_disable)(struct exynos_drm_crtc *crtc, unsigned int zpos); 178 178 void (*te_handler)(struct exynos_drm_crtc *crtc); 179 179 void (*clock_enable)(struct exynos_drm_crtc *crtc, bool enable); 180 + void (*clear_channels)(struct exynos_drm_crtc *crtc); 180 181 }; 181 182 182 183 /*
+8 -26
drivers/gpu/drm/exynos/exynos_drm_fimd.c
··· 298 298 writel(val, ctx->regs + SHADOWCON); 299 299 } 300 300 301 - static void fimd_clear_channel(struct fimd_context *ctx) 301 + static void fimd_clear_channels(struct exynos_drm_crtc *crtc) 302 302 { 303 + struct fimd_context *ctx = crtc->ctx; 303 304 unsigned int win, ch_enabled = 0; 304 305 305 306 DRM_DEBUG_KMS("%s\n", __FILE__); ··· 346 345 clk_disable_unprepare(ctx->bus_clk); 347 346 348 347 pm_runtime_put(ctx->dev); 349 - } 350 - 351 - static int fimd_iommu_attach_devices(struct fimd_context *ctx, 352 - struct drm_device *drm_dev) 353 - { 354 - 355 - /* attach this sub driver to iommu mapping if supported. */ 356 - if (is_drm_iommu_supported(ctx->drm_dev)) { 357 - int ret; 358 - 359 - /* 360 - * If any channel is already active, iommu will throw 361 - * a PAGE FAULT when enabled. So clear any channel if enabled. 362 - */ 363 - fimd_clear_channel(ctx); 364 - ret = drm_iommu_attach_device(ctx->drm_dev, ctx->dev); 365 - if (ret) { 366 - DRM_ERROR("drm_iommu_attach failed.\n"); 367 - return ret; 368 - } 369 - 370 - } 371 - 372 - return 0; 373 348 } 374 349 375 350 static void fimd_iommu_detach_devices(struct fimd_context *ctx) ··· 894 917 .win_disable = fimd_win_disable, 895 918 .te_handler = fimd_te_handler, 896 919 .clock_enable = fimd_dp_clock_enable, 920 + .clear_channels = fimd_clear_channels, 897 921 }; 898 922 899 923 static irqreturn_t fimd_irq_handler(int irq, void *dev_id) ··· 964 986 if (ctx->display) 965 987 exynos_drm_create_enc_conn(drm_dev, ctx->display); 966 988 967 - return fimd_iommu_attach_devices(ctx, drm_dev); 989 + ret = drm_iommu_attach_device_if_possible(ctx->crtc, drm_dev, dev); 990 + if (ret) 991 + priv->pipe--; 992 + 993 + return ret; 968 994 } 969 995 970 996 static void fimd_unbind(struct device *dev, struct device *master,
+14
drivers/gpu/drm/exynos/exynos_drm_iommu.c
··· 144 144 iommu_detach_device(mapping->domain, subdrv_dev); 145 145 drm_release_iommu_mapping(drm_dev); 146 146 } 147 + 148 + int drm_iommu_attach_device_if_possible(struct exynos_drm_crtc *exynos_crtc, 149 + struct drm_device *drm_dev, struct device *subdrv_dev) 150 + { 151 + int ret = 0; 152 + 153 + if (is_drm_iommu_supported(drm_dev)) { 154 + if (exynos_crtc->ops->clear_channels) 155 + exynos_crtc->ops->clear_channels(exynos_crtc); 156 + return drm_iommu_attach_device(drm_dev, subdrv_dev); 157 + } 158 + 159 + return ret; 160 + }
+11
drivers/gpu/drm/exynos/exynos_drm_iommu.h
··· 38 38 #endif 39 39 } 40 40 41 + int drm_iommu_attach_device_if_possible( 42 + struct exynos_drm_crtc *exynos_crtc, struct drm_device *drm_dev, 43 + struct device *subdrv_dev); 44 + 41 45 #else 42 46 43 47 static inline int drm_create_iommu_mapping(struct drm_device *drm_dev) ··· 67 63 static inline bool is_drm_iommu_supported(struct drm_device *drm_dev) 68 64 { 69 65 return false; 66 + } 67 + 68 + static inline int drm_iommu_attach_device_if_possible( 69 + struct exynos_drm_crtc *exynos_crtc, struct drm_device *drm_dev, 70 + struct device *subdrv_dev) 71 + { 72 + return 0; 70 73 } 71 74 72 75 #endif
+5 -3
drivers/gpu/drm/exynos/exynos_mixer.c
··· 882 882 } 883 883 } 884 884 885 - if (!is_drm_iommu_supported(mixer_ctx->drm_dev)) 886 - return 0; 885 + ret = drm_iommu_attach_device_if_possible(mixer_ctx->crtc, drm_dev, 886 + mixer_ctx->dev); 887 + if (ret) 888 + priv->pipe--; 887 889 888 - return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev); 890 + return ret; 889 891 } 890 892 891 893 static void mixer_ctx_remove(struct mixer_context *mixer_ctx)