diff options
| author | hauke <hauke@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2013-02-24 01:11:20 +0000 | 
|---|---|---|
| committer | hauke <hauke@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2013-02-24 01:11:20 +0000 | 
| commit | 60ba17b69f9bc3c752555b64e8d6aff9eb263d56 (patch) | |
| tree | 9cee6208f53d8dea76ddb1a6a75dbea7fac76124 /package | |
| parent | f5eb604a40dc934ae09752e54af561d9e6d0f7f9 (diff) | |
mac80211: brcmsmac: add ap mode support
This does not work very well. I did not got this running in 5GHz mode and it was not very fast.
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@35763 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package')
14 files changed, 1121 insertions, 0 deletions
diff --git a/package/mac80211/patches/860-brcmsmac-implement-ieee80211_ops-get_tsf-and-set_tsf.patch b/package/mac80211/patches/860-brcmsmac-implement-ieee80211_ops-get_tsf-and-set_tsf.patch new file mode 100644 index 000000000..33991bcf6 --- /dev/null +++ b/package/mac80211/patches/860-brcmsmac-implement-ieee80211_ops-get_tsf-and-set_tsf.patch @@ -0,0 +1,121 @@ +--- a/drivers/net/wireless/brcm80211/brcmsmac/d11.h ++++ b/drivers/net/wireless/brcm80211/brcmsmac/d11.h +@@ -457,6 +457,7 @@ struct d11regs { + /*== maccontrol register ==*/ + #define	MCTL_GMODE		(1U << 31) + #define	MCTL_DISCARD_PMQ	(1 << 30) ++#define	MCTL_TBTTHOLD		(1 << 28) + #define	MCTL_WAKE		(1 << 26) + #define	MCTL_HPS		(1 << 25) + #define	MCTL_PROMISC		(1 << 24) +--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +@@ -741,6 +741,28 @@ static void brcms_ops_flush(struct ieee8 + 			   "ret=%d\n", jiffies_to_msecs(ret)); + } +  ++static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) ++{ ++	struct brcms_info *wl = hw->priv; ++	u64 tsf; ++ ++	spin_lock_bh(&wl->lock); ++	tsf = brcms_c_tsf_get(wl->wlc); ++	spin_unlock_bh(&wl->lock); ++ ++	return tsf; ++} ++ ++static void brcms_ops_set_tsf(struct ieee80211_hw *hw, ++			   struct ieee80211_vif *vif, u64 tsf) ++{ ++	struct brcms_info *wl = hw->priv; ++ ++	spin_lock_bh(&wl->lock); ++	brcms_c_tsf_set(wl->wlc, tsf); ++	spin_unlock_bh(&wl->lock); ++} ++ + static const struct ieee80211_ops brcms_ops = { + 	.tx = brcms_ops_tx, + 	.start = brcms_ops_start, +@@ -757,6 +779,8 @@ static const struct ieee80211_ops brcms_ + 	.ampdu_action = brcms_ops_ampdu_action, + 	.rfkill_poll = brcms_ops_rfkill_poll, + 	.flush = brcms_ops_flush, ++	.get_tsf = brcms_ops_get_tsf, ++	.set_tsf = brcms_ops_set_tsf, + }; +  + void brcms_dpc(unsigned long data) +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c +@@ -5545,6 +5545,20 @@ int brcms_c_set_rateset(struct brcms_c_i + 	return bcmerror; + } +  ++static void brcms_c_time_lock(struct brcms_c_info *wlc) ++{ ++	bcma_set32(wlc->hw->d11core, D11REGOFFS(maccontrol), MCTL_TBTTHOLD); ++	/* Commit the write */ ++	bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol)); ++} ++ ++static void brcms_c_time_unlock(struct brcms_c_info *wlc) ++{ ++	bcma_mask32(wlc->hw->d11core, D11REGOFFS(maccontrol), ~MCTL_TBTTHOLD); ++	/* Commit the write */ ++	bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol)); ++} ++ + int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period) + { + 	if (period == 0) +@@ -7530,6 +7544,36 @@ void brcms_c_set_beacon_listen_interval( + 		brcms_c_bcn_li_upd(wlc); + } +  ++u64 brcms_c_tsf_get(struct brcms_c_info *wlc) ++{ ++	u32 tsf_h, tsf_l; ++	u64 tsf; ++ ++	brcms_b_read_tsf(wlc->hw, &tsf_l, &tsf_h); ++ ++	tsf = tsf_h; ++	tsf <<= 32; ++	tsf |= tsf_l; ++ ++	return tsf; ++} ++ ++void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf) ++{ ++	u32 tsf_h, tsf_l; ++ ++	brcms_c_time_lock(wlc); ++ ++	tsf_l = tsf; ++	tsf_h = (tsf >> 32); ++ ++	/* read the tsf timer low, then high to get an atomic read */ ++	bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_timerlow), tsf_l); ++	bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_timerhigh), tsf_h); ++ ++	brcms_c_time_unlock(wlc); ++} ++ + int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr) + { + 	uint qdbm; +--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h ++++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h +@@ -326,6 +326,8 @@ extern void brcms_c_set_shortslot_overri + 				    s8 sslot_override); + extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, + 					u8 interval); ++extern u64 brcms_c_tsf_get(struct brcms_c_info *wlc); ++extern void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf); + extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr); + extern int brcms_c_get_tx_power(struct brcms_c_info *wlc); + extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc); diff --git a/package/mac80211/patches/861-brcmsmac-add-interface-type-to-brcms_bss_cfg.patch b/package/mac80211/patches/861-brcmsmac-add-interface-type-to-brcms_bss_cfg.patch new file mode 100644 index 000000000..21b1e0e4d --- /dev/null +++ b/package/mac80211/patches/861-brcmsmac-add-interface-type-to-brcms_bss_cfg.patch @@ -0,0 +1,66 @@ +--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +@@ -367,9 +367,10 @@ brcms_ops_add_interface(struct ieee80211 + 	} +  + 	spin_lock_bh(&wl->lock); +-	memcpy(wl->pub->cur_etheraddr, vif->addr, sizeof(vif->addr)); + 	wl->mute_tx = false; + 	brcms_c_mute(wl->wlc, false); ++	if (vif->type == NL80211_IFTYPE_STATION) ++		brcms_c_start_station(wl->wlc, vif->addr); + 	spin_unlock_bh(&wl->lock); +  + 	return 0; +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c +@@ -2165,6 +2165,12 @@ void brcms_b_switch_macfreq(struct brcms + 	} + } +  ++void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr) ++{ ++	memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr)); ++	wlc->bsscfg->type = BRCMS_TYPE_STATION; ++} ++ + /* Initialize GPIOs that are controlled by D11 core */ + static void brcms_c_gpio_init(struct brcms_c_info *wlc) + { +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h +@@ -576,10 +576,17 @@ struct antsel_info { + 	struct brcms_antselcfg antcfg_cur; /* current antenna config (auto) */ + }; +  ++enum brcms_bss_type { ++	BRCMS_TYPE_STATION, ++	BRCMS_TYPE_AP, ++	BRCMS_TYPE_ADHOC, ++}; ++ + /* +  * BSS configuration state +  * +  * wlc: wlc to which this bsscfg belongs to. ++ * type: interface type +  * up: is this configuration up operational +  * enable: is this configuration enabled +  * associated: is BSS in ASSOCIATED state +@@ -599,6 +606,7 @@ struct antsel_info { +  */ + struct brcms_bss_cfg { + 	struct brcms_c_info *wlc; ++	enum brcms_bss_type type; + 	bool up; + 	bool enable; + 	bool associated; +--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h ++++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h +@@ -333,5 +333,6 @@ extern int brcms_c_get_tx_power(struct b + extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc); + extern void brcms_c_mute(struct brcms_c_info *wlc, bool on); + extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc); ++extern void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr); +  + #endif				/* _BRCM_PUB_H_ */ diff --git a/package/mac80211/patches/862-brcmsmac-remove-brcms_bss_cfg-BSS.patch b/package/mac80211/patches/862-brcmsmac-remove-brcms_bss_cfg-BSS.patch new file mode 100644 index 000000000..a7ffcf6a7 --- /dev/null +++ b/package/mac80211/patches/862-brcmsmac-remove-brcms_bss_cfg-BSS.patch @@ -0,0 +1,77 @@ +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c +@@ -1071,7 +1071,7 @@ brcms_b_txstatus(struct brcms_hardware * +  + static void brcms_c_tbtt(struct brcms_c_info *wlc) + { +-	if (!wlc->bsscfg->BSS) ++	if (wlc->bsscfg->type == BRCMS_TYPE_ADHOC) + 		/* + 		 * DirFrmQ is now valid...defer setting until end + 		 * of ATIM window +@@ -3061,16 +3061,8 @@ static bool brcms_c_ps_allowed(struct br + 	if (wlc->filter_flags & FIF_PROMISC_IN_BSS) + 		return false; +  +-	if (cfg->associated) { +-		/* +-		 * disallow PS when one of the following +-		 * bsscfg specific conditions meets +-		 */ +-		if (!cfg->BSS) +-			return false; +- ++	if (cfg->associated) + 		return false; +-	} +  + 	return true; + } +@@ -5080,8 +5072,9 @@ int brcms_c_up(struct brcms_c_info *wlc) + 				struct brcms_bss_cfg *bsscfg = wlc->bsscfg; + 				mboolset(wlc->pub->radio_disabled, + 					 WL_RADIO_HW_DISABLE); +- +-				if (bsscfg->enable && bsscfg->BSS) ++				if (bsscfg->enable && ++				    (bsscfg->type == BRCMS_TYPE_STATION || ++				     bsscfg->type == BRCMS_TYPE_ADHOC)) + 					brcms_err(wlc->hw->d11core, + 						  "wl%d: up: rfdisable -> " + 						  "bsscfg_disable()\n", +@@ -7390,7 +7383,7 @@ void brcms_c_update_beacon(struct brcms_ + { + 	struct brcms_bss_cfg *bsscfg = wlc->bsscfg; +  +-	if (bsscfg->up && !bsscfg->BSS) ++	if (bsscfg->up && bsscfg->type == BRCMS_TYPE_AP) + 		/* Clear the soft intmask */ + 		wlc->defmacintmask &= ~MI_BCNTPL; + } +@@ -7465,7 +7458,7 @@ void brcms_c_update_probe_resp(struct br + 	struct brcms_bss_cfg *bsscfg = wlc->bsscfg; +  + 	/* update AP or IBSS probe responses */ +-	if (bsscfg->up && !bsscfg->BSS) ++	if (bsscfg->up && bsscfg->type == BRCMS_TYPE_AP) + 		brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend); + } +  +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h +@@ -590,7 +590,6 @@ enum brcms_bss_type { +  * up: is this configuration up operational +  * enable: is this configuration enabled +  * associated: is BSS in ASSOCIATED state +- * BSS: infraustructure or adhoc +  * SSID_len: the length of SSID +  * SSID: SSID string +  * +@@ -610,7 +609,6 @@ struct brcms_bss_cfg { + 	bool up; + 	bool enable; + 	bool associated; +-	bool BSS; + 	u8 SSID_len; + 	u8 SSID[IEEE80211_MAX_SSID_LEN]; + 	u8 BSSID[ETH_ALEN]; diff --git a/package/mac80211/patches/863-brcmsmac-remove-brcms_bss_cfg-associated.patch b/package/mac80211/patches/863-brcmsmac-remove-brcms_bss_cfg-associated.patch new file mode 100644 index 000000000..7f84f00e2 --- /dev/null +++ b/package/mac80211/patches/863-brcmsmac-remove-brcms_bss_cfg-associated.patch @@ -0,0 +1,74 @@ +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c +@@ -3051,8 +3051,6 @@ static void brcms_b_antsel_set(struct br +  */ + static bool brcms_c_ps_allowed(struct brcms_c_info *wlc) + { +-	struct brcms_bss_cfg *cfg = wlc->bsscfg; +- + 	/* disallow PS when one of the following global conditions meets */ + 	if (!wlc->pub->associated) + 		return false; +@@ -3061,9 +3059,6 @@ static bool brcms_c_ps_allowed(struct br + 	if (wlc->filter_flags & FIF_PROMISC_IN_BSS) + 		return false; +  +-	if (cfg->associated) +-		return false; +- + 	return true; + } +  +@@ -3821,7 +3816,7 @@ static void brcms_c_set_home_chanspec(st + 	if (wlc->home_chanspec != chanspec) { + 		wlc->home_chanspec = chanspec; +  +-		if (wlc->bsscfg->associated) ++		if (wlc->pub->associated) + 			wlc->bsscfg->current_bss->chanspec = chanspec; + 	} + } +@@ -5435,7 +5430,7 @@ static void brcms_c_ofdm_rateset_war(str + 	u8 r; + 	bool war = false; +  +-	if (wlc->bsscfg->associated) ++	if (wlc->pub->associated) + 		r = wlc->bsscfg->current_bss->rateset.rates[0]; + 	else + 		r = wlc->default_bss->rateset.rates[0]; +@@ -5529,7 +5524,7 @@ int brcms_c_set_rateset(struct brcms_c_i + 	/* merge rateset coming in with the current mcsset */ + 	if (wlc->pub->_n_enab & SUPPORT_11N) { + 		struct brcms_bss_info *mcsset_bss; +-		if (wlc->bsscfg->associated) ++		if (wlc->pub->associated) + 			mcsset_bss = wlc->bsscfg->current_bss; + 		else + 			mcsset_bss = wlc->default_bss; +@@ -7498,7 +7493,6 @@ void brcms_c_scan_stop(struct brcms_c_in + void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state) + { + 	wlc->pub->associated = state; +-	wlc->bsscfg->associated = state; + } +  + /* +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h +@@ -589,7 +589,6 @@ enum brcms_bss_type { +  * type: interface type +  * up: is this configuration up operational +  * enable: is this configuration enabled +- * associated: is BSS in ASSOCIATED state +  * SSID_len: the length of SSID +  * SSID: SSID string +  * +@@ -608,7 +607,6 @@ struct brcms_bss_cfg { + 	enum brcms_bss_type type; + 	bool up; + 	bool enable; +-	bool associated; + 	u8 SSID_len; + 	u8 SSID[IEEE80211_MAX_SSID_LEN]; + 	u8 BSSID[ETH_ALEN]; diff --git a/package/mac80211/patches/864-brcmsmac-remove-brcms_bss_cfg-enable.patch b/package/mac80211/patches/864-brcmsmac-remove-brcms_bss_cfg-enable.patch new file mode 100644 index 000000000..9f5c4da7f --- /dev/null +++ b/package/mac80211/patches/864-brcmsmac-remove-brcms_bss_cfg-enable.patch @@ -0,0 +1,32 @@ +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c +@@ -5067,9 +5067,8 @@ int brcms_c_up(struct brcms_c_info *wlc) + 				struct brcms_bss_cfg *bsscfg = wlc->bsscfg; + 				mboolset(wlc->pub->radio_disabled, + 					 WL_RADIO_HW_DISABLE); +-				if (bsscfg->enable && +-				    (bsscfg->type == BRCMS_TYPE_STATION || +-				     bsscfg->type == BRCMS_TYPE_ADHOC)) ++				if (bsscfg->type == BRCMS_TYPE_STATION || ++				    bsscfg->type == BRCMS_TYPE_ADHOC) + 					brcms_err(wlc->hw->d11core, + 						  "wl%d: up: rfdisable -> " + 						  "bsscfg_disable()\n", +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h +@@ -588,7 +588,6 @@ enum brcms_bss_type { +  * wlc: wlc to which this bsscfg belongs to. +  * type: interface type +  * up: is this configuration up operational +- * enable: is this configuration enabled +  * SSID_len: the length of SSID +  * SSID: SSID string +  * +@@ -606,7 +605,6 @@ struct brcms_bss_cfg { + 	struct brcms_c_info *wlc; + 	enum brcms_bss_type type; + 	bool up; +-	bool enable; + 	u8 SSID_len; + 	u8 SSID[IEEE80211_MAX_SSID_LEN]; + 	u8 BSSID[ETH_ALEN]; diff --git a/package/mac80211/patches/865-brcmsmac-remove-brcms_bss_cfg-up.patch b/package/mac80211/patches/865-brcmsmac-remove-brcms_bss_cfg-up.patch new file mode 100644 index 000000000..40fe6eaf6 --- /dev/null +++ b/package/mac80211/patches/865-brcmsmac-remove-brcms_bss_cfg-up.patch @@ -0,0 +1,47 @@ +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c +@@ -7377,7 +7377,7 @@ void brcms_c_update_beacon(struct brcms_ + { + 	struct brcms_bss_cfg *bsscfg = wlc->bsscfg; +  +-	if (bsscfg->up && bsscfg->type == BRCMS_TYPE_AP) ++	if (wlc->pub->up && bsscfg->type == BRCMS_TYPE_AP) + 		/* Clear the soft intmask */ + 		wlc->defmacintmask &= ~MI_BCNTPL; + } +@@ -7452,7 +7452,7 @@ void brcms_c_update_probe_resp(struct br + 	struct brcms_bss_cfg *bsscfg = wlc->bsscfg; +  + 	/* update AP or IBSS probe responses */ +-	if (bsscfg->up && bsscfg->type == BRCMS_TYPE_AP) ++	if (wlc->pub->up && bsscfg->type == BRCMS_TYPE_AP) + 		brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend); + } +  +@@ -7805,7 +7805,7 @@ void brcms_c_init(struct brcms_c_info *w + 	brcms_c_set_bssid(wlc->bsscfg); +  + 	/* Update tsf_cfprep if associated and up */ +-	if (wlc->pub->associated && wlc->bsscfg->up) { ++	if (wlc->pub->associated && wlc->pub->up) { + 		u32 bi; +  + 		/* get beacon period and convert to uS */ +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h +@@ -587,7 +587,6 @@ enum brcms_bss_type { +  * +  * wlc: wlc to which this bsscfg belongs to. +  * type: interface type +- * up: is this configuration up operational +  * SSID_len: the length of SSID +  * SSID: SSID string +  * +@@ -604,7 +603,6 @@ enum brcms_bss_type { + struct brcms_bss_cfg { + 	struct brcms_c_info *wlc; + 	enum brcms_bss_type type; +-	bool up; + 	u8 SSID_len; + 	u8 SSID[IEEE80211_MAX_SSID_LEN]; + 	u8 BSSID[ETH_ALEN]; diff --git a/package/mac80211/patches/866-brcmsmac-remove-brcms_bss_cfg-cur_etheraddr.patch b/package/mac80211/patches/866-brcmsmac-remove-brcms_bss_cfg-cur_etheraddr.patch new file mode 100644 index 000000000..0571932e8 --- /dev/null +++ b/package/mac80211/patches/866-brcmsmac-remove-brcms_bss_cfg-cur_etheraddr.patch @@ -0,0 +1,30 @@ +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c +@@ -3766,7 +3766,7 @@ static int brcms_c_set_mac(struct brcms_ + 	struct brcms_c_info *wlc = bsscfg->wlc; +  + 	/* enter the MAC addr into the RXE match registers */ +-	brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, bsscfg->cur_etheraddr); ++	brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, wlc->pub->cur_etheraddr); +  + 	brcms_c_ampdu_macaddr_upd(wlc); +  +@@ -7359,7 +7359,7 @@ brcms_c_bcn_prb_template(struct brcms_c_ + 	/* A1 filled in by MAC for prb resp, broadcast for bcn */ + 	if (type == IEEE80211_STYPE_BEACON) + 		memcpy(&h->da, ðer_bcast, ETH_ALEN); +-	memcpy(&h->sa, &cfg->cur_etheraddr, ETH_ALEN); ++	memcpy(&h->sa, &wlc->pub->cur_etheraddr, ETH_ALEN); + 	memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN); +  + 	/* SEQ filled in by MAC */ +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h +@@ -606,7 +606,6 @@ struct brcms_bss_cfg { + 	u8 SSID_len; + 	u8 SSID[IEEE80211_MAX_SSID_LEN]; + 	u8 BSSID[ETH_ALEN]; +-	u8 cur_etheraddr[ETH_ALEN]; + 	struct brcms_bss_info *current_bss; + }; +  diff --git a/package/mac80211/patches/867-brcmsmac-remove-brcms_pub-bcmerr.patch b/package/mac80211/patches/867-brcmsmac-remove-brcms_pub-bcmerr.patch new file mode 100644 index 000000000..2e7c166c3 --- /dev/null +++ b/package/mac80211/patches/867-brcmsmac-remove-brcms_pub-bcmerr.patch @@ -0,0 +1,21 @@ +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c +@@ -4327,7 +4327,6 @@ static void brcms_c_info_init(struct brc +  + 	/* WME QoS mode is Auto by default */ + 	wlc->pub->_ampdu = AMPDU_AGG_HOST; +-	wlc->pub->bcmerror = 0; + } +  + static uint brcms_c_attach_module(struct brcms_c_info *wlc) +--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h ++++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h +@@ -164,8 +164,6 @@ struct brcms_pub { +  + 	u8 cur_etheraddr[ETH_ALEN];	/* our local ethernet address */ +  +-	int bcmerror;		/* last bcm error */ +- + 	u32 radio_disabled;	/* bit vector for radio disabled reasons */ +  + 	u16 boardrev;	/* version # of particular board */ diff --git a/package/mac80211/patches/868-brcmsmac-write-beacon-period-to-hardware.patch b/package/mac80211/patches/868-brcmsmac-write-beacon-period-to-hardware.patch new file mode 100644 index 000000000..fb10e1ba6 --- /dev/null +++ b/package/mac80211/patches/868-brcmsmac-write-beacon-period-to-hardware.patch @@ -0,0 +1,23 @@ +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c +@@ -5553,10 +5553,20 @@ static void brcms_c_time_unlock(struct b +  + int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period) + { ++	u32 bcnint_us; ++ + 	if (period == 0) + 		return -EINVAL; +  + 	wlc->default_bss->beacon_period = period; ++ ++	bcnint_us = period << 10; ++	brcms_c_time_lock(wlc); ++	bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_cfprep), ++		     (bcnint_us << CFPREP_CBI_SHIFT)); ++	bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_cfpstart), bcnint_us); ++	brcms_c_time_unlock(wlc); ++ + 	return 0; + } +  diff --git a/package/mac80211/patches/869-brcmsmac-add-beacon-template-support.patch b/package/mac80211/patches/869-brcmsmac-add-beacon-template-support.patch new file mode 100644 index 000000000..ab864a3db --- /dev/null +++ b/package/mac80211/patches/869-brcmsmac-add-beacon-template-support.patch @@ -0,0 +1,266 @@ +--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +@@ -1,5 +1,6 @@ + /* +  * Copyright (c) 2010 Broadcom Corporation ++ * Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de> +  * +  * Permission to use, copy, modify, and/or distribute this software for any +  * purpose with or without fee is hereby granted, provided that the above +@@ -522,9 +523,17 @@ brcms_ops_bss_info_changed(struct ieee80 + 		brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET, info->bssid); + 		spin_unlock_bh(&wl->lock); + 	} +-	if (changed & BSS_CHANGED_BEACON) ++	if (changed & BSS_CHANGED_BEACON) { + 		/* Beacon data changed, retrieve new beacon (beaconing modes) */ +-		brcms_err(core, "%s: beacon changed\n", __func__); ++		struct sk_buff *beacon; ++		u16 tim_offset = 0; ++ ++		spin_lock_bh(&wl->lock); ++		beacon = ieee80211_beacon_get_tim(hw, vif, &tim_offset, NULL); ++		brcms_c_set_new_beacon(wl->wlc, beacon, tim_offset, ++				       info->dtim_period); ++		spin_unlock_bh(&wl->lock); ++	} +  + 	if (changed & BSS_CHANGED_BEACON_ENABLED) { + 		/* Beaconing should be enabled/disabled (beaconing modes) */ +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c +@@ -1,5 +1,6 @@ + /* +  * Copyright (c) 2010 Broadcom Corporation ++ * Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de> +  * +  * Permission to use, copy, modify, and/or distribute this software for any +  * purpose with or without fee is hereby granted, provided that the above +@@ -450,6 +451,8 @@ static void brcms_c_detach_mfree(struct + 	kfree(wlc->corestate); + 	kfree(wlc->hw->bandstate[0]); + 	kfree(wlc->hw); ++	if (wlc->beacon) ++		dev_kfree_skb_any(wlc->beacon); +  + 	/* free the wlc */ + 	kfree(wlc); +@@ -4086,10 +4089,14 @@ void brcms_c_wme_setparams(struct brcms_ + 					  *shm_entry++); + 	} +  +-	if (suspend) { ++	if (suspend) + 		brcms_c_suspend_mac_and_wait(wlc); ++ ++	brcms_c_update_beacon(wlc); ++	brcms_c_update_probe_resp(wlc, false); ++ ++	if (suspend) + 		brcms_c_enable_mac(wlc); +-	} + } +  + static void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend) +@@ -7379,6 +7386,107 @@ int brcms_c_get_header_len(void) + 	return TXOFF; + } +  ++static void brcms_c_beacon_write(struct brcms_c_info *wlc, ++				 struct sk_buff *beacon, u16 tim_offset, ++				 u16 dtim_period, bool bcn0, bool bcn1) ++{ ++	size_t len; ++	struct ieee80211_tx_info *tx_info; ++	struct brcms_hardware *wlc_hw = wlc->hw; ++	struct ieee80211_hw *ieee_hw = brcms_c_pub(wlc)->ieee_hw; ++ ++	/* Get tx_info */ ++	tx_info = IEEE80211_SKB_CB(beacon); ++ ++	len = min_t(size_t, beacon->len, BCN_TMPL_LEN); ++	wlc->bcn_rspec = ieee80211_get_tx_rate(ieee_hw, tx_info)->hw_value; ++ ++	brcms_c_compute_plcp(wlc, wlc->bcn_rspec, ++			     len + FCS_LEN - D11_PHY_HDR_LEN, beacon->data); ++ ++	/* "Regular" and 16 MBSS but not for 4 MBSS */ ++	/* Update the phytxctl for the beacon based on the rspec */ ++	brcms_c_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec); ++ ++	if (bcn0) { ++		/* write the probe response into the template region */ ++		brcms_b_write_template_ram(wlc_hw, T_BCN0_TPL_BASE, ++					    (len + 3) & ~3, beacon->data); ++ ++		/* write beacon length to SCR */ ++		brcms_b_write_shm(wlc_hw, M_BCN0_FRM_BYTESZ, (u16) len); ++	} ++	if (bcn1) { ++		/* write the probe response into the template region */ ++		brcms_b_write_template_ram(wlc_hw, T_BCN1_TPL_BASE, ++					    (len + 3) & ~3, beacon->data); ++ ++		/* write beacon length to SCR */ ++		brcms_b_write_shm(wlc_hw, M_BCN1_FRM_BYTESZ, (u16) len); ++	} ++ ++	if (tim_offset != 0) { ++		brcms_b_write_shm(wlc_hw, M_TIMBPOS_INBEACON, ++				  tim_offset + D11B_PHY_HDR_LEN); ++		brcms_b_write_shm(wlc_hw, M_DOT11_DTIMPERIOD, dtim_period); ++	} else { ++		brcms_b_write_shm(wlc_hw, M_TIMBPOS_INBEACON, ++				  len + D11B_PHY_HDR_LEN); ++		brcms_b_write_shm(wlc_hw, M_DOT11_DTIMPERIOD, 0); ++	} ++} ++ ++static void brcms_c_update_beacon_hw(struct brcms_c_info *wlc, ++				     struct sk_buff *beacon, u16 tim_offset, ++				     u16 dtim_period) ++{ ++	struct brcms_hardware *wlc_hw = wlc->hw; ++	struct bcma_device *core = wlc_hw->d11core; ++ ++	/* Hardware beaconing for this config */ ++	u32 both_valid = MCMD_BCN0VLD | MCMD_BCN1VLD; ++ ++	/* Check if both templates are in use, if so sched. an interrupt ++	 *      that will call back into this routine ++	 */ ++	if ((bcma_read32(core, D11REGOFFS(maccommand)) & both_valid) == both_valid) ++		/* clear any previous status */ ++		bcma_write32(core, D11REGOFFS(macintstatus), MI_BCNTPL); ++ ++	if (wlc->beacon_template_virgin) { ++		wlc->beacon_template_virgin = false; ++		brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period, true, ++				     true); ++		/* mark beacon0 valid */ ++		bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN0VLD); ++		return; ++	} ++ ++	/* Check that after scheduling the interrupt both of the ++	 *      templates are still busy. if not clear the int. & remask ++	 */ ++	if ((bcma_read32(core, D11REGOFFS(maccommand)) & both_valid) == both_valid) { ++		wlc->defmacintmask |= MI_BCNTPL; ++		return; ++	} ++ ++	if (!(bcma_read32(core, D11REGOFFS(maccommand)) & MCMD_BCN0VLD)) { ++		brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period, true, ++				     false); ++		/* mark beacon0 valid */ ++		bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN0VLD); ++		return; ++	} ++	if (!(bcma_read32(core, D11REGOFFS(maccommand)) & MCMD_BCN1VLD)) { ++		brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period, ++				     false, true); ++		/* mark beacon0 valid */ ++		bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN1VLD); ++		return; ++	} ++	return; ++} ++ + /* +  * Update all beacons for the system. +  */ +@@ -7386,9 +7494,31 @@ void brcms_c_update_beacon(struct brcms_ + { + 	struct brcms_bss_cfg *bsscfg = wlc->bsscfg; +  +-	if (wlc->pub->up && bsscfg->type == BRCMS_TYPE_AP) ++	if (wlc->pub->up && bsscfg->type == BRCMS_TYPE_AP) { + 		/* Clear the soft intmask */ + 		wlc->defmacintmask &= ~MI_BCNTPL; ++		if (!wlc->beacon) ++			return; ++		brcms_c_update_beacon_hw(wlc, wlc->beacon, ++					 wlc->beacon_tim_offset, ++					 wlc->beacon_dtim_period); ++	} ++} ++ ++void brcms_c_set_new_beacon(struct brcms_c_info *wlc, struct sk_buff *beacon, ++			    u16 tim_offset, u16 dtim_period) ++{ ++	if (!beacon) ++		return; ++	if (wlc->beacon) ++		dev_kfree_skb_any(wlc->beacon); ++	wlc->beacon = beacon; ++ ++	/* add PLCP */ ++	skb_push(wlc->beacon, D11_PHY_HDR_LEN); ++	wlc->beacon_tim_offset = tim_offset; ++	wlc->beacon_dtim_period = dtim_period; ++	brcms_c_update_beacon(wlc); + } +  + /* Write ssid into shared memory */ +@@ -7786,6 +7916,10 @@ bool brcms_c_dpc(struct brcms_c_info *wl + 		brcms_rfkill_set_hw_state(wlc->wl); + 	} +  ++	/* BCN template is available */ ++	if (macintstatus & MI_BCNTPL) ++		brcms_c_update_beacon(wlc); ++ + 	/* it isn't done and needs to be resched if macintstatus is non-zero */ + 	return wlc->macintstatus != 0; +  +@@ -7917,6 +8051,7 @@ brcms_c_attach(struct brcms_info *wl, st + 	pub->unit = unit; + 	pub->_piomode = piomode; + 	wlc->bandinit_pending = false; ++	wlc->beacon_template_virgin = true; +  + 	/* populate struct brcms_c_info with default values  */ + 	brcms_c_info_init(wlc, unit); +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h +@@ -492,6 +492,8 @@ struct brcms_c_info { + 	bool radio_monitor; + 	bool going_down; +  ++	bool beacon_template_virgin; ++ + 	struct brcms_timer *wdtimer; + 	struct brcms_timer *radio_timer; +  +@@ -561,6 +563,10 @@ struct brcms_c_info { +  + 	struct wiphy *wiphy; + 	struct scb pri_scb; ++ ++	struct sk_buff *beacon; ++	u16 beacon_tim_offset; ++	u16 beacon_dtim_period; + }; +  + /* antsel module specific state */ +@@ -630,7 +636,6 @@ extern u16 brcms_c_compute_rtscts_dur(st + extern void brcms_c_inval_dma_pkts(struct brcms_hardware *hw, + 			       struct ieee80211_sta *sta, + 			       void (*dma_callback_fn)); +-extern void brcms_c_update_beacon(struct brcms_c_info *wlc); + extern void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend); + extern int brcms_c_set_nmode(struct brcms_c_info *wlc); + extern void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, +--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h ++++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h +@@ -332,5 +332,9 @@ extern bool brcms_c_check_radio_disabled + extern void brcms_c_mute(struct brcms_c_info *wlc, bool on); + extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc); + extern void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr); ++extern void brcms_c_update_beacon(struct brcms_c_info *wlc); ++extern void brcms_c_set_new_beacon(struct brcms_c_info *wlc, ++				   struct sk_buff *beacon, u16 tim_offset, ++				   u16 dtim_period); +  + #endif				/* _BRCM_PUB_H_ */ diff --git a/package/mac80211/patches/870-brcmsmac-react-on-changing-SSID.patch b/package/mac80211/patches/870-brcmsmac-react-on-changing-SSID.patch new file mode 100644 index 000000000..34969ad35 --- /dev/null +++ b/package/mac80211/patches/870-brcmsmac-react-on-changing-SSID.patch @@ -0,0 +1,43 @@ +--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +@@ -523,6 +523,12 @@ brcms_ops_bss_info_changed(struct ieee80 + 		brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET, info->bssid); + 		spin_unlock_bh(&wl->lock); + 	} ++	if (changed & BSS_CHANGED_SSID) { ++		/* BSSID changed, for whatever reason (IBSS and managed mode) */ ++		spin_lock_bh(&wl->lock); ++		brcms_c_set_ssid(wl->wlc, info->ssid, info->ssid_len); ++		spin_unlock_bh(&wl->lock); ++	} + 	if (changed & BSS_CHANGED_BEACON) { + 		/* Beacon data changed, retrieve new beacon (beaconing modes) */ + 		struct sk_buff *beacon; +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c +@@ -3785,6 +3785,15 @@ static void brcms_c_set_bssid(struct brc + 	brcms_c_set_addrmatch(bsscfg->wlc, RCM_BSSID_OFFSET, bsscfg->BSSID); + } +  ++void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid, size_t ssid_len) ++{ ++	u8 len = min_t(u8, sizeof(wlc->bsscfg->SSID), ssid_len); ++	memset(wlc->bsscfg->SSID, 0, sizeof(wlc->bsscfg->SSID)); ++ ++	memcpy(wlc->bsscfg->SSID, ssid, len); ++	wlc->bsscfg->SSID_len = len; ++} ++ + static void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot) + { + 	wlc_hw->shortslot = shortslot; +--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h ++++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h +@@ -336,5 +336,7 @@ extern void brcms_c_update_beacon(struct + extern void brcms_c_set_new_beacon(struct brcms_c_info *wlc, + 				   struct sk_buff *beacon, u16 tim_offset, + 				   u16 dtim_period); ++extern void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid, ++			     size_t ssid_len); +  + #endif				/* _BRCM_PUB_H_ */ diff --git a/package/mac80211/patches/871-brcmsmac-add-support-for-probe-response-template.patch b/package/mac80211/patches/871-brcmsmac-add-support-for-probe-response-template.patch new file mode 100644 index 000000000..5d022d2b5 --- /dev/null +++ b/package/mac80211/patches/871-brcmsmac-add-support-for-probe-response-template.patch @@ -0,0 +1,216 @@ +--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +@@ -541,6 +541,15 @@ brcms_ops_bss_info_changed(struct ieee80 + 		spin_unlock_bh(&wl->lock); + 	} +  ++	if (changed & BSS_CHANGED_AP_PROBE_RESP) { ++		struct sk_buff *probe_resp; ++ ++		spin_lock_bh(&wl->lock); ++		probe_resp = ieee80211_proberesp_get(hw, vif); ++		brcms_c_set_new_probe_resp(wl->wlc, probe_resp); ++		spin_unlock_bh(&wl->lock); ++	} ++ + 	if (changed & BSS_CHANGED_BEACON_ENABLED) { + 		/* Beaconing should be enabled/disabled (beaconing modes) */ + 		brcms_err(core, "%s: Beacon enabled: %s\n", __func__, +@@ -1039,6 +1048,8 @@ static int ieee_hw_init(struct ieee80211 + 	hw->channel_change_time = 7 * 1000; + 	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); +  ++	hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; ++ + 	hw->rate_control_algorithm = "minstrel_ht"; +  + 	hw->sta_data_size = 0; +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c +@@ -453,6 +453,8 @@ static void brcms_c_detach_mfree(struct + 	kfree(wlc->hw); + 	if (wlc->beacon) + 		dev_kfree_skb_any(wlc->beacon); ++	if (wlc->probe_resp) ++		dev_kfree_skb_any(wlc->probe_resp); +  + 	/* free the wlc */ + 	kfree(wlc); +@@ -7327,69 +7329,6 @@ brcms_c_mod_prb_rsp_rate_table(struct br + 	} + } +  +-/*	Max buffering needed for beacon template/prb resp template is 142 bytes. +- * +- *	PLCP header is 6 bytes. +- *	802.11 A3 header is 24 bytes. +- *	Max beacon frame body template length is 112 bytes. +- *	Max probe resp frame body template length is 110 bytes. +- * +- *      *len on input contains the max length of the packet available. +- * +- *	The *len value is set to the number of bytes in buf used, and starts +- *	with the PLCP and included up to, but not including, the 4 byte FCS. +- */ +-static void +-brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type, +-			 u32 bcn_rspec, +-			 struct brcms_bss_cfg *cfg, u16 *buf, int *len) +-{ +-	static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255}; +-	struct cck_phy_hdr *plcp; +-	struct ieee80211_mgmt *h; +-	int hdr_len, body_len; +- +-	hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN; +- +-	/* calc buffer size provided for frame body */ +-	body_len = *len - hdr_len; +-	/* return actual size */ +-	*len = hdr_len + body_len; +- +-	/* format PHY and MAC headers */ +-	memset(buf, 0, hdr_len); +- +-	plcp = (struct cck_phy_hdr *) buf; +- +-	/* +-	 * PLCP for Probe Response frames are filled in from +-	 * core's rate table +-	 */ +-	if (type == IEEE80211_STYPE_BEACON) +-		/* fill in PLCP */ +-		brcms_c_compute_plcp(wlc, bcn_rspec, +-				 (DOT11_MAC_HDR_LEN + body_len + FCS_LEN), +-				 (u8 *) plcp); +- +-	/* "Regular" and 16 MBSS but not for 4 MBSS */ +-	/* Update the phytxctl for the beacon based on the rspec */ +-	brcms_c_beacon_phytxctl_txant_upd(wlc, bcn_rspec); +- +-	h = (struct ieee80211_mgmt *)&plcp[1]; +- +-	/* fill in 802.11 header */ +-	h->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | type); +- +-	/* DUR is 0 for multicast bcn, or filled in by MAC for prb resp */ +-	/* A1 filled in by MAC for prb resp, broadcast for bcn */ +-	if (type == IEEE80211_STYPE_BEACON) +-		memcpy(&h->da, ðer_bcast, ETH_ALEN); +-	memcpy(&h->sa, &wlc->pub->cur_etheraddr, ETH_ALEN); +-	memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN); +- +-	/* SEQ filled in by MAC */ +-} +- + int brcms_c_get_header_len(void) + { + 	return TXOFF; +@@ -7530,6 +7469,20 @@ void brcms_c_set_new_beacon(struct brcms + 	brcms_c_update_beacon(wlc); + } +  ++void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc, ++				struct sk_buff *probe_resp) ++{ ++	if (!probe_resp) ++		return; ++	if (wlc->probe_resp) ++		dev_kfree_skb_any(wlc->probe_resp); ++	wlc->probe_resp = probe_resp; ++ ++	/* add PLCP */ ++	skb_push(wlc->probe_resp, D11_PHY_HDR_LEN); ++	brcms_c_update_probe_resp(wlc, false); ++} ++ + /* Write ssid into shared memory */ + static void + brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg) +@@ -7549,30 +7502,19 @@ brcms_c_shm_ssid_upd(struct brcms_c_info + static void + brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc, + 			      struct brcms_bss_cfg *cfg, ++			      struct sk_buff *probe_resp, + 			      bool suspend) + { +-	u16 *prb_resp; +-	int len = BCN_TMPL_LEN; ++	int len; +  +-	prb_resp = kmalloc(BCN_TMPL_LEN, GFP_ATOMIC); +-	if (!prb_resp) +-		return; +- +-	/* +-	 * write the probe response to hardware, or save in +-	 * the config structure +-	 */ +- +-	/* create the probe response template */ +-	brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0, +-				 cfg, prb_resp, &len); ++	len = min_t(size_t, probe_resp->len, BCN_TMPL_LEN); +  + 	if (suspend) + 		brcms_c_suspend_mac_and_wait(wlc); +  + 	/* write the probe response into the template region */ + 	brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE, +-				    (len + 3) & ~3, prb_resp); ++				    (len + 3) & ~3, probe_resp->data); +  + 	/* write the length of the probe response frame (+PLCP/-FCS) */ + 	brcms_b_write_shm(wlc->hw, M_PRB_RESP_FRM_LEN, (u16) len); +@@ -7586,13 +7528,11 @@ brcms_c_bss_update_probe_resp(struct brc + 	 * PLCP header for the call to brcms_c_mod_prb_rsp_rate_table() + 	 * by subtracting the PLCP len and adding the FCS. + 	 */ +-	len += (-D11_PHY_HDR_LEN + FCS_LEN); +-	brcms_c_mod_prb_rsp_rate_table(wlc, (u16) len); ++	brcms_c_mod_prb_rsp_rate_table(wlc, ++				      (u16)len + FCS_LEN - D11_PHY_HDR_LEN); +  + 	if (suspend) + 		brcms_c_enable_mac(wlc); +- +-	kfree(prb_resp); + } +  + void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend) +@@ -7600,8 +7540,12 @@ void brcms_c_update_probe_resp(struct br + 	struct brcms_bss_cfg *bsscfg = wlc->bsscfg; +  + 	/* update AP or IBSS probe responses */ +-	if (wlc->pub->up && bsscfg->type == BRCMS_TYPE_AP) +-		brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend); ++	if (wlc->pub->up && bsscfg->type == BRCMS_TYPE_AP) { ++		if (!wlc->probe_resp) ++			return; ++		brcms_c_bss_update_probe_resp(wlc, bsscfg, wlc->probe_resp, ++					      suspend); ++	} + } +  + int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h +@@ -567,6 +567,7 @@ struct brcms_c_info { + 	struct sk_buff *beacon; + 	u16 beacon_tim_offset; + 	u16 beacon_dtim_period; ++	struct sk_buff *probe_resp; + }; +  + /* antsel module specific state */ +--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h ++++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h +@@ -336,6 +336,8 @@ extern void brcms_c_update_beacon(struct + extern void brcms_c_set_new_beacon(struct brcms_c_info *wlc, + 				   struct sk_buff *beacon, u16 tim_offset, + 				   u16 dtim_period); ++extern void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc, ++				       struct sk_buff *probe_resp); + extern void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid, + 			     size_t ssid_len); +  diff --git a/package/mac80211/patches/872-brcmsmac-activate-AP-support.patch b/package/mac80211/patches/872-brcmsmac-activate-AP-support.patch new file mode 100644 index 000000000..aaf6840c5 --- /dev/null +++ b/package/mac80211/patches/872-brcmsmac-activate-AP-support.patch @@ -0,0 +1,74 @@ +--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +@@ -360,7 +360,8 @@ brcms_ops_add_interface(struct ieee80211 + 	struct brcms_info *wl = hw->priv; +  + 	/* Just STA for now */ +-	if (vif->type != NL80211_IFTYPE_STATION) { ++	if (vif->type != NL80211_IFTYPE_STATION && ++	    vif->type != NL80211_IFTYPE_AP) { + 		brcms_err(wl->wlc->hw->d11core, + 			  "%s: Attempt to add type %d, only STA for now\n", + 			  __func__, vif->type); +@@ -372,6 +373,9 @@ brcms_ops_add_interface(struct ieee80211 + 	brcms_c_mute(wl->wlc, false); + 	if (vif->type == NL80211_IFTYPE_STATION) + 		brcms_c_start_station(wl->wlc, vif->addr); ++	else if (vif->type == NL80211_IFTYPE_AP) ++		brcms_c_start_ap(wl->wlc, vif->addr, vif->bss_conf.bssid, ++				 vif->bss_conf.ssid, vif->bss_conf.ssid_len); + 	spin_unlock_bh(&wl->lock); +  + 	return 0; +@@ -1046,7 +1050,8 @@ static int ieee_hw_init(struct ieee80211 +  + 	/* channel change time is dependent on chip and band  */ + 	hw->channel_change_time = 7 * 1000; +-	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); ++	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | ++				     BIT(NL80211_IFTYPE_AP); +  + 	hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; +  +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c +@@ -2176,6 +2176,18 @@ void brcms_c_start_station(struct brcms_ + 	wlc->bsscfg->type = BRCMS_TYPE_STATION; + } +  ++void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr, const u8 *bssid, ++		      u8 *ssid, size_t ssid_len) ++{ ++	brcms_c_set_ssid(wlc, ssid, ssid_len); ++ ++	memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr)); ++	memcpy(wlc->bsscfg->BSSID, bssid, sizeof(wlc->bsscfg->BSSID)); ++	wlc->bsscfg->type = BRCMS_TYPE_AP; ++ ++	brcms_b_mctrl(wlc->hw, MCTL_AP | MCTL_INFRA, MCTL_AP | MCTL_INFRA); ++} ++ + /* Initialize GPIOs that are controlled by D11 core */ + static void brcms_c_gpio_init(struct brcms_c_info *wlc) + { +@@ -3064,6 +3076,9 @@ static bool brcms_c_ps_allowed(struct br + 	if (wlc->filter_flags & FIF_PROMISC_IN_BSS) + 		return false; +  ++	if (wlc->bsscfg->type == BRCMS_TYPE_AP) ++		return false; ++ + 	return true; + } +  +--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h ++++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h +@@ -332,6 +332,8 @@ extern bool brcms_c_check_radio_disabled + extern void brcms_c_mute(struct brcms_c_info *wlc, bool on); + extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc); + extern void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr); ++extern void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr, ++			     const u8 *bssid, u8 *ssid, size_t ssid_len); + extern void brcms_c_update_beacon(struct brcms_c_info *wlc); + extern void brcms_c_set_new_beacon(struct brcms_c_info *wlc, + 				   struct sk_buff *beacon, u16 tim_offset, diff --git a/package/mac80211/patches/873-brcmsmac-remove-extra-regulation-restriction.patch b/package/mac80211/patches/873-brcmsmac-remove-extra-regulation-restriction.patch new file mode 100644 index 000000000..dd1393ae5 --- /dev/null +++ b/package/mac80211/patches/873-brcmsmac-remove-extra-regulation-restriction.patch @@ -0,0 +1,31 @@ +--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c +@@ -59,23 +59,16 @@ +  + #define BRCM_2GHZ_2412_2462	REG_RULE(2412-10, 2462+10, 40, 0, 19, 0) + #define BRCM_2GHZ_2467_2472	REG_RULE(2467-10, 2472+10, 20, 0, 19, \ +-					 NL80211_RRF_PASSIVE_SCAN | \ +-					 NL80211_RRF_NO_IBSS) ++					 0) +  + #define BRCM_5GHZ_5180_5240	REG_RULE(5180-10, 5240+10, 40, 0, 21, \ +-					 NL80211_RRF_PASSIVE_SCAN | \ +-					 NL80211_RRF_NO_IBSS) ++					 0) + #define BRCM_5GHZ_5260_5320	REG_RULE(5260-10, 5320+10, 40, 0, 21, \ +-					 NL80211_RRF_PASSIVE_SCAN | \ +-					 NL80211_RRF_DFS | \ +-					 NL80211_RRF_NO_IBSS) ++					 0) + #define BRCM_5GHZ_5500_5700	REG_RULE(5500-10, 5700+10, 40, 0, 21, \ +-					 NL80211_RRF_PASSIVE_SCAN | \ +-					 NL80211_RRF_DFS | \ +-					 NL80211_RRF_NO_IBSS) ++					 0) + #define BRCM_5GHZ_5745_5825	REG_RULE(5745-10, 5825+10, 40, 0, 21, \ +-					 NL80211_RRF_PASSIVE_SCAN | \ +-					 NL80211_RRF_NO_IBSS) ++					 0) +  + static const struct ieee80211_regdomain brcms_regdom_x2 = { + 	.n_reg_rules = 6,  | 
