Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[sfrench/cifs-2.6.git] / drivers / net / macvtap.c
index 6a64197f5bcef6fa4fce9e714bee6fa664e46fb7..3b933bb5a8d5084208c2a9903ab44317cae5d146 100644 (file)
@@ -48,15 +48,70 @@ struct macvtap_queue {
 #define MACVTAP_FEATURES (IFF_VNET_HDR | IFF_MULTI_QUEUE)
 
 #define MACVTAP_VNET_LE 0x80000000
+#define MACVTAP_VNET_BE 0x40000000
+
+#ifdef CONFIG_TUN_VNET_CROSS_LE
+static inline bool macvtap_legacy_is_little_endian(struct macvtap_queue *q)
+{
+       return q->flags & MACVTAP_VNET_BE ? false :
+               virtio_legacy_is_little_endian();
+}
+
+static long macvtap_get_vnet_be(struct macvtap_queue *q, int __user *sp)
+{
+       int s = !!(q->flags & MACVTAP_VNET_BE);
+
+       if (put_user(s, sp))
+               return -EFAULT;
+
+       return 0;
+}
+
+static long macvtap_set_vnet_be(struct macvtap_queue *q, int __user *sp)
+{
+       int s;
+
+       if (get_user(s, sp))
+               return -EFAULT;
+
+       if (s)
+               q->flags |= MACVTAP_VNET_BE;
+       else
+               q->flags &= ~MACVTAP_VNET_BE;
+
+       return 0;
+}
+#else
+static inline bool macvtap_legacy_is_little_endian(struct macvtap_queue *q)
+{
+       return virtio_legacy_is_little_endian();
+}
+
+static long macvtap_get_vnet_be(struct macvtap_queue *q, int __user *argp)
+{
+       return -EINVAL;
+}
+
+static long macvtap_set_vnet_be(struct macvtap_queue *q, int __user *argp)
+{
+       return -EINVAL;
+}
+#endif /* CONFIG_TUN_VNET_CROSS_LE */
+
+static inline bool macvtap_is_little_endian(struct macvtap_queue *q)
+{
+       return q->flags & MACVTAP_VNET_LE ||
+               macvtap_legacy_is_little_endian(q);
+}
 
 static inline u16 macvtap16_to_cpu(struct macvtap_queue *q, __virtio16 val)
 {
-       return __virtio16_to_cpu(q->flags & MACVTAP_VNET_LE, val);
+       return __virtio16_to_cpu(macvtap_is_little_endian(q), val);
 }
 
 static inline __virtio16 cpu_to_macvtap16(struct macvtap_queue *q, u16 val)
 {
-       return __cpu_to_virtio16(q->flags & MACVTAP_VNET_LE, val);
+       return __cpu_to_virtio16(macvtap_is_little_endian(q), val);
 }
 
 static struct proto macvtap_proto = {
@@ -1085,6 +1140,12 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
                        q->flags &= ~MACVTAP_VNET_LE;
                return 0;
 
+       case TUNGETVNETBE:
+               return macvtap_get_vnet_be(q, sp);
+
+       case TUNSETVNETBE:
+               return macvtap_set_vnet_be(q, sp);
+
        case TUNSETOFFLOAD:
                /* let the user check for future flags */
                if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 |
@@ -1294,6 +1355,7 @@ static void macvtap_exit(void)
        class_unregister(macvtap_class);
        cdev_del(&macvtap_cdev);
        unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS);
+       idr_destroy(&minor_idr);
 }
 module_exit(macvtap_exit);