diff options
| author | Stefani Seibold <stefani@seibold.net> | 2010-08-10 21:03:39 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-11 11:59:23 -0400 |
| commit | 5bf2b19320ec31d094d7370fdf536f7fd91fd799 (patch) | |
| tree | 47052fd9bdb0969d4a4a7d430695388094409964 | |
| parent | 2e956fb320568cc70861761483e2f0e2db75fd66 (diff) | |
kfifo: add example files to the kernel sample directory
Add four examples to the kernel sample directory.
It shows how to handle:
- a byte stream fifo
- a integer type fifo
- a dynamic record sized fifo
- the fifo DMA functions
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Stefani Seibold <stefani@seibold.net>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | samples/Kconfig | 10 | ||||
| -rw-r--r-- | samples/Makefile | 2 | ||||
| -rw-r--r-- | samples/kfifo/Makefile | 1 | ||||
| -rw-r--r-- | samples/kfifo/bytestream-example.c | 163 | ||||
| -rw-r--r-- | samples/kfifo/dma-example.c | 115 | ||||
| -rw-r--r-- | samples/kfifo/inttype-example.c | 157 | ||||
| -rw-r--r-- | samples/kfifo/record-example.c | 167 |
7 files changed, 614 insertions, 1 deletions
diff --git a/samples/Kconfig b/samples/Kconfig index 8924f72f0629..954a1d550c5f 100644 --- a/samples/Kconfig +++ b/samples/Kconfig | |||
| @@ -44,4 +44,14 @@ config SAMPLE_HW_BREAKPOINT | |||
| 44 | help | 44 | help |
| 45 | This builds kernel hardware breakpoint example modules. | 45 | This builds kernel hardware breakpoint example modules. |
| 46 | 46 | ||
| 47 | config SAMPLE_KFIFO | ||
| 48 | tristate "Build kfifo examples -- loadable modules only" | ||
| 49 | depends on m | ||
| 50 | help | ||
| 51 | This config option will allow you to build a number of | ||
| 52 | different kfifo sample modules showing how to use the | ||
| 53 | generic kfifo API. | ||
| 54 | |||
| 55 | If in doubt, say "N" here. | ||
| 56 | |||
| 47 | endif # SAMPLES | 57 | endif # SAMPLES |
diff --git a/samples/Makefile b/samples/Makefile index 0f15e6d77fd6..76b3c3455c29 100644 --- a/samples/Makefile +++ b/samples/Makefile | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | # Makefile for Linux samples code | 1 | # Makefile for Linux samples code |
| 2 | 2 | ||
| 3 | obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ tracepoints/ trace_events/ \ | 3 | obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ tracepoints/ trace_events/ \ |
| 4 | hw_breakpoint/ | 4 | hw_breakpoint/ kfifo/ |
diff --git a/samples/kfifo/Makefile b/samples/kfifo/Makefile new file mode 100644 index 000000000000..bcc9484a15b2 --- /dev/null +++ b/samples/kfifo/Makefile | |||
| @@ -0,0 +1 @@ | |||
| obj-$(CONFIG_SAMPLE_KFIFO) += bytestream-example.o dma-example.o inttype-example.o record-example.o | |||
diff --git a/samples/kfifo/bytestream-example.c b/samples/kfifo/bytestream-example.c new file mode 100644 index 000000000000..642eef3f6336 --- /dev/null +++ b/samples/kfifo/bytestream-example.c | |||
| @@ -0,0 +1,163 @@ | |||
| 1 | /* | ||
| 2 | * Sample kfifo byte stream implementation | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Stefani Seibold <stefani@seibold.net> | ||
| 5 | * | ||
| 6 | * Released under the GPL version 2 only. | ||
| 7 | * | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/init.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/proc_fs.h> | ||
| 13 | #include <linux/mutex.h> | ||
| 14 | #include <linux/kfifo.h> | ||
| 15 | |||
| 16 | /* | ||
| 17 | * This module shows how to create a byte stream fifo. | ||
| 18 | */ | ||
| 19 | |||
| 20 | /* fifo size in elements (bytes) */ | ||
| 21 | #define FIFO_SIZE 32 | ||
| 22 | |||
| 23 | /* name of the proc entry */ | ||
| 24 | #define PROC_FIFO "bytestream-fifo" | ||
| 25 | |||
| 26 | /* lock for procfs read access */ | ||
| 27 | static DEFINE_MUTEX(read_lock); | ||
| 28 | |||
| 29 | /* lock for procfs write access */ | ||
| 30 | static DEFINE_MUTEX(write_lock); | ||
| 31 | |||
| 32 | /* | ||
| 33 | * define DYNAMIC in this example for a dynamically allocated fifo. | ||
| 34 | * | ||
| 35 | * Otherwise the fifo storage will be a part of the fifo structure. | ||
| 36 | */ | ||
| 37 | #if 0 | ||
| 38 | #define DYNAMIC | ||
| 39 | #endif | ||
| 40 | |||
| 41 | #ifdef DYNAMIC | ||
| 42 | static struct kfifo test; | ||
| 43 | #else | ||
| 44 | static DECLARE_KFIFO(test, unsigned char, FIFO_SIZE); | ||
| 45 | #endif | ||
| 46 | |||
| 47 | static int __init testfunc(void) | ||
| 48 | { | ||
| 49 | unsigned char buf[6]; | ||
| 50 | unsigned char i; | ||
| 51 | unsigned int ret; | ||
| 52 | |||
| 53 | printk(KERN_INFO "byte stream fifo test start\n"); | ||
| 54 | |||
| 55 | /* put string into the fifo */ | ||
| 56 | kfifo_in(&test, "hello", 5); | ||
| 57 | |||
| 58 | /* put values into the fifo */ | ||
| 59 | for (i = 0; i != 10; i++) | ||
| 60 | kfifo_put(&test, &i); | ||
| 61 | |||
| 62 | /* show the number of used elements */ | ||
| 63 | printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test)); | ||
| 64 | |||
| 65 | /* get max of 5 bytes from the fifo */ | ||
| 66 | i = kfifo_out(&test, buf, 5); | ||
| 67 | printk(KERN_INFO "buf: %.*s\n", i, buf); | ||
| 68 | |||
| 69 | /* get max of 2 elements from the fifo */ | ||
| 70 | ret = kfifo_out(&test, buf, 2); | ||
| 71 | printk(KERN_INFO "ret: %d\n", ret); | ||
| 72 | /* and put it back to the end of the fifo */ | ||
| 73 | ret = kfifo_in(&test, buf, ret); | ||
| 74 | printk(KERN_INFO "ret: %d\n", ret); | ||
| 75 | |||
| 76 | /* put values into the fifo until is full */ | ||
| 77 | for (i = 20; kfifo_put(&test, &i); i++) | ||
| 78 | ; | ||
| 79 | |||
| 80 | printk(KERN_INFO "queue len: %u\n", kfifo_len(&test)); | ||
| 81 | |||
| 82 | /* print out all values in the fifo */ | ||
| 83 | while (kfifo_get(&test, &i)) | ||
| 84 | printk("%d ", i); | ||
| 85 | printk("\n"); | ||
| 86 | |||
| 87 | return 0; | ||
| 88 | } | ||
| 89 | |||
| 90 | static ssize_t fifo_write(struct file *file, const char __user *buf, | ||
| 91 | size_t count, loff_t *ppos) | ||
| 92 | { | ||
| 93 | int ret; | ||
| 94 | unsigned int copied; | ||
| 95 | |||
| 96 | if (mutex_lock_interruptible(&write_lock)) | ||
| 97 | return -ERESTARTSYS; | ||
| 98 | |||
| 99 | ret = kfifo_from_user(&test, buf, count, &copied); | ||
| 100 | |||
| 101 | mutex_unlock(&write_lock); | ||
| 102 | |||
| 103 | return ret ? ret : copied; | ||
| 104 | } | ||
| 105 | |||
| 106 | static ssize_t fifo_read(struct file *file, char __user *buf, | ||
| 107 | size_t count, loff_t *ppos) | ||
| 108 | { | ||
| 109 | int ret; | ||
| 110 | unsigned int copied; | ||
| 111 | |||
| 112 | if (mutex_lock_interruptible(&read_lock)) | ||
| 113 | return -ERESTARTSYS; | ||
| 114 | |||
| 115 | ret = kfifo_to_user(&test, buf, count, &copied); | ||
| 116 | |||
| 117 | mutex_unlock(&read_lock); | ||
| 118 | |||
| 119 | return ret ? ret : copied; | ||
| 120 | } | ||
| 121 | |||
| 122 | static const struct file_operations fifo_fops = { | ||
| 123 | .owner = THIS_MODULE, | ||
| 124 | .read = fifo_read, | ||
| 125 | .write = fifo_write, | ||
| 126 | }; | ||
| 127 | |||
| 128 | static int __init example_init(void) | ||
| 129 | { | ||
| 130 | #ifdef DYNAMIC | ||
| 131 | int ret; | ||
| 132 | |||
| 133 | ret = kfifo_alloc(&test, FIFO_SIZE, GFP_KERNEL); | ||
| 134 | if (ret) { | ||
| 135 | printk(KERN_ERR "error kfifo_alloc\n"); | ||
| 136 | return ret; | ||
| 137 | } | ||
| 138 | #else | ||
| 139 | INIT_KFIFO(test); | ||
| 140 | #endif | ||
| 141 | testfunc(); | ||
| 142 | |||
| 143 | if (proc_create(PROC_FIFO, 0, NULL, &fifo_fops) == NULL) { | ||
| 144 | #ifdef DYNAMIC | ||
| 145 | kfifo_free(&test); | ||
| 146 | #endif | ||
| 147 | return -ENOMEM; | ||
| 148 | } | ||
| 149 | return 0; | ||
| 150 | } | ||
| 151 | |||
| 152 | static void __exit example_exit(void) | ||
| 153 | { | ||
| 154 | remove_proc_entry(PROC_FIFO, NULL); | ||
| 155 | #ifdef DYNAMIC | ||
| 156 | kfifo_free(&test); | ||
| 157 | #endif | ||
| 158 | } | ||
| 159 | |||
| 160 | module_init(example_init); | ||
| 161 | module_exit(example_exit); | ||
| 162 | MODULE_LICENSE("GPL"); | ||
| 163 | MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>"); | ||
diff --git a/samples/kfifo/dma-example.c b/samples/kfifo/dma-example.c new file mode 100644 index 000000000000..b9482c28b41a --- /dev/null +++ b/samples/kfifo/dma-example.c | |||
| @@ -0,0 +1,115 @@ | |||
| 1 | /* | ||
| 2 | * Sample fifo dma implementation | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Stefani Seibold <stefani@seibold.net> | ||
| 5 | * | ||
| 6 | * Released under the GPL version 2 only. | ||
| 7 | * | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/init.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/kfifo.h> | ||
| 13 | |||
| 14 | /* | ||
| 15 | * This module shows how to handle fifo dma operations. | ||
| 16 | */ | ||
| 17 | |||
| 18 | /* fifo size in elements (bytes) */ | ||
| 19 | #define FIFO_SIZE 32 | ||
| 20 | |||
| 21 | static struct kfifo fifo; | ||
| 22 | |||
| 23 | static int __init example_init(void) | ||
| 24 | { | ||
| 25 | int i; | ||
| 26 | unsigned int ret; | ||
| 27 | struct scatterlist sg[10]; | ||
| 28 | |||
| 29 | printk(KERN_INFO "DMA fifo test start\n"); | ||
| 30 | |||
| 31 | if (kfifo_alloc(&fifo, FIFO_SIZE, GFP_KERNEL)) { | ||
| 32 | printk(KERN_ERR "error kfifo_alloc\n"); | ||
| 33 | return 1; | ||
| 34 | } | ||
| 35 | |||
| 36 | printk(KERN_INFO "queue size: %u\n", kfifo_size(&fifo)); | ||
| 37 | |||
| 38 | kfifo_in(&fifo, "test", 4); | ||
| 39 | |||
| 40 | for (i = 0; i != 9; i++) | ||
| 41 | kfifo_put(&fifo, &i); | ||
| 42 | |||
| 43 | /* kick away first byte */ | ||
| 44 | ret = kfifo_get(&fifo, &i); | ||
| 45 | |||
| 46 | printk(KERN_INFO "queue len: %u\n", kfifo_len(&fifo)); | ||
| 47 | |||
| 48 | ret = kfifo_dma_in_prepare(&fifo, sg, ARRAY_SIZE(sg), FIFO_SIZE); | ||
| 49 | printk(KERN_INFO "DMA sgl entries: %d\n", ret); | ||
| 50 | |||
| 51 | /* if 0 was returned, fifo is full and no sgl was created */ | ||
| 52 | if (ret) { | ||
| 53 | printk(KERN_INFO "scatterlist for receive:\n"); | ||
| 54 | for (i = 0; i < ARRAY_SIZE(sg); i++) { | ||
| 55 | printk(KERN_INFO | ||
| 56 | "sg[%d] -> " | ||
| 57 | "page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n", | ||
| 58 | i, sg[i].page_link, sg[i].offset, sg[i].length); | ||
| 59 | |||
| 60 | if (sg_is_last(&sg[i])) | ||
| 61 | break; | ||
| 62 | } | ||
| 63 | |||
| 64 | /* but here your code to setup and exectute the dma operation */ | ||
| 65 | /* ... */ | ||
| 66 | |||
| 67 | /* example: zero bytes received */ | ||
| 68 | ret = 0; | ||
| 69 | |||
| 70 | /* finish the dma operation and update the received data */ | ||
| 71 | kfifo_dma_in_finish(&fifo, ret); | ||
| 72 | } | ||
| 73 | |||
| 74 | ret = kfifo_dma_out_prepare(&fifo, sg, ARRAY_SIZE(sg), 8); | ||
| 75 | printk(KERN_INFO "DMA sgl entries: %d\n", ret); | ||
| 76 | |||
| 77 | /* if 0 was returned, no data was available and no sgl was created */ | ||
| 78 | if (ret) { | ||
| 79 | printk(KERN_INFO "scatterlist for transmit:\n"); | ||
| 80 | for (i = 0; i < ARRAY_SIZE(sg); i++) { | ||
| 81 | printk(KERN_INFO | ||
| 82 | "sg[%d] -> " | ||
| 83 | "page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n", | ||
| 84 | i, sg[i].page_link, sg[i].offset, sg[i].length); | ||
| 85 | |||
| 86 | if (sg_is_last(&sg[i])) | ||
| 87 | break; | ||
| 88 | } | ||
| 89 | |||
| 90 | /* but here your code to setup and exectute the dma operation */ | ||
| 91 | /* ... */ | ||
| 92 | |||
| 93 | /* example: 5 bytes transmitted */ | ||
| 94 | ret = 5; | ||
| 95 | |||
| 96 | /* finish the dma operation and update the transmitted data */ | ||
| 97 | kfifo_dma_out_finish(&fifo, ret); | ||
| 98 | } | ||
| 99 | |||
| 100 | printk(KERN_INFO "queue len: %u\n", kfifo_len(&fifo)); | ||
| 101 | |||
| 102 | return 0; | ||
| 103 | } | ||
| 104 | |||
| 105 | static void __exit example_exit(void) | ||
| 106 | { | ||
| 107 | #ifdef DYNAMIC | ||
| 108 | kfifo_free(&test); | ||
| 109 | #endif | ||
| 110 | } | ||
| 111 | |||
| 112 | module_init(example_init); | ||
| 113 | module_exit(example_exit); | ||
| 114 | MODULE_LICENSE("GPL"); | ||
| 115 | MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>"); | ||
diff --git a/samples/kfifo/inttype-example.c b/samples/kfifo/inttype-example.c new file mode 100644 index 000000000000..d6c5b7d9df64 --- /dev/null +++ b/samples/kfifo/inttype-example.c | |||
| @@ -0,0 +1,157 @@ | |||
| 1 | /* | ||
| 2 | * Sample kfifo int type implementation | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Stefani Seibold <stefani@seibold.net> | ||
| 5 | * | ||
| 6 | * Released under the GPL version 2 only. | ||
| 7 | * | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/init.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/proc_fs.h> | ||
| 13 | #include <linux/mutex.h> | ||
| 14 | #include <linux/kfifo.h> | ||
| 15 | |||
| 16 | /* | ||
| 17 | * This module shows how to create a int type fifo. | ||
| 18 | */ | ||
| 19 | |||
| 20 | /* fifo size in elements (ints) */ | ||
| 21 | #define FIFO_SIZE 32 | ||
| 22 | |||
| 23 | /* name of the proc entry */ | ||
| 24 | #define PROC_FIFO "int-fifo" | ||
| 25 | |||
| 26 | /* lock for procfs read access */ | ||
| 27 | static DEFINE_MUTEX(read_lock); | ||
| 28 | |||
| 29 | /* lock for procfs write access */ | ||
| 30 | static DEFINE_MUTEX(write_lock); | ||
| 31 | |||
| 32 | /* | ||
| 33 | * define DYNAMIC in this example for a dynamically allocated fifo. | ||
| 34 | * | ||
| 35 | * Otherwise the fifo storage will be a part of the fifo structure. | ||
| 36 | */ | ||
| 37 | #if 0 | ||
| 38 | #define DYNAMIC | ||
| 39 | #endif | ||
| 40 | |||
| 41 | #ifdef DYNAMIC | ||
| 42 | static DECLARE_KFIFO_PTR(test, int); | ||
| 43 | #else | ||
| 44 | static DEFINE_KFIFO(test, int, FIFO_SIZE); | ||
| 45 | #endif | ||
| 46 | |||
| 47 | static int __init testfunc(void) | ||
| 48 | { | ||
| 49 | int buf[6]; | ||
| 50 | int i; | ||
| 51 | unsigned int ret; | ||
| 52 | |||
| 53 | printk(KERN_INFO "int fifo test start\n"); | ||
| 54 | |||
| 55 | /* put values into the fifo */ | ||
| 56 | for (i = 0; i != 10; i++) | ||
| 57 | kfifo_put(&test, &i); | ||
| 58 | |||
| 59 | /* show the number of used elements */ | ||
| 60 | printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test)); | ||
| 61 | |||
| 62 | /* get max of 2 elements from the fifo */ | ||
| 63 | ret = kfifo_out(&test, buf, 2); | ||
| 64 | printk(KERN_INFO "ret: %d\n", ret); | ||
| 65 | /* and put it back to the end of the fifo */ | ||
| 66 | ret = kfifo_in(&test, buf, ret); | ||
| 67 | printk(KERN_INFO "ret: %d\n", ret); | ||
| 68 | |||
| 69 | for (i = 20; i != 30; i++) | ||
| 70 | kfifo_put(&test, &i); | ||
| 71 | |||
| 72 | printk(KERN_INFO "queue len: %u\n", kfifo_len(&test)); | ||
| 73 | |||
| 74 | /* show the first value without removing from the fifo */ | ||
| 75 | if (kfifo_peek(&test, &i)) | ||
| 76 | printk(KERN_INFO "%d\n", i); | ||
| 77 | |||
| 78 | /* print out all values in the fifo */ | ||
| 79 | while (kfifo_get(&test, &i)) | ||
| 80 | printk("%d ", i); | ||
| 81 | printk("\n"); | ||
| 82 | |||
| 83 | return 0; | ||
| 84 | } | ||
| 85 | |||
| 86 | static ssize_t fifo_write(struct file *file, const char __user *buf, | ||
| 87 | size_t count, loff_t *ppos) | ||
| 88 | { | ||
| 89 | int ret; | ||
| 90 | unsigned int copied; | ||
| 91 | |||
| 92 | if (mutex_lock_interruptible(&write_lock)) | ||
| 93 | return -ERESTARTSYS; | ||
| 94 | |||
| 95 | ret = kfifo_from_user(&test, buf, count, &copied); | ||
| 96 | |||
| 97 | mutex_unlock(&write_lock); | ||
| 98 | |||
| 99 | return ret ? ret : copied; | ||
| 100 | } | ||
| 101 | |||
| 102 | static ssize_t fifo_read(struct file *file, char __user *buf, | ||
| 103 | size_t count, loff_t *ppos) | ||
| 104 | { | ||
| 105 | int ret; | ||
| 106 | unsigned int copied; | ||
| 107 | |||
| 108 | if (mutex_lock_interruptible(&read_lock)) | ||
| 109 | return -ERESTARTSYS; | ||
| 110 | |||
| 111 | ret = kfifo_to_user(&test, buf, count, &copied); | ||
| 112 | |||
| 113 | mutex_unlock(&read_lock); | ||
| 114 | |||
| 115 | return ret ? ret : copied; | ||
| 116 | } | ||
| 117 | |||
| 118 | static const struct file_operations fifo_fops = { | ||
| 119 | .owner = THIS_MODULE, | ||
| 120 | .read = fifo_read, | ||
| 121 | .write = fifo_write, | ||
| 122 | }; | ||
| 123 | |||
| 124 | static int __init example_init(void) | ||
| 125 | { | ||
| 126 | #ifdef DYNAMIC | ||
| 127 | int ret; | ||
| 128 | |||
| 129 | ret = kfifo_alloc(&test, FIFO_SIZE, GFP_KERNEL); | ||
| 130 | if (ret) { | ||
| 131 | printk(KERN_ERR "error kfifo_alloc\n"); | ||
| 132 | return ret; | ||
| 133 | } | ||
| 134 | #endif | ||
| 135 | testfunc(); | ||
| 136 | |||
| 137 | if (proc_create(PROC_FIFO, 0, NULL, &fifo_fops) == NULL) { | ||
| 138 | #ifdef DYNAMIC | ||
| 139 | kfifo_free(&test); | ||
| 140 | #endif | ||
| 141 | return -ENOMEM; | ||
| 142 | } | ||
| 143 | return 0; | ||
| 144 | } | ||
| 145 | |||
| 146 | static void __exit example_exit(void) | ||
| 147 | { | ||
| 148 | remove_proc_entry(PROC_FIFO, NULL); | ||
| 149 | #ifdef DYNAMIC | ||
| 150 | kfifo_free(&test); | ||
| 151 | #endif | ||
| 152 | } | ||
| 153 | |||
| 154 | module_init(example_init); | ||
| 155 | module_exit(example_exit); | ||
| 156 | MODULE_LICENSE("GPL"); | ||
| 157 | MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>"); | ||
diff --git a/samples/kfifo/record-example.c b/samples/kfifo/record-example.c new file mode 100644 index 000000000000..32c6e0bda744 --- /dev/null +++ b/samples/kfifo/record-example.c | |||
| @@ -0,0 +1,167 @@ | |||
| 1 | /* | ||
| 2 | * Sample dynamic sized record fifo implementation | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Stefani Seibold <stefani@seibold.net> | ||
| 5 | * | ||
| 6 | * Released under the GPL version 2 only. | ||
| 7 | * | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/init.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/proc_fs.h> | ||
| 13 | #include <linux/mutex.h> | ||
| 14 | #include <linux/kfifo.h> | ||
| 15 | |||
| 16 | /* | ||
| 17 | * This module shows how to create a variable sized record fifo. | ||
| 18 | */ | ||
| 19 | |||
| 20 | /* fifo size in elements (bytes) */ | ||
| 21 | #define FIFO_SIZE 128 | ||
| 22 | |||
| 23 | /* name of the proc entry */ | ||
| 24 | #define PROC_FIFO "record-fifo" | ||
| 25 | |||
| 26 | /* lock for procfs read access */ | ||
| 27 | static DEFINE_MUTEX(read_lock); | ||
| 28 | |||
| 29 | /* lock for procfs write access */ | ||
| 30 | static DEFINE_MUTEX(write_lock); | ||
| 31 | |||
| 32 | /* | ||
| 33 | * define DYNAMIC in this example for a dynamically allocated fifo. | ||
| 34 | * | ||
| 35 | * Otherwise the fifo storage will be a part of the fifo structure. | ||
| 36 | */ | ||
| 37 | #if 0 | ||
| 38 | #define DYNAMIC | ||
| 39 | #endif | ||
| 40 | |||
| 41 | /* | ||
| 42 | * struct kfifo_rec_ptr_1 and STRUCT_KFIFO_REC_1 can handle records of a | ||
| 43 | * length between 0 and 255 bytes. | ||
| 44 | * | ||
| 45 | * struct kfifo_rec_ptr_2 and STRUCT_KFIFO_REC_2 can handle records of a | ||
| 46 | * length between 0 and 65535 bytes. | ||
| 47 | */ | ||
| 48 | |||
| 49 | #ifdef DYNAMIC | ||
| 50 | struct kfifo_rec_ptr_1 test; | ||
| 51 | |||
| 52 | #else | ||
| 53 | typedef STRUCT_KFIFO_REC_1(FIFO_SIZE) mytest; | ||
| 54 | |||
| 55 | static mytest test; | ||
| 56 | #endif | ||
| 57 | |||
| 58 | static int __init testfunc(void) | ||
| 59 | { | ||
| 60 | char buf[100]; | ||
| 61 | unsigned int i; | ||
| 62 | unsigned int ret; | ||
| 63 | struct { unsigned char buf[6]; } hello = { "hello" }; | ||
| 64 | |||
| 65 | printk(KERN_INFO "record fifo test start\n"); | ||
| 66 | |||
| 67 | kfifo_in(&test, &hello, sizeof(hello)); | ||
| 68 | |||
| 69 | /* show the size of the next record in the fifo */ | ||
| 70 | printk(KERN_INFO "fifo peek len: %u\n", kfifo_peek_len(&test)); | ||
| 71 | |||
| 72 | /* put in variable length data */ | ||
| 73 | for (i = 0; i < 10; i++) { | ||
| 74 | memset(buf, 'a' + i, i + 1); | ||
| 75 | kfifo_in(&test, buf, i + 1); | ||
| 76 | } | ||
| 77 | |||
| 78 | printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test)); | ||
| 79 | |||
| 80 | /* show the first record without removing from the fifo */ | ||
| 81 | ret = kfifo_out_peek(&test, buf, sizeof(buf)); | ||
| 82 | if (ret) | ||
| 83 | printk(KERN_INFO "%.*s\n", ret, buf); | ||
| 84 | |||
| 85 | /* print out all records in the fifo */ | ||
| 86 | while (!kfifo_is_empty(&test)) { | ||
| 87 | ret = kfifo_out(&test, buf, sizeof(buf)); | ||
| 88 | printk(KERN_INFO "%.*s\n", ret, buf); | ||
| 89 | } | ||
| 90 | |||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | static ssize_t fifo_write(struct file *file, const char __user *buf, | ||
| 95 | size_t count, loff_t *ppos) | ||
| 96 | { | ||
| 97 | int ret; | ||
| 98 | unsigned int copied; | ||
| 99 | |||
| 100 | if (mutex_lock_interruptible(&write_lock)) | ||
| 101 | return -ERESTARTSYS; | ||
| 102 | |||
| 103 | ret = kfifo_from_user(&test, buf, count, &copied); | ||
| 104 | |||
| 105 | mutex_unlock(&write_lock); | ||
| 106 | |||
| 107 | return ret ? ret : copied; | ||
| 108 | } | ||
| 109 | |||
| 110 | static ssize_t fifo_read(struct file *file, char __user *buf, | ||
| 111 | size_t count, loff_t *ppos) | ||
| 112 | { | ||
| 113 | int ret; | ||
| 114 | unsigned int copied; | ||
| 115 | |||
| 116 | if (mutex_lock_interruptible(&read_lock)) | ||
| 117 | return -ERESTARTSYS; | ||
| 118 | |||
| 119 | ret = kfifo_to_user(&test, buf, count, &copied); | ||
| 120 | |||
| 121 | mutex_unlock(&read_lock); | ||
| 122 | |||
| 123 | return ret ? ret : copied; | ||
| 124 | } | ||
| 125 | |||
| 126 | static const struct file_operations fifo_fops = { | ||
| 127 | .owner = THIS_MODULE, | ||
| 128 | .read = fifo_read, | ||
| 129 | .write = fifo_write, | ||
| 130 | }; | ||
| 131 | |||
| 132 | static int __init example_init(void) | ||
| 133 | { | ||
| 134 | #ifdef DYNAMIC | ||
| 135 | int ret; | ||
| 136 | |||
| 137 | ret = kfifo_alloc(&test, FIFO_SIZE, GFP_KERNEL); | ||
| 138 | if (ret) { | ||
| 139 | printk(KERN_ERR "error kfifo_alloc\n"); | ||
| 140 | return ret; | ||
| 141 | } | ||
| 142 | #else | ||
| 143 | INIT_KFIFO(test); | ||
| 144 | #endif | ||
| 145 | testfunc(); | ||
| 146 | |||
| 147 | if (proc_create(PROC_FIFO, 0, NULL, &fifo_fops) == NULL) { | ||
| 148 | #ifdef DYNAMIC | ||
| 149 | kfifo_free(&test); | ||
| 150 | #endif | ||
| 151 | return -ENOMEM; | ||
| 152 | } | ||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | static void __exit example_exit(void) | ||
| 157 | { | ||
| 158 | remove_proc_entry(PROC_FIFO, NULL); | ||
| 159 | #ifdef DYNAMIC | ||
| 160 | kfifo_free(&test); | ||
| 161 | #endif | ||
| 162 | } | ||
| 163 | |||
| 164 | module_init(example_init); | ||
| 165 | module_exit(example_exit); | ||
| 166 | MODULE_LICENSE("GPL"); | ||
| 167 | MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>"); | ||
