forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 [[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
Showing
7 changed files
with
614 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]>"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]>"); |
Oops, something went wrong.