diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-22 14:43:13 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-22 14:43:13 -0700 |
| commit | 951cc93a7493a81a47e20231441bc6cf17c98a37 (patch) | |
| tree | f53934f0f225e0215a85c8c59af4c6513e89e3f1 /drivers/net/tun.c | |
| parent | a7e1aabb28e8154ce987b622fd78d80a1ca39361 (diff) | |
| parent | 415b3334a21aa67806c52d1acf4e72e14f7f402f (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1287 commits)
icmp: Fix regression in nexthop resolution during replies.
net: Fix ppc64 BPF JIT dependencies.
acenic: include NET_SKB_PAD headroom to incoming skbs
ixgbe: convert to ndo_fix_features
ixgbe: only enable WoL for magic packet by default
ixgbe: remove ifdef check for non-existent define
ixgbe: Pass staterr instead of re-reading status and error bits from descriptor
ixgbe: Move interrupt related values out of ring and into q_vector
ixgbe: add structure for containing RX/TX rings to q_vector
ixgbe: inline the ixgbe_maybe_stop_tx function
ixgbe: Update ATR to use recorded TX queues instead of CPU for routing
igb: Fix for DH89xxCC near end loopback test
e1000: always call e1000_check_for_link() on e1000_ce4100 MACs.
netxen: add fw version compatibility check
be2net: request native mode each time the card is reset
ipv4: Constrain UFO fragment sizes to multiples of 8 bytes
virtio_net: Fix panic in virtnet_remove
ipv6: make fragment identifications less predictable
ipv6: unshare inetpeers
can: make function can_get_bittiming static
...
Diffstat (limited to 'drivers/net/tun.c')
| -rw-r--r-- | drivers/net/tun.c | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 5235f48be1be..9a6b3824da14 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -572,9 +572,9 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) /* prepad is the amount to reserve at front. len is length after that. * linear is a hint as to how much to copy (usually headers). */ -static inline struct sk_buff *tun_alloc_skb(struct tun_struct *tun, - size_t prepad, size_t len, - size_t linear, int noblock) +static struct sk_buff *tun_alloc_skb(struct tun_struct *tun, + size_t prepad, size_t len, + size_t linear, int noblock) { struct sock *sk = tun->socket.sk; struct sk_buff *skb; @@ -600,13 +600,13 @@ static inline struct sk_buff *tun_alloc_skb(struct tun_struct *tun, } /* Get packet from user space buffer */ -static __inline__ ssize_t tun_get_user(struct tun_struct *tun, - const struct iovec *iv, size_t count, - int noblock) +static ssize_t tun_get_user(struct tun_struct *tun, + const struct iovec *iv, size_t count, + int noblock) { struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) }; struct sk_buff *skb; - size_t len = count, align = 0; + size_t len = count, align = NET_SKB_PAD; struct virtio_net_hdr gso = { 0 }; int offset = 0; @@ -636,7 +636,7 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, } if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) { - align = NET_IP_ALIGN; + align += NET_IP_ALIGN; if (unlikely(len < ETH_HLEN || (gso.hdr_len && gso.hdr_len < ETH_HLEN))) return -EINVAL; @@ -688,7 +688,7 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, case TUN_TAP_DEV: skb->protocol = eth_type_trans(skb, tun->dev); break; - }; + } if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) { pr_debug("GSO!\n"); @@ -751,9 +751,9 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, } /* Put packet to the user space buffer */ -static __inline__ ssize_t tun_put_user(struct tun_struct *tun, - struct sk_buff *skb, - const struct iovec *iv, int len) +static ssize_t tun_put_user(struct tun_struct *tun, + struct sk_buff *skb, + const struct iovec *iv, int len) { struct tun_pi pi = { 0, skb->protocol }; ssize_t total = 0; @@ -810,6 +810,8 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun, gso.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; gso.csum_start = skb_checksum_start_offset(skb); gso.csum_offset = skb->csum_offset; + } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + gso.flags = VIRTIO_NET_HDR_F_DATA_VALID; } /* else everything is zero */ if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total, @@ -839,7 +841,8 @@ static ssize_t tun_do_read(struct tun_struct *tun, tun_debug(KERN_INFO, tun, "tun_chr_read\n"); - add_wait_queue(&tun->wq.wait, &wait); + if (unlikely(!noblock)) + add_wait_queue(&tun->wq.wait, &wait); while (len) { current->state = TASK_INTERRUPTIBLE; @@ -870,7 +873,8 @@ static ssize_t tun_do_read(struct tun_struct *tun, } current->state = TASK_RUNNING; - remove_wait_queue(&tun->wq.wait, &wait); + if (unlikely(!noblock)) + remove_wait_queue(&tun->wq.wait, &wait); return ret; } |
