Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
[linux-block.git] / net / core / skb_dma_map.c
CommitLineData
a40c24a1
DM
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
11int 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
042a53a9 23 sp->dma_head = map;
a40c24a1
DM
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;
042a53a9 31 sp->dma_maps[i] = map;
a40c24a1 32 }
a40c24a1
DM
33
34 return 0;
35
36unwind:
ab396eb0 37 while (--i >= 0) {
a40c24a1
DM
38 skb_frag_t *fp = &sp->frags[i];
39
042a53a9 40 dma_unmap_page(dev, sp->dma_maps[i],
a40c24a1
DM
41 fp->size, dir);
42 }
042a53a9 43 dma_unmap_single(dev, sp->dma_head,
a40c24a1
DM
44 skb_headlen(skb), dir);
45out_err:
46 return -ENOMEM;
47}
48EXPORT_SYMBOL(skb_dma_map);
49
50void skb_dma_unmap(struct device *dev, struct sk_buff *skb,
51 enum dma_data_direction dir)
52{
53 struct skb_shared_info *sp = skb_shinfo(skb);
54 int i;
55
042a53a9 56 dma_unmap_single(dev, sp->dma_head,
a40c24a1
DM
57 skb_headlen(skb), dir);
58 for (i = 0; i < sp->nr_frags; i++) {
59 skb_frag_t *fp = &sp->frags[i];
60
042a53a9 61 dma_unmap_page(dev, sp->dma_maps[i],
a40c24a1
DM
62 fp->size, dir);
63 }
64}
65EXPORT_SYMBOL(skb_dma_unmap);