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 21static struct kfifo fifo; 22 23static int __init example_init(void) 24{ 25 int i; 26 unsigned int ret; 27 unsigned int nents; 28 struct scatterlist sg[10]; 29 30 printk(KERN_INFO "DMA fifo test start\n"); 31 32 if (kfifo_alloc(&fifo, FIFO_SIZE, GFP_KERNEL)) { 33 printk(KERN_WARNING "error kfifo_alloc\n"); 34 return -ENOMEM; 35 } 36 37 printk(KERN_INFO "queue size: %u\n", kfifo_size(&fifo)); 38 39 kfifo_in(&fifo, "test", 4); 40 41 for (i = 0; i != 9; i++) 42 kfifo_put(&fifo, i); 43 44 /* kick away first byte */ 45 kfifo_skip(&fifo); 46 47 printk(KERN_INFO "queue len: %u\n", kfifo_len(&fifo)); 48 49 /* 50 * Configure the kfifo buffer to receive data from DMA input. 51 * 52 * .--------------------------------------. 53 * | 0 | 1 | 2 | ... | 12 | 13 | ... | 31 | 54 * |---|------------------|---------------| 55 * \_/ \________________/ \_____________/ 56 * \ \ \ 57 * \ \_allocated data \ 58 * \_*free space* \_*free space* 59 * 60 * We need two different SG entries: one for the free space area at the 61 * end of the kfifo buffer (19 bytes) and another for the first free 62 * byte at the beginning, after the kfifo_skip(). 63 */ 64 sg_init_table(sg, ARRAY_SIZE(sg)); 65 nents = kfifo_dma_in_prepare(&fifo, sg, ARRAY_SIZE(sg), FIFO_SIZE); 66 printk(KERN_INFO "DMA sgl entries: %d\n", nents); 67 if (!nents) { 68 /* fifo is full and no sgl was created */ 69 printk(KERN_WARNING "error kfifo_dma_in_prepare\n"); 70 return -EIO; 71 } 72 73 /* receive data */ 74 printk(KERN_INFO "scatterlist for receive:\n"); 75 for (i = 0; i < nents; i++) { 76 printk(KERN_INFO 77 "sg[%d] -> " 78 "page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n", 79 i, sg[i].page_link, sg[i].offset, sg[i].length); 80 81 if (sg_is_last(&sg[i])) 82 break; 83 } 84 85 /* put here your code to setup and exectute the dma operation */ 86 /* ... */ 87 88 /* example: zero bytes received */ 89 ret = 0; 90 91 /* finish the dma operation and update the received data */ 92 kfifo_dma_in_finish(&fifo, ret); 93 94 /* Prepare to transmit data, example: 8 bytes */ 95 nents = kfifo_dma_out_prepare(&fifo, sg, ARRAY_SIZE(sg), 8); 96 printk(KERN_INFO "DMA sgl entries: %d\n", nents); 97 if (!nents) { 98 /* no data was available and no sgl was created */ 99 printk(KERN_WARNING "error kfifo_dma_out_prepare\n"); 100 return -EIO; 101 } 102 103 printk(KERN_INFO "scatterlist for transmit:\n"); 104 for (i = 0; i < nents; i++) { 105 printk(KERN_INFO 106 "sg[%d] -> " 107 "page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n", 108 i, sg[i].page_link, sg[i].offset, sg[i].length); 109 110 if (sg_is_last(&sg[i])) 111 break; 112 } 113 114 /* put here your code to setup and exectute the dma operation */ 115 /* ... */ 116 117 /* example: 5 bytes transmitted */ 118 ret = 5; 119 120 /* finish the dma operation and update the transmitted data */ 121 kfifo_dma_out_finish(&fifo, ret); 122 123 ret = kfifo_len(&fifo); 124 printk(KERN_INFO "queue len: %u\n", kfifo_len(&fifo)); 125 126 if (ret != 7) { 127 printk(KERN_WARNING "size mismatch: test failed"); 128 return -EIO; 129 } 130 printk(KERN_INFO "test passed\n"); 131 132 return 0; 133} 134 135static void __exit example_exit(void) 136{ 137 kfifo_free(&fifo); 138} 139 140module_init(example_init); 141module_exit(example_exit); 142MODULE_LICENSE("GPL"); 143MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>"); 144