Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3e0a97e1 authored by Arend van Spriel's avatar Arend van Spriel Committed by John W. Linville
Browse files

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: default avatarHante Meuleman <meuleman@broadcom.com>
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarFranky Lin <frankyl@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent b522dd80
Loading
Loading
Loading
Loading
+55 −47
Original line number Original line Diff line number Diff line
@@ -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:
	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);
		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;
}
}


/**
/**
@@ -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);
			goto event_free;
		}

		err = brcmf_fweh_call_event_handler(ifp, event->code, &emsg,
						    event->data);
						    event->data);
		else
			brcmf_dbg(ERROR, "unhandled event %d ignored\n",
				  event->code);
		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;