Commit 30a9573d authored by Stelian Pop's avatar Stelian Pop Committed by Linus Torvalds

[PATCH] meye: replace homebrew queue with kfifo

Signed-off-by: default avatarStelian Pop <stelian@popies.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 73d89156
...@@ -65,68 +65,6 @@ MODULE_PARM_DESC(video_nr, "video device to register (0=/dev/video0, etc)"); ...@@ -65,68 +65,6 @@ MODULE_PARM_DESC(video_nr, "video device to register (0=/dev/video0, etc)");
/* driver structure - only one possible */ /* driver structure - only one possible */
static struct meye meye; static struct meye meye;
/****************************************************************************/
/* Queue routines */
/****************************************************************************/
/* Inits the queue */
static inline void meye_initq(struct meye_queue *queue) {
queue->head = queue->tail = 0;
queue->len = 0;
queue->s_lock = SPIN_LOCK_UNLOCKED;
init_waitqueue_head(&queue->proc_list);
}
/* Pulls an element from the queue */
static inline int meye_pullq(struct meye_queue *queue) {
int result;
unsigned long flags;
spin_lock_irqsave(&queue->s_lock, flags);
if (!queue->len) {
spin_unlock_irqrestore(&queue->s_lock, flags);
return -1;
}
result = queue->buf[queue->head];
queue->head++;
queue->head &= (MEYE_QUEUE_SIZE - 1);
queue->len--;
spin_unlock_irqrestore(&queue->s_lock, flags);
return result;
}
/* Pushes an element into the queue */
static inline void meye_pushq(struct meye_queue *queue, int element) {
unsigned long flags;
spin_lock_irqsave(&queue->s_lock, flags);
if (queue->len == MEYE_QUEUE_SIZE) {
/* remove the first element */
queue->head++;
queue->head &= (MEYE_QUEUE_SIZE - 1);
queue->len--;
}
queue->buf[queue->tail] = element;
queue->tail++;
queue->tail &= (MEYE_QUEUE_SIZE - 1);
queue->len++;
spin_unlock_irqrestore(&queue->s_lock, flags);
}
/* Tests if the queue is empty */
static inline int meye_emptyq(struct meye_queue *queue, int *elem) {
int result;
unsigned long flags;
spin_lock_irqsave(&queue->s_lock, flags);
result = (queue->len == 0);
if (!result && elem)
*elem = queue->buf[queue->head];
spin_unlock_irqrestore(&queue->s_lock, flags);
return result;
}
/****************************************************************************/ /****************************************************************************/
/* Memory allocation routines (stolen from bttv-driver.c) */ /* Memory allocation routines (stolen from bttv-driver.c) */
/****************************************************************************/ /****************************************************************************/
...@@ -839,54 +777,54 @@ static void mchip_cont_compression_start(void) { ...@@ -839,54 +777,54 @@ static void mchip_cont_compression_start(void) {
/****************************************************************************/ /****************************************************************************/
/* Interrupt handling */ /* Interrupt handling */
/****************************************************************************/ /****************************************************************************/
static irqreturn_t meye_irq(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t meye_irq(int irq, void *dev_id, struct pt_regs *regs) { {
u32 v; u32 v;
int reqnr; int reqnr;
v = mchip_read(MCHIP_MM_INTA); v = mchip_read(MCHIP_MM_INTA);
while (1) { if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_OUT &&
meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
return IRQ_NONE;
again:
v = mchip_get_frame(); v = mchip_get_frame();
if (!(v & MCHIP_MM_FIR_RDY)) if (!(v & MCHIP_MM_FIR_RDY))
return IRQ_NONE; return IRQ_HANDLED;
switch (meye.mchip_mode) {
case MCHIP_HIC_MODE_CONT_OUT: if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) {
if (!meye_emptyq(&meye.grabq, NULL)) { if (kfifo_get(meye.grabq, (unsigned char *)&reqnr,
int nr = meye_pullq(&meye.grabq); sizeof(int)) != sizeof(int)) {
mchip_cont_read_frame( mchip_free_frame();
v, return IRQ_HANDLED;
meye.grab_fbuffer + gbufsize * nr,
mchip_hsize() * mchip_vsize() * 2);
meye.grab_buffer[nr].state = MEYE_BUF_DONE;
wake_up_interruptible(&meye.grabq.proc_list);
} }
break; mchip_cont_read_frame(v, meye.grab_fbuffer + gbufsize * reqnr,
mchip_hsize() * mchip_vsize() * 2);
case MCHIP_HIC_MODE_CONT_COMP: meye.grab_buffer[reqnr].size = mchip_hsize() * mchip_vsize() * 2;
if (!meye_emptyq(&meye.grabq, &reqnr)) { meye.grab_buffer[reqnr].state = MEYE_BUF_DONE;
kfifo_put(meye.doneq, (unsigned char *)&reqnr, sizeof(int));
wake_up_interruptible(&meye.proc_list);
} else {
int size; int size;
size = mchip_comp_read_frame( size = mchip_comp_read_frame(v, meye.grab_temp, gbufsize);
v, if (size == -1) {
meye.grab_fbuffer + gbufsize * reqnr, mchip_free_frame();
gbufsize); goto again;
if (size == -1) }
break; if (kfifo_get(meye.grabq, (unsigned char *)&reqnr,
reqnr = meye_pullq(&meye.grabq); sizeof(int)) != sizeof(int)) {
mchip_free_frame();
goto again;
}
memcpy(meye.grab_fbuffer + gbufsize * reqnr, meye.grab_temp,
size);
meye.grab_buffer[reqnr].size = size; meye.grab_buffer[reqnr].size = size;
meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; meye.grab_buffer[reqnr].state = MEYE_BUF_DONE;
wake_up_interruptible(&meye.grabq.proc_list); kfifo_put(meye.doneq, (unsigned char *)&reqnr, sizeof(int));
wake_up_interruptible(&meye.proc_list);
} }
break;
default:
/* do not free frame, since it can be a snap */
return IRQ_NONE;
} /* switch */
mchip_free_frame(); mchip_free_frame();
} goto again;
return IRQ_HANDLED;
} }
/****************************************************************************/ /****************************************************************************/
...@@ -906,9 +844,12 @@ static int meye_open(struct inode *inode, struct file *file) { ...@@ -906,9 +844,12 @@ static int meye_open(struct inode *inode, struct file *file) {
return -ENOBUFS; return -ENOBUFS;
} }
mchip_hic_stop(); mchip_hic_stop();
meye_initq(&meye.grabq);
for (i = 0; i < MEYE_MAX_BUFNBRS; i++) for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
meye.grab_buffer[i].state = MEYE_BUF_UNUSED; meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
kfifo_reset(meye.grabq);
kfifo_reset(meye.doneq);
return 0; return 0;
} }
...@@ -983,6 +924,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, ...@@ -983,6 +924,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file,
case VIDIOCSYNC: { case VIDIOCSYNC: {
int *i = arg; int *i = arg;
int unused;
if (*i < 0 || *i >= gbuffers) if (*i < 0 || *i >= gbuffers)
return -EINVAL; return -EINVAL;
...@@ -992,12 +934,13 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, ...@@ -992,12 +934,13 @@ static int meye_do_ioctl(struct inode *inode, struct file *file,
case MEYE_BUF_UNUSED: case MEYE_BUF_UNUSED:
return -EINVAL; return -EINVAL;
case MEYE_BUF_USING: case MEYE_BUF_USING:
if (wait_event_interruptible(meye.grabq.proc_list, if (wait_event_interruptible(meye.proc_list,
(meye.grab_buffer[*i].state != MEYE_BUF_USING))) (meye.grab_buffer[*i].state != MEYE_BUF_USING)))
return -EINTR; return -EINTR;
/* fall through */ /* fall through */
case MEYE_BUF_DONE: case MEYE_BUF_DONE:
meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int));
} }
break; break;
} }
...@@ -1038,7 +981,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, ...@@ -1038,7 +981,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file,
if (restart || meye.mchip_mode != MCHIP_HIC_MODE_CONT_OUT) if (restart || meye.mchip_mode != MCHIP_HIC_MODE_CONT_OUT)
mchip_continuous_start(); mchip_continuous_start();
meye.grab_buffer[vm->frame].state = MEYE_BUF_USING; meye.grab_buffer[vm->frame].state = MEYE_BUF_USING;
meye_pushq(&meye.grabq, vm->frame); kfifo_put(meye.grabq, (unsigned char *)&vm->frame, sizeof(int));
up(&meye.lock); up(&meye.lock);
break; break;
} }
...@@ -1104,13 +1047,14 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, ...@@ -1104,13 +1047,14 @@ static int meye_do_ioctl(struct inode *inode, struct file *file,
if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP) if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
mchip_cont_compression_start(); mchip_cont_compression_start();
meye.grab_buffer[*nb].state = MEYE_BUF_USING; meye.grab_buffer[*nb].state = MEYE_BUF_USING;
meye_pushq(&meye.grabq, *nb); kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int));
up(&meye.lock); up(&meye.lock);
break; break;
} }
case MEYEIOC_SYNC: { case MEYEIOC_SYNC: {
int *i = arg; int *i = arg;
int unused;
if (*i < 0 || *i >= gbuffers) if (*i < 0 || *i >= gbuffers)
return -EINVAL; return -EINVAL;
...@@ -1120,12 +1064,13 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, ...@@ -1120,12 +1064,13 @@ static int meye_do_ioctl(struct inode *inode, struct file *file,
case MEYE_BUF_UNUSED: case MEYE_BUF_UNUSED:
return -EINVAL; return -EINVAL;
case MEYE_BUF_USING: case MEYE_BUF_USING:
if (wait_event_interruptible(meye.grabq.proc_list, if (wait_event_interruptible(meye.proc_list,
(meye.grab_buffer[*i].state != MEYE_BUF_USING))) (meye.grab_buffer[*i].state != MEYE_BUF_USING)))
return -EINTR; return -EINTR;
/* fall through */ /* fall through */
case MEYE_BUF_DONE: case MEYE_BUF_DONE:
meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int));
} }
*i = meye.grab_buffer[*i].size; *i = meye.grab_buffer[*i].size;
break; break;
...@@ -1290,6 +1235,29 @@ static int __devinit meye_probe(struct pci_dev *pcidev, ...@@ -1290,6 +1235,29 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
ret = -EBUSY; ret = -EBUSY;
goto out1; goto out1;
} }
ret = -ENOMEM;
meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE);
if (!meye.grab_temp) {
printk(KERN_ERR "meye: grab buffer allocation failed\n");
goto outvmalloc;
}
meye.grabq_lock = SPIN_LOCK_UNLOCKED;
meye.grabq = kfifo_alloc(sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL,
&meye.grabq_lock);
if (IS_ERR(meye.grabq)) {
printk(KERN_ERR "meye: fifo allocation failed\n");
goto outkfifoalloc1;
}
meye.doneq_lock = SPIN_LOCK_UNLOCKED;
meye.doneq = kfifo_alloc(sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL,
&meye.doneq_lock);
if (IS_ERR(meye.doneq)) {
printk(KERN_ERR "meye: fifo allocation failed\n");
goto outkfifoalloc2;
}
memcpy(meye.video_dev, &meye_template, sizeof(meye_template)); memcpy(meye.video_dev, &meye_template, sizeof(meye_template));
meye.video_dev->dev = &meye.mchip_dev->dev; meye.video_dev->dev = &meye.mchip_dev->dev;
...@@ -1365,6 +1333,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev, ...@@ -1365,6 +1333,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
/* init all fields */ /* init all fields */
init_MUTEX(&meye.lock); init_MUTEX(&meye.lock);
init_waitqueue_head(&meye.proc_list);
meye.picture.depth = 2; meye.picture.depth = 2;
meye.picture.palette = VIDEO_PALETTE_YUV422; meye.picture.palette = VIDEO_PALETTE_YUV422;
...@@ -1402,6 +1371,13 @@ static int __devinit meye_probe(struct pci_dev *pcidev, ...@@ -1402,6 +1371,13 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
meye.video_dev = NULL; meye.video_dev = NULL;
sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 0); sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 0);
kfifo_free(meye.doneq);
outkfifoalloc2:
kfifo_free(meye.grabq);
outkfifoalloc1:
vfree(meye.grab_temp);
outvmalloc:
video_device_release(meye.video_dev);
out1: out1:
return ret; return ret;
} }
...@@ -1431,6 +1407,11 @@ static void __devexit meye_remove(struct pci_dev *pcidev) { ...@@ -1431,6 +1407,11 @@ static void __devexit meye_remove(struct pci_dev *pcidev) {
sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 0); sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 0);
kfifo_free(meye.doneq);
kfifo_free(meye.grabq);
vfree(meye.grab_temp);
printk(KERN_INFO "meye: removed\n"); printk(KERN_INFO "meye: removed\n");
} }
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/kfifo.h>
/****************************************************************************/ /****************************************************************************/
/* Motion JPEG chip registers */ /* Motion JPEG chip registers */
...@@ -280,16 +281,8 @@ struct meye_grab_buffer { ...@@ -280,16 +281,8 @@ struct meye_grab_buffer {
unsigned long size; /* size of jpg frame */ unsigned long size; /* size of jpg frame */
}; };
/* queues containing the buffer indices */ /* size of kfifos containings buffer indices */
#define MEYE_QUEUE_SIZE MEYE_MAX_BUFNBRS #define MEYE_QUEUE_SIZE MEYE_MAX_BUFNBRS
struct meye_queue {
unsigned int head; /* queue head */
unsigned int tail; /* queue tail */
unsigned int len; /* queue length */
spinlock_t s_lock; /* spinlock protecting the queue */
wait_queue_head_t proc_list; /* wait queue */
int buf[MEYE_QUEUE_SIZE]; /* queue contents */
};
/* Motion Eye device structure */ /* Motion Eye device structure */
struct meye { struct meye {
...@@ -306,13 +299,18 @@ struct meye { ...@@ -306,13 +299,18 @@ struct meye {
dma_addr_t mchip_dmahandle; /* mchip: dma handle to ptable toc */ dma_addr_t mchip_dmahandle; /* mchip: dma handle to ptable toc */
unsigned char *grab_fbuffer; /* capture framebuffer */ unsigned char *grab_fbuffer; /* capture framebuffer */
unsigned char *grab_temp; /* temporary buffer */
/* list of buffers */ /* list of buffers */
struct meye_grab_buffer grab_buffer[MEYE_MAX_BUFNBRS]; struct meye_grab_buffer grab_buffer[MEYE_MAX_BUFNBRS];
/* other */ /* other */
struct semaphore lock; /* semaphore for open/mmap... */ struct semaphore lock; /* semaphore for open/mmap... */
struct meye_queue grabq; /* queue for buffers to be grabbed */ struct kfifo *grabq; /* queue for buffers to be grabbed */
spinlock_t grabq_lock; /* lock protecting the queue */
struct kfifo *doneq; /* queue for grabbed buffers */
spinlock_t doneq_lock; /* lock protecting the queue */
wait_queue_head_t proc_list; /* wait queue */
struct video_device *video_dev; /* video device parameters */ struct video_device *video_dev; /* video device parameters */
struct video_picture picture; /* video picture parameters */ struct video_picture picture; /* video picture parameters */
......
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