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