compat: backport net_ns_type_operations
[~emulex/for-vlad/old/compat.git] / compat / compat-2.6.23.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.23.
9  */
10
11 #include <net/compat.h>
12
13 /* All things not in 2.6.22 */
14 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23))
15
16 /* On net/core/dev.c as of 2.6.24 */
17 int __dev_addr_delete(struct dev_addr_list **list, int *count,
18                       void *addr, int alen, int glbl)
19 {
20         struct dev_addr_list *da;
21
22         for (; (da = *list) != NULL; list = &da->next) {
23                 if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 &&
24                         alen == da->da_addrlen) {
25                         if (glbl) {
26                                 int old_glbl = da->da_gusers;
27                                 da->da_gusers = 0;
28                                 if (old_glbl == 0)
29                                         break;
30                         }
31                         if (--da->da_users)
32                                 return 0;
33
34                         *list = da->next;
35                         kfree(da);
36                         (*count)--;
37                         return 0;
38                 }
39         }
40         return -ENOENT;
41 }
42 EXPORT_SYMBOL(__dev_addr_delete);
43
44 /* On net/core/dev.c as of 2.6.24. This is not yet used by mac80211 but
45  * might as well add it */
46 int __dev_addr_add(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; da != NULL; da = da->next) {
52                 if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 &&
53                         da->da_addrlen == alen) {
54                         if (glbl) {
55                                 int old_glbl = da->da_gusers;
56                                 da->da_gusers = 1;
57                                 if (old_glbl)
58                                         return 0;
59                         }
60                         da->da_users++;
61                         return 0;
62                 }
63         }
64
65         da = kmalloc(sizeof(*da), GFP_ATOMIC);
66         if (da == NULL)
67                 return -ENOMEM;
68         memcpy(da->da_addr, addr, alen);
69         da->da_addrlen = alen;
70         da->da_users = 1;
71         da->da_gusers = glbl ? 1 : 0;
72         da->next = *list;
73         *list = da;
74         (*count)++;
75         return 0;
76 }
77 EXPORT_SYMBOL(__dev_addr_add);
78
79
80 /* Part of net/core/dev_mcast.c as of 2.6.23. This is a slightly different version.
81  * Since da->da_synced is not part of 2.6.22 we need to take longer route when
82  * syncing */
83
84 /**
85  *      dev_mc_sync     - Synchronize device's multicast list to another device
86  *      @to: destination device
87  *      @from: source device
88  *
89  *      Add newly added addresses to the destination device and release
90  *      addresses that have no users left. The source device must be
91  *      locked by netif_tx_lock_bh.
92  *
93  *      This function is intended to be called from the dev->set_multicast_list
94  *      function of layered software devices.
95  */
96 int dev_mc_sync(struct net_device *to, struct net_device *from)
97 {
98         struct dev_addr_list *da, *next, *da_to;
99         int err = 0;
100
101         netif_tx_lock_bh(to);
102         da = from->mc_list;
103         while (da != NULL) {
104                 int synced = 0;
105                 next = da->next;
106                 da_to = to->mc_list;
107                 /* 2.6.22 does not have da->da_synced so lets take the long route */
108                 while (da_to != NULL) {
109                         if (memcmp(da_to->da_addr, da->da_addr, da_to->da_addrlen) == 0 &&
110                                 da->da_addrlen == da_to->da_addrlen)
111                                 synced = 1;
112                                 break;
113                 }
114                 if (!synced) {
115                         err = __dev_addr_add(&to->mc_list, &to->mc_count,
116                                              da->da_addr, da->da_addrlen, 0);
117                         if (err < 0)
118                                 break;
119                         da->da_users++;
120                 } else if (da->da_users == 1) {
121                         __dev_addr_delete(&to->mc_list, &to->mc_count,
122                                           da->da_addr, da->da_addrlen, 0);
123                         __dev_addr_delete(&from->mc_list, &from->mc_count,
124                                           da->da_addr, da->da_addrlen, 0);
125                 }
126                 da = next;
127         }
128         if (!err)
129                 __dev_set_rx_mode(to);
130         netif_tx_unlock_bh(to);
131
132         return err;
133 }
134 EXPORT_SYMBOL(dev_mc_sync);
135
136
137 /* Part of net/core/dev_mcast.c as of 2.6.23. This is a slighty different version.
138  * Since da->da_synced is not part of 2.6.22 we need to take longer route when
139  * unsyncing */
140
141 /**
142  *      dev_mc_unsync   - Remove synchronized addresses from the destination
143  *                        device
144  *      @to: destination device
145  *      @from: source device
146  *
147  *      Remove all addresses that were added to the destination device by
148  *      dev_mc_sync(). This function is intended to be called from the
149  *      dev->stop function of layered software devices.
150  */
151 void dev_mc_unsync(struct net_device *to, struct net_device *from)
152 {
153         struct dev_addr_list *da, *next, *da_to;
154
155         netif_tx_lock_bh(from);
156         netif_tx_lock_bh(to);
157
158         da = from->mc_list;
159         while (da != NULL) {
160                 bool synced = false;
161                 next = da->next;
162                 da_to = to->mc_list;
163                 /* 2.6.22 does not have da->da_synced so lets take the long route */
164                 while (da_to != NULL) {
165                         if (memcmp(da_to->da_addr, da->da_addr, da_to->da_addrlen) == 0 &&
166                                 da->da_addrlen == da_to->da_addrlen)
167                                 synced = true;
168                                 break;
169                 }
170                 if (!synced) {
171                         da = next;
172                         continue;
173                 }
174                 __dev_addr_delete(&to->mc_list, &to->mc_count,
175                         da->da_addr, da->da_addrlen, 0);
176                 __dev_addr_delete(&from->mc_list, &from->mc_count,
177                         da->da_addr, da->da_addrlen, 0);
178                 da = next;
179         }
180         __dev_set_rx_mode(to);
181
182         netif_tx_unlock_bh(to);
183         netif_tx_unlock_bh(from);
184 }
185 EXPORT_SYMBOL(dev_mc_unsync);
186
187 /* Added as of 2.6.23 on net/core/dev.c. Slightly modifed, no dev->set_rx_mode on
188  * 2.6.22 so ignore that. */
189
190 /*
191  *      Upload unicast and multicast address lists to device and
192  *      configure RX filtering. When the device doesn't support unicast
193  *      filtering it is put in promiscous mode while unicast addresses
194  *      are present.
195  */
196 void __dev_set_rx_mode(struct net_device *dev)
197 {
198         /* dev_open will call this function so the list will stay sane. */
199         if (!(dev->flags&IFF_UP))
200                 return;
201
202         if (!netif_device_present(dev))
203                 return;
204
205 /* This needs to be ported to 2.6.22 framework */
206 #if 0
207         /* Unicast addresses changes may only happen under the rtnl,
208          * therefore calling __dev_set_promiscuity here is safe.
209          */
210         if (dev->uc_count > 0 && !dev->uc_promisc) {
211                 __dev_set_promiscuity(dev, 1);
212                 dev->uc_promisc = 1;
213         } else if (dev->uc_count == 0 && dev->uc_promisc) {
214                 __dev_set_promiscuity(dev, -1);
215                 dev->uc_promisc = 0;
216         }
217 #endif
218
219         if (dev->set_multicast_list)
220                 dev->set_multicast_list(dev);
221 }
222
223 #ifndef HAVE_PCI_SET_MWI
224 int pci_try_set_mwi(struct pci_dev *dev)
225 {
226         return 0;
227 }
228 EXPORT_SYMBOL(pci_try_set_mwi);
229 #else
230
231 /**
232  * pci_try_set_mwi - enables memory-write-invalidate PCI transaction
233  * @dev: the PCI device for which MWI is enabled
234  *
235  * Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND.
236  * Callers are not required to check the return value.
237  *
238  * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
239  */
240 int pci_try_set_mwi(struct pci_dev *dev)
241 {
242         int rc = pci_set_mwi(dev);
243         return rc;
244 }
245 EXPORT_SYMBOL(pci_try_set_mwi);
246 #endif
247
248 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)) */
249