Example #1
0
File: core.c Project: gxt/linux
void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked)
{
	if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bsscfgidx] != ifp))
		return;
	brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", ifp->bsscfgidx,
		  ifp->ifidx);
	brcmf_fws_del_interface(ifp);
	brcmf_del_if(ifp->drvr, ifp->bsscfgidx, rtnl_locked);
}
Example #2
0
/**
 * brcmf_fweh_handle_if_event() - handle IF event.
 *
 * @drvr: driver information object.
 * @item: queue entry.
 * @ifpp: interface object (may change upon ADD action).
 */
static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
				       struct brcmf_event_msg *emsg,
				       void *data)
{
	struct brcmf_if_event *ifevent = data;
	struct brcmf_if *ifp;
	int err = 0;

	brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u role: %u\n",
		  ifevent->action, ifevent->ifidx, ifevent->bssidx,
		  ifevent->flags, ifevent->role);

	/* The P2P Device interface event must not be ignored
	 * contrary to what firmware tells us. The only way to
	 * distinguish the P2P Device is by looking at the ifidx
	 * and bssidx received.
	 */
	if (!(ifevent->ifidx == 0 && ifevent->bssidx == 1) &&
	    (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) {
		brcmf_dbg(EVENT, "event can be ignored\n");
		return;
	}
	if (ifevent->ifidx >= BRCMF_MAX_IFS) {
		brcmf_err("invalid interface index: %u\n",
			  ifevent->ifidx);
		return;
	}

	ifp = drvr->iflist[ifevent->bssidx];

	if (ifevent->action == BRCMF_E_IF_ADD) {
		brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
			  emsg->addr);
		ifp = brcmf_add_if(drvr, ifevent->bssidx, ifevent->ifidx,
				   emsg->ifname, emsg->addr);
		if (IS_ERR(ifp))
			return;
		brcmf_fws_add_interface(ifp);
		if (!drvr->fweh.evt_handler[BRCMF_E_IF])
			if (brcmf_net_attach(ifp, false) < 0)
				return;
	}

	if (ifp && ifevent->action == BRCMF_E_IF_CHANGE)
		brcmf_fws_reset_interface(ifp);

	err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);

	if (ifp && ifevent->action == BRCMF_E_IF_DEL) {
		brcmf_fws_del_interface(ifp);
		brcmf_del_if(drvr, ifevent->bssidx);
	}
}
Example #3
0
/**
 * brcmf_fweh_handle_if_event() - handle IF event.
 *
 * @drvr: driver information object.
 * @item: queue entry.
 * @ifpp: interface object (may change upon ADD action).
 */
static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
				       struct brcmf_event_msg *emsg,
				       void *data)
{
	struct brcmf_if_event *ifevent = data;
	struct brcmf_if *ifp;
	int err = 0;

	brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u role: %u\n",
		  ifevent->action, ifevent->ifidx, ifevent->bssidx,
		  ifevent->flags, ifevent->role);

	if (ifevent->flags & BRCMF_E_IF_FLAG_NOIF) {
		brcmf_dbg(EVENT, "event can be ignored\n");
		return;
	}
	if (ifevent->ifidx >= BRCMF_MAX_IFS) {
		brcmf_err("invalid interface index: %u\n",
			  ifevent->ifidx);
		return;
	}

	ifp = drvr->iflist[ifevent->bssidx];

	if (ifevent->action == BRCMF_E_IF_ADD) {
		brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
			  emsg->addr);
		ifp = brcmf_add_if(drvr, ifevent->bssidx, ifevent->ifidx,
				   emsg->ifname, emsg->addr);
		if (IS_ERR(ifp))
			return;
		brcmf_fws_add_interface(ifp);
		if (!drvr->fweh.evt_handler[BRCMF_E_IF])
			if (brcmf_net_attach(ifp, false) < 0)
				return;
	}

	if (ifevent->action == BRCMF_E_IF_CHANGE)
		brcmf_fws_reset_interface(ifp);

	err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);

	if (ifevent->action == BRCMF_E_IF_DEL) {
		brcmf_fws_del_interface(ifp);
		brcmf_del_if(drvr, ifevent->bssidx);
	}
}
Example #4
0
int
brcmf_c_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
		   struct brcmf_event_msg *event, void **data_ptr)
{
	/* check whether packet is a BRCM event pkt */
	struct brcmf_event *pvt_data = (struct brcmf_event *) pktdata;
	char *event_data;
	u32 type, status;
	u16 flags;
	int evlen;

	if (memcmp(BRCM_OUI, &pvt_data->hdr.oui[0], DOT11_OUI_LEN)) {
		BRCMF_ERROR(("%s: mismatched OUI, bailing\n", __func__));
		return -EBADE;
	}

	/* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */
	if (get_unaligned_be16(&pvt_data->hdr.usr_subtype) !=
	    BCMILCP_BCM_SUBTYPE_EVENT) {
		BRCMF_ERROR(("%s: mismatched subtype, bailing\n", __func__));
		return -EBADE;
	}

	*data_ptr = &pvt_data[1];
	event_data = *data_ptr;

	/* memcpy since BRCM event pkt may be unaligned. */
	memcpy(event, &pvt_data->msg, sizeof(struct brcmf_event_msg));

	type = get_unaligned_be32(&event->event_type);
	flags = get_unaligned_be16(&event->flags);
	status = get_unaligned_be32(&event->status);
	evlen = get_unaligned_be32(&event->datalen) +
		sizeof(struct brcmf_event);

	switch (type) {
	case BRCMF_E_IF:
		{
			struct brcmf_if_event *ifevent =
					(struct brcmf_if_event *) event_data;
			BRCMF_TRACE(("%s: if event\n", __func__));

			if (ifevent->ifidx > 0 &&
				 ifevent->ifidx < BRCMF_MAX_IFS) {
				if (ifevent->action == BRCMF_E_IF_ADD)
					brcmf_add_if(drvr_priv, ifevent->ifidx,
						   NULL, event->ifname,
						   pvt_data->eth.h_dest,
						   ifevent->flags,
						   ifevent->bssidx);
				else
					brcmf_del_if(drvr_priv, ifevent->ifidx);
			} else {
				BRCMF_ERROR(("%s: Invalid ifidx %d for %s\n",
					     __func__, ifevent->ifidx,
					     event->ifname));
			}
		}
		/* send up the if event: btamp user needs it */
		*ifidx = brcmf_ifname2idx(drvr_priv, event->ifname);
		break;

		/* These are what external supplicant/authenticator wants */
	case BRCMF_E_LINK:
	case BRCMF_E_ASSOC_IND:
	case BRCMF_E_REASSOC_IND:
	case BRCMF_E_DISASSOC_IND:
	case BRCMF_E_MIC_ERROR:
	default:
		/* Fall through: this should get _everything_  */

		*ifidx = brcmf_ifname2idx(drvr_priv, event->ifname);
		BRCMF_TRACE(("%s: MAC event %d, flags %x, status %x\n",
			     __func__, type, flags, status));

		/* put it back to BRCMF_E_NDIS_LINK */
		if (type == BRCMF_E_NDIS_LINK) {
			u32 temp;

			temp = get_unaligned_be32(&event->event_type);
			BRCMF_TRACE(("Converted to WLC_E_LINK type %d\n",
				     temp));

			temp = be32_to_cpu(BRCMF_E_NDIS_LINK);
			memcpy((void *)(&pvt_data->msg.event_type), &temp,
			       sizeof(pvt_data->msg.event_type));
		}
		break;
	}

#ifdef SHOW_EVENTS
	brcmf_c_show_host_event(event, event_data);
#endif				/* SHOW_EVENTS */

	return 0;
}
int
brcmf_c_host_event(struct brcmf_pub *drvr, int *ifidx, void *pktdata,
		   struct brcmf_event_msg *event, void **data_ptr)
{
	
	struct brcmf_event *pvt_data = (struct brcmf_event *) pktdata;
	struct brcmf_if_event *ifevent;
	char *event_data;
	u32 type, status;
	u16 flags;
	int evlen;

	if (memcmp(BRCM_OUI, &pvt_data->hdr.oui[0], DOT11_OUI_LEN)) {
		brcmf_dbg(ERROR, "mismatched OUI, bailing\n");
		return -EBADE;
	}

	
	if (get_unaligned_be16(&pvt_data->hdr.usr_subtype) !=
	    BCMILCP_BCM_SUBTYPE_EVENT) {
		brcmf_dbg(ERROR, "mismatched subtype, bailing\n");
		return -EBADE;
	}

	*data_ptr = &pvt_data[1];
	event_data = *data_ptr;

	
	memcpy(event, &pvt_data->msg, sizeof(struct brcmf_event_msg));

	type = get_unaligned_be32(&event->event_type);
	flags = get_unaligned_be16(&event->flags);
	status = get_unaligned_be32(&event->status);
	evlen = get_unaligned_be32(&event->datalen) +
		sizeof(struct brcmf_event);

	switch (type) {
	case BRCMF_E_IF:
		ifevent = (struct brcmf_if_event *) event_data;
		brcmf_dbg(TRACE, "if event\n");

		if (ifevent->ifidx > 0 && ifevent->ifidx < BRCMF_MAX_IFS) {
			if (ifevent->action == BRCMF_E_IF_ADD)
				brcmf_add_if(drvr->dev, ifevent->ifidx,
					     event->ifname,
					     pvt_data->eth.h_dest);
			else
				brcmf_del_if(drvr, ifevent->ifidx);
		} else {
			brcmf_dbg(ERROR, "Invalid ifidx %d for %s\n",
				  ifevent->ifidx, event->ifname);
		}

		
		*ifidx = brcmf_ifname2idx(drvr, event->ifname);
		break;

		
	case BRCMF_E_LINK:
	case BRCMF_E_ASSOC_IND:
	case BRCMF_E_REASSOC_IND:
	case BRCMF_E_DISASSOC_IND:
	case BRCMF_E_MIC_ERROR:
	default:
		

		*ifidx = brcmf_ifname2idx(drvr, event->ifname);
		brcmf_dbg(TRACE, "MAC event %d, flags %x, status %x\n",
			  type, flags, status);

		
		if (type == BRCMF_E_NDIS_LINK) {
			u32 temp1;
			__be32 temp2;

			temp1 = get_unaligned_be32(&event->event_type);
			brcmf_dbg(TRACE, "Converted to WLC_E_LINK type %d\n",
				  temp1);

			temp2 = cpu_to_be32(BRCMF_E_NDIS_LINK);
			memcpy((void *)(&pvt_data->msg.event_type), &temp2,
			       sizeof(pvt_data->msg.event_type));
		}
		break;
	}

#ifdef DEBUG
	brcmf_c_show_host_event(event, event_data);
#endif				

	return 0;
}