aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmsmac/main.c
diff options
context:
space:
mode:
authorHauke Mehrtens <hauke@hauke-m.de>2013-03-23 20:46:00 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-03-27 13:37:36 -0400
commit5f1e59e59ffd11a150144977e38ec55bb868f027 (patch)
tree71107f32c733330ef4f5effe8eacb4a3813b5f78 /drivers/net/wireless/brcm80211/brcmsmac/main.c
parentc031df31daf69ffbb4c9f6f966df83646241a195 (diff)
brcmsmac: add support for probe response template
The ucode is able to answer probe response by itself. This writes such a template into the specific memory. Currently the probe requests are also send to mac80211 so there are more answers send to a requesting client. We have to make the ucode stop sending probe requests to the driver. Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmsmac/main.c')
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/main.c112
1 files changed, 28 insertions, 84 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index cf11d8949499..04192ed42527 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -451,6 +451,8 @@ static void brcms_c_detach_mfree(struct brcms_c_info *wlc)
451 kfree(wlc->hw); 451 kfree(wlc->hw);
452 if (wlc->beacon) 452 if (wlc->beacon)
453 dev_kfree_skb_any(wlc->beacon); 453 dev_kfree_skb_any(wlc->beacon);
454 if (wlc->probe_resp)
455 dev_kfree_skb_any(wlc->probe_resp);
454 456
455 /* free the wlc */ 457 /* free the wlc */
456 kfree(wlc); 458 kfree(wlc);
@@ -7323,69 +7325,6 @@ brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len)
7323 } 7325 }
7324} 7326}
7325 7327
7326/* Max buffering needed for beacon template/prb resp template is 142 bytes.
7327 *
7328 * PLCP header is 6 bytes.
7329 * 802.11 A3 header is 24 bytes.
7330 * Max beacon frame body template length is 112 bytes.
7331 * Max probe resp frame body template length is 110 bytes.
7332 *
7333 * *len on input contains the max length of the packet available.
7334 *
7335 * The *len value is set to the number of bytes in buf used, and starts
7336 * with the PLCP and included up to, but not including, the 4 byte FCS.
7337 */
7338static void
7339brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type,
7340 u32 bcn_rspec,
7341 struct brcms_bss_cfg *cfg, u16 *buf, int *len)
7342{
7343 static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
7344 struct cck_phy_hdr *plcp;
7345 struct ieee80211_mgmt *h;
7346 int hdr_len, body_len;
7347
7348 hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN;
7349
7350 /* calc buffer size provided for frame body */
7351 body_len = *len - hdr_len;
7352 /* return actual size */
7353 *len = hdr_len + body_len;
7354
7355 /* format PHY and MAC headers */
7356 memset(buf, 0, hdr_len);
7357
7358 plcp = (struct cck_phy_hdr *) buf;
7359
7360 /*
7361 * PLCP for Probe Response frames are filled in from
7362 * core's rate table
7363 */
7364 if (type == IEEE80211_STYPE_BEACON)
7365 /* fill in PLCP */
7366 brcms_c_compute_plcp(wlc, bcn_rspec,
7367 (DOT11_MAC_HDR_LEN + body_len + FCS_LEN),
7368 (u8 *) plcp);
7369
7370 /* "Regular" and 16 MBSS but not for 4 MBSS */
7371 /* Update the phytxctl for the beacon based on the rspec */
7372 brcms_c_beacon_phytxctl_txant_upd(wlc, bcn_rspec);
7373
7374 h = (struct ieee80211_mgmt *)&plcp[1];
7375
7376 /* fill in 802.11 header */
7377 h->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | type);
7378
7379 /* DUR is 0 for multicast bcn, or filled in by MAC for prb resp */
7380 /* A1 filled in by MAC for prb resp, broadcast for bcn */
7381 if (type == IEEE80211_STYPE_BEACON)
7382 memcpy(&h->da, &ether_bcast, ETH_ALEN);
7383 memcpy(&h->sa, &wlc->pub->cur_etheraddr, ETH_ALEN);
7384 memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN);
7385
7386 /* SEQ filled in by MAC */
7387}
7388
7389int brcms_c_get_header_len(void) 7328int brcms_c_get_header_len(void)
7390{ 7329{
7391 return TXOFF; 7330 return TXOFF;
@@ -7527,6 +7466,20 @@ void brcms_c_set_new_beacon(struct brcms_c_info *wlc, struct sk_buff *beacon,
7527 brcms_c_update_beacon(wlc); 7466 brcms_c_update_beacon(wlc);
7528} 7467}
7529 7468
7469void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc,
7470 struct sk_buff *probe_resp)
7471{
7472 if (!probe_resp)
7473 return;
7474 if (wlc->probe_resp)
7475 dev_kfree_skb_any(wlc->probe_resp);
7476 wlc->probe_resp = probe_resp;
7477
7478 /* add PLCP */
7479 skb_push(wlc->probe_resp, D11_PHY_HDR_LEN);
7480 brcms_c_update_probe_resp(wlc, false);
7481}
7482
7530/* Write ssid into shared memory */ 7483/* Write ssid into shared memory */
7531static void 7484static void
7532brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg) 7485brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg)
@@ -7546,30 +7499,19 @@ brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg)
7546static void 7499static void
7547brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc, 7500brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
7548 struct brcms_bss_cfg *cfg, 7501 struct brcms_bss_cfg *cfg,
7502 struct sk_buff *probe_resp,
7549 bool suspend) 7503 bool suspend)
7550{ 7504{
7551 u16 *prb_resp; 7505 int len;
7552 int len = BCN_TMPL_LEN;
7553 7506
7554 prb_resp = kmalloc(BCN_TMPL_LEN, GFP_ATOMIC); 7507 len = min_t(size_t, probe_resp->len, BCN_TMPL_LEN);
7555 if (!prb_resp)
7556 return;
7557
7558 /*
7559 * write the probe response to hardware, or save in
7560 * the config structure
7561 */
7562
7563 /* create the probe response template */
7564 brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0,
7565 cfg, prb_resp, &len);
7566 7508
7567 if (suspend) 7509 if (suspend)
7568 brcms_c_suspend_mac_and_wait(wlc); 7510 brcms_c_suspend_mac_and_wait(wlc);
7569 7511
7570 /* write the probe response into the template region */ 7512 /* write the probe response into the template region */
7571 brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE, 7513 brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE,
7572 (len + 3) & ~3, prb_resp); 7514 (len + 3) & ~3, probe_resp->data);
7573 7515
7574 /* write the length of the probe response frame (+PLCP/-FCS) */ 7516 /* write the length of the probe response frame (+PLCP/-FCS) */
7575 brcms_b_write_shm(wlc->hw, M_PRB_RESP_FRM_LEN, (u16) len); 7517 brcms_b_write_shm(wlc->hw, M_PRB_RESP_FRM_LEN, (u16) len);
@@ -7583,13 +7525,11 @@ brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
7583 * PLCP header for the call to brcms_c_mod_prb_rsp_rate_table() 7525 * PLCP header for the call to brcms_c_mod_prb_rsp_rate_table()
7584 * by subtracting the PLCP len and adding the FCS. 7526 * by subtracting the PLCP len and adding the FCS.
7585 */ 7527 */
7586 len += (-D11_PHY_HDR_LEN + FCS_LEN); 7528 brcms_c_mod_prb_rsp_rate_table(wlc,
7587 brcms_c_mod_prb_rsp_rate_table(wlc, (u16) len); 7529 (u16)len + FCS_LEN - D11_PHY_HDR_LEN);
7588 7530
7589 if (suspend) 7531 if (suspend)
7590 brcms_c_enable_mac(wlc); 7532 brcms_c_enable_mac(wlc);
7591
7592 kfree(prb_resp);
7593} 7533}
7594 7534
7595void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend) 7535void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
@@ -7598,8 +7538,12 @@ void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
7598 7538
7599 /* update AP or IBSS probe responses */ 7539 /* update AP or IBSS probe responses */
7600 if (wlc->pub->up && (bsscfg->type == BRCMS_TYPE_AP || 7540 if (wlc->pub->up && (bsscfg->type == BRCMS_TYPE_AP ||
7601 bsscfg->type == BRCMS_TYPE_ADHOC)) 7541 bsscfg->type == BRCMS_TYPE_ADHOC)) {
7602 brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend); 7542 if (!wlc->probe_resp)
7543 return;
7544 brcms_c_bss_update_probe_resp(wlc, bsscfg, wlc->probe_resp,
7545 suspend);
7546 }
7603} 7547}
7604 7548
7605int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, 7549int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,