diff options
author | Hauke Mehrtens <hauke@hauke-m.de> | 2013-03-23 20:46:00 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-03-27 13:37:36 -0400 |
commit | 5f1e59e59ffd11a150144977e38ec55bb868f027 (patch) | |
tree | 71107f32c733330ef4f5effe8eacb4a3813b5f78 /drivers/net/wireless/brcm80211/brcmsmac/main.c | |
parent | c031df31daf69ffbb4c9f6f966df83646241a195 (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.c | 112 |
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 | */ | ||
7338 | static void | ||
7339 | brcms_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, ðer_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 | |||
7389 | int brcms_c_get_header_len(void) | 7328 | int 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 | ||
7469 | void 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 */ |
7531 | static void | 7484 | static void |
7532 | brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg) | 7485 | brcms_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) | |||
7546 | static void | 7499 | static void |
7547 | brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc, | 7500 | brcms_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 | ||
7595 | void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend) | 7535 | void 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 | ||
7605 | int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, | 7549 | int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, |