示例#1
0
文件: fweh.c 项目: AK101111/linux
/**
 * 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;
	bool is_p2pdev;
	int err = 0;

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

	/* The P2P Device interface event must not be ignored contrary to what
	 * firmware tells us. Older firmware uses p2p noif, with sta role.
	 * This should be accepted when p2pdev_setup is ongoing. TDLS setup will
	 * use the same ifevent and should be ignored.
	 */
	is_p2pdev = ((ifevent->flags & BRCMF_E_IF_FLAG_NOIF) &&
		     (ifevent->role == BRCMF_E_IF_ROLE_P2P_CLIENT ||
		      ((ifevent->role == BRCMF_E_IF_ROLE_STA) &&
		       (drvr->fweh.p2pdev_setup_ongoing))));
	if (!is_p2pdev && (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->bsscfgidx];

	if (ifevent->action == BRCMF_E_IF_ADD) {
		brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
			  emsg->addr);
		ifp = brcmf_add_if(drvr, ifevent->bsscfgidx, ifevent->ifidx,
				   is_p2pdev, emsg->ifname, emsg->addr);
		if (IS_ERR(ifp))
			return;
		if (!is_p2pdev)
			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) {
		bool armed = brcmf_cfg80211_vif_event_armed(drvr->config);

		/* Default handling in case no-one waits for this event */
		if (!armed)
			brcmf_remove_interface(ifp, false);
	}
}
示例#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);
	}
}
示例#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);
	}
}