Commit 5d9955f8 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB: uvc: Fix multiple symbols definitions with UVC gadget and host drivers



The UVC gadget driver borrowed code from the UVC host driver without
changing the symbol names. This results in a namespace clash with
multiple definitions of several symbols when compiling both drivers in
the kernel.

Make all generic UVC functions and variables static in the UVC gadget
driver, as the symbols are not referenced outside of the gadget driver.
Rename the uvc_trace_param global variable to uvc_gadget_trace_param.
Signed-off-by: Laurent Pinchart's avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent b6ae906b
......@@ -28,7 +28,7 @@
#include "uvc.h"
unsigned int uvc_trace_param;
unsigned int uvc_gadget_trace_param;
/* --------------------------------------------------------------------------
* Function descriptors
......@@ -656,6 +656,6 @@ uvc_bind_config(struct usb_configuration *c,
return ret;
}
module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR);
module_param_named(trace, uvc_gadget_trace_param, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(trace, "Trace level bitmask");
......@@ -107,11 +107,11 @@ struct uvc_streaming_control {
#define UVC_WARN_MINMAX 0
#define UVC_WARN_PROBE_DEF 1
extern unsigned int uvc_trace_param;
extern unsigned int uvc_gadget_trace_param;
#define uvc_trace(flag, msg...) \
do { \
if (uvc_trace_param & flag) \
if (uvc_gadget_trace_param & flag) \
printk(KERN_DEBUG "uvcvideo: " msg); \
} while (0)
......@@ -220,16 +220,10 @@ struct uvc_file_handle
#define to_uvc_file_handle(handle) \
container_of(handle, struct uvc_file_handle, vfh)
extern struct v4l2_file_operations uvc_v4l2_fops;
/* ------------------------------------------------------------------------
* Functions
*/
extern int uvc_video_enable(struct uvc_video *video, int enable);
extern int uvc_video_init(struct uvc_video *video);
extern int uvc_video_pump(struct uvc_video *video);
extern void uvc_endpoint_stream(struct uvc_device *dev);
extern void uvc_function_connect(struct uvc_device *uvc);
......
......@@ -78,7 +78,8 @@
*
*/
void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
static void
uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
{
mutex_init(&queue->mutex);
spin_lock_init(&queue->irqlock);
......@@ -87,6 +88,28 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
queue->type = type;
}
/*
* Free the video buffers.
*
* This function must be called with the queue lock held.
*/
static int uvc_free_buffers(struct uvc_video_queue *queue)
{
unsigned int i;
for (i = 0; i < queue->count; ++i) {
if (queue->buffer[i].vma_use_count != 0)
return -EBUSY;
}
if (queue->count) {
vfree(queue->mem);
queue->count = 0;
}
return 0;
}
/*
* Allocate the video buffers.
*
......@@ -95,8 +118,9 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
*
* Buffers will be individually mapped, so they must all be page aligned.
*/
int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
unsigned int buflength)
static int
uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
unsigned int buflength)
{
unsigned int bufsize = PAGE_ALIGN(buflength);
unsigned int i;
......@@ -150,28 +174,6 @@ int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
return ret;
}
/*
* Free the video buffers.
*
* This function must be called with the queue lock held.
*/
int uvc_free_buffers(struct uvc_video_queue *queue)
{
unsigned int i;
for (i = 0; i < queue->count; ++i) {
if (queue->buffer[i].vma_use_count != 0)
return -EBUSY;
}
if (queue->count) {
vfree(queue->mem);
queue->count = 0;
}
return 0;
}
static void __uvc_query_buffer(struct uvc_buffer *buf,
struct v4l2_buffer *v4l2_buf)
{
......@@ -195,8 +197,8 @@ static void __uvc_query_buffer(struct uvc_buffer *buf,
}
}
int uvc_query_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf)
static int
uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
{
int ret = 0;
......@@ -217,8 +219,8 @@ int uvc_query_buffer(struct uvc_video_queue *queue,
* Queue a video buffer. Attempting to queue a buffer that has already been
* queued will return -EINVAL.
*/
int uvc_queue_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf)
static int
uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
{
struct uvc_buffer *buf;
unsigned long flags;
......@@ -298,8 +300,9 @@ static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking)
* Dequeue a video buffer. If nonblocking is false, block until a buffer is
* available.
*/
int uvc_dequeue_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf, int nonblocking)
static int
uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf,
int nonblocking)
{
struct uvc_buffer *buf;
int ret = 0;
......@@ -359,8 +362,9 @@ int uvc_dequeue_buffer(struct uvc_video_queue *queue,
* This function implements video queue polling and is intended to be used by
* the device poll handler.
*/
unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
poll_table *wait)
static unsigned int
uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
poll_table *wait)
{
struct uvc_buffer *buf;
unsigned int mask = 0;
......@@ -407,7 +411,8 @@ static struct vm_operations_struct uvc_vm_ops = {
* This function implements video buffer memory mapping and is intended to be
* used by the device mmap handler.
*/
int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
static int
uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
{
struct uvc_buffer *uninitialized_var(buffer);
struct page *page;
......@@ -457,6 +462,42 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
return ret;
}
/*
* Cancel the video buffers queue.
*
* Cancelling the queue marks all buffers on the irq queue as erroneous,
* wakes them up and removes them from the queue.
*
* If the disconnect parameter is set, further calls to uvc_queue_buffer will
* fail with -ENODEV.
*
* This function acquires the irq spinlock and can be called from interrupt
* context.
*/
static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
{
struct uvc_buffer *buf;
unsigned long flags;
spin_lock_irqsave(&queue->irqlock, flags);
while (!list_empty(&queue->irqqueue)) {
buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
queue);
list_del(&buf->queue);
buf->state = UVC_BUF_STATE_ERROR;
wake_up(&buf->wait);
}
/* This must be protected by the irqlock spinlock to avoid race
* conditions between uvc_queue_buffer and the disconnection event that
* could result in an interruptible wait in uvc_dequeue_buffer. Do not
* blindly replace this logic by checking for the UVC_DEV_DISCONNECTED
* state outside the queue code.
*/
if (disconnect)
queue->flags |= UVC_QUEUE_DISCONNECTED;
spin_unlock_irqrestore(&queue->irqlock, flags);
}
/*
* Enable or disable the video buffers queue.
*
......@@ -474,7 +515,7 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
* This function can't be called from interrupt context. Use
* uvc_queue_cancel() instead.
*/
int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
static int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
{
unsigned int i;
int ret = 0;
......@@ -503,44 +544,8 @@ int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
return ret;
}
/*
* Cancel the video buffers queue.
*
* Cancelling the queue marks all buffers on the irq queue as erroneous,
* wakes them up and removes them from the queue.
*
* If the disconnect parameter is set, further calls to uvc_queue_buffer will
* fail with -ENODEV.
*
* This function acquires the irq spinlock and can be called from interrupt
* context.
*/
void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
{
struct uvc_buffer *buf;
unsigned long flags;
spin_lock_irqsave(&queue->irqlock, flags);
while (!list_empty(&queue->irqqueue)) {
buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
queue);
list_del(&buf->queue);
buf->state = UVC_BUF_STATE_ERROR;
wake_up(&buf->wait);
}
/* This must be protected by the irqlock spinlock to avoid race
* conditions between uvc_queue_buffer and the disconnection event that
* could result in an interruptible wait in uvc_dequeue_buffer. Do not
* blindly replace this logic by checking for the UVC_DEV_DISCONNECTED
* state outside the queue code.
*/
if (disconnect)
queue->flags |= UVC_QUEUE_DISCONNECTED;
spin_unlock_irqrestore(&queue->irqlock, flags);
}
struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
struct uvc_buffer *buf)
static struct uvc_buffer *
uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
{
struct uvc_buffer *nextbuf;
unsigned long flags;
......@@ -568,7 +573,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
return nextbuf;
}
struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue)
static struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue)
{
struct uvc_buffer *buf = NULL;
......
......@@ -58,30 +58,10 @@ struct uvc_video_queue {
struct list_head irqqueue;
};
extern void uvc_queue_init(struct uvc_video_queue *queue,
enum v4l2_buf_type type);
extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
unsigned int nbuffers, unsigned int buflength);
extern int uvc_free_buffers(struct uvc_video_queue *queue);
extern int uvc_query_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf);
extern int uvc_queue_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf);
extern int uvc_dequeue_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf, int nonblocking);
extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);
extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);
extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
struct uvc_buffer *buf);
extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
struct file *file, poll_table *wait);
extern int uvc_queue_mmap(struct uvc_video_queue *queue,
struct vm_area_struct *vma);
static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
{
return queue->flags & UVC_QUEUE_STREAMING;
}
extern struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue);
#endif /* __KERNEL__ */
......
......@@ -363,7 +363,7 @@ uvc_v4l2_poll(struct file *file, poll_table *wait)
return mask;
}
struct v4l2_file_operations uvc_v4l2_fops = {
static struct v4l2_file_operations uvc_v4l2_fops = {
.owner = THIS_MODULE,
.open = uvc_v4l2_open,
.release = uvc_v4l2_release,
......
......@@ -271,7 +271,7 @@ uvc_video_alloc_requests(struct uvc_video *video)
* This function fills the available USB requests (listed in req_free) with
* video data from the queued buffers.
*/
int
static int
uvc_video_pump(struct uvc_video *video)
{
struct usb_request *req;
......@@ -328,7 +328,7 @@ uvc_video_pump(struct uvc_video *video)
/*
* Enable or disable the video stream.
*/
int
static int
uvc_video_enable(struct uvc_video *video, int enable)
{
unsigned int i;
......@@ -367,7 +367,7 @@ uvc_video_enable(struct uvc_video *video, int enable)
/*
* Initialize the UVC video stream.
*/
int
static int
uvc_video_init(struct uvc_video *video)
{
INIT_LIST_HEAD(&video->req_free);
......
......@@ -28,10 +28,10 @@
#include "config.c"
#include "epautoconf.c"
#include "f_uvc.c"
#include "uvc_queue.c"
#include "uvc_v4l2.c"
#include "uvc_video.c"
#include "uvc_v4l2.c"
#include "f_uvc.c"
/* --------------------------------------------------------------------------
* Device descriptor
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment