Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
virt-dma.h
Go to the documentation of this file.
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 {
20  /* protected by vc.lock */
21  struct list_head node;
22 };
23 
24 struct virt_dma_chan {
25  struct dma_chan chan;
28 
30 
31  /* protected by vc.lock */
35 
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 
45 void vchan_init(struct virt_dma_chan *vc, struct dma_device *dmadev);
47 
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 {
58 
60  vd->tx.flags = tx_flags;
61  vd->tx.tx_submit = vchan_tx_submit;
62 
63  return &vd->tx;
64 }
65 
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 
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 
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 
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 
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 
150 }
151 
152 #endif