Commit 0acedc124aca35f5cce9d4ee288dc372bf517e09
Committed by
Linus Torvalds
1 parent
f41b177157
Exists in
master
and in
39 other branches
dma-mapping.h: add the dma_unmap state API
Adds the following macros: DECLARE_DMA_UNMAP_ADDR(ADDR_NAME) DECLARE_DMA_UNMAP_LEN(LEN_NAME) dma_unmap_addr(PTR, ADDR_NAME) dma_unmap_addr_set(PTR, ADDR_NAME, VAL) dma_unmap_len(PTR, LEN_NAME) dma_unmap_len_set(PTR, LEN_NAME, VAL) The API corresponds to the pci_unmap state API. We'll move to this new generic API from the PCI specific API in the long term. As include/asm-generic/pci-dma-compat.h does, the pci_unmap API simply calls the new generic API for some time. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Cc: James Bottomley <James.Bottomley@suse.de> Cc: David S. Miller <davem@davemloft.net> Cc: Jesse Barnes <jbarnes@virtuousgeek.org> Cc: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 3 changed files with 80 additions and 15 deletions Side-by-side Diff
Documentation/DMA-API.txt
... | ... | @@ -472,6 +472,64 @@ |
472 | 472 | .... |
473 | 473 | |
474 | 474 | |
475 | +Part Ie - Optimizing Unmap State Space Consumption | |
476 | +-------------------------------- | |
477 | + | |
478 | +On some platforms, dma_unmap_{single,page}() is simply a nop. | |
479 | +Therefore, keeping track of the mapping address and length is a waste | |
480 | +of space. Instead of filling your drivers up with ifdefs and the like | |
481 | +to "work around" this (which would defeat the whole purpose of a | |
482 | +portable API) the following facilities are provided. | |
483 | + | |
484 | +Actually, instead of describing the macros one by one, we'll | |
485 | +transform some example code. | |
486 | + | |
487 | +1) Use DEFINE_DMA_UNMAP_{ADDR,LEN} in state saving structures. | |
488 | + Example, before: | |
489 | + | |
490 | + struct ring_state { | |
491 | + struct sk_buff *skb; | |
492 | + dma_addr_t mapping; | |
493 | + __u32 len; | |
494 | + }; | |
495 | + | |
496 | + after: | |
497 | + | |
498 | + struct ring_state { | |
499 | + struct sk_buff *skb; | |
500 | + DEFINE_DMA_UNMAP_ADDR(mapping); | |
501 | + DEFINE_DMA_UNMAP_LEN(len); | |
502 | + }; | |
503 | + | |
504 | +2) Use dma_unmap_{addr,len}_set to set these values. | |
505 | + Example, before: | |
506 | + | |
507 | + ringp->mapping = FOO; | |
508 | + ringp->len = BAR; | |
509 | + | |
510 | + after: | |
511 | + | |
512 | + dma_unmap_addr_set(ringp, mapping, FOO); | |
513 | + dma_unmap_len_set(ringp, len, BAR); | |
514 | + | |
515 | +3) Use dma_unmap_{addr,len} to access these values. | |
516 | + Example, before: | |
517 | + | |
518 | + dma_unmap_single(dev, ringp->mapping, ringp->len, | |
519 | + DMA_FROM_DEVICE); | |
520 | + | |
521 | + after: | |
522 | + | |
523 | + dma_unmap_single(dev, | |
524 | + dma_unmap_addr(ringp, mapping), | |
525 | + dma_unmap_len(ringp, len), | |
526 | + DMA_FROM_DEVICE); | |
527 | + | |
528 | +It really should be self-explanatory. We treat the ADDR and LEN | |
529 | +separately, because it is possible for an implementation to only | |
530 | +need the address in order to perform the unmap operation. | |
531 | + | |
532 | + | |
475 | 533 | Part II - Advanced dma_ usage |
476 | 534 | ----------------------------- |
477 | 535 |
include/linux/dma-mapping.h
... | ... | @@ -232,5 +232,21 @@ |
232 | 232 | |
233 | 233 | #endif /* CONFIG_HAVE_DMA_ATTRS */ |
234 | 234 | |
235 | +#ifdef CONFIG_NEED_DMA_MAP_STATE | |
236 | +#define DEFINE_DMA_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME | |
237 | +#define DEFINE_DMA_UNMAP_LEN(LEN_NAME) __u32 LEN_NAME | |
238 | +#define dma_unmap_addr(PTR, ADDR_NAME) ((PTR)->ADDR_NAME) | |
239 | +#define dma_unmap_addr_set(PTR, ADDR_NAME, VAL) (((PTR)->ADDR_NAME) = (VAL)) | |
240 | +#define dma_unmap_len(PTR, LEN_NAME) ((PTR)->LEN_NAME) | |
241 | +#define dma_unmap_len_set(PTR, LEN_NAME, VAL) (((PTR)->LEN_NAME) = (VAL)) | |
242 | +#else | |
243 | +#define DEFINE_DMA_UNMAP_ADDR(ADDR_NAME) | |
244 | +#define DEFINE_DMA_UNMAP_LEN(LEN_NAME) | |
245 | +#define dma_unmap_addr(PTR, ADDR_NAME) (0) | |
246 | +#define dma_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0) | |
247 | +#define dma_unmap_len(PTR, LEN_NAME) (0) | |
248 | +#define dma_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) | |
249 | +#endif | |
250 | + | |
235 | 251 | #endif |
include/linux/pci-dma.h
1 | 1 | #ifndef _LINUX_PCI_DMA_H |
2 | 2 | #define _LINUX_PCI_DMA_H |
3 | 3 | |
4 | -#ifdef CONFIG_NEED_DMA_MAP_STATE | |
5 | -#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME; | |
6 | -#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) __u32 LEN_NAME; | |
7 | -#define pci_unmap_addr(PTR, ADDR_NAME) ((PTR)->ADDR_NAME) | |
8 | -#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) (((PTR)->ADDR_NAME) = (VAL)) | |
9 | -#define pci_unmap_len(PTR, LEN_NAME) ((PTR)->LEN_NAME) | |
10 | -#define pci_unmap_len_set(PTR, LEN_NAME, VAL) (((PTR)->LEN_NAME) = (VAL)) | |
11 | -#else | |
12 | -#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) | |
13 | -#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) | |
14 | -#define pci_unmap_addr(PTR, ADDR_NAME) (0) | |
15 | -#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0) | |
16 | -#define pci_unmap_len(PTR, LEN_NAME) (0) | |
17 | -#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) | |
18 | -#endif | |
4 | +#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) DEFINE_DMA_UNMAP_ADDR(ADDR_NAME); | |
5 | +#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) DEFINE_DMA_UNMAP_LEN(LEN_NAME); | |
6 | +#define pci_unmap_addr dma_unmap_addr | |
7 | +#define pci_unmap_addr_set dma_unmap_addr_set | |
8 | +#define pci_unmap_len dma_unmap_len | |
9 | +#define pci_unmap_len_set dma_unmap_len_set | |
19 | 10 | |
20 | 11 | #endif |