compat-2.6.h: include generated config.h
[~tnikolova/compat/.git] / compat / compat-3.9.c
1 /*
2  * Copyright 2013  Mellanox Technologies Ltd.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * Compatibility file for Linux RDMA for kernels 3.9.
9  */
10
11 #include <linux/skbuff.h>
12 #include <linux/export.h>
13 #include <linux/ip.h>
14 #include <linux/ipv6.h>
15 #include <linux/if_vlan.h>
16 #include <net/ip.h>
17 #include <net/ipv6.h>
18 #include <linux/igmp.h>
19 #include <linux/icmp.h>
20 #include <linux/sctp.h>
21 #include <linux/dccp.h>
22 #include <linux/if_tunnel.h>
23 #include <linux/if_pppox.h>
24 #include <linux/ppp_defs.h>
25 #include <net/flow_keys.h>
26
27 #ifdef CONFIG_XPS
28 static u32 hashrnd __read_mostly;
29 #endif
30
31 #define get_xps_queue LINUX_BACKPORT(get_xps_queue)
32 static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
33 {
34 #ifdef CONFIG_XPS
35         struct xps_dev_maps *dev_maps;
36         struct xps_map *map;
37         int queue_index = -1;
38
39         rcu_read_lock();
40         dev_maps = rcu_dereference(dev->xps_maps);
41         if (dev_maps) {
42                 map = rcu_dereference(
43                     dev_maps->cpu_map[raw_smp_processor_id()]);
44                 if (map) {
45                         if (map->len == 1)
46                                 queue_index = map->queues[0];
47                         else {
48                                 u32 hash;
49                                 if (skb->sk && skb->sk->sk_hash)
50                                         hash = skb->sk->sk_hash;
51                                 else
52                                         hash = (__force u16) skb->protocol ^
53                                             skb->rxhash;
54                                 hash = jhash_1word(hash, hashrnd);
55                                 queue_index = map->queues[
56                                     ((u64)hash * map->len) >> 32];
57                         }
58                         if (unlikely(queue_index >= dev->real_num_tx_queues))
59                                 queue_index = -1;
60                 }
61         }
62         rcu_read_unlock();
63
64         return queue_index;
65 #else
66         return -1;
67 #endif
68 }
69
70 #define __netdev_pick_tx LINUX_BACKPORT(__netdev_pick_tx)
71 u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
72 {
73         struct sock *sk = skb->sk;
74         int queue_index = sk_tx_queue_get(sk);
75
76         if (queue_index < 0 || skb->ooo_okay ||
77             queue_index >= dev->real_num_tx_queues) {
78                 int new_index = get_xps_queue(dev, skb);
79                 if (new_index < 0)
80                         new_index = skb_tx_hash(dev, skb);
81
82                 if (queue_index != new_index && sk &&
83                     rcu_access_pointer(sk->sk_dst_cache))
84                         sk_tx_queue_set(sk, new_index);
85
86                 queue_index = new_index;
87         }
88
89         return queue_index;
90 }
91 EXPORT_SYMBOL(__netdev_pick_tx);
92
93 #define netif_set_xps_queue LINUX_BACKPORT(netif_set_xps_queue)
94 int netif_set_xps_queue(struct net_device *dev, struct cpumask *msk, u16 idx)
95 {
96 #ifdef HAVE_XPS_MAP
97         int i, len, err;
98         char buf[MAX_XPS_BUFFER_SIZE];
99         struct attribute *attr = NULL;
100         struct kobj_type *ktype = NULL;
101         struct mlx4_en_netq_attribute *xps_attr = NULL;
102         struct netdev_queue *txq = netdev_get_tx_queue(dev, idx);
103
104 #ifdef HAVE_NET_DEVICE_EXTENDED_TX_EXT
105         struct netdev_tx_queue_extended *txq_ext =
106                                         netdev_extended(dev)->_tx_ext + idx;
107         ktype = txq_ext->kobj.ktype;
108 #else /* HAVE_NET_DEVICE_EXTENDED_TX_EXT */
109         ktype = txq->kobj.ktype;
110 #endif /* HAVE_NET_DEVICE_EXTENDED_TX_EXT */
111         if (!ktype)
112                 return -ENOMEM;
113
114         for (i = 0; (attr = ktype->default_attrs[i]); i++) {
115                 if (!strcmp("xps_cpus", attr->name))
116                         break;
117         }
118         if (!attr)
119                 return -EINVAL;
120
121         len = bitmap_scnprintf(buf, MAX_XPS_BUFFER_SIZE,
122                                cpumask_bits(msk), MAX_XPS_CPUS);
123         if (!len)
124                 return -ENOMEM;
125
126         xps_attr = to_netq_attr(attr);
127         err = xps_attr->store(txq, xps_attr, buf, len);
128         if (err)
129                 return -EINVAL;
130
131         return 0;
132 #else /* HAVE_XPS_MAP */
133         return -1;
134 #endif /* HAVE_XPS_MAP */
135 }
136 EXPORT_SYMBOL(netif_set_xps_queue);