Merge branch 'omap-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind...
[pandora-kernel.git] / drivers / net / macvtap.c
index abba3cc..a8a94e2 100644 (file)
@@ -37,6 +37,8 @@
 struct macvtap_queue {
        struct sock sk;
        struct socket sock;
+       struct socket_wq wq;
+       int vnet_hdr_sz;
        struct macvlan_dev *vlan;
        struct file *file;
        unsigned int flags;
@@ -181,7 +183,7 @@ static int macvtap_forward(struct net_device *dev, struct sk_buff *skb)
                return -ENOLINK;
 
        skb_queue_tail(&q->sk.sk_receive_queue, skb);
-       wake_up_interruptible_poll(q->sk.sk_sleep, POLLIN | POLLRDNORM | POLLRDBAND);
+       wake_up_interruptible_poll(sk_sleep(&q->sk), POLLIN | POLLRDNORM | POLLRDBAND);
        return 0;
 }
 
@@ -242,12 +244,15 @@ static struct rtnl_link_ops macvtap_link_ops __read_mostly = {
 
 static void macvtap_sock_write_space(struct sock *sk)
 {
+       wait_queue_head_t *wqueue;
+
        if (!sock_writeable(sk) ||
            !test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags))
                return;
 
-       if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
-               wake_up_interruptible_poll(sk->sk_sleep, POLLOUT | POLLWRNORM | POLLWRBAND);
+       wqueue = sk_sleep(sk);
+       if (wqueue && waitqueue_active(wqueue))
+               wake_up_interruptible_poll(wqueue, POLLOUT | POLLWRNORM | POLLWRBAND);
 }
 
 static int macvtap_open(struct inode *inode, struct file *file)
@@ -272,7 +277,8 @@ static int macvtap_open(struct inode *inode, struct file *file)
        if (!q)
                goto out;
 
-       init_waitqueue_head(&q->sock.wait);
+       q->sock.wq = &q->wq;
+       init_waitqueue_head(&q->wq.wait);
        q->sock.type = SOCK_RAW;
        q->sock.state = SS_CONNECTED;
        q->sock.file = file;
@@ -280,6 +286,7 @@ static int macvtap_open(struct inode *inode, struct file *file)
        sock_init_data(&q->sock, &q->sk);
        q->sk.sk_write_space = macvtap_sock_write_space;
        q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP;
+       q->vnet_hdr_sz = sizeof(struct virtio_net_hdr);
 
        err = macvtap_set_queue(dev, file, q);
        if (err)
@@ -308,7 +315,7 @@ static unsigned int macvtap_poll(struct file *file, poll_table * wait)
                goto out;
 
        mask = 0;
-       poll_wait(file, &q->sock.wait, wait);
+       poll_wait(file, &q->wq.wait, wait);
 
        if (!skb_queue_empty(&q->sk.sk_receive_queue))
                mask |= POLLIN | POLLRDNORM;
@@ -440,14 +447,14 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q,
        int vnet_hdr_len = 0;
 
        if (q->flags & IFF_VNET_HDR) {
-               vnet_hdr_len = sizeof(vnet_hdr);
+               vnet_hdr_len = q->vnet_hdr_sz;
 
                err = -EINVAL;
                if ((len -= vnet_hdr_len) < 0)
                        goto err;
 
                err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0,
-                                          vnet_hdr_len);
+                                          sizeof(vnet_hdr));
                if (err < 0)
                        goto err;
                if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) &&
@@ -529,7 +536,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
 
        if (q->flags & IFF_VNET_HDR) {
                struct virtio_net_hdr vnet_hdr;
-               vnet_hdr_len = sizeof (vnet_hdr);
+               vnet_hdr_len = q->vnet_hdr_sz;
                if ((len -= vnet_hdr_len) < 0)
                        return -EINVAL;
 
@@ -537,7 +544,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
                if (ret)
                        return ret;
 
-               if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, vnet_hdr_len))
+               if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr)))
                        return -EFAULT;
        }
 
@@ -562,7 +569,7 @@ static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb,
        struct sk_buff *skb;
        ssize_t ret = 0;
 
-       add_wait_queue(q->sk.sk_sleep, &wait);
+       add_wait_queue(sk_sleep(&q->sk), &wait);
        while (len) {
                current->state = TASK_INTERRUPTIBLE;
 
@@ -587,7 +594,7 @@ static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb,
        }
 
        current->state = TASK_RUNNING;
-       remove_wait_queue(q->sk.sk_sleep, &wait);
+       remove_wait_queue(sk_sleep(&q->sk), &wait);
        return ret;
 }
 
@@ -622,6 +629,8 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
        struct ifreq __user *ifr = argp;
        unsigned int __user *up = argp;
        unsigned int u;
+       int __user *sp = argp;
+       int s;
        int ret;
 
        switch (cmd) {
@@ -667,6 +676,21 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
                q->sk.sk_sndbuf = u;
                return 0;
 
+       case TUNGETVNETHDRSZ:
+               s = q->vnet_hdr_sz;
+               if (put_user(s, sp))
+                       return -EFAULT;
+               return 0;
+
+       case TUNSETVNETHDRSZ:
+               if (get_user(s, sp))
+                       return -EFAULT;
+               if (s < (int)sizeof(struct virtio_net_hdr))
+                       return -EINVAL;
+
+               q->vnet_hdr_sz = s;
+               return 0;
+
        case TUNSETOFFLOAD:
                /* let the user check for future flags */
                if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 |