Add initial 2.6.22 support
[~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 /* Part of net/core/dev_mcast.c as of 2.6.23. This is a slightly different version.
17  * Since da->da_synced is not part of 2.6.22 we need to take longer route when
18  * syncing */
19
20 /**
21  *      dev_mc_sync     - Synchronize device's multicast list to another device
22  *      @to: destination device
23  *      @from: source device
24  *
25  *      Add newly added addresses to the destination device and release
26  *      addresses that have no users left. The source device must be
27  *      locked by netif_tx_lock_bh.
28  *
29  *      This function is intended to be called from the dev->set_multicast_list
30  *      function of layered software devices.
31  */
32 int dev_mc_sync(struct net_device *to, struct net_device *from)
33 {
34         struct dev_addr_list *da, *next, *da_to;
35         int err = 0;
36
37         netif_tx_lock_bh(to);
38         da = from->mc_list;
39         while (da != NULL) {
40                 int synced = 0;
41                 next = da->next;
42                 da_to = to->mc_list;
43                 /* 2.6.22 does not have da->da_synced so lets take the long route */
44                 while (da_to != NULL) {
45                         if (memcmp(da_to->da_addr, da->da_addr, da_to->da_addrlen) == 0 &&
46                                 da->da_addrlen == da_to->da_addrlen)
47                                 synced = 1;
48                                 break;
49                 }
50                 if (!synced) {
51                         err = __dev_addr_add(&to->mc_list, &to->mc_count,
52                                              da->da_addr, da->da_addrlen, 0);
53                         if (err < 0)
54                                 break;
55                         da->da_users++;
56                 } else if (da->da_users == 1) {
57                         __dev_addr_delete(&to->mc_list, &to->mc_count,
58                                           da->da_addr, da->da_addrlen, 0);
59                         __dev_addr_delete(&from->mc_list, &from->mc_count,
60                                           da->da_addr, da->da_addrlen, 0);
61                 }
62                 da = next;
63         }
64         if (!err)
65                 __dev_set_rx_mode(to);
66         netif_tx_unlock_bh(to);
67
68         return err;
69 }
70 EXPORT_SYMBOL(dev_mc_sync);
71
72
73 /* Part of net/core/dev_mcast.c as of 2.6.23. This is a slighty different version.
74  * Since da->da_synced is not part of 2.6.22 we need to take longer route when
75  * unsyncing */
76
77 /**
78  *      dev_mc_unsync   - Remove synchronized addresses from the destination
79  *                        device
80  *      @to: destination device
81  *      @from: source device
82  *
83  *      Remove all addresses that were added to the destination device by
84  *      dev_mc_sync(). This function is intended to be called from the
85  *      dev->stop function of layered software devices.
86  */
87 void dev_mc_unsync(struct net_device *to, struct net_device *from)
88 {
89         struct dev_addr_list *da, *next, *da_to;
90
91         netif_tx_lock_bh(from);
92         netif_tx_lock_bh(to);
93
94         da = from->mc_list;
95         while (da != NULL) {
96                 bool synced = false;
97                 next = da->next;
98                 da_to = to->mc_list;
99                 /* 2.6.22 does not have da->da_synced so lets take the long route */
100                 while (da_to != NULL) {
101                         if (memcmp(da_to->da_addr, da->da_addr, da_to->da_addrlen) == 0 &&
102                                 da->da_addrlen == da_to->da_addrlen)
103                                 synced = true;
104                                 break;
105                 }
106                 if (!synced) {
107                         da = next;
108                         continue;
109                 }
110                 __dev_addr_delete(&to->mc_list, &to->mc_count,
111                         da->da_addr, da->da_addrlen, 0);
112                 __dev_addr_delete(&from->mc_list, &from->mc_count,
113                         da->da_addr, da->da_addrlen, 0);
114                 da = next;
115         }
116         __dev_set_rx_mode(to);
117
118         netif_tx_unlock_bh(to);
119         netif_tx_unlock_bh(from);
120 }
121 EXPORT_SYMBOL(dev_mc_unsync);
122
123 /* Added as of 2.6.23 on net/core/dev.c. Slightly modifed, no dev->set_rx_mode on
124  * 2.6.22 so ignore that. */
125
126 /*
127  *      Upload unicast and multicast address lists to device and
128  *      configure RX filtering. When the device doesn't support unicast
129  *      filtering it is put in promiscous mode while unicast addresses
130  *      are present.
131  */
132 void __dev_set_rx_mode(struct net_device *dev)
133 {
134         /* dev_open will call this function so the list will stay sane. */
135         if (!(dev->flags&IFF_UP))
136                 return;
137
138         if (!netif_device_present(dev))
139                 return;
140
141 /* This needs to be ported to 2.6.22 framework */
142 #if 0
143         /* Unicast addresses changes may only happen under the rtnl,
144          * therefore calling __dev_set_promiscuity here is safe.
145          */
146         if (dev->uc_count > 0 && !dev->uc_promisc) {
147                 __dev_set_promiscuity(dev, 1);
148                 dev->uc_promisc = 1;
149         } else if (dev->uc_count == 0 && dev->uc_promisc) {
150                 __dev_set_promiscuity(dev, -1);
151                 dev->uc_promisc = 0;
152         }
153 #endif
154
155         if (dev->set_multicast_list)
156                 dev->set_multicast_list(dev);
157 }
158
159 #ifndef HAVE_PCI_SET_MWI
160 int pci_try_set_mwi(struct pci_dev *dev)
161 {
162         return 0;
163 }
164 EXPORT_SYMBOL(pci_try_set_mwi);
165 #else
166
167 /**
168  * pci_try_set_mwi - enables memory-write-invalidate PCI transaction
169  * @dev: the PCI device for which MWI is enabled
170  *
171  * Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND.
172  * Callers are not required to check the return value.
173  *
174  * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
175  */
176 int pci_try_set_mwi(struct pci_dev *dev)
177 {
178         int rc = pci_set_mwi(dev);
179         return rc;
180 }
181 EXPORT_SYMBOL(pci_try_set_mwi);
182 #endif
183
184 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)) */
185