diff options
author | Arend van Spriel <arend@broadcom.com> | 2012-11-14 21:46:16 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-11-16 14:28:57 -0500 |
commit | 3e0a97e1507c482d2299a6ff24e597c1316ba60a (patch) | |
tree | c05e911af1244d3ee863860a8f9f62c615d358a2 | |
parent | b522dd8071947be7f62e75d7de5b6b3de0d882f5 (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.c | 102 |
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 | ||
208 | static 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 | */ |
215 | static int brcmf_fweh_process_if_event(struct brcmf_pub *drvr, | 237 | static 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; |