From 60ba17b69f9bc3c752555b64e8d6aff9eb263d56 Mon Sep 17 00:00:00 2001 From: hauke Date: Sun, 24 Feb 2013 01:11:20 +0000 Subject: 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 --- ...plement-ieee80211_ops-get_tsf-and-set_tsf.patch | 121 ++++++++++ ...msmac-add-interface-type-to-brcms_bss_cfg.patch | 66 +++++ .../862-brcmsmac-remove-brcms_bss_cfg-BSS.patch | 77 ++++++ ...-brcmsmac-remove-brcms_bss_cfg-associated.patch | 74 ++++++ .../864-brcmsmac-remove-brcms_bss_cfg-enable.patch | 32 +++ .../865-brcmsmac-remove-brcms_bss_cfg-up.patch | 47 ++++ ...cmsmac-remove-brcms_bss_cfg-cur_etheraddr.patch | 30 +++ .../867-brcmsmac-remove-brcms_pub-bcmerr.patch | 21 ++ ...-brcmsmac-write-beacon-period-to-hardware.patch | 23 ++ .../869-brcmsmac-add-beacon-template-support.patch | 266 +++++++++++++++++++++ .../870-brcmsmac-react-on-changing-SSID.patch | 43 ++++ ...c-add-support-for-probe-response-template.patch | 216 +++++++++++++++++ .../patches/872-brcmsmac-activate-AP-support.patch | 74 ++++++ ...msmac-remove-extra-regulation-restriction.patch | 31 +++ 14 files changed, 1121 insertions(+) create mode 100644 package/mac80211/patches/860-brcmsmac-implement-ieee80211_ops-get_tsf-and-set_tsf.patch create mode 100644 package/mac80211/patches/861-brcmsmac-add-interface-type-to-brcms_bss_cfg.patch create mode 100644 package/mac80211/patches/862-brcmsmac-remove-brcms_bss_cfg-BSS.patch create mode 100644 package/mac80211/patches/863-brcmsmac-remove-brcms_bss_cfg-associated.patch create mode 100644 package/mac80211/patches/864-brcmsmac-remove-brcms_bss_cfg-enable.patch create mode 100644 package/mac80211/patches/865-brcmsmac-remove-brcms_bss_cfg-up.patch create mode 100644 package/mac80211/patches/866-brcmsmac-remove-brcms_bss_cfg-cur_etheraddr.patch create mode 100644 package/mac80211/patches/867-brcmsmac-remove-brcms_pub-bcmerr.patch create mode 100644 package/mac80211/patches/868-brcmsmac-write-beacon-period-to-hardware.patch create mode 100644 package/mac80211/patches/869-brcmsmac-add-beacon-template-support.patch create mode 100644 package/mac80211/patches/870-brcmsmac-react-on-changing-SSID.patch create mode 100644 package/mac80211/patches/871-brcmsmac-add-support-for-probe-response-template.patch create mode 100644 package/mac80211/patches/872-brcmsmac-activate-AP-support.patch create mode 100644 package/mac80211/patches/873-brcmsmac-remove-extra-regulation-restriction.patch 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 + * + * 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 + * + * 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, -- cgit v1.2.3