Message ID | 1466734413-7453-8-git-send-email-zhengsq@rock-chips.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 2016年06月24日 10:13, Shunqian Zheng wrote: > Rockchip DRM used the arm special API, arm_iommu_*(), to attach > iommu for ARM32 SoCs. This patch convert to common iommu API > so it would support ARM64 like RK3399. > > Since previous patch added support for direct IOMMU address space > management, there is no need to use DMA API anymore and this patch wires > things to use the new method. > > Signed-off-by: Shunqian Zheng <zhengsq@rock-chips.com> > Signed-off-by: Tomasz Figa <tfiga@chromium.org> Looks good for me, and it works on rk3399 board, so Acked-by: Mark Yao <mark.yao@rock-chips.com> > --- > drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 100 +++++++++++++++------------- > 1 file changed, 53 insertions(+), 47 deletions(-) > > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c > index 8b96c69..ca9624f 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c > @@ -14,18 +14,18 @@ > * GNU General Public License for more details. > */ > > -#include <asm/dma-iommu.h> > - > #include <drm/drmP.h> > #include <drm/drm_crtc_helper.h> > #include <drm/drm_fb_helper.h> > #include <drm/drm_gem_cma_helper.h> > #include <linux/dma-mapping.h> > +#include <linux/dma-iommu.h> > #include <linux/pm_runtime.h> > #include <linux/module.h> > #include <linux/of_graph.h> > #include <linux/component.h> > #include <linux/console.h> > +#include <linux/iommu.h> > > #include <drm/rockchip_drm.h> > > @@ -51,28 +51,31 @@ static struct drm_driver rockchip_drm_driver; > int rockchip_drm_dma_attach_device(struct drm_device *drm_dev, > struct device *dev) > { > - struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping; > + struct rockchip_drm_private *private = drm_dev->dev_private; > int ret; > > if (!is_support_iommu) > return 0; > > - ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); > - if (ret) > + ret = iommu_attach_device(private->domain, dev); > + if (ret) { > + dev_err(dev, "Failed to attach iommu device\n"); > return ret; > + } > > - dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); > - > - return arm_iommu_attach_device(dev, mapping); > + return 0; > } > > void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, > struct device *dev) > { > + struct rockchip_drm_private *private = drm_dev->dev_private; > + struct iommu_domain *domain = private->domain; > + > if (!is_support_iommu) > return; > > - arm_iommu_detach_device(dev); > + iommu_detach_device(domain, dev); > } > > int rockchip_register_crtc_funcs(struct drm_crtc *crtc, > @@ -137,11 +140,45 @@ static void rockchip_drm_crtc_disable_vblank(struct drm_device *dev, > priv->crtc_funcs[pipe]->disable_vblank(crtc); > } > > +static int rockchip_drm_init_iommu(struct drm_device *drm_dev) > +{ > + struct rockchip_drm_private *private = drm_dev->dev_private; > + struct iommu_domain_geometry *geometry; > + u64 start, end; > + > + if (!is_support_iommu) > + return 0; > + > + private->domain = iommu_domain_alloc(&platform_bus_type); > + if (!private->domain) > + return -ENOMEM; > + > + geometry = &private->domain->geometry; > + start = geometry->aperture_start; > + end = geometry->aperture_end; > + > + DRM_DEBUG("IOMMU context initialized (aperture: %#llx-%#llx)\n", > + start, end); > + drm_mm_init(&private->mm, start, end - start + 1); > + > + return 0; > +} > + > +static void rockchip_iommu_cleanup(struct drm_device *drm_dev) > +{ > + struct rockchip_drm_private *private = drm_dev->dev_private; > + > + if (!is_support_iommu) > + return; > + > + drm_mm_takedown(&private->mm); > + iommu_domain_free(private->domain); > +} > + > static int rockchip_drm_bind(struct device *dev) > { > struct drm_device *drm_dev; > struct rockchip_drm_private *private; > - struct dma_iommu_mapping *mapping = NULL; > int ret; > > drm_dev = drm_dev_alloc(&rockchip_drm_driver, dev); > @@ -162,38 +199,14 @@ static int rockchip_drm_bind(struct device *dev) > > rockchip_drm_mode_config_init(drm_dev); > > - dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), > - GFP_KERNEL); > - if (!dev->dma_parms) { > - ret = -ENOMEM; > + ret = rockchip_drm_init_iommu(drm_dev); > + if (ret) > goto err_config_cleanup; > - } > - > - if (is_support_iommu) { > - /* TODO(djkurtz): fetch the mapping start/size from somewhere */ > - mapping = arm_iommu_create_mapping(&platform_bus_type, > - 0x00000000, > - SZ_2G); > - if (IS_ERR(mapping)) { > - ret = PTR_ERR(mapping); > - goto err_config_cleanup; > - } > - > - ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); > - if (ret) > - goto err_release_mapping; > - > - dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); > - > - ret = arm_iommu_attach_device(dev, mapping); > - if (ret) > - goto err_release_mapping; > - } > > /* Try to bind all sub drivers. */ > ret = component_bind_all(dev, drm_dev); > if (ret) > - goto err_detach_device; > + goto err_iommu_cleanup; > > /* init kms poll for handling hpd */ > drm_kms_helper_poll_init(drm_dev); > @@ -218,8 +231,6 @@ static int rockchip_drm_bind(struct device *dev) > if (ret) > goto err_fbdev_fini; > > - if (is_support_iommu) > - arm_iommu_release_mapping(mapping); > return 0; > err_fbdev_fini: > rockchip_drm_fbdev_fini(drm_dev); > @@ -228,12 +239,8 @@ err_vblank_cleanup: > err_kms_helper_poll_fini: > drm_kms_helper_poll_fini(drm_dev); > component_unbind_all(dev, drm_dev); > -err_detach_device: > - if (is_support_iommu) > - arm_iommu_detach_device(dev); > -err_release_mapping: > - if (is_support_iommu) > - arm_iommu_release_mapping(mapping); > +err_iommu_cleanup: > + rockchip_iommu_cleanup(drm_dev); > err_config_cleanup: > drm_mode_config_cleanup(drm_dev); > drm_dev->dev_private = NULL; > @@ -250,8 +257,7 @@ static void rockchip_drm_unbind(struct device *dev) > drm_vblank_cleanup(drm_dev); > drm_kms_helper_poll_fini(drm_dev); > component_unbind_all(dev, drm_dev); > - if (is_support_iommu) > - arm_iommu_detach_device(dev); > + rockchip_iommu_cleanup(drm_dev); > drm_mode_config_cleanup(drm_dev); > drm_dev->dev_private = NULL; > drm_dev_unregister(drm_dev);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 8b96c69..ca9624f 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -14,18 +14,18 @@ * GNU General Public License for more details. */ -#include <asm/dma-iommu.h> - #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <linux/dma-mapping.h> +#include <linux/dma-iommu.h> #include <linux/pm_runtime.h> #include <linux/module.h> #include <linux/of_graph.h> #include <linux/component.h> #include <linux/console.h> +#include <linux/iommu.h> #include <drm/rockchip_drm.h> @@ -51,28 +51,31 @@ static struct drm_driver rockchip_drm_driver; int rockchip_drm_dma_attach_device(struct drm_device *drm_dev, struct device *dev) { - struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping; + struct rockchip_drm_private *private = drm_dev->dev_private; int ret; if (!is_support_iommu) return 0; - ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); - if (ret) + ret = iommu_attach_device(private->domain, dev); + if (ret) { + dev_err(dev, "Failed to attach iommu device\n"); return ret; + } - dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); - - return arm_iommu_attach_device(dev, mapping); + return 0; } void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, struct device *dev) { + struct rockchip_drm_private *private = drm_dev->dev_private; + struct iommu_domain *domain = private->domain; + if (!is_support_iommu) return; - arm_iommu_detach_device(dev); + iommu_detach_device(domain, dev); } int rockchip_register_crtc_funcs(struct drm_crtc *crtc, @@ -137,11 +140,45 @@ static void rockchip_drm_crtc_disable_vblank(struct drm_device *dev, priv->crtc_funcs[pipe]->disable_vblank(crtc); } +static int rockchip_drm_init_iommu(struct drm_device *drm_dev) +{ + struct rockchip_drm_private *private = drm_dev->dev_private; + struct iommu_domain_geometry *geometry; + u64 start, end; + + if (!is_support_iommu) + return 0; + + private->domain = iommu_domain_alloc(&platform_bus_type); + if (!private->domain) + return -ENOMEM; + + geometry = &private->domain->geometry; + start = geometry->aperture_start; + end = geometry->aperture_end; + + DRM_DEBUG("IOMMU context initialized (aperture: %#llx-%#llx)\n", + start, end); + drm_mm_init(&private->mm, start, end - start + 1); + + return 0; +} + +static void rockchip_iommu_cleanup(struct drm_device *drm_dev) +{ + struct rockchip_drm_private *private = drm_dev->dev_private; + + if (!is_support_iommu) + return; + + drm_mm_takedown(&private->mm); + iommu_domain_free(private->domain); +} + static int rockchip_drm_bind(struct device *dev) { struct drm_device *drm_dev; struct rockchip_drm_private *private; - struct dma_iommu_mapping *mapping = NULL; int ret; drm_dev = drm_dev_alloc(&rockchip_drm_driver, dev); @@ -162,38 +199,14 @@ static int rockchip_drm_bind(struct device *dev) rockchip_drm_mode_config_init(drm_dev); - dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), - GFP_KERNEL); - if (!dev->dma_parms) { - ret = -ENOMEM; + ret = rockchip_drm_init_iommu(drm_dev); + if (ret) goto err_config_cleanup; - } - - if (is_support_iommu) { - /* TODO(djkurtz): fetch the mapping start/size from somewhere */ - mapping = arm_iommu_create_mapping(&platform_bus_type, - 0x00000000, - SZ_2G); - if (IS_ERR(mapping)) { - ret = PTR_ERR(mapping); - goto err_config_cleanup; - } - - ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); - if (ret) - goto err_release_mapping; - - dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); - - ret = arm_iommu_attach_device(dev, mapping); - if (ret) - goto err_release_mapping; - } /* Try to bind all sub drivers. */ ret = component_bind_all(dev, drm_dev); if (ret) - goto err_detach_device; + goto err_iommu_cleanup; /* init kms poll for handling hpd */ drm_kms_helper_poll_init(drm_dev); @@ -218,8 +231,6 @@ static int rockchip_drm_bind(struct device *dev) if (ret) goto err_fbdev_fini; - if (is_support_iommu) - arm_iommu_release_mapping(mapping); return 0; err_fbdev_fini: rockchip_drm_fbdev_fini(drm_dev); @@ -228,12 +239,8 @@ err_vblank_cleanup: err_kms_helper_poll_fini: drm_kms_helper_poll_fini(drm_dev); component_unbind_all(dev, drm_dev); -err_detach_device: - if (is_support_iommu) - arm_iommu_detach_device(dev); -err_release_mapping: - if (is_support_iommu) - arm_iommu_release_mapping(mapping); +err_iommu_cleanup: + rockchip_iommu_cleanup(drm_dev); err_config_cleanup: drm_mode_config_cleanup(drm_dev); drm_dev->dev_private = NULL; @@ -250,8 +257,7 @@ static void rockchip_drm_unbind(struct device *dev) drm_vblank_cleanup(drm_dev); drm_kms_helper_poll_fini(drm_dev); component_unbind_all(dev, drm_dev); - if (is_support_iommu) - arm_iommu_detach_device(dev); + rockchip_iommu_cleanup(drm_dev); drm_mode_config_cleanup(drm_dev); drm_dev->dev_private = NULL; drm_dev_unregister(drm_dev);