aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/virt-dma.h
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2012-04-13 07:07:23 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2012-07-01 09:15:21 -0400
commit50437bff7f7374f86837986f66e15e73a364f894 (patch)
tree60f2ed3601d374dcc1bf074265e5ab891a3dee55 /drivers/dma/virt-dma.h
parent6887a4131da3adaab011613776d865f4bcfb5678 (diff)
dmaengine: split out virtual channel DMA support from sa11x0 driver
Split the virtual slave channel DMA support from the sa11x0 driver so this code can be shared with other slave DMA engine drivers. Acked-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/dma/virt-dma.h')
-rw-r--r--drivers/dma/virt-dma.h138
1 files changed, 138 insertions, 0 deletions
diff --git a/drivers/dma/virt-dma.h b/drivers/dma/virt-dma.h
new file mode 100644
index 000000000000..825bb9623175
--- /dev/null
+++ b/drivers/dma/virt-dma.h
@@ -0,0 +1,138 @@
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
18struct virt_dma_desc {
19 struct dma_async_tx_descriptor tx;
20 /* protected by vc.lock */
21 struct list_head node;
22};
23
24struct 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
37static inline struct virt_dma_chan *to_virt_chan(struct dma_chan *chan)
38{
39 return container_of(chan, struct virt_dma_chan, chan);
40}
41
42void vchan_dma_desc_free_list(struct virt_dma_chan *vc, struct list_head *head);
43
44void vchan_init(struct virt_dma_chan *vc, struct dma_device *dmadev);
45
46/**
47 * vchan_tx_prep - prepare a descriptor
48 * vc: virtual channel allocating this descriptor
49 * vd: virtual descriptor to prepare
50 * tx_flags: flags argument passed in to prepare function
51 */
52static inline struct dma_async_tx_descriptor *vchan_tx_prep(struct virt_dma_chan *vc,
53 struct virt_dma_desc *vd, unsigned long tx_flags)
54{
55 extern dma_cookie_t vchan_tx_submit(struct dma_async_tx_descriptor *);
56
57 dma_async_tx_descriptor_init(&vd->tx, &vc->chan);
58 vd->tx.flags = tx_flags;
59 vd->tx.tx_submit = vchan_tx_submit;
60
61 return &vd->tx;
62}
63
64/**
65 * vchan_issue_pending - move submitted descriptors to issued list
66 * vc: virtual channel to update
67 *
68 * vc.lock must be held by caller
69 */
70static inline bool vchan_issue_pending(struct virt_dma_chan *vc)
71{
72 list_splice_tail_init(&vc->desc_submitted, &vc->desc_issued);
73 return !list_empty(&vc->desc_issued);
74}
75
76/**
77 * vchan_cookie_complete - report completion of a descriptor
78 * vd: virtual descriptor to update
79 *
80 * vc.lock must be held by caller
81 */
82static inline void vchan_cookie_complete(struct virt_dma_desc *vd)
83{
84 struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan);
85
86 dma_cookie_complete(&vd->tx);
87 dev_vdbg(vc->chan.device->dev, "txd %p[%x]: marked complete\n",
88 vd, vd->tx.cookie);
89 list_add_tail(&vd->node, &vc->desc_completed);
90
91 tasklet_schedule(&vc->task);
92}
93
94/**
95 * vchan_next_desc - peek at the next descriptor to be processed
96 * vc: virtual channel to obtain descriptor from
97 *
98 * vc.lock must be held by caller
99 */
100static inline struct virt_dma_desc *vchan_next_desc(struct virt_dma_chan *vc)
101{
102 if (list_empty(&vc->desc_issued))
103 return NULL;
104
105 return list_first_entry(&vc->desc_issued, struct virt_dma_desc, node);
106}
107
108/**
109 * vchan_get_all_descriptors - obtain all submitted and issued descriptors
110 * vc: virtual channel to get descriptors from
111 * head: list of descriptors found
112 *
113 * vc.lock must be held by caller
114 *
115 * Removes all submitted and issued descriptors from internal lists, and
116 * provides a list of all descriptors found
117 */
118static inline void vchan_get_all_descriptors(struct virt_dma_chan *vc,
119 struct list_head *head)
120{
121 list_splice_tail_init(&vc->desc_submitted, head);
122 list_splice_tail_init(&vc->desc_issued, head);
123 list_splice_tail_init(&vc->desc_completed, head);
124}
125
126static inline void vchan_free_chan_resources(struct virt_dma_chan *vc)
127{
128 unsigned long flags;
129 LIST_HEAD(head);
130
131 spin_lock_irqsave(&vc->lock, flags);
132 vchan_get_all_descriptors(vc, &head);
133 spin_unlock_irqrestore(&vc->lock, flags);
134
135 vchan_dma_desc_free_list(vc, &head);
136}
137
138#endif