diff options
author | David S. Miller <davem@davemloft.net> | 2008-09-11 07:51:14 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-09-11 07:51:14 -0400 |
commit | a40c24a13366e324bc0ff8c3bb107db89312c984 (patch) | |
tree | e09838bb9becdc16220b8d1bbc67b67010543190 | |
parent | 271bff7afbb2cbaa81e744006ad2fff1f3e10b1b (diff) |
net: Add SKB DMA mapping helper functions.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/skbuff.h | 8 | ||||
-rw-r--r-- | net/core/Makefile | 1 | ||||
-rw-r--r-- | net/core/skb_dma_map.c | 66 |
3 files changed, 75 insertions, 0 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 4b2be23903c4..aa80ad9cbc88 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -359,6 +359,14 @@ struct sk_buff { | |||
359 | 359 | ||
360 | #include <asm/system.h> | 360 | #include <asm/system.h> |
361 | 361 | ||
362 | #ifdef CONFIG_HAS_DMA | ||
363 | #include <linux/dma-mapping.h> | ||
364 | extern int skb_dma_map(struct device *dev, struct sk_buff *skb, | ||
365 | enum dma_data_direction dir); | ||
366 | extern void skb_dma_unmap(struct device *dev, struct sk_buff *skb, | ||
367 | enum dma_data_direction dir); | ||
368 | #endif | ||
369 | |||
362 | extern void kfree_skb(struct sk_buff *skb); | 370 | extern void kfree_skb(struct sk_buff *skb); |
363 | extern void __kfree_skb(struct sk_buff *skb); | 371 | extern void __kfree_skb(struct sk_buff *skb); |
364 | extern struct sk_buff *__alloc_skb(unsigned int size, | 372 | extern struct sk_buff *__alloc_skb(unsigned int size, |
diff --git a/net/core/Makefile b/net/core/Makefile index b1332f6d0042..26a37cb31923 100644 --- a/net/core/Makefile +++ b/net/core/Makefile | |||
@@ -6,6 +6,7 @@ obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \ | |||
6 | gen_stats.o gen_estimator.o net_namespace.o | 6 | gen_stats.o gen_estimator.o net_namespace.o |
7 | 7 | ||
8 | obj-$(CONFIG_SYSCTL) += sysctl_net_core.o | 8 | obj-$(CONFIG_SYSCTL) += sysctl_net_core.o |
9 | obj-$(CONFIG_HAS_DMA) += skb_dma_map.o | ||
9 | 10 | ||
10 | obj-y += dev.o ethtool.o dev_mcast.o dst.o netevent.o \ | 11 | obj-y += dev.o ethtool.o dev_mcast.o dst.o netevent.o \ |
11 | neighbour.o rtnetlink.o utils.o link_watch.o filter.o | 12 | neighbour.o rtnetlink.o utils.o link_watch.o filter.o |
diff --git a/net/core/skb_dma_map.c b/net/core/skb_dma_map.c new file mode 100644 index 000000000000..1f49afcd8e86 --- /dev/null +++ b/net/core/skb_dma_map.c | |||
@@ -0,0 +1,66 @@ | |||
1 | /* skb_dma_map.c: DMA mapping helpers for socket buffers. | ||
2 | * | ||
3 | * Copyright (C) David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/dma-mapping.h> | ||
9 | #include <linux/skbuff.h> | ||
10 | |||
11 | int skb_dma_map(struct device *dev, struct sk_buff *skb, | ||
12 | enum dma_data_direction dir) | ||
13 | { | ||
14 | struct skb_shared_info *sp = skb_shinfo(skb); | ||
15 | dma_addr_t map; | ||
16 | int i; | ||
17 | |||
18 | map = dma_map_single(dev, skb->data, | ||
19 | skb_headlen(skb), dir); | ||
20 | if (dma_mapping_error(dev, map)) | ||
21 | goto out_err; | ||
22 | |||
23 | sp->dma_maps[0] = map; | ||
24 | for (i = 0; i < sp->nr_frags; i++) { | ||
25 | skb_frag_t *fp = &sp->frags[i]; | ||
26 | |||
27 | map = dma_map_page(dev, fp->page, fp->page_offset, | ||
28 | fp->size, dir); | ||
29 | if (dma_mapping_error(dev, map)) | ||
30 | goto unwind; | ||
31 | sp->dma_maps[i + 1] = map; | ||
32 | } | ||
33 | sp->num_dma_maps = i + 1; | ||
34 | |||
35 | return 0; | ||
36 | |||
37 | unwind: | ||
38 | while (i-- >= 0) { | ||
39 | skb_frag_t *fp = &sp->frags[i]; | ||
40 | |||
41 | dma_unmap_page(dev, sp->dma_maps[i + 1], | ||
42 | fp->size, dir); | ||
43 | } | ||
44 | dma_unmap_single(dev, sp->dma_maps[0], | ||
45 | skb_headlen(skb), dir); | ||
46 | out_err: | ||
47 | return -ENOMEM; | ||
48 | } | ||
49 | EXPORT_SYMBOL(skb_dma_map); | ||
50 | |||
51 | void skb_dma_unmap(struct device *dev, struct sk_buff *skb, | ||
52 | enum dma_data_direction dir) | ||
53 | { | ||
54 | struct skb_shared_info *sp = skb_shinfo(skb); | ||
55 | int i; | ||
56 | |||
57 | dma_unmap_single(dev, sp->dma_maps[0], | ||
58 | skb_headlen(skb), dir); | ||
59 | for (i = 0; i < sp->nr_frags; i++) { | ||
60 | skb_frag_t *fp = &sp->frags[i]; | ||
61 | |||
62 | dma_unmap_page(dev, sp->dma_maps[i + 1], | ||
63 | fp->size, dir); | ||
64 | } | ||
65 | } | ||
66 | EXPORT_SYMBOL(skb_dma_unmap); | ||