Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Sample fifo dma implementation
0004  *
0005  * Copyright (C) 2010 Stefani Seibold <stefani@seibold.net>
0006  */
0007 
0008 #include <linux/init.h>
0009 #include <linux/module.h>
0010 #include <linux/kfifo.h>
0011 
0012 /*
0013  * This module shows how to handle fifo dma operations.
0014  */
0015 
0016 /* fifo size in elements (bytes) */
0017 #define FIFO_SIZE   32
0018 
0019 static struct kfifo fifo;
0020 
0021 static int __init example_init(void)
0022 {
0023     int         i;
0024     unsigned int        ret;
0025     unsigned int        nents;
0026     struct scatterlist  sg[10];
0027 
0028     printk(KERN_INFO "DMA fifo test start\n");
0029 
0030     if (kfifo_alloc(&fifo, FIFO_SIZE, GFP_KERNEL)) {
0031         printk(KERN_WARNING "error kfifo_alloc\n");
0032         return -ENOMEM;
0033     }
0034 
0035     printk(KERN_INFO "queue size: %u\n", kfifo_size(&fifo));
0036 
0037     kfifo_in(&fifo, "test", 4);
0038 
0039     for (i = 0; i != 9; i++)
0040         kfifo_put(&fifo, i);
0041 
0042     /* kick away first byte */
0043     kfifo_skip(&fifo);
0044 
0045     printk(KERN_INFO "queue len: %u\n", kfifo_len(&fifo));
0046 
0047     /*
0048      * Configure the kfifo buffer to receive data from DMA input.
0049      *
0050      *  .--------------------------------------.
0051      *  | 0 | 1 | 2 | ... | 12 | 13 | ... | 31 |
0052      *  |---|------------------|---------------|
0053      *   \_/ \________________/ \_____________/
0054      *    \          \                  \
0055      *     \          \_allocated data   \
0056      *      \_*free space*                \_*free space*
0057      *
0058      * We need two different SG entries: one for the free space area at the
0059      * end of the kfifo buffer (19 bytes) and another for the first free
0060      * byte at the beginning, after the kfifo_skip().
0061      */
0062     sg_init_table(sg, ARRAY_SIZE(sg));
0063     nents = kfifo_dma_in_prepare(&fifo, sg, ARRAY_SIZE(sg), FIFO_SIZE);
0064     printk(KERN_INFO "DMA sgl entries: %d\n", nents);
0065     if (!nents) {
0066         /* fifo is full and no sgl was created */
0067         printk(KERN_WARNING "error kfifo_dma_in_prepare\n");
0068         return -EIO;
0069     }
0070 
0071     /* receive data */
0072     printk(KERN_INFO "scatterlist for receive:\n");
0073     for (i = 0; i < nents; i++) {
0074         printk(KERN_INFO
0075         "sg[%d] -> "
0076         "page %p offset 0x%.8x length 0x%.8x\n",
0077             i, sg_page(&sg[i]), sg[i].offset, sg[i].length);
0078 
0079         if (sg_is_last(&sg[i]))
0080             break;
0081     }
0082 
0083     /* put here your code to setup and exectute the dma operation */
0084     /* ... */
0085 
0086     /* example: zero bytes received */
0087     ret = 0;
0088 
0089     /* finish the dma operation and update the received data */
0090     kfifo_dma_in_finish(&fifo, ret);
0091 
0092     /* Prepare to transmit data, example: 8 bytes */
0093     nents = kfifo_dma_out_prepare(&fifo, sg, ARRAY_SIZE(sg), 8);
0094     printk(KERN_INFO "DMA sgl entries: %d\n", nents);
0095     if (!nents) {
0096         /* no data was available and no sgl was created */
0097         printk(KERN_WARNING "error kfifo_dma_out_prepare\n");
0098         return -EIO;
0099     }
0100 
0101     printk(KERN_INFO "scatterlist for transmit:\n");
0102     for (i = 0; i < nents; i++) {
0103         printk(KERN_INFO
0104         "sg[%d] -> "
0105         "page %p offset 0x%.8x length 0x%.8x\n",
0106             i, sg_page(&sg[i]), sg[i].offset, sg[i].length);
0107 
0108         if (sg_is_last(&sg[i]))
0109             break;
0110     }
0111 
0112     /* put here your code to setup and exectute the dma operation */
0113     /* ... */
0114 
0115     /* example: 5 bytes transmitted */
0116     ret = 5;
0117 
0118     /* finish the dma operation and update the transmitted data */
0119     kfifo_dma_out_finish(&fifo, ret);
0120 
0121     ret = kfifo_len(&fifo);
0122     printk(KERN_INFO "queue len: %u\n", kfifo_len(&fifo));
0123 
0124     if (ret != 7) {
0125         printk(KERN_WARNING "size mismatch: test failed");
0126         return -EIO;
0127     }
0128     printk(KERN_INFO "test passed\n");
0129 
0130     return 0;
0131 }
0132 
0133 static void __exit example_exit(void)
0134 {
0135     kfifo_free(&fifo);
0136 }
0137 
0138 module_init(example_init);
0139 module_exit(example_exit);
0140 MODULE_LICENSE("GPL");
0141 MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>");