mirror of
https://github.com/torvalds/linux.git
synced 2024-11-16 00:52:01 +00:00
V4L/DVB (11840): change kmalloc to vmalloc for sglist allocation in videobuf_dma_map/unmap
Change kmalloc()/kfree() to vmalloc()/vfree() for sglist allocation during videobuf_dma_map() and videobuf_dma_unmap() High resolution sensors might require too many contiguous pages to be allocated for sglist by kmalloc() during videobuf_dma_map() (i.e. 256Kib for 8MP sensor). In such situations, kmalloc() could face some problem to find the required free memory. vmalloc() is a safer solution instead, as the allocated memory does not need to be contiguous. Signed-off-by: David Cohen <david.cohen@nokia.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
04a37e0f32
commit
1010ed1327
@ -62,3 +62,5 @@
|
|||||||
64 -> Easy Cap Capture DC-60 (em2860)
|
64 -> Easy Cap Capture DC-60 (em2860)
|
||||||
65 -> IO-DATA GV-MVP/SZ (em2820/em2840) [04bb:0515]
|
65 -> IO-DATA GV-MVP/SZ (em2820/em2840) [04bb:0515]
|
||||||
66 -> Empire dual TV (em2880)
|
66 -> Empire dual TV (em2880)
|
||||||
|
67 -> Terratec Grabby (em2860) [0ccd:0096]
|
||||||
|
68 -> Terratec AV350 (em2860) [0ccd:0084]
|
||||||
|
@ -58,9 +58,10 @@ videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages)
|
|||||||
struct page *pg;
|
struct page *pg;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL);
|
sglist = vmalloc(nr_pages * sizeof(*sglist));
|
||||||
if (NULL == sglist)
|
if (NULL == sglist)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
memset(sglist, 0, nr_pages * sizeof(*sglist));
|
||||||
sg_init_table(sglist, nr_pages);
|
sg_init_table(sglist, nr_pages);
|
||||||
for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
|
for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
|
||||||
pg = vmalloc_to_page(virt);
|
pg = vmalloc_to_page(virt);
|
||||||
@ -72,7 +73,7 @@ videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages)
|
|||||||
return sglist;
|
return sglist;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
kfree(sglist);
|
vfree(sglist);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +85,7 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset)
|
|||||||
|
|
||||||
if (NULL == pages[0])
|
if (NULL == pages[0])
|
||||||
return NULL;
|
return NULL;
|
||||||
sglist = kmalloc(nr_pages * sizeof(*sglist), GFP_KERNEL);
|
sglist = vmalloc(nr_pages * sizeof(*sglist));
|
||||||
if (NULL == sglist)
|
if (NULL == sglist)
|
||||||
return NULL;
|
return NULL;
|
||||||
sg_init_table(sglist, nr_pages);
|
sg_init_table(sglist, nr_pages);
|
||||||
@ -104,12 +105,12 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset)
|
|||||||
|
|
||||||
nopage:
|
nopage:
|
||||||
dprintk(2,"sgl: oops - no page\n");
|
dprintk(2,"sgl: oops - no page\n");
|
||||||
kfree(sglist);
|
vfree(sglist);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
highmem:
|
highmem:
|
||||||
dprintk(2,"sgl: oops - highmem page\n");
|
dprintk(2,"sgl: oops - highmem page\n");
|
||||||
kfree(sglist);
|
vfree(sglist);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +231,7 @@ int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma)
|
|||||||
(dma->vmalloc,dma->nr_pages);
|
(dma->vmalloc,dma->nr_pages);
|
||||||
}
|
}
|
||||||
if (dma->bus_addr) {
|
if (dma->bus_addr) {
|
||||||
dma->sglist = kmalloc(sizeof(struct scatterlist), GFP_KERNEL);
|
dma->sglist = vmalloc(sizeof(*dma->sglist));
|
||||||
if (NULL != dma->sglist) {
|
if (NULL != dma->sglist) {
|
||||||
dma->sglen = 1;
|
dma->sglen = 1;
|
||||||
sg_dma_address(&dma->sglist[0]) = dma->bus_addr & PAGE_MASK;
|
sg_dma_address(&dma->sglist[0]) = dma->bus_addr & PAGE_MASK;
|
||||||
@ -248,7 +249,7 @@ int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma)
|
|||||||
if (0 == dma->sglen) {
|
if (0 == dma->sglen) {
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
"%s: videobuf_map_sg failed\n",__func__);
|
"%s: videobuf_map_sg failed\n",__func__);
|
||||||
kfree(dma->sglist);
|
vfree(dma->sglist);
|
||||||
dma->sglist = NULL;
|
dma->sglist = NULL;
|
||||||
dma->sglen = 0;
|
dma->sglen = 0;
|
||||||
return -EIO;
|
return -EIO;
|
||||||
@ -274,7 +275,7 @@ int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
|
|||||||
|
|
||||||
dma_unmap_sg(q->dev, dma->sglist, dma->nr_pages, dma->direction);
|
dma_unmap_sg(q->dev, dma->sglist, dma->nr_pages, dma->direction);
|
||||||
|
|
||||||
kfree(dma->sglist);
|
vfree(dma->sglist);
|
||||||
dma->sglist = NULL;
|
dma->sglist = NULL;
|
||||||
dma->sglen = 0;
|
dma->sglen = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user