diff options
author | Stefani Seibold <stefani@seibold.net> | 2009-12-21 17:37:26 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-22 17:17:55 -0500 |
commit | 45465487897a1c6d508b14b904dc5777f7ec7e04 (patch) | |
tree | 935c8dae68dc793ff2f795d57cf027531475cd53 /drivers/media | |
parent | 2ec91eec47f713e3d158ba5b28a24a85a2cf3650 (diff) |
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 <stefani@seibold.net>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Acked-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/meye.c | 48 | ||||
-rw-r--r-- | drivers/media/video/meye.h | 4 |
2 files changed, 25 insertions, 27 deletions
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: | |||
800 | return IRQ_HANDLED; | 800 | return IRQ_HANDLED; |
801 | 801 | ||
802 | if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) { | 802 | if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) { |
803 | if (kfifo_get(meye.grabq, (unsigned char *)&reqnr, | 803 | if (kfifo_get(&meye.grabq, (unsigned char *)&reqnr, |
804 | sizeof(int)) != sizeof(int)) { | 804 | sizeof(int)) != sizeof(int)) { |
805 | mchip_free_frame(); | 805 | mchip_free_frame(); |
806 | return IRQ_HANDLED; | 806 | return IRQ_HANDLED; |
@@ -811,7 +811,7 @@ again: | |||
811 | meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; | 811 | meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; |
812 | do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); | 812 | do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); |
813 | meye.grab_buffer[reqnr].sequence = sequence++; | 813 | meye.grab_buffer[reqnr].sequence = sequence++; |
814 | kfifo_put(meye.doneq, (unsigned char *)&reqnr, sizeof(int)); | 814 | kfifo_put(&meye.doneq, (unsigned char *)&reqnr, sizeof(int)); |
815 | wake_up_interruptible(&meye.proc_list); | 815 | wake_up_interruptible(&meye.proc_list); |
816 | } else { | 816 | } else { |
817 | int size; | 817 | int size; |
@@ -820,7 +820,7 @@ again: | |||
820 | mchip_free_frame(); | 820 | mchip_free_frame(); |
821 | goto again; | 821 | goto again; |
822 | } | 822 | } |
823 | if (kfifo_get(meye.grabq, (unsigned char *)&reqnr, | 823 | if (kfifo_get(&meye.grabq, (unsigned char *)&reqnr, |
824 | sizeof(int)) != sizeof(int)) { | 824 | sizeof(int)) != sizeof(int)) { |
825 | mchip_free_frame(); | 825 | mchip_free_frame(); |
826 | goto again; | 826 | goto again; |
@@ -831,7 +831,7 @@ again: | |||
831 | meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; | 831 | meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; |
832 | do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); | 832 | do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); |
833 | meye.grab_buffer[reqnr].sequence = sequence++; | 833 | meye.grab_buffer[reqnr].sequence = sequence++; |
834 | kfifo_put(meye.doneq, (unsigned char *)&reqnr, sizeof(int)); | 834 | kfifo_put(&meye.doneq, (unsigned char *)&reqnr, sizeof(int)); |
835 | wake_up_interruptible(&meye.proc_list); | 835 | wake_up_interruptible(&meye.proc_list); |
836 | } | 836 | } |
837 | mchip_free_frame(); | 837 | mchip_free_frame(); |
@@ -859,8 +859,8 @@ static int meye_open(struct file *file) | |||
859 | 859 | ||
860 | for (i = 0; i < MEYE_MAX_BUFNBRS; i++) | 860 | for (i = 0; i < MEYE_MAX_BUFNBRS; i++) |
861 | meye.grab_buffer[i].state = MEYE_BUF_UNUSED; | 861 | meye.grab_buffer[i].state = MEYE_BUF_UNUSED; |
862 | kfifo_reset(meye.grabq); | 862 | kfifo_reset(&meye.grabq); |
863 | kfifo_reset(meye.doneq); | 863 | kfifo_reset(&meye.doneq); |
864 | return 0; | 864 | return 0; |
865 | } | 865 | } |
866 | 866 | ||
@@ -933,7 +933,7 @@ static int meyeioc_qbuf_capt(int *nb) | |||
933 | mchip_cont_compression_start(); | 933 | mchip_cont_compression_start(); |
934 | 934 | ||
935 | meye.grab_buffer[*nb].state = MEYE_BUF_USING; | 935 | meye.grab_buffer[*nb].state = MEYE_BUF_USING; |
936 | kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int)); | 936 | kfifo_put(&meye.grabq, (unsigned char *)nb, sizeof(int)); |
937 | mutex_unlock(&meye.lock); | 937 | mutex_unlock(&meye.lock); |
938 | 938 | ||
939 | return 0; | 939 | return 0; |
@@ -965,7 +965,7 @@ static int meyeioc_sync(struct file *file, void *fh, int *i) | |||
965 | /* fall through */ | 965 | /* fall through */ |
966 | case MEYE_BUF_DONE: | 966 | case MEYE_BUF_DONE: |
967 | meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; | 967 | meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; |
968 | kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int)); | 968 | kfifo_get(&meye.doneq, (unsigned char *)&unused, sizeof(int)); |
969 | } | 969 | } |
970 | *i = meye.grab_buffer[*i].size; | 970 | *i = meye.grab_buffer[*i].size; |
971 | mutex_unlock(&meye.lock); | 971 | mutex_unlock(&meye.lock); |
@@ -1452,7 +1452,7 @@ static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) | |||
1452 | buf->flags |= V4L2_BUF_FLAG_QUEUED; | 1452 | buf->flags |= V4L2_BUF_FLAG_QUEUED; |
1453 | buf->flags &= ~V4L2_BUF_FLAG_DONE; | 1453 | buf->flags &= ~V4L2_BUF_FLAG_DONE; |
1454 | meye.grab_buffer[buf->index].state = MEYE_BUF_USING; | 1454 | meye.grab_buffer[buf->index].state = MEYE_BUF_USING; |
1455 | kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int)); | 1455 | kfifo_put(&meye.grabq, (unsigned char *)&buf->index, sizeof(int)); |
1456 | mutex_unlock(&meye.lock); | 1456 | mutex_unlock(&meye.lock); |
1457 | 1457 | ||
1458 | return 0; | 1458 | return 0; |
@@ -1467,18 +1467,18 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) | |||
1467 | 1467 | ||
1468 | mutex_lock(&meye.lock); | 1468 | mutex_lock(&meye.lock); |
1469 | 1469 | ||
1470 | if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) { | 1470 | if (kfifo_len(&meye.doneq) == 0 && file->f_flags & O_NONBLOCK) { |
1471 | mutex_unlock(&meye.lock); | 1471 | mutex_unlock(&meye.lock); |
1472 | return -EAGAIN; | 1472 | return -EAGAIN; |
1473 | } | 1473 | } |
1474 | 1474 | ||
1475 | if (wait_event_interruptible(meye.proc_list, | 1475 | if (wait_event_interruptible(meye.proc_list, |
1476 | kfifo_len(meye.doneq) != 0) < 0) { | 1476 | kfifo_len(&meye.doneq) != 0) < 0) { |
1477 | mutex_unlock(&meye.lock); | 1477 | mutex_unlock(&meye.lock); |
1478 | return -EINTR; | 1478 | return -EINTR; |
1479 | } | 1479 | } |
1480 | 1480 | ||
1481 | if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr, | 1481 | if (!kfifo_get(&meye.doneq, (unsigned char *)&reqnr, |
1482 | sizeof(int))) { | 1482 | sizeof(int))) { |
1483 | mutex_unlock(&meye.lock); | 1483 | mutex_unlock(&meye.lock); |
1484 | return -EBUSY; | 1484 | return -EBUSY; |
@@ -1529,8 +1529,8 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i) | |||
1529 | { | 1529 | { |
1530 | mutex_lock(&meye.lock); | 1530 | mutex_lock(&meye.lock); |
1531 | mchip_hic_stop(); | 1531 | mchip_hic_stop(); |
1532 | kfifo_reset(meye.grabq); | 1532 | kfifo_reset(&meye.grabq); |
1533 | kfifo_reset(meye.doneq); | 1533 | kfifo_reset(&meye.doneq); |
1534 | 1534 | ||
1535 | for (i = 0; i < MEYE_MAX_BUFNBRS; i++) | 1535 | for (i = 0; i < MEYE_MAX_BUFNBRS; i++) |
1536 | meye.grab_buffer[i].state = MEYE_BUF_UNUSED; | 1536 | meye.grab_buffer[i].state = MEYE_BUF_UNUSED; |
@@ -1572,7 +1572,7 @@ static unsigned int meye_poll(struct file *file, poll_table *wait) | |||
1572 | 1572 | ||
1573 | mutex_lock(&meye.lock); | 1573 | mutex_lock(&meye.lock); |
1574 | poll_wait(file, &meye.proc_list, wait); | 1574 | poll_wait(file, &meye.proc_list, wait); |
1575 | if (kfifo_len(meye.doneq)) | 1575 | if (kfifo_len(&meye.doneq)) |
1576 | res = POLLIN | POLLRDNORM; | 1576 | res = POLLIN | POLLRDNORM; |
1577 | mutex_unlock(&meye.lock); | 1577 | mutex_unlock(&meye.lock); |
1578 | return res; | 1578 | return res; |
@@ -1745,16 +1745,14 @@ static int __devinit meye_probe(struct pci_dev *pcidev, | |||
1745 | } | 1745 | } |
1746 | 1746 | ||
1747 | spin_lock_init(&meye.grabq_lock); | 1747 | spin_lock_init(&meye.grabq_lock); |
1748 | meye.grabq = kfifo_alloc(sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, | 1748 | if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, |
1749 | &meye.grabq_lock); | 1749 | &meye.grabq_lock)) { |
1750 | if (IS_ERR(meye.grabq)) { | ||
1751 | printk(KERN_ERR "meye: fifo allocation failed\n"); | 1750 | printk(KERN_ERR "meye: fifo allocation failed\n"); |
1752 | goto outkfifoalloc1; | 1751 | goto outkfifoalloc1; |
1753 | } | 1752 | } |
1754 | spin_lock_init(&meye.doneq_lock); | 1753 | spin_lock_init(&meye.doneq_lock); |
1755 | meye.doneq = kfifo_alloc(sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, | 1754 | if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, |
1756 | &meye.doneq_lock); | 1755 | &meye.doneq_lock)) { |
1757 | if (IS_ERR(meye.doneq)) { | ||
1758 | printk(KERN_ERR "meye: fifo allocation failed\n"); | 1756 | printk(KERN_ERR "meye: fifo allocation failed\n"); |
1759 | goto outkfifoalloc2; | 1757 | goto outkfifoalloc2; |
1760 | } | 1758 | } |
@@ -1868,9 +1866,9 @@ outregions: | |||
1868 | outenabledev: | 1866 | outenabledev: |
1869 | sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0); | 1867 | sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0); |
1870 | outsonypienable: | 1868 | outsonypienable: |
1871 | kfifo_free(meye.doneq); | 1869 | kfifo_free(&meye.doneq); |
1872 | outkfifoalloc2: | 1870 | outkfifoalloc2: |
1873 | kfifo_free(meye.grabq); | 1871 | kfifo_free(&meye.grabq); |
1874 | outkfifoalloc1: | 1872 | outkfifoalloc1: |
1875 | vfree(meye.grab_temp); | 1873 | vfree(meye.grab_temp); |
1876 | outvmalloc: | 1874 | outvmalloc: |
@@ -1901,8 +1899,8 @@ static void __devexit meye_remove(struct pci_dev *pcidev) | |||
1901 | 1899 | ||
1902 | sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0); | 1900 | sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0); |
1903 | 1901 | ||
1904 | kfifo_free(meye.doneq); | 1902 | kfifo_free(&meye.doneq); |
1905 | kfifo_free(meye.grabq); | 1903 | kfifo_free(&meye.grabq); |
1906 | 1904 | ||
1907 | vfree(meye.grab_temp); | 1905 | vfree(meye.grab_temp); |
1908 | 1906 | ||
diff --git a/drivers/media/video/meye.h b/drivers/media/video/meye.h index 5f70a106ba2b..1321ad5d6597 100644 --- a/drivers/media/video/meye.h +++ b/drivers/media/video/meye.h | |||
@@ -303,9 +303,9 @@ struct meye { | |||
303 | struct meye_grab_buffer grab_buffer[MEYE_MAX_BUFNBRS]; | 303 | struct meye_grab_buffer grab_buffer[MEYE_MAX_BUFNBRS]; |
304 | int vma_use_count[MEYE_MAX_BUFNBRS]; /* mmap count */ | 304 | int vma_use_count[MEYE_MAX_BUFNBRS]; /* mmap count */ |
305 | struct mutex lock; /* mutex for open/mmap... */ | 305 | struct mutex lock; /* mutex for open/mmap... */ |
306 | struct kfifo *grabq; /* queue for buffers to be grabbed */ | 306 | struct kfifo grabq; /* queue for buffers to be grabbed */ |
307 | spinlock_t grabq_lock; /* lock protecting the queue */ | 307 | spinlock_t grabq_lock; /* lock protecting the queue */ |
308 | struct kfifo *doneq; /* queue for grabbed buffers */ | 308 | struct kfifo doneq; /* queue for grabbed buffers */ |
309 | spinlock_t doneq_lock; /* lock protecting the queue */ | 309 | spinlock_t doneq_lock; /* lock protecting the queue */ |
310 | wait_queue_head_t proc_list; /* wait queue */ | 310 | wait_queue_head_t proc_list; /* wait queue */ |
311 | struct video_device *video_dev; /* video device parameters */ | 311 | struct video_device *video_dev; /* video device parameters */ |