diff options
author | Dan Williams <dan.j.williams@intel.com> | 2007-01-02 13:10:43 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2007-07-13 11:06:11 -0400 |
commit | 7405f74badf46b5d023c5d2b670b4471525f6c91 (patch) | |
tree | 20dd20571637dba1c2b04c7b13ac208c33b5706b /drivers/dma/ioatdma.c | |
parent | 428ed6024fa74a271142f3257966e9b5e1cb37a1 (diff) |
dmaengine: refactor dmaengine around dma_async_tx_descriptor
The current dmaengine interface defines mutliple routines per operation,
i.e. dma_async_memcpy_buf_to_buf, dma_async_memcpy_buf_to_page etc. Adding
more operation types (xor, crc, etc) to this model would result in an
unmanageable number of method permutations.
Are we really going to add a set of hooks for each DMA engine
whizbang feature?
- Jeff Garzik
The descriptor creation process is refactored using the new common
dma_async_tx_descriptor structure. Instead of per driver
do_<operation>_<dest>_to_<src> methods, drivers integrate
dma_async_tx_descriptor into their private software descriptor and then
define a 'prep' routine per operation. The prep routine allocates a
descriptor and ensures that the tx_set_src, tx_set_dest, tx_submit routines
are valid. Descriptor creation and submission becomes:
struct dma_device *dev;
struct dma_chan *chan;
struct dma_async_tx_descriptor *tx;
tx = dev->device_prep_dma_<operation>(chan, len, int_flag)
tx->tx_set_src(dma_addr_t, tx, index /* for multi-source ops */)
tx->tx_set_dest(dma_addr_t, tx, index)
tx->tx_submit(tx)
In addition to the refactoring, dma_async_tx_descriptor also lays the
groundwork for definining cross-channel-operation dependencies, and a
callback facility for asynchronous notification of operation completion.
Changelog:
* drop dma mapping methods, suggested by Chris Leech
* fix ioat_dma_dependency_added, also caught by Andrew Morton
* fix dma_sync_wait, change from Andrew Morton
* uninline large functions, change from Andrew Morton
* add tx->callback = NULL to dmaengine calls to interoperate with async_tx
calls
* hookup ioat_tx_submit
* convert channel capabilities to a 'cpumask_t like' bitmap
* removed DMA_TX_ARRAY_INIT, no longer needed
* checkpatch.pl fixes
* make set_src, set_dest, and tx_submit descriptor specific methods
* fixup git-ioat merge
* move group_list and phys to dma_async_tx_descriptor
Cc: Jeff Garzik <jeff@garzik.org>
Cc: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Shannon Nelson <shannon.nelson@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/dma/ioatdma.c')
-rw-r--r-- | drivers/dma/ioatdma.c | 295 |
1 files changed, 137 insertions, 158 deletions
diff --git a/drivers/dma/ioatdma.c b/drivers/dma/ioatdma.c index c4209af4fde4..171044930282 100644 --- a/drivers/dma/ioatdma.c +++ b/drivers/dma/ioatdma.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common) | 38 | #define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common) |
39 | #define to_ioat_device(dev) container_of(dev, struct ioat_device, common) | 39 | #define to_ioat_device(dev) container_of(dev, struct ioat_device, common) |
40 | #define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node) | 40 | #define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node) |
41 | #define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, async_tx) | ||
41 | 42 | ||
42 | /* internal functions */ | 43 | /* internal functions */ |
43 | static int __devinit ioat_probe(struct pci_dev *pdev, const struct pci_device_id *ent); | 44 | static int __devinit ioat_probe(struct pci_dev *pdev, const struct pci_device_id *ent); |
@@ -78,6 +79,73 @@ static int enumerate_dma_channels(struct ioat_device *device) | |||
78 | return device->common.chancnt; | 79 | return device->common.chancnt; |
79 | } | 80 | } |
80 | 81 | ||
82 | static void | ||
83 | ioat_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx, int index) | ||
84 | { | ||
85 | struct ioat_desc_sw *iter, *desc = tx_to_ioat_desc(tx); | ||
86 | struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan); | ||
87 | |||
88 | pci_unmap_addr_set(desc, src, addr); | ||
89 | |||
90 | list_for_each_entry(iter, &desc->async_tx.tx_list, node) { | ||
91 | iter->hw->src_addr = addr; | ||
92 | addr += ioat_chan->xfercap; | ||
93 | } | ||
94 | |||
95 | } | ||
96 | |||
97 | static void | ||
98 | ioat_set_dest(dma_addr_t addr, struct dma_async_tx_descriptor *tx, int index) | ||
99 | { | ||
100 | struct ioat_desc_sw *iter, *desc = tx_to_ioat_desc(tx); | ||
101 | struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan); | ||
102 | |||
103 | pci_unmap_addr_set(desc, dst, addr); | ||
104 | |||
105 | list_for_each_entry(iter, &desc->async_tx.tx_list, node) { | ||
106 | iter->hw->dst_addr = addr; | ||
107 | addr += ioat_chan->xfercap; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | static dma_cookie_t | ||
112 | ioat_tx_submit(struct dma_async_tx_descriptor *tx) | ||
113 | { | ||
114 | struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan); | ||
115 | struct ioat_desc_sw *desc = tx_to_ioat_desc(tx); | ||
116 | int append = 0; | ||
117 | dma_cookie_t cookie; | ||
118 | struct ioat_desc_sw *group_start; | ||
119 | |||
120 | group_start = list_entry(desc->async_tx.tx_list.next, | ||
121 | struct ioat_desc_sw, node); | ||
122 | spin_lock_bh(&ioat_chan->desc_lock); | ||
123 | /* cookie incr and addition to used_list must be atomic */ | ||
124 | cookie = ioat_chan->common.cookie; | ||
125 | cookie++; | ||
126 | if (cookie < 0) | ||
127 | cookie = 1; | ||
128 | ioat_chan->common.cookie = desc->async_tx.cookie = cookie; | ||
129 | |||
130 | /* write address into NextDescriptor field of last desc in chain */ | ||
131 | to_ioat_desc(ioat_chan->used_desc.prev)->hw->next = | ||
132 | group_start->async_tx.phys; | ||
133 | list_splice_init(&desc->async_tx.tx_list, ioat_chan->used_desc.prev); | ||
134 | |||
135 | ioat_chan->pending += desc->tx_cnt; | ||
136 | if (ioat_chan->pending >= 4) { | ||
137 | append = 1; | ||
138 | ioat_chan->pending = 0; | ||
139 | } | ||
140 | spin_unlock_bh(&ioat_chan->desc_lock); | ||
141 | |||
142 | if (append) | ||
143 | writeb(IOAT_CHANCMD_APPEND, | ||
144 | ioat_chan->reg_base + IOAT_CHANCMD_OFFSET); | ||
145 | |||
146 | return cookie; | ||
147 | } | ||
148 | |||
81 | static struct ioat_desc_sw *ioat_dma_alloc_descriptor( | 149 | static struct ioat_desc_sw *ioat_dma_alloc_descriptor( |
82 | struct ioat_dma_chan *ioat_chan, | 150 | struct ioat_dma_chan *ioat_chan, |
83 | gfp_t flags) | 151 | gfp_t flags) |
@@ -99,8 +167,13 @@ static struct ioat_desc_sw *ioat_dma_alloc_descriptor( | |||
99 | } | 167 | } |
100 | 168 | ||
101 | memset(desc, 0, sizeof(*desc)); | 169 | memset(desc, 0, sizeof(*desc)); |
170 | dma_async_tx_descriptor_init(&desc_sw->async_tx, &ioat_chan->common); | ||
171 | desc_sw->async_tx.tx_set_src = ioat_set_src; | ||
172 | desc_sw->async_tx.tx_set_dest = ioat_set_dest; | ||
173 | desc_sw->async_tx.tx_submit = ioat_tx_submit; | ||
174 | INIT_LIST_HEAD(&desc_sw->async_tx.tx_list); | ||
102 | desc_sw->hw = desc; | 175 | desc_sw->hw = desc; |
103 | desc_sw->phys = phys; | 176 | desc_sw->async_tx.phys = phys; |
104 | 177 | ||
105 | return desc_sw; | 178 | return desc_sw; |
106 | } | 179 | } |
@@ -188,12 +261,14 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan) | |||
188 | list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) { | 261 | list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) { |
189 | in_use_descs++; | 262 | in_use_descs++; |
190 | list_del(&desc->node); | 263 | list_del(&desc->node); |
191 | pci_pool_free(ioat_device->dma_pool, desc->hw, desc->phys); | 264 | pci_pool_free(ioat_device->dma_pool, desc->hw, |
265 | desc->async_tx.phys); | ||
192 | kfree(desc); | 266 | kfree(desc); |
193 | } | 267 | } |
194 | list_for_each_entry_safe(desc, _desc, &ioat_chan->free_desc, node) { | 268 | list_for_each_entry_safe(desc, _desc, &ioat_chan->free_desc, node) { |
195 | list_del(&desc->node); | 269 | list_del(&desc->node); |
196 | pci_pool_free(ioat_device->dma_pool, desc->hw, desc->phys); | 270 | pci_pool_free(ioat_device->dma_pool, desc->hw, |
271 | desc->async_tx.phys); | ||
197 | kfree(desc); | 272 | kfree(desc); |
198 | } | 273 | } |
199 | spin_unlock_bh(&ioat_chan->desc_lock); | 274 | spin_unlock_bh(&ioat_chan->desc_lock); |
@@ -215,45 +290,25 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan) | |||
215 | writew(chanctrl, ioat_chan->reg_base + IOAT_CHANCTRL_OFFSET); | 290 | writew(chanctrl, ioat_chan->reg_base + IOAT_CHANCTRL_OFFSET); |
216 | } | 291 | } |
217 | 292 | ||
218 | /** | 293 | static struct dma_async_tx_descriptor * |
219 | * do_ioat_dma_memcpy - actual function that initiates a IOAT DMA transaction | 294 | ioat_dma_prep_memcpy(struct dma_chan *chan, size_t len, int int_en) |
220 | * @ioat_chan: IOAT DMA channel handle | ||
221 | * @dest: DMA destination address | ||
222 | * @src: DMA source address | ||
223 | * @len: transaction length in bytes | ||
224 | */ | ||
225 | |||
226 | static dma_cookie_t do_ioat_dma_memcpy(struct ioat_dma_chan *ioat_chan, | ||
227 | dma_addr_t dest, | ||
228 | dma_addr_t src, | ||
229 | size_t len) | ||
230 | { | 295 | { |
231 | struct ioat_desc_sw *first; | 296 | struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); |
232 | struct ioat_desc_sw *prev; | 297 | struct ioat_desc_sw *first, *prev, *new; |
233 | struct ioat_desc_sw *new; | ||
234 | dma_cookie_t cookie; | ||
235 | LIST_HEAD(new_chain); | 298 | LIST_HEAD(new_chain); |
236 | u32 copy; | 299 | u32 copy; |
237 | size_t orig_len; | 300 | size_t orig_len; |
238 | dma_addr_t orig_src, orig_dst; | 301 | int desc_count = 0; |
239 | unsigned int desc_count = 0; | ||
240 | unsigned int append = 0; | ||
241 | |||
242 | if (!ioat_chan || !dest || !src) | ||
243 | return -EFAULT; | ||
244 | 302 | ||
245 | if (!len) | 303 | if (!len) |
246 | return ioat_chan->common.cookie; | 304 | return NULL; |
247 | 305 | ||
248 | orig_len = len; | 306 | orig_len = len; |
249 | orig_src = src; | ||
250 | orig_dst = dest; | ||
251 | 307 | ||
252 | first = NULL; | 308 | first = NULL; |
253 | prev = NULL; | 309 | prev = NULL; |
254 | 310 | ||
255 | spin_lock_bh(&ioat_chan->desc_lock); | 311 | spin_lock_bh(&ioat_chan->desc_lock); |
256 | |||
257 | while (len) { | 312 | while (len) { |
258 | if (!list_empty(&ioat_chan->free_desc)) { | 313 | if (!list_empty(&ioat_chan->free_desc)) { |
259 | new = to_ioat_desc(ioat_chan->free_desc.next); | 314 | new = to_ioat_desc(ioat_chan->free_desc.next); |
@@ -270,140 +325,36 @@ static dma_cookie_t do_ioat_dma_memcpy(struct ioat_dma_chan *ioat_chan, | |||
270 | 325 | ||
271 | new->hw->size = copy; | 326 | new->hw->size = copy; |
272 | new->hw->ctl = 0; | 327 | new->hw->ctl = 0; |
273 | new->hw->src_addr = src; | 328 | new->async_tx.cookie = 0; |
274 | new->hw->dst_addr = dest; | 329 | new->async_tx.ack = 1; |
275 | new->cookie = 0; | ||
276 | 330 | ||
277 | /* chain together the physical address list for the HW */ | 331 | /* chain together the physical address list for the HW */ |
278 | if (!first) | 332 | if (!first) |
279 | first = new; | 333 | first = new; |
280 | else | 334 | else |
281 | prev->hw->next = (u64) new->phys; | 335 | prev->hw->next = (u64) new->async_tx.phys; |
282 | 336 | ||
283 | prev = new; | 337 | prev = new; |
284 | |||
285 | len -= copy; | 338 | len -= copy; |
286 | dest += copy; | ||
287 | src += copy; | ||
288 | |||
289 | list_add_tail(&new->node, &new_chain); | 339 | list_add_tail(&new->node, &new_chain); |
290 | desc_count++; | 340 | desc_count++; |
291 | } | 341 | } |
292 | new->hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS; | ||
293 | new->hw->next = 0; | ||
294 | 342 | ||
295 | /* cookie incr and addition to used_list must be atomic */ | 343 | list_splice(&new_chain, &new->async_tx.tx_list); |
296 | 344 | ||
297 | cookie = ioat_chan->common.cookie; | 345 | new->hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS; |
298 | cookie++; | 346 | new->hw->next = 0; |
299 | if (cookie < 0) | 347 | new->tx_cnt = desc_count; |
300 | cookie = 1; | 348 | new->async_tx.ack = 0; /* client is in control of this ack */ |
301 | ioat_chan->common.cookie = new->cookie = cookie; | 349 | new->async_tx.cookie = -EBUSY; |
302 | 350 | ||
303 | pci_unmap_addr_set(new, src, orig_src); | ||
304 | pci_unmap_addr_set(new, dst, orig_dst); | ||
305 | pci_unmap_len_set(new, src_len, orig_len); | 351 | pci_unmap_len_set(new, src_len, orig_len); |
306 | pci_unmap_len_set(new, dst_len, orig_len); | 352 | pci_unmap_len_set(new, dst_len, orig_len); |
307 | |||
308 | /* write address into NextDescriptor field of last desc in chain */ | ||
309 | to_ioat_desc(ioat_chan->used_desc.prev)->hw->next = first->phys; | ||
310 | list_splice_init(&new_chain, ioat_chan->used_desc.prev); | ||
311 | |||
312 | ioat_chan->pending += desc_count; | ||
313 | if (ioat_chan->pending >= 4) { | ||
314 | append = 1; | ||
315 | ioat_chan->pending = 0; | ||
316 | } | ||
317 | |||
318 | spin_unlock_bh(&ioat_chan->desc_lock); | 353 | spin_unlock_bh(&ioat_chan->desc_lock); |
319 | 354 | ||
320 | if (append) | 355 | return new ? &new->async_tx : NULL; |
321 | writeb(IOAT_CHANCMD_APPEND, | ||
322 | ioat_chan->reg_base + IOAT_CHANCMD_OFFSET); | ||
323 | return cookie; | ||
324 | } | 356 | } |
325 | 357 | ||
326 | /** | ||
327 | * ioat_dma_memcpy_buf_to_buf - wrapper that takes src & dest bufs | ||
328 | * @chan: IOAT DMA channel handle | ||
329 | * @dest: DMA destination address | ||
330 | * @src: DMA source address | ||
331 | * @len: transaction length in bytes | ||
332 | */ | ||
333 | |||
334 | static dma_cookie_t ioat_dma_memcpy_buf_to_buf(struct dma_chan *chan, | ||
335 | void *dest, | ||
336 | void *src, | ||
337 | size_t len) | ||
338 | { | ||
339 | dma_addr_t dest_addr; | ||
340 | dma_addr_t src_addr; | ||
341 | struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); | ||
342 | |||
343 | dest_addr = pci_map_single(ioat_chan->device->pdev, | ||
344 | dest, len, PCI_DMA_FROMDEVICE); | ||
345 | src_addr = pci_map_single(ioat_chan->device->pdev, | ||
346 | src, len, PCI_DMA_TODEVICE); | ||
347 | |||
348 | return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len); | ||
349 | } | ||
350 | |||
351 | /** | ||
352 | * ioat_dma_memcpy_buf_to_pg - wrapper, copying from a buf to a page | ||
353 | * @chan: IOAT DMA channel handle | ||
354 | * @page: pointer to the page to copy to | ||
355 | * @offset: offset into that page | ||
356 | * @src: DMA source address | ||
357 | * @len: transaction length in bytes | ||
358 | */ | ||
359 | |||
360 | static dma_cookie_t ioat_dma_memcpy_buf_to_pg(struct dma_chan *chan, | ||
361 | struct page *page, | ||
362 | unsigned int offset, | ||
363 | void *src, | ||
364 | size_t len) | ||
365 | { | ||
366 | dma_addr_t dest_addr; | ||
367 | dma_addr_t src_addr; | ||
368 | struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); | ||
369 | |||
370 | dest_addr = pci_map_page(ioat_chan->device->pdev, | ||
371 | page, offset, len, PCI_DMA_FROMDEVICE); | ||
372 | src_addr = pci_map_single(ioat_chan->device->pdev, | ||
373 | src, len, PCI_DMA_TODEVICE); | ||
374 | |||
375 | return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len); | ||
376 | } | ||
377 | |||
378 | /** | ||
379 | * ioat_dma_memcpy_pg_to_pg - wrapper, copying between two pages | ||
380 | * @chan: IOAT DMA channel handle | ||
381 | * @dest_pg: pointer to the page to copy to | ||
382 | * @dest_off: offset into that page | ||
383 | * @src_pg: pointer to the page to copy from | ||
384 | * @src_off: offset into that page | ||
385 | * @len: transaction length in bytes. This is guaranteed not to make a copy | ||
386 | * across a page boundary. | ||
387 | */ | ||
388 | |||
389 | static dma_cookie_t ioat_dma_memcpy_pg_to_pg(struct dma_chan *chan, | ||
390 | struct page *dest_pg, | ||
391 | unsigned int dest_off, | ||
392 | struct page *src_pg, | ||
393 | unsigned int src_off, | ||
394 | size_t len) | ||
395 | { | ||
396 | dma_addr_t dest_addr; | ||
397 | dma_addr_t src_addr; | ||
398 | struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); | ||
399 | |||
400 | dest_addr = pci_map_page(ioat_chan->device->pdev, | ||
401 | dest_pg, dest_off, len, PCI_DMA_FROMDEVICE); | ||
402 | src_addr = pci_map_page(ioat_chan->device->pdev, | ||
403 | src_pg, src_off, len, PCI_DMA_TODEVICE); | ||
404 | |||
405 | return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len); | ||
406 | } | ||
407 | 358 | ||
408 | /** | 359 | /** |
409 | * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended descriptors to hw | 360 | * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended descriptors to hw |
@@ -465,8 +416,8 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *chan) | |||
465 | * exceeding xfercap, perhaps. If so, only the last one will | 416 | * exceeding xfercap, perhaps. If so, only the last one will |
466 | * have a cookie, and require unmapping. | 417 | * have a cookie, and require unmapping. |
467 | */ | 418 | */ |
468 | if (desc->cookie) { | 419 | if (desc->async_tx.cookie) { |
469 | cookie = desc->cookie; | 420 | cookie = desc->async_tx.cookie; |
470 | 421 | ||
471 | /* yes we are unmapping both _page and _single alloc'd | 422 | /* yes we are unmapping both _page and _single alloc'd |
472 | regions with unmap_page. Is this *really* that bad? | 423 | regions with unmap_page. Is this *really* that bad? |
@@ -481,14 +432,19 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *chan) | |||
481 | PCI_DMA_TODEVICE); | 432 | PCI_DMA_TODEVICE); |
482 | } | 433 | } |
483 | 434 | ||
484 | if (desc->phys != phys_complete) { | 435 | if (desc->async_tx.phys != phys_complete) { |
485 | /* a completed entry, but not the last, so cleanup */ | 436 | /* a completed entry, but not the last, so cleanup |
486 | list_del(&desc->node); | 437 | * if the client is done with the descriptor |
487 | list_add_tail(&desc->node, &chan->free_desc); | 438 | */ |
439 | if (desc->async_tx.ack) { | ||
440 | list_del(&desc->node); | ||
441 | list_add_tail(&desc->node, &chan->free_desc); | ||
442 | } else | ||
443 | desc->async_tx.cookie = 0; | ||
488 | } else { | 444 | } else { |
489 | /* last used desc. Do not remove, so we can append from | 445 | /* last used desc. Do not remove, so we can append from |
490 | it, but don't look at it next time, either */ | 446 | it, but don't look at it next time, either */ |
491 | desc->cookie = 0; | 447 | desc->async_tx.cookie = 0; |
492 | 448 | ||
493 | /* TODO check status bits? */ | 449 | /* TODO check status bits? */ |
494 | break; | 450 | break; |
@@ -504,6 +460,17 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *chan) | |||
504 | spin_unlock(&chan->cleanup_lock); | 460 | spin_unlock(&chan->cleanup_lock); |
505 | } | 461 | } |
506 | 462 | ||
463 | static void ioat_dma_dependency_added(struct dma_chan *chan) | ||
464 | { | ||
465 | struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); | ||
466 | spin_lock_bh(&ioat_chan->desc_lock); | ||
467 | if (ioat_chan->pending == 0) { | ||
468 | spin_unlock_bh(&ioat_chan->desc_lock); | ||
469 | ioat_dma_memcpy_cleanup(ioat_chan); | ||
470 | } else | ||
471 | spin_unlock_bh(&ioat_chan->desc_lock); | ||
472 | } | ||
473 | |||
507 | /** | 474 | /** |
508 | * ioat_dma_is_complete - poll the status of a IOAT DMA transaction | 475 | * ioat_dma_is_complete - poll the status of a IOAT DMA transaction |
509 | * @chan: IOAT DMA channel handle | 476 | * @chan: IOAT DMA channel handle |
@@ -606,13 +573,14 @@ static void ioat_start_null_desc(struct ioat_dma_chan *ioat_chan) | |||
606 | 573 | ||
607 | desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL; | 574 | desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL; |
608 | desc->hw->next = 0; | 575 | desc->hw->next = 0; |
576 | desc->async_tx.ack = 1; | ||
609 | 577 | ||
610 | list_add_tail(&desc->node, &ioat_chan->used_desc); | 578 | list_add_tail(&desc->node, &ioat_chan->used_desc); |
611 | spin_unlock_bh(&ioat_chan->desc_lock); | 579 | spin_unlock_bh(&ioat_chan->desc_lock); |
612 | 580 | ||
613 | writel(((u64) desc->phys) & 0x00000000FFFFFFFF, | 581 | writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF, |
614 | ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_LOW); | 582 | ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_LOW); |
615 | writel(((u64) desc->phys) >> 32, | 583 | writel(((u64) desc->async_tx.phys) >> 32, |
616 | ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_HIGH); | 584 | ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_HIGH); |
617 | 585 | ||
618 | writeb(IOAT_CHANCMD_START, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET); | 586 | writeb(IOAT_CHANCMD_START, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET); |
@@ -629,6 +597,8 @@ static int ioat_self_test(struct ioat_device *device) | |||
629 | u8 *src; | 597 | u8 *src; |
630 | u8 *dest; | 598 | u8 *dest; |
631 | struct dma_chan *dma_chan; | 599 | struct dma_chan *dma_chan; |
600 | struct dma_async_tx_descriptor *tx; | ||
601 | dma_addr_t addr; | ||
632 | dma_cookie_t cookie; | 602 | dma_cookie_t cookie; |
633 | int err = 0; | 603 | int err = 0; |
634 | 604 | ||
@@ -654,7 +624,15 @@ static int ioat_self_test(struct ioat_device *device) | |||
654 | goto out; | 624 | goto out; |
655 | } | 625 | } |
656 | 626 | ||
657 | cookie = ioat_dma_memcpy_buf_to_buf(dma_chan, dest, src, IOAT_TEST_SIZE); | 627 | tx = ioat_dma_prep_memcpy(dma_chan, IOAT_TEST_SIZE, 0); |
628 | async_tx_ack(tx); | ||
629 | addr = dma_map_single(dma_chan->device->dev, src, IOAT_TEST_SIZE, | ||
630 | DMA_TO_DEVICE); | ||
631 | ioat_set_src(addr, tx, 0); | ||
632 | addr = dma_map_single(dma_chan->device->dev, dest, IOAT_TEST_SIZE, | ||
633 | DMA_FROM_DEVICE); | ||
634 | ioat_set_dest(addr, tx, 0); | ||
635 | cookie = ioat_tx_submit(tx); | ||
658 | ioat_dma_memcpy_issue_pending(dma_chan); | 636 | ioat_dma_memcpy_issue_pending(dma_chan); |
659 | msleep(1); | 637 | msleep(1); |
660 | 638 | ||
@@ -750,13 +728,14 @@ static int __devinit ioat_probe(struct pci_dev *pdev, | |||
750 | INIT_LIST_HEAD(&device->common.channels); | 728 | INIT_LIST_HEAD(&device->common.channels); |
751 | enumerate_dma_channels(device); | 729 | enumerate_dma_channels(device); |
752 | 730 | ||
731 | dma_cap_set(DMA_MEMCPY, device->common.cap_mask); | ||
753 | device->common.device_alloc_chan_resources = ioat_dma_alloc_chan_resources; | 732 | device->common.device_alloc_chan_resources = ioat_dma_alloc_chan_resources; |
754 | device->common.device_free_chan_resources = ioat_dma_free_chan_resources; | 733 | device->common.device_free_chan_resources = ioat_dma_free_chan_resources; |
755 | device->common.device_memcpy_buf_to_buf = ioat_dma_memcpy_buf_to_buf; | 734 | device->common.device_prep_dma_memcpy = ioat_dma_prep_memcpy; |
756 | device->common.device_memcpy_buf_to_pg = ioat_dma_memcpy_buf_to_pg; | 735 | device->common.device_is_tx_complete = ioat_dma_is_complete; |
757 | device->common.device_memcpy_pg_to_pg = ioat_dma_memcpy_pg_to_pg; | 736 | device->common.device_issue_pending = ioat_dma_memcpy_issue_pending; |
758 | device->common.device_memcpy_complete = ioat_dma_is_complete; | 737 | device->common.device_dependency_added = ioat_dma_dependency_added; |
759 | device->common.device_memcpy_issue_pending = ioat_dma_memcpy_issue_pending; | 738 | device->common.dev = &pdev->dev; |
760 | printk(KERN_INFO "Intel(R) I/OAT DMA Engine found, %d channels\n", | 739 | printk(KERN_INFO "Intel(R) I/OAT DMA Engine found, %d channels\n", |
761 | device->common.chancnt); | 740 | device->common.chancnt); |
762 | 741 | ||