Remove duplicate __dev_addr_sync() and __dev_addr_sync() for older kernels
[~emulex/for-vlad/old/compat.git] / compat / compat-2.6.25.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.25.
9  */
10
11 #include <net/compat.h>
12
13 /* All things not in 2.6.22, 2.6.23 and 2.6.24 */
14 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25))
15
16 #include <linux/miscdevice.h>
17
18 /* Backport work for QoS dependencies (kernel/pm_qos_params.c)
19  * ipw2100 now makes use of
20  * pm_qos_add_requirement(),
21  * pm_qos_update_requirement() and
22  * pm_qos_remove_requirement() from it
23  *
24  * */
25
26 /*
27  * locking rule: all changes to target_value or requirements or notifiers lists
28  * or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock
29  * held, taken with _irqsave.  One lock to rule them all
30  */
31 struct requirement_list {
32         struct list_head list;
33         union {
34                 s32 value;
35                 s32 usec;
36                 s32 kbps;
37         };
38         char *name;
39 };
40
41 static s32 max_compare(s32 v1, s32 v2);
42 static s32 min_compare(s32 v1, s32 v2);
43
44 struct pm_qos_object {
45         struct requirement_list requirements;
46         struct blocking_notifier_head *notifiers;
47         struct miscdevice pm_qos_power_miscdev;
48         char *name;
49         s32 default_value;
50         s32 target_value;
51         s32 (*comparitor)(s32, s32);
52 };
53
54 static struct pm_qos_object null_pm_qos;
55 static BLOCKING_NOTIFIER_HEAD(cpu_dma_lat_notifier);
56 static struct pm_qos_object cpu_dma_pm_qos = {
57         .requirements = {LIST_HEAD_INIT(cpu_dma_pm_qos.requirements.list)},
58         .notifiers = &cpu_dma_lat_notifier,
59         .name = "cpu_dma_latency",
60         .default_value = 2000 * USEC_PER_SEC,
61         .target_value = 2000 * USEC_PER_SEC,
62         .comparitor = min_compare
63 };
64
65 static BLOCKING_NOTIFIER_HEAD(network_lat_notifier);
66 static struct pm_qos_object network_lat_pm_qos = {
67         .requirements = {LIST_HEAD_INIT(network_lat_pm_qos.requirements.list)},
68         .notifiers = &network_lat_notifier,
69         .name = "network_latency",
70         .default_value = 2000 * USEC_PER_SEC,
71         .target_value = 2000 * USEC_PER_SEC,
72         .comparitor = min_compare
73 };
74
75
76 static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier);
77 static struct pm_qos_object network_throughput_pm_qos = {
78         .requirements =
79                 {LIST_HEAD_INIT(network_throughput_pm_qos.requirements.list)},
80         .notifiers = &network_throughput_notifier,
81         .name = "network_throughput",
82         .default_value = 0,
83         .target_value = 0,
84         .comparitor = max_compare
85 };
86
87
88 static struct pm_qos_object *pm_qos_array[] = {
89         &null_pm_qos,
90         &cpu_dma_pm_qos,
91         &network_lat_pm_qos,
92         &network_throughput_pm_qos
93 };
94
95 static DEFINE_SPINLOCK(pm_qos_lock);
96
97 /* static helper functions */
98 static s32 max_compare(s32 v1, s32 v2)
99 {
100         return max(v1, v2);
101 }
102
103 static s32 min_compare(s32 v1, s32 v2)
104 {
105         return min(v1, v2);
106 }
107
108 static void update_target(int target)
109 {
110         s32 extreme_value;
111         struct requirement_list *node;
112         unsigned long flags;
113         int call_notifier = 0;
114
115         spin_lock_irqsave(&pm_qos_lock, flags);
116         extreme_value = pm_qos_array[target]->default_value;
117         list_for_each_entry(node,
118                         &pm_qos_array[target]->requirements.list, list) {
119                 extreme_value = pm_qos_array[target]->comparitor(
120                                 extreme_value, node->value);
121         }
122         if (pm_qos_array[target]->target_value != extreme_value) {
123                 call_notifier = 1;
124                 pm_qos_array[target]->target_value = extreme_value;
125                 pr_debug(KERN_ERR "new target for qos %d is %d\n", target,
126                         pm_qos_array[target]->target_value);
127         }
128         spin_unlock_irqrestore(&pm_qos_lock, flags);
129
130         if (call_notifier)
131                 blocking_notifier_call_chain(pm_qos_array[target]->notifiers,
132                         (unsigned long) extreme_value, NULL);
133 }
134
135
136 /**
137  * pm_qos_add_requirement - inserts new qos request into the list
138  * @pm_qos_class: identifies which list of qos request to us
139  * @name: identifies the request
140  * @value: defines the qos request
141  *
142  * This function inserts a new entry in the pm_qos_class list of requested qos
143  * performance charactoistics.  It recomputes the agregate QoS expectations for
144  * the pm_qos_class of parrameters.
145  */
146 int pm_qos_add_requirement(int pm_qos_class, char *name, s32 value)
147 {
148         struct requirement_list *dep;
149         unsigned long flags;
150
151         dep = kzalloc(sizeof(struct requirement_list), GFP_KERNEL);
152         if (dep) {
153                 if (value == PM_QOS_DEFAULT_VALUE)
154                         dep->value = pm_qos_array[pm_qos_class]->default_value;
155                 else
156                         dep->value = value;
157                 dep->name = kstrdup(name, GFP_KERNEL);
158                 if (!dep->name)
159                         goto cleanup;
160
161                 spin_lock_irqsave(&pm_qos_lock, flags);
162                 list_add(&dep->list,
163                         &pm_qos_array[pm_qos_class]->requirements.list);
164                 spin_unlock_irqrestore(&pm_qos_lock, flags);
165                 update_target(pm_qos_class);
166
167                 return 0;
168         }
169
170 cleanup:
171         kfree(dep);
172         return -ENOMEM;
173 }
174 EXPORT_SYMBOL_GPL(pm_qos_add_requirement);
175
176 /**
177  * pm_qos_update_requirement - modifies an existing qos request
178  * @pm_qos_class: identifies which list of qos request to us
179  * @name: identifies the request
180  * @value: defines the qos request
181  *
182  * Updates an existing qos requierement for the pm_qos_class of parameters along
183  * with updating the target pm_qos_class value.
184  *
185  * If the named request isn't in the lest then no change is made.
186  */
187 int pm_qos_update_requirement(int pm_qos_class, char *name, s32 new_value)
188 {
189         unsigned long flags;
190         struct requirement_list *node;
191         int pending_update = 0;
192
193         spin_lock_irqsave(&pm_qos_lock, flags);
194         list_for_each_entry(node,
195                 &pm_qos_array[pm_qos_class]->requirements.list, list) {
196                 if (strcmp(node->name, name) == 0) {
197                         if (new_value == PM_QOS_DEFAULT_VALUE)
198                                 node->value =
199                                 pm_qos_array[pm_qos_class]->default_value;
200                         else
201                                 node->value = new_value;
202                         pending_update = 1;
203                         break;
204                 }
205         }
206         spin_unlock_irqrestore(&pm_qos_lock, flags);
207         if (pending_update)
208                 update_target(pm_qos_class);
209
210         return 0;
211 }
212 EXPORT_SYMBOL_GPL(pm_qos_update_requirement);
213
214 /**
215  * pm_qos_remove_requirement - modifies an existing qos request
216  * @pm_qos_class: identifies which list of qos request to us
217  * @name: identifies the request
218  *
219  * Will remove named qos request from pm_qos_class list of parrameters and
220  * recompute the current target value for the pm_qos_class.
221  */
222 void pm_qos_remove_requirement(int pm_qos_class, char *name)
223 {
224         unsigned long flags;
225         struct requirement_list *node;
226         int pending_update = 0;
227
228         spin_lock_irqsave(&pm_qos_lock, flags);
229         list_for_each_entry(node,
230                 &pm_qos_array[pm_qos_class]->requirements.list, list) {
231                 if (strcmp(node->name, name) == 0) {
232                         kfree(node->name);
233                         list_del(&node->list);
234                         kfree(node);
235                         pending_update = 1;
236                         break;
237                 }
238         }
239         spin_unlock_irqrestore(&pm_qos_lock, flags);
240         if (pending_update)
241                 update_target(pm_qos_class);
242 }
243 EXPORT_SYMBOL_GPL(pm_qos_remove_requirement);
244
245
246 /**
247  * The following things are out of ./lib/vsprintf.c
248  * The new iwlwifi driver is using them.
249  */
250
251 /**
252  * strict_strtoul - convert a string to an unsigned long strictly
253  * @cp: The string to be converted
254  * @base: The number base to use
255  * @res: The converted result value
256  *
257  * strict_strtoul converts a string to an unsigned long only if the
258  * string is really an unsigned long string, any string containing
259  * any invalid char at the tail will be rejected and -EINVAL is returned,
260  * only a newline char at the tail is acceptible because people generally
261  * change a module parameter in the following way:
262  *
263  *      echo 1024 > /sys/module/e1000/parameters/copybreak
264  *
265  * echo will append a newline to the tail.
266  *
267  * It returns 0 if conversion is successful and *res is set to the converted
268  * value, otherwise it returns -EINVAL and *res is set to 0.
269  *
270  * simple_strtoul just ignores the successive invalid characters and
271  * return the converted value of prefix part of the string.
272  */
273 int strict_strtoul(const char *cp, unsigned int base, unsigned long *res);
274
275 /**
276  * strict_strtol - convert a string to a long strictly
277  * @cp: The string to be converted
278  * @base: The number base to use
279  * @res: The converted result value
280  *
281  * strict_strtol is similiar to strict_strtoul, but it allows the first
282  * character of a string is '-'.
283  *
284  * It returns 0 if conversion is successful and *res is set to the converted
285  * value, otherwise it returns -EINVAL and *res is set to 0.
286  */
287 int strict_strtol(const char *cp, unsigned int base, long *res);
288
289 #define define_strict_strtoux(type, valtype)                            \
290 int strict_strtou##type(const char *cp, unsigned int base, valtype *res)\
291 {                                                                       \
292         char *tail;                                                     \
293         valtype val;                                                    \
294         size_t len;                                                     \
295                                                                         \
296         *res = 0;                                                       \
297         len = strlen(cp);                                               \
298         if (len == 0)                                                   \
299                 return -EINVAL;                                         \
300                                                                         \
301         val = simple_strtou##type(cp, &tail, base);                     \
302         if ((*tail == '\0') ||                                          \
303                 ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {\
304                 *res = val;                                             \
305                 return 0;                                               \
306         }                                                               \
307                                                                         \
308         return -EINVAL;                                                 \
309 }                                                                       \
310
311 #define define_strict_strtox(type, valtype)                             \
312 int strict_strto##type(const char *cp, unsigned int base, valtype *res) \
313 {                                                                       \
314         int ret;                                                        \
315         if (*cp == '-') {                                               \
316                 ret = strict_strtou##type(cp+1, base, res);             \
317                 if (!ret)                                               \
318                         *res = -(*res);                                 \
319         } else                                                          \
320                 ret = strict_strtou##type(cp, base, res);               \
321                                                                         \
322         return ret;                                                     \
323 }                                                                       \
324
325 define_strict_strtoux(l, unsigned long)
326 define_strict_strtox(l, long)
327
328 EXPORT_SYMBOL(strict_strtoul);
329 EXPORT_SYMBOL(strict_strtol);
330
331 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) */
332