9a06cd57d77e69cb56192cc0a631ff474c5c1551
[~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 static u32 hashrnd __read_mostly;
28
29 #define get_xps_queue LINUX_BACKPORT(get_xps_queue)
30 static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
31 {
32 #ifdef CONFIG_XPS
33         struct xps_dev_maps *dev_maps;
34         struct xps_map *map;
35         int queue_index = -1;
36
37         rcu_read_lock();
38         dev_maps = rcu_dereference(dev->xps_maps);
39         if (dev_maps) {
40                 map = rcu_dereference(
41                     dev_maps->cpu_map[raw_smp_processor_id()]);
42                 if (map) {
43                         if (map->len == 1)
44                                 queue_index = map->queues[0];
45                         else {
46                                 u32 hash;
47                                 if (skb->sk && skb->sk->sk_hash)
48                                         hash = skb->sk->sk_hash;
49                                 else
50                                         hash = (__force u16) skb->protocol ^
51                                             skb->rxhash;
52                                 hash = jhash_1word(hash, hashrnd);
53                                 queue_index = map->queues[
54                                     ((u64)hash * map->len) >> 32];
55                         }
56                         if (unlikely(queue_index >= dev->real_num_tx_queues))
57                                 queue_index = -1;
58                 }
59         }
60         rcu_read_unlock();
61
62         return queue_index;
63 #else
64         return -1;
65 #endif
66 }
67
68 #define __netdev_pick_tx LINUX_BACKPORT(__netdev_pick_tx)
69 u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
70 {
71         struct sock *sk = skb->sk;
72         int queue_index = sk_tx_queue_get(sk);
73
74         if (queue_index < 0 || skb->ooo_okay ||
75             queue_index >= dev->real_num_tx_queues) {
76                 int new_index = get_xps_queue(dev, skb);
77                 if (new_index < 0)
78                         new_index = skb_tx_hash(dev, skb);
79
80                 if (queue_index != new_index && sk &&
81                     rcu_access_pointer(sk->sk_dst_cache))
82                         sk_tx_queue_set(sk, new_index);
83
84                 queue_index = new_index;
85         }
86
87         return queue_index;
88 }
89 EXPORT_SYMBOL(__netdev_pick_tx);