Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.5-rc3 131 lines 3.4 kB view raw
1/* 2 * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. 3 * Portions based on net/core/datagram.c and copyrighted by their authors. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License as published by the Free 7 * Software Foundation; either version 2 of the License, or (at your option) 8 * any later version. 9 * 10 * This program is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * You should have received a copy of the GNU General Public License along with 16 * this program; if not, write to the Free Software Foundation, Inc., 59 17 * Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 * 19 * The full GNU General Public License is included in this distribution in the 20 * file called COPYING. 21 */ 22 23/* 24 * This code allows the net stack to make use of a DMA engine for 25 * skb to iovec copies. 26 */ 27 28#include <linux/dmaengine.h> 29#include <linux/socket.h> 30#include <linux/export.h> 31#include <net/tcp.h> 32#include <net/netdma.h> 33 34#define NET_DMA_DEFAULT_COPYBREAK 4096 35 36int sysctl_tcp_dma_copybreak = NET_DMA_DEFAULT_COPYBREAK; 37EXPORT_SYMBOL(sysctl_tcp_dma_copybreak); 38 39/** 40 * dma_skb_copy_datagram_iovec - Copy a datagram to an iovec. 41 * @skb - buffer to copy 42 * @offset - offset in the buffer to start copying from 43 * @iovec - io vector to copy to 44 * @len - amount of data to copy from buffer to iovec 45 * @pinned_list - locked iovec buffer data 46 * 47 * Note: the iovec is modified during the copy. 48 */ 49int dma_skb_copy_datagram_iovec(struct dma_chan *chan, 50 struct sk_buff *skb, int offset, struct iovec *to, 51 size_t len, struct dma_pinned_list *pinned_list) 52{ 53 int start = skb_headlen(skb); 54 int i, copy = start - offset; 55 struct sk_buff *frag_iter; 56 dma_cookie_t cookie = 0; 57 58 /* Copy header. */ 59 if (copy > 0) { 60 if (copy > len) 61 copy = len; 62 cookie = dma_memcpy_to_iovec(chan, to, pinned_list, 63 skb->data + offset, copy); 64 if (cookie < 0) 65 goto fault; 66 len -= copy; 67 if (len == 0) 68 goto end; 69 offset += copy; 70 } 71 72 /* Copy paged appendix. Hmm... why does this look so complicated? */ 73 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 74 int end; 75 const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 76 77 WARN_ON(start > offset + len); 78 79 end = start + skb_frag_size(frag); 80 copy = end - offset; 81 if (copy > 0) { 82 struct page *page = skb_frag_page(frag); 83 84 if (copy > len) 85 copy = len; 86 87 cookie = dma_memcpy_pg_to_iovec(chan, to, pinned_list, page, 88 frag->page_offset + offset - start, copy); 89 if (cookie < 0) 90 goto fault; 91 len -= copy; 92 if (len == 0) 93 goto end; 94 offset += copy; 95 } 96 start = end; 97 } 98 99 skb_walk_frags(skb, frag_iter) { 100 int end; 101 102 WARN_ON(start > offset + len); 103 104 end = start + frag_iter->len; 105 copy = end - offset; 106 if (copy > 0) { 107 if (copy > len) 108 copy = len; 109 cookie = dma_skb_copy_datagram_iovec(chan, frag_iter, 110 offset - start, 111 to, copy, 112 pinned_list); 113 if (cookie < 0) 114 goto fault; 115 len -= copy; 116 if (len == 0) 117 goto end; 118 offset += copy; 119 } 120 start = end; 121 } 122 123end: 124 if (!len) { 125 skb->dma_cookie = cookie; 126 return cookie; 127 } 128 129fault: 130 return -EFAULT; 131}