[PATCH] media: zoran: move to dma-mapping interface
From: Arnd Bergmann
Date: Tue Apr 24 2018 - 16:42:27 EST
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 <arnd@xxxxxxxx>
---
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