[PATCH] media: zoran: move to dma-mapping interface

Arnd Bergmann <[email protected]>
Newsgroups gmane.linux.kernel,gmane.comp.video.mjpeg.user,gmane.linux.drivers.video-input-infrastructure
Message-ID <[email protected]>
No drivers should use virt_to_bus() any more. This converts
one of the few remaining ones to the DMA mapping interface.

Signed-off-by: Arnd Bergmann <[email protected]>
---
 drivers/media/pci/zoran/Kconfig        |  2 +-
 drivers/media/pci/zoran/zoran.h        | 10 +++++--
 drivers/media/pci/zoran/zoran_card.c   | 10 +++++--
 drivers/media/pci/zoran/zoran_device.c | 16 +++++-----
 drivers/media/pci/zoran/zoran_driver.c | 54 +++++++++++++++++++++++++---------
 5 files changed, 63 insertions(+), 29 deletions(-)

diff --git a/drivers/media/pci/zoran/Kconfig b/drivers/media/pci/zoran/Kconfig
index 39ec35bd21a5..26f40e124a32 100644
--- a/drivers/media/pci/zoran/Kconfig
+++ b/drivers/media/pci/zoran/Kconfig
@@ -1,6 +1,6 @@
 config VIDEO_ZORAN
 	tristate "Zoran ZR36057/36067 Video For Linux"
-	depends on PCI && I2C_ALGOBIT && VIDEO_V4L2 && VIRT_TO_BUS
+	depends on PCI && I2C_ALGOBIT && VIDEO_V4L2
 	depends on !ALPHA
 	help
 	  Say Y for support for MJPEG capture cards based on the Zoran
diff --git a/drivers/media/pci/zoran/zoran.h b/drivers/media/pci/zoran/zoran.h
index 9bb3c21aa275..9ff3a9acb60a 100644
--- a/drivers/media/pci/zoran/zoran.h
+++ b/drivers/media/pci/zoran/zoran.h
@@ -183,13 +183,14 @@ struct zoran_buffer {
 	struct zoran_sync bs;		/* DONE: info to return to application */
 	union {
 		struct {
-			__le32 *frag_tab;	/* addresses of frag table */
-			u32 frag_tab_bus;	/* same value cached to save time in ISR */
+			__le32 *frag_tab;	/* DMA addresses of frag table */
+			void **frag_virt_tab;	/* virtual addresses of frag table */
+			dma_addr_t frag_tab_dma;/* same value cached to save time in ISR */
 		} jpg;
 		struct {
 			char *fbuffer;		/* virtual address of frame buffer */
 			unsigned long fbuffer_phys;/* physical address of frame buffer */
-			unsigned long fbuffer_bus;/* bus address of frame buffer */
+			dma_addr_t fbuffer_dma;/* bus address of frame buffer */
 		} v4l;
 	};
 };
@@ -221,6 +222,7 @@ struct zoran_fh {
 
 	struct zoran_overlay_settings overlay_settings;
 	u32 *overlay_mask;			/* overlay mask */
+	dma_addr_t overlay_mask_dma;
 	enum zoran_lock_activity overlay_active;/* feature currently in use? */
 
 	struct zoran_buffer_col buffers;	/* buffers' info */
@@ -307,6 +309,7 @@ struct zoran {
 
 	struct zoran_overlay_settings overlay_settings;
 	u32 *overlay_mask;	/* overlay mask */
+	dma_addr_t overlay_mask_dma;
 	enum zoran_lock_activity overlay_active;	/* feature currently in use? */
 
 	wait_queue_head_t v4l_capq;
@@ -346,6 +349,7 @@ struct zoran {
 
 	/* zr36057's code buffer table */
 	__le32 *stat_com;		/* stat_com[i] is indexed by dma_head/tail & BUZ_MASK_STAT_COM */
+	dma_addr_t stat_com_dma;
 
 	/* (value & BUZ_MASK_FRAME) corresponds to index in pend[] queue */
 	int jpg_pend[BUZ_MAX_FRAME];
diff --git a/drivers/media/pci/zoran/zoran_card.c b/drivers/media/pci/zoran/zoran_card.c
index a6b9ebd20263..dabd8bf77472 100644
--- a/drivers/media/pci/zoran/zoran_card.c
+++ b/drivers/media/pci/zoran/zoran_card.c
@@ -890,6 +890,7 @@ zoran_open_init_params (struct zoran *zr)
 	/* User must explicitly set a window */
 	zr->overlay_settings.is_set = 0;
 	zr->overlay_mask = NULL;
+	zr->overlay_mask_dma = 0;
 	zr->overlay_active = ZORAN_FREE;
 
 	zr->v4l_memgrab_active = 0;
@@ -1028,7 +1029,8 @@ static int zr36057_init (struct zoran *zr)
 
 	/* allocate memory *before* doing anything to the hardware
 	 * in case allocation fails */
-	zr->stat_com = kzalloc(BUZ_NUM_STAT_COM * 4, GFP_KERNEL);
+	zr->stat_com = dma_alloc_coherent(&zr->pci_dev->dev,
+				BUZ_NUM_STAT_COM * 4, &zr->stat_com_dma, GFP_KERNEL);
 	zr->video_dev = video_device_alloc();
 	if (!zr->stat_com || !zr->video_dev) {
 		dprintk(1,
@@ -1072,7 +1074,8 @@ static int zr36057_init (struct zoran *zr)
 	return 0;
 
 exit_free:
-	kfree(zr->stat_com);
+	dma_free_coherent(&zr->pci_dev->dev, BUZ_NUM_STAT_COM * 4,
+			  zr->stat_com, zr->stat_com_dma);
 	kfree(zr->video_dev);
 	return err;
 }
@@ -1107,7 +1110,8 @@ static void zoran_remove(struct pci_dev *pdev)
 	btwrite(0, ZR36057_SPGPPCR);
 	free_irq(zr->pci_dev->irq, zr);
 	/* unmap and free memory */
-	kfree(zr->stat_com);
+	dma_free_coherent(&zr->pci_dev->dev, BUZ_NUM_STAT_COM * 4,
+			  zr->stat_com, zr->stat_com_dma);
 	zoran_proc_cleanup(zr);
 	iounmap(zr->zr36057_mem);
 	pci_disable_device(zr->pci_dev);
diff --git a/drivers/media/pci/zoran/zoran_device.c b/drivers/media/pci/zoran/zoran_device.c
index 40adceebca7e..1ac7810ddd25 100644
--- a/drivers/media/pci/zoran/zoran_device.c
+++ b/drivers/media/pci/zoran/zoran_device.c
@@ -430,9 +430,9 @@ zr36057_set_vfe (struct zoran              *zr,
 		 * zr->overlay_settings.width instead of video_width */
 
 		mask_line_size = (BUZ_MAX_WIDTH + 31) / 32;
-		reg = virt_to_bus(zr->overlay_mask);
+		reg = zr->overlay_mask_dma;
 		btwrite(reg, ZR36057_MMTR);
-		reg = virt_to_bus(zr->overlay_mask + mask_line_size);
+		reg = zr->overlay_mask_dma + mask_line_size;
 		btwrite(reg, ZR36057_MMBR);
 		reg =
 		    mask_line_size - (zr->overlay_settings.width +
@@ -775,7 +775,7 @@ zr36057_set_jpg (struct zoran          *zr,
 	//btor(ZR36057_VFESPFR_VCLKPol, ZR36057_VFESPFR);
 
 	/* code base address */
-	reg = virt_to_bus(zr->stat_com);
+	reg = zr->stat_com_dma;
 	btwrite(reg, ZR36057_JCBA);
 
 	/* FIFO threshold (FIFO is 160. double words) */
@@ -1097,7 +1097,7 @@ zoran_feed_stat_com (struct zoran *zr)
 			if (!(zr->stat_com[i] & cpu_to_le32(1)))
 				break;
 			zr->stat_com[i] =
-			    cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus);
+			    cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_dma);
 		} else {
 			/* fill 2 stat_com entries */
 			i = ((zr->jpg_dma_head -
@@ -1105,9 +1105,9 @@ zoran_feed_stat_com (struct zoran *zr)
 			if (!(zr->stat_com[i] & cpu_to_le32(1)))
 				break;
 			zr->stat_com[i] =
-			    cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus);
+			    cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_dma);
 			zr->stat_com[i + 1] =
-			    cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus);
+			    cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_dma);
 		}
 		zr->jpg_buffers.buffer[frame].state = BUZ_STATE_DMA;
 		zr->jpg_dma_head++;
@@ -1272,7 +1272,7 @@ error_handler (struct zoran *zr,
 		printk(KERN_INFO "stat_com frames:");
 		for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
 			for (i = 0; i < zr->jpg_buffers.num_buffers; i++) {
-				if (le32_to_cpu(zr->stat_com[j]) == zr->jpg_buffers.buffer[i].jpg.frag_tab_bus)
+				if (le32_to_cpu(zr->stat_com[j]) == zr->jpg_buffers.buffer[i].jpg.frag_tab_dma)
 					printk(KERN_CONT "% d->%d", j, i);
 			}
 		}
@@ -1411,7 +1411,7 @@ zoran_irq (int             irq,
 
 					/* Buffer address */
 
-					reg = zr->v4l_buffers.buffer[frame].v4l.fbuffer_bus;
+					reg = zr->v4l_buffers.buffer[frame].v4l.fbuffer_dma;
 					btwrite(reg, ZR36057_VDTR);
 					if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2)
 						reg += zr->v4l_settings.bytesperline;
diff --git a/drivers/media/pci/zoran/zoran_driver.c b/drivers/media/pci/zoran/zoran_driver.c
index 4b6466961b41..dad1fb02ced2 100644
--- a/drivers/media/pci/zoran/zoran_driver.c
+++ b/drivers/media/pci/zoran/zoran_driver.c
@@ -235,15 +235,20 @@ static int v4l_fbuffer_alloc(struct zoran_fh *fh)
 		}
 		fh->buffers.buffer[i].v4l.fbuffer = mem;
 		fh->buffers.buffer[i].v4l.fbuffer_phys = virt_to_phys(mem);
-		fh->buffers.buffer[i].v4l.fbuffer_bus = virt_to_bus(mem);
+		fh->buffers.buffer[i].v4l.fbuffer_dma =
+			dma_map_single(&zr->pci_dev->dev, mem,
+				       fh->buffers.buffer_size,
+				       DMA_FROM_DEVICE);
+		if (!fh->buffers.buffer[i].v4l.fbuffer_dma)
+			return -ENXIO;
 		for (off = 0; off < fh->buffers.buffer_size;
 		     off += PAGE_SIZE)
 			SetPageReserved(virt_to_page(mem + off));
 		dprintk(4,
 			KERN_INFO
-			"%s: %s - V4L frame %d mem %p (bus: 0x%llx)\n",
+			"%s: %s - V4L frame %d mem %p (bus: %pad)\n",
 			ZR_DEVNAME(zr), __func__, i, mem,
-			(unsigned long long)virt_to_bus(mem));
+			&fh->buffers.buffer[i].v4l.fbuffer_dma);
 	}
 
 	fh->buffers.allocated = 1;
@@ -308,6 +313,7 @@ static int jpg_fbuffer_alloc(struct zoran_fh *fh)
 	struct zoran *zr = fh->zr;
 	int i, j, off;
 	u8 *mem;
+	void **virt_tab;
 
 	for (i = 0; i < fh->buffers.num_buffers; i++) {
 		if (fh->buffers.buffer[i].jpg.frag_tab)
@@ -319,16 +325,19 @@ static int jpg_fbuffer_alloc(struct zoran_fh *fh)
 		/* Allocate fragment table for this buffer */
 
 		mem = (void *)get_zeroed_page(GFP_KERNEL);
-		if (!mem) {
+		virt_tab = (void *)get_zeroed_page(GFP_KERNEL);
+		if (!mem || !virt_tab) {
 			dprintk(1,
 				KERN_ERR
 				"%s: %s - get_zeroed_page (frag_tab) failed for buffer %d\n",
 				ZR_DEVNAME(zr), __func__, i);
+			kfree(mem);
+			kfree(virt_tab);
 			jpg_fbuffer_free(fh);
 			return -ENOBUFS;
 		}
 		fh->buffers.buffer[i].jpg.frag_tab = (__le32 *)mem;
-		fh->buffers.buffer[i].jpg.frag_tab_bus = virt_to_bus(mem);
+		fh->buffers.buffer[i].jpg.frag_virt_tab = virt_tab;
 
 		if (fh->buffers.need_contiguous) {
 			mem = kmalloc(fh->buffers.buffer_size, GFP_KERNEL);
@@ -340,8 +349,9 @@ static int jpg_fbuffer_alloc(struct zoran_fh *fh)
 				jpg_fbuffer_free(fh);
 				return -ENOBUFS;
 			}
+			fh->buffers.buffer[i].jpg.frag_virt_tab[0] = mem;
 			fh->buffers.buffer[i].jpg.frag_tab[0] =
-				cpu_to_le32(virt_to_bus(mem));
+				cpu_to_le32(dma_map_single(&zr->pci_dev->dev, mem, fh->buffers.buffer_size, DMA_FROM_DEVICE));
 			fh->buffers.buffer[i].jpg.frag_tab[1] =
 				cpu_to_le32((fh->buffers.buffer_size >> 1) | 1);
 			for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE)
@@ -359,8 +369,9 @@ static int jpg_fbuffer_alloc(struct zoran_fh *fh)
 					return -ENOBUFS;
 				}
 
+				fh->buffers.buffer[i].jpg.frag_virt_tab[j] = mem;
 				fh->buffers.buffer[i].jpg.frag_tab[2 * j] =
-					cpu_to_le32(virt_to_bus(mem));
+					cpu_to_le32(dma_map_single(&zr->pci_dev->dev, mem, fh->buffers.buffer_size, DMA_FROM_DEVICE));
 				fh->buffers.buffer[i].jpg.frag_tab[2 * j + 1] =
 					cpu_to_le32((PAGE_SIZE >> 2) << 1);
 				SetPageReserved(virt_to_page(mem));
@@ -368,6 +379,8 @@ static int jpg_fbuffer_alloc(struct zoran_fh *fh)
 
 			fh->buffers.buffer[i].jpg.frag_tab[2 * j - 1] |= cpu_to_le32(1);
 		}
+
+		fh->buffers.buffer[i].jpg.frag_tab_dma = dma_map_single(&zr->pci_dev->dev, mem, PAGE_SIZE, DMA_TO_DEVICE);
 	}
 
 	dprintk(4,
@@ -400,9 +413,10 @@ static void jpg_fbuffer_free(struct zoran_fh *fh)
 			frag_tab = buffer->jpg.frag_tab[0];
 
 			if (frag_tab) {
-				mem = bus_to_virt(le32_to_cpu(frag_tab));
+				mem = buffer->jpg.frag_virt_tab[0];
 				for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE)
 					ClearPageReserved(virt_to_page(mem + off));
+				dma_unmap_single(&zr->pci_dev->dev, frag_tab, PAGE_SIZE, DMA_FROM_DEVICE);
 				kfree(mem);
 				buffer->jpg.frag_tab[0] = 0;
 				buffer->jpg.frag_tab[1] = 0;
@@ -413,14 +427,19 @@ static void jpg_fbuffer_free(struct zoran_fh *fh)
 
 				if (!frag_tab)
 					break;
-				ClearPageReserved(virt_to_page(bus_to_virt(le32_to_cpu(frag_tab))));
-				free_page((unsigned long)bus_to_virt(le32_to_cpu(frag_tab)));
+				ClearPageReserved(virt_to_page(buffer->jpg.frag_virt_tab[j]));
+				dma_unmap_single(&zr->pci_dev->dev, le32_to_cpu(frag_tab), PAGE_SIZE, DMA_FROM_DEVICE);
+				free_page((unsigned long)buffer->jpg.frag_virt_tab[j]);
+				buffer->jpg.frag_virt_tab[j] = NULL;
 				buffer->jpg.frag_tab[2 * j] = 0;
 				buffer->jpg.frag_tab[2 * j + 1] = 0;
 			}
 		}
 
+		dma_unmap_single(&zr->pci_dev->dev, buffer->jpg.frag_tab_dma, PAGE_SIZE, DMA_TO_DEVICE);
 		free_page((unsigned long)buffer->jpg.frag_tab);
+		free_page((unsigned long)buffer->jpg.frag_virt_tab);
+		buffer->jpg.frag_virt_tab = NULL;
 		buffer->jpg.frag_tab = NULL;
 	}
 
@@ -873,6 +892,7 @@ static void zoran_close_end_session(struct zoran_fh *fh)
 		if (!zr->v4l_memgrab_active)
 			zr36057_overlay(zr, 0);
 		zr->overlay_mask = NULL;
+		zr->overlay_mask_dma = 0;
 	}
 
 	if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
@@ -940,8 +960,10 @@ static int zoran_open(struct file *file)
 
 	/* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows
 	 * on norm-change! */
-	fh->overlay_mask =
-	    kmalloc(((768 + 31) / 32) * 576 * 4, GFP_KERNEL);
+	fh->overlay_mask = dma_alloc_wc(&zr->pci_dev->dev,
+					((768 + 31) / 32) * 576 * 4,
+					&fh->overlay_mask_dma,
+					GFP_KERNEL);
 	if (!fh->overlay_mask) {
 		dprintk(1,
 			KERN_ERR
@@ -1016,6 +1038,7 @@ zoran_close(struct file  *file)
 		zr->v4l_overlay_active = 0;
 		zr36057_overlay(zr, 0);
 		zr->overlay_mask = NULL;
+		zr->overlay_mask_dma = 0;
 
 		/* capture off */
 		wake_up_interruptible(&zr->v4l_capq);
@@ -1033,7 +1056,8 @@ zoran_close(struct file  *file)
 
 	v4l2_fh_del(&fh->fh);
 	v4l2_fh_exit(&fh->fh);
-	kfree(fh->overlay_mask);
+	dma_free_wc(&zr->pci_dev->dev, ((768 + 31) / 32) * 576 * 4,
+		    fh->overlay_mask, fh->overlay_mask_dma);
 	kfree(fh);
 
 	dprintk(4, KERN_INFO "%s: %s done\n", ZR_DEVNAME(zr), __func__);
@@ -1284,6 +1308,7 @@ static int setup_overlay(struct zoran_fh *fh, int on)
 		if (!zr->v4l_memgrab_active)
 			zr36057_overlay(zr, 0);
 		zr->overlay_mask = NULL;
+		zr->overlay_mask_dma = 0;
 	} else {
 		if (!zr->vbuf_base || !fh->overlay_settings.is_set) {
 			dprintk(1,
@@ -1302,6 +1327,7 @@ static int setup_overlay(struct zoran_fh *fh, int on)
 		zr->overlay_active = fh->overlay_active = ZORAN_LOCKED;
 		zr->v4l_overlay_active = 1;
 		zr->overlay_mask = fh->overlay_mask;
+		zr->overlay_mask_dma = fh->overlay_mask_dma;
 		zr->overlay_settings = fh->overlay_settings;
 		if (!zr->v4l_memgrab_active)
 			zr36057_overlay(zr, 1);
@@ -2763,7 +2789,7 @@ zoran_mmap (struct file           *file,
 				    le32_to_cpu(fh->buffers.
 				    buffer[i].jpg.frag_tab[2 * j]);
 				/* should just be pos on i386 */
-				page = virt_to_phys(bus_to_virt(pos))
+				page = virt_to_phys(fh->buffers.buffer[i].jpg.frag_virt_tab[j])
 								>> PAGE_SHIFT;
 				if (remap_pfn_range(vma, start, page,
 							todo, PAGE_SHARED)) {
-- 
2.9.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.