]>
git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/staging/fwserial/dma_fifo.h
2 * DMA-able FIFO interface
4 * Copyright (C) 2012 Peter Hurley <peter@hurleysoftware.com>
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.
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.
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).
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.
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.
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.
45 #define DMA_FIFO_GUARD 3 /* # of cache lines to reserve for the guard area */
49 unsigned out
; /* updated when dma is pended */
50 unsigned done
; /* updated upon dma completion */
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 */
67 struct list_head link
;
74 static inline void dp_mark_completed(struct dma_pending
*dp
)
79 static inline bool dp_is_completed(struct dma_pending
*dp
)
81 return (unsigned long)dp
->data
& 1UL;
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
);
94 /* returns the # of used bytes in the fifo */
95 static inline int dma_fifo_level(struct dma_fifo
*fifo
)
97 return fifo
->size
- fifo
->avail
;
100 /* returns the # of bytes ready for output in the fifo */
101 static inline int dma_fifo_out_level(struct dma_fifo
*fifo
)
103 return fifo
->in
- fifo
->out
;
106 /* returns the # of unused bytes in the fifo */
107 static inline int dma_fifo_avail(struct dma_fifo
*fifo
)
112 /* returns true if fifo has max # of outstanding dmas */
113 static inline bool dma_fifo_busy(struct dma_fifo
*fifo
)
115 return fifo
->open
== fifo
->open_limit
;
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
)
121 tx_limit
= round_down(tx_limit
, fifo
->align
);
122 fifo
->tx_limit
= max_t(int, tx_limit
, fifo
->align
);
126 #endif /* _DMA_FIFO_H_ */