summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac
diff options
context:
space:
mode:
authorArend van Spriel <arend@broadcom.com>2012-11-14 18:46:16 -0800
committerJohn W. Linville <linville@tuxdriver.com>2012-11-16 14:28:57 -0500
commit3e0a97e1507c482d2299a6ff24e597c1316ba60a (patch)
treec05e911af1244d3ee863860a8f9f62c615d358a2 /drivers/net/wireless/brcm80211/brcmfmac
parentb522dd8071947be7f62e75d7de5b6b3de0d882f5 (diff)
downloadlinux-3e0a97e1507c482d2299a6ff24e597c1316ba60a.tar.bz2
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>
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac')
-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,
schedule_work(&fweh->event_work);
}
+static int brcmf_fweh_call_event_handler(struct brcmf_if *ifp,
+ enum brcmf_fweh_event_code code,
+ struct brcmf_event_msg *emsg,
+ void *data)
+{
+ struct brcmf_fweh_info *fweh;
+ int err = -EINVAL;
+
+ if (ifp) {
+ fweh = &ifp->drvr->fweh;
+
+ /* handle the event if valid interface and handler */
+ if (ifp->ndev && fweh->evt_handler[code])
+ err = fweh->evt_handler[code](ifp, emsg, data);
+ else
+ brcmf_dbg(ERROR, "unhandled event %d ignored\n", code);
+ } else {
+ brcmf_dbg(ERROR, "no interface object\n");
+ }
+ return err;
+}
+
/**
- * brcmf_fweh_process_if_event() - handle IF event.
+ * brcmf_fweh_handle_if_event() - handle IF event.
*
* @drvr: driver information object.
* @item: queue entry.
* @ifpp: interface object (may change upon ADD action).
*/
-static int brcmf_fweh_process_if_event(struct brcmf_pub *drvr,
- struct brcmf_fweh_queue_item *item,
- struct brcmf_if **ifpp)
+static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
+ struct brcmf_event_msg *emsg,
+ void *data)
{
- struct brcmf_event_msg_be *event = &item->emsg;
- struct brcmf_if_event *ifevent = (struct brcmf_if_event *)item->data;
+ struct brcmf_if_event *ifevent = data;
struct brcmf_if *ifp;
int err = 0;
@@ -228,34 +249,27 @@ static int brcmf_fweh_process_if_event(struct brcmf_pub *drvr,
if (ifevent->ifidx >= BRCMF_MAX_IFS) {
brcmf_dbg(ERROR, "invalid interface index: %u\n",
ifevent->ifidx);
- return -EINVAL;
+ return;
}
- switch (ifevent->action) {
- case BRCMF_E_IF_ADD:
- brcmf_dbg(EVENT, "adding %s (%pM, %pM)\n", event->ifname,
- event->addr, item->ifaddr);
+ ifp = drvr->iflist[ifevent->ifidx];
+
+ if (ifevent->action == BRCMF_E_IF_ADD) {
+ brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
+ emsg->addr);
ifp = brcmf_add_if(drvr, ifevent->ifidx, ifevent->bssidx,
- event->ifname, item->ifaddr);
- if (!IS_ERR(ifp)) {
- *ifpp = ifp;
+ emsg->ifname, emsg->addr);
+ if (IS_ERR(ifp))
+ return;
+
+ if (!drvr->fweh.evt_handler[BRCMF_E_IF])
err = brcmf_net_attach(ifp);
- } else {
- err = PTR_ERR(ifp);
- }
- break;
- case BRCMF_E_IF_DEL:
- brcmf_del_if(drvr, ifevent->ifidx);
- break;
- case BRCMF_E_IF_CHANGE:
- /* nothing to do here */
- break;
- default:
- brcmf_dbg(ERROR, "unknown event action: %u\n", ifevent->action);
- err = -EBADE;
- break;
}
- return err;
+
+ err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
+
+ if (ifevent->action == BRCMF_E_IF_DEL)
+ brcmf_del_if(drvr, ifevent->ifidx);
}
/**
@@ -306,13 +320,6 @@ static void brcmf_fweh_event_worker(struct work_struct *work)
event->emsg.ifidx, event->emsg.bsscfgidx,
event->emsg.addr);
- /* handle interface event */
- if (event->code == BRCMF_E_IF) {
- err = brcmf_fweh_process_if_event(drvr, event, &ifp);
- if (err)
- goto event_free;
- }
-
/* convert event message */
emsg_be = &event->emsg;
emsg.version = be16_to_cpu(emsg_be->version);
@@ -333,13 +340,14 @@ static void brcmf_fweh_event_worker(struct work_struct *work)
min_t(u32, emsg.datalen, 64),
"appended:");
- /* handle the event if valid interface and handler */
- if (ifp->ndev && fweh->evt_handler[event->code])
- err = fweh->evt_handler[event->code](ifp, &emsg,
- event->data);
- else
- brcmf_dbg(ERROR, "unhandled event %d ignored\n",
- event->code);
+ /* special handling of interface event */
+ if (event->code == BRCMF_E_IF) {
+ brcmf_fweh_handle_if_event(drvr, &emsg, event->data);
+ goto event_free;
+ }
+
+ err = brcmf_fweh_call_event_handler(ifp, event->code, &emsg,
+ event->data);
if (err) {
brcmf_dbg(ERROR, "event handler failed (%d)\n",
event->code);
@@ -477,11 +485,11 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
*ifidx = event_packet->msg.ifidx;
data = &event_packet[1];
- if (code != BRCMF_E_IF && !fweh->evt_handler[code]) {
- brcmf_dbg(EVENT, "event ignored: code=%d\n", code);
- brcmf_dbg_hex_dump(BRCMF_EVENT_ON(), data, datalen, "event:");
+ if (code >= BRCMF_E_LAST)
+ return;
+
+ if (code != BRCMF_E_IF && !fweh->evt_handler[code])
return;
- }
if (in_interrupt())
alloc_flag = GFP_ATOMIC;