compat/nes: Adding pci_zalloc_consistent backport
[compat-rdma/compat.git] / compat / compat-3.16.c
1 #include <linux/slab.h>
2 #include <linux/kernel.h>
3 #include <linux/bitops.h>
4 #include <linux/cpumask.h>
5 #include <linux/export.h>
6 #include <linux/bootmem.h>
7
8 /**
9  * cpumask_set_cpu_local_first - set i'th cpu with local numa cpu's first
10  *
11  * @i: index number
12  * @numa_node: local numa_node
13  * @dstp: cpumask with the relevant cpu bit set according to the policy
14  *
15  * This function sets the cpumask according to a numa aware policy.
16  * cpumask could be used as an affinity hint for the IRQ related to a
17  * queue. When the policy is to spread queues across cores - local cores
18  * first.
19  *
20  * Returns 0 on success, -ENOMEM for no memory, and -EAGAIN when failed to set
21  * the cpu bit and need to re-call the function.
22  */
23 #define cpumask_set_cpu_local_first LINUX_BACKPORT(cpumask_set_cpu_local_first)
24 int cpumask_set_cpu_local_first(int i, int numa_node, cpumask_t *dstp)
25 {
26         cpumask_var_t mask;
27         int cpu;
28         int ret = 0;
29
30         if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
31                 return -ENOMEM;
32
33         i %= num_online_cpus();
34
35         if (numa_node == -1 || !cpumask_of_node(numa_node)) {
36                 /* Use all online cpu's for non numa aware system */
37                 cpumask_copy(mask, cpu_online_mask);
38         } else {
39                 int n;
40
41                 cpumask_and(mask,
42                             cpumask_of_node(numa_node), cpu_online_mask);
43
44                 n = cpumask_weight(mask);
45                 if (i >= n) {
46                         i -= n;
47
48                         /* If index > number of local cpu's, mask out local
49                          * cpu's
50                          */
51                         cpumask_andnot(mask, cpu_online_mask, mask);
52                 }
53         }
54
55         for_each_cpu(cpu, mask) {
56                 if (--i < 0)
57                         goto out;
58         }
59
60         ret = -EAGAIN;
61
62 out:
63         free_cpumask_var(mask);
64
65         if (!ret)
66                 cpumask_set_cpu(cpu, dstp);
67
68         return ret;
69 }
70 EXPORT_SYMBOL(cpumask_set_cpu_local_first);
71
72 static int __hw_addr_del_entry(struct netdev_hw_addr_list *list,
73                                struct netdev_hw_addr *ha, bool global,
74                                bool sync)
75 {
76         if (global && !ha->global_use)
77                 return -ENOENT;
78
79         if (sync && !ha->synced)
80                 return -ENOENT;
81
82         if (global)
83                 ha->global_use = false;
84
85         if (sync)
86                 ha->synced--;
87
88         if (--ha->refcount)
89                 return 0;
90         list_del_rcu(&ha->list);
91         kfree_rcu(ha, rcu_head);
92         list->count--;
93         return 0;
94 }
95
96 /**
97  *  __hw_addr_sync_dev - Synchonize device's multicast list
98  *  @list: address list to syncronize
99  *  @dev:  device to sync
100  *  @sync: function to call if address should be added
101  *  @unsync: function to call if address should be removed
102  *
103  *  This funciton is intended to be called from the ndo_set_rx_mode
104  *  function of devices that require explicit address add/remove
105  *  notifications.  The unsync function may be NULL in which case
106  *  the addresses requiring removal will simply be removed without
107  *  any notification to the device.
108  **/
109 #define __hw_addr_sync_dev LINUX_BACKPORT(__hw_addr_sync_dev)
110 int __hw_addr_sync_dev(struct netdev_hw_addr_list *list,
111                        struct net_device *dev,
112                        int (*sync)(struct net_device *, const unsigned char *),
113                        int (*unsync)(struct net_device *,
114                                      const unsigned char *))
115 {
116         struct netdev_hw_addr *ha, *tmp;
117         int err;
118
119         /* first go through and flush out any stale entries */
120         list_for_each_entry_safe(ha, tmp, &list->list, list) {
121                 if (!ha->sync_cnt || ha->refcount != 1)
122                         continue;
123
124                 /* if unsync is defined and fails defer unsyncing address */
125                 if (unsync && unsync(dev, ha->addr))
126                         continue;
127
128                 ha->sync_cnt--;
129                 __hw_addr_del_entry(list, ha, false, false);
130         }
131
132         /* go through and sync new entries to the list */
133         list_for_each_entry_safe(ha, tmp, &list->list, list) {
134                 if (ha->sync_cnt)
135                         continue;
136
137                 err = sync(dev, ha->addr);
138                 if (err)
139                         return err;
140
141                 ha->sync_cnt++;
142                 ha->refcount++;
143         }
144
145         return 0;
146 }
147 EXPORT_SYMBOL(__hw_addr_sync_dev);