diff options
Diffstat (limited to 'package/mac80211/patches/871-brcmsmac-add-support-for-probe-response-template.patch')
-rw-r--r-- | package/mac80211/patches/871-brcmsmac-add-support-for-probe-response-template.patch | 216 |
1 files changed, 216 insertions, 0 deletions
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); + |