compat/nes: Adding pci_zalloc_consistent backport
[compat-rdma/compat.git] / compat / compat-2.6.37.c
1 /*
2  * Copyright 2010    Hauke Mehrtens <hauke@hauke-m.de>
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 wireless for kernels 2.6.37.
9  */
10
11 #include <linux/compat.h>
12 #include <linux/netdevice.h>
13 #include <net/sock.h>
14 #include <linux/nsproxy.h>
15 #include <linux/vmalloc.h>
16 #include <linux/sunrpc/xprt.h>
17
18 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
19 static const void *net_current_ns(void)
20 {
21         return current->nsproxy->net_ns;
22 }
23
24 static const void *net_initial_ns(void)
25 {
26         return &init_net;
27 }
28
29 static const void *net_netlink_ns(struct sock *sk)
30 {
31         return sock_net(sk);
32 }
33
34 struct kobj_ns_type_operations net_ns_type_operations = {
35         .type = KOBJ_NS_TYPE_NET,
36         .current_ns = net_current_ns,
37         .netlink_ns = net_netlink_ns,
38         .initial_ns = net_initial_ns,
39 };
40 EXPORT_SYMBOL_GPL(net_ns_type_operations);
41
42 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)*/ 
43
44 #undef genl_info
45 #undef genl_unregister_family
46
47 static LIST_HEAD(compat_nl_fam);
48
49 static struct genl_ops *genl_get_cmd(u8 cmd, struct genl_family *family)
50 {
51         struct genl_ops *ops;
52
53         list_for_each_entry(ops, &family->family.ops_list, ops.ops_list)
54                 if (ops->cmd == cmd)
55                         return ops;
56
57         return NULL;
58 }
59
60
61 static int nl_doit_wrapper(struct sk_buff *skb, struct genl_info *info)
62 {
63         struct compat_genl_info compat_info;
64         struct genl_family *family;
65         struct genl_ops *ops;
66         int err;
67
68         list_for_each_entry(family, &compat_nl_fam, list) {
69                 if (family->id == info->nlhdr->nlmsg_type)
70                         goto found;
71         }
72         return -ENOENT;
73
74 found:
75         ops = genl_get_cmd(info->genlhdr->cmd, family);
76         if (!ops)
77                 return -ENOENT;
78
79         memset(&compat_info.user_ptr, 0, sizeof(compat_info.user_ptr));
80         compat_info.info = info;
81 #define __copy(_field) compat_info._field = info->_field
82         __copy(snd_seq);
83         __copy(snd_pid);
84         __copy(genlhdr);
85         __copy(attrs);
86 #undef __copy
87         if (family->pre_doit) {
88                 err = family->pre_doit(ops, skb, &compat_info);
89                 if (err)
90                         return err;
91         }
92
93         err = ops->doit(skb, &compat_info);
94
95         if (family->post_doit)
96                 family->post_doit(ops, skb, &compat_info);
97
98         return err;
99 }
100
101 int compat_genl_register_family_with_ops(struct genl_family *family,
102                                          struct genl_ops *ops, size_t n_ops)
103 {
104         int i, ret;
105
106 #define __copy(_field) family->family._field = family->_field
107         __copy(id);
108         __copy(hdrsize);
109         __copy(version);
110         __copy(maxattr);
111         strncpy(family->family.name, family->name, sizeof(family->family.name));
112 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32))
113         __copy(netnsok);
114 #endif
115 #undef __copy
116
117         ret = genl_register_family(&family->family);
118         if (ret < 0)
119                 return ret;
120
121         family->attrbuf = family->family.attrbuf;
122         family->id = family->family.id;
123
124         for (i = 0; i < n_ops; i++) {
125 #define __copy(_field) ops[i].ops._field = ops[i]._field
126                 __copy(cmd);
127                 __copy(flags);
128                 __copy(policy);
129                 __copy(dumpit);
130                 __copy(done);
131 #undef __copy
132                 if (ops[i].doit)
133                         ops[i].ops.doit = nl_doit_wrapper;
134                 ret = genl_register_ops(&family->family, &ops[i].ops);
135                 if (ret < 0)
136                         goto error_ops;
137         }
138         list_add(&family->list, &compat_nl_fam);
139
140         return ret;
141
142 error_ops:
143         compat_genl_unregister_family(family);
144         return ret;
145 }
146 EXPORT_SYMBOL_GPL(compat_genl_register_family_with_ops);
147
148 int compat_genl_unregister_family(struct genl_family *family)
149 {
150         int err;
151         err = genl_unregister_family(&family->family);
152         list_del(&family->list);
153         return err;
154 }
155 EXPORT_SYMBOL_GPL(compat_genl_unregister_family);
156
157 #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
158
159 #undef led_brightness_set
160 #undef led_classdev_unregister
161
162 static DEFINE_SPINLOCK(led_lock);
163 static LIST_HEAD(led_timers);
164
165 struct led_timer {
166         struct list_head list;
167         struct led_classdev *cdev;
168         struct timer_list blink_timer;
169         unsigned long blink_delay_on;
170         unsigned long blink_delay_off;
171         int blink_brightness;
172 };
173
174 static void led_brightness_set(struct led_classdev *led_cdev,
175                                enum led_brightness brightness)
176 {
177         led_cdev->brightness = brightness;
178         led_cdev->brightness_set(led_cdev, brightness);
179 }
180
181 static struct led_timer *led_get_timer(struct led_classdev *led_cdev)
182 {
183         struct led_timer *p;
184         unsigned long flags;
185
186         spin_lock_irqsave(&led_lock, flags);
187         list_for_each_entry(p, &led_timers, list) {
188                 if (p->cdev == led_cdev)
189                         goto found;
190         }
191         p = NULL;
192 found:
193         spin_unlock_irqrestore(&led_lock, flags);
194         return p;
195 }
196
197 static void led_stop_software_blink(struct led_timer *led)
198 {
199         del_timer_sync(&led->blink_timer);
200         led->blink_delay_on = 0;
201         led->blink_delay_off = 0;
202 }
203
204 static void led_timer_function(unsigned long data)
205 {
206         struct led_timer *led = (struct led_timer *)data;
207         unsigned long brightness;
208         unsigned long delay;
209
210         if (!led->blink_delay_on || !led->blink_delay_off) {
211                 led->cdev->brightness_set(led->cdev, LED_OFF);
212                 return;
213         }
214
215         brightness = led->cdev->brightness;
216         if (!brightness) {
217                 /* Time to switch the LED on. */
218                 brightness = led->blink_brightness;
219                 delay = led->blink_delay_on;
220         } else {
221                 /* Store the current brightness value to be able
222                  * to restore it when the delay_off period is over.
223                  */
224                 led->blink_brightness = brightness;
225                 brightness = LED_OFF;
226                 delay = led->blink_delay_off;
227         }
228
229         led_brightness_set(led->cdev, brightness);
230         mod_timer(&led->blink_timer, jiffies + msecs_to_jiffies(delay));
231 }
232
233 static struct led_timer *led_new_timer(struct led_classdev *led_cdev)
234 {
235         struct led_timer *led;
236         unsigned long flags;
237
238         led = kzalloc(sizeof(struct led_timer), GFP_ATOMIC);
239         if (!led)
240                 return NULL;
241
242         led->cdev = led_cdev;
243         init_timer(&led->blink_timer);
244         led->blink_timer.function = led_timer_function;
245         led->blink_timer.data = (unsigned long) led;
246
247         spin_lock_irqsave(&led_lock, flags);
248         list_add(&led->list, &led_timers);
249         spin_unlock_irqrestore(&led_lock, flags);
250
251         return led;
252 }
253
254 void led_blink_set(struct led_classdev *led_cdev,
255                    unsigned long *delay_on,
256                    unsigned long *delay_off)
257 {
258         struct led_timer *led;
259         int current_brightness;
260
261 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25))
262         if (led_cdev->blink_set &&
263             !led_cdev->blink_set(led_cdev, delay_on, delay_off))
264                 return;
265 #endif
266
267         led = led_get_timer(led_cdev);
268         if (!led) {
269                 led = led_new_timer(led_cdev);
270                 if (!led)
271                         return;
272         }
273
274         /* blink with 1 Hz as default if nothing specified */
275         if (!*delay_on && !*delay_off)
276                 *delay_on = *delay_off = 500;
277
278         if (led->blink_delay_on == *delay_on &&
279             led->blink_delay_off == *delay_off)
280                 return;
281
282         current_brightness = led_cdev->brightness;
283         if (current_brightness)
284                 led->blink_brightness = current_brightness;
285         if (!led->blink_brightness)
286 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
287                 led->blink_brightness = led_cdev->max_brightness;
288 #else
289                 led->blink_brightness = LED_FULL;
290 #endif
291
292         led_stop_software_blink(led);
293         led->blink_delay_on = *delay_on;
294         led->blink_delay_off = *delay_off;
295
296         /* never on - don't blink */
297         if (!*delay_on)
298                 return;
299
300         /* never off - just set to brightness */
301         if (!*delay_off) {
302                 led_brightness_set(led_cdev, led->blink_brightness);
303                 return;
304         }
305
306         mod_timer(&led->blink_timer, jiffies + 1);
307 }
308 EXPORT_SYMBOL_GPL(led_blink_set);
309
310 void compat_led_brightness_set(struct led_classdev *led_cdev,
311                                enum led_brightness brightness)
312 {
313         struct led_timer *led = led_get_timer(led_cdev);
314
315         if (led)
316                 led_stop_software_blink(led);
317
318         return led_cdev->brightness_set(led_cdev, brightness);
319 }
320 EXPORT_SYMBOL_GPL(compat_led_brightness_set);
321
322 void compat_led_classdev_unregister(struct led_classdev *led_cdev)
323 {
324         struct led_timer *led = led_get_timer(led_cdev);
325         unsigned long flags;
326
327         if (led) {
328                 del_timer_sync(&led->blink_timer);
329                 spin_lock_irqsave(&led_lock, flags);
330                 list_del(&led->list);
331                 spin_unlock_irqrestore(&led_lock, flags);
332                 kfree(led);
333         }
334
335         led_classdev_unregister(led_cdev);
336 }
337 EXPORT_SYMBOL_GPL(compat_led_classdev_unregister);
338
339 /**
340  *      vzalloc - allocate virtually contiguous memory with zero fill
341  *      @size:  allocation size
342  *      Allocate enough pages to cover @size from the page level
343  *      allocator and map them into contiguous kernel virtual space.
344  *      The memory allocated is set to zero.
345  *
346  *      For tight control over page level allocator and protection flags
347  *      use __vmalloc() instead.
348  */
349 void *vzalloc(unsigned long size)
350 {
351         void *buf;
352         buf = vmalloc(size);
353         if (buf)
354                 memset(buf, 0, size);
355         return buf;
356 }
357 EXPORT_SYMBOL_GPL(vzalloc);
358
359 /**
360  * vzalloc_node - allocate memory on a specific node with zero fill
361  * @size:       allocation size
362  * @node:       numa node
363  *
364  * Allocate enough pages to cover @size from the page level
365  * allocator and map them into contiguous kernel virtual space.
366  * The memory allocated is set to zero.
367  *
368  * For tight control over page level allocator and protection flags
369  * use __vmalloc() instead.
370  */
371 void *vzalloc_node(unsigned long size, int node)
372 {
373         return vzalloc(size);
374 }
375 EXPORT_SYMBOL(vzalloc_node);
376
377 #endif
378
379 #ifndef CONFIG_COMPAT_XPRTRDMA_NEEDED
380 struct rpc_xprt *xprt_alloc(int size, int max_req)
381 {
382         struct rpc_xprt *xprt;
383
384         xprt = kzalloc(size, GFP_KERNEL);
385         if (xprt == NULL)
386                 goto out;
387
388         xprt->max_reqs = max_req;
389         xprt->slot = kcalloc(max_req, sizeof(struct rpc_rqst), GFP_KERNEL);
390         if (xprt->slot == NULL)
391                 goto out_free;
392
393         return xprt;
394
395 out_free:
396         kfree(xprt);
397 out:
398         return NULL;
399 }
400 EXPORT_SYMBOL_GPL(xprt_alloc);
401
402 void xprt_free(struct rpc_xprt *xprt)
403 {
404         kfree(xprt->slot);
405         kfree(xprt);
406 }
407 EXPORT_SYMBOL_GPL(xprt_free);
408 #endif