Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f3791889 authored by Anton Vorontsov's avatar Anton Vorontsov Committed by Kumar Gala
Browse files

fsl-diu-fb: Pass the proper device for dma mapping routines



The driver should pass a device that specifies internal DMA ops, but
currently NULL pointers are passed, and thus following bug pops up:

  Freescale DIU driver
  ------------[ cut here ]------------
  kernel BUG at arch/powerpc/include/asm/dma-mapping.h:237!
  Oops: Exception in kernel mode, sig: 5 [#1]
  ...
  NIP [c01658b4] allocate_buf+0x0/0x8
  LR [c0306554] fsl_diu_probe+0x2b4/0x518
  Call Trace:
  [df02be10] [c030638c] fsl_diu_probe+0xec/0x518 (unreliable)
  [df02be60] [c020cdec] of_platform_device_probe+0x5c/0x84
  [df02be80] [c018f5d0] really_probe+0x78/0x1a0
  [df02bea0] [c018f7c0] __driver_attach+0xa4/0xa8
  [df02bec0] [c018ea00] bus_for_each_dev+0x60/0x9c
  [df02bef0] [c018f414] driver_attach+0x24/0x34
  [df02bf00] [c018f168] bus_add_driver+0x12c/0x1cc
  [df02bf20] [c018fbdc] driver_register+0x6c/0x110
  [df02bf30] [c020ccb4] of_register_driver+0x54/0x70
  [df02bf40] [c03d0a50] fsl_diu_init+0x70/0xa4
  ...

This patch fixes the issue.

Signed-off-by: default avatarAnton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: default avatarKumar Gala <galak@kernel.crashing.org>
parent 65cc0fa3
Loading
Loading
Loading
Loading
+21 −13
Original line number Diff line number Diff line
@@ -1352,14 +1352,15 @@ static int fsl_diu_resume(struct of_device *ofdev)
#endif				/* CONFIG_PM */

/* Align to 64-bit(8-byte), 32-byte, etc. */
static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
static int allocate_buf(struct device *dev, struct diu_addr *buf, u32 size,
			u32 bytes_align)
{
	u32 offset, ssize;
	u32 mask;
	dma_addr_t paddr = 0;

	ssize = size + bytes_align;
	buf->vaddr = dma_alloc_coherent(NULL, ssize, &paddr, GFP_DMA |
	buf->vaddr = dma_alloc_coherent(dev, ssize, &paddr, GFP_DMA |
							     __GFP_ZERO);
	if (!buf->vaddr)
		return -ENOMEM;
@@ -1376,9 +1377,10 @@ static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
	return 0;
}

static void free_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
static void free_buf(struct device *dev, struct diu_addr *buf, u32 size,
		     u32 bytes_align)
{
	dma_free_coherent(NULL, size + bytes_align,
	dma_free_coherent(dev, size + bytes_align,
				buf->vaddr, (buf->paddr - buf->offset));
	return;
}
@@ -1476,17 +1478,19 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev,
	machine_data->monitor_port = monitor_port;

	/* Area descriptor memory pool aligns to 64-bit boundary */
	if (allocate_buf(&pool.ad, sizeof(struct diu_ad) * FSL_AOI_NUM, 8))
	if (allocate_buf(&ofdev->dev, &pool.ad,
			 sizeof(struct diu_ad) * FSL_AOI_NUM, 8))
		return -ENOMEM;

	/* Get memory for Gamma Table  - 32-byte aligned memory */
	if (allocate_buf(&pool.gamma, 768, 32)) {
	if (allocate_buf(&ofdev->dev, &pool.gamma, 768, 32)) {
		ret = -ENOMEM;
		goto error;
	}

	/* For performance, cursor bitmap buffer aligns to 32-byte boundary */
	if (allocate_buf(&pool.cursor, MAX_CURS * MAX_CURS * 2, 32)) {
	if (allocate_buf(&ofdev->dev, &pool.cursor, MAX_CURS * MAX_CURS * 2,
			 32)) {
		ret = -ENOMEM;
		goto error;
	}
@@ -1554,11 +1558,13 @@ error:
		i > 0; i--)
		uninstall_fb(machine_data->fsl_diu_info[i - 1]);
	if (pool.ad.vaddr)
		free_buf(&pool.ad, sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
		free_buf(&ofdev->dev, &pool.ad,
			 sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
	if (pool.gamma.vaddr)
		free_buf(&pool.gamma, 768, 32);
		free_buf(&ofdev->dev, &pool.gamma, 768, 32);
	if (pool.cursor.vaddr)
		free_buf(&pool.cursor, MAX_CURS * MAX_CURS * 2, 32);
		free_buf(&ofdev->dev, &pool.cursor, MAX_CURS * MAX_CURS * 2,
			 32);
	if (machine_data->dummy_aoi_virt)
		fsl_diu_free(machine_data->dummy_aoi_virt, 64);
	iounmap(dr.diu_reg);
@@ -1584,11 +1590,13 @@ static int fsl_diu_remove(struct of_device *ofdev)
	for (i = ARRAY_SIZE(machine_data->fsl_diu_info); i > 0; i--)
		uninstall_fb(machine_data->fsl_diu_info[i - 1]);
	if (pool.ad.vaddr)
		free_buf(&pool.ad, sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
		free_buf(&ofdev->dev, &pool.ad,
			 sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
	if (pool.gamma.vaddr)
		free_buf(&pool.gamma, 768, 32);
		free_buf(&ofdev->dev, &pool.gamma, 768, 32);
	if (pool.cursor.vaddr)
		free_buf(&pool.cursor, MAX_CURS * MAX_CURS * 2, 32);
		free_buf(&ofdev->dev, &pool.cursor, MAX_CURS * MAX_CURS * 2,
			 32);
	if (machine_data->dummy_aoi_virt)
		fsl_diu_free(machine_data->dummy_aoi_virt, 64);
	iounmap(dr.diu_reg);