diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/dma/virt-dma.h | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/dma/virt-dma.h b/drivers/dma/virt-dma.h index 2edb05505102..b09b75ab0751 100644 --- a/drivers/dma/virt-dma.h +++ b/drivers/dma/virt-dma.h | |||
@@ -35,6 +35,7 @@ struct virt_dma_chan { | |||
35 | struct list_head desc_completed; | 35 | struct list_head desc_completed; |
36 | 36 | ||
37 | struct virt_dma_desc *cyclic; | 37 | struct virt_dma_desc *cyclic; |
38 | struct virt_dma_desc *vd_terminated; | ||
38 | }; | 39 | }; |
39 | 40 | ||
40 | static inline struct virt_dma_chan *to_virt_chan(struct dma_chan *chan) | 41 | static inline struct virt_dma_chan *to_virt_chan(struct dma_chan *chan) |
@@ -130,6 +131,25 @@ static inline void vchan_cyclic_callback(struct virt_dma_desc *vd) | |||
130 | } | 131 | } |
131 | 132 | ||
132 | /** | 133 | /** |
134 | * vchan_terminate_vdesc - Disable pending cyclic callback | ||
135 | * @vd: virtual descriptor to be terminated | ||
136 | * | ||
137 | * vc.lock must be held by caller | ||
138 | */ | ||
139 | static inline void vchan_terminate_vdesc(struct virt_dma_desc *vd) | ||
140 | { | ||
141 | struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); | ||
142 | |||
143 | /* free up stuck descriptor */ | ||
144 | if (vc->vd_terminated) | ||
145 | vchan_vdesc_fini(vc->vd_terminated); | ||
146 | |||
147 | vc->vd_terminated = vd; | ||
148 | if (vc->cyclic == vd) | ||
149 | vc->cyclic = NULL; | ||
150 | } | ||
151 | |||
152 | /** | ||
133 | * vchan_next_desc - peek at the next descriptor to be processed | 153 | * vchan_next_desc - peek at the next descriptor to be processed |
134 | * @vc: virtual channel to obtain descriptor from | 154 | * @vc: virtual channel to obtain descriptor from |
135 | * | 155 | * |
@@ -182,10 +202,20 @@ static inline void vchan_free_chan_resources(struct virt_dma_chan *vc) | |||
182 | * Makes sure that all scheduled or active callbacks have finished running. For | 202 | * Makes sure that all scheduled or active callbacks have finished running. For |
183 | * proper operation the caller has to ensure that no new callbacks are scheduled | 203 | * proper operation the caller has to ensure that no new callbacks are scheduled |
184 | * after the invocation of this function started. | 204 | * after the invocation of this function started. |
205 | * Free up the terminated cyclic descriptor to prevent memory leakage. | ||
185 | */ | 206 | */ |
186 | static inline void vchan_synchronize(struct virt_dma_chan *vc) | 207 | static inline void vchan_synchronize(struct virt_dma_chan *vc) |
187 | { | 208 | { |
209 | unsigned long flags; | ||
210 | |||
188 | tasklet_kill(&vc->task); | 211 | tasklet_kill(&vc->task); |
212 | |||
213 | spin_lock_irqsave(&vc->lock, flags); | ||
214 | if (vc->vd_terminated) { | ||
215 | vchan_vdesc_fini(vc->vd_terminated); | ||
216 | vc->vd_terminated = NULL; | ||
217 | } | ||
218 | spin_unlock_irqrestore(&vc->lock, flags); | ||
189 | } | 219 | } |
190 | 220 | ||
191 | #endif | 221 | #endif |