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>
This commit is contained in:
parent
b522dd8071
commit
3e0a97e150
|
@ -205,19 +205,40 @@ static void brcmf_fweh_queue_event(struct brcmf_fweh_info *fweh,
|
||||||
schedule_work(&fweh->event_work);
|
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.
|
* @drvr: driver information object.
|
||||||
* @item: queue entry.
|
* @item: queue entry.
|
||||||
* @ifpp: interface object (may change upon ADD action).
|
* @ifpp: interface object (may change upon ADD action).
|
||||||
*/
|
*/
|
||||||
static int brcmf_fweh_process_if_event(struct brcmf_pub *drvr,
|
static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
|
||||||
struct brcmf_fweh_queue_item *item,
|
struct brcmf_event_msg *emsg,
|
||||||
struct brcmf_if **ifpp)
|
void *data)
|
||||||
{
|
{
|
||||||
struct brcmf_event_msg_be *event = &item->emsg;
|
struct brcmf_if_event *ifevent = data;
|
||||||
struct brcmf_if_event *ifevent = (struct brcmf_if_event *)item->data;
|
|
||||||
struct brcmf_if *ifp;
|
struct brcmf_if *ifp;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
@ -228,34 +249,27 @@ static int brcmf_fweh_process_if_event(struct brcmf_pub *drvr,
|
||||||
if (ifevent->ifidx >= BRCMF_MAX_IFS) {
|
if (ifevent->ifidx >= BRCMF_MAX_IFS) {
|
||||||
brcmf_dbg(ERROR, "invalid interface index: %u\n",
|
brcmf_dbg(ERROR, "invalid interface index: %u\n",
|
||||||
ifevent->ifidx);
|
ifevent->ifidx);
|
||||||
return -EINVAL;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ifevent->action) {
|
ifp = drvr->iflist[ifevent->ifidx];
|
||||||
case BRCMF_E_IF_ADD:
|
|
||||||
brcmf_dbg(EVENT, "adding %s (%pM, %pM)\n", event->ifname,
|
if (ifevent->action == BRCMF_E_IF_ADD) {
|
||||||
event->addr, item->ifaddr);
|
brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
|
||||||
|
emsg->addr);
|
||||||
ifp = brcmf_add_if(drvr, ifevent->ifidx, ifevent->bssidx,
|
ifp = brcmf_add_if(drvr, ifevent->ifidx, ifevent->bssidx,
|
||||||
event->ifname, item->ifaddr);
|
emsg->ifname, emsg->addr);
|
||||||
if (!IS_ERR(ifp)) {
|
if (IS_ERR(ifp))
|
||||||
*ifpp = ifp;
|
return;
|
||||||
|
|
||||||
|
if (!drvr->fweh.evt_handler[BRCMF_E_IF])
|
||||||
err = brcmf_net_attach(ifp);
|
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.ifidx, event->emsg.bsscfgidx,
|
||||||
event->emsg.addr);
|
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 */
|
/* convert event message */
|
||||||
emsg_be = &event->emsg;
|
emsg_be = &event->emsg;
|
||||||
emsg.version = be16_to_cpu(emsg_be->version);
|
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),
|
min_t(u32, emsg.datalen, 64),
|
||||||
"appended:");
|
"appended:");
|
||||||
|
|
||||||
/* handle the event if valid interface and handler */
|
/* special handling of interface event */
|
||||||
if (ifp->ndev && fweh->evt_handler[event->code])
|
if (event->code == BRCMF_E_IF) {
|
||||||
err = fweh->evt_handler[event->code](ifp, &emsg,
|
brcmf_fweh_handle_if_event(drvr, &emsg, event->data);
|
||||||
event->data);
|
goto event_free;
|
||||||
else
|
}
|
||||||
brcmf_dbg(ERROR, "unhandled event %d ignored\n",
|
|
||||||
event->code);
|
err = brcmf_fweh_call_event_handler(ifp, event->code, &emsg,
|
||||||
|
event->data);
|
||||||
if (err) {
|
if (err) {
|
||||||
brcmf_dbg(ERROR, "event handler failed (%d)\n",
|
brcmf_dbg(ERROR, "event handler failed (%d)\n",
|
||||||
event->code);
|
event->code);
|
||||||
|
@ -477,11 +485,11 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
|
||||||
*ifidx = event_packet->msg.ifidx;
|
*ifidx = event_packet->msg.ifidx;
|
||||||
data = &event_packet[1];
|
data = &event_packet[1];
|
||||||
|
|
||||||
if (code != BRCMF_E_IF && !fweh->evt_handler[code]) {
|
if (code >= BRCMF_E_LAST)
|
||||||
brcmf_dbg(EVENT, "event ignored: code=%d\n", code);
|
return;
|
||||||
brcmf_dbg_hex_dump(BRCMF_EVENT_ON(), data, datalen, "event:");
|
|
||||||
|
if (code != BRCMF_E_IF && !fweh->evt_handler[code])
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (in_interrupt())
|
if (in_interrupt())
|
||||||
alloc_flag = GFP_ATOMIC;
|
alloc_flag = GFP_ATOMIC;
|
||||||
|
|
Loading…
Reference in New Issue