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>
Unified · Split
| @@ -44,4 +44,14 @@ config SAMPLE_HW_BREAKPOINT · 43 unmodified lines | ||
| 44 | 44 | help |
| 45 | 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 | 57 | endif # SAMPLES |
| @@ -1,4 +1,4 @@ | ||
| 1 | 1 | # Makefile for Linux samples code |
| 2 | 2 | |
| 3 | 3 | obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ tracepoints/ trace_events/ \ |
| 4 | − hw_breakpoint/ | |
| 4 | + hw_breakpoint/ kfifo/ | |
| @@ -0,0 +1 @@ | ||
| 1 | +obj-$(CONFIG_SAMPLE_KFIFO) += bytestream-example.o dma-example.o inttype-example.o record-example.o | |
| @@ -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>"); | |
| @@ -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>"); | |
| @@ -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>"); | |
| @@ -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>"); | |