]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/brcm80211/sys/wlc_event.c
staging: brcm80211: Purge unused #includes
[net-next-2.6.git] / drivers / staging / brcm80211 / sys / wlc_event.c
1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <typedefs.h>
18 #include <linux/kernel.h>
19 #include <linuxver.h>
20 #include <bcmutils.h>
21 #include <siutils.h>
22 #include <wlioctl.h>
23 #include <wlc_cfg.h>
24 #include <wlc_pub.h>
25 #include <wlc_key.h>
26 #include <wl_export.h>
27 #include <wlc_event.h>
28
29 #include <d11.h>
30 #include <wlc_rate.h>
31 #include <wlc_mac80211.h>
32 #ifdef MSGTRACE
33 #include <msgtrace.h>
34 #endif
35
36 /* Local prototypes */
37 static void wlc_timer_cb(void *arg);
38
39 /* Private data structures */
40 struct wlc_eventq {
41         wlc_event_t *head;
42         wlc_event_t *tail;
43         struct wlc_info *wlc;
44         void *wl;
45         wlc_pub_t *pub;
46         bool tpending;
47         bool workpending;
48         struct wl_timer *timer;
49         wlc_eventq_cb_t cb;
50         uint8 event_inds_mask[ROUNDUP(WLC_E_LAST, NBBY) / NBBY];
51 };
52
53 /*
54  * Export functions
55  */
56 wlc_eventq_t *BCMATTACHFN(wlc_eventq_attach) (wlc_pub_t *pub,
57                                               struct wlc_info *wlc, void *wl,
58                                               wlc_eventq_cb_t cb) {
59         wlc_eventq_t *eq;
60
61         eq = (wlc_eventq_t *) MALLOC(pub->osh, sizeof(wlc_eventq_t));
62         if (eq == NULL)
63                 return NULL;
64
65         bzero(eq, sizeof(wlc_eventq_t));
66
67         eq->cb = cb;
68         eq->wlc = wlc;
69         eq->wl = wl;
70         eq->pub = pub;
71
72         eq->timer = wl_init_timer(eq->wl, wlc_timer_cb, eq, "eventq");
73         if (!eq->timer) {
74                 WL_ERROR(("wl%d: wlc_eventq_attach: timer failed\n",
75                           pub->unit));
76                 MFREE(eq->pub->osh, eq, sizeof(wlc_eventq_t));
77                 return NULL;
78         }
79
80         return eq;
81 }
82
83 int BCMATTACHFN(wlc_eventq_detach) (wlc_eventq_t *eq)
84 {
85         /* Clean up pending events */
86         wlc_eventq_down(eq);
87
88         if (eq->timer) {
89                 if (eq->tpending) {
90                         wl_del_timer(eq->wl, eq->timer);
91                         eq->tpending = FALSE;
92                 }
93                 wl_free_timer(eq->wl, eq->timer);
94                 eq->timer = NULL;
95         }
96
97         ASSERT(wlc_eventq_avail(eq) == FALSE);
98         MFREE(eq->pub->osh, eq, sizeof(wlc_eventq_t));
99         return 0;
100 }
101
102 int BCMUNINITFN(wlc_eventq_down) (wlc_eventq_t *eq)
103 {
104         int callbacks = 0;
105         if (eq->tpending && !eq->workpending) {
106                 if (!wl_del_timer(eq->wl, eq->timer))
107                         callbacks++;
108
109                 ASSERT(wlc_eventq_avail(eq) == TRUE);
110                 ASSERT(eq->workpending == FALSE);
111                 eq->workpending = TRUE;
112                 if (eq->cb)
113                         eq->cb(eq->wlc);
114
115                 ASSERT(eq->workpending == TRUE);
116                 eq->workpending = FALSE;
117                 eq->tpending = FALSE;
118         } else {
119                 ASSERT(eq->workpending || wlc_eventq_avail(eq) == FALSE);
120         }
121         return callbacks;
122 }
123
124 wlc_event_t *wlc_event_alloc(wlc_eventq_t *eq)
125 {
126         wlc_event_t *e;
127
128         e = MALLOC(eq->pub->osh, sizeof(wlc_event_t));
129
130         if (e == NULL)
131                 return NULL;
132
133         bzero(e, sizeof(wlc_event_t));
134         return e;
135 }
136
137 void wlc_event_free(wlc_eventq_t *eq, wlc_event_t *e)
138 {
139         ASSERT(e->data == NULL);
140         ASSERT(e->next == NULL);
141         MFREE(eq->pub->osh, e, sizeof(wlc_event_t));
142 }
143
144 void wlc_eventq_enq(wlc_eventq_t *eq, wlc_event_t *e)
145 {
146         ASSERT(e->next == NULL);
147         e->next = NULL;
148
149         if (eq->tail) {
150                 eq->tail->next = e;
151                 eq->tail = e;
152         } else
153                 eq->head = eq->tail = e;
154
155         if (!eq->tpending) {
156                 eq->tpending = TRUE;
157                 /* Use a zero-delay timer to trigger
158                  * delayed processing of the event.
159                  */
160                 wl_add_timer(eq->wl, eq->timer, 0, 0);
161         }
162 }
163
164 wlc_event_t *wlc_eventq_deq(wlc_eventq_t *eq)
165 {
166         wlc_event_t *e;
167
168         e = eq->head;
169         if (e) {
170                 eq->head = e->next;
171                 e->next = NULL;
172
173                 if (eq->head == NULL)
174                         eq->tail = eq->head;
175         }
176         return e;
177 }
178
179 wlc_event_t *wlc_eventq_next(wlc_eventq_t *eq, wlc_event_t *e)
180 {
181 #ifdef BCMDBG
182         wlc_event_t *etmp;
183
184         for (etmp = eq->head; etmp; etmp = etmp->next) {
185                 if (etmp == e)
186                         break;
187         }
188         ASSERT(etmp != NULL);
189 #endif
190
191         return e->next;
192 }
193
194 int wlc_eventq_cnt(wlc_eventq_t *eq)
195 {
196         wlc_event_t *etmp;
197         int cnt = 0;
198
199         for (etmp = eq->head; etmp; etmp = etmp->next)
200                 cnt++;
201
202         return cnt;
203 }
204
205 bool wlc_eventq_avail(wlc_eventq_t *eq)
206 {
207         return (eq->head != NULL);
208 }
209
210 /*
211  * Local Functions
212  */
213 static void wlc_timer_cb(void *arg)
214 {
215         struct wlc_eventq *eq = (struct wlc_eventq *)arg;
216
217         ASSERT(eq->tpending == TRUE);
218         ASSERT(wlc_eventq_avail(eq) == TRUE);
219         ASSERT(eq->workpending == FALSE);
220         eq->workpending = TRUE;
221
222         if (eq->cb)
223                 eq->cb(eq->wlc);
224
225         ASSERT(wlc_eventq_avail(eq) == FALSE);
226         ASSERT(eq->tpending == TRUE);
227         eq->workpending = FALSE;
228         eq->tpending = FALSE;
229 }