compat/nes: Adding pci_zalloc_consistent backport
[compat-rdma/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
120 /*
121  * Nonzero if YEAR is a leap year (every 4 years,
122  * except every 100th isn't, and every 400th is).
123  */
124 static int __isleap(long year)
125 {
126         return (year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0);
127 }
128
129 /* do a mathdiv for long type */
130 static long math_div(long a, long b)
131 {
132         return a / b - (a % b < 0);
133 }
134
135 /* How many leap years between y1 and y2, y1 must less or equal to y2 */
136 static long leaps_between(long y1, long y2)
137 {
138         long leaps1 = math_div(y1 - 1, 4) - math_div(y1 - 1, 100)
139                 + math_div(y1 - 1, 400);
140         long leaps2 = math_div(y2 - 1, 4) - math_div(y2 - 1, 100)
141                 + math_div(y2 - 1, 400);
142         return leaps2 - leaps1;
143 }
144
145 /* How many days come before each month (0-12). */
146 static const unsigned short __mon_yday[2][13] = {
147         /* Normal years. */
148         {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
149         /* Leap years. */
150         {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
151 };
152
153 #define SECS_PER_HOUR   (60 * 60)
154 #define SECS_PER_DAY    (SECS_PER_HOUR * 24)
155
156 /**
157  * time_to_tm - converts the calendar time to local broken-down time
158  *
159  * @totalsecs   the number of seconds elapsed since 00:00:00 on January 1, 1970,
160  *              Coordinated Universal Time (UTC).
161  * @offset      offset seconds adding to totalsecs.
162  * @result      pointer to struct tm variable to receive broken-down time
163  */
164 void time_to_tm(time_t totalsecs, int offset, struct tm *result)
165 {
166         long days, rem, y;
167         const unsigned short *ip;
168
169         days = totalsecs / SECS_PER_DAY;
170         rem = totalsecs % SECS_PER_DAY;
171         rem += offset;
172         while (rem < 0) {
173                 rem += SECS_PER_DAY;
174                 --days;
175         }
176         while (rem >= SECS_PER_DAY) {
177                 rem -= SECS_PER_DAY;
178                 ++days;
179         }
180
181         result->tm_hour = rem / SECS_PER_HOUR;
182         rem %= SECS_PER_HOUR;
183         result->tm_min = rem / 60;
184         result->tm_sec = rem % 60;
185
186         /* January 1, 1970 was a Thursday. */
187         result->tm_wday = (4 + days) % 7;
188         if (result->tm_wday < 0)
189                 result->tm_wday += 7;
190
191         y = 1970;
192
193         while (days < 0 || days >= (__isleap(y) ? 366 : 365)) {
194                 /* Guess a corrected year, assuming 365 days per year. */
195                 long yg = y + math_div(days, 365);
196
197                 /* Adjust DAYS and Y to match the guessed year. */
198                 days -= (yg - y) * 365 + leaps_between(y, yg);
199                 y = yg;
200         }
201
202         result->tm_year = y - 1900;
203
204         result->tm_yday = days;
205
206         ip = __mon_yday[__isleap(y)];
207         for (y = 11; days < ip[y]; y--)
208                 continue;
209         days -= ip[y];
210
211         result->tm_mon = y;
212         result->tm_mday = days + 1;
213 }
214 EXPORT_SYMBOL_GPL(time_to_tm);
215 /* source: kernel/time/timeconv.c*/
216