summaryrefslogtreecommitdiffstats
path: root/package/mac80211/patches/871-brcmsmac-add-support-for-probe-response-template.patch
diff options
context:
space:
mode:
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.patch216
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, &ether_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);
+