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

Commit 0de8aace authored by Hante Meuleman's avatar Hante Meuleman Committed by John W. Linville
Browse files

brcmfmac: add support for P2P listen mode.



With this patch a device can be put in p2p listen mode and becomes
visible for other p2p devices (via p2p_find).

Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarHante Meuleman <meuleman@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent d3c0b633
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -452,6 +452,19 @@ struct brcmf_sta_info_le {
	__le32	rx_decrypt_failures;	/* # of packet decrypted failed */
};

/*
 * WLC_E_PROBRESP_MSG
 * WLC_E_P2P_PROBREQ_MSG
 * WLC_E_ACTION_FRAME_RX
 */
struct brcmf_rx_mgmt_data {
	__be16	version;
	__be16	chanspec;
	__be32	rssi;
	__be32	mactime;
	__be32	rate;
};

/* Bus independent dongle command */
struct brcmf_dcmd {
	uint cmd;		/* common dongle cmd definition */
+5 −1
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ struct brcmf_event;
	BRCMF_ENUM_DEF(MULTICAST_DECODE_ERROR, 51) \
	BRCMF_ENUM_DEF(TRACE, 52) \
	BRCMF_ENUM_DEF(IF, 54) \
	BRCMF_ENUM_DEF(P2P_DISC_LISTEN_COMPLETE, 55) \
	BRCMF_ENUM_DEF(RSSI, 56) \
	BRCMF_ENUM_DEF(PFN_SCAN_COMPLETE, 57) \
	BRCMF_ENUM_DEF(EXTLOG_MSG, 58) \
@@ -96,8 +97,11 @@ struct brcmf_event;
	BRCMF_ENUM_DEF(DFS_AP_RESUME, 66) \
	BRCMF_ENUM_DEF(ESCAN_RESULT, 69) \
	BRCMF_ENUM_DEF(ACTION_FRAME_OFF_CHAN_COMPLETE, 70) \
	BRCMF_ENUM_DEF(PROBERESP_MSG, 71) \
	BRCMF_ENUM_DEF(P2P_PROBEREQ_MSG, 72) \
	BRCMF_ENUM_DEF(DCS_REQUEST, 73) \
	BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74)
	BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \
	BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75)

#define BRCMF_ENUM_DEF(id, val) \
	BRCMF_E_##id = (val),
+124 −26
Original line number Diff line number Diff line
@@ -318,11 +318,6 @@ static s32 brcmf_p2p_deinit_discovery(struct brcmf_p2p_info *p2p)
	brcmf_dbg(TRACE, "enter\n");

	bss_dev = &p2p->bss_idx[P2PAPI_BSSCFG_DEVICE];
	if (bss_dev->vif == NULL) {
		brcmf_err("do nothing, not initialized\n");
		return -EINVAL;
	}

	ifp = bss_dev->vif->ifp;

	/* Set the discovery state to SCAN */
@@ -348,8 +343,7 @@ static s32 brcmf_p2p_deinit_discovery(struct brcmf_p2p_info *p2p)
 *
 * Initializes the discovery device and configure the virtual interface.
 */
static int brcmf_p2p_enable_discovery(struct brcmf_p2p_info *p2p,
				      const u8 *ie, u32 ie_len)
static int brcmf_p2p_enable_discovery(struct brcmf_p2p_info *p2p)
{
	struct brcmf_cfg80211_vif *vif;
	s32 ret = 0;
@@ -357,9 +351,8 @@ static int brcmf_p2p_enable_discovery(struct brcmf_p2p_info *p2p,
	brcmf_dbg(TRACE, "enter\n");
	vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
	if (vif) {
		brcmf_dbg(INFO,
			  "DISCOVERY init already done, just process IE\n");
		goto set_ie;
		brcmf_dbg(INFO, "DISCOVERY init already done\n");
		goto exit;
	}

	ret = brcmf_p2p_init_discovery(p2p);
@@ -380,20 +373,36 @@ static int brcmf_p2p_enable_discovery(struct brcmf_p2p_info *p2p,
	if (ret < 0)
		brcmf_err("wsec error %d\n", ret);

set_ie:
	if (ie_len) {
		ret = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBREQ_FLAG,
					    ie, ie_len);

		if (ret < 0) {
			brcmf_err("set probreq ie occurs error %d\n", ret);
			goto exit;
		}
	}
exit:
	return ret;
}

/**
 * brcmf_p2p_configure_probereq() - Configure probe request data.
 *
 * @p2p: P2P specific data.
 * @ie: buffer containing information elements.
 * @ie_len: length of @ie buffer.
 *
 */
static int brcmf_p2p_configure_probereq(struct brcmf_p2p_info *p2p,
					const u8 *ie, u32 ie_len)
{
	struct brcmf_cfg80211_vif *vif;
	s32 err = 0;

	brcmf_dbg(TRACE, "enter\n");
	vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;

	err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBREQ_FLAG,
				    ie, ie_len);

	if (err < 0)
		brcmf_err("set probreq ie occurs error %d\n", err);

	return err;
}

/*
 * brcmf_p2p_escan() - initiate a P2P scan.
 *
@@ -420,9 +429,6 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
	struct brcmf_scan_params_le *sparams;
	struct brcmf_ssid ssid;

	/* add padding if uneven */
	if (num_chans % 2)
		memsize += sizeof(__le16);
	memsize += num_chans * sizeof(__le16);
	memblk = kzalloc(memsize, GFP_KERNEL);
	if (!memblk)
@@ -639,7 +645,9 @@ int brcmf_p2p_scan_prep(struct wiphy *wiphy,
		clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status);
		brcmf_dbg(INFO, "P2P: GO_NEG_PHASE status cleared\n");

		err = brcmf_p2p_enable_discovery(p2p, request->ie,
		err = brcmf_p2p_enable_discovery(p2p);
		if (err == 0)
			err = brcmf_p2p_configure_probereq(p2p, request->ie,
							   request->ie_len);

		/*
@@ -666,6 +674,92 @@ int brcmf_p2p_scan_prep(struct wiphy *wiphy,
	return err;
}


/**
 * brcmf_p2p_remain_on_channel() - put device on channel and stay there.
 *
 * @wiphy: wiphy device.
 * @channel: channel to stay on.
 * @duration: time in ms to remain on channel.
 *
 */
int brcmf_p2p_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
				struct ieee80211_channel *channel,
				unsigned int duration, u64 *cookie)
{
	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
	struct brcmf_p2p_info *p2p = &cfg->p2p;
	struct brcmf_cfg80211_vif *vif;
	s32 err;
	u16 chanspec;

	brcmf_dbg(TRACE, "Enter, channel: %d, duration ms (%d)\n",
		  ieee80211_frequency_to_channel(channel->center_freq),
		  duration);

	*cookie = 0;
	err = brcmf_p2p_enable_discovery(p2p);
	if (err)
		goto exit;

	chanspec = channel_to_chanspec(channel);
	vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
	err = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_LISTEN,
					   chanspec, (u16)duration);
	if (err)
		goto exit;

	memcpy(&p2p->remain_on_channel, channel,
	       sizeof(p2p->remain_on_channel));

	set_bit(BRCMF_P2P_STATUS_REMAIN_ON_CHANNEL, &p2p->status);

exit:
	cfg80211_ready_on_channel(wdev, *cookie, channel, duration, GFP_KERNEL);
	return err;
}


/**
 * brcmf_p2p_notify_listen_complete() - p2p listen has completed.
 *
 * @ifp: interfac control.
 * @e: event message. Not used, to make it usable for fweh event dispatcher.
 * @data: payload of message. Not used.
 *
 */
int brcmf_p2p_notify_listen_complete(struct brcmf_if *ifp,
				     const struct brcmf_event_msg *e,
				     void *data)
{
	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
	struct brcmf_p2p_info *p2p = &cfg->p2p;

	brcmf_dbg(TRACE, "Enter\n");
	if (test_and_clear_bit(BRCMF_P2P_STATUS_REMAIN_ON_CHANNEL,
			       &p2p->status))
		cfg80211_remain_on_channel_expired(&ifp->vif->wdev, 0,
						   &p2p->remain_on_channel,
						   GFP_KERNEL);
	return 0;
}


/**
 * brcmf_p2p_cancel_remain_on_channel() - cancel p2p listen state.
 *
 * @ifp: interfac control.
 *
 */
void brcmf_p2p_cancel_remain_on_channel(struct brcmf_if *ifp)
{
	if (!ifp)
		return;
	brcmf_p2p_set_discover_state(ifp, WL_P2P_DISC_ST_SCAN, 0, 0);
	brcmf_p2p_notify_listen_complete(ifp, NULL, NULL);
}


/**
 * brcmf_p2p_attach() - attach for P2P.
 *
@@ -689,7 +783,11 @@ void brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
 */
void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
{
	if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif != NULL) {
		brcmf_p2p_cancel_remain_on_channel(
			p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->ifp);
		brcmf_p2p_deinit_discovery(p2p);
	}
	/* just set it all to zero */
	memset(p2p, 0, sizeof(*p2p));
}
+12 −3
Original line number Diff line number Diff line
@@ -60,10 +60,10 @@ struct p2p_bss {
 * @BRCMF_P2P_STATUS_IF_DELETING: peer-to-peer vif delete sent to dongle.
 * @BRCMF_P2P_STATUS_IF_CHANGING: peer-to-peer vif change sent to dongle.
 * @BRCMF_P2P_STATUS_IF_CHANGED: peer-to-peer vif change completed on dongle.
 * @BRCMF_P2P_STATUS_LISTEN_EXPIRED: listen duration expired.
 * @BRCMF_P2P_STATUS_ACTION_TX_COMPLETED: action frame tx completed.
 * @BRCMF_P2P_STATUS_ACTION_TX_NOACK: action frame tx not acked.
 * @BRCMF_P2P_STATUS_GO_NEG_PHASE: P2P GO negotiation ongoing.
 * @BRCMF_P2P_STATUS_REMAIN_ON_CHANNEL: P2P listen, remaining on channel.
 */
enum brcmf_p2p_status {
	BRCMF_P2P_STATUS_IF_ADD = 0,
@@ -71,10 +71,10 @@ enum brcmf_p2p_status {
	BRCMF_P2P_STATUS_IF_DELETING,
	BRCMF_P2P_STATUS_IF_CHANGING,
	BRCMF_P2P_STATUS_IF_CHANGED,
	BRCMF_P2P_STATUS_LISTEN_EXPIRED,
	BRCMF_P2P_STATUS_ACTION_TX_COMPLETED,
	BRCMF_P2P_STATUS_ACTION_TX_NOACK,
	BRCMF_P2P_STATUS_GO_NEG_PHASE
	BRCMF_P2P_STATUS_GO_NEG_PHASE,
	BRCMF_P2P_STATUS_REMAIN_ON_CHANNEL
};

/**
@@ -88,6 +88,7 @@ enum brcmf_p2p_status {
 * @listen_timer: timer for @WL_P2P_DISC_ST_LISTEN discover state.
 * @ssid: ssid for P2P GO.
 * @listen_channel: channel for @WL_P2P_DISC_ST_LISTEN discover state.
 * @remain_on_channel: contains copy of struct used by cfg80211.
 */
struct brcmf_p2p_info {
	struct brcmf_cfg80211_info *cfg;
@@ -98,6 +99,7 @@ struct brcmf_p2p_info {
	struct timer_list listen_timer;
	struct brcmf_ssid ssid;
	u8 listen_channel;
	struct ieee80211_channel remain_on_channel;
};

void brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg);
@@ -110,5 +112,12 @@ int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev);
void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev);
int brcmf_p2p_scan_prep(struct wiphy *wiphy,
			struct cfg80211_scan_request *request);
int brcmf_p2p_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
				struct ieee80211_channel *channel,
				unsigned int duration, u64 *cookie);
int brcmf_p2p_notify_listen_complete(struct brcmf_if *ifp,
				     const struct brcmf_event_msg *e,
				     void *data);
void brcmf_p2p_cancel_remain_on_channel(struct brcmf_if *ifp);

#endif /* WL_CFGP2P_H_ */
+185 −4
Original line number Diff line number Diff line
@@ -3359,6 +3359,11 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
			mgmt_ie_len = &saved_ie->probe_req_ie_len;
			mgmt_ie_buf_len = sizeof(saved_ie->probe_req_ie);
			break;
		case BRCMF_VNDR_IE_PRBRSP_FLAG:
			mgmt_ie_buf = saved_ie->probe_res_ie;
			mgmt_ie_len = &saved_ie->probe_res_ie_len;
			mgmt_ie_buf_len = sizeof(saved_ie->probe_res_ie);
			break;
		default:
			err = -EPERM;
			brcmf_err("not suitable type\n");
@@ -3674,6 +3679,150 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
	return err;
}


static void
brcmf_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
				   struct wireless_dev *wdev,
				   u16 frame_type, bool reg)
{
	struct brcmf_if *ifp = netdev_priv(wdev->netdev);
	struct brcmf_cfg80211_vif *vif = ifp->vif;
	u16 mgmt_type;

	brcmf_dbg(TRACE, "Enter, frame_type %04x, reg=%d\n", frame_type, reg);

	mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
	if (reg)
		vif->mgmt_rx_reg |= BIT(mgmt_type);
	else
		vif->mgmt_rx_reg |= ~BIT(mgmt_type);
}


static int
brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
		       struct ieee80211_channel *chan, bool offchan,
		       unsigned int wait, const u8 *buf, size_t len,
		       bool no_cck, bool dont_wait_for_ack, u64 *cookie)
{
	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
	const struct ieee80211_mgmt *mgmt;
	struct brcmf_cfg80211_vif *vif;
	s32 err = 0;
	s32 ie_offset;
	s32 ie_len;

	brcmf_dbg(TRACE, "Enter\n");

	*cookie = 0;

	mgmt = (const struct ieee80211_mgmt *)buf;

	if (ieee80211_is_mgmt(mgmt->frame_control)) {
		if (ieee80211_is_probe_resp(mgmt->frame_control)) {
			/* Right now the only reason to get a probe response */
			/* is for p2p listen response from wpa_supplicant.   */
			/* Unfortunately the wpa_supplicant sends it on the  */
			/* primary ndev, while dongle wants it on the p2p    */
			/* vif. Since this is only reason for a probe        */
			/* response to be sent, the vif is taken from cfg.   */
			/* If ever desired to send proberesp for non p2p     */
			/* response then data should be checked for          */
			/* "DIRECT-". Note in future supplicant will take    */
			/* dedicated p2p wdev to do this and then this 'hack'*/
			/* is not needed anymore.                            */
			ie_offset =  DOT11_MGMT_HDR_LEN +
				     DOT11_BCN_PRB_FIXED_LEN;
			ie_len = len - ie_offset;

			vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
			if (vif == NULL) {
				brcmf_err("No p2p device available for probe response\n");
				err = -ENODEV;
				goto exit;
			}
			err = brcmf_vif_set_mgmt_ie(vif,
						    BRCMF_VNDR_IE_PRBRSP_FLAG,
						    &buf[ie_offset],
						    ie_len);
			cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true,
						GFP_KERNEL);
			goto exit;
		}
	}
	brcmf_dbg(TRACE, "Unhandled, is_mgmt %d, fc=%04x!!!!!\n",
		  ieee80211_is_mgmt(mgmt->frame_control), mgmt->frame_control);
exit:
	return err;
}


static int
brcmf_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
					struct wireless_dev *wdev,
					u64 cookie)
{
	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
	struct brcmf_cfg80211_vif *vif;
	int err = 0;

	brcmf_dbg(TRACE, "Enter p2p listen cancel\n");

	vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
	if (vif == NULL) {
		brcmf_err("No p2p device available for probe response\n");
		err = -ENODEV;
		goto exit;
	}
	brcmf_p2p_cancel_remain_on_channel(vif->ifp);
exit:
	return err;
}

static s32 brcmf_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
					     const struct brcmf_event_msg *e,
					     void *data)
{
	struct wireless_dev *wdev;
	struct brcmf_cfg80211_vif *vif = ifp->vif;
	struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data;
	u16 chanspec = be16_to_cpu(rxframe->chanspec);
	u8 *mgmt_frame;
	u32 mgmt_frame_len;
	s32 freq;
	u16 mgmt_type;

	brcmf_dbg(INFO,
		  "Enter: event %d reason %d\n", e->event_code, e->reason);

	/* Firmware sends us two proberesponses for each idx one. At the */
	/* moment only bsscfgidx 0 is passed up to supplicant            */
	if (e->bsscfgidx)
		return 0;

	/* Check if wpa_supplicant has registered for this frame */
	brcmf_dbg(INFO, "vif->mgmt_rx_reg %04x\n", vif->mgmt_rx_reg);
	mgmt_type = (IEEE80211_STYPE_PROBE_REQ & IEEE80211_FCTL_STYPE) >> 4;
	if ((vif->mgmt_rx_reg & BIT(mgmt_type)) == 0)
		return 0;

	mgmt_frame = (u8 *)(rxframe + 1);
	mgmt_frame_len = e->datalen - sizeof(*rxframe);
	freq = ieee80211_channel_to_frequency(CHSPEC_CHANNEL(chanspec),
					      CHSPEC_IS2G(chanspec) ?
					      IEEE80211_BAND_2GHZ :
					      IEEE80211_BAND_5GHZ);
	wdev = ifp->ndev->ieee80211_ptr;
	cfg80211_rx_mgmt(wdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);

	brcmf_dbg(INFO,
		  "mgmt_frame_len (%d) , e->datalen (%d), chanspec (%04x), freq (%d)\n",
		  mgmt_frame_len, e->datalen, chanspec, freq);

	return 0;
}


static struct cfg80211_ops wl_cfg80211_ops = {
	.add_virtual_intf = brcmf_cfg80211_add_iface,
	.del_virtual_intf = brcmf_cfg80211_del_iface,
@@ -3703,6 +3852,10 @@ static struct cfg80211_ops wl_cfg80211_ops = {
	.del_station = brcmf_cfg80211_del_station,
	.sched_scan_start = brcmf_cfg80211_sched_scan_start,
	.sched_scan_stop = brcmf_cfg80211_sched_scan_stop,
	.mgmt_frame_register = brcmf_cfg80211_mgmt_frame_register,
	.mgmt_tx = brcmf_cfg80211_mgmt_tx,
	.remain_on_channel = brcmf_p2p_remain_on_channel,
	.cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel,
#ifdef CONFIG_NL80211_TESTMODE
	.testmode_cmd = brcmf_cfg80211_testmode
#endif
@@ -3765,6 +3918,30 @@ static const struct ieee80211_iface_combination brcmf_iface_combos[] = {
	}
};

static const struct ieee80211_txrx_stypes
brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
	[NL80211_IFTYPE_STATION] = {
		.tx = 0xffff,
		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
	},
	[NL80211_IFTYPE_P2P_CLIENT] = {
		.tx = 0xffff,
		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
	},
	[NL80211_IFTYPE_P2P_GO] = {
		.tx = 0xffff,
		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
		      BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
		      BIT(IEEE80211_STYPE_DISASSOC >> 4) |
		      BIT(IEEE80211_STYPE_AUTH >> 4) |
		      BIT(IEEE80211_STYPE_DEAUTH >> 4) |
		      BIT(IEEE80211_STYPE_ACTION >> 4)
	}
};

static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
{
	struct wiphy *wiphy;
@@ -3797,10 +3974,10 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
	wiphy->cipher_suites = __wl_cipher_suites;
	wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
	wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;	/* enable power
								 * save mode
								 * by default
								 */
	wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT |
			WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
	wiphy->mgmt_stypes = brcmf_txrx_stypes;
	wiphy->max_remain_on_channel_duration = 5000;
	brcmf_wiphy_pno_params(wiphy);
	err = wiphy_register(wiphy);
	if (err < 0) {
@@ -4271,6 +4448,10 @@ static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg)
			    brcmf_notify_sched_scan_results);
	brcmf_fweh_register(cfg->pub, BRCMF_E_IF,
			    brcmf_notify_vif_event);
	brcmf_fweh_register(cfg->pub, BRCMF_E_P2P_PROBEREQ_MSG,
			    brcmf_notify_rx_mgmt_p2p_probereq);
	brcmf_fweh_register(cfg->pub, BRCMF_E_P2P_DISC_LISTEN_COMPLETE,
			    brcmf_p2p_notify_listen_complete);
}

static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg)
Loading