Skip to content

Commit

Permalink
brcmfmac: restructure handling of IF event
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Arend van Spriel authored and John W. Linville committed Nov 16, 2012
1 parent b522dd8 commit 3e0a97e
Showing 1 changed file with 55 additions and 47 deletions.
102 changes: 55 additions & 47 deletions drivers/net/wireless/brcm80211/brcmfmac/fweh.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);
}

/**
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 3e0a97e

Please sign in to comment.