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