013150d098fe610309e0c8bc98f485fea78d357a
[~tnikolova/compat/.git] / compat / compat-2.6.32.c
1 /*
2  * Copyright 2007       Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
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.32.
9  */
10
11 #include <linux/compat.h>
12 #include <linux/netdevice.h>
13
14 int __dev_addr_add(struct dev_addr_list **list, int *count,
15                    void *addr, int alen, int glbl)
16 {
17         struct dev_addr_list *da;
18
19         for (da = *list; da != NULL; da = da->next) {
20                 if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 &&
21                     da->da_addrlen == alen) {
22                         if (glbl) {
23                                 int old_glbl = da->da_gusers;
24                                 da->da_gusers = 1;
25                                 if (old_glbl)
26                                         return 0;
27                         }
28                         da->da_users++;
29                         return 0;
30                 }
31         }
32
33         da = kzalloc(sizeof(*da), GFP_ATOMIC);
34         if (da == NULL)
35                 return -ENOMEM;
36         memcpy(da->da_addr, addr, alen);
37         da->da_addrlen = alen;
38         da->da_users = 1;
39         da->da_gusers = glbl ? 1 : 0;
40         da->next = *list;
41         *list = da;
42         (*count)++;
43         return 0;
44 }
45
46 int __dev_addr_delete(struct dev_addr_list **list, int *count,
47                       void *addr, int alen, int glbl)
48 {
49         struct dev_addr_list *da;
50
51         for (; (da = *list) != NULL; list = &da->next) {
52                 if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 &&
53                     alen == da->da_addrlen) {
54                         if (glbl) {
55                                 int old_glbl = da->da_gusers;
56                                 da->da_gusers = 0;
57                                 if (old_glbl == 0)
58                                         break;
59                         }
60                         if (--da->da_users)
61                                 return 0;
62
63                         *list = da->next;
64                         kfree(da);
65                         (*count)--;
66                         return 0;
67                 }
68         }
69         return -ENOENT;
70 }
71
72 int __dev_addr_sync(struct dev_addr_list **to, int *to_count,
73                     struct dev_addr_list **from, int *from_count)
74 {
75         struct dev_addr_list *da, *next;
76         int err = 0;
77
78         da = *from;
79         while (da != NULL) {
80                 next = da->next;
81                 if (!da->da_synced) {
82                         err = __dev_addr_add(to, to_count,
83                                              da->da_addr, da->da_addrlen, 0);
84                         if (err < 0)
85                                 break;
86                         da->da_synced = 1;
87                         da->da_users++;
88                 } else if (da->da_users == 1) {
89                         __dev_addr_delete(to, to_count,
90                                           da->da_addr, da->da_addrlen, 0);
91                         __dev_addr_delete(from, from_count,
92                                           da->da_addr, da->da_addrlen, 0);
93                 }
94                 da = next;
95         }
96         return err;
97 }
98 EXPORT_SYMBOL_GPL(__dev_addr_sync);
99
100 void __dev_addr_unsync(struct dev_addr_list **to, int *to_count,
101                        struct dev_addr_list **from, int *from_count)
102 {
103         struct dev_addr_list *da, *next;
104
105         da = *from;
106         while (da != NULL) {
107                 next = da->next;
108                 if (da->da_synced) {
109                         __dev_addr_delete(to, to_count,
110                                           da->da_addr, da->da_addrlen, 0);
111                         da->da_synced = 0;
112                         __dev_addr_delete(from, from_count,
113                                           da->da_addr, da->da_addrlen, 0);
114                 }
115                 da = next;
116         }
117 }
118 EXPORT_SYMBOL_GPL(__dev_addr_unsync);
119