diff options
-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>"); | ||