cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dma-example.c (3468B)


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