brcmfmac: restructure handling of IF event
authorArend van Spriel <arend@broadcom.com>
Thu, 15 Nov 2012 02:46:16 +0000 (18:46 -0800)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 16 Nov 2012 19:28:57 +0000 (14:28 -0500)
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>
drivers/net/wireless/brcm80211/brcmfmac/fweh.c

index 7b57b8902a340ffcccfc37fce16a0020df643a76..37f853d45d30e6e56f81e7a57af737b621303ccd 100644 (file)
@@ -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;