aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArend van Spriel <arend@broadcom.com>2012-11-14 21:46:16 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-11-16 14:28:57 -0500
commit3e0a97e1507c482d2299a6ff24e597c1316ba60a (patch)
treec05e911af1244d3ee863860a8f9f62c615d358a2
parentb522dd8071947be7f62e75d7de5b6b3de0d882f5 (diff)
brcmfmac: restructure handling of IF event
The IF event need special care. It can be either an ADD, DEL, or CHANGE. For an ADD we need to call brcmf_add_if() before the event handler call. Upon a DEL we need to call brcmf_del_if() after the event handler call. CHANGE does not require special attention. Reviewed-by: Hante Meuleman <meuleman@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: Franky Lin <frankyl@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fweh.c102
1 files changed, 55 insertions, 47 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
index 7b57b8902a34..37f853d45d30 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
@@ -205,19 +205,40 @@ static void brcmf_fweh_queue_event(struct brcmf_fweh_info *fweh,
205 schedule_work(&fweh->event_work); 205 schedule_work(&fweh->event_work);
206} 206}
207 207
208static int brcmf_fweh_call_event_handler(struct brcmf_if *ifp,
209 enum brcmf_fweh_event_code code,
210 struct brcmf_event_msg *emsg,
211 void *data)
212{
213 struct brcmf_fweh_info *fweh;
214 int err = -EINVAL;
215
216 if (ifp) {
217 fweh = &ifp->drvr->fweh;
218
219 /* handle the event if valid interface and handler */
220 if (ifp->ndev && fweh->evt_handler[code])
221 err = fweh->evt_handler[code](ifp, emsg, data);
222 else
223 brcmf_dbg(ERROR, "unhandled event %d ignored\n", code);
224 } else {
225 brcmf_dbg(ERROR, "no interface object\n");
226 }
227 return err;
228}
229
208/** 230/**
209 * brcmf_fweh_process_if_event() - handle IF event. 231 * brcmf_fweh_handle_if_event() - handle IF event.
210 * 232 *
211 * @drvr: driver information object. 233 * @drvr: driver information object.
212 * @item: queue entry. 234 * @item: queue entry.
213 * @ifpp: interface object (may change upon ADD action). 235 * @ifpp: interface object (may change upon ADD action).
214 */ 236 */
215static int brcmf_fweh_process_if_event(struct brcmf_pub *drvr, 237static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
216 struct brcmf_fweh_queue_item *item, 238 struct brcmf_event_msg *emsg,
217 struct brcmf_if **ifpp) 239 void *data)
218{ 240{
219 struct brcmf_event_msg_be *event = &item->emsg; 241 struct brcmf_if_event *ifevent = data;
220 struct brcmf_if_event *ifevent = (struct brcmf_if_event *)item->data;
221 struct brcmf_if *ifp; 242 struct brcmf_if *ifp;
222 int err = 0; 243 int err = 0;
223 244
@@ -228,34 +249,27 @@ static int brcmf_fweh_process_if_event(struct brcmf_pub *drvr,
228 if (ifevent->ifidx >= BRCMF_MAX_IFS) { 249 if (ifevent->ifidx >= BRCMF_MAX_IFS) {
229 brcmf_dbg(ERROR, "invalid interface index: %u\n", 250 brcmf_dbg(ERROR, "invalid interface index: %u\n",
230 ifevent->ifidx); 251 ifevent->ifidx);
231 return -EINVAL; 252 return;
232 } 253 }
233 254
234 switch (ifevent->action) { 255 ifp = drvr->iflist[ifevent->ifidx];
235 case BRCMF_E_IF_ADD: 256
236 brcmf_dbg(EVENT, "adding %s (%pM, %pM)\n", event->ifname, 257 if (ifevent->action == BRCMF_E_IF_ADD) {
237 event->addr, item->ifaddr); 258 brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
259 emsg->addr);
238 ifp = brcmf_add_if(drvr, ifevent->ifidx, ifevent->bssidx, 260 ifp = brcmf_add_if(drvr, ifevent->ifidx, ifevent->bssidx,
239 event->ifname, item->ifaddr); 261 emsg->ifname, emsg->addr);
240 if (!IS_ERR(ifp)) { 262 if (IS_ERR(ifp))
241 *ifpp = ifp; 263 return;
264
265 if (!drvr->fweh.evt_handler[BRCMF_E_IF])
242 err = brcmf_net_attach(ifp); 266 err = brcmf_net_attach(ifp);
243 } else {
244 err = PTR_ERR(ifp);
245 }
246 break;
247 case BRCMF_E_IF_DEL:
248 brcmf_del_if(drvr, ifevent->ifidx);
249 break;
250 case BRCMF_E_IF_CHANGE:
251 /* nothing to do here */
252 break;
253 default:
254 brcmf_dbg(ERROR, "unknown event action: %u\n", ifevent->action);
255 err = -EBADE;
256 break;
257 } 267 }
258 return err; 268
269 err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
270
271 if (ifevent->action == BRCMF_E_IF_DEL)
272 brcmf_del_if(drvr, ifevent->ifidx);
259} 273}
260 274
261/** 275/**
@@ -306,13 +320,6 @@ static void brcmf_fweh_event_worker(struct work_struct *work)
306 event->emsg.ifidx, event->emsg.bsscfgidx, 320 event->emsg.ifidx, event->emsg.bsscfgidx,
307 event->emsg.addr); 321 event->emsg.addr);
308 322
309 /* handle interface event */
310 if (event->code == BRCMF_E_IF) {
311 err = brcmf_fweh_process_if_event(drvr, event, &ifp);
312 if (err)
313 goto event_free;
314 }
315
316 /* convert event message */ 323 /* convert event message */
317 emsg_be = &event->emsg; 324 emsg_be = &event->emsg;
318 emsg.version = be16_to_cpu(emsg_be->version); 325 emsg.version = be16_to_cpu(emsg_be->version);
@@ -333,13 +340,14 @@ static void brcmf_fweh_event_worker(struct work_struct *work)
333 min_t(u32, emsg.datalen, 64), 340 min_t(u32, emsg.datalen, 64),
334 "appended:"); 341 "appended:");
335 342
336 /* handle the event if valid interface and handler */ 343 /* special handling of interface event */
337 if (ifp->ndev && fweh->evt_handler[event->code]) 344 if (event->code == BRCMF_E_IF) {
338 err = fweh->evt_handler[event->code](ifp, &emsg, 345 brcmf_fweh_handle_if_event(drvr, &emsg, event->data);
339 event->data); 346 goto event_free;
340 else 347 }
341 brcmf_dbg(ERROR, "unhandled event %d ignored\n", 348
342 event->code); 349 err = brcmf_fweh_call_event_handler(ifp, event->code, &emsg,
350 event->data);
343 if (err) { 351 if (err) {
344 brcmf_dbg(ERROR, "event handler failed (%d)\n", 352 brcmf_dbg(ERROR, "event handler failed (%d)\n",
345 event->code); 353 event->code);
@@ -477,11 +485,11 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
477 *ifidx = event_packet->msg.ifidx; 485 *ifidx = event_packet->msg.ifidx;
478 data = &event_packet[1]; 486 data = &event_packet[1];
479 487
480 if (code != BRCMF_E_IF && !fweh->evt_handler[code]) { 488 if (code >= BRCMF_E_LAST)
481 brcmf_dbg(EVENT, "event ignored: code=%d\n", code); 489 return;
482 brcmf_dbg_hex_dump(BRCMF_EVENT_ON(), data, datalen, "event:"); 490
491 if (code != BRCMF_E_IF && !fweh->evt_handler[code])
483 return; 492 return;
484 }
485 493
486 if (in_interrupt()) 494 if (in_interrupt())
487 alloc_flag = GFP_ATOMIC; 495 alloc_flag = GFP_ATOMIC;