Root/
1 | /* |
2 | * Virtual DMA channel support for DMAengine |
3 | * |
4 | * Copyright (C) 2012 Russell King |
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 version 2 as |
8 | * published by the Free Software Foundation. |
9 | */ |
10 | #ifndef VIRT_DMA_H |
11 | #define VIRT_DMA_H |
12 | |
13 | #include <linux/dmaengine.h> |
14 | #include <linux/interrupt.h> |
15 | |
16 | #include "dmaengine.h" |
17 | |
18 | struct virt_dma_desc { |
19 | struct dma_async_tx_descriptor tx; |
20 | /* protected by vc.lock */ |
21 | struct list_head node; |
22 | }; |
23 | |
24 | struct virt_dma_chan { |
25 | struct dma_chan chan; |
26 | struct tasklet_struct task; |
27 | void (*desc_free)(struct virt_dma_desc *); |
28 | |
29 | spinlock_t lock; |
30 | |
31 | /* protected by vc.lock */ |
32 | struct list_head desc_submitted; |
33 | struct list_head desc_issued; |
34 | struct list_head desc_completed; |
35 | |
36 | struct virt_dma_desc *cyclic; |
37 | }; |
38 | |
39 | static inline struct virt_dma_chan *to_virt_chan(struct dma_chan *chan) |
40 | { |
41 | return container_of(chan, struct virt_dma_chan, chan); |
42 | } |
43 | |
44 | void vchan_dma_desc_free_list(struct virt_dma_chan *vc, struct list_head *head); |
45 | void vchan_init(struct virt_dma_chan *vc, struct dma_device *dmadev); |
46 | struct virt_dma_desc *vchan_find_desc(struct virt_dma_chan *, dma_cookie_t); |
47 | |
48 | /** |
49 | * vchan_tx_prep - prepare a descriptor |
50 | * vc: virtual channel allocating this descriptor |
51 | * vd: virtual descriptor to prepare |
52 | * tx_flags: flags argument passed in to prepare function |
53 | */ |
54 | static inline struct dma_async_tx_descriptor *vchan_tx_prep(struct virt_dma_chan *vc, |
55 | struct virt_dma_desc *vd, unsigned long tx_flags) |
56 | { |
57 | extern dma_cookie_t vchan_tx_submit(struct dma_async_tx_descriptor *); |
58 | |
59 | dma_async_tx_descriptor_init(&vd->tx, &vc->chan); |
60 | vd->tx.flags = tx_flags; |
61 | vd->tx.tx_submit = vchan_tx_submit; |
62 | |
63 | return &vd->tx; |
64 | } |
65 | |
66 | /** |
67 | * vchan_issue_pending - move submitted descriptors to issued list |
68 | * vc: virtual channel to update |
69 | * |
70 | * vc.lock must be held by caller |
71 | */ |
72 | static inline bool vchan_issue_pending(struct virt_dma_chan *vc) |
73 | { |
74 | list_splice_tail_init(&vc->desc_submitted, &vc->desc_issued); |
75 | return !list_empty(&vc->desc_issued); |
76 | } |
77 | |
78 | /** |
79 | * vchan_cookie_complete - report completion of a descriptor |
80 | * vd: virtual descriptor to update |
81 | * |
82 | * vc.lock must be held by caller |
83 | */ |
84 | static inline void vchan_cookie_complete(struct virt_dma_desc *vd) |
85 | { |
86 | struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); |
87 | |
88 | dma_cookie_complete(&vd->tx); |
89 | dev_vdbg(vc->chan.device->dev, "txd %p[%x]: marked complete\n", |
90 | vd, vd->tx.cookie); |
91 | list_add_tail(&vd->node, &vc->desc_completed); |
92 | |
93 | tasklet_schedule(&vc->task); |
94 | } |
95 | |
96 | /** |
97 | * vchan_cyclic_callback - report the completion of a period |
98 | * vd: virtual descriptor |
99 | */ |
100 | static inline void vchan_cyclic_callback(struct virt_dma_desc *vd) |
101 | { |
102 | struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); |
103 | |
104 | vc->cyclic = vd; |
105 | tasklet_schedule(&vc->task); |
106 | } |
107 | |
108 | /** |
109 | * vchan_next_desc - peek at the next descriptor to be processed |
110 | * vc: virtual channel to obtain descriptor from |
111 | * |
112 | * vc.lock must be held by caller |
113 | */ |
114 | static inline struct virt_dma_desc *vchan_next_desc(struct virt_dma_chan *vc) |
115 | { |
116 | if (list_empty(&vc->desc_issued)) |
117 | return NULL; |
118 | |
119 | return list_first_entry(&vc->desc_issued, struct virt_dma_desc, node); |
120 | } |
121 | |
122 | /** |
123 | * vchan_get_all_descriptors - obtain all submitted and issued descriptors |
124 | * vc: virtual channel to get descriptors from |
125 | * head: list of descriptors found |
126 | * |
127 | * vc.lock must be held by caller |
128 | * |
129 | * Removes all submitted and issued descriptors from internal lists, and |
130 | * provides a list of all descriptors found |
131 | */ |
132 | static inline void vchan_get_all_descriptors(struct virt_dma_chan *vc, |
133 | struct list_head *head) |
134 | { |
135 | list_splice_tail_init(&vc->desc_submitted, head); |
136 | list_splice_tail_init(&vc->desc_issued, head); |
137 | list_splice_tail_init(&vc->desc_completed, head); |
138 | } |
139 | |
140 | static inline void vchan_free_chan_resources(struct virt_dma_chan *vc) |
141 | { |
142 | unsigned long flags; |
143 | LIST_HEAD(head); |
144 | |
145 | spin_lock_irqsave(&vc->lock, flags); |
146 | vchan_get_all_descriptors(vc, &head); |
147 | spin_unlock_irqrestore(&vc->lock, flags); |
148 | |
149 | vchan_dma_desc_free_list(vc, &head); |
150 | } |
151 | |
152 | #endif |
153 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9