From 45465487897a1c6d508b14b904dc5777f7ec7e04 Mon Sep 17 00:00:00 2001 From: Stefani Seibold Date: Mon, 21 Dec 2009 14:37:26 -0800 Subject: kfifo: move struct kfifo in place This is a new generic kernel FIFO implementation. The current kernel fifo API is not very widely used, because it has to many constrains. Only 17 files in the current 2.6.31-rc5 used it. FIFO's are like list's a very basic thing and a kfifo API which handles the most use case would save a lot of development time and memory resources. I think this are the reasons why kfifo is not in use: - The API is to simple, important functions are missing - A fifo can be only allocated dynamically - There is a requirement of a spinlock whether you need it or not - There is no support for data records inside a fifo So I decided to extend the kfifo in a more generic way without blowing up the API to much. The new API has the following benefits: - Generic usage: For kernel internal use and/or device driver. - Provide an API for the most use case. - Slim API: The whole API provides 25 functions. - Linux style habit. - DECLARE_KFIFO, DEFINE_KFIFO and INIT_KFIFO Macros - Direct copy_to_user from the fifo and copy_from_user into the fifo. - The kfifo itself is an in place member of the using data structure, this save an indirection access and does not waste the kernel allocator. - Lockless access: if only one reader and one writer is active on the fifo, which is the common use case, no additional locking is necessary. - Remove spinlock - give the user the freedom of choice what kind of locking to use if one is required. - Ability to handle records. Three type of records are supported: - Variable length records between 0-255 bytes, with a record size field of 1 bytes. - Variable length records between 0-65535 bytes, with a record size field of 2 bytes. - Fixed size records, which no record size field. - Preserve memory resource. - Performance! - Easy to use! This patch: Since most users want to have the kfifo as part of another object, reorganize the code to allow including struct kfifo in another data structure. This requires changing the kfifo_alloc and kfifo_init prototypes so that we pass an existing kfifo pointer into them. This patch changes the implementation and all existing users. [akpm@linux-foundation.org: fix warning] Signed-off-by: Stefani Seibold Acked-by: Greg Kroah-Hartman Acked-by: Mauro Carvalho Chehab Acked-by: Andi Kleen Acked-by: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/meye.c | 48 ++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 25 deletions(-) (limited to 'drivers/media/video/meye.c') diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 6ffa64cd1c6d..dacbbb839b9e 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -800,7 +800,7 @@ again: return IRQ_HANDLED; if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) { - if (kfifo_get(meye.grabq, (unsigned char *)&reqnr, + if (kfifo_get(&meye.grabq, (unsigned char *)&reqnr, sizeof(int)) != sizeof(int)) { mchip_free_frame(); return IRQ_HANDLED; @@ -811,7 +811,7 @@ again: meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); meye.grab_buffer[reqnr].sequence = sequence++; - kfifo_put(meye.doneq, (unsigned char *)&reqnr, sizeof(int)); + kfifo_put(&meye.doneq, (unsigned char *)&reqnr, sizeof(int)); wake_up_interruptible(&meye.proc_list); } else { int size; @@ -820,7 +820,7 @@ again: mchip_free_frame(); goto again; } - if (kfifo_get(meye.grabq, (unsigned char *)&reqnr, + if (kfifo_get(&meye.grabq, (unsigned char *)&reqnr, sizeof(int)) != sizeof(int)) { mchip_free_frame(); goto again; @@ -831,7 +831,7 @@ again: meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); meye.grab_buffer[reqnr].sequence = sequence++; - kfifo_put(meye.doneq, (unsigned char *)&reqnr, sizeof(int)); + kfifo_put(&meye.doneq, (unsigned char *)&reqnr, sizeof(int)); wake_up_interruptible(&meye.proc_list); } mchip_free_frame(); @@ -859,8 +859,8 @@ static int meye_open(struct file *file) for (i = 0; i < MEYE_MAX_BUFNBRS; i++) meye.grab_buffer[i].state = MEYE_BUF_UNUSED; - kfifo_reset(meye.grabq); - kfifo_reset(meye.doneq); + kfifo_reset(&meye.grabq); + kfifo_reset(&meye.doneq); return 0; } @@ -933,7 +933,7 @@ static int meyeioc_qbuf_capt(int *nb) mchip_cont_compression_start(); meye.grab_buffer[*nb].state = MEYE_BUF_USING; - kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int)); + kfifo_put(&meye.grabq, (unsigned char *)nb, sizeof(int)); mutex_unlock(&meye.lock); return 0; @@ -965,7 +965,7 @@ static int meyeioc_sync(struct file *file, void *fh, int *i) /* fall through */ case MEYE_BUF_DONE: meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; - kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int)); + kfifo_get(&meye.doneq, (unsigned char *)&unused, sizeof(int)); } *i = meye.grab_buffer[*i].size; mutex_unlock(&meye.lock); @@ -1452,7 +1452,7 @@ static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) buf->flags |= V4L2_BUF_FLAG_QUEUED; buf->flags &= ~V4L2_BUF_FLAG_DONE; meye.grab_buffer[buf->index].state = MEYE_BUF_USING; - kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int)); + kfifo_put(&meye.grabq, (unsigned char *)&buf->index, sizeof(int)); mutex_unlock(&meye.lock); return 0; @@ -1467,18 +1467,18 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) mutex_lock(&meye.lock); - if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) { + if (kfifo_len(&meye.doneq) == 0 && file->f_flags & O_NONBLOCK) { mutex_unlock(&meye.lock); return -EAGAIN; } if (wait_event_interruptible(meye.proc_list, - kfifo_len(meye.doneq) != 0) < 0) { + kfifo_len(&meye.doneq) != 0) < 0) { mutex_unlock(&meye.lock); return -EINTR; } - if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr, + if (!kfifo_get(&meye.doneq, (unsigned char *)&reqnr, sizeof(int))) { mutex_unlock(&meye.lock); return -EBUSY; @@ -1529,8 +1529,8 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i) { mutex_lock(&meye.lock); mchip_hic_stop(); - kfifo_reset(meye.grabq); - kfifo_reset(meye.doneq); + kfifo_reset(&meye.grabq); + kfifo_reset(&meye.doneq); for (i = 0; i < MEYE_MAX_BUFNBRS; i++) meye.grab_buffer[i].state = MEYE_BUF_UNUSED; @@ -1572,7 +1572,7 @@ static unsigned int meye_poll(struct file *file, poll_table *wait) mutex_lock(&meye.lock); poll_wait(file, &meye.proc_list, wait); - if (kfifo_len(meye.doneq)) + if (kfifo_len(&meye.doneq)) res = POLLIN | POLLRDNORM; mutex_unlock(&meye.lock); return res; @@ -1745,16 +1745,14 @@ static int __devinit meye_probe(struct pci_dev *pcidev, } spin_lock_init(&meye.grabq_lock); - meye.grabq = kfifo_alloc(sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, - &meye.grabq_lock); - if (IS_ERR(meye.grabq)) { + if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, + &meye.grabq_lock)) { printk(KERN_ERR "meye: fifo allocation failed\n"); goto outkfifoalloc1; } spin_lock_init(&meye.doneq_lock); - meye.doneq = kfifo_alloc(sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, - &meye.doneq_lock); - if (IS_ERR(meye.doneq)) { + if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, + &meye.doneq_lock)) { printk(KERN_ERR "meye: fifo allocation failed\n"); goto outkfifoalloc2; } @@ -1868,9 +1866,9 @@ outregions: outenabledev: sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0); outsonypienable: - kfifo_free(meye.doneq); + kfifo_free(&meye.doneq); outkfifoalloc2: - kfifo_free(meye.grabq); + kfifo_free(&meye.grabq); outkfifoalloc1: vfree(meye.grab_temp); outvmalloc: @@ -1901,8 +1899,8 @@ static void __devexit meye_remove(struct pci_dev *pcidev) sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0); - kfifo_free(meye.doneq); - kfifo_free(meye.grabq); + kfifo_free(&meye.doneq); + kfifo_free(&meye.grabq); vfree(meye.grab_temp); -- cgit v1.2.2 From c1e13f25674ed564948ecb7dfe5f83e578892896 Mon Sep 17 00:00:00 2001 From: Stefani Seibold Date: Mon, 21 Dec 2009 14:37:27 -0800 Subject: kfifo: move out spinlock Move the pointer to the spinlock out of struct kfifo. Most users in tree do not actually use a spinlock, so the few exceptions now have to call kfifo_{get,put}_locked, which takes an extra argument to a spinlock. Signed-off-by: Stefani Seibold Acked-by: Greg Kroah-Hartman Acked-by: Mauro Carvalho Chehab Acked-by: Andi Kleen Acked-by: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/meye.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'drivers/media/video/meye.c') diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index dacbbb839b9e..38bcedfd9fec 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -800,8 +800,8 @@ again: return IRQ_HANDLED; if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) { - if (kfifo_get(&meye.grabq, (unsigned char *)&reqnr, - sizeof(int)) != sizeof(int)) { + if (kfifo_get_locked(&meye.grabq, (unsigned char *)&reqnr, + sizeof(int), &meye.grabq_lock) != sizeof(int)) { mchip_free_frame(); return IRQ_HANDLED; } @@ -811,7 +811,8 @@ again: meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); meye.grab_buffer[reqnr].sequence = sequence++; - kfifo_put(&meye.doneq, (unsigned char *)&reqnr, sizeof(int)); + kfifo_put_locked(&meye.doneq, (unsigned char *)&reqnr, + sizeof(int), &meye.doneq_lock); wake_up_interruptible(&meye.proc_list); } else { int size; @@ -820,8 +821,8 @@ again: mchip_free_frame(); goto again; } - if (kfifo_get(&meye.grabq, (unsigned char *)&reqnr, - sizeof(int)) != sizeof(int)) { + if (kfifo_get_locked(&meye.grabq, (unsigned char *)&reqnr, + sizeof(int), &meye.grabq_lock) != sizeof(int)) { mchip_free_frame(); goto again; } @@ -831,7 +832,8 @@ again: meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); meye.grab_buffer[reqnr].sequence = sequence++; - kfifo_put(&meye.doneq, (unsigned char *)&reqnr, sizeof(int)); + kfifo_put_locked(&meye.doneq, (unsigned char *)&reqnr, + sizeof(int), &meye.doneq_lock); wake_up_interruptible(&meye.proc_list); } mchip_free_frame(); @@ -933,7 +935,8 @@ static int meyeioc_qbuf_capt(int *nb) mchip_cont_compression_start(); meye.grab_buffer[*nb].state = MEYE_BUF_USING; - kfifo_put(&meye.grabq, (unsigned char *)nb, sizeof(int)); + kfifo_put_locked(&meye.grabq, (unsigned char *)nb, sizeof(int), + &meye.grabq_lock); mutex_unlock(&meye.lock); return 0; @@ -965,7 +968,8 @@ static int meyeioc_sync(struct file *file, void *fh, int *i) /* fall through */ case MEYE_BUF_DONE: meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; - kfifo_get(&meye.doneq, (unsigned char *)&unused, sizeof(int)); + kfifo_get_locked(&meye.doneq, (unsigned char *)&unused, + sizeof(int), &meye.doneq_lock); } *i = meye.grab_buffer[*i].size; mutex_unlock(&meye.lock); @@ -1452,7 +1456,8 @@ static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) buf->flags |= V4L2_BUF_FLAG_QUEUED; buf->flags &= ~V4L2_BUF_FLAG_DONE; meye.grab_buffer[buf->index].state = MEYE_BUF_USING; - kfifo_put(&meye.grabq, (unsigned char *)&buf->index, sizeof(int)); + kfifo_put_locked(&meye.grabq, (unsigned char *)&buf->index, + sizeof(int), &meye.grabq_lock); mutex_unlock(&meye.lock); return 0; @@ -1478,8 +1483,8 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) return -EINTR; } - if (!kfifo_get(&meye.doneq, (unsigned char *)&reqnr, - sizeof(int))) { + if (!kfifo_get_locked(&meye.doneq, (unsigned char *)&reqnr, + sizeof(int), &meye.doneq_lock)) { mutex_unlock(&meye.lock); return -EBUSY; } @@ -1745,14 +1750,14 @@ static int __devinit meye_probe(struct pci_dev *pcidev, } spin_lock_init(&meye.grabq_lock); - if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, - &meye.grabq_lock)) { + if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS, + GFP_KERNEL)) { printk(KERN_ERR "meye: fifo allocation failed\n"); goto outkfifoalloc1; } spin_lock_init(&meye.doneq_lock); - if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, - &meye.doneq_lock)) { + if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS, + GFP_KERNEL)) { printk(KERN_ERR "meye: fifo allocation failed\n"); goto outkfifoalloc2; } -- cgit v1.2.2 From 7acd72eb85f1c7a15e8b5eb554994949241737f1 Mon Sep 17 00:00:00 2001 From: Stefani Seibold Date: Mon, 21 Dec 2009 14:37:28 -0800 Subject: kfifo: rename kfifo_put... into kfifo_in... and kfifo_get... into kfifo_out... rename kfifo_put... into kfifo_in... to prevent miss use of old non in kernel-tree drivers ditto for kfifo_get... -> kfifo_out... Improve the prototypes of kfifo_in and kfifo_out to make the kerneldoc annotations more readable. Add mini "howto porting to the new API" in kfifo.h Signed-off-by: Stefani Seibold Acked-by: Greg Kroah-Hartman Acked-by: Mauro Carvalho Chehab Acked-by: Andi Kleen Acked-by: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/meye.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/media/video/meye.c') diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 38bcedfd9fec..884a569d60a2 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -800,7 +800,7 @@ again: return IRQ_HANDLED; if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) { - if (kfifo_get_locked(&meye.grabq, (unsigned char *)&reqnr, + if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr, sizeof(int), &meye.grabq_lock) != sizeof(int)) { mchip_free_frame(); return IRQ_HANDLED; @@ -811,7 +811,7 @@ again: meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); meye.grab_buffer[reqnr].sequence = sequence++; - kfifo_put_locked(&meye.doneq, (unsigned char *)&reqnr, + kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr, sizeof(int), &meye.doneq_lock); wake_up_interruptible(&meye.proc_list); } else { @@ -821,7 +821,7 @@ again: mchip_free_frame(); goto again; } - if (kfifo_get_locked(&meye.grabq, (unsigned char *)&reqnr, + if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr, sizeof(int), &meye.grabq_lock) != sizeof(int)) { mchip_free_frame(); goto again; @@ -832,7 +832,7 @@ again: meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); meye.grab_buffer[reqnr].sequence = sequence++; - kfifo_put_locked(&meye.doneq, (unsigned char *)&reqnr, + kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr, sizeof(int), &meye.doneq_lock); wake_up_interruptible(&meye.proc_list); } @@ -935,7 +935,7 @@ static int meyeioc_qbuf_capt(int *nb) mchip_cont_compression_start(); meye.grab_buffer[*nb].state = MEYE_BUF_USING; - kfifo_put_locked(&meye.grabq, (unsigned char *)nb, sizeof(int), + kfifo_in_locked(&meye.grabq, (unsigned char *)nb, sizeof(int), &meye.grabq_lock); mutex_unlock(&meye.lock); @@ -968,7 +968,7 @@ static int meyeioc_sync(struct file *file, void *fh, int *i) /* fall through */ case MEYE_BUF_DONE: meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; - kfifo_get_locked(&meye.doneq, (unsigned char *)&unused, + kfifo_out_locked(&meye.doneq, (unsigned char *)&unused, sizeof(int), &meye.doneq_lock); } *i = meye.grab_buffer[*i].size; @@ -1456,7 +1456,7 @@ static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) buf->flags |= V4L2_BUF_FLAG_QUEUED; buf->flags &= ~V4L2_BUF_FLAG_DONE; meye.grab_buffer[buf->index].state = MEYE_BUF_USING; - kfifo_put_locked(&meye.grabq, (unsigned char *)&buf->index, + kfifo_in_locked(&meye.grabq, (unsigned char *)&buf->index, sizeof(int), &meye.grabq_lock); mutex_unlock(&meye.lock); @@ -1483,7 +1483,7 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) return -EINTR; } - if (!kfifo_get_locked(&meye.doneq, (unsigned char *)&reqnr, + if (!kfifo_out_locked(&meye.doneq, (unsigned char *)&reqnr, sizeof(int), &meye.doneq_lock)) { mutex_unlock(&meye.lock); return -EBUSY; -- cgit v1.2.2 From 9842c38e917636fa7dc6b88aff17a8f1fd7f0cc0 Mon Sep 17 00:00:00 2001 From: Stefani Seibold Date: Mon, 21 Dec 2009 14:37:29 -0800 Subject: kfifo: fix warn_unused_result Fix the "ignoring return value of '...', declared with attribute warn_unused_result" compiler warning in several users of the new kfifo API. It removes the __must_check attribute from kfifo_in() and kfifo_in_locked() which must not necessary performed. Fix the allocation bug in the nozomi driver file, by moving out the kfifo_alloc from the interrupt handler into the probe function. Fix the kfifo_out() and kfifo_out_locked() users to handle a unexpected end of fifo. Signed-off-by: Stefani Seibold Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/meye.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/media/video/meye.c') diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 884a569d60a2..b421858ccf90 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -968,8 +968,9 @@ static int meyeioc_sync(struct file *file, void *fh, int *i) /* fall through */ case MEYE_BUF_DONE: meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; - kfifo_out_locked(&meye.doneq, (unsigned char *)&unused, - sizeof(int), &meye.doneq_lock); + if (kfifo_out_locked(&meye.doneq, (unsigned char *)&unused, + sizeof(int), &meye.doneq_lock) != sizeof(int)) + break; } *i = meye.grab_buffer[*i].size; mutex_unlock(&meye.lock); -- cgit v1.2.2