Blame view

samples/kfifo/dma-example.c 3.39 KB
5bf2b1932   Stefani Seibold   kfifo: add exampl...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  /*
   * Sample fifo dma implementation
   *
   * Copyright (C) 2010 Stefani Seibold <stefani@seibold.net>
   *
   * 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;
399f1e30a   Ira W. Snyder   kfifo: fix scatte...
27
  	unsigned int		nents;
5bf2b1932   Stefani Seibold   kfifo: add exampl...
28
29
30
31
32
33
  	struct scatterlist	sg[10];
  
  	printk(KERN_INFO "DMA fifo test start
  ");
  
  	if (kfifo_alloc(&fifo, FIFO_SIZE, GFP_KERNEL)) {
a25effa4d   Andrea Righi   kfifo: add explic...
34
35
36
  		printk(KERN_WARNING "error kfifo_alloc
  ");
  		return -ENOMEM;
5bf2b1932   Stefani Seibold   kfifo: add exampl...
37
38
39
40
41
42
43
44
  	}
  
  	printk(KERN_INFO "queue size: %u
  ", kfifo_size(&fifo));
  
  	kfifo_in(&fifo, "test", 4);
  
  	for (i = 0; i != 9; i++)
498d319bb   Stefani Seibold   kfifo API type sa...
45
  		kfifo_put(&fifo, i);
5bf2b1932   Stefani Seibold   kfifo: add exampl...
46
47
  
  	/* kick away first byte */
a25effa4d   Andrea Righi   kfifo: add explic...
48
  	kfifo_skip(&fifo);
5bf2b1932   Stefani Seibold   kfifo: add exampl...
49
50
51
  
  	printk(KERN_INFO "queue len: %u
  ", kfifo_len(&fifo));
a25effa4d   Andrea Righi   kfifo: add explic...
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
  	/*
  	 * Configure the kfifo buffer to receive data from DMA input.
  	 *
  	 *  .--------------------------------------.
  	 *  | 0 | 1 | 2 | ... | 12 | 13 | ... | 31 |
  	 *  |---|------------------|---------------|
  	 *   \_/ \________________/ \_____________/
  	 *    \          \                  \
  	 *     \          \_allocated data   \
  	 *      \_*free space*                \_*free space*
  	 *
  	 * We need two different SG entries: one for the free space area at the
  	 * end of the kfifo buffer (19 bytes) and another for the first free
  	 * byte at the beginning, after the kfifo_skip().
  	 */
7b34d5257   Andrea Righi   kfifo: fix kernel...
67
  	sg_init_table(sg, ARRAY_SIZE(sg));
399f1e30a   Ira W. Snyder   kfifo: fix scatte...
68
69
70
71
  	nents = kfifo_dma_in_prepare(&fifo, sg, ARRAY_SIZE(sg), FIFO_SIZE);
  	printk(KERN_INFO "DMA sgl entries: %d
  ", nents);
  	if (!nents) {
a25effa4d   Andrea Righi   kfifo: add explic...
72
73
74
75
76
  		/* fifo is full and no sgl was created */
  		printk(KERN_WARNING "error kfifo_dma_in_prepare
  ");
  		return -EIO;
  	}
5bf2b1932   Stefani Seibold   kfifo: add exampl...
77

a25effa4d   Andrea Righi   kfifo: add explic...
78
79
80
  	/* receive data */
  	printk(KERN_INFO "scatterlist for receive:
  ");
399f1e30a   Ira W. Snyder   kfifo: fix scatte...
81
  	for (i = 0; i < nents; i++) {
a25effa4d   Andrea Righi   kfifo: add explic...
82
83
  		printk(KERN_INFO
  		"sg[%d] -> "
9263969a4   Logan Gunthorpe   kfifo: clean up e...
84
85
86
  		"page %p offset 0x%.8x length 0x%.8x
  ",
  			i, sg_page(&sg[i]), sg[i].offset, sg[i].length);
5bf2b1932   Stefani Seibold   kfifo: add exampl...
87

a25effa4d   Andrea Righi   kfifo: add explic...
88
89
90
  		if (sg_is_last(&sg[i]))
  			break;
  	}
5bf2b1932   Stefani Seibold   kfifo: add exampl...
91

a25effa4d   Andrea Righi   kfifo: add explic...
92
93
  	/* put here your code to setup and exectute the dma operation */
  	/* ... */
5bf2b1932   Stefani Seibold   kfifo: add exampl...
94

a25effa4d   Andrea Righi   kfifo: add explic...
95
96
  	/* example: zero bytes received */
  	ret = 0;
5bf2b1932   Stefani Seibold   kfifo: add exampl...
97

a25effa4d   Andrea Righi   kfifo: add explic...
98
99
  	/* finish the dma operation and update the received data */
  	kfifo_dma_in_finish(&fifo, ret);
5bf2b1932   Stefani Seibold   kfifo: add exampl...
100

a25effa4d   Andrea Righi   kfifo: add explic...
101
  	/* Prepare to transmit data, example: 8 bytes */
399f1e30a   Ira W. Snyder   kfifo: fix scatte...
102
103
104
105
  	nents = kfifo_dma_out_prepare(&fifo, sg, ARRAY_SIZE(sg), 8);
  	printk(KERN_INFO "DMA sgl entries: %d
  ", nents);
  	if (!nents) {
a25effa4d   Andrea Righi   kfifo: add explic...
106
107
108
109
110
  		/* no data was available and no sgl was created */
  		printk(KERN_WARNING "error kfifo_dma_out_prepare
  ");
  		return -EIO;
  	}
5bf2b1932   Stefani Seibold   kfifo: add exampl...
111

a25effa4d   Andrea Righi   kfifo: add explic...
112
113
  	printk(KERN_INFO "scatterlist for transmit:
  ");
399f1e30a   Ira W. Snyder   kfifo: fix scatte...
114
  	for (i = 0; i < nents; i++) {
a25effa4d   Andrea Righi   kfifo: add explic...
115
116
  		printk(KERN_INFO
  		"sg[%d] -> "
9263969a4   Logan Gunthorpe   kfifo: clean up e...
117
118
119
  		"page %p offset 0x%.8x length 0x%.8x
  ",
  			i, sg_page(&sg[i]), sg[i].offset, sg[i].length);
5bf2b1932   Stefani Seibold   kfifo: add exampl...
120

a25effa4d   Andrea Righi   kfifo: add explic...
121
122
123
  		if (sg_is_last(&sg[i]))
  			break;
  	}
5bf2b1932   Stefani Seibold   kfifo: add exampl...
124

a25effa4d   Andrea Righi   kfifo: add explic...
125
126
  	/* put here your code to setup and exectute the dma operation */
  	/* ... */
5bf2b1932   Stefani Seibold   kfifo: add exampl...
127

a25effa4d   Andrea Righi   kfifo: add explic...
128
129
  	/* example: 5 bytes transmitted */
  	ret = 5;
5bf2b1932   Stefani Seibold   kfifo: add exampl...
130

a25effa4d   Andrea Righi   kfifo: add explic...
131
132
  	/* finish the dma operation and update the transmitted data */
  	kfifo_dma_out_finish(&fifo, ret);
5bf2b1932   Stefani Seibold   kfifo: add exampl...
133

a25effa4d   Andrea Righi   kfifo: add explic...
134
  	ret = kfifo_len(&fifo);
5bf2b1932   Stefani Seibold   kfifo: add exampl...
135
136
  	printk(KERN_INFO "queue len: %u
  ", kfifo_len(&fifo));
a25effa4d   Andrea Righi   kfifo: add explic...
137
138
139
140
141
142
  	if (ret != 7) {
  		printk(KERN_WARNING "size mismatch: test failed");
  		return -EIO;
  	}
  	printk(KERN_INFO "test passed
  ");
5bf2b1932   Stefani Seibold   kfifo: add exampl...
143
144
145
146
147
  	return 0;
  }
  
  static void __exit example_exit(void)
  {
d83a71c42   Andrea Righi   kfifo: fix a memo...
148
  	kfifo_free(&fifo);
5bf2b1932   Stefani Seibold   kfifo: add exampl...
149
150
151
152
153
154
  }
  
  module_init(example_init);
  module_exit(example_exit);
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>");