X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fmedia%2Fvideo%2Fvideo-buf.c;h=6504a5866849ab73d6058304d9b7dd91b9c85db7;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=9ef477523d27ecba4789ed4607bcb959ec335440;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c index 9ef477523..6504a5866 100644 --- a/drivers/media/video/video-buf.c +++ b/drivers/media/video/video-buf.c @@ -1,15 +1,20 @@ /* * * generic helper functions for video4linux capture buffers, to handle - * memory management and PCI DMA. Right now bttv + saa7134 use it. + * memory management and PCI DMA. + * Right now, bttv, saa7134, saa7146 and cx88 use it. * * The functions expect the hardware being able to scatter gatter * (i.e. the buffers are not linear in physical memory, but fragmented * into PAGE_SIZE chunks). They also assume the driver does not need - * to touch the video data (thus it is probably not useful for USB 1.1 - * as data often must be uncompressed by the drivers). + * to touch the video data. + * + * device specific map/unmap/sync stuff now are mapped as operations + * to allow its usage by USB and virtual devices. * * (c) 2001-2004 Gerd Knorr [SUSE Labs] + * (c) 2006 Mauro Carvalho Chehab + * (c) 2006 Ted Walther and John Sokol * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -59,8 +64,7 @@ videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages) pg = vmalloc_to_page(virt); if (NULL == pg) goto err; - if (PageHighMem(pg)) - BUG(); + BUG_ON(PageHighMem(pg)); sglist[i].page = pg; sglist[i].length = PAGE_SIZE; } @@ -168,6 +172,9 @@ int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, dprintk(1,"vmalloc_32(%d pages) failed\n",nr_pages); return -ENOMEM; } + dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n", + (unsigned long)dma->vmalloc, + nr_pages << PAGE_SHIFT); memset(dma->vmalloc,0,nr_pages << PAGE_SHIFT); dma->nr_pages = nr_pages; return 0; @@ -187,8 +194,10 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, return 0; } -int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma) +int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma) { + void *dev=q->dev; + MAGIC_CHECK(dma->magic,MAGIC_DMABUF); BUG_ON(0 == dma->nr_pages); @@ -198,7 +207,7 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma) } if (dma->vmalloc) { dma->sglist = videobuf_vmalloc_to_sg - (dma->vmalloc,dma->nr_pages); + (dma->vmalloc,dma->nr_pages); } if (dma->bus_addr) { dma->sglist = kmalloc(sizeof(struct scatterlist), GFP_KERNEL); @@ -213,13 +222,14 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma) dprintk(1,"scatterlist is NULL\n"); return -ENOMEM; } - if (!dma->bus_addr) { - dma->sglen = pci_map_sg(dev,dma->sglist,dma->nr_pages, - dma->direction); + if (q->ops->vb_map_sg) { + dma->sglen = q->ops->vb_map_sg(dev,dma->sglist, + dma->nr_pages, dma->direction); + } if (0 == dma->sglen) { printk(KERN_WARNING - "%s: pci_map_sg failed\n",__FUNCTION__); + "%s: videobuf_map_sg failed\n",__FUNCTION__); kfree(dma->sglist); dma->sglist = NULL; dma->sglen = 0; @@ -229,24 +239,31 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma) return 0; } -int videobuf_dma_pci_sync(struct pci_dev *dev, struct videobuf_dmabuf *dma) +int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma) { + void *dev=q->dev; + MAGIC_CHECK(dma->magic,MAGIC_DMABUF); BUG_ON(!dma->sglen); - if (!dma->bus_addr) - pci_dma_sync_sg_for_cpu(dev,dma->sglist,dma->nr_pages,dma->direction); + if (!dma->bus_addr && q->ops->vb_dma_sync_sg) + q->ops->vb_dma_sync_sg(dev,dma->sglist,dma->nr_pages, + dma->direction); + return 0; } -int videobuf_dma_pci_unmap(struct pci_dev *dev, struct videobuf_dmabuf *dma) +int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma) { + void *dev=q->dev; + MAGIC_CHECK(dma->magic,MAGIC_DMABUF); if (!dma->sglen) return 0; - if (!dma->bus_addr) - pci_unmap_sg(dev,dma->sglist,dma->nr_pages,dma->direction); + if (!dma->bus_addr && q->ops->vb_unmap_sg) + q->ops->vb_unmap_sg(dev,dma->sglist,dma->nr_pages, + dma->direction); kfree(dma->sglist); dma->sglist = NULL; dma->sglen = 0; @@ -319,7 +336,7 @@ int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr) } int -videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb, +videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb, struct v4l2_framebuffer *fbuf) { int err,pages; @@ -348,7 +365,12 @@ videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb, if (NULL == fbuf) return -EINVAL; /* FIXME: need sanity checks for vb->boff */ - bus = (dma_addr_t)fbuf->base + vb->boff; + /* + * Using a double cast to avoid compiler warnings when + * building for PAE. Compiler doesn't like direct casting + * of a 32 bit ptr to 64 bit integer. + */ + bus = (dma_addr_t)(unsigned long)fbuf->base + vb->boff; pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT; err = videobuf_dma_init_overlay(&vb->dma,PCI_DMA_FROMDEVICE, bus, pages); @@ -358,7 +380,7 @@ videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb, default: BUG(); } - err = videobuf_dma_pci_map(pci,&vb->dma); + err = videobuf_dma_map(q,&vb->dma); if (0 != err) return err; @@ -367,9 +389,47 @@ videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb, /* --------------------------------------------------------------------- */ +void videobuf_queue_pci(struct videobuf_queue* q) +{ + /* If not specified, defaults to PCI map sg */ + if (!q->ops->vb_map_sg) + q->ops->vb_map_sg=(vb_map_sg_t *)pci_map_sg; + + if (!q->ops->vb_dma_sync_sg) + q->ops->vb_dma_sync_sg=(vb_map_sg_t *)pci_dma_sync_sg_for_cpu; + if (!q->ops->vb_unmap_sg) + q->ops->vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg; +} + +int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma) +{ + struct videobuf_queue q; + struct videobuf_queue_ops qops; + + q.dev=pci; + qops.vb_map_sg=(vb_map_sg_t *)pci_map_sg; + qops.vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg; + q.ops = &qops; + + return (videobuf_dma_map(&q,dma)); +} + +int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma) +{ + struct videobuf_queue q; + struct videobuf_queue_ops qops; + + q.dev=pci; + qops.vb_map_sg=(vb_map_sg_t *)pci_map_sg; + qops.vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg; + q.ops = &qops; + + return (videobuf_dma_unmap(&q,dma)); +} + void videobuf_queue_init(struct videobuf_queue* q, struct videobuf_queue_ops *ops, - struct pci_dev *pci, + void *dev, spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, @@ -378,14 +438,16 @@ void videobuf_queue_init(struct videobuf_queue* q, { memset(q,0,sizeof(*q)); q->irqlock = irqlock; - q->pci = pci; + q->dev = dev; q->type = type; q->field = field; q->msize = msize; q->ops = ops; q->priv_data = priv; - init_MUTEX(&q->lock); + videobuf_queue_pci(q); + + mutex_init(&q->lock); INIT_LIST_HEAD(&q->stream); } @@ -428,11 +490,12 @@ videobuf_queue_is_busy(struct videobuf_queue *q) void videobuf_queue_cancel(struct videobuf_queue *q) { - unsigned long flags; + unsigned long flags=0; int i; /* remove queued buffers from list */ - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; @@ -441,7 +504,8 @@ videobuf_queue_cancel(struct videobuf_queue *q) q->bufs[i]->state = STATE_ERROR; } } - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); /* free all buffers + clear queue */ for (i = 0; i < VIDEO_MAX_FRAME; i++) { @@ -535,21 +599,31 @@ videobuf_reqbufs(struct videobuf_queue *q, unsigned int size,count; int retval; - if (req->type != q->type) + if (req->type != q->type) { + dprintk(1,"reqbufs: queue type invalid\n"); return -EINVAL; - if (req->count < 1) + } + if (req->count < 1) { + dprintk(1,"reqbufs: count invalid (%d)\n",req->count); return -EINVAL; + } if (req->memory != V4L2_MEMORY_MMAP && req->memory != V4L2_MEMORY_USERPTR && - req->memory != V4L2_MEMORY_OVERLAY) + req->memory != V4L2_MEMORY_OVERLAY) { + dprintk(1,"reqbufs: memory type invalid\n"); return -EINVAL; + } - if (q->streaming) + if (q->streaming) { + dprintk(1,"reqbufs: streaming already exists\n"); return -EBUSY; - if (!list_empty(&q->stream)) + } + if (!list_empty(&q->stream)) { + dprintk(1,"reqbufs: stream running\n"); return -EBUSY; + } - down(&q->lock); + mutex_lock(&q->lock); count = req->count; if (count > VIDEO_MAX_FRAME) count = VIDEO_MAX_FRAME; @@ -560,25 +634,33 @@ videobuf_reqbufs(struct videobuf_queue *q, count, size, (count*size)>>PAGE_SHIFT); retval = videobuf_mmap_setup(q,count,size,req->memory); - if (retval < 0) + if (retval < 0) { + dprintk(1,"reqbufs: mmap setup returned %d\n",retval); goto done; + } req->count = count; done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) { - if (unlikely(b->type != q->type)) + if (unlikely(b->type != q->type)) { + dprintk(1,"querybuf: Wrong type.\n"); return -EINVAL; - if (unlikely(b->index < 0 || b->index >= VIDEO_MAX_FRAME)) + } + if (unlikely(b->index < 0 || b->index >= VIDEO_MAX_FRAME)) { + dprintk(1,"querybuf: index out of range.\n"); return -EINVAL; - if (unlikely(NULL == q->bufs[b->index])) + } + if (unlikely(NULL == q->bufs[b->index])) { + dprintk(1,"querybuf: buffer is null.\n"); return -EINVAL; + } videobuf_status(b,q->bufs[b->index],q->type); return 0; } @@ -589,31 +671,46 @@ videobuf_qbuf(struct videobuf_queue *q, { struct videobuf_buffer *buf; enum v4l2_field field; - unsigned long flags; + unsigned long flags=0; int retval; - down(&q->lock); + mutex_lock(&q->lock); retval = -EBUSY; - if (q->reading) + if (q->reading) { + dprintk(1,"qbuf: Reading running...\n"); goto done; + } retval = -EINVAL; - if (b->type != q->type) + if (b->type != q->type) { + dprintk(1,"qbuf: Wrong type.\n"); goto done; - if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) + } + if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) { + dprintk(1,"qbuf: index out of range.\n"); goto done; + } buf = q->bufs[b->index]; - if (NULL == buf) + if (NULL == buf) { + dprintk(1,"qbuf: buffer is null.\n"); goto done; + } MAGIC_CHECK(buf->magic,MAGIC_BUFFER); - if (buf->memory != b->memory) + if (buf->memory != b->memory) { + dprintk(1,"qbuf: memory type is wrong.\n"); goto done; + } if (buf->state == STATE_QUEUED || - buf->state == STATE_ACTIVE) + buf->state == STATE_PREPARED || + buf->state == STATE_ACTIVE) { + dprintk(1,"qbuf: buffer is already queued or active.\n"); goto done; + } if (b->flags & V4L2_BUF_FLAG_INPUT) { - if (b->input >= q->inputs) + if (b->input >= q->inputs) { + dprintk(1,"qbuf: wrong input.\n"); goto done; + } buf->input = b->input; } else { buf->input = UNSET; @@ -621,12 +718,16 @@ videobuf_qbuf(struct videobuf_queue *q, switch (b->memory) { case V4L2_MEMORY_MMAP: - if (0 == buf->baddr) + if (0 == buf->baddr) { + dprintk(1,"qbuf: mmap requested but buffer addr is zero!\n"); goto done; + } break; case V4L2_MEMORY_USERPTR: - if (b->length < buf->bsize) + if (b->length < buf->bsize) { + dprintk(1,"qbuf: buffer length is not enough\n"); goto done; + } if (STATE_NEEDS_INIT != buf->state && buf->baddr != b->m.userptr) q->ops->buf_release(q,buf); buf->baddr = b->m.userptr; @@ -635,24 +736,31 @@ videobuf_qbuf(struct videobuf_queue *q, buf->boff = b->m.offset; break; default: + dprintk(1,"qbuf: wrong memory type\n"); goto done; } + dprintk(1,"qbuf: requesting next field\n"); field = videobuf_next_field(q); retval = q->ops->buf_prepare(q,buf,field); - if (0 != retval) + if (0 != retval) { + dprintk(1,"qbuf: buffer_prepare returned %d\n",retval); goto done; + } list_add_tail(&buf->stream,&q->stream); if (q->streaming) { - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); q->ops->buf_queue(q,buf); - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); } + dprintk(1,"qbuf: succeded\n"); retval = 0; done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -663,28 +771,41 @@ videobuf_dqbuf(struct videobuf_queue *q, struct videobuf_buffer *buf; int retval; - down(&q->lock); + mutex_lock(&q->lock); retval = -EBUSY; - if (q->reading) + if (q->reading) { + dprintk(1,"dqbuf: Reading running...\n"); goto done; + } retval = -EINVAL; - if (b->type != q->type) + if (b->type != q->type) { + dprintk(1,"dqbuf: Wrong type.\n"); goto done; - if (list_empty(&q->stream)) + } + if (list_empty(&q->stream)) { + dprintk(1,"dqbuf: stream running\n"); goto done; + } buf = list_entry(q->stream.next, struct videobuf_buffer, stream); retval = videobuf_waiton(buf, nonblocking, 1); - if (retval < 0) + if (retval < 0) { + dprintk(1,"dqbuf: waiton returned %d\n",retval); goto done; + } switch (buf->state) { case STATE_ERROR: + dprintk(1,"dqbuf: state is error\n"); retval = -EIO; - /* fall through */ + videobuf_dma_sync(q,&buf->dma); + buf->state = STATE_IDLE; + break; case STATE_DONE: - videobuf_dma_pci_sync(q->pci,&buf->dma); + dprintk(1,"dqbuf: state is done\n"); + videobuf_dma_sync(q,&buf->dma); buf->state = STATE_IDLE; break; default: + dprintk(1,"dqbuf: state invalid\n"); retval = -EINVAL; goto done; } @@ -693,7 +814,7 @@ videobuf_dqbuf(struct videobuf_queue *q, videobuf_status(b,buf,q->type); done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -701,10 +822,10 @@ int videobuf_streamon(struct videobuf_queue *q) { struct videobuf_buffer *buf; struct list_head *list; - unsigned long flags; + unsigned long flags=0; int retval; - down(&q->lock); + mutex_lock(&q->lock); retval = -EBUSY; if (q->reading) goto done; @@ -712,16 +833,18 @@ int videobuf_streamon(struct videobuf_queue *q) if (q->streaming) goto done; q->streaming = 1; - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); list_for_each(list,&q->stream) { buf = list_entry(list, struct videobuf_buffer, stream); if (buf->state == STATE_PREPARED) q->ops->buf_queue(q,buf); } - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -729,7 +852,7 @@ int videobuf_streamoff(struct videobuf_queue *q) { int retval = -EINVAL; - down(&q->lock); + mutex_lock(&q->lock); if (!q->streaming) goto done; videobuf_queue_cancel(q); @@ -737,7 +860,7 @@ int videobuf_streamoff(struct videobuf_queue *q) retval = 0; done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -746,7 +869,7 @@ videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data, size_t count, loff_t *ppos) { enum v4l2_field field; - unsigned long flags; + unsigned long flags=0; int retval; /* setup stuff */ @@ -763,12 +886,14 @@ videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data, goto done; /* start capture & wait */ - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); q->ops->buf_queue(q,q->read_buf); - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); retval = videobuf_waiton(q->read_buf,0,0); if (0 == retval) { - videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); + videobuf_dma_sync(q,&q->read_buf->dma); if (STATE_ERROR == q->read_buf->state) retval = -EIO; else @@ -788,11 +913,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, int nonblocking) { enum v4l2_field field; - unsigned long flags; + unsigned long flags=0; unsigned size, nbufs, bytes; int retval; - down(&q->lock); + mutex_lock(&q->lock); nbufs = 1; size = 0; q->ops->buf_setup(q,&nbufs,&size); @@ -810,6 +935,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, /* need to capture a new frame */ retval = -ENOMEM; q->read_buf = videobuf_alloc(q->msize); + dprintk(1,"video alloc=0x%p\n", q->read_buf); if (NULL == q->read_buf) goto done; q->read_buf->memory = V4L2_MEMORY_USERPTR; @@ -821,9 +947,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, q->read_buf = NULL; goto done; } - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); q->ops->buf_queue(q,q->read_buf); - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); q->read_off = 0; } @@ -831,7 +959,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, retval = videobuf_waiton(q->read_buf, nonblocking, 1); if (0 != retval) goto done; - videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); + videobuf_dma_sync(q,&q->read_buf->dma); if (STATE_ERROR == q->read_buf->state) { /* catch I/O errors */ @@ -860,14 +988,14 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, } done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } int videobuf_read_start(struct videobuf_queue *q) { enum v4l2_field field; - unsigned long flags; + unsigned long flags=0; int count = 0, size = 0; int err, i; @@ -888,10 +1016,12 @@ int videobuf_read_start(struct videobuf_queue *q) return err; list_add_tail(&q->bufs[i]->stream, &q->stream); } - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); for (i = 0; i < count; i++) q->ops->buf_queue(q,q->bufs[i]); - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); q->reading = 1; return 0; } @@ -919,10 +1049,10 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, { unsigned int *fc, bytes; int err, retval; - unsigned long flags; + unsigned long flags=0; dprintk(2,"%s\n",__FUNCTION__); - down(&q->lock); + mutex_lock(&q->lock); retval = -EBUSY; if (q->streaming) goto done; @@ -986,9 +1116,11 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, if (q->read_off == q->read_buf->size) { list_add_tail(&q->read_buf->stream, &q->stream); - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); q->ops->buf_queue(q,q->read_buf); - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); q->read_buf = NULL; } if (retval < 0) @@ -996,7 +1128,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, } done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -1007,7 +1139,7 @@ unsigned int videobuf_poll_stream(struct file *file, struct videobuf_buffer *buf = NULL; unsigned int rc = 0; - down(&q->lock); + mutex_lock(&q->lock); if (q->streaming) { if (!list_empty(&q->stream)) buf = list_entry(q->stream.next, @@ -1035,7 +1167,7 @@ unsigned int videobuf_poll_stream(struct file *file, buf->state == STATE_ERROR) rc = POLLIN|POLLRDNORM; } - up(&q->lock); + mutex_unlock(&q->lock); return rc; } @@ -1064,7 +1196,7 @@ videobuf_vm_close(struct vm_area_struct *vma) map->count--; if (0 == map->count) { dprintk(1,"munmap %p q=%p\n",map,q); - down(&q->lock); + mutex_lock(&q->lock); for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; @@ -1076,7 +1208,7 @@ videobuf_vm_close(struct vm_area_struct *vma) q->bufs[i]->baddr = 0; q->ops->buf_release(q,q->bufs[i]); } - up(&q->lock); + mutex_unlock(&q->lock); kfree(map); } return; @@ -1098,7 +1230,7 @@ videobuf_vm_nopage(struct vm_area_struct *vma, unsigned long vaddr, vaddr,vma->vm_start,vma->vm_end); if (vaddr > vma->vm_end) return NOPAGE_SIGBUS; - page = alloc_page(GFP_USER); + page = alloc_page(GFP_USER | __GFP_DMA32); if (!page) return NOPAGE_OOM; clear_user_page(page_address(page), vaddr, page); @@ -1170,7 +1302,7 @@ int videobuf_mmap_mapper(struct videobuf_queue *q, unsigned int first,last,size,i; int retval; - down(&q->lock); + mutex_lock(&q->lock); retval = -EINVAL; if (!(vma->vm_flags & VM_WRITE)) { dprintk(1,"mmap app bug: PROT_WRITE please\n"); @@ -1238,7 +1370,7 @@ int videobuf_mmap_mapper(struct videobuf_queue *q, retval = 0; done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -1250,11 +1382,14 @@ EXPORT_SYMBOL_GPL(videobuf_dma_init); EXPORT_SYMBOL_GPL(videobuf_dma_init_user); EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel); EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay); -EXPORT_SYMBOL_GPL(videobuf_dma_pci_map); -EXPORT_SYMBOL_GPL(videobuf_dma_pci_sync); -EXPORT_SYMBOL_GPL(videobuf_dma_pci_unmap); +EXPORT_SYMBOL_GPL(videobuf_dma_map); +EXPORT_SYMBOL_GPL(videobuf_dma_sync); +EXPORT_SYMBOL_GPL(videobuf_dma_unmap); EXPORT_SYMBOL_GPL(videobuf_dma_free); +EXPORT_SYMBOL_GPL(videobuf_pci_dma_map); +EXPORT_SYMBOL_GPL(videobuf_pci_dma_unmap); + EXPORT_SYMBOL_GPL(videobuf_alloc); EXPORT_SYMBOL_GPL(videobuf_waiton); EXPORT_SYMBOL_GPL(videobuf_iolock);