Commit 2ba552b2 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'mediatek-drm-fixes-5.3' of...

Merge tag 'mediatek-drm-fixes-5.3' of https://github.com/ckhu-mediatek/linux.git-tags

 into drm-fixes

Mediatek memory leak drm fix for Linux 5.3

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: CK Hu <ck.hu@mediatek.com>
Link: https://patchwork.freedesktop.org/patch/msgid/1566264270.30493.4.camel@mtksdaap41
parents 14673e15 165d42c0
Loading
Loading
Loading
Loading
+50 −4
Original line number Diff line number Diff line
@@ -213,6 +213,7 @@ static int mtk_drm_kms_init(struct drm_device *drm)
	struct mtk_drm_private *private = drm->dev_private;
	struct platform_device *pdev;
	struct device_node *np;
	struct device *dma_dev;
	int ret;

	if (!iommu_present(&platform_bus_type))
@@ -275,7 +276,29 @@ static int mtk_drm_kms_init(struct drm_device *drm)
		goto err_component_unbind;
	}

	private->dma_dev = &pdev->dev;
	dma_dev = &pdev->dev;
	private->dma_dev = dma_dev;

	/*
	 * Configure the DMA segment size to make sure we get contiguous IOVA
	 * when importing PRIME buffers.
	 */
	if (!dma_dev->dma_parms) {
		private->dma_parms_allocated = true;
		dma_dev->dma_parms =
			devm_kzalloc(drm->dev, sizeof(*dma_dev->dma_parms),
				     GFP_KERNEL);
	}
	if (!dma_dev->dma_parms) {
		ret = -ENOMEM;
		goto err_component_unbind;
	}

	ret = dma_set_max_seg_size(dma_dev, (unsigned int)DMA_BIT_MASK(32));
	if (ret) {
		dev_err(dma_dev, "Failed to set DMA segment size\n");
		goto err_unset_dma_parms;
	}

	/*
	 * We don't use the drm_irq_install() helpers provided by the DRM
@@ -285,13 +308,16 @@ static int mtk_drm_kms_init(struct drm_device *drm)
	drm->irq_enabled = true;
	ret = drm_vblank_init(drm, MAX_CRTC);
	if (ret < 0)
		goto err_component_unbind;
		goto err_unset_dma_parms;

	drm_kms_helper_poll_init(drm);
	drm_mode_config_reset(drm);

	return 0;

err_unset_dma_parms:
	if (private->dma_parms_allocated)
		dma_dev->dma_parms = NULL;
err_component_unbind:
	component_unbind_all(drm->dev, drm);
err_config_cleanup:
@@ -302,9 +328,14 @@ err_config_cleanup:

static void mtk_drm_kms_deinit(struct drm_device *drm)
{
	struct mtk_drm_private *private = drm->dev_private;

	drm_kms_helper_poll_fini(drm);
	drm_atomic_helper_shutdown(drm);

	if (private->dma_parms_allocated)
		private->dma_dev->dma_parms = NULL;

	component_unbind_all(drm->dev, drm);
	drm_mode_config_cleanup(drm);
}
@@ -320,6 +351,18 @@ static const struct file_operations mtk_drm_fops = {
	.compat_ioctl = drm_compat_ioctl,
};

/*
 * We need to override this because the device used to import the memory is
 * not dev->dev, as drm_gem_prime_import() expects.
 */
struct drm_gem_object *mtk_drm_gem_prime_import(struct drm_device *dev,
						struct dma_buf *dma_buf)
{
	struct mtk_drm_private *private = dev->dev_private;

	return drm_gem_prime_import_dev(dev, dma_buf, private->dma_dev);
}

static struct drm_driver mtk_drm_driver = {
	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
			   DRIVER_ATOMIC,
@@ -331,7 +374,7 @@ static struct drm_driver mtk_drm_driver = {
	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
	.gem_prime_export = drm_gem_prime_export,
	.gem_prime_import = drm_gem_prime_import,
	.gem_prime_import = mtk_drm_gem_prime_import,
	.gem_prime_get_sg_table = mtk_gem_prime_get_sg_table,
	.gem_prime_import_sg_table = mtk_gem_prime_import_sg_table,
	.gem_prime_mmap = mtk_drm_gem_mmap_buf,
@@ -524,12 +567,15 @@ static int mtk_drm_probe(struct platform_device *pdev)
			comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL);
			if (!comp) {
				ret = -ENOMEM;
				of_node_put(node);
				goto err_node;
			}

			ret = mtk_ddp_comp_init(dev, node, comp, comp_id, NULL);
			if (ret)
			if (ret) {
				of_node_put(node);
				goto err_node;
			}

			private->ddp_comp[comp_id] = comp;
		}
+2 −0
Original line number Diff line number Diff line
@@ -51,6 +51,8 @@ struct mtk_drm_private {
	} commit;

	struct drm_atomic_state *suspend_state;

	bool dma_parms_allocated;
};

extern struct platform_driver mtk_ddp_driver;