diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-09 14:52:14 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-09 14:52:14 -0500 |
commit | d9e8a3a5b8298a3c814ed37ac5756e6f67b6be41 (patch) | |
tree | ffa1cf8b367b3f32155f6336d7b86b781a368019 | |
parent | 2150edc6c5cf00f7adb54538b9ea2a3e9cedca3f (diff) | |
parent | b9bdcbba010c2e49c8f837ea7a49fe006b636f41 (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/async_tx
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/async_tx: (22 commits)
ioat: fix self test for multi-channel case
dmaengine: bump initcall level to arch_initcall
dmaengine: advertise all channels on a device to dma_filter_fn
dmaengine: use idr for registering dma device numbers
dmaengine: add a release for dma class devices and dependent infrastructure
ioat: do not perform removal actions at shutdown
iop-adma: enable module removal
iop-adma: kill debug BUG_ON
iop-adma: let devm do its job, don't duplicate free
dmaengine: kill enum dma_state_client
dmaengine: remove 'bigref' infrastructure
dmaengine: kill struct dma_client and supporting infrastructure
dmaengine: replace dma_async_client_register with dmaengine_get
atmel-mci: convert to dma_request_channel and down-level dma_slave
dmatest: convert to dma_request_channel
dmaengine: introduce dma_request_channel and private channels
net_dma: convert to dma_find_channel
dmaengine: provide a common 'issue_pending_all' implementation
dmaengine: centralize channel allocation, introduce dma_find_channel
dmaengine: up-level reference counting to the module level
...
-rw-r--r-- | Documentation/crypto/async-tx-api.txt | 96 | ||||
-rw-r--r-- | Documentation/dmaengine.txt | 1 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/at32ap700x.c | 15 | ||||
-rw-r--r-- | crypto/async_tx/async_tx.c | 350 | ||||
-rw-r--r-- | drivers/dca/dca-core.c | 2 | ||||
-rw-r--r-- | drivers/dma/Kconfig | 2 | ||||
-rw-r--r-- | drivers/dma/dmaengine.c | 778 | ||||
-rw-r--r-- | drivers/dma/dmatest.c | 129 | ||||
-rw-r--r-- | drivers/dma/dw_dmac.c | 119 | ||||
-rw-r--r-- | drivers/dma/fsldma.c | 5 | ||||
-rw-r--r-- | drivers/dma/ioat.c | 92 | ||||
-rw-r--r-- | drivers/dma/ioat_dma.c | 18 | ||||
-rw-r--r-- | drivers/dma/iop-adma.c | 30 | ||||
-rw-r--r-- | drivers/dma/mv_xor.c | 11 | ||||
-rw-r--r-- | drivers/mmc/host/atmel-mci.c | 103 | ||||
-rw-r--r-- | include/linux/async_tx.h | 17 | ||||
-rw-r--r-- | include/linux/atmel-mci.h | 6 | ||||
-rw-r--r-- | include/linux/dmaengine.h | 181 | ||||
-rw-r--r-- | include/linux/dw_dmac.h | 31 | ||||
-rw-r--r-- | include/linux/netdevice.h | 3 | ||||
-rw-r--r-- | include/net/netdma.h | 11 | ||||
-rw-r--r-- | net/core/dev.c | 149 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 5 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 2 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 2 |
26 files changed, 900 insertions, 1260 deletions
diff --git a/Documentation/crypto/async-tx-api.txt b/Documentation/crypto/async-tx-api.txt index c1e9545c59bd..9f59fcbf5d82 100644 --- a/Documentation/crypto/async-tx-api.txt +++ b/Documentation/crypto/async-tx-api.txt | |||
@@ -13,9 +13,9 @@ | |||
13 | 3.6 Constraints | 13 | 3.6 Constraints |
14 | 3.7 Example | 14 | 3.7 Example |
15 | 15 | ||
16 | 4 DRIVER DEVELOPER NOTES | 16 | 4 DMAENGINE DRIVER DEVELOPER NOTES |
17 | 4.1 Conformance points | 17 | 4.1 Conformance points |
18 | 4.2 "My application needs finer control of hardware channels" | 18 | 4.2 "My application needs exclusive control of hardware channels" |
19 | 19 | ||
20 | 5 SOURCE | 20 | 5 SOURCE |
21 | 21 | ||
@@ -150,6 +150,7 @@ ops_run_* and ops_complete_* routines in drivers/md/raid5.c for more | |||
150 | implementation examples. | 150 | implementation examples. |
151 | 151 | ||
152 | 4 DRIVER DEVELOPMENT NOTES | 152 | 4 DRIVER DEVELOPMENT NOTES |
153 | |||
153 | 4.1 Conformance points: | 154 | 4.1 Conformance points: |
154 | There are a few conformance points required in dmaengine drivers to | 155 | There are a few conformance points required in dmaengine drivers to |
155 | accommodate assumptions made by applications using the async_tx API: | 156 | accommodate assumptions made by applications using the async_tx API: |
@@ -158,58 +159,49 @@ accommodate assumptions made by applications using the async_tx API: | |||
158 | 3/ Use async_tx_run_dependencies() in the descriptor clean up path to | 159 | 3/ Use async_tx_run_dependencies() in the descriptor clean up path to |
159 | handle submission of dependent operations | 160 | handle submission of dependent operations |
160 | 161 | ||
161 | 4.2 "My application needs finer control of hardware channels" | 162 | 4.2 "My application needs exclusive control of hardware channels" |
162 | This requirement seems to arise from cases where a DMA engine driver is | 163 | Primarily this requirement arises from cases where a DMA engine driver |
163 | trying to support device-to-memory DMA. The dmaengine and async_tx | 164 | is being used to support device-to-memory operations. A channel that is |
164 | implementations were designed for offloading memory-to-memory | 165 | performing these operations cannot, for many platform specific reasons, |
165 | operations; however, there are some capabilities of the dmaengine layer | 166 | be shared. For these cases the dma_request_channel() interface is |
166 | that can be used for platform-specific channel management. | 167 | provided. |
167 | Platform-specific constraints can be handled by registering the | 168 | |
168 | application as a 'dma_client' and implementing a 'dma_event_callback' to | 169 | The interface is: |
169 | apply a filter to the available channels in the system. Before showing | 170 | struct dma_chan *dma_request_channel(dma_cap_mask_t mask, |
170 | how to implement a custom dma_event callback some background of | 171 | dma_filter_fn filter_fn, |
171 | dmaengine's client support is required. | 172 | void *filter_param); |
172 | 173 | ||
173 | The following routines in dmaengine support multiple clients requesting | 174 | Where dma_filter_fn is defined as: |
174 | use of a channel: | 175 | typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param); |
175 | - dma_async_client_register(struct dma_client *client) | 176 | |
176 | - dma_async_client_chan_request(struct dma_client *client) | 177 | When the optional 'filter_fn' parameter is set to NULL |
177 | 178 | dma_request_channel simply returns the first channel that satisfies the | |
178 | dma_async_client_register takes a pointer to an initialized dma_client | 179 | capability mask. Otherwise, when the mask parameter is insufficient for |
179 | structure. It expects that the 'event_callback' and 'cap_mask' fields | 180 | specifying the necessary channel, the filter_fn routine can be used to |
180 | are already initialized. | 181 | disposition the available channels in the system. The filter_fn routine |
181 | 182 | is called once for each free channel in the system. Upon seeing a | |
182 | dma_async_client_chan_request triggers dmaengine to notify the client of | 183 | suitable channel filter_fn returns DMA_ACK which flags that channel to |
183 | all channels that satisfy the capability mask. It is up to the client's | 184 | be the return value from dma_request_channel. A channel allocated via |
184 | event_callback routine to track how many channels the client needs and | 185 | this interface is exclusive to the caller, until dma_release_channel() |
185 | how many it is currently using. The dma_event_callback routine returns a | 186 | is called. |
186 | dma_state_client code to let dmaengine know the status of the | 187 | |
187 | allocation. | 188 | The DMA_PRIVATE capability flag is used to tag dma devices that should |
188 | 189 | not be used by the general-purpose allocator. It can be set at | |
189 | Below is the example of how to extend this functionality for | 190 | initialization time if it is known that a channel will always be |
190 | platform-specific filtering of the available channels beyond the | 191 | private. Alternatively, it is set when dma_request_channel() finds an |
191 | standard capability mask: | 192 | unused "public" channel. |
192 | 193 | ||
193 | static enum dma_state_client | 194 | A couple caveats to note when implementing a driver and consumer: |
194 | my_dma_client_callback(struct dma_client *client, | 195 | 1/ Once a channel has been privately allocated it will no longer be |
195 | struct dma_chan *chan, enum dma_state state) | 196 | considered by the general-purpose allocator even after a call to |
196 | { | 197 | dma_release_channel(). |
197 | struct dma_device *dma_dev; | 198 | 2/ Since capabilities are specified at the device level a dma_device |
198 | struct my_platform_specific_dma *plat_dma_dev; | 199 | with multiple channels will either have all channels public, or all |
199 | 200 | channels private. | |
200 | dma_dev = chan->device; | ||
201 | plat_dma_dev = container_of(dma_dev, | ||
202 | struct my_platform_specific_dma, | ||
203 | dma_dev); | ||
204 | |||
205 | if (!plat_dma_dev->platform_specific_capability) | ||
206 | return DMA_DUP; | ||
207 | |||
208 | . . . | ||
209 | } | ||
210 | 201 | ||
211 | 5 SOURCE | 202 | 5 SOURCE |
212 | include/linux/dmaengine.h: core header file for DMA drivers and clients | 203 | |
204 | include/linux/dmaengine.h: core header file for DMA drivers and api users | ||
213 | drivers/dma/dmaengine.c: offload engine channel management routines | 205 | drivers/dma/dmaengine.c: offload engine channel management routines |
214 | drivers/dma/: location for offload engine drivers | 206 | drivers/dma/: location for offload engine drivers |
215 | include/linux/async_tx.h: core header file for the async_tx api | 207 | include/linux/async_tx.h: core header file for the async_tx api |
diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt new file mode 100644 index 000000000000..0c1c2f63c0a9 --- /dev/null +++ b/Documentation/dmaengine.txt | |||
@@ -0,0 +1 @@ | |||
See Documentation/crypto/async-tx-api.txt | |||
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index ea7bc1e8562b..3fbfd1e32a9e 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c | |||
@@ -1305,7 +1305,7 @@ struct platform_device *__init | |||
1305 | at32_add_device_mci(unsigned int id, struct mci_platform_data *data) | 1305 | at32_add_device_mci(unsigned int id, struct mci_platform_data *data) |
1306 | { | 1306 | { |
1307 | struct platform_device *pdev; | 1307 | struct platform_device *pdev; |
1308 | struct dw_dma_slave *dws; | 1308 | struct dw_dma_slave *dws = &data->dma_slave; |
1309 | u32 pioa_mask; | 1309 | u32 pioa_mask; |
1310 | u32 piob_mask; | 1310 | u32 piob_mask; |
1311 | 1311 | ||
@@ -1324,22 +1324,13 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) | |||
1324 | ARRAY_SIZE(atmel_mci0_resource))) | 1324 | ARRAY_SIZE(atmel_mci0_resource))) |
1325 | goto fail; | 1325 | goto fail; |
1326 | 1326 | ||
1327 | if (data->dma_slave) | 1327 | dws->dma_dev = &dw_dmac0_device.dev; |
1328 | dws = kmemdup(to_dw_dma_slave(data->dma_slave), | 1328 | dws->reg_width = DW_DMA_SLAVE_WIDTH_32BIT; |
1329 | sizeof(struct dw_dma_slave), GFP_KERNEL); | ||
1330 | else | ||
1331 | dws = kzalloc(sizeof(struct dw_dma_slave), GFP_KERNEL); | ||
1332 | |||
1333 | dws->slave.dev = &pdev->dev; | ||
1334 | dws->slave.dma_dev = &dw_dmac0_device.dev; | ||
1335 | dws->slave.reg_width = DMA_SLAVE_WIDTH_32BIT; | ||
1336 | dws->cfg_hi = (DWC_CFGH_SRC_PER(0) | 1329 | dws->cfg_hi = (DWC_CFGH_SRC_PER(0) |
1337 | | DWC_CFGH_DST_PER(1)); | 1330 | | DWC_CFGH_DST_PER(1)); |
1338 | dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | 1331 | dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL |
1339 | | DWC_CFGL_HS_SRC_POL); | 1332 | | DWC_CFGL_HS_SRC_POL); |
1340 | 1333 | ||
1341 | data->dma_slave = &dws->slave; | ||
1342 | |||
1343 | if (platform_device_add_data(pdev, data, | 1334 | if (platform_device_add_data(pdev, data, |
1344 | sizeof(struct mci_platform_data))) | 1335 | sizeof(struct mci_platform_data))) |
1345 | goto fail; | 1336 | goto fail; |
diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c index dcbf1be149f3..f21147f3626a 100644 --- a/crypto/async_tx/async_tx.c +++ b/crypto/async_tx/async_tx.c | |||
@@ -28,351 +28,18 @@ | |||
28 | #include <linux/async_tx.h> | 28 | #include <linux/async_tx.h> |
29 | 29 | ||
30 | #ifdef CONFIG_DMA_ENGINE | 30 | #ifdef CONFIG_DMA_ENGINE |
31 | static enum dma_state_client | 31 | static int __init async_tx_init(void) |
32 | dma_channel_add_remove(struct dma_client *client, | ||
33 | struct dma_chan *chan, enum dma_state state); | ||
34 | |||
35 | static struct dma_client async_tx_dma = { | ||
36 | .event_callback = dma_channel_add_remove, | ||
37 | /* .cap_mask == 0 defaults to all channels */ | ||
38 | }; | ||
39 | |||
40 | /** | ||
41 | * dma_cap_mask_all - enable iteration over all operation types | ||
42 | */ | ||
43 | static dma_cap_mask_t dma_cap_mask_all; | ||
44 | |||
45 | /** | ||
46 | * chan_ref_percpu - tracks channel allocations per core/opertion | ||
47 | */ | ||
48 | struct chan_ref_percpu { | ||
49 | struct dma_chan_ref *ref; | ||
50 | }; | ||
51 | |||
52 | static int channel_table_initialized; | ||
53 | static struct chan_ref_percpu *channel_table[DMA_TX_TYPE_END]; | ||
54 | |||
55 | /** | ||
56 | * async_tx_lock - protect modification of async_tx_master_list and serialize | ||
57 | * rebalance operations | ||
58 | */ | ||
59 | static spinlock_t async_tx_lock; | ||
60 | |||
61 | static LIST_HEAD(async_tx_master_list); | ||
62 | |||
63 | /* async_tx_issue_pending_all - start all transactions on all channels */ | ||
64 | void async_tx_issue_pending_all(void) | ||
65 | { | ||
66 | struct dma_chan_ref *ref; | ||
67 | |||
68 | rcu_read_lock(); | ||
69 | list_for_each_entry_rcu(ref, &async_tx_master_list, node) | ||
70 | ref->chan->device->device_issue_pending(ref->chan); | ||
71 | rcu_read_unlock(); | ||
72 | } | ||
73 | EXPORT_SYMBOL_GPL(async_tx_issue_pending_all); | ||
74 | |||
75 | /* dma_wait_for_async_tx - spin wait for a transcation to complete | ||
76 | * @tx: transaction to wait on | ||
77 | */ | ||
78 | enum dma_status | ||
79 | dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) | ||
80 | { | ||
81 | enum dma_status status; | ||
82 | struct dma_async_tx_descriptor *iter; | ||
83 | struct dma_async_tx_descriptor *parent; | ||
84 | |||
85 | if (!tx) | ||
86 | return DMA_SUCCESS; | ||
87 | |||
88 | /* poll through the dependency chain, return when tx is complete */ | ||
89 | do { | ||
90 | iter = tx; | ||
91 | |||
92 | /* find the root of the unsubmitted dependency chain */ | ||
93 | do { | ||
94 | parent = iter->parent; | ||
95 | if (!parent) | ||
96 | break; | ||
97 | else | ||
98 | iter = parent; | ||
99 | } while (parent); | ||
100 | |||
101 | /* there is a small window for ->parent == NULL and | ||
102 | * ->cookie == -EBUSY | ||
103 | */ | ||
104 | while (iter->cookie == -EBUSY) | ||
105 | cpu_relax(); | ||
106 | |||
107 | status = dma_sync_wait(iter->chan, iter->cookie); | ||
108 | } while (status == DMA_IN_PROGRESS || (iter != tx)); | ||
109 | |||
110 | return status; | ||
111 | } | ||
112 | EXPORT_SYMBOL_GPL(dma_wait_for_async_tx); | ||
113 | |||
114 | /* async_tx_run_dependencies - helper routine for dma drivers to process | ||
115 | * (start) dependent operations on their target channel | ||
116 | * @tx: transaction with dependencies | ||
117 | */ | ||
118 | void async_tx_run_dependencies(struct dma_async_tx_descriptor *tx) | ||
119 | { | ||
120 | struct dma_async_tx_descriptor *dep = tx->next; | ||
121 | struct dma_async_tx_descriptor *dep_next; | ||
122 | struct dma_chan *chan; | ||
123 | |||
124 | if (!dep) | ||
125 | return; | ||
126 | |||
127 | chan = dep->chan; | ||
128 | |||
129 | /* keep submitting up until a channel switch is detected | ||
130 | * in that case we will be called again as a result of | ||
131 | * processing the interrupt from async_tx_channel_switch | ||
132 | */ | ||
133 | for (; dep; dep = dep_next) { | ||
134 | spin_lock_bh(&dep->lock); | ||
135 | dep->parent = NULL; | ||
136 | dep_next = dep->next; | ||
137 | if (dep_next && dep_next->chan == chan) | ||
138 | dep->next = NULL; /* ->next will be submitted */ | ||
139 | else | ||
140 | dep_next = NULL; /* submit current dep and terminate */ | ||
141 | spin_unlock_bh(&dep->lock); | ||
142 | |||
143 | dep->tx_submit(dep); | ||
144 | } | ||
145 | |||
146 | chan->device->device_issue_pending(chan); | ||
147 | } | ||
148 | EXPORT_SYMBOL_GPL(async_tx_run_dependencies); | ||
149 | |||
150 | static void | ||
151 | free_dma_chan_ref(struct rcu_head *rcu) | ||
152 | { | ||
153 | struct dma_chan_ref *ref; | ||
154 | ref = container_of(rcu, struct dma_chan_ref, rcu); | ||
155 | kfree(ref); | ||
156 | } | ||
157 | |||
158 | static void | ||
159 | init_dma_chan_ref(struct dma_chan_ref *ref, struct dma_chan *chan) | ||
160 | { | ||
161 | INIT_LIST_HEAD(&ref->node); | ||
162 | INIT_RCU_HEAD(&ref->rcu); | ||
163 | ref->chan = chan; | ||
164 | atomic_set(&ref->count, 0); | ||
165 | } | ||
166 | |||
167 | /** | ||
168 | * get_chan_ref_by_cap - returns the nth channel of the given capability | ||
169 | * defaults to returning the channel with the desired capability and the | ||
170 | * lowest reference count if the index can not be satisfied | ||
171 | * @cap: capability to match | ||
172 | * @index: nth channel desired, passing -1 has the effect of forcing the | ||
173 | * default return value | ||
174 | */ | ||
175 | static struct dma_chan_ref * | ||
176 | get_chan_ref_by_cap(enum dma_transaction_type cap, int index) | ||
177 | { | ||
178 | struct dma_chan_ref *ret_ref = NULL, *min_ref = NULL, *ref; | ||
179 | |||
180 | rcu_read_lock(); | ||
181 | list_for_each_entry_rcu(ref, &async_tx_master_list, node) | ||
182 | if (dma_has_cap(cap, ref->chan->device->cap_mask)) { | ||
183 | if (!min_ref) | ||
184 | min_ref = ref; | ||
185 | else if (atomic_read(&ref->count) < | ||
186 | atomic_read(&min_ref->count)) | ||
187 | min_ref = ref; | ||
188 | |||
189 | if (index-- == 0) { | ||
190 | ret_ref = ref; | ||
191 | break; | ||
192 | } | ||
193 | } | ||
194 | rcu_read_unlock(); | ||
195 | |||
196 | if (!ret_ref) | ||
197 | ret_ref = min_ref; | ||
198 | |||
199 | if (ret_ref) | ||
200 | atomic_inc(&ret_ref->count); | ||
201 | |||
202 | return ret_ref; | ||
203 | } | ||
204 | |||
205 | /** | ||
206 | * async_tx_rebalance - redistribute the available channels, optimize | ||
207 | * for cpu isolation in the SMP case, and opertaion isolation in the | ||
208 | * uniprocessor case | ||
209 | */ | ||
210 | static void async_tx_rebalance(void) | ||
211 | { | ||
212 | int cpu, cap, cpu_idx = 0; | ||
213 | unsigned long flags; | ||
214 | |||
215 | if (!channel_table_initialized) | ||
216 | return; | ||
217 | |||
218 | spin_lock_irqsave(&async_tx_lock, flags); | ||
219 | |||
220 | /* undo the last distribution */ | ||
221 | for_each_dma_cap_mask(cap, dma_cap_mask_all) | ||
222 | for_each_possible_cpu(cpu) { | ||
223 | struct dma_chan_ref *ref = | ||
224 | per_cpu_ptr(channel_table[cap], cpu)->ref; | ||
225 | if (ref) { | ||
226 | atomic_set(&ref->count, 0); | ||
227 | per_cpu_ptr(channel_table[cap], cpu)->ref = | ||
228 | NULL; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | for_each_dma_cap_mask(cap, dma_cap_mask_all) | ||
233 | for_each_online_cpu(cpu) { | ||
234 | struct dma_chan_ref *new; | ||
235 | if (NR_CPUS > 1) | ||
236 | new = get_chan_ref_by_cap(cap, cpu_idx++); | ||
237 | else | ||
238 | new = get_chan_ref_by_cap(cap, -1); | ||
239 | |||
240 | per_cpu_ptr(channel_table[cap], cpu)->ref = new; | ||
241 | } | ||
242 | |||
243 | spin_unlock_irqrestore(&async_tx_lock, flags); | ||
244 | } | ||
245 | |||
246 | static enum dma_state_client | ||
247 | dma_channel_add_remove(struct dma_client *client, | ||
248 | struct dma_chan *chan, enum dma_state state) | ||
249 | { | ||
250 | unsigned long found, flags; | ||
251 | struct dma_chan_ref *master_ref, *ref; | ||
252 | enum dma_state_client ack = DMA_DUP; /* default: take no action */ | ||
253 | |||
254 | switch (state) { | ||
255 | case DMA_RESOURCE_AVAILABLE: | ||
256 | found = 0; | ||
257 | rcu_read_lock(); | ||
258 | list_for_each_entry_rcu(ref, &async_tx_master_list, node) | ||
259 | if (ref->chan == chan) { | ||
260 | found = 1; | ||
261 | break; | ||
262 | } | ||
263 | rcu_read_unlock(); | ||
264 | |||
265 | pr_debug("async_tx: dma resource available [%s]\n", | ||
266 | found ? "old" : "new"); | ||
267 | |||
268 | if (!found) | ||
269 | ack = DMA_ACK; | ||
270 | else | ||
271 | break; | ||
272 | |||
273 | /* add the channel to the generic management list */ | ||
274 | master_ref = kmalloc(sizeof(*master_ref), GFP_KERNEL); | ||
275 | if (master_ref) { | ||
276 | /* keep a reference until async_tx is unloaded */ | ||
277 | dma_chan_get(chan); | ||
278 | init_dma_chan_ref(master_ref, chan); | ||
279 | spin_lock_irqsave(&async_tx_lock, flags); | ||
280 | list_add_tail_rcu(&master_ref->node, | ||
281 | &async_tx_master_list); | ||
282 | spin_unlock_irqrestore(&async_tx_lock, | ||
283 | flags); | ||
284 | } else { | ||
285 | printk(KERN_WARNING "async_tx: unable to create" | ||
286 | " new master entry in response to" | ||
287 | " a DMA_RESOURCE_ADDED event" | ||
288 | " (-ENOMEM)\n"); | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | async_tx_rebalance(); | ||
293 | break; | ||
294 | case DMA_RESOURCE_REMOVED: | ||
295 | found = 0; | ||
296 | spin_lock_irqsave(&async_tx_lock, flags); | ||
297 | list_for_each_entry(ref, &async_tx_master_list, node) | ||
298 | if (ref->chan == chan) { | ||
299 | /* permit backing devices to go away */ | ||
300 | dma_chan_put(ref->chan); | ||
301 | list_del_rcu(&ref->node); | ||
302 | call_rcu(&ref->rcu, free_dma_chan_ref); | ||
303 | found = 1; | ||
304 | break; | ||
305 | } | ||
306 | spin_unlock_irqrestore(&async_tx_lock, flags); | ||
307 | |||
308 | pr_debug("async_tx: dma resource removed [%s]\n", | ||
309 | found ? "ours" : "not ours"); | ||
310 | |||
311 | if (found) | ||
312 | ack = DMA_ACK; | ||
313 | else | ||
314 | break; | ||
315 | |||
316 | async_tx_rebalance(); | ||
317 | break; | ||
318 | case DMA_RESOURCE_SUSPEND: | ||
319 | case DMA_RESOURCE_RESUME: | ||
320 | printk(KERN_WARNING "async_tx: does not support dma channel" | ||
321 | " suspend/resume\n"); | ||
322 | break; | ||
323 | default: | ||
324 | BUG(); | ||
325 | } | ||
326 | |||
327 | return ack; | ||
328 | } | ||
329 | |||
330 | static int __init | ||
331 | async_tx_init(void) | ||
332 | { | 32 | { |
333 | enum dma_transaction_type cap; | 33 | dmaengine_get(); |
334 | |||
335 | spin_lock_init(&async_tx_lock); | ||
336 | bitmap_fill(dma_cap_mask_all.bits, DMA_TX_TYPE_END); | ||
337 | |||
338 | /* an interrupt will never be an explicit operation type. | ||
339 | * clearing this bit prevents allocation to a slot in 'channel_table' | ||
340 | */ | ||
341 | clear_bit(DMA_INTERRUPT, dma_cap_mask_all.bits); | ||
342 | |||
343 | for_each_dma_cap_mask(cap, dma_cap_mask_all) { | ||
344 | channel_table[cap] = alloc_percpu(struct chan_ref_percpu); | ||
345 | if (!channel_table[cap]) | ||
346 | goto err; | ||
347 | } | ||
348 | |||
349 | channel_table_initialized = 1; | ||
350 | dma_async_client_register(&async_tx_dma); | ||
351 | dma_async_client_chan_request(&async_tx_dma); | ||
352 | 34 | ||
353 | printk(KERN_INFO "async_tx: api initialized (async)\n"); | 35 | printk(KERN_INFO "async_tx: api initialized (async)\n"); |
354 | 36 | ||
355 | return 0; | 37 | return 0; |
356 | err: | ||
357 | printk(KERN_ERR "async_tx: initialization failure\n"); | ||
358 | |||
359 | while (--cap >= 0) | ||
360 | free_percpu(channel_table[cap]); | ||
361 | |||
362 | return 1; | ||
363 | } | 38 | } |
364 | 39 | ||
365 | static void __exit async_tx_exit(void) | 40 | static void __exit async_tx_exit(void) |
366 | { | 41 | { |
367 | enum dma_transaction_type cap; | 42 | dmaengine_put(); |
368 | |||
369 | channel_table_initialized = 0; | ||
370 | |||
371 | for_each_dma_cap_mask(cap, dma_cap_mask_all) | ||
372 | if (channel_table[cap]) | ||
373 | free_percpu(channel_table[cap]); | ||
374 | |||
375 | dma_async_client_unregister(&async_tx_dma); | ||
376 | } | 43 | } |
377 | 44 | ||
378 | /** | 45 | /** |
@@ -387,16 +54,9 @@ __async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx, | |||
387 | { | 54 | { |
388 | /* see if we can keep the chain on one channel */ | 55 | /* see if we can keep the chain on one channel */ |
389 | if (depend_tx && | 56 | if (depend_tx && |
390 | dma_has_cap(tx_type, depend_tx->chan->device->cap_mask)) | 57 | dma_has_cap(tx_type, depend_tx->chan->device->cap_mask)) |
391 | return depend_tx->chan; | 58 | return depend_tx->chan; |
392 | else if (likely(channel_table_initialized)) { | 59 | return dma_find_channel(tx_type); |
393 | struct dma_chan_ref *ref; | ||
394 | int cpu = get_cpu(); | ||
395 | ref = per_cpu_ptr(channel_table[tx_type], cpu)->ref; | ||
396 | put_cpu(); | ||
397 | return ref ? ref->chan : NULL; | ||
398 | } else | ||
399 | return NULL; | ||
400 | } | 60 | } |
401 | EXPORT_SYMBOL_GPL(__async_tx_find_channel); | 61 | EXPORT_SYMBOL_GPL(__async_tx_find_channel); |
402 | #else | 62 | #else |
diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c index d883e1b8bb8c..55433849bfa6 100644 --- a/drivers/dca/dca-core.c +++ b/drivers/dca/dca-core.c | |||
@@ -270,6 +270,6 @@ static void __exit dca_exit(void) | |||
270 | dca_sysfs_exit(); | 270 | dca_sysfs_exit(); |
271 | } | 271 | } |
272 | 272 | ||
273 | subsys_initcall(dca_init); | 273 | arch_initcall(dca_init); |
274 | module_exit(dca_exit); | 274 | module_exit(dca_exit); |
275 | 275 | ||
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 904e57558bb5..e34b06420816 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig | |||
@@ -33,7 +33,6 @@ config INTEL_IOATDMA | |||
33 | config INTEL_IOP_ADMA | 33 | config INTEL_IOP_ADMA |
34 | tristate "Intel IOP ADMA support" | 34 | tristate "Intel IOP ADMA support" |
35 | depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX | 35 | depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX |
36 | select ASYNC_CORE | ||
37 | select DMA_ENGINE | 36 | select DMA_ENGINE |
38 | help | 37 | help |
39 | Enable support for the Intel(R) IOP Series RAID engines. | 38 | Enable support for the Intel(R) IOP Series RAID engines. |
@@ -59,7 +58,6 @@ config FSL_DMA | |||
59 | config MV_XOR | 58 | config MV_XOR |
60 | bool "Marvell XOR engine support" | 59 | bool "Marvell XOR engine support" |
61 | depends on PLAT_ORION | 60 | depends on PLAT_ORION |
62 | select ASYNC_CORE | ||
63 | select DMA_ENGINE | 61 | select DMA_ENGINE |
64 | ---help--- | 62 | ---help--- |
65 | Enable support for the Marvell XOR engine. | 63 | Enable support for the Marvell XOR engine. |
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 657996517374..403dbe781122 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c | |||
@@ -31,32 +31,18 @@ | |||
31 | * | 31 | * |
32 | * LOCKING: | 32 | * LOCKING: |
33 | * | 33 | * |
34 | * The subsystem keeps two global lists, dma_device_list and dma_client_list. | 34 | * The subsystem keeps a global list of dma_device structs it is protected by a |
35 | * Both of these are protected by a mutex, dma_list_mutex. | 35 | * mutex, dma_list_mutex. |
36 | * | ||
37 | * A subsystem can get access to a channel by calling dmaengine_get() followed | ||
38 | * by dma_find_channel(), or if it has need for an exclusive channel it can call | ||
39 | * dma_request_channel(). Once a channel is allocated a reference is taken | ||
40 | * against its corresponding driver to disable removal. | ||
36 | * | 41 | * |
37 | * Each device has a channels list, which runs unlocked but is never modified | 42 | * Each device has a channels list, which runs unlocked but is never modified |
38 | * once the device is registered, it's just setup by the driver. | 43 | * once the device is registered, it's just setup by the driver. |
39 | * | 44 | * |
40 | * Each client is responsible for keeping track of the channels it uses. See | 45 | * See Documentation/dmaengine.txt for more details |
41 | * the definition of dma_event_callback in dmaengine.h. | ||
42 | * | ||
43 | * Each device has a kref, which is initialized to 1 when the device is | ||
44 | * registered. A kref_get is done for each device registered. When the | ||
45 | * device is released, the corresponding kref_put is done in the release | ||
46 | * method. Every time one of the device's channels is allocated to a client, | ||
47 | * a kref_get occurs. When the channel is freed, the corresponding kref_put | ||
48 | * happens. The device's release function does a completion, so | ||
49 | * unregister_device does a remove event, device_unregister, a kref_put | ||
50 | * for the first reference, then waits on the completion for all other | ||
51 | * references to finish. | ||
52 | * | ||
53 | * Each channel has an open-coded implementation of Rusty Russell's "bigref," | ||
54 | * with a kref and a per_cpu local_t. A dma_chan_get is called when a client | ||
55 | * signals that it wants to use a channel, and dma_chan_put is called when | ||
56 | * a channel is removed or a client using it is unregistered. A client can | ||
57 | * take extra references per outstanding transaction, as is the case with | ||
58 | * the NET DMA client. The release function does a kref_put on the device. | ||
59 | * -ChrisL, DanW | ||
60 | */ | 46 | */ |
61 | 47 | ||
62 | #include <linux/init.h> | 48 | #include <linux/init.h> |
@@ -70,54 +56,85 @@ | |||
70 | #include <linux/rcupdate.h> | 56 | #include <linux/rcupdate.h> |
71 | #include <linux/mutex.h> | 57 | #include <linux/mutex.h> |
72 | #include <linux/jiffies.h> | 58 | #include <linux/jiffies.h> |
59 | #include <linux/rculist.h> | ||
60 | #include <linux/idr.h> | ||
73 | 61 | ||
74 | static DEFINE_MUTEX(dma_list_mutex); | 62 | static DEFINE_MUTEX(dma_list_mutex); |
75 | static LIST_HEAD(dma_device_list); | 63 | static LIST_HEAD(dma_device_list); |
76 | static LIST_HEAD(dma_client_list); | 64 | static long dmaengine_ref_count; |
65 | static struct idr dma_idr; | ||
77 | 66 | ||
78 | /* --- sysfs implementation --- */ | 67 | /* --- sysfs implementation --- */ |
79 | 68 | ||
69 | /** | ||
70 | * dev_to_dma_chan - convert a device pointer to the its sysfs container object | ||
71 | * @dev - device node | ||
72 | * | ||
73 | * Must be called under dma_list_mutex | ||
74 | */ | ||
75 | static struct dma_chan *dev_to_dma_chan(struct device *dev) | ||
76 | { | ||
77 | struct dma_chan_dev *chan_dev; | ||
78 | |||
79 | chan_dev = container_of(dev, typeof(*chan_dev), device); | ||
80 | return chan_dev->chan; | ||
81 | } | ||
82 | |||
80 | static ssize_t show_memcpy_count(struct device *dev, struct device_attribute *attr, char *buf) | 83 | static ssize_t show_memcpy_count(struct device *dev, struct device_attribute *attr, char *buf) |
81 | { | 84 | { |
82 | struct dma_chan *chan = to_dma_chan(dev); | 85 | struct dma_chan *chan; |
83 | unsigned long count = 0; | 86 | unsigned long count = 0; |
84 | int i; | 87 | int i; |
88 | int err; | ||
85 | 89 | ||
86 | for_each_possible_cpu(i) | 90 | mutex_lock(&dma_list_mutex); |
87 | count += per_cpu_ptr(chan->local, i)->memcpy_count; | 91 | chan = dev_to_dma_chan(dev); |
92 | if (chan) { | ||
93 | for_each_possible_cpu(i) | ||
94 | count += per_cpu_ptr(chan->local, i)->memcpy_count; | ||
95 | err = sprintf(buf, "%lu\n", count); | ||
96 | } else | ||
97 | err = -ENODEV; | ||
98 | mutex_unlock(&dma_list_mutex); | ||
88 | 99 | ||
89 | return sprintf(buf, "%lu\n", count); | 100 | return err; |
90 | } | 101 | } |
91 | 102 | ||
92 | static ssize_t show_bytes_transferred(struct device *dev, struct device_attribute *attr, | 103 | static ssize_t show_bytes_transferred(struct device *dev, struct device_attribute *attr, |
93 | char *buf) | 104 | char *buf) |
94 | { | 105 | { |
95 | struct dma_chan *chan = to_dma_chan(dev); | 106 | struct dma_chan *chan; |
96 | unsigned long count = 0; | 107 | unsigned long count = 0; |
97 | int i; | 108 | int i; |
109 | int err; | ||
98 | 110 | ||
99 | for_each_possible_cpu(i) | 111 | mutex_lock(&dma_list_mutex); |
100 | count += per_cpu_ptr(chan->local, i)->bytes_transferred; | 112 | chan = dev_to_dma_chan(dev); |
113 | if (chan) { | ||
114 | for_each_possible_cpu(i) | ||
115 | count += per_cpu_ptr(chan->local, i)->bytes_transferred; | ||
116 | err = sprintf(buf, "%lu\n", count); | ||
117 | } else | ||
118 | err = -ENODEV; | ||
119 | mutex_unlock(&dma_list_mutex); | ||
101 | 120 | ||
102 | return sprintf(buf, "%lu\n", count); | 121 | return err; |
103 | } | 122 | } |
104 | 123 | ||
105 | static ssize_t show_in_use(struct device *dev, struct device_attribute *attr, char *buf) | 124 | static ssize_t show_in_use(struct device *dev, struct device_attribute *attr, char *buf) |
106 | { | 125 | { |
107 | struct dma_chan *chan = to_dma_chan(dev); | 126 | struct dma_chan *chan; |
108 | int in_use = 0; | 127 | int err; |
109 | |||
110 | if (unlikely(chan->slow_ref) && | ||
111 | atomic_read(&chan->refcount.refcount) > 1) | ||
112 | in_use = 1; | ||
113 | else { | ||
114 | if (local_read(&(per_cpu_ptr(chan->local, | ||
115 | get_cpu())->refcount)) > 0) | ||
116 | in_use = 1; | ||
117 | put_cpu(); | ||
118 | } | ||
119 | 128 | ||
120 | return sprintf(buf, "%d\n", in_use); | 129 | mutex_lock(&dma_list_mutex); |
130 | chan = dev_to_dma_chan(dev); | ||
131 | if (chan) | ||
132 | err = sprintf(buf, "%d\n", chan->client_count); | ||
133 | else | ||
134 | err = -ENODEV; | ||
135 | mutex_unlock(&dma_list_mutex); | ||
136 | |||
137 | return err; | ||
121 | } | 138 | } |
122 | 139 | ||
123 | static struct device_attribute dma_attrs[] = { | 140 | static struct device_attribute dma_attrs[] = { |
@@ -127,76 +144,110 @@ static struct device_attribute dma_attrs[] = { | |||
127 | __ATTR_NULL | 144 | __ATTR_NULL |
128 | }; | 145 | }; |
129 | 146 | ||
130 | static void dma_async_device_cleanup(struct kref *kref); | 147 | static void chan_dev_release(struct device *dev) |
131 | |||
132 | static void dma_dev_release(struct device *dev) | ||
133 | { | 148 | { |
134 | struct dma_chan *chan = to_dma_chan(dev); | 149 | struct dma_chan_dev *chan_dev; |
135 | kref_put(&chan->device->refcount, dma_async_device_cleanup); | 150 | |
151 | chan_dev = container_of(dev, typeof(*chan_dev), device); | ||
152 | if (atomic_dec_and_test(chan_dev->idr_ref)) { | ||
153 | mutex_lock(&dma_list_mutex); | ||
154 | idr_remove(&dma_idr, chan_dev->dev_id); | ||
155 | mutex_unlock(&dma_list_mutex); | ||
156 | kfree(chan_dev->idr_ref); | ||
157 | } | ||
158 | kfree(chan_dev); | ||
136 | } | 159 | } |
137 | 160 | ||
138 | static struct class dma_devclass = { | 161 | static struct class dma_devclass = { |
139 | .name = "dma", | 162 | .name = "dma", |
140 | .dev_attrs = dma_attrs, | 163 | .dev_attrs = dma_attrs, |
141 | .dev_release = dma_dev_release, | 164 | .dev_release = chan_dev_release, |
142 | }; | 165 | }; |
143 | 166 | ||
144 | /* --- client and device registration --- */ | 167 | /* --- client and device registration --- */ |
145 | 168 | ||
146 | #define dma_chan_satisfies_mask(chan, mask) \ | 169 | #define dma_device_satisfies_mask(device, mask) \ |
147 | __dma_chan_satisfies_mask((chan), &(mask)) | 170 | __dma_device_satisfies_mask((device), &(mask)) |
148 | static int | 171 | static int |
149 | __dma_chan_satisfies_mask(struct dma_chan *chan, dma_cap_mask_t *want) | 172 | __dma_device_satisfies_mask(struct dma_device *device, dma_cap_mask_t *want) |
150 | { | 173 | { |
151 | dma_cap_mask_t has; | 174 | dma_cap_mask_t has; |
152 | 175 | ||
153 | bitmap_and(has.bits, want->bits, chan->device->cap_mask.bits, | 176 | bitmap_and(has.bits, want->bits, device->cap_mask.bits, |
154 | DMA_TX_TYPE_END); | 177 | DMA_TX_TYPE_END); |
155 | return bitmap_equal(want->bits, has.bits, DMA_TX_TYPE_END); | 178 | return bitmap_equal(want->bits, has.bits, DMA_TX_TYPE_END); |
156 | } | 179 | } |
157 | 180 | ||
181 | static struct module *dma_chan_to_owner(struct dma_chan *chan) | ||
182 | { | ||
183 | return chan->device->dev->driver->owner; | ||
184 | } | ||
185 | |||
158 | /** | 186 | /** |
159 | * dma_client_chan_alloc - try to allocate channels to a client | 187 | * balance_ref_count - catch up the channel reference count |
160 | * @client: &dma_client | 188 | * @chan - channel to balance ->client_count versus dmaengine_ref_count |
161 | * | 189 | * |
162 | * Called with dma_list_mutex held. | 190 | * balance_ref_count must be called under dma_list_mutex |
163 | */ | 191 | */ |
164 | static void dma_client_chan_alloc(struct dma_client *client) | 192 | static void balance_ref_count(struct dma_chan *chan) |
165 | { | 193 | { |
166 | struct dma_device *device; | 194 | struct module *owner = dma_chan_to_owner(chan); |
167 | struct dma_chan *chan; | ||
168 | int desc; /* allocated descriptor count */ | ||
169 | enum dma_state_client ack; | ||
170 | 195 | ||
171 | /* Find a channel */ | 196 | while (chan->client_count < dmaengine_ref_count) { |
172 | list_for_each_entry(device, &dma_device_list, global_node) { | 197 | __module_get(owner); |
173 | /* Does the client require a specific DMA controller? */ | 198 | chan->client_count++; |
174 | if (client->slave && client->slave->dma_dev | 199 | } |
175 | && client->slave->dma_dev != device->dev) | 200 | } |
176 | continue; | ||
177 | 201 | ||
178 | list_for_each_entry(chan, &device->channels, device_node) { | 202 | /** |
179 | if (!dma_chan_satisfies_mask(chan, client->cap_mask)) | 203 | * dma_chan_get - try to grab a dma channel's parent driver module |
180 | continue; | 204 | * @chan - channel to grab |
205 | * | ||
206 | * Must be called under dma_list_mutex | ||
207 | */ | ||
208 | static int dma_chan_get(struct dma_chan *chan) | ||
209 | { | ||
210 | int err = -ENODEV; | ||
211 | struct module *owner = dma_chan_to_owner(chan); | ||
212 | |||
213 | if (chan->client_count) { | ||
214 | __module_get(owner); | ||
215 | err = 0; | ||
216 | } else if (try_module_get(owner)) | ||
217 | err = 0; | ||
218 | |||
219 | if (err == 0) | ||
220 | chan->client_count++; | ||
221 | |||
222 | /* allocate upon first client reference */ | ||
223 | if (chan->client_count == 1 && err == 0) { | ||
224 | int desc_cnt = chan->device->device_alloc_chan_resources(chan); | ||
225 | |||
226 | if (desc_cnt < 0) { | ||
227 | err = desc_cnt; | ||
228 | chan->client_count = 0; | ||
229 | module_put(owner); | ||
230 | } else if (!dma_has_cap(DMA_PRIVATE, chan->device->cap_mask)) | ||
231 | balance_ref_count(chan); | ||
232 | } | ||
181 | 233 | ||
182 | desc = chan->device->device_alloc_chan_resources( | 234 | return err; |
183 | chan, client); | 235 | } |
184 | if (desc >= 0) { | ||
185 | ack = client->event_callback(client, | ||
186 | chan, | ||
187 | DMA_RESOURCE_AVAILABLE); | ||
188 | 236 | ||
189 | /* we are done once this client rejects | 237 | /** |
190 | * an available resource | 238 | * dma_chan_put - drop a reference to a dma channel's parent driver module |
191 | */ | 239 | * @chan - channel to release |
192 | if (ack == DMA_ACK) { | 240 | * |
193 | dma_chan_get(chan); | 241 | * Must be called under dma_list_mutex |
194 | chan->client_count++; | 242 | */ |
195 | } else if (ack == DMA_NAK) | 243 | static void dma_chan_put(struct dma_chan *chan) |
196 | return; | 244 | { |
197 | } | 245 | if (!chan->client_count) |
198 | } | 246 | return; /* this channel failed alloc_chan_resources */ |
199 | } | 247 | chan->client_count--; |
248 | module_put(dma_chan_to_owner(chan)); | ||
249 | if (chan->client_count == 0) | ||
250 | chan->device->device_free_chan_resources(chan); | ||
200 | } | 251 | } |
201 | 252 | ||
202 | enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie) | 253 | enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie) |
@@ -218,138 +269,342 @@ enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie) | |||
218 | EXPORT_SYMBOL(dma_sync_wait); | 269 | EXPORT_SYMBOL(dma_sync_wait); |
219 | 270 | ||
220 | /** | 271 | /** |
221 | * dma_chan_cleanup - release a DMA channel's resources | 272 | * dma_cap_mask_all - enable iteration over all operation types |
222 | * @kref: kernel reference structure that contains the DMA channel device | 273 | */ |
274 | static dma_cap_mask_t dma_cap_mask_all; | ||
275 | |||
276 | /** | ||
277 | * dma_chan_tbl_ent - tracks channel allocations per core/operation | ||
278 | * @chan - associated channel for this entry | ||
279 | */ | ||
280 | struct dma_chan_tbl_ent { | ||
281 | struct dma_chan *chan; | ||
282 | }; | ||
283 | |||
284 | /** | ||
285 | * channel_table - percpu lookup table for memory-to-memory offload providers | ||
223 | */ | 286 | */ |
224 | void dma_chan_cleanup(struct kref *kref) | 287 | static struct dma_chan_tbl_ent *channel_table[DMA_TX_TYPE_END]; |
288 | |||
289 | static int __init dma_channel_table_init(void) | ||
225 | { | 290 | { |
226 | struct dma_chan *chan = container_of(kref, struct dma_chan, refcount); | 291 | enum dma_transaction_type cap; |
227 | chan->device->device_free_chan_resources(chan); | 292 | int err = 0; |
228 | kref_put(&chan->device->refcount, dma_async_device_cleanup); | 293 | |
294 | bitmap_fill(dma_cap_mask_all.bits, DMA_TX_TYPE_END); | ||
295 | |||
296 | /* 'interrupt', 'private', and 'slave' are channel capabilities, | ||
297 | * but are not associated with an operation so they do not need | ||
298 | * an entry in the channel_table | ||
299 | */ | ||
300 | clear_bit(DMA_INTERRUPT, dma_cap_mask_all.bits); | ||
301 | clear_bit(DMA_PRIVATE, dma_cap_mask_all.bits); | ||
302 | clear_bit(DMA_SLAVE, dma_cap_mask_all.bits); | ||
303 | |||
304 | for_each_dma_cap_mask(cap, dma_cap_mask_all) { | ||
305 | channel_table[cap] = alloc_percpu(struct dma_chan_tbl_ent); | ||
306 | if (!channel_table[cap]) { | ||
307 | err = -ENOMEM; | ||
308 | break; | ||
309 | } | ||
310 | } | ||
311 | |||
312 | if (err) { | ||
313 | pr_err("dmaengine: initialization failure\n"); | ||
314 | for_each_dma_cap_mask(cap, dma_cap_mask_all) | ||
315 | if (channel_table[cap]) | ||
316 | free_percpu(channel_table[cap]); | ||
317 | } | ||
318 | |||
319 | return err; | ||
229 | } | 320 | } |
230 | EXPORT_SYMBOL(dma_chan_cleanup); | 321 | arch_initcall(dma_channel_table_init); |
231 | 322 | ||
232 | static void dma_chan_free_rcu(struct rcu_head *rcu) | 323 | /** |
324 | * dma_find_channel - find a channel to carry out the operation | ||
325 | * @tx_type: transaction type | ||
326 | */ | ||
327 | struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type) | ||
233 | { | 328 | { |
234 | struct dma_chan *chan = container_of(rcu, struct dma_chan, rcu); | 329 | struct dma_chan *chan; |
235 | int bias = 0x7FFFFFFF; | 330 | int cpu; |
236 | int i; | 331 | |
237 | for_each_possible_cpu(i) | 332 | WARN_ONCE(dmaengine_ref_count == 0, |
238 | bias -= local_read(&per_cpu_ptr(chan->local, i)->refcount); | 333 | "client called %s without a reference", __func__); |
239 | atomic_sub(bias, &chan->refcount.refcount); | 334 | |
240 | kref_put(&chan->refcount, dma_chan_cleanup); | 335 | cpu = get_cpu(); |
336 | chan = per_cpu_ptr(channel_table[tx_type], cpu)->chan; | ||
337 | put_cpu(); | ||
338 | |||
339 | return chan; | ||
241 | } | 340 | } |
341 | EXPORT_SYMBOL(dma_find_channel); | ||
242 | 342 | ||
243 | static void dma_chan_release(struct dma_chan *chan) | 343 | /** |
344 | * dma_issue_pending_all - flush all pending operations across all channels | ||
345 | */ | ||
346 | void dma_issue_pending_all(void) | ||
244 | { | 347 | { |
245 | atomic_add(0x7FFFFFFF, &chan->refcount.refcount); | 348 | struct dma_device *device; |
246 | chan->slow_ref = 1; | 349 | struct dma_chan *chan; |
247 | call_rcu(&chan->rcu, dma_chan_free_rcu); | 350 | |
351 | WARN_ONCE(dmaengine_ref_count == 0, | ||
352 | "client called %s without a reference", __func__); | ||
353 | |||
354 | rcu_read_lock(); | ||
355 | list_for_each_entry_rcu(device, &dma_device_list, global_node) { | ||
356 | if (dma_has_cap(DMA_PRIVATE, device->cap_mask)) | ||
357 | continue; | ||
358 | list_for_each_entry(chan, &device->channels, device_node) | ||
359 | if (chan->client_count) | ||
360 | device->device_issue_pending(chan); | ||
361 | } | ||
362 | rcu_read_unlock(); | ||
248 | } | 363 | } |
364 | EXPORT_SYMBOL(dma_issue_pending_all); | ||
249 | 365 | ||
250 | /** | 366 | /** |
251 | * dma_chans_notify_available - broadcast available channels to the clients | 367 | * nth_chan - returns the nth channel of the given capability |
368 | * @cap: capability to match | ||
369 | * @n: nth channel desired | ||
370 | * | ||
371 | * Defaults to returning the channel with the desired capability and the | ||
372 | * lowest reference count when 'n' cannot be satisfied. Must be called | ||
373 | * under dma_list_mutex. | ||
252 | */ | 374 | */ |
253 | static void dma_clients_notify_available(void) | 375 | static struct dma_chan *nth_chan(enum dma_transaction_type cap, int n) |
254 | { | 376 | { |
255 | struct dma_client *client; | 377 | struct dma_device *device; |
378 | struct dma_chan *chan; | ||
379 | struct dma_chan *ret = NULL; | ||
380 | struct dma_chan *min = NULL; | ||
256 | 381 | ||
257 | mutex_lock(&dma_list_mutex); | 382 | list_for_each_entry(device, &dma_device_list, global_node) { |
383 | if (!dma_has_cap(cap, device->cap_mask) || | ||
384 | dma_has_cap(DMA_PRIVATE, device->cap_mask)) | ||
385 | continue; | ||
386 | list_for_each_entry(chan, &device->channels, device_node) { | ||
387 | if (!chan->client_count) | ||
388 | continue; | ||
389 | if (!min) | ||
390 | min = chan; | ||
391 | else if (chan->table_count < min->table_count) | ||
392 | min = chan; | ||
393 | |||
394 | if (n-- == 0) { | ||
395 | ret = chan; | ||
396 | break; /* done */ | ||
397 | } | ||
398 | } | ||
399 | if (ret) | ||
400 | break; /* done */ | ||
401 | } | ||
258 | 402 | ||
259 | list_for_each_entry(client, &dma_client_list, global_node) | 403 | if (!ret) |
260 | dma_client_chan_alloc(client); | 404 | ret = min; |
261 | 405 | ||
262 | mutex_unlock(&dma_list_mutex); | 406 | if (ret) |
407 | ret->table_count++; | ||
408 | |||
409 | return ret; | ||
263 | } | 410 | } |
264 | 411 | ||
265 | /** | 412 | /** |
266 | * dma_chans_notify_available - tell the clients that a channel is going away | 413 | * dma_channel_rebalance - redistribute the available channels |
267 | * @chan: channel on its way out | 414 | * |
415 | * Optimize for cpu isolation (each cpu gets a dedicated channel for an | ||
416 | * operation type) in the SMP case, and operation isolation (avoid | ||
417 | * multi-tasking channels) in the non-SMP case. Must be called under | ||
418 | * dma_list_mutex. | ||
268 | */ | 419 | */ |
269 | static void dma_clients_notify_removed(struct dma_chan *chan) | 420 | static void dma_channel_rebalance(void) |
270 | { | 421 | { |
271 | struct dma_client *client; | 422 | struct dma_chan *chan; |
272 | enum dma_state_client ack; | 423 | struct dma_device *device; |
424 | int cpu; | ||
425 | int cap; | ||
426 | int n; | ||
273 | 427 | ||
274 | mutex_lock(&dma_list_mutex); | 428 | /* undo the last distribution */ |
429 | for_each_dma_cap_mask(cap, dma_cap_mask_all) | ||
430 | for_each_possible_cpu(cpu) | ||
431 | per_cpu_ptr(channel_table[cap], cpu)->chan = NULL; | ||
432 | |||
433 | list_for_each_entry(device, &dma_device_list, global_node) { | ||
434 | if (dma_has_cap(DMA_PRIVATE, device->cap_mask)) | ||
435 | continue; | ||
436 | list_for_each_entry(chan, &device->channels, device_node) | ||
437 | chan->table_count = 0; | ||
438 | } | ||
275 | 439 | ||
276 | list_for_each_entry(client, &dma_client_list, global_node) { | 440 | /* don't populate the channel_table if no clients are available */ |
277 | ack = client->event_callback(client, chan, | 441 | if (!dmaengine_ref_count) |
278 | DMA_RESOURCE_REMOVED); | 442 | return; |
279 | 443 | ||
280 | /* client was holding resources for this channel so | 444 | /* redistribute available channels */ |
281 | * free it | 445 | n = 0; |
282 | */ | 446 | for_each_dma_cap_mask(cap, dma_cap_mask_all) |
283 | if (ack == DMA_ACK) { | 447 | for_each_online_cpu(cpu) { |
284 | dma_chan_put(chan); | 448 | if (num_possible_cpus() > 1) |
285 | chan->client_count--; | 449 | chan = nth_chan(cap, n++); |
450 | else | ||
451 | chan = nth_chan(cap, -1); | ||
452 | |||
453 | per_cpu_ptr(channel_table[cap], cpu)->chan = chan; | ||
454 | } | ||
455 | } | ||
456 | |||
457 | static struct dma_chan *private_candidate(dma_cap_mask_t *mask, struct dma_device *dev, | ||
458 | dma_filter_fn fn, void *fn_param) | ||
459 | { | ||
460 | struct dma_chan *chan; | ||
461 | |||
462 | if (!__dma_device_satisfies_mask(dev, mask)) { | ||
463 | pr_debug("%s: wrong capabilities\n", __func__); | ||
464 | return NULL; | ||
465 | } | ||
466 | /* devices with multiple channels need special handling as we need to | ||
467 | * ensure that all channels are either private or public. | ||
468 | */ | ||
469 | if (dev->chancnt > 1 && !dma_has_cap(DMA_PRIVATE, dev->cap_mask)) | ||
470 | list_for_each_entry(chan, &dev->channels, device_node) { | ||
471 | /* some channels are already publicly allocated */ | ||
472 | if (chan->client_count) | ||
473 | return NULL; | ||
286 | } | 474 | } |
475 | |||
476 | list_for_each_entry(chan, &dev->channels, device_node) { | ||
477 | if (chan->client_count) { | ||
478 | pr_debug("%s: %s busy\n", | ||
479 | __func__, dma_chan_name(chan)); | ||
480 | continue; | ||
481 | } | ||
482 | if (fn && !fn(chan, fn_param)) { | ||
483 | pr_debug("%s: %s filter said false\n", | ||
484 | __func__, dma_chan_name(chan)); | ||
485 | continue; | ||
486 | } | ||
487 | return chan; | ||
287 | } | 488 | } |
288 | 489 | ||
289 | mutex_unlock(&dma_list_mutex); | 490 | return NULL; |
290 | } | 491 | } |
291 | 492 | ||
292 | /** | 493 | /** |
293 | * dma_async_client_register - register a &dma_client | 494 | * dma_request_channel - try to allocate an exclusive channel |
294 | * @client: ptr to a client structure with valid 'event_callback' and 'cap_mask' | 495 | * @mask: capabilities that the channel must satisfy |
496 | * @fn: optional callback to disposition available channels | ||
497 | * @fn_param: opaque parameter to pass to dma_filter_fn | ||
295 | */ | 498 | */ |
296 | void dma_async_client_register(struct dma_client *client) | 499 | struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param) |
297 | { | 500 | { |
298 | /* validate client data */ | 501 | struct dma_device *device, *_d; |
299 | BUG_ON(dma_has_cap(DMA_SLAVE, client->cap_mask) && | 502 | struct dma_chan *chan = NULL; |
300 | !client->slave); | 503 | int err; |
301 | 504 | ||
505 | /* Find a channel */ | ||
506 | mutex_lock(&dma_list_mutex); | ||
507 | list_for_each_entry_safe(device, _d, &dma_device_list, global_node) { | ||
508 | chan = private_candidate(mask, device, fn, fn_param); | ||
509 | if (chan) { | ||
510 | /* Found a suitable channel, try to grab, prep, and | ||
511 | * return it. We first set DMA_PRIVATE to disable | ||
512 | * balance_ref_count as this channel will not be | ||
513 | * published in the general-purpose allocator | ||
514 | */ | ||
515 | dma_cap_set(DMA_PRIVATE, device->cap_mask); | ||
516 | err = dma_chan_get(chan); | ||
517 | |||
518 | if (err == -ENODEV) { | ||
519 | pr_debug("%s: %s module removed\n", __func__, | ||
520 | dma_chan_name(chan)); | ||
521 | list_del_rcu(&device->global_node); | ||
522 | } else if (err) | ||
523 | pr_err("dmaengine: failed to get %s: (%d)\n", | ||
524 | dma_chan_name(chan), err); | ||
525 | else | ||
526 | break; | ||
527 | chan = NULL; | ||
528 | } | ||
529 | } | ||
530 | mutex_unlock(&dma_list_mutex); | ||
531 | |||
532 | pr_debug("%s: %s (%s)\n", __func__, chan ? "success" : "fail", | ||
533 | chan ? dma_chan_name(chan) : NULL); | ||
534 | |||
535 | return chan; | ||
536 | } | ||
537 | EXPORT_SYMBOL_GPL(__dma_request_channel); | ||
538 | |||
539 | void dma_release_channel(struct dma_chan *chan) | ||
540 | { | ||
302 | mutex_lock(&dma_list_mutex); | 541 | mutex_lock(&dma_list_mutex); |
303 | list_add_tail(&client->global_node, &dma_client_list); | 542 | WARN_ONCE(chan->client_count != 1, |
543 | "chan reference count %d != 1\n", chan->client_count); | ||
544 | dma_chan_put(chan); | ||
304 | mutex_unlock(&dma_list_mutex); | 545 | mutex_unlock(&dma_list_mutex); |
305 | } | 546 | } |
306 | EXPORT_SYMBOL(dma_async_client_register); | 547 | EXPORT_SYMBOL_GPL(dma_release_channel); |
307 | 548 | ||
308 | /** | 549 | /** |
309 | * dma_async_client_unregister - unregister a client and free the &dma_client | 550 | * dmaengine_get - register interest in dma_channels |
310 | * @client: &dma_client to free | ||
311 | * | ||
312 | * Force frees any allocated DMA channels, frees the &dma_client memory | ||
313 | */ | 551 | */ |
314 | void dma_async_client_unregister(struct dma_client *client) | 552 | void dmaengine_get(void) |
315 | { | 553 | { |
316 | struct dma_device *device; | 554 | struct dma_device *device, *_d; |
317 | struct dma_chan *chan; | 555 | struct dma_chan *chan; |
318 | enum dma_state_client ack; | 556 | int err; |
319 | |||
320 | if (!client) | ||
321 | return; | ||
322 | 557 | ||
323 | mutex_lock(&dma_list_mutex); | 558 | mutex_lock(&dma_list_mutex); |
324 | /* free all channels the client is holding */ | 559 | dmaengine_ref_count++; |
325 | list_for_each_entry(device, &dma_device_list, global_node) | ||
326 | list_for_each_entry(chan, &device->channels, device_node) { | ||
327 | ack = client->event_callback(client, chan, | ||
328 | DMA_RESOURCE_REMOVED); | ||
329 | 560 | ||
330 | if (ack == DMA_ACK) { | 561 | /* try to grab channels */ |
331 | dma_chan_put(chan); | 562 | list_for_each_entry_safe(device, _d, &dma_device_list, global_node) { |
332 | chan->client_count--; | 563 | if (dma_has_cap(DMA_PRIVATE, device->cap_mask)) |
333 | } | 564 | continue; |
565 | list_for_each_entry(chan, &device->channels, device_node) { | ||
566 | err = dma_chan_get(chan); | ||
567 | if (err == -ENODEV) { | ||
568 | /* module removed before we could use it */ | ||
569 | list_del_rcu(&device->global_node); | ||
570 | break; | ||
571 | } else if (err) | ||
572 | pr_err("dmaengine: failed to get %s: (%d)\n", | ||
573 | dma_chan_name(chan), err); | ||
334 | } | 574 | } |
575 | } | ||
335 | 576 | ||
336 | list_del(&client->global_node); | 577 | /* if this is the first reference and there were channels |
578 | * waiting we need to rebalance to get those channels | ||
579 | * incorporated into the channel table | ||
580 | */ | ||
581 | if (dmaengine_ref_count == 1) | ||
582 | dma_channel_rebalance(); | ||
337 | mutex_unlock(&dma_list_mutex); | 583 | mutex_unlock(&dma_list_mutex); |
338 | } | 584 | } |
339 | EXPORT_SYMBOL(dma_async_client_unregister); | 585 | EXPORT_SYMBOL(dmaengine_get); |
340 | 586 | ||
341 | /** | 587 | /** |
342 | * dma_async_client_chan_request - send all available channels to the | 588 | * dmaengine_put - let dma drivers be removed when ref_count == 0 |
343 | * client that satisfy the capability mask | ||
344 | * @client - requester | ||
345 | */ | 589 | */ |
346 | void dma_async_client_chan_request(struct dma_client *client) | 590 | void dmaengine_put(void) |
347 | { | 591 | { |
592 | struct dma_device *device; | ||
593 | struct dma_chan *chan; | ||
594 | |||
348 | mutex_lock(&dma_list_mutex); | 595 | mutex_lock(&dma_list_mutex); |
349 | dma_client_chan_alloc(client); | 596 | dmaengine_ref_count--; |
597 | BUG_ON(dmaengine_ref_count < 0); | ||
598 | /* drop channel references */ | ||
599 | list_for_each_entry(device, &dma_device_list, global_node) { | ||
600 | if (dma_has_cap(DMA_PRIVATE, device->cap_mask)) | ||
601 | continue; | ||
602 | list_for_each_entry(chan, &device->channels, device_node) | ||
603 | dma_chan_put(chan); | ||
604 | } | ||
350 | mutex_unlock(&dma_list_mutex); | 605 | mutex_unlock(&dma_list_mutex); |
351 | } | 606 | } |
352 | EXPORT_SYMBOL(dma_async_client_chan_request); | 607 | EXPORT_SYMBOL(dmaengine_put); |
353 | 608 | ||
354 | /** | 609 | /** |
355 | * dma_async_device_register - registers DMA devices found | 610 | * dma_async_device_register - registers DMA devices found |
@@ -357,9 +612,9 @@ EXPORT_SYMBOL(dma_async_client_chan_request); | |||
357 | */ | 612 | */ |
358 | int dma_async_device_register(struct dma_device *device) | 613 | int dma_async_device_register(struct dma_device *device) |
359 | { | 614 | { |
360 | static int id; | ||
361 | int chancnt = 0, rc; | 615 | int chancnt = 0, rc; |
362 | struct dma_chan* chan; | 616 | struct dma_chan* chan; |
617 | atomic_t *idr_ref; | ||
363 | 618 | ||
364 | if (!device) | 619 | if (!device) |
365 | return -ENODEV; | 620 | return -ENODEV; |
@@ -386,57 +641,83 @@ int dma_async_device_register(struct dma_device *device) | |||
386 | BUG_ON(!device->device_issue_pending); | 641 | BUG_ON(!device->device_issue_pending); |
387 | BUG_ON(!device->dev); | 642 | BUG_ON(!device->dev); |
388 | 643 | ||
389 | init_completion(&device->done); | 644 | idr_ref = kmalloc(sizeof(*idr_ref), GFP_KERNEL); |
390 | kref_init(&device->refcount); | 645 | if (!idr_ref) |
391 | 646 | return -ENOMEM; | |
647 | atomic_set(idr_ref, 0); | ||
648 | idr_retry: | ||
649 | if (!idr_pre_get(&dma_idr, GFP_KERNEL)) | ||
650 | return -ENOMEM; | ||
392 | mutex_lock(&dma_list_mutex); | 651 | mutex_lock(&dma_list_mutex); |
393 | device->dev_id = id++; | 652 | rc = idr_get_new(&dma_idr, NULL, &device->dev_id); |
394 | mutex_unlock(&dma_list_mutex); | 653 | mutex_unlock(&dma_list_mutex); |
654 | if (rc == -EAGAIN) | ||
655 | goto idr_retry; | ||
656 | else if (rc != 0) | ||
657 | return rc; | ||
395 | 658 | ||
396 | /* represent channels in sysfs. Probably want devs too */ | 659 | /* represent channels in sysfs. Probably want devs too */ |
397 | list_for_each_entry(chan, &device->channels, device_node) { | 660 | list_for_each_entry(chan, &device->channels, device_node) { |
398 | chan->local = alloc_percpu(typeof(*chan->local)); | 661 | chan->local = alloc_percpu(typeof(*chan->local)); |
399 | if (chan->local == NULL) | 662 | if (chan->local == NULL) |
400 | continue; | 663 | continue; |
664 | chan->dev = kzalloc(sizeof(*chan->dev), GFP_KERNEL); | ||
665 | if (chan->dev == NULL) { | ||
666 | free_percpu(chan->local); | ||
667 | continue; | ||
668 | } | ||
401 | 669 | ||
402 | chan->chan_id = chancnt++; | 670 | chan->chan_id = chancnt++; |
403 | chan->dev.class = &dma_devclass; | 671 | chan->dev->device.class = &dma_devclass; |
404 | chan->dev.parent = device->dev; | 672 | chan->dev->device.parent = device->dev; |
405 | dev_set_name(&chan->dev, "dma%dchan%d", | 673 | chan->dev->chan = chan; |
674 | chan->dev->idr_ref = idr_ref; | ||
675 | chan->dev->dev_id = device->dev_id; | ||
676 | atomic_inc(idr_ref); | ||
677 | dev_set_name(&chan->dev->device, "dma%dchan%d", | ||
406 | device->dev_id, chan->chan_id); | 678 | device->dev_id, chan->chan_id); |
407 | 679 | ||
408 | rc = device_register(&chan->dev); | 680 | rc = device_register(&chan->dev->device); |
409 | if (rc) { | 681 | if (rc) { |
410 | chancnt--; | ||
411 | free_percpu(chan->local); | 682 | free_percpu(chan->local); |
412 | chan->local = NULL; | 683 | chan->local = NULL; |
413 | goto err_out; | 684 | goto err_out; |
414 | } | 685 | } |
415 | |||
416 | /* One for the channel, one of the class device */ | ||
417 | kref_get(&device->refcount); | ||
418 | kref_get(&device->refcount); | ||
419 | kref_init(&chan->refcount); | ||
420 | chan->client_count = 0; | 686 | chan->client_count = 0; |
421 | chan->slow_ref = 0; | ||
422 | INIT_RCU_HEAD(&chan->rcu); | ||
423 | } | 687 | } |
688 | device->chancnt = chancnt; | ||
424 | 689 | ||
425 | mutex_lock(&dma_list_mutex); | 690 | mutex_lock(&dma_list_mutex); |
426 | list_add_tail(&device->global_node, &dma_device_list); | 691 | /* take references on public channels */ |
692 | if (dmaengine_ref_count && !dma_has_cap(DMA_PRIVATE, device->cap_mask)) | ||
693 | list_for_each_entry(chan, &device->channels, device_node) { | ||
694 | /* if clients are already waiting for channels we need | ||
695 | * to take references on their behalf | ||
696 | */ | ||
697 | if (dma_chan_get(chan) == -ENODEV) { | ||
698 | /* note we can only get here for the first | ||
699 | * channel as the remaining channels are | ||
700 | * guaranteed to get a reference | ||
701 | */ | ||
702 | rc = -ENODEV; | ||
703 | mutex_unlock(&dma_list_mutex); | ||
704 | goto err_out; | ||
705 | } | ||
706 | } | ||
707 | list_add_tail_rcu(&device->global_node, &dma_device_list); | ||
708 | dma_channel_rebalance(); | ||
427 | mutex_unlock(&dma_list_mutex); | 709 | mutex_unlock(&dma_list_mutex); |
428 | 710 | ||
429 | dma_clients_notify_available(); | ||
430 | |||
431 | return 0; | 711 | return 0; |
432 | 712 | ||
433 | err_out: | 713 | err_out: |
434 | list_for_each_entry(chan, &device->channels, device_node) { | 714 | list_for_each_entry(chan, &device->channels, device_node) { |
435 | if (chan->local == NULL) | 715 | if (chan->local == NULL) |
436 | continue; | 716 | continue; |
437 | kref_put(&device->refcount, dma_async_device_cleanup); | 717 | mutex_lock(&dma_list_mutex); |
438 | device_unregister(&chan->dev); | 718 | chan->dev->chan = NULL; |
439 | chancnt--; | 719 | mutex_unlock(&dma_list_mutex); |
720 | device_unregister(&chan->dev->device); | ||
440 | free_percpu(chan->local); | 721 | free_percpu(chan->local); |
441 | } | 722 | } |
442 | return rc; | 723 | return rc; |
@@ -444,37 +725,30 @@ err_out: | |||
444 | EXPORT_SYMBOL(dma_async_device_register); | 725 | EXPORT_SYMBOL(dma_async_device_register); |
445 | 726 | ||
446 | /** | 727 | /** |
447 | * dma_async_device_cleanup - function called when all references are released | 728 | * dma_async_device_unregister - unregister a DMA device |
448 | * @kref: kernel reference object | ||
449 | */ | ||
450 | static void dma_async_device_cleanup(struct kref *kref) | ||
451 | { | ||
452 | struct dma_device *device; | ||
453 | |||
454 | device = container_of(kref, struct dma_device, refcount); | ||
455 | complete(&device->done); | ||
456 | } | ||
457 | |||
458 | /** | ||
459 | * dma_async_device_unregister - unregisters DMA devices | ||
460 | * @device: &dma_device | 729 | * @device: &dma_device |
730 | * | ||
731 | * This routine is called by dma driver exit routines, dmaengine holds module | ||
732 | * references to prevent it being called while channels are in use. | ||
461 | */ | 733 | */ |
462 | void dma_async_device_unregister(struct dma_device *device) | 734 | void dma_async_device_unregister(struct dma_device *device) |
463 | { | 735 | { |
464 | struct dma_chan *chan; | 736 | struct dma_chan *chan; |
465 | 737 | ||
466 | mutex_lock(&dma_list_mutex); | 738 | mutex_lock(&dma_list_mutex); |
467 | list_del(&device->global_node); | 739 | list_del_rcu(&device->global_node); |
740 | dma_channel_rebalance(); | ||
468 | mutex_unlock(&dma_list_mutex); | 741 | mutex_unlock(&dma_list_mutex); |
469 | 742 | ||
470 | list_for_each_entry(chan, &device->channels, device_node) { | 743 | list_for_each_entry(chan, &device->channels, device_node) { |
471 | dma_clients_notify_removed(chan); | 744 | WARN_ONCE(chan->client_count, |
472 | device_unregister(&chan->dev); | 745 | "%s called while %d clients hold a reference\n", |
473 | dma_chan_release(chan); | 746 | __func__, chan->client_count); |
747 | mutex_lock(&dma_list_mutex); | ||
748 | chan->dev->chan = NULL; | ||
749 | mutex_unlock(&dma_list_mutex); | ||
750 | device_unregister(&chan->dev->device); | ||
474 | } | 751 | } |
475 | |||
476 | kref_put(&device->refcount, dma_async_device_cleanup); | ||
477 | wait_for_completion(&device->done); | ||
478 | } | 752 | } |
479 | EXPORT_SYMBOL(dma_async_device_unregister); | 753 | EXPORT_SYMBOL(dma_async_device_unregister); |
480 | 754 | ||
@@ -626,10 +900,96 @@ void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx, | |||
626 | } | 900 | } |
627 | EXPORT_SYMBOL(dma_async_tx_descriptor_init); | 901 | EXPORT_SYMBOL(dma_async_tx_descriptor_init); |
628 | 902 | ||
903 | /* dma_wait_for_async_tx - spin wait for a transaction to complete | ||
904 | * @tx: in-flight transaction to wait on | ||
905 | * | ||
906 | * This routine assumes that tx was obtained from a call to async_memcpy, | ||
907 | * async_xor, async_memset, etc which ensures that tx is "in-flight" (prepped | ||
908 | * and submitted). Walking the parent chain is only meant to cover for DMA | ||
909 | * drivers that do not implement the DMA_INTERRUPT capability and may race with | ||
910 | * the driver's descriptor cleanup routine. | ||
911 | */ | ||
912 | enum dma_status | ||
913 | dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) | ||
914 | { | ||
915 | enum dma_status status; | ||
916 | struct dma_async_tx_descriptor *iter; | ||
917 | struct dma_async_tx_descriptor *parent; | ||
918 | |||
919 | if (!tx) | ||
920 | return DMA_SUCCESS; | ||
921 | |||
922 | WARN_ONCE(tx->parent, "%s: speculatively walking dependency chain for" | ||
923 | " %s\n", __func__, dma_chan_name(tx->chan)); | ||
924 | |||
925 | /* poll through the dependency chain, return when tx is complete */ | ||
926 | do { | ||
927 | iter = tx; | ||
928 | |||
929 | /* find the root of the unsubmitted dependency chain */ | ||
930 | do { | ||
931 | parent = iter->parent; | ||
932 | if (!parent) | ||
933 | break; | ||
934 | else | ||
935 | iter = parent; | ||
936 | } while (parent); | ||
937 | |||
938 | /* there is a small window for ->parent == NULL and | ||
939 | * ->cookie == -EBUSY | ||
940 | */ | ||
941 | while (iter->cookie == -EBUSY) | ||
942 | cpu_relax(); | ||
943 | |||
944 | status = dma_sync_wait(iter->chan, iter->cookie); | ||
945 | } while (status == DMA_IN_PROGRESS || (iter != tx)); | ||
946 | |||
947 | return status; | ||
948 | } | ||
949 | EXPORT_SYMBOL_GPL(dma_wait_for_async_tx); | ||
950 | |||
951 | /* dma_run_dependencies - helper routine for dma drivers to process | ||
952 | * (start) dependent operations on their target channel | ||
953 | * @tx: transaction with dependencies | ||
954 | */ | ||
955 | void dma_run_dependencies(struct dma_async_tx_descriptor *tx) | ||
956 | { | ||
957 | struct dma_async_tx_descriptor *dep = tx->next; | ||
958 | struct dma_async_tx_descriptor *dep_next; | ||
959 | struct dma_chan *chan; | ||
960 | |||
961 | if (!dep) | ||
962 | return; | ||
963 | |||
964 | chan = dep->chan; | ||
965 | |||
966 | /* keep submitting up until a channel switch is detected | ||
967 | * in that case we will be called again as a result of | ||
968 | * processing the interrupt from async_tx_channel_switch | ||
969 | */ | ||
970 | for (; dep; dep = dep_next) { | ||
971 | spin_lock_bh(&dep->lock); | ||
972 | dep->parent = NULL; | ||
973 | dep_next = dep->next; | ||
974 | if (dep_next && dep_next->chan == chan) | ||
975 | dep->next = NULL; /* ->next will be submitted */ | ||
976 | else | ||
977 | dep_next = NULL; /* submit current dep and terminate */ | ||
978 | spin_unlock_bh(&dep->lock); | ||
979 | |||
980 | dep->tx_submit(dep); | ||
981 | } | ||
982 | |||
983 | chan->device->device_issue_pending(chan); | ||
984 | } | ||
985 | EXPORT_SYMBOL_GPL(dma_run_dependencies); | ||
986 | |||
629 | static int __init dma_bus_init(void) | 987 | static int __init dma_bus_init(void) |
630 | { | 988 | { |
989 | idr_init(&dma_idr); | ||
631 | mutex_init(&dma_list_mutex); | 990 | mutex_init(&dma_list_mutex); |
632 | return class_register(&dma_devclass); | 991 | return class_register(&dma_devclass); |
633 | } | 992 | } |
634 | subsys_initcall(dma_bus_init); | 993 | arch_initcall(dma_bus_init); |
994 | |||
635 | 995 | ||
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index ed9636bfb54a..3603f1ea5b28 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c | |||
@@ -35,7 +35,7 @@ MODULE_PARM_DESC(threads_per_chan, | |||
35 | 35 | ||
36 | static unsigned int max_channels; | 36 | static unsigned int max_channels; |
37 | module_param(max_channels, uint, S_IRUGO); | 37 | module_param(max_channels, uint, S_IRUGO); |
38 | MODULE_PARM_DESC(nr_channels, | 38 | MODULE_PARM_DESC(max_channels, |
39 | "Maximum number of channels to use (default: all)"); | 39 | "Maximum number of channels to use (default: all)"); |
40 | 40 | ||
41 | /* | 41 | /* |
@@ -71,7 +71,7 @@ struct dmatest_chan { | |||
71 | 71 | ||
72 | /* | 72 | /* |
73 | * These are protected by dma_list_mutex since they're only used by | 73 | * These are protected by dma_list_mutex since they're only used by |
74 | * the DMA client event callback | 74 | * the DMA filter function callback |
75 | */ | 75 | */ |
76 | static LIST_HEAD(dmatest_channels); | 76 | static LIST_HEAD(dmatest_channels); |
77 | static unsigned int nr_channels; | 77 | static unsigned int nr_channels; |
@@ -80,7 +80,7 @@ static bool dmatest_match_channel(struct dma_chan *chan) | |||
80 | { | 80 | { |
81 | if (test_channel[0] == '\0') | 81 | if (test_channel[0] == '\0') |
82 | return true; | 82 | return true; |
83 | return strcmp(dev_name(&chan->dev), test_channel) == 0; | 83 | return strcmp(dma_chan_name(chan), test_channel) == 0; |
84 | } | 84 | } |
85 | 85 | ||
86 | static bool dmatest_match_device(struct dma_device *device) | 86 | static bool dmatest_match_device(struct dma_device *device) |
@@ -215,7 +215,6 @@ static int dmatest_func(void *data) | |||
215 | 215 | ||
216 | smp_rmb(); | 216 | smp_rmb(); |
217 | chan = thread->chan; | 217 | chan = thread->chan; |
218 | dma_chan_get(chan); | ||
219 | 218 | ||
220 | while (!kthread_should_stop()) { | 219 | while (!kthread_should_stop()) { |
221 | total_tests++; | 220 | total_tests++; |
@@ -293,7 +292,6 @@ static int dmatest_func(void *data) | |||
293 | } | 292 | } |
294 | 293 | ||
295 | ret = 0; | 294 | ret = 0; |
296 | dma_chan_put(chan); | ||
297 | kfree(thread->dstbuf); | 295 | kfree(thread->dstbuf); |
298 | err_dstbuf: | 296 | err_dstbuf: |
299 | kfree(thread->srcbuf); | 297 | kfree(thread->srcbuf); |
@@ -319,21 +317,16 @@ static void dmatest_cleanup_channel(struct dmatest_chan *dtc) | |||
319 | kfree(dtc); | 317 | kfree(dtc); |
320 | } | 318 | } |
321 | 319 | ||
322 | static enum dma_state_client dmatest_add_channel(struct dma_chan *chan) | 320 | static int dmatest_add_channel(struct dma_chan *chan) |
323 | { | 321 | { |
324 | struct dmatest_chan *dtc; | 322 | struct dmatest_chan *dtc; |
325 | struct dmatest_thread *thread; | 323 | struct dmatest_thread *thread; |
326 | unsigned int i; | 324 | unsigned int i; |
327 | 325 | ||
328 | /* Have we already been told about this channel? */ | ||
329 | list_for_each_entry(dtc, &dmatest_channels, node) | ||
330 | if (dtc->chan == chan) | ||
331 | return DMA_DUP; | ||
332 | |||
333 | dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL); | 326 | dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL); |
334 | if (!dtc) { | 327 | if (!dtc) { |
335 | pr_warning("dmatest: No memory for %s\n", dev_name(&chan->dev)); | 328 | pr_warning("dmatest: No memory for %s\n", dma_chan_name(chan)); |
336 | return DMA_NAK; | 329 | return -ENOMEM; |
337 | } | 330 | } |
338 | 331 | ||
339 | dtc->chan = chan; | 332 | dtc->chan = chan; |
@@ -343,16 +336,16 @@ static enum dma_state_client dmatest_add_channel(struct dma_chan *chan) | |||
343 | thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL); | 336 | thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL); |
344 | if (!thread) { | 337 | if (!thread) { |
345 | pr_warning("dmatest: No memory for %s-test%u\n", | 338 | pr_warning("dmatest: No memory for %s-test%u\n", |
346 | dev_name(&chan->dev), i); | 339 | dma_chan_name(chan), i); |
347 | break; | 340 | break; |
348 | } | 341 | } |
349 | thread->chan = dtc->chan; | 342 | thread->chan = dtc->chan; |
350 | smp_wmb(); | 343 | smp_wmb(); |
351 | thread->task = kthread_run(dmatest_func, thread, "%s-test%u", | 344 | thread->task = kthread_run(dmatest_func, thread, "%s-test%u", |
352 | dev_name(&chan->dev), i); | 345 | dma_chan_name(chan), i); |
353 | if (IS_ERR(thread->task)) { | 346 | if (IS_ERR(thread->task)) { |
354 | pr_warning("dmatest: Failed to run thread %s-test%u\n", | 347 | pr_warning("dmatest: Failed to run thread %s-test%u\n", |
355 | dev_name(&chan->dev), i); | 348 | dma_chan_name(chan), i); |
356 | kfree(thread); | 349 | kfree(thread); |
357 | break; | 350 | break; |
358 | } | 351 | } |
@@ -362,86 +355,62 @@ static enum dma_state_client dmatest_add_channel(struct dma_chan *chan) | |||
362 | list_add_tail(&thread->node, &dtc->threads); | 355 | list_add_tail(&thread->node, &dtc->threads); |
363 | } | 356 | } |
364 | 357 | ||
365 | pr_info("dmatest: Started %u threads using %s\n", i, dev_name(&chan->dev)); | 358 | pr_info("dmatest: Started %u threads using %s\n", i, dma_chan_name(chan)); |
366 | 359 | ||
367 | list_add_tail(&dtc->node, &dmatest_channels); | 360 | list_add_tail(&dtc->node, &dmatest_channels); |
368 | nr_channels++; | 361 | nr_channels++; |
369 | 362 | ||
370 | return DMA_ACK; | 363 | return 0; |
371 | } | ||
372 | |||
373 | static enum dma_state_client dmatest_remove_channel(struct dma_chan *chan) | ||
374 | { | ||
375 | struct dmatest_chan *dtc, *_dtc; | ||
376 | |||
377 | list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) { | ||
378 | if (dtc->chan == chan) { | ||
379 | list_del(&dtc->node); | ||
380 | dmatest_cleanup_channel(dtc); | ||
381 | pr_debug("dmatest: lost channel %s\n", | ||
382 | dev_name(&chan->dev)); | ||
383 | return DMA_ACK; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | return DMA_DUP; | ||
388 | } | 364 | } |
389 | 365 | ||
390 | /* | 366 | static bool filter(struct dma_chan *chan, void *param) |
391 | * Start testing threads as new channels are assigned to us, and kill | ||
392 | * them when the channels go away. | ||
393 | * | ||
394 | * When we unregister the client, all channels are removed so this | ||
395 | * will also take care of cleaning things up when the module is | ||
396 | * unloaded. | ||
397 | */ | ||
398 | static enum dma_state_client | ||
399 | dmatest_event(struct dma_client *client, struct dma_chan *chan, | ||
400 | enum dma_state state) | ||
401 | { | 367 | { |
402 | enum dma_state_client ack = DMA_NAK; | 368 | if (!dmatest_match_channel(chan) || !dmatest_match_device(chan->device)) |
403 | 369 | return false; | |
404 | switch (state) { | 370 | else |
405 | case DMA_RESOURCE_AVAILABLE: | 371 | return true; |
406 | if (!dmatest_match_channel(chan) | ||
407 | || !dmatest_match_device(chan->device)) | ||
408 | ack = DMA_DUP; | ||
409 | else if (max_channels && nr_channels >= max_channels) | ||
410 | ack = DMA_NAK; | ||
411 | else | ||
412 | ack = dmatest_add_channel(chan); | ||
413 | break; | ||
414 | |||
415 | case DMA_RESOURCE_REMOVED: | ||
416 | ack = dmatest_remove_channel(chan); | ||
417 | break; | ||
418 | |||
419 | default: | ||
420 | pr_info("dmatest: Unhandled event %u (%s)\n", | ||
421 | state, dev_name(&chan->dev)); | ||
422 | break; | ||
423 | } | ||
424 | |||
425 | return ack; | ||
426 | } | 372 | } |
427 | 373 | ||
428 | static struct dma_client dmatest_client = { | ||
429 | .event_callback = dmatest_event, | ||
430 | }; | ||
431 | |||
432 | static int __init dmatest_init(void) | 374 | static int __init dmatest_init(void) |
433 | { | 375 | { |
434 | dma_cap_set(DMA_MEMCPY, dmatest_client.cap_mask); | 376 | dma_cap_mask_t mask; |
435 | dma_async_client_register(&dmatest_client); | 377 | struct dma_chan *chan; |
436 | dma_async_client_chan_request(&dmatest_client); | 378 | int err = 0; |
379 | |||
380 | dma_cap_zero(mask); | ||
381 | dma_cap_set(DMA_MEMCPY, mask); | ||
382 | for (;;) { | ||
383 | chan = dma_request_channel(mask, filter, NULL); | ||
384 | if (chan) { | ||
385 | err = dmatest_add_channel(chan); | ||
386 | if (err == 0) | ||
387 | continue; | ||
388 | else { | ||
389 | dma_release_channel(chan); | ||
390 | break; /* add_channel failed, punt */ | ||
391 | } | ||
392 | } else | ||
393 | break; /* no more channels available */ | ||
394 | if (max_channels && nr_channels >= max_channels) | ||
395 | break; /* we have all we need */ | ||
396 | } | ||
437 | 397 | ||
438 | return 0; | 398 | return err; |
439 | } | 399 | } |
440 | module_init(dmatest_init); | 400 | /* when compiled-in wait for drivers to load first */ |
401 | late_initcall(dmatest_init); | ||
441 | 402 | ||
442 | static void __exit dmatest_exit(void) | 403 | static void __exit dmatest_exit(void) |
443 | { | 404 | { |
444 | dma_async_client_unregister(&dmatest_client); | 405 | struct dmatest_chan *dtc, *_dtc; |
406 | |||
407 | list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) { | ||
408 | list_del(&dtc->node); | ||
409 | dmatest_cleanup_channel(dtc); | ||
410 | pr_debug("dmatest: dropped channel %s\n", | ||
411 | dma_chan_name(dtc->chan)); | ||
412 | dma_release_channel(dtc->chan); | ||
413 | } | ||
445 | } | 414 | } |
446 | module_exit(dmatest_exit); | 415 | module_exit(dmatest_exit); |
447 | 416 | ||
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 0778d99aea7c..6b702cc46b3d 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c | |||
@@ -70,6 +70,15 @@ | |||
70 | * the controller, though. | 70 | * the controller, though. |
71 | */ | 71 | */ |
72 | 72 | ||
73 | static struct device *chan2dev(struct dma_chan *chan) | ||
74 | { | ||
75 | return &chan->dev->device; | ||
76 | } | ||
77 | static struct device *chan2parent(struct dma_chan *chan) | ||
78 | { | ||
79 | return chan->dev->device.parent; | ||
80 | } | ||
81 | |||
73 | static struct dw_desc *dwc_first_active(struct dw_dma_chan *dwc) | 82 | static struct dw_desc *dwc_first_active(struct dw_dma_chan *dwc) |
74 | { | 83 | { |
75 | return list_entry(dwc->active_list.next, struct dw_desc, desc_node); | 84 | return list_entry(dwc->active_list.next, struct dw_desc, desc_node); |
@@ -93,12 +102,12 @@ static struct dw_desc *dwc_desc_get(struct dw_dma_chan *dwc) | |||
93 | ret = desc; | 102 | ret = desc; |
94 | break; | 103 | break; |
95 | } | 104 | } |
96 | dev_dbg(&dwc->chan.dev, "desc %p not ACKed\n", desc); | 105 | dev_dbg(chan2dev(&dwc->chan), "desc %p not ACKed\n", desc); |
97 | i++; | 106 | i++; |
98 | } | 107 | } |
99 | spin_unlock_bh(&dwc->lock); | 108 | spin_unlock_bh(&dwc->lock); |
100 | 109 | ||
101 | dev_vdbg(&dwc->chan.dev, "scanned %u descriptors on freelist\n", i); | 110 | dev_vdbg(chan2dev(&dwc->chan), "scanned %u descriptors on freelist\n", i); |
102 | 111 | ||
103 | return ret; | 112 | return ret; |
104 | } | 113 | } |
@@ -108,10 +117,10 @@ static void dwc_sync_desc_for_cpu(struct dw_dma_chan *dwc, struct dw_desc *desc) | |||
108 | struct dw_desc *child; | 117 | struct dw_desc *child; |
109 | 118 | ||
110 | list_for_each_entry(child, &desc->txd.tx_list, desc_node) | 119 | list_for_each_entry(child, &desc->txd.tx_list, desc_node) |
111 | dma_sync_single_for_cpu(dwc->chan.dev.parent, | 120 | dma_sync_single_for_cpu(chan2parent(&dwc->chan), |
112 | child->txd.phys, sizeof(child->lli), | 121 | child->txd.phys, sizeof(child->lli), |
113 | DMA_TO_DEVICE); | 122 | DMA_TO_DEVICE); |
114 | dma_sync_single_for_cpu(dwc->chan.dev.parent, | 123 | dma_sync_single_for_cpu(chan2parent(&dwc->chan), |
115 | desc->txd.phys, sizeof(desc->lli), | 124 | desc->txd.phys, sizeof(desc->lli), |
116 | DMA_TO_DEVICE); | 125 | DMA_TO_DEVICE); |
117 | } | 126 | } |
@@ -129,11 +138,11 @@ static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc) | |||
129 | 138 | ||
130 | spin_lock_bh(&dwc->lock); | 139 | spin_lock_bh(&dwc->lock); |
131 | list_for_each_entry(child, &desc->txd.tx_list, desc_node) | 140 | list_for_each_entry(child, &desc->txd.tx_list, desc_node) |
132 | dev_vdbg(&dwc->chan.dev, | 141 | dev_vdbg(chan2dev(&dwc->chan), |
133 | "moving child desc %p to freelist\n", | 142 | "moving child desc %p to freelist\n", |
134 | child); | 143 | child); |
135 | list_splice_init(&desc->txd.tx_list, &dwc->free_list); | 144 | list_splice_init(&desc->txd.tx_list, &dwc->free_list); |
136 | dev_vdbg(&dwc->chan.dev, "moving desc %p to freelist\n", desc); | 145 | dev_vdbg(chan2dev(&dwc->chan), "moving desc %p to freelist\n", desc); |
137 | list_add(&desc->desc_node, &dwc->free_list); | 146 | list_add(&desc->desc_node, &dwc->free_list); |
138 | spin_unlock_bh(&dwc->lock); | 147 | spin_unlock_bh(&dwc->lock); |
139 | } | 148 | } |
@@ -163,9 +172,9 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first) | |||
163 | 172 | ||
164 | /* ASSERT: channel is idle */ | 173 | /* ASSERT: channel is idle */ |
165 | if (dma_readl(dw, CH_EN) & dwc->mask) { | 174 | if (dma_readl(dw, CH_EN) & dwc->mask) { |
166 | dev_err(&dwc->chan.dev, | 175 | dev_err(chan2dev(&dwc->chan), |
167 | "BUG: Attempted to start non-idle channel\n"); | 176 | "BUG: Attempted to start non-idle channel\n"); |
168 | dev_err(&dwc->chan.dev, | 177 | dev_err(chan2dev(&dwc->chan), |
169 | " SAR: 0x%x DAR: 0x%x LLP: 0x%x CTL: 0x%x:%08x\n", | 178 | " SAR: 0x%x DAR: 0x%x LLP: 0x%x CTL: 0x%x:%08x\n", |
170 | channel_readl(dwc, SAR), | 179 | channel_readl(dwc, SAR), |
171 | channel_readl(dwc, DAR), | 180 | channel_readl(dwc, DAR), |
@@ -193,7 +202,7 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc) | |||
193 | void *param; | 202 | void *param; |
194 | struct dma_async_tx_descriptor *txd = &desc->txd; | 203 | struct dma_async_tx_descriptor *txd = &desc->txd; |
195 | 204 | ||
196 | dev_vdbg(&dwc->chan.dev, "descriptor %u complete\n", txd->cookie); | 205 | dev_vdbg(chan2dev(&dwc->chan), "descriptor %u complete\n", txd->cookie); |
197 | 206 | ||
198 | dwc->completed = txd->cookie; | 207 | dwc->completed = txd->cookie; |
199 | callback = txd->callback; | 208 | callback = txd->callback; |
@@ -208,11 +217,11 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc) | |||
208 | * mapped before they were submitted... | 217 | * mapped before they were submitted... |
209 | */ | 218 | */ |
210 | if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) | 219 | if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) |
211 | dma_unmap_page(dwc->chan.dev.parent, desc->lli.dar, desc->len, | 220 | dma_unmap_page(chan2parent(&dwc->chan), desc->lli.dar, |
212 | DMA_FROM_DEVICE); | 221 | desc->len, DMA_FROM_DEVICE); |
213 | if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) | 222 | if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) |
214 | dma_unmap_page(dwc->chan.dev.parent, desc->lli.sar, desc->len, | 223 | dma_unmap_page(chan2parent(&dwc->chan), desc->lli.sar, |
215 | DMA_TO_DEVICE); | 224 | desc->len, DMA_TO_DEVICE); |
216 | 225 | ||
217 | /* | 226 | /* |
218 | * The API requires that no submissions are done from a | 227 | * The API requires that no submissions are done from a |
@@ -228,7 +237,7 @@ static void dwc_complete_all(struct dw_dma *dw, struct dw_dma_chan *dwc) | |||
228 | LIST_HEAD(list); | 237 | LIST_HEAD(list); |
229 | 238 | ||
230 | if (dma_readl(dw, CH_EN) & dwc->mask) { | 239 | if (dma_readl(dw, CH_EN) & dwc->mask) { |
231 | dev_err(&dwc->chan.dev, | 240 | dev_err(chan2dev(&dwc->chan), |
232 | "BUG: XFER bit set, but channel not idle!\n"); | 241 | "BUG: XFER bit set, but channel not idle!\n"); |
233 | 242 | ||
234 | /* Try to continue after resetting the channel... */ | 243 | /* Try to continue after resetting the channel... */ |
@@ -273,7 +282,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) | |||
273 | return; | 282 | return; |
274 | } | 283 | } |
275 | 284 | ||
276 | dev_vdbg(&dwc->chan.dev, "scan_descriptors: llp=0x%x\n", llp); | 285 | dev_vdbg(chan2dev(&dwc->chan), "scan_descriptors: llp=0x%x\n", llp); |
277 | 286 | ||
278 | list_for_each_entry_safe(desc, _desc, &dwc->active_list, desc_node) { | 287 | list_for_each_entry_safe(desc, _desc, &dwc->active_list, desc_node) { |
279 | if (desc->lli.llp == llp) | 288 | if (desc->lli.llp == llp) |
@@ -292,7 +301,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) | |||
292 | dwc_descriptor_complete(dwc, desc); | 301 | dwc_descriptor_complete(dwc, desc); |
293 | } | 302 | } |
294 | 303 | ||
295 | dev_err(&dwc->chan.dev, | 304 | dev_err(chan2dev(&dwc->chan), |
296 | "BUG: All descriptors done, but channel not idle!\n"); | 305 | "BUG: All descriptors done, but channel not idle!\n"); |
297 | 306 | ||
298 | /* Try to continue after resetting the channel... */ | 307 | /* Try to continue after resetting the channel... */ |
@@ -308,7 +317,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) | |||
308 | 317 | ||
309 | static void dwc_dump_lli(struct dw_dma_chan *dwc, struct dw_lli *lli) | 318 | static void dwc_dump_lli(struct dw_dma_chan *dwc, struct dw_lli *lli) |
310 | { | 319 | { |
311 | dev_printk(KERN_CRIT, &dwc->chan.dev, | 320 | dev_printk(KERN_CRIT, chan2dev(&dwc->chan), |
312 | " desc: s0x%x d0x%x l0x%x c0x%x:%x\n", | 321 | " desc: s0x%x d0x%x l0x%x c0x%x:%x\n", |
313 | lli->sar, lli->dar, lli->llp, | 322 | lli->sar, lli->dar, lli->llp, |
314 | lli->ctlhi, lli->ctllo); | 323 | lli->ctlhi, lli->ctllo); |
@@ -342,9 +351,9 @@ static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc) | |||
342 | * controller flagged an error instead of scribbling over | 351 | * controller flagged an error instead of scribbling over |
343 | * random memory locations. | 352 | * random memory locations. |
344 | */ | 353 | */ |
345 | dev_printk(KERN_CRIT, &dwc->chan.dev, | 354 | dev_printk(KERN_CRIT, chan2dev(&dwc->chan), |
346 | "Bad descriptor submitted for DMA!\n"); | 355 | "Bad descriptor submitted for DMA!\n"); |
347 | dev_printk(KERN_CRIT, &dwc->chan.dev, | 356 | dev_printk(KERN_CRIT, chan2dev(&dwc->chan), |
348 | " cookie: %d\n", bad_desc->txd.cookie); | 357 | " cookie: %d\n", bad_desc->txd.cookie); |
349 | dwc_dump_lli(dwc, &bad_desc->lli); | 358 | dwc_dump_lli(dwc, &bad_desc->lli); |
350 | list_for_each_entry(child, &bad_desc->txd.tx_list, desc_node) | 359 | list_for_each_entry(child, &bad_desc->txd.tx_list, desc_node) |
@@ -442,12 +451,12 @@ static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx) | |||
442 | * for DMA. But this is hard to do in a race-free manner. | 451 | * for DMA. But this is hard to do in a race-free manner. |
443 | */ | 452 | */ |
444 | if (list_empty(&dwc->active_list)) { | 453 | if (list_empty(&dwc->active_list)) { |
445 | dev_vdbg(&tx->chan->dev, "tx_submit: started %u\n", | 454 | dev_vdbg(chan2dev(tx->chan), "tx_submit: started %u\n", |
446 | desc->txd.cookie); | 455 | desc->txd.cookie); |
447 | dwc_dostart(dwc, desc); | 456 | dwc_dostart(dwc, desc); |
448 | list_add_tail(&desc->desc_node, &dwc->active_list); | 457 | list_add_tail(&desc->desc_node, &dwc->active_list); |
449 | } else { | 458 | } else { |
450 | dev_vdbg(&tx->chan->dev, "tx_submit: queued %u\n", | 459 | dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u\n", |
451 | desc->txd.cookie); | 460 | desc->txd.cookie); |
452 | 461 | ||
453 | list_add_tail(&desc->desc_node, &dwc->queue); | 462 | list_add_tail(&desc->desc_node, &dwc->queue); |
@@ -472,11 +481,11 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, | |||
472 | unsigned int dst_width; | 481 | unsigned int dst_width; |
473 | u32 ctllo; | 482 | u32 ctllo; |
474 | 483 | ||
475 | dev_vdbg(&chan->dev, "prep_dma_memcpy d0x%x s0x%x l0x%zx f0x%lx\n", | 484 | dev_vdbg(chan2dev(chan), "prep_dma_memcpy d0x%x s0x%x l0x%zx f0x%lx\n", |
476 | dest, src, len, flags); | 485 | dest, src, len, flags); |
477 | 486 | ||
478 | if (unlikely(!len)) { | 487 | if (unlikely(!len)) { |
479 | dev_dbg(&chan->dev, "prep_dma_memcpy: length is zero!\n"); | 488 | dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n"); |
480 | return NULL; | 489 | return NULL; |
481 | } | 490 | } |
482 | 491 | ||
@@ -516,7 +525,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, | |||
516 | first = desc; | 525 | first = desc; |
517 | } else { | 526 | } else { |
518 | prev->lli.llp = desc->txd.phys; | 527 | prev->lli.llp = desc->txd.phys; |
519 | dma_sync_single_for_device(chan->dev.parent, | 528 | dma_sync_single_for_device(chan2parent(chan), |
520 | prev->txd.phys, sizeof(prev->lli), | 529 | prev->txd.phys, sizeof(prev->lli), |
521 | DMA_TO_DEVICE); | 530 | DMA_TO_DEVICE); |
522 | list_add_tail(&desc->desc_node, | 531 | list_add_tail(&desc->desc_node, |
@@ -531,7 +540,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, | |||
531 | prev->lli.ctllo |= DWC_CTLL_INT_EN; | 540 | prev->lli.ctllo |= DWC_CTLL_INT_EN; |
532 | 541 | ||
533 | prev->lli.llp = 0; | 542 | prev->lli.llp = 0; |
534 | dma_sync_single_for_device(chan->dev.parent, | 543 | dma_sync_single_for_device(chan2parent(chan), |
535 | prev->txd.phys, sizeof(prev->lli), | 544 | prev->txd.phys, sizeof(prev->lli), |
536 | DMA_TO_DEVICE); | 545 | DMA_TO_DEVICE); |
537 | 546 | ||
@@ -562,15 +571,15 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
562 | struct scatterlist *sg; | 571 | struct scatterlist *sg; |
563 | size_t total_len = 0; | 572 | size_t total_len = 0; |
564 | 573 | ||
565 | dev_vdbg(&chan->dev, "prep_dma_slave\n"); | 574 | dev_vdbg(chan2dev(chan), "prep_dma_slave\n"); |
566 | 575 | ||
567 | if (unlikely(!dws || !sg_len)) | 576 | if (unlikely(!dws || !sg_len)) |
568 | return NULL; | 577 | return NULL; |
569 | 578 | ||
570 | reg_width = dws->slave.reg_width; | 579 | reg_width = dws->reg_width; |
571 | prev = first = NULL; | 580 | prev = first = NULL; |
572 | 581 | ||
573 | sg_len = dma_map_sg(chan->dev.parent, sgl, sg_len, direction); | 582 | sg_len = dma_map_sg(chan2parent(chan), sgl, sg_len, direction); |
574 | 583 | ||
575 | switch (direction) { | 584 | switch (direction) { |
576 | case DMA_TO_DEVICE: | 585 | case DMA_TO_DEVICE: |
@@ -579,7 +588,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
579 | | DWC_CTLL_DST_FIX | 588 | | DWC_CTLL_DST_FIX |
580 | | DWC_CTLL_SRC_INC | 589 | | DWC_CTLL_SRC_INC |
581 | | DWC_CTLL_FC_M2P); | 590 | | DWC_CTLL_FC_M2P); |
582 | reg = dws->slave.tx_reg; | 591 | reg = dws->tx_reg; |
583 | for_each_sg(sgl, sg, sg_len, i) { | 592 | for_each_sg(sgl, sg, sg_len, i) { |
584 | struct dw_desc *desc; | 593 | struct dw_desc *desc; |
585 | u32 len; | 594 | u32 len; |
@@ -587,7 +596,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
587 | 596 | ||
588 | desc = dwc_desc_get(dwc); | 597 | desc = dwc_desc_get(dwc); |
589 | if (!desc) { | 598 | if (!desc) { |
590 | dev_err(&chan->dev, | 599 | dev_err(chan2dev(chan), |
591 | "not enough descriptors available\n"); | 600 | "not enough descriptors available\n"); |
592 | goto err_desc_get; | 601 | goto err_desc_get; |
593 | } | 602 | } |
@@ -607,7 +616,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
607 | first = desc; | 616 | first = desc; |
608 | } else { | 617 | } else { |
609 | prev->lli.llp = desc->txd.phys; | 618 | prev->lli.llp = desc->txd.phys; |
610 | dma_sync_single_for_device(chan->dev.parent, | 619 | dma_sync_single_for_device(chan2parent(chan), |
611 | prev->txd.phys, | 620 | prev->txd.phys, |
612 | sizeof(prev->lli), | 621 | sizeof(prev->lli), |
613 | DMA_TO_DEVICE); | 622 | DMA_TO_DEVICE); |
@@ -625,7 +634,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
625 | | DWC_CTLL_SRC_FIX | 634 | | DWC_CTLL_SRC_FIX |
626 | | DWC_CTLL_FC_P2M); | 635 | | DWC_CTLL_FC_P2M); |
627 | 636 | ||
628 | reg = dws->slave.rx_reg; | 637 | reg = dws->rx_reg; |
629 | for_each_sg(sgl, sg, sg_len, i) { | 638 | for_each_sg(sgl, sg, sg_len, i) { |
630 | struct dw_desc *desc; | 639 | struct dw_desc *desc; |
631 | u32 len; | 640 | u32 len; |
@@ -633,7 +642,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
633 | 642 | ||
634 | desc = dwc_desc_get(dwc); | 643 | desc = dwc_desc_get(dwc); |
635 | if (!desc) { | 644 | if (!desc) { |
636 | dev_err(&chan->dev, | 645 | dev_err(chan2dev(chan), |
637 | "not enough descriptors available\n"); | 646 | "not enough descriptors available\n"); |
638 | goto err_desc_get; | 647 | goto err_desc_get; |
639 | } | 648 | } |
@@ -653,7 +662,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
653 | first = desc; | 662 | first = desc; |
654 | } else { | 663 | } else { |
655 | prev->lli.llp = desc->txd.phys; | 664 | prev->lli.llp = desc->txd.phys; |
656 | dma_sync_single_for_device(chan->dev.parent, | 665 | dma_sync_single_for_device(chan2parent(chan), |
657 | prev->txd.phys, | 666 | prev->txd.phys, |
658 | sizeof(prev->lli), | 667 | sizeof(prev->lli), |
659 | DMA_TO_DEVICE); | 668 | DMA_TO_DEVICE); |
@@ -673,7 +682,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
673 | prev->lli.ctllo |= DWC_CTLL_INT_EN; | 682 | prev->lli.ctllo |= DWC_CTLL_INT_EN; |
674 | 683 | ||
675 | prev->lli.llp = 0; | 684 | prev->lli.llp = 0; |
676 | dma_sync_single_for_device(chan->dev.parent, | 685 | dma_sync_single_for_device(chan2parent(chan), |
677 | prev->txd.phys, sizeof(prev->lli), | 686 | prev->txd.phys, sizeof(prev->lli), |
678 | DMA_TO_DEVICE); | 687 | DMA_TO_DEVICE); |
679 | 688 | ||
@@ -758,29 +767,21 @@ static void dwc_issue_pending(struct dma_chan *chan) | |||
758 | spin_unlock_bh(&dwc->lock); | 767 | spin_unlock_bh(&dwc->lock); |
759 | } | 768 | } |
760 | 769 | ||
761 | static int dwc_alloc_chan_resources(struct dma_chan *chan, | 770 | static int dwc_alloc_chan_resources(struct dma_chan *chan) |
762 | struct dma_client *client) | ||
763 | { | 771 | { |
764 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); | 772 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); |
765 | struct dw_dma *dw = to_dw_dma(chan->device); | 773 | struct dw_dma *dw = to_dw_dma(chan->device); |
766 | struct dw_desc *desc; | 774 | struct dw_desc *desc; |
767 | struct dma_slave *slave; | ||
768 | struct dw_dma_slave *dws; | 775 | struct dw_dma_slave *dws; |
769 | int i; | 776 | int i; |
770 | u32 cfghi; | 777 | u32 cfghi; |
771 | u32 cfglo; | 778 | u32 cfglo; |
772 | 779 | ||
773 | dev_vdbg(&chan->dev, "alloc_chan_resources\n"); | 780 | dev_vdbg(chan2dev(chan), "alloc_chan_resources\n"); |
774 | |||
775 | /* Channels doing slave DMA can only handle one client. */ | ||
776 | if (dwc->dws || client->slave) { | ||
777 | if (chan->client_count) | ||
778 | return -EBUSY; | ||
779 | } | ||
780 | 781 | ||
781 | /* ASSERT: channel is idle */ | 782 | /* ASSERT: channel is idle */ |
782 | if (dma_readl(dw, CH_EN) & dwc->mask) { | 783 | if (dma_readl(dw, CH_EN) & dwc->mask) { |
783 | dev_dbg(&chan->dev, "DMA channel not idle?\n"); | 784 | dev_dbg(chan2dev(chan), "DMA channel not idle?\n"); |
784 | return -EIO; | 785 | return -EIO; |
785 | } | 786 | } |
786 | 787 | ||
@@ -789,23 +790,17 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan, | |||
789 | cfghi = DWC_CFGH_FIFO_MODE; | 790 | cfghi = DWC_CFGH_FIFO_MODE; |
790 | cfglo = 0; | 791 | cfglo = 0; |
791 | 792 | ||
792 | slave = client->slave; | 793 | dws = dwc->dws; |
793 | if (slave) { | 794 | if (dws) { |
794 | /* | 795 | /* |
795 | * We need controller-specific data to set up slave | 796 | * We need controller-specific data to set up slave |
796 | * transfers. | 797 | * transfers. |
797 | */ | 798 | */ |
798 | BUG_ON(!slave->dma_dev || slave->dma_dev != dw->dma.dev); | 799 | BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev); |
799 | |||
800 | dws = container_of(slave, struct dw_dma_slave, slave); | ||
801 | 800 | ||
802 | dwc->dws = dws; | ||
803 | cfghi = dws->cfg_hi; | 801 | cfghi = dws->cfg_hi; |
804 | cfglo = dws->cfg_lo; | 802 | cfglo = dws->cfg_lo; |
805 | } else { | ||
806 | dwc->dws = NULL; | ||
807 | } | 803 | } |
808 | |||
809 | channel_writel(dwc, CFG_LO, cfglo); | 804 | channel_writel(dwc, CFG_LO, cfglo); |
810 | channel_writel(dwc, CFG_HI, cfghi); | 805 | channel_writel(dwc, CFG_HI, cfghi); |
811 | 806 | ||
@@ -822,7 +817,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan, | |||
822 | 817 | ||
823 | desc = kzalloc(sizeof(struct dw_desc), GFP_KERNEL); | 818 | desc = kzalloc(sizeof(struct dw_desc), GFP_KERNEL); |
824 | if (!desc) { | 819 | if (!desc) { |
825 | dev_info(&chan->dev, | 820 | dev_info(chan2dev(chan), |
826 | "only allocated %d descriptors\n", i); | 821 | "only allocated %d descriptors\n", i); |
827 | spin_lock_bh(&dwc->lock); | 822 | spin_lock_bh(&dwc->lock); |
828 | break; | 823 | break; |
@@ -832,7 +827,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan, | |||
832 | desc->txd.tx_submit = dwc_tx_submit; | 827 | desc->txd.tx_submit = dwc_tx_submit; |
833 | desc->txd.flags = DMA_CTRL_ACK; | 828 | desc->txd.flags = DMA_CTRL_ACK; |
834 | INIT_LIST_HEAD(&desc->txd.tx_list); | 829 | INIT_LIST_HEAD(&desc->txd.tx_list); |
835 | desc->txd.phys = dma_map_single(chan->dev.parent, &desc->lli, | 830 | desc->txd.phys = dma_map_single(chan2parent(chan), &desc->lli, |
836 | sizeof(desc->lli), DMA_TO_DEVICE); | 831 | sizeof(desc->lli), DMA_TO_DEVICE); |
837 | dwc_desc_put(dwc, desc); | 832 | dwc_desc_put(dwc, desc); |
838 | 833 | ||
@@ -847,7 +842,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan, | |||
847 | 842 | ||
848 | spin_unlock_bh(&dwc->lock); | 843 | spin_unlock_bh(&dwc->lock); |
849 | 844 | ||
850 | dev_dbg(&chan->dev, | 845 | dev_dbg(chan2dev(chan), |
851 | "alloc_chan_resources allocated %d descriptors\n", i); | 846 | "alloc_chan_resources allocated %d descriptors\n", i); |
852 | 847 | ||
853 | return i; | 848 | return i; |
@@ -860,7 +855,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan) | |||
860 | struct dw_desc *desc, *_desc; | 855 | struct dw_desc *desc, *_desc; |
861 | LIST_HEAD(list); | 856 | LIST_HEAD(list); |
862 | 857 | ||
863 | dev_dbg(&chan->dev, "free_chan_resources (descs allocated=%u)\n", | 858 | dev_dbg(chan2dev(chan), "free_chan_resources (descs allocated=%u)\n", |
864 | dwc->descs_allocated); | 859 | dwc->descs_allocated); |
865 | 860 | ||
866 | /* ASSERT: channel is idle */ | 861 | /* ASSERT: channel is idle */ |
@@ -881,13 +876,13 @@ static void dwc_free_chan_resources(struct dma_chan *chan) | |||
881 | spin_unlock_bh(&dwc->lock); | 876 | spin_unlock_bh(&dwc->lock); |
882 | 877 | ||
883 | list_for_each_entry_safe(desc, _desc, &list, desc_node) { | 878 | list_for_each_entry_safe(desc, _desc, &list, desc_node) { |
884 | dev_vdbg(&chan->dev, " freeing descriptor %p\n", desc); | 879 | dev_vdbg(chan2dev(chan), " freeing descriptor %p\n", desc); |
885 | dma_unmap_single(chan->dev.parent, desc->txd.phys, | 880 | dma_unmap_single(chan2parent(chan), desc->txd.phys, |
886 | sizeof(desc->lli), DMA_TO_DEVICE); | 881 | sizeof(desc->lli), DMA_TO_DEVICE); |
887 | kfree(desc); | 882 | kfree(desc); |
888 | } | 883 | } |
889 | 884 | ||
890 | dev_vdbg(&chan->dev, "free_chan_resources done\n"); | 885 | dev_vdbg(chan2dev(chan), "free_chan_resources done\n"); |
891 | } | 886 | } |
892 | 887 | ||
893 | /*----------------------------------------------------------------------*/ | 888 | /*----------------------------------------------------------------------*/ |
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 0b95dcce447e..ca70a21afc68 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c | |||
@@ -366,8 +366,7 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor( | |||
366 | * | 366 | * |
367 | * Return - The number of descriptors allocated. | 367 | * Return - The number of descriptors allocated. |
368 | */ | 368 | */ |
369 | static int fsl_dma_alloc_chan_resources(struct dma_chan *chan, | 369 | static int fsl_dma_alloc_chan_resources(struct dma_chan *chan) |
370 | struct dma_client *client) | ||
371 | { | 370 | { |
372 | struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan); | 371 | struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan); |
373 | 372 | ||
@@ -823,7 +822,7 @@ static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev, | |||
823 | */ | 822 | */ |
824 | WARN_ON(fdev->feature != new_fsl_chan->feature); | 823 | WARN_ON(fdev->feature != new_fsl_chan->feature); |
825 | 824 | ||
826 | new_fsl_chan->dev = &new_fsl_chan->common.dev; | 825 | new_fsl_chan->dev = &new_fsl_chan->common.dev->device; |
827 | new_fsl_chan->reg_base = ioremap(new_fsl_chan->reg.start, | 826 | new_fsl_chan->reg_base = ioremap(new_fsl_chan->reg.start, |
828 | new_fsl_chan->reg.end - new_fsl_chan->reg.start + 1); | 827 | new_fsl_chan->reg.end - new_fsl_chan->reg.start + 1); |
829 | 828 | ||
diff --git a/drivers/dma/ioat.c b/drivers/dma/ioat.c index 9b16a3af9a0a..4105d6575b64 100644 --- a/drivers/dma/ioat.c +++ b/drivers/dma/ioat.c | |||
@@ -75,60 +75,10 @@ static int ioat_dca_enabled = 1; | |||
75 | module_param(ioat_dca_enabled, int, 0644); | 75 | module_param(ioat_dca_enabled, int, 0644); |
76 | MODULE_PARM_DESC(ioat_dca_enabled, "control support of dca service (default: 1)"); | 76 | MODULE_PARM_DESC(ioat_dca_enabled, "control support of dca service (default: 1)"); |
77 | 77 | ||
78 | static int ioat_setup_functionality(struct pci_dev *pdev, void __iomem *iobase) | ||
79 | { | ||
80 | struct ioat_device *device = pci_get_drvdata(pdev); | ||
81 | u8 version; | ||
82 | int err = 0; | ||
83 | |||
84 | version = readb(iobase + IOAT_VER_OFFSET); | ||
85 | switch (version) { | ||
86 | case IOAT_VER_1_2: | ||
87 | device->dma = ioat_dma_probe(pdev, iobase); | ||
88 | if (device->dma && ioat_dca_enabled) | ||
89 | device->dca = ioat_dca_init(pdev, iobase); | ||
90 | break; | ||
91 | case IOAT_VER_2_0: | ||
92 | device->dma = ioat_dma_probe(pdev, iobase); | ||
93 | if (device->dma && ioat_dca_enabled) | ||
94 | device->dca = ioat2_dca_init(pdev, iobase); | ||
95 | break; | ||
96 | case IOAT_VER_3_0: | ||
97 | device->dma = ioat_dma_probe(pdev, iobase); | ||
98 | if (device->dma && ioat_dca_enabled) | ||
99 | device->dca = ioat3_dca_init(pdev, iobase); | ||
100 | break; | ||
101 | default: | ||
102 | err = -ENODEV; | ||
103 | break; | ||
104 | } | ||
105 | if (!device->dma) | ||
106 | err = -ENODEV; | ||
107 | return err; | ||
108 | } | ||
109 | |||
110 | static void ioat_shutdown_functionality(struct pci_dev *pdev) | ||
111 | { | ||
112 | struct ioat_device *device = pci_get_drvdata(pdev); | ||
113 | |||
114 | dev_err(&pdev->dev, "Removing dma and dca services\n"); | ||
115 | if (device->dca) { | ||
116 | unregister_dca_provider(device->dca); | ||
117 | free_dca_provider(device->dca); | ||
118 | device->dca = NULL; | ||
119 | } | ||
120 | |||
121 | if (device->dma) { | ||
122 | ioat_dma_remove(device->dma); | ||
123 | device->dma = NULL; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | static struct pci_driver ioat_pci_driver = { | 78 | static struct pci_driver ioat_pci_driver = { |
128 | .name = "ioatdma", | 79 | .name = "ioatdma", |
129 | .id_table = ioat_pci_tbl, | 80 | .id_table = ioat_pci_tbl, |
130 | .probe = ioat_probe, | 81 | .probe = ioat_probe, |
131 | .shutdown = ioat_shutdown_functionality, | ||
132 | .remove = __devexit_p(ioat_remove), | 82 | .remove = __devexit_p(ioat_remove), |
133 | }; | 83 | }; |
134 | 84 | ||
@@ -179,7 +129,29 @@ static int __devinit ioat_probe(struct pci_dev *pdev, | |||
179 | 129 | ||
180 | pci_set_master(pdev); | 130 | pci_set_master(pdev); |
181 | 131 | ||
182 | err = ioat_setup_functionality(pdev, iobase); | 132 | switch (readb(iobase + IOAT_VER_OFFSET)) { |
133 | case IOAT_VER_1_2: | ||
134 | device->dma = ioat_dma_probe(pdev, iobase); | ||
135 | if (device->dma && ioat_dca_enabled) | ||
136 | device->dca = ioat_dca_init(pdev, iobase); | ||
137 | break; | ||
138 | case IOAT_VER_2_0: | ||
139 | device->dma = ioat_dma_probe(pdev, iobase); | ||
140 | if (device->dma && ioat_dca_enabled) | ||
141 | device->dca = ioat2_dca_init(pdev, iobase); | ||
142 | break; | ||
143 | case IOAT_VER_3_0: | ||
144 | device->dma = ioat_dma_probe(pdev, iobase); | ||
145 | if (device->dma && ioat_dca_enabled) | ||
146 | device->dca = ioat3_dca_init(pdev, iobase); | ||
147 | break; | ||
148 | default: | ||
149 | err = -ENODEV; | ||
150 | break; | ||
151 | } | ||
152 | if (!device->dma) | ||
153 | err = -ENODEV; | ||
154 | |||
183 | if (err) | 155 | if (err) |
184 | goto err_version; | 156 | goto err_version; |
185 | 157 | ||
@@ -198,17 +170,21 @@ err_enable_device: | |||
198 | return err; | 170 | return err; |
199 | } | 171 | } |
200 | 172 | ||
201 | /* | ||
202 | * It is unsafe to remove this module: if removed while a requested | ||
203 | * dma is outstanding, esp. from tcp, it is possible to hang while | ||
204 | * waiting for something that will never finish. However, if you're | ||
205 | * feeling lucky, this usually works just fine. | ||
206 | */ | ||
207 | static void __devexit ioat_remove(struct pci_dev *pdev) | 173 | static void __devexit ioat_remove(struct pci_dev *pdev) |
208 | { | 174 | { |
209 | struct ioat_device *device = pci_get_drvdata(pdev); | 175 | struct ioat_device *device = pci_get_drvdata(pdev); |
210 | 176 | ||
211 | ioat_shutdown_functionality(pdev); | 177 | dev_err(&pdev->dev, "Removing dma and dca services\n"); |
178 | if (device->dca) { | ||
179 | unregister_dca_provider(device->dca); | ||
180 | free_dca_provider(device->dca); | ||
181 | device->dca = NULL; | ||
182 | } | ||
183 | |||
184 | if (device->dma) { | ||
185 | ioat_dma_remove(device->dma); | ||
186 | device->dma = NULL; | ||
187 | } | ||
212 | 188 | ||
213 | kfree(device); | 189 | kfree(device); |
214 | } | 190 | } |
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index 6607fdd00b1c..b3759c4b6536 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c | |||
@@ -734,8 +734,7 @@ static void ioat2_dma_massage_chan_desc(struct ioat_dma_chan *ioat_chan) | |||
734 | * ioat_dma_alloc_chan_resources - returns the number of allocated descriptors | 734 | * ioat_dma_alloc_chan_resources - returns the number of allocated descriptors |
735 | * @chan: the channel to be filled out | 735 | * @chan: the channel to be filled out |
736 | */ | 736 | */ |
737 | static int ioat_dma_alloc_chan_resources(struct dma_chan *chan, | 737 | static int ioat_dma_alloc_chan_resources(struct dma_chan *chan) |
738 | struct dma_client *client) | ||
739 | { | 738 | { |
740 | struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); | 739 | struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); |
741 | struct ioat_desc_sw *desc; | 740 | struct ioat_desc_sw *desc; |
@@ -1341,12 +1340,11 @@ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan) | |||
1341 | */ | 1340 | */ |
1342 | #define IOAT_TEST_SIZE 2000 | 1341 | #define IOAT_TEST_SIZE 2000 |
1343 | 1342 | ||
1344 | DECLARE_COMPLETION(test_completion); | ||
1345 | static void ioat_dma_test_callback(void *dma_async_param) | 1343 | static void ioat_dma_test_callback(void *dma_async_param) |
1346 | { | 1344 | { |
1347 | printk(KERN_ERR "ioatdma: ioat_dma_test_callback(%p)\n", | 1345 | struct completion *cmp = dma_async_param; |
1348 | dma_async_param); | 1346 | |
1349 | complete(&test_completion); | 1347 | complete(cmp); |
1350 | } | 1348 | } |
1351 | 1349 | ||
1352 | /** | 1350 | /** |
@@ -1363,6 +1361,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device) | |||
1363 | dma_addr_t dma_dest, dma_src; | 1361 | dma_addr_t dma_dest, dma_src; |
1364 | dma_cookie_t cookie; | 1362 | dma_cookie_t cookie; |
1365 | int err = 0; | 1363 | int err = 0; |
1364 | struct completion cmp; | ||
1366 | 1365 | ||
1367 | src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL); | 1366 | src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL); |
1368 | if (!src) | 1367 | if (!src) |
@@ -1381,7 +1380,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device) | |||
1381 | dma_chan = container_of(device->common.channels.next, | 1380 | dma_chan = container_of(device->common.channels.next, |
1382 | struct dma_chan, | 1381 | struct dma_chan, |
1383 | device_node); | 1382 | device_node); |
1384 | if (device->common.device_alloc_chan_resources(dma_chan, NULL) < 1) { | 1383 | if (device->common.device_alloc_chan_resources(dma_chan) < 1) { |
1385 | dev_err(&device->pdev->dev, | 1384 | dev_err(&device->pdev->dev, |
1386 | "selftest cannot allocate chan resource\n"); | 1385 | "selftest cannot allocate chan resource\n"); |
1387 | err = -ENODEV; | 1386 | err = -ENODEV; |
@@ -1402,8 +1401,9 @@ static int ioat_dma_self_test(struct ioatdma_device *device) | |||
1402 | } | 1401 | } |
1403 | 1402 | ||
1404 | async_tx_ack(tx); | 1403 | async_tx_ack(tx); |
1404 | init_completion(&cmp); | ||
1405 | tx->callback = ioat_dma_test_callback; | 1405 | tx->callback = ioat_dma_test_callback; |
1406 | tx->callback_param = (void *)0x8086; | 1406 | tx->callback_param = &cmp; |
1407 | cookie = tx->tx_submit(tx); | 1407 | cookie = tx->tx_submit(tx); |
1408 | if (cookie < 0) { | 1408 | if (cookie < 0) { |
1409 | dev_err(&device->pdev->dev, | 1409 | dev_err(&device->pdev->dev, |
@@ -1413,7 +1413,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device) | |||
1413 | } | 1413 | } |
1414 | device->common.device_issue_pending(dma_chan); | 1414 | device->common.device_issue_pending(dma_chan); |
1415 | 1415 | ||
1416 | wait_for_completion_timeout(&test_completion, msecs_to_jiffies(3000)); | 1416 | wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000)); |
1417 | 1417 | ||
1418 | if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL) | 1418 | if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL) |
1419 | != DMA_SUCCESS) { | 1419 | != DMA_SUCCESS) { |
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index 6be317262200..ea5440dd10dc 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c | |||
@@ -24,7 +24,6 @@ | |||
24 | 24 | ||
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/async_tx.h> | ||
28 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
29 | #include <linux/dma-mapping.h> | 28 | #include <linux/dma-mapping.h> |
30 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
@@ -116,7 +115,7 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc, | |||
116 | } | 115 | } |
117 | 116 | ||
118 | /* run dependent operations */ | 117 | /* run dependent operations */ |
119 | async_tx_run_dependencies(&desc->async_tx); | 118 | dma_run_dependencies(&desc->async_tx); |
120 | 119 | ||
121 | return cookie; | 120 | return cookie; |
122 | } | 121 | } |
@@ -270,8 +269,6 @@ static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan) | |||
270 | break; | 269 | break; |
271 | } | 270 | } |
272 | 271 | ||
273 | BUG_ON(!seen_current); | ||
274 | |||
275 | if (cookie > 0) { | 272 | if (cookie > 0) { |
276 | iop_chan->completed_cookie = cookie; | 273 | iop_chan->completed_cookie = cookie; |
277 | pr_debug("\tcompleted cookie %d\n", cookie); | 274 | pr_debug("\tcompleted cookie %d\n", cookie); |
@@ -471,8 +468,7 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan); | |||
471 | * greater than 2x the number slots needed to satisfy a device->max_xor | 468 | * greater than 2x the number slots needed to satisfy a device->max_xor |
472 | * request. | 469 | * request. |
473 | * */ | 470 | * */ |
474 | static int iop_adma_alloc_chan_resources(struct dma_chan *chan, | 471 | static int iop_adma_alloc_chan_resources(struct dma_chan *chan) |
475 | struct dma_client *client) | ||
476 | { | 472 | { |
477 | char *hw_desc; | 473 | char *hw_desc; |
478 | int idx; | 474 | int idx; |
@@ -866,7 +862,7 @@ static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device) | |||
866 | dma_chan = container_of(device->common.channels.next, | 862 | dma_chan = container_of(device->common.channels.next, |
867 | struct dma_chan, | 863 | struct dma_chan, |
868 | device_node); | 864 | device_node); |
869 | if (iop_adma_alloc_chan_resources(dma_chan, NULL) < 1) { | 865 | if (iop_adma_alloc_chan_resources(dma_chan) < 1) { |
870 | err = -ENODEV; | 866 | err = -ENODEV; |
871 | goto out; | 867 | goto out; |
872 | } | 868 | } |
@@ -964,7 +960,7 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device) | |||
964 | dma_chan = container_of(device->common.channels.next, | 960 | dma_chan = container_of(device->common.channels.next, |
965 | struct dma_chan, | 961 | struct dma_chan, |
966 | device_node); | 962 | device_node); |
967 | if (iop_adma_alloc_chan_resources(dma_chan, NULL) < 1) { | 963 | if (iop_adma_alloc_chan_resources(dma_chan) < 1) { |
968 | err = -ENODEV; | 964 | err = -ENODEV; |
969 | goto out; | 965 | goto out; |
970 | } | 966 | } |
@@ -1115,26 +1111,13 @@ static int __devexit iop_adma_remove(struct platform_device *dev) | |||
1115 | struct iop_adma_device *device = platform_get_drvdata(dev); | 1111 | struct iop_adma_device *device = platform_get_drvdata(dev); |
1116 | struct dma_chan *chan, *_chan; | 1112 | struct dma_chan *chan, *_chan; |
1117 | struct iop_adma_chan *iop_chan; | 1113 | struct iop_adma_chan *iop_chan; |
1118 | int i; | ||
1119 | struct iop_adma_platform_data *plat_data = dev->dev.platform_data; | 1114 | struct iop_adma_platform_data *plat_data = dev->dev.platform_data; |
1120 | 1115 | ||
1121 | dma_async_device_unregister(&device->common); | 1116 | dma_async_device_unregister(&device->common); |
1122 | 1117 | ||
1123 | for (i = 0; i < 3; i++) { | ||
1124 | unsigned int irq; | ||
1125 | irq = platform_get_irq(dev, i); | ||
1126 | free_irq(irq, device); | ||
1127 | } | ||
1128 | |||
1129 | dma_free_coherent(&dev->dev, plat_data->pool_size, | 1118 | dma_free_coherent(&dev->dev, plat_data->pool_size, |
1130 | device->dma_desc_pool_virt, device->dma_desc_pool); | 1119 | device->dma_desc_pool_virt, device->dma_desc_pool); |
1131 | 1120 | ||
1132 | do { | ||
1133 | struct resource *res; | ||
1134 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
1135 | release_mem_region(res->start, res->end - res->start); | ||
1136 | } while (0); | ||
1137 | |||
1138 | list_for_each_entry_safe(chan, _chan, &device->common.channels, | 1121 | list_for_each_entry_safe(chan, _chan, &device->common.channels, |
1139 | device_node) { | 1122 | device_node) { |
1140 | iop_chan = to_iop_adma_chan(chan); | 1123 | iop_chan = to_iop_adma_chan(chan); |
@@ -1255,7 +1238,6 @@ static int __devinit iop_adma_probe(struct platform_device *pdev) | |||
1255 | spin_lock_init(&iop_chan->lock); | 1238 | spin_lock_init(&iop_chan->lock); |
1256 | INIT_LIST_HEAD(&iop_chan->chain); | 1239 | INIT_LIST_HEAD(&iop_chan->chain); |
1257 | INIT_LIST_HEAD(&iop_chan->all_slots); | 1240 | INIT_LIST_HEAD(&iop_chan->all_slots); |
1258 | INIT_RCU_HEAD(&iop_chan->common.rcu); | ||
1259 | iop_chan->common.device = dma_dev; | 1241 | iop_chan->common.device = dma_dev; |
1260 | list_add_tail(&iop_chan->common.device_node, &dma_dev->channels); | 1242 | list_add_tail(&iop_chan->common.device_node, &dma_dev->channels); |
1261 | 1243 | ||
@@ -1431,16 +1413,12 @@ static int __init iop_adma_init (void) | |||
1431 | return platform_driver_register(&iop_adma_driver); | 1413 | return platform_driver_register(&iop_adma_driver); |
1432 | } | 1414 | } |
1433 | 1415 | ||
1434 | /* it's currently unsafe to unload this module */ | ||
1435 | #if 0 | ||
1436 | static void __exit iop_adma_exit (void) | 1416 | static void __exit iop_adma_exit (void) |
1437 | { | 1417 | { |
1438 | platform_driver_unregister(&iop_adma_driver); | 1418 | platform_driver_unregister(&iop_adma_driver); |
1439 | return; | 1419 | return; |
1440 | } | 1420 | } |
1441 | module_exit(iop_adma_exit); | 1421 | module_exit(iop_adma_exit); |
1442 | #endif | ||
1443 | |||
1444 | module_init(iop_adma_init); | 1422 | module_init(iop_adma_init); |
1445 | 1423 | ||
1446 | MODULE_AUTHOR("Intel Corporation"); | 1424 | MODULE_AUTHOR("Intel Corporation"); |
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index bcda17426411..d35cbd1ff0b3 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c | |||
@@ -18,7 +18,6 @@ | |||
18 | 18 | ||
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/async_tx.h> | ||
22 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
23 | #include <linux/dma-mapping.h> | 22 | #include <linux/dma-mapping.h> |
24 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
@@ -340,7 +339,7 @@ mv_xor_run_tx_complete_actions(struct mv_xor_desc_slot *desc, | |||
340 | } | 339 | } |
341 | 340 | ||
342 | /* run dependent operations */ | 341 | /* run dependent operations */ |
343 | async_tx_run_dependencies(&desc->async_tx); | 342 | dma_run_dependencies(&desc->async_tx); |
344 | 343 | ||
345 | return cookie; | 344 | return cookie; |
346 | } | 345 | } |
@@ -607,8 +606,7 @@ submit_done: | |||
607 | } | 606 | } |
608 | 607 | ||
609 | /* returns the number of allocated descriptors */ | 608 | /* returns the number of allocated descriptors */ |
610 | static int mv_xor_alloc_chan_resources(struct dma_chan *chan, | 609 | static int mv_xor_alloc_chan_resources(struct dma_chan *chan) |
611 | struct dma_client *client) | ||
612 | { | 610 | { |
613 | char *hw_desc; | 611 | char *hw_desc; |
614 | int idx; | 612 | int idx; |
@@ -958,7 +956,7 @@ static int __devinit mv_xor_memcpy_self_test(struct mv_xor_device *device) | |||
958 | dma_chan = container_of(device->common.channels.next, | 956 | dma_chan = container_of(device->common.channels.next, |
959 | struct dma_chan, | 957 | struct dma_chan, |
960 | device_node); | 958 | device_node); |
961 | if (mv_xor_alloc_chan_resources(dma_chan, NULL) < 1) { | 959 | if (mv_xor_alloc_chan_resources(dma_chan) < 1) { |
962 | err = -ENODEV; | 960 | err = -ENODEV; |
963 | goto out; | 961 | goto out; |
964 | } | 962 | } |
@@ -1053,7 +1051,7 @@ mv_xor_xor_self_test(struct mv_xor_device *device) | |||
1053 | dma_chan = container_of(device->common.channels.next, | 1051 | dma_chan = container_of(device->common.channels.next, |
1054 | struct dma_chan, | 1052 | struct dma_chan, |
1055 | device_node); | 1053 | device_node); |
1056 | if (mv_xor_alloc_chan_resources(dma_chan, NULL) < 1) { | 1054 | if (mv_xor_alloc_chan_resources(dma_chan) < 1) { |
1057 | err = -ENODEV; | 1055 | err = -ENODEV; |
1058 | goto out; | 1056 | goto out; |
1059 | } | 1057 | } |
@@ -1221,7 +1219,6 @@ static int __devinit mv_xor_probe(struct platform_device *pdev) | |||
1221 | INIT_LIST_HEAD(&mv_chan->chain); | 1219 | INIT_LIST_HEAD(&mv_chan->chain); |
1222 | INIT_LIST_HEAD(&mv_chan->completed_slots); | 1220 | INIT_LIST_HEAD(&mv_chan->completed_slots); |
1223 | INIT_LIST_HEAD(&mv_chan->all_slots); | 1221 | INIT_LIST_HEAD(&mv_chan->all_slots); |
1224 | INIT_RCU_HEAD(&mv_chan->common.rcu); | ||
1225 | mv_chan->common.device = dma_dev; | 1222 | mv_chan->common.device = dma_dev; |
1226 | 1223 | ||
1227 | list_add_tail(&mv_chan->common.device_node, &dma_dev->channels); | 1224 | list_add_tail(&mv_chan->common.device_node, &dma_dev->channels); |
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 1e97916914ad..76bfe16c09b1 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
@@ -55,7 +55,6 @@ enum atmel_mci_state { | |||
55 | 55 | ||
56 | struct atmel_mci_dma { | 56 | struct atmel_mci_dma { |
57 | #ifdef CONFIG_MMC_ATMELMCI_DMA | 57 | #ifdef CONFIG_MMC_ATMELMCI_DMA |
58 | struct dma_client client; | ||
59 | struct dma_chan *chan; | 58 | struct dma_chan *chan; |
60 | struct dma_async_tx_descriptor *data_desc; | 59 | struct dma_async_tx_descriptor *data_desc; |
61 | #endif | 60 | #endif |
@@ -593,10 +592,8 @@ atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data) | |||
593 | 592 | ||
594 | /* If we don't have a channel, we can't do DMA */ | 593 | /* If we don't have a channel, we can't do DMA */ |
595 | chan = host->dma.chan; | 594 | chan = host->dma.chan; |
596 | if (chan) { | 595 | if (chan) |
597 | dma_chan_get(chan); | ||
598 | host->data_chan = chan; | 596 | host->data_chan = chan; |
599 | } | ||
600 | 597 | ||
601 | if (!chan) | 598 | if (!chan) |
602 | return -ENODEV; | 599 | return -ENODEV; |
@@ -1443,60 +1440,6 @@ static irqreturn_t atmci_detect_interrupt(int irq, void *dev_id) | |||
1443 | return IRQ_HANDLED; | 1440 | return IRQ_HANDLED; |
1444 | } | 1441 | } |
1445 | 1442 | ||
1446 | #ifdef CONFIG_MMC_ATMELMCI_DMA | ||
1447 | |||
1448 | static inline struct atmel_mci * | ||
1449 | dma_client_to_atmel_mci(struct dma_client *client) | ||
1450 | { | ||
1451 | return container_of(client, struct atmel_mci, dma.client); | ||
1452 | } | ||
1453 | |||
1454 | static enum dma_state_client atmci_dma_event(struct dma_client *client, | ||
1455 | struct dma_chan *chan, enum dma_state state) | ||
1456 | { | ||
1457 | struct atmel_mci *host; | ||
1458 | enum dma_state_client ret = DMA_NAK; | ||
1459 | |||
1460 | host = dma_client_to_atmel_mci(client); | ||
1461 | |||
1462 | switch (state) { | ||
1463 | case DMA_RESOURCE_AVAILABLE: | ||
1464 | spin_lock_bh(&host->lock); | ||
1465 | if (!host->dma.chan) { | ||
1466 | host->dma.chan = chan; | ||
1467 | ret = DMA_ACK; | ||
1468 | } | ||
1469 | spin_unlock_bh(&host->lock); | ||
1470 | |||
1471 | if (ret == DMA_ACK) | ||
1472 | dev_info(&host->pdev->dev, | ||
1473 | "Using %s for DMA transfers\n", | ||
1474 | chan->dev.bus_id); | ||
1475 | break; | ||
1476 | |||
1477 | case DMA_RESOURCE_REMOVED: | ||
1478 | spin_lock_bh(&host->lock); | ||
1479 | if (host->dma.chan == chan) { | ||
1480 | host->dma.chan = NULL; | ||
1481 | ret = DMA_ACK; | ||
1482 | } | ||
1483 | spin_unlock_bh(&host->lock); | ||
1484 | |||
1485 | if (ret == DMA_ACK) | ||
1486 | dev_info(&host->pdev->dev, | ||
1487 | "Lost %s, falling back to PIO\n", | ||
1488 | chan->dev.bus_id); | ||
1489 | break; | ||
1490 | |||
1491 | default: | ||
1492 | break; | ||
1493 | } | ||
1494 | |||
1495 | |||
1496 | return ret; | ||
1497 | } | ||
1498 | #endif /* CONFIG_MMC_ATMELMCI_DMA */ | ||
1499 | |||
1500 | static int __init atmci_init_slot(struct atmel_mci *host, | 1443 | static int __init atmci_init_slot(struct atmel_mci *host, |
1501 | struct mci_slot_pdata *slot_data, unsigned int id, | 1444 | struct mci_slot_pdata *slot_data, unsigned int id, |
1502 | u32 sdc_reg) | 1445 | u32 sdc_reg) |
@@ -1600,6 +1543,18 @@ static void __exit atmci_cleanup_slot(struct atmel_mci_slot *slot, | |||
1600 | mmc_free_host(slot->mmc); | 1543 | mmc_free_host(slot->mmc); |
1601 | } | 1544 | } |
1602 | 1545 | ||
1546 | #ifdef CONFIG_MMC_ATMELMCI_DMA | ||
1547 | static bool filter(struct dma_chan *chan, void *slave) | ||
1548 | { | ||
1549 | struct dw_dma_slave *dws = slave; | ||
1550 | |||
1551 | if (dws->dma_dev == chan->device->dev) | ||
1552 | return true; | ||
1553 | else | ||
1554 | return false; | ||
1555 | } | ||
1556 | #endif | ||
1557 | |||
1603 | static int __init atmci_probe(struct platform_device *pdev) | 1558 | static int __init atmci_probe(struct platform_device *pdev) |
1604 | { | 1559 | { |
1605 | struct mci_platform_data *pdata; | 1560 | struct mci_platform_data *pdata; |
@@ -1652,22 +1607,20 @@ static int __init atmci_probe(struct platform_device *pdev) | |||
1652 | goto err_request_irq; | 1607 | goto err_request_irq; |
1653 | 1608 | ||
1654 | #ifdef CONFIG_MMC_ATMELMCI_DMA | 1609 | #ifdef CONFIG_MMC_ATMELMCI_DMA |
1655 | if (pdata->dma_slave) { | 1610 | if (pdata->dma_slave.dma_dev) { |
1656 | struct dma_slave *slave = pdata->dma_slave; | 1611 | struct dw_dma_slave *dws = &pdata->dma_slave; |
1612 | dma_cap_mask_t mask; | ||
1657 | 1613 | ||
1658 | slave->tx_reg = regs->start + MCI_TDR; | 1614 | dws->tx_reg = regs->start + MCI_TDR; |
1659 | slave->rx_reg = regs->start + MCI_RDR; | 1615 | dws->rx_reg = regs->start + MCI_RDR; |
1660 | 1616 | ||
1661 | /* Try to grab a DMA channel */ | 1617 | /* Try to grab a DMA channel */ |
1662 | host->dma.client.event_callback = atmci_dma_event; | 1618 | dma_cap_zero(mask); |
1663 | dma_cap_set(DMA_SLAVE, host->dma.client.cap_mask); | 1619 | dma_cap_set(DMA_SLAVE, mask); |
1664 | host->dma.client.slave = slave; | 1620 | host->dma.chan = dma_request_channel(mask, filter, dws); |
1665 | |||
1666 | dma_async_client_register(&host->dma.client); | ||
1667 | dma_async_client_chan_request(&host->dma.client); | ||
1668 | } else { | ||
1669 | dev_notice(&pdev->dev, "DMA not available, using PIO\n"); | ||
1670 | } | 1621 | } |
1622 | if (!host->dma.chan) | ||
1623 | dev_notice(&pdev->dev, "DMA not available, using PIO\n"); | ||
1671 | #endif /* CONFIG_MMC_ATMELMCI_DMA */ | 1624 | #endif /* CONFIG_MMC_ATMELMCI_DMA */ |
1672 | 1625 | ||
1673 | platform_set_drvdata(pdev, host); | 1626 | platform_set_drvdata(pdev, host); |
@@ -1699,8 +1652,8 @@ static int __init atmci_probe(struct platform_device *pdev) | |||
1699 | 1652 | ||
1700 | err_init_slot: | 1653 | err_init_slot: |
1701 | #ifdef CONFIG_MMC_ATMELMCI_DMA | 1654 | #ifdef CONFIG_MMC_ATMELMCI_DMA |
1702 | if (pdata->dma_slave) | 1655 | if (host->dma.chan) |
1703 | dma_async_client_unregister(&host->dma.client); | 1656 | dma_release_channel(host->dma.chan); |
1704 | #endif | 1657 | #endif |
1705 | free_irq(irq, host); | 1658 | free_irq(irq, host); |
1706 | err_request_irq: | 1659 | err_request_irq: |
@@ -1731,8 +1684,8 @@ static int __exit atmci_remove(struct platform_device *pdev) | |||
1731 | clk_disable(host->mck); | 1684 | clk_disable(host->mck); |
1732 | 1685 | ||
1733 | #ifdef CONFIG_MMC_ATMELMCI_DMA | 1686 | #ifdef CONFIG_MMC_ATMELMCI_DMA |
1734 | if (host->dma.client.slave) | 1687 | if (host->dma.chan) |
1735 | dma_async_client_unregister(&host->dma.client); | 1688 | dma_release_channel(host->dma.chan); |
1736 | #endif | 1689 | #endif |
1737 | 1690 | ||
1738 | free_irq(platform_get_irq(pdev, 0), host); | 1691 | free_irq(platform_get_irq(pdev, 0), host); |
@@ -1761,7 +1714,7 @@ static void __exit atmci_exit(void) | |||
1761 | platform_driver_unregister(&atmci_driver); | 1714 | platform_driver_unregister(&atmci_driver); |
1762 | } | 1715 | } |
1763 | 1716 | ||
1764 | module_init(atmci_init); | 1717 | late_initcall(atmci_init); /* try to load after dma driver when built-in */ |
1765 | module_exit(atmci_exit); | 1718 | module_exit(atmci_exit); |
1766 | 1719 | ||
1767 | MODULE_DESCRIPTION("Atmel Multimedia Card Interface driver"); | 1720 | MODULE_DESCRIPTION("Atmel Multimedia Card Interface driver"); |
diff --git a/include/linux/async_tx.h b/include/linux/async_tx.h index 0f50d4cc4360..45f6297821bd 100644 --- a/include/linux/async_tx.h +++ b/include/linux/async_tx.h | |||
@@ -59,9 +59,7 @@ enum async_tx_flags { | |||
59 | }; | 59 | }; |
60 | 60 | ||
61 | #ifdef CONFIG_DMA_ENGINE | 61 | #ifdef CONFIG_DMA_ENGINE |
62 | void async_tx_issue_pending_all(void); | 62 | #define async_tx_issue_pending_all dma_issue_pending_all |
63 | enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx); | ||
64 | void async_tx_run_dependencies(struct dma_async_tx_descriptor *tx); | ||
65 | #ifdef CONFIG_ARCH_HAS_ASYNC_TX_FIND_CHANNEL | 63 | #ifdef CONFIG_ARCH_HAS_ASYNC_TX_FIND_CHANNEL |
66 | #include <asm/async_tx.h> | 64 | #include <asm/async_tx.h> |
67 | #else | 65 | #else |
@@ -77,19 +75,6 @@ static inline void async_tx_issue_pending_all(void) | |||
77 | do { } while (0); | 75 | do { } while (0); |
78 | } | 76 | } |
79 | 77 | ||
80 | static inline enum dma_status | ||
81 | dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) | ||
82 | { | ||
83 | return DMA_SUCCESS; | ||
84 | } | ||
85 | |||
86 | static inline void | ||
87 | async_tx_run_dependencies(struct dma_async_tx_descriptor *tx, | ||
88 | struct dma_chan *host_chan) | ||
89 | { | ||
90 | do { } while (0); | ||
91 | } | ||
92 | |||
93 | static inline struct dma_chan * | 78 | static inline struct dma_chan * |
94 | async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx, | 79 | async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx, |
95 | enum dma_transaction_type tx_type, struct page **dst, int dst_count, | 80 | enum dma_transaction_type tx_type, struct page **dst, int dst_count, |
diff --git a/include/linux/atmel-mci.h b/include/linux/atmel-mci.h index 2a2213eefd85..2f1f95737acb 100644 --- a/include/linux/atmel-mci.h +++ b/include/linux/atmel-mci.h | |||
@@ -3,7 +3,7 @@ | |||
3 | 3 | ||
4 | #define ATMEL_MCI_MAX_NR_SLOTS 2 | 4 | #define ATMEL_MCI_MAX_NR_SLOTS 2 |
5 | 5 | ||
6 | struct dma_slave; | 6 | #include <linux/dw_dmac.h> |
7 | 7 | ||
8 | /** | 8 | /** |
9 | * struct mci_slot_pdata - board-specific per-slot configuration | 9 | * struct mci_slot_pdata - board-specific per-slot configuration |
@@ -28,11 +28,11 @@ struct mci_slot_pdata { | |||
28 | 28 | ||
29 | /** | 29 | /** |
30 | * struct mci_platform_data - board-specific MMC/SDcard configuration | 30 | * struct mci_platform_data - board-specific MMC/SDcard configuration |
31 | * @dma_slave: DMA slave interface to use in data transfers, or NULL. | 31 | * @dma_slave: DMA slave interface to use in data transfers. |
32 | * @slot: Per-slot configuration data. | 32 | * @slot: Per-slot configuration data. |
33 | */ | 33 | */ |
34 | struct mci_platform_data { | 34 | struct mci_platform_data { |
35 | struct dma_slave *dma_slave; | 35 | struct dw_dma_slave dma_slave; |
36 | struct mci_slot_pdata slot[ATMEL_MCI_MAX_NR_SLOTS]; | 36 | struct mci_slot_pdata slot[ATMEL_MCI_MAX_NR_SLOTS]; |
37 | }; | 37 | }; |
38 | 38 | ||
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index adb0b084eb5a..64dea2ab326c 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h | |||
@@ -29,32 +29,6 @@ | |||
29 | #include <linux/dma-mapping.h> | 29 | #include <linux/dma-mapping.h> |
30 | 30 | ||
31 | /** | 31 | /** |
32 | * enum dma_state - resource PNP/power management state | ||
33 | * @DMA_RESOURCE_SUSPEND: DMA device going into low power state | ||
34 | * @DMA_RESOURCE_RESUME: DMA device returning to full power | ||
35 | * @DMA_RESOURCE_AVAILABLE: DMA device available to the system | ||
36 | * @DMA_RESOURCE_REMOVED: DMA device removed from the system | ||
37 | */ | ||
38 | enum dma_state { | ||
39 | DMA_RESOURCE_SUSPEND, | ||
40 | DMA_RESOURCE_RESUME, | ||
41 | DMA_RESOURCE_AVAILABLE, | ||
42 | DMA_RESOURCE_REMOVED, | ||
43 | }; | ||
44 | |||
45 | /** | ||
46 | * enum dma_state_client - state of the channel in the client | ||
47 | * @DMA_ACK: client would like to use, or was using this channel | ||
48 | * @DMA_DUP: client has already seen this channel, or is not using this channel | ||
49 | * @DMA_NAK: client does not want to see any more channels | ||
50 | */ | ||
51 | enum dma_state_client { | ||
52 | DMA_ACK, | ||
53 | DMA_DUP, | ||
54 | DMA_NAK, | ||
55 | }; | ||
56 | |||
57 | /** | ||
58 | * typedef dma_cookie_t - an opaque DMA cookie | 32 | * typedef dma_cookie_t - an opaque DMA cookie |
59 | * | 33 | * |
60 | * if dma_cookie_t is >0 it's a DMA request cookie, <0 it's an error code | 34 | * if dma_cookie_t is >0 it's a DMA request cookie, <0 it's an error code |
@@ -89,23 +63,13 @@ enum dma_transaction_type { | |||
89 | DMA_MEMSET, | 63 | DMA_MEMSET, |
90 | DMA_MEMCPY_CRC32C, | 64 | DMA_MEMCPY_CRC32C, |
91 | DMA_INTERRUPT, | 65 | DMA_INTERRUPT, |
66 | DMA_PRIVATE, | ||
92 | DMA_SLAVE, | 67 | DMA_SLAVE, |
93 | }; | 68 | }; |
94 | 69 | ||
95 | /* last transaction type for creation of the capabilities mask */ | 70 | /* last transaction type for creation of the capabilities mask */ |
96 | #define DMA_TX_TYPE_END (DMA_SLAVE + 1) | 71 | #define DMA_TX_TYPE_END (DMA_SLAVE + 1) |
97 | 72 | ||
98 | /** | ||
99 | * enum dma_slave_width - DMA slave register access width. | ||
100 | * @DMA_SLAVE_WIDTH_8BIT: Do 8-bit slave register accesses | ||
101 | * @DMA_SLAVE_WIDTH_16BIT: Do 16-bit slave register accesses | ||
102 | * @DMA_SLAVE_WIDTH_32BIT: Do 32-bit slave register accesses | ||
103 | */ | ||
104 | enum dma_slave_width { | ||
105 | DMA_SLAVE_WIDTH_8BIT, | ||
106 | DMA_SLAVE_WIDTH_16BIT, | ||
107 | DMA_SLAVE_WIDTH_32BIT, | ||
108 | }; | ||
109 | 73 | ||
110 | /** | 74 | /** |
111 | * enum dma_ctrl_flags - DMA flags to augment operation preparation, | 75 | * enum dma_ctrl_flags - DMA flags to augment operation preparation, |
@@ -132,32 +96,6 @@ enum dma_ctrl_flags { | |||
132 | typedef struct { DECLARE_BITMAP(bits, DMA_TX_TYPE_END); } dma_cap_mask_t; | 96 | typedef struct { DECLARE_BITMAP(bits, DMA_TX_TYPE_END); } dma_cap_mask_t; |
133 | 97 | ||
134 | /** | 98 | /** |
135 | * struct dma_slave - Information about a DMA slave | ||
136 | * @dev: device acting as DMA slave | ||
137 | * @dma_dev: required DMA master device. If non-NULL, the client can not be | ||
138 | * bound to other masters than this. | ||
139 | * @tx_reg: physical address of data register used for | ||
140 | * memory-to-peripheral transfers | ||
141 | * @rx_reg: physical address of data register used for | ||
142 | * peripheral-to-memory transfers | ||
143 | * @reg_width: peripheral register width | ||
144 | * | ||
145 | * If dma_dev is non-NULL, the client can not be bound to other DMA | ||
146 | * masters than the one corresponding to this device. The DMA master | ||
147 | * driver may use this to determine if there is controller-specific | ||
148 | * data wrapped around this struct. Drivers of platform code that sets | ||
149 | * the dma_dev field must therefore make sure to use an appropriate | ||
150 | * controller-specific dma slave structure wrapping this struct. | ||
151 | */ | ||
152 | struct dma_slave { | ||
153 | struct device *dev; | ||
154 | struct device *dma_dev; | ||
155 | dma_addr_t tx_reg; | ||
156 | dma_addr_t rx_reg; | ||
157 | enum dma_slave_width reg_width; | ||
158 | }; | ||
159 | |||
160 | /** | ||
161 | * struct dma_chan_percpu - the per-CPU part of struct dma_chan | 99 | * struct dma_chan_percpu - the per-CPU part of struct dma_chan |
162 | * @refcount: local_t used for open-coded "bigref" counting | 100 | * @refcount: local_t used for open-coded "bigref" counting |
163 | * @memcpy_count: transaction counter | 101 | * @memcpy_count: transaction counter |
@@ -165,7 +103,6 @@ struct dma_slave { | |||
165 | */ | 103 | */ |
166 | 104 | ||
167 | struct dma_chan_percpu { | 105 | struct dma_chan_percpu { |
168 | local_t refcount; | ||
169 | /* stats */ | 106 | /* stats */ |
170 | unsigned long memcpy_count; | 107 | unsigned long memcpy_count; |
171 | unsigned long bytes_transferred; | 108 | unsigned long bytes_transferred; |
@@ -176,13 +113,14 @@ struct dma_chan_percpu { | |||
176 | * @device: ptr to the dma device who supplies this channel, always !%NULL | 113 | * @device: ptr to the dma device who supplies this channel, always !%NULL |
177 | * @cookie: last cookie value returned to client | 114 | * @cookie: last cookie value returned to client |
178 | * @chan_id: channel ID for sysfs | 115 | * @chan_id: channel ID for sysfs |
179 | * @class_dev: class device for sysfs | 116 | * @dev: class device for sysfs |
180 | * @refcount: kref, used in "bigref" slow-mode | 117 | * @refcount: kref, used in "bigref" slow-mode |
181 | * @slow_ref: indicates that the DMA channel is free | 118 | * @slow_ref: indicates that the DMA channel is free |
182 | * @rcu: the DMA channel's RCU head | 119 | * @rcu: the DMA channel's RCU head |
183 | * @device_node: used to add this to the device chan list | 120 | * @device_node: used to add this to the device chan list |
184 | * @local: per-cpu pointer to a struct dma_chan_percpu | 121 | * @local: per-cpu pointer to a struct dma_chan_percpu |
185 | * @client-count: how many clients are using this channel | 122 | * @client-count: how many clients are using this channel |
123 | * @table_count: number of appearances in the mem-to-mem allocation table | ||
186 | */ | 124 | */ |
187 | struct dma_chan { | 125 | struct dma_chan { |
188 | struct dma_device *device; | 126 | struct dma_device *device; |
@@ -190,73 +128,47 @@ struct dma_chan { | |||
190 | 128 | ||
191 | /* sysfs */ | 129 | /* sysfs */ |
192 | int chan_id; | 130 | int chan_id; |
193 | struct device dev; | 131 | struct dma_chan_dev *dev; |
194 | |||
195 | struct kref refcount; | ||
196 | int slow_ref; | ||
197 | struct rcu_head rcu; | ||
198 | 132 | ||
199 | struct list_head device_node; | 133 | struct list_head device_node; |
200 | struct dma_chan_percpu *local; | 134 | struct dma_chan_percpu *local; |
201 | int client_count; | 135 | int client_count; |
136 | int table_count; | ||
202 | }; | 137 | }; |
203 | 138 | ||
204 | #define to_dma_chan(p) container_of(p, struct dma_chan, dev) | 139 | /** |
205 | 140 | * struct dma_chan_dev - relate sysfs device node to backing channel device | |
206 | void dma_chan_cleanup(struct kref *kref); | 141 | * @chan - driver channel device |
207 | 142 | * @device - sysfs device | |
208 | static inline void dma_chan_get(struct dma_chan *chan) | 143 | * @dev_id - parent dma_device dev_id |
209 | { | 144 | * @idr_ref - reference count to gate release of dma_device dev_id |
210 | if (unlikely(chan->slow_ref)) | 145 | */ |
211 | kref_get(&chan->refcount); | 146 | struct dma_chan_dev { |
212 | else { | 147 | struct dma_chan *chan; |
213 | local_inc(&(per_cpu_ptr(chan->local, get_cpu())->refcount)); | 148 | struct device device; |
214 | put_cpu(); | 149 | int dev_id; |
215 | } | 150 | atomic_t *idr_ref; |
216 | } | 151 | }; |
217 | 152 | ||
218 | static inline void dma_chan_put(struct dma_chan *chan) | 153 | static inline const char *dma_chan_name(struct dma_chan *chan) |
219 | { | 154 | { |
220 | if (unlikely(chan->slow_ref)) | 155 | return dev_name(&chan->dev->device); |
221 | kref_put(&chan->refcount, dma_chan_cleanup); | ||
222 | else { | ||
223 | local_dec(&(per_cpu_ptr(chan->local, get_cpu())->refcount)); | ||
224 | put_cpu(); | ||
225 | } | ||
226 | } | 156 | } |
227 | 157 | ||
228 | /* | 158 | void dma_chan_cleanup(struct kref *kref); |
229 | * typedef dma_event_callback - function pointer to a DMA event callback | ||
230 | * For each channel added to the system this routine is called for each client. | ||
231 | * If the client would like to use the channel it returns '1' to signal (ack) | ||
232 | * the dmaengine core to take out a reference on the channel and its | ||
233 | * corresponding device. A client must not 'ack' an available channel more | ||
234 | * than once. When a channel is removed all clients are notified. If a client | ||
235 | * is using the channel it must 'ack' the removal. A client must not 'ack' a | ||
236 | * removed channel more than once. | ||
237 | * @client - 'this' pointer for the client context | ||
238 | * @chan - channel to be acted upon | ||
239 | * @state - available or removed | ||
240 | */ | ||
241 | struct dma_client; | ||
242 | typedef enum dma_state_client (*dma_event_callback) (struct dma_client *client, | ||
243 | struct dma_chan *chan, enum dma_state state); | ||
244 | 159 | ||
245 | /** | 160 | /** |
246 | * struct dma_client - info on the entity making use of DMA services | 161 | * typedef dma_filter_fn - callback filter for dma_request_channel |
247 | * @event_callback: func ptr to call when something happens | 162 | * @chan: channel to be reviewed |
248 | * @cap_mask: only return channels that satisfy the requested capabilities | 163 | * @filter_param: opaque parameter passed through dma_request_channel |
249 | * a value of zero corresponds to any capability | 164 | * |
250 | * @slave: data for preparing slave transfer. Must be non-NULL iff the | 165 | * When this optional parameter is specified in a call to dma_request_channel a |
251 | * DMA_SLAVE capability is requested. | 166 | * suitable channel is passed to this routine for further dispositioning before |
252 | * @global_node: list_head for global dma_client_list | 167 | * being returned. Where 'suitable' indicates a non-busy channel that |
168 | * satisfies the given capability mask. It returns 'true' to indicate that the | ||
169 | * channel is suitable. | ||
253 | */ | 170 | */ |
254 | struct dma_client { | 171 | typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param); |
255 | dma_event_callback event_callback; | ||
256 | dma_cap_mask_t cap_mask; | ||
257 | struct dma_slave *slave; | ||
258 | struct list_head global_node; | ||
259 | }; | ||
260 | 172 | ||
261 | typedef void (*dma_async_tx_callback)(void *dma_async_param); | 173 | typedef void (*dma_async_tx_callback)(void *dma_async_param); |
262 | /** | 174 | /** |
@@ -323,14 +235,10 @@ struct dma_device { | |||
323 | dma_cap_mask_t cap_mask; | 235 | dma_cap_mask_t cap_mask; |
324 | int max_xor; | 236 | int max_xor; |
325 | 237 | ||
326 | struct kref refcount; | ||
327 | struct completion done; | ||
328 | |||
329 | int dev_id; | 238 | int dev_id; |
330 | struct device *dev; | 239 | struct device *dev; |
331 | 240 | ||
332 | int (*device_alloc_chan_resources)(struct dma_chan *chan, | 241 | int (*device_alloc_chan_resources)(struct dma_chan *chan); |
333 | struct dma_client *client); | ||
334 | void (*device_free_chan_resources)(struct dma_chan *chan); | 242 | void (*device_free_chan_resources)(struct dma_chan *chan); |
335 | 243 | ||
336 | struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)( | 244 | struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)( |
@@ -362,9 +270,8 @@ struct dma_device { | |||
362 | 270 | ||
363 | /* --- public DMA engine API --- */ | 271 | /* --- public DMA engine API --- */ |
364 | 272 | ||
365 | void dma_async_client_register(struct dma_client *client); | 273 | void dmaengine_get(void); |
366 | void dma_async_client_unregister(struct dma_client *client); | 274 | void dmaengine_put(void); |
367 | void dma_async_client_chan_request(struct dma_client *client); | ||
368 | dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan, | 275 | dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan, |
369 | void *dest, void *src, size_t len); | 276 | void *dest, void *src, size_t len); |
370 | dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan, | 277 | dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan, |
@@ -406,6 +313,12 @@ __dma_cap_set(enum dma_transaction_type tx_type, dma_cap_mask_t *dstp) | |||
406 | set_bit(tx_type, dstp->bits); | 313 | set_bit(tx_type, dstp->bits); |
407 | } | 314 | } |
408 | 315 | ||
316 | #define dma_cap_zero(mask) __dma_cap_zero(&(mask)) | ||
317 | static inline void __dma_cap_zero(dma_cap_mask_t *dstp) | ||
318 | { | ||
319 | bitmap_zero(dstp->bits, DMA_TX_TYPE_END); | ||
320 | } | ||
321 | |||
409 | #define dma_has_cap(tx, mask) __dma_has_cap((tx), &(mask)) | 322 | #define dma_has_cap(tx, mask) __dma_has_cap((tx), &(mask)) |
410 | static inline int | 323 | static inline int |
411 | __dma_has_cap(enum dma_transaction_type tx_type, dma_cap_mask_t *srcp) | 324 | __dma_has_cap(enum dma_transaction_type tx_type, dma_cap_mask_t *srcp) |
@@ -475,11 +388,25 @@ static inline enum dma_status dma_async_is_complete(dma_cookie_t cookie, | |||
475 | } | 388 | } |
476 | 389 | ||
477 | enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie); | 390 | enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie); |
391 | #ifdef CONFIG_DMA_ENGINE | ||
392 | enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx); | ||
393 | #else | ||
394 | static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) | ||
395 | { | ||
396 | return DMA_SUCCESS; | ||
397 | } | ||
398 | #endif | ||
478 | 399 | ||
479 | /* --- DMA device --- */ | 400 | /* --- DMA device --- */ |
480 | 401 | ||
481 | int dma_async_device_register(struct dma_device *device); | 402 | int dma_async_device_register(struct dma_device *device); |
482 | void dma_async_device_unregister(struct dma_device *device); | 403 | void dma_async_device_unregister(struct dma_device *device); |
404 | void dma_run_dependencies(struct dma_async_tx_descriptor *tx); | ||
405 | struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type); | ||
406 | void dma_issue_pending_all(void); | ||
407 | #define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y) | ||
408 | struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param); | ||
409 | void dma_release_channel(struct dma_chan *chan); | ||
483 | 410 | ||
484 | /* --- Helper iov-locking functions --- */ | 411 | /* --- Helper iov-locking functions --- */ |
485 | 412 | ||
diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h index 04d217b442bf..d797dde247f7 100644 --- a/include/linux/dw_dmac.h +++ b/include/linux/dw_dmac.h | |||
@@ -22,14 +22,34 @@ struct dw_dma_platform_data { | |||
22 | }; | 22 | }; |
23 | 23 | ||
24 | /** | 24 | /** |
25 | * enum dw_dma_slave_width - DMA slave register access width. | ||
26 | * @DMA_SLAVE_WIDTH_8BIT: Do 8-bit slave register accesses | ||
27 | * @DMA_SLAVE_WIDTH_16BIT: Do 16-bit slave register accesses | ||
28 | * @DMA_SLAVE_WIDTH_32BIT: Do 32-bit slave register accesses | ||
29 | */ | ||
30 | enum dw_dma_slave_width { | ||
31 | DW_DMA_SLAVE_WIDTH_8BIT, | ||
32 | DW_DMA_SLAVE_WIDTH_16BIT, | ||
33 | DW_DMA_SLAVE_WIDTH_32BIT, | ||
34 | }; | ||
35 | |||
36 | /** | ||
25 | * struct dw_dma_slave - Controller-specific information about a slave | 37 | * struct dw_dma_slave - Controller-specific information about a slave |
26 | * @slave: Generic information about the slave | 38 | * |
27 | * @ctl_lo: Platform-specific initializer for the CTL_LO register | 39 | * @dma_dev: required DMA master device |
40 | * @tx_reg: physical address of data register used for | ||
41 | * memory-to-peripheral transfers | ||
42 | * @rx_reg: physical address of data register used for | ||
43 | * peripheral-to-memory transfers | ||
44 | * @reg_width: peripheral register width | ||
28 | * @cfg_hi: Platform-specific initializer for the CFG_HI register | 45 | * @cfg_hi: Platform-specific initializer for the CFG_HI register |
29 | * @cfg_lo: Platform-specific initializer for the CFG_LO register | 46 | * @cfg_lo: Platform-specific initializer for the CFG_LO register |
30 | */ | 47 | */ |
31 | struct dw_dma_slave { | 48 | struct dw_dma_slave { |
32 | struct dma_slave slave; | 49 | struct device *dma_dev; |
50 | dma_addr_t tx_reg; | ||
51 | dma_addr_t rx_reg; | ||
52 | enum dw_dma_slave_width reg_width; | ||
33 | u32 cfg_hi; | 53 | u32 cfg_hi; |
34 | u32 cfg_lo; | 54 | u32 cfg_lo; |
35 | }; | 55 | }; |
@@ -54,9 +74,4 @@ struct dw_dma_slave { | |||
54 | #define DWC_CFGL_HS_DST_POL (1 << 18) /* dst handshake active low */ | 74 | #define DWC_CFGL_HS_DST_POL (1 << 18) /* dst handshake active low */ |
55 | #define DWC_CFGL_HS_SRC_POL (1 << 19) /* src handshake active low */ | 75 | #define DWC_CFGL_HS_SRC_POL (1 << 19) /* src handshake active low */ |
56 | 76 | ||
57 | static inline struct dw_dma_slave *to_dw_dma_slave(struct dma_slave *slave) | ||
58 | { | ||
59 | return container_of(slave, struct dw_dma_slave, slave); | ||
60 | } | ||
61 | |||
62 | #endif /* DW_DMAC_H */ | 77 | #endif /* DW_DMAC_H */ |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 114091be8872..f24556813375 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -1125,9 +1125,6 @@ struct softnet_data | |||
1125 | struct sk_buff *completion_queue; | 1125 | struct sk_buff *completion_queue; |
1126 | 1126 | ||
1127 | struct napi_struct backlog; | 1127 | struct napi_struct backlog; |
1128 | #ifdef CONFIG_NET_DMA | ||
1129 | struct dma_chan *net_dma; | ||
1130 | #endif | ||
1131 | }; | 1128 | }; |
1132 | 1129 | ||
1133 | DECLARE_PER_CPU(struct softnet_data,softnet_data); | 1130 | DECLARE_PER_CPU(struct softnet_data,softnet_data); |
diff --git a/include/net/netdma.h b/include/net/netdma.h index f28c6e064e8f..8ba8ce284eeb 100644 --- a/include/net/netdma.h +++ b/include/net/netdma.h | |||
@@ -24,17 +24,6 @@ | |||
24 | #include <linux/dmaengine.h> | 24 | #include <linux/dmaengine.h> |
25 | #include <linux/skbuff.h> | 25 | #include <linux/skbuff.h> |
26 | 26 | ||
27 | static inline struct dma_chan *get_softnet_dma(void) | ||
28 | { | ||
29 | struct dma_chan *chan; | ||
30 | rcu_read_lock(); | ||
31 | chan = rcu_dereference(__get_cpu_var(softnet_data).net_dma); | ||
32 | if (chan) | ||
33 | dma_chan_get(chan); | ||
34 | rcu_read_unlock(); | ||
35 | return chan; | ||
36 | } | ||
37 | |||
38 | int dma_skb_copy_datagram_iovec(struct dma_chan* chan, | 27 | int dma_skb_copy_datagram_iovec(struct dma_chan* chan, |
39 | struct sk_buff *skb, int offset, struct iovec *to, | 28 | struct sk_buff *skb, int offset, struct iovec *to, |
40 | size_t len, struct dma_pinned_list *pinned_list); | 29 | size_t len, struct dma_pinned_list *pinned_list); |
diff --git a/net/core/dev.c b/net/core/dev.c index bab8bcedd62e..5f736f1ceeae 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -170,25 +170,6 @@ static DEFINE_SPINLOCK(ptype_lock); | |||
170 | static struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly; | 170 | static struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly; |
171 | static struct list_head ptype_all __read_mostly; /* Taps */ | 171 | static struct list_head ptype_all __read_mostly; /* Taps */ |
172 | 172 | ||
173 | #ifdef CONFIG_NET_DMA | ||
174 | struct net_dma { | ||
175 | struct dma_client client; | ||
176 | spinlock_t lock; | ||
177 | cpumask_t channel_mask; | ||
178 | struct dma_chan **channels; | ||
179 | }; | ||
180 | |||
181 | static enum dma_state_client | ||
182 | netdev_dma_event(struct dma_client *client, struct dma_chan *chan, | ||
183 | enum dma_state state); | ||
184 | |||
185 | static struct net_dma net_dma = { | ||
186 | .client = { | ||
187 | .event_callback = netdev_dma_event, | ||
188 | }, | ||
189 | }; | ||
190 | #endif | ||
191 | |||
192 | /* | 173 | /* |
193 | * The @dev_base_head list is protected by @dev_base_lock and the rtnl | 174 | * The @dev_base_head list is protected by @dev_base_lock and the rtnl |
194 | * semaphore. | 175 | * semaphore. |
@@ -2754,14 +2735,7 @@ out: | |||
2754 | * There may not be any more sk_buffs coming right now, so push | 2735 | * There may not be any more sk_buffs coming right now, so push |
2755 | * any pending DMA copies to hardware | 2736 | * any pending DMA copies to hardware |
2756 | */ | 2737 | */ |
2757 | if (!cpus_empty(net_dma.channel_mask)) { | 2738 | dma_issue_pending_all(); |
2758 | int chan_idx; | ||
2759 | for_each_cpu_mask_nr(chan_idx, net_dma.channel_mask) { | ||
2760 | struct dma_chan *chan = net_dma.channels[chan_idx]; | ||
2761 | if (chan) | ||
2762 | dma_async_memcpy_issue_pending(chan); | ||
2763 | } | ||
2764 | } | ||
2765 | #endif | 2739 | #endif |
2766 | 2740 | ||
2767 | return; | 2741 | return; |
@@ -4952,122 +4926,6 @@ static int dev_cpu_callback(struct notifier_block *nfb, | |||
4952 | return NOTIFY_OK; | 4926 | return NOTIFY_OK; |
4953 | } | 4927 | } |
4954 | 4928 | ||
4955 | #ifdef CONFIG_NET_DMA | ||
4956 | /** | ||
4957 | * net_dma_rebalance - try to maintain one DMA channel per CPU | ||
4958 | * @net_dma: DMA client and associated data (lock, channels, channel_mask) | ||
4959 | * | ||
4960 | * This is called when the number of channels allocated to the net_dma client | ||
4961 | * changes. The net_dma client tries to have one DMA channel per CPU. | ||
4962 | */ | ||
4963 | |||
4964 | static void net_dma_rebalance(struct net_dma *net_dma) | ||
4965 | { | ||
4966 | unsigned int cpu, i, n, chan_idx; | ||
4967 | struct dma_chan *chan; | ||
4968 | |||
4969 | if (cpus_empty(net_dma->channel_mask)) { | ||
4970 | for_each_online_cpu(cpu) | ||
4971 | rcu_assign_pointer(per_cpu(softnet_data, cpu).net_dma, NULL); | ||
4972 | return; | ||
4973 | } | ||
4974 | |||
4975 | i = 0; | ||
4976 | cpu = first_cpu(cpu_online_map); | ||
4977 | |||
4978 | for_each_cpu_mask_nr(chan_idx, net_dma->channel_mask) { | ||
4979 | chan = net_dma->channels[chan_idx]; | ||
4980 | |||
4981 | n = ((num_online_cpus() / cpus_weight(net_dma->channel_mask)) | ||
4982 | + (i < (num_online_cpus() % | ||
4983 | cpus_weight(net_dma->channel_mask)) ? 1 : 0)); | ||
4984 | |||
4985 | while(n) { | ||
4986 | per_cpu(softnet_data, cpu).net_dma = chan; | ||
4987 | cpu = next_cpu(cpu, cpu_online_map); | ||
4988 | n--; | ||
4989 | } | ||
4990 | i++; | ||
4991 | } | ||
4992 | } | ||
4993 | |||
4994 | /** | ||
4995 | * netdev_dma_event - event callback for the net_dma_client | ||
4996 | * @client: should always be net_dma_client | ||
4997 | * @chan: DMA channel for the event | ||
4998 | * @state: DMA state to be handled | ||
4999 | */ | ||
5000 | static enum dma_state_client | ||
5001 | netdev_dma_event(struct dma_client *client, struct dma_chan *chan, | ||
5002 | enum dma_state state) | ||
5003 | { | ||
5004 | int i, found = 0, pos = -1; | ||
5005 | struct net_dma *net_dma = | ||
5006 | container_of(client, struct net_dma, client); | ||
5007 | enum dma_state_client ack = DMA_DUP; /* default: take no action */ | ||
5008 | |||
5009 | spin_lock(&net_dma->lock); | ||
5010 | switch (state) { | ||
5011 | case DMA_RESOURCE_AVAILABLE: | ||
5012 | for (i = 0; i < nr_cpu_ids; i++) | ||
5013 | if (net_dma->channels[i] == chan) { | ||
5014 | found = 1; | ||
5015 | break; | ||
5016 | } else if (net_dma->channels[i] == NULL && pos < 0) | ||
5017 | pos = i; | ||
5018 | |||
5019 | if (!found && pos >= 0) { | ||
5020 | ack = DMA_ACK; | ||
5021 | net_dma->channels[pos] = chan; | ||
5022 | cpu_set(pos, net_dma->channel_mask); | ||
5023 | net_dma_rebalance(net_dma); | ||
5024 | } | ||
5025 | break; | ||
5026 | case DMA_RESOURCE_REMOVED: | ||
5027 | for (i = 0; i < nr_cpu_ids; i++) | ||
5028 | if (net_dma->channels[i] == chan) { | ||
5029 | found = 1; | ||
5030 | pos = i; | ||
5031 | break; | ||
5032 | } | ||
5033 | |||
5034 | if (found) { | ||
5035 | ack = DMA_ACK; | ||
5036 | cpu_clear(pos, net_dma->channel_mask); | ||
5037 | net_dma->channels[i] = NULL; | ||
5038 | net_dma_rebalance(net_dma); | ||
5039 | } | ||
5040 | break; | ||
5041 | default: | ||
5042 | break; | ||
5043 | } | ||
5044 | spin_unlock(&net_dma->lock); | ||
5045 | |||
5046 | return ack; | ||
5047 | } | ||
5048 | |||
5049 | /** | ||
5050 | * netdev_dma_register - register the networking subsystem as a DMA client | ||
5051 | */ | ||
5052 | static int __init netdev_dma_register(void) | ||
5053 | { | ||
5054 | net_dma.channels = kzalloc(nr_cpu_ids * sizeof(struct net_dma), | ||
5055 | GFP_KERNEL); | ||
5056 | if (unlikely(!net_dma.channels)) { | ||
5057 | printk(KERN_NOTICE | ||
5058 | "netdev_dma: no memory for net_dma.channels\n"); | ||
5059 | return -ENOMEM; | ||
5060 | } | ||
5061 | spin_lock_init(&net_dma.lock); | ||
5062 | dma_cap_set(DMA_MEMCPY, net_dma.client.cap_mask); | ||
5063 | dma_async_client_register(&net_dma.client); | ||
5064 | dma_async_client_chan_request(&net_dma.client); | ||
5065 | return 0; | ||
5066 | } | ||
5067 | |||
5068 | #else | ||
5069 | static int __init netdev_dma_register(void) { return -ENODEV; } | ||
5070 | #endif /* CONFIG_NET_DMA */ | ||
5071 | 4929 | ||
5072 | /** | 4930 | /** |
5073 | * netdev_increment_features - increment feature set by one | 4931 | * netdev_increment_features - increment feature set by one |
@@ -5287,14 +5145,15 @@ static int __init net_dev_init(void) | |||
5287 | if (register_pernet_device(&default_device_ops)) | 5145 | if (register_pernet_device(&default_device_ops)) |
5288 | goto out; | 5146 | goto out; |
5289 | 5147 | ||
5290 | netdev_dma_register(); | ||
5291 | |||
5292 | open_softirq(NET_TX_SOFTIRQ, net_tx_action); | 5148 | open_softirq(NET_TX_SOFTIRQ, net_tx_action); |
5293 | open_softirq(NET_RX_SOFTIRQ, net_rx_action); | 5149 | open_softirq(NET_RX_SOFTIRQ, net_rx_action); |
5294 | 5150 | ||
5295 | hotcpu_notifier(dev_cpu_callback, 0); | 5151 | hotcpu_notifier(dev_cpu_callback, 0); |
5296 | dst_init(); | 5152 | dst_init(); |
5297 | dev_mcast_init(); | 5153 | dev_mcast_init(); |
5154 | #ifdef CONFIG_NET_DMA | ||
5155 | dmaengine_get(); | ||
5156 | #endif | ||
5298 | rc = 0; | 5157 | rc = 0; |
5299 | out: | 5158 | out: |
5300 | return rc; | 5159 | return rc; |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index bd6ff907d9e4..ce572f9dff02 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -1313,7 +1313,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
1313 | if ((available < target) && | 1313 | if ((available < target) && |
1314 | (len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) && | 1314 | (len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) && |
1315 | !sysctl_tcp_low_latency && | 1315 | !sysctl_tcp_low_latency && |
1316 | __get_cpu_var(softnet_data).net_dma) { | 1316 | dma_find_channel(DMA_MEMCPY)) { |
1317 | preempt_enable_no_resched(); | 1317 | preempt_enable_no_resched(); |
1318 | tp->ucopy.pinned_list = | 1318 | tp->ucopy.pinned_list = |
1319 | dma_pin_iovec_pages(msg->msg_iov, len); | 1319 | dma_pin_iovec_pages(msg->msg_iov, len); |
@@ -1523,7 +1523,7 @@ do_prequeue: | |||
1523 | if (!(flags & MSG_TRUNC)) { | 1523 | if (!(flags & MSG_TRUNC)) { |
1524 | #ifdef CONFIG_NET_DMA | 1524 | #ifdef CONFIG_NET_DMA |
1525 | if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) | 1525 | if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) |
1526 | tp->ucopy.dma_chan = get_softnet_dma(); | 1526 | tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY); |
1527 | 1527 | ||
1528 | if (tp->ucopy.dma_chan) { | 1528 | if (tp->ucopy.dma_chan) { |
1529 | tp->ucopy.dma_cookie = dma_skb_copy_datagram_iovec( | 1529 | tp->ucopy.dma_cookie = dma_skb_copy_datagram_iovec( |
@@ -1628,7 +1628,6 @@ skip_copy: | |||
1628 | 1628 | ||
1629 | /* Safe to free early-copied skbs now */ | 1629 | /* Safe to free early-copied skbs now */ |
1630 | __skb_queue_purge(&sk->sk_async_wait_queue); | 1630 | __skb_queue_purge(&sk->sk_async_wait_queue); |
1631 | dma_chan_put(tp->ucopy.dma_chan); | ||
1632 | tp->ucopy.dma_chan = NULL; | 1631 | tp->ucopy.dma_chan = NULL; |
1633 | } | 1632 | } |
1634 | if (tp->ucopy.pinned_list) { | 1633 | if (tp->ucopy.pinned_list) { |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 99b7ecbe8893..a6961d75c7ea 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -5005,7 +5005,7 @@ static int tcp_dma_try_early_copy(struct sock *sk, struct sk_buff *skb, | |||
5005 | return 0; | 5005 | return 0; |
5006 | 5006 | ||
5007 | if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) | 5007 | if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) |
5008 | tp->ucopy.dma_chan = get_softnet_dma(); | 5008 | tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY); |
5009 | 5009 | ||
5010 | if (tp->ucopy.dma_chan && skb_csum_unnecessary(skb)) { | 5010 | if (tp->ucopy.dma_chan && skb_csum_unnecessary(skb)) { |
5011 | 5011 | ||
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 9d839fa9331e..19d7b429a262 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1594,7 +1594,7 @@ process: | |||
1594 | #ifdef CONFIG_NET_DMA | 1594 | #ifdef CONFIG_NET_DMA |
1595 | struct tcp_sock *tp = tcp_sk(sk); | 1595 | struct tcp_sock *tp = tcp_sk(sk); |
1596 | if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) | 1596 | if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) |
1597 | tp->ucopy.dma_chan = get_softnet_dma(); | 1597 | tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY); |
1598 | if (tp->ucopy.dma_chan) | 1598 | if (tp->ucopy.dma_chan) |
1599 | ret = tcp_v4_do_rcv(sk, skb); | 1599 | ret = tcp_v4_do_rcv(sk, skb); |
1600 | else | 1600 | else |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 1297306d729c..e5b85d45bee8 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1675,7 +1675,7 @@ process: | |||
1675 | #ifdef CONFIG_NET_DMA | 1675 | #ifdef CONFIG_NET_DMA |
1676 | struct tcp_sock *tp = tcp_sk(sk); | 1676 | struct tcp_sock *tp = tcp_sk(sk); |
1677 | if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) | 1677 | if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) |
1678 | tp->ucopy.dma_chan = get_softnet_dma(); | 1678 | tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY); |
1679 | if (tp->ucopy.dma_chan) | 1679 | if (tp->ucopy.dma_chan) |
1680 | ret = tcp_v6_do_rcv(sk, skb); | 1680 | ret = tcp_v6_do_rcv(sk, skb); |
1681 | else | 1681 | else |