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_fifo.h (4022B)


      1/* SPDX-License-Identifier: GPL-2.0+ */
      2/*
      3 * DMA-able FIFO interface
      4 *
      5 * Copyright (C) 2012 Peter Hurley <peter@hurleysoftware.com>
      6 */
      7
      8#ifndef _DMA_FIFO_H_
      9#define _DMA_FIFO_H_
     10
     11/**
     12 * The design basis for the DMA FIFO is to provide an output side that
     13 * complies with the streaming DMA API design that can be DMA'd from directly
     14 * (without additional copying), coupled with an input side that maintains a
     15 * logically consistent 'apparent' size (ie, bytes in + bytes avail is static
     16 * for the lifetime of the FIFO).
     17 *
     18 * DMA output transactions originate on a cache line boundary and can be
     19 * variably-sized. DMA output transactions can be retired out-of-order but
     20 * the FIFO will only advance the output in the original input sequence.
     21 * This means the FIFO will eventually stall if a transaction is never retired.
     22 *
     23 * Chunking the output side into cache line multiples means that some FIFO
     24 * memory is unused. For example, if all the avail input has been pended out,
     25 * then the in and out markers are re-aligned to the next cache line.
     26 * The maximum possible waste is
     27 *     (cache line alignment - 1) * (max outstanding dma transactions)
     28 * This potential waste requires additional hidden capacity within the FIFO
     29 * to be able to accept input while the 'apparent' size has not been reached.
     30 *
     31 * Additional cache lines (ie, guard area) are used to minimize DMA
     32 * fragmentation when wrapping at the end of the FIFO. Input is allowed into the
     33 * guard area, but the in and out FIFO markers are wrapped when DMA is pended.
     34 */
     35
     36#define DMA_FIFO_GUARD 3   /* # of cache lines to reserve for the guard area */
     37
     38struct dma_fifo {
     39	unsigned int	 in;
     40	unsigned int	 out;		/* updated when dma is pended         */
     41	unsigned int	 done;		/* updated upon dma completion        */
     42	struct {
     43		unsigned corrupt:1;
     44	};
     45	int		 size;		/* 'apparent' size of fifo	      */
     46	int		 guard;		/* ofs of guard area		      */
     47	int		 capacity;	/* size + reserved                    */
     48	int		 avail;		/* # of unused bytes in fifo          */
     49	unsigned int	 align;		/* must be power of 2                 */
     50	int		 tx_limit;	/* max # of bytes per dma transaction */
     51	int		 open_limit;	/* max # of outstanding allowed       */
     52	int		 open;		/* # of outstanding dma transactions  */
     53	struct list_head pending;	/* fifo markers for outstanding dma   */
     54	void		 *data;
     55};
     56
     57struct dma_pending {
     58	struct list_head link;
     59	void		 *data;
     60	unsigned int	 len;
     61	unsigned int	 next;
     62	unsigned int	 out;
     63};
     64
     65static inline void dp_mark_completed(struct dma_pending *dp)
     66{
     67	dp->data += 1;
     68}
     69
     70static inline bool dp_is_completed(struct dma_pending *dp)
     71{
     72	return (unsigned long)dp->data & 1UL;
     73}
     74
     75void dma_fifo_init(struct dma_fifo *fifo);
     76int dma_fifo_alloc(struct dma_fifo *fifo, int size, unsigned int align,
     77		   int tx_limit, int open_limit, gfp_t gfp_mask);
     78void dma_fifo_free(struct dma_fifo *fifo);
     79void dma_fifo_reset(struct dma_fifo *fifo);
     80int dma_fifo_in(struct dma_fifo *fifo, const void *src, int n);
     81int dma_fifo_out_pend(struct dma_fifo *fifo, struct dma_pending *pended);
     82int dma_fifo_out_complete(struct dma_fifo *fifo,
     83			  struct dma_pending *complete);
     84
     85/* returns the # of used bytes in the fifo */
     86static inline int dma_fifo_level(struct dma_fifo *fifo)
     87{
     88	return fifo->size - fifo->avail;
     89}
     90
     91/* returns the # of bytes ready for output in the fifo */
     92static inline int dma_fifo_out_level(struct dma_fifo *fifo)
     93{
     94	return fifo->in - fifo->out;
     95}
     96
     97/* returns the # of unused bytes in the fifo */
     98static inline int dma_fifo_avail(struct dma_fifo *fifo)
     99{
    100	return fifo->avail;
    101}
    102
    103/* returns true if fifo has max # of outstanding dmas */
    104static inline bool dma_fifo_busy(struct dma_fifo *fifo)
    105{
    106	return fifo->open == fifo->open_limit;
    107}
    108
    109/* changes the max size of dma returned from dma_fifo_out_pend() */
    110static inline int dma_fifo_change_tx_limit(struct dma_fifo *fifo, int tx_limit)
    111{
    112	tx_limit = round_down(tx_limit, fifo->align);
    113	fifo->tx_limit = max_t(int, tx_limit, fifo->align);
    114	return 0;
    115}
    116
    117#endif /* _DMA_FIFO_H_ */