Skip to content

Commit

Permalink
kfifo: add example files to the kernel sample directory
Browse files Browse the repository at this point in the history
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

[[email protected]: coding-style fixes]
Signed-off-by: Stefani Seibold <[email protected]>
Cc: Greg KH <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
sstefani authored and torvalds committed Aug 11, 2010
1 parent 2e956fb commit 5bf2b19
Show file tree
Hide file tree
Showing 7 changed files with 614 additions and 1 deletion.
10 changes: 10 additions & 0 deletions samples/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,14 @@ config SAMPLE_HW_BREAKPOINT
help
This builds kernel hardware breakpoint example modules.

config SAMPLE_KFIFO
tristate "Build kfifo examples -- loadable modules only"
depends on m
help
This config option will allow you to build a number of
different kfifo sample modules showing how to use the
generic kfifo API.

If in doubt, say "N" here.

endif # SAMPLES
2 changes: 1 addition & 1 deletion samples/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Makefile for Linux samples code

obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ tracepoints/ trace_events/ \
hw_breakpoint/
hw_breakpoint/ kfifo/
1 change: 1 addition & 0 deletions samples/kfifo/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
obj-$(CONFIG_SAMPLE_KFIFO) += bytestream-example.o dma-example.o inttype-example.o record-example.o
163 changes: 163 additions & 0 deletions samples/kfifo/bytestream-example.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/*
* Sample kfifo byte stream implementation
*
* Copyright (C) 2010 Stefani Seibold <[email protected]>
*
* Released under the GPL version 2 only.
*
*/

#include <linux/init.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/mutex.h>
#include <linux/kfifo.h>

/*
* This module shows how to create a byte stream fifo.
*/

/* fifo size in elements (bytes) */
#define FIFO_SIZE 32

/* name of the proc entry */
#define PROC_FIFO "bytestream-fifo"

/* lock for procfs read access */
static DEFINE_MUTEX(read_lock);

/* lock for procfs write access */
static DEFINE_MUTEX(write_lock);

/*
* define DYNAMIC in this example for a dynamically allocated fifo.
*
* Otherwise the fifo storage will be a part of the fifo structure.
*/
#if 0
#define DYNAMIC
#endif

#ifdef DYNAMIC
static struct kfifo test;
#else
static DECLARE_KFIFO(test, unsigned char, FIFO_SIZE);
#endif

static int __init testfunc(void)
{
unsigned char buf[6];
unsigned char i;
unsigned int ret;

printk(KERN_INFO "byte stream fifo test start\n");

/* put string into the fifo */
kfifo_in(&test, "hello", 5);

/* put values into the fifo */
for (i = 0; i != 10; i++)
kfifo_put(&test, &i);

/* show the number of used elements */
printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test));

/* get max of 5 bytes from the fifo */
i = kfifo_out(&test, buf, 5);
printk(KERN_INFO "buf: %.*s\n", i, buf);

/* get max of 2 elements from the fifo */
ret = kfifo_out(&test, buf, 2);
printk(KERN_INFO "ret: %d\n", ret);
/* and put it back to the end of the fifo */
ret = kfifo_in(&test, buf, ret);
printk(KERN_INFO "ret: %d\n", ret);

/* put values into the fifo until is full */
for (i = 20; kfifo_put(&test, &i); i++)
;

printk(KERN_INFO "queue len: %u\n", kfifo_len(&test));

/* print out all values in the fifo */
while (kfifo_get(&test, &i))
printk("%d ", i);
printk("\n");

return 0;
}

static ssize_t fifo_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
int ret;
unsigned int copied;

if (mutex_lock_interruptible(&write_lock))
return -ERESTARTSYS;

ret = kfifo_from_user(&test, buf, count, &copied);

mutex_unlock(&write_lock);

return ret ? ret : copied;
}

static ssize_t fifo_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
int ret;
unsigned int copied;

if (mutex_lock_interruptible(&read_lock))
return -ERESTARTSYS;

ret = kfifo_to_user(&test, buf, count, &copied);

mutex_unlock(&read_lock);

return ret ? ret : copied;
}

static const struct file_operations fifo_fops = {
.owner = THIS_MODULE,
.read = fifo_read,
.write = fifo_write,
};

static int __init example_init(void)
{
#ifdef DYNAMIC
int ret;

ret = kfifo_alloc(&test, FIFO_SIZE, GFP_KERNEL);
if (ret) {
printk(KERN_ERR "error kfifo_alloc\n");
return ret;
}
#else
INIT_KFIFO(test);
#endif
testfunc();

if (proc_create(PROC_FIFO, 0, NULL, &fifo_fops) == NULL) {
#ifdef DYNAMIC
kfifo_free(&test);
#endif
return -ENOMEM;
}
return 0;
}

static void __exit example_exit(void)
{
remove_proc_entry(PROC_FIFO, NULL);
#ifdef DYNAMIC
kfifo_free(&test);
#endif
}

module_init(example_init);
module_exit(example_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Stefani Seibold <[email protected]>");
115 changes: 115 additions & 0 deletions samples/kfifo/dma-example.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Sample fifo dma implementation
*
* Copyright (C) 2010 Stefani Seibold <[email protected]>
*
* Released under the GPL version 2 only.
*
*/

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kfifo.h>

/*
* This module shows how to handle fifo dma operations.
*/

/* fifo size in elements (bytes) */
#define FIFO_SIZE 32

static struct kfifo fifo;

static int __init example_init(void)
{
int i;
unsigned int ret;
struct scatterlist sg[10];

printk(KERN_INFO "DMA fifo test start\n");

if (kfifo_alloc(&fifo, FIFO_SIZE, GFP_KERNEL)) {
printk(KERN_ERR "error kfifo_alloc\n");
return 1;
}

printk(KERN_INFO "queue size: %u\n", kfifo_size(&fifo));

kfifo_in(&fifo, "test", 4);

for (i = 0; i != 9; i++)
kfifo_put(&fifo, &i);

/* kick away first byte */
ret = kfifo_get(&fifo, &i);

printk(KERN_INFO "queue len: %u\n", kfifo_len(&fifo));

ret = kfifo_dma_in_prepare(&fifo, sg, ARRAY_SIZE(sg), FIFO_SIZE);
printk(KERN_INFO "DMA sgl entries: %d\n", ret);

/* if 0 was returned, fifo is full and no sgl was created */
if (ret) {
printk(KERN_INFO "scatterlist for receive:\n");
for (i = 0; i < ARRAY_SIZE(sg); i++) {
printk(KERN_INFO
"sg[%d] -> "
"page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n",
i, sg[i].page_link, sg[i].offset, sg[i].length);

if (sg_is_last(&sg[i]))
break;
}

/* but here your code to setup and exectute the dma operation */
/* ... */

/* example: zero bytes received */
ret = 0;

/* finish the dma operation and update the received data */
kfifo_dma_in_finish(&fifo, ret);
}

ret = kfifo_dma_out_prepare(&fifo, sg, ARRAY_SIZE(sg), 8);
printk(KERN_INFO "DMA sgl entries: %d\n", ret);

/* if 0 was returned, no data was available and no sgl was created */
if (ret) {
printk(KERN_INFO "scatterlist for transmit:\n");
for (i = 0; i < ARRAY_SIZE(sg); i++) {
printk(KERN_INFO
"sg[%d] -> "
"page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n",
i, sg[i].page_link, sg[i].offset, sg[i].length);

if (sg_is_last(&sg[i]))
break;
}

/* but here your code to setup and exectute the dma operation */
/* ... */

/* example: 5 bytes transmitted */
ret = 5;

/* finish the dma operation and update the transmitted data */
kfifo_dma_out_finish(&fifo, ret);
}

printk(KERN_INFO "queue len: %u\n", kfifo_len(&fifo));

return 0;
}

static void __exit example_exit(void)
{
#ifdef DYNAMIC
kfifo_free(&test);
#endif
}

module_init(example_init);
module_exit(example_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Stefani Seibold <[email protected]>");
Loading

0 comments on commit 5bf2b19

Please sign in to comment.