Merge remote-tracking branch 'regulator/fix/doc' into tmp
[deliverable/linux.git] / drivers / staging / fwserial / dma_fifo.h
CommitLineData
e5711071
PH
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 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#ifndef _DMA_FIFO_H_
22#define _DMA_FIFO_H_
23
24/**
25 * The design basis for the DMA FIFO is to provide an output side that
26 * complies with the streaming DMA API design that can be DMA'd from directly
27 * (without additional copying), coupled with an input side that maintains a
28 * logically consistent 'apparent' size (ie, bytes in + bytes avail is static
29 * for the lifetime of the FIFO).
30 *
31 * DMA output transactions originate on a cache line boundary and can be
32 * variably-sized. DMA output transactions can be retired out-of-order but
33 * the FIFO will only advance the output in the original input sequence.
34 * This means the FIFO will eventually stall if a transaction is never retired.
35 *
36 * Chunking the output side into cache line multiples means that some FIFO
37 * memory is unused. For example, if all the avail input has been pended out,
38 * then the in and out markers are re-aligned to the next cache line.
39 * The maximum possible waste is
40 * (cache line alignment - 1) * (max outstanding dma transactions)
41 * This potential waste requires additional hidden capacity within the FIFO
42 * to be able to accept input while the 'apparent' size has not been reached.
43 *
44 * Additional cache lines (ie, guard area) are used to minimize DMA
45 * fragmentation when wrapping at the end of the FIFO. Input is allowed into the
46 * guard area, but the in and out FIFO markers are wrapped when DMA is pended.
47 */
48
49#define DMA_FIFO_GUARD 3 /* # of cache lines to reserve for the guard area */
50
51struct dma_fifo {
52 unsigned in;
53 unsigned out; /* updated when dma is pended */
54 unsigned done; /* updated upon dma completion */
55 struct {
56 unsigned corrupt:1;
57 };
58 int size; /* 'apparent' size of fifo */
59 int guard; /* ofs of guard area */
60 int capacity; /* size + reserved */
61 int avail; /* # of unused bytes in fifo */
62 unsigned align; /* must be power of 2 */
63 int tx_limit; /* max # of bytes per dma transaction */
64 int open_limit; /* max # of outstanding allowed */
65 int open; /* # of outstanding dma transactions */
66 struct list_head pending; /* fifo markers for outstanding dma */
67 void *data;
68};
69
70struct dma_pending {
71 struct list_head link;
72 void *data;
73 unsigned len;
74 unsigned next;
75 unsigned out;
76};
77
78static inline void dp_mark_completed(struct dma_pending *dp)
79{
80 dp->data += 1;
81}
82
83static inline bool dp_is_completed(struct dma_pending *dp)
84{
85 return (unsigned long)dp->data & 1UL;
86}
87
88extern void dma_fifo_init(struct dma_fifo *fifo);
89extern int dma_fifo_alloc(struct dma_fifo *fifo, int size, unsigned align,
90 int tx_limit, int open_limit, gfp_t gfp_mask);
91extern void dma_fifo_free(struct dma_fifo *fifo);
92extern void dma_fifo_reset(struct dma_fifo *fifo);
93extern int dma_fifo_in(struct dma_fifo *fifo, const void *src, int n);
94extern int dma_fifo_out_pend(struct dma_fifo *fifo, struct dma_pending *pended);
95extern int dma_fifo_out_complete(struct dma_fifo *fifo,
96 struct dma_pending *complete);
97
98/* returns the # of used bytes in the fifo */
99static inline int dma_fifo_level(struct dma_fifo *fifo)
100{
101 return fifo->size - fifo->avail;
102}
103
104/* returns the # of bytes ready for output in the fifo */
105static inline int dma_fifo_out_level(struct dma_fifo *fifo)
106{
107 return fifo->in - fifo->out;
108}
109
110/* returns the # of unused bytes in the fifo */
111static inline int dma_fifo_avail(struct dma_fifo *fifo)
112{
113 return fifo->avail;
114}
115
116/* returns true if fifo has max # of outstanding dmas */
117static inline bool dma_fifo_busy(struct dma_fifo *fifo)
118{
119 return fifo->open == fifo->open_limit;
120}
121
122/* changes the max size of dma returned from dma_fifo_out_pend() */
123static inline int dma_fifo_change_tx_limit(struct dma_fifo *fifo, int tx_limit)
124{
125 tx_limit = round_down(tx_limit, fifo->align);
126 fifo->tx_limit = max_t(int, tx_limit, fifo->align);
127 return 0;
128}
129
130#endif /* _DMA_FIFO_H_ */
This page took 0.061043 seconds and 5 git commands to generate.