Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

wlcore: update beacon and probe_resp templates when rates change

When the data rates change, we get BSS_CHANGED_BASIC_RATES. At this
point, we should update all the templates to match the new rates. We
were changing some of the templates, but the beacon and the probe
response templates were missing.

[Remove redundant min_rate variable - Arik]

Signed-off-by: Luciano Coelho <coelho@ti.com>
Signed-off-by: Arik Nemtsov <arik@wizery.com>

+100 -73
+100 -73
drivers/net/wireless/ti/wlcore/main.c
··· 3277 3277 skb->data, 3278 3278 skb->len, 0, 3279 3279 rates); 3280 - 3281 3280 dev_kfree_skb(skb); 3281 + 3282 + if (ret < 0) 3283 + goto out; 3284 + 3285 + wl1271_debug(DEBUG_AP, "probe response updated"); 3286 + set_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags); 3287 + 3288 + out: 3282 3289 return ret; 3283 3290 } 3284 3291 ··· 3390 3383 return ret; 3391 3384 } 3392 3385 3386 + static int wlcore_set_beacon_template(struct wl1271 *wl, 3387 + struct ieee80211_vif *vif, 3388 + bool is_ap) 3389 + { 3390 + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); 3391 + struct ieee80211_hdr *hdr; 3392 + u32 min_rate; 3393 + int ret; 3394 + int ieoffset = offsetof(struct ieee80211_mgmt, 3395 + u.beacon.variable); 3396 + struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif); 3397 + u16 tmpl_id; 3398 + 3399 + if (!beacon) { 3400 + ret = -EINVAL; 3401 + goto out; 3402 + } 3403 + 3404 + wl1271_debug(DEBUG_MASTER, "beacon updated"); 3405 + 3406 + ret = wl1271_ssid_set(vif, beacon, ieoffset); 3407 + if (ret < 0) { 3408 + dev_kfree_skb(beacon); 3409 + goto out; 3410 + } 3411 + min_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); 3412 + tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON : 3413 + CMD_TEMPL_BEACON; 3414 + ret = wl1271_cmd_template_set(wl, wlvif->role_id, tmpl_id, 3415 + beacon->data, 3416 + beacon->len, 0, 3417 + min_rate); 3418 + if (ret < 0) { 3419 + dev_kfree_skb(beacon); 3420 + goto out; 3421 + } 3422 + 3423 + /* 3424 + * In case we already have a probe-resp beacon set explicitly 3425 + * by usermode, don't use the beacon data. 3426 + */ 3427 + if (test_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags)) 3428 + goto end_bcn; 3429 + 3430 + /* remove TIM ie from probe response */ 3431 + wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset); 3432 + 3433 + /* 3434 + * remove p2p ie from probe response. 3435 + * the fw reponds to probe requests that don't include 3436 + * the p2p ie. probe requests with p2p ie will be passed, 3437 + * and will be responded by the supplicant (the spec 3438 + * forbids including the p2p ie when responding to probe 3439 + * requests that didn't include it). 3440 + */ 3441 + wl12xx_remove_vendor_ie(beacon, WLAN_OUI_WFA, 3442 + WLAN_OUI_TYPE_WFA_P2P, ieoffset); 3443 + 3444 + hdr = (struct ieee80211_hdr *) beacon->data; 3445 + hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 3446 + IEEE80211_STYPE_PROBE_RESP); 3447 + if (is_ap) 3448 + ret = wl1271_ap_set_probe_resp_tmpl_legacy(wl, vif, 3449 + beacon->data, 3450 + beacon->len, 3451 + min_rate); 3452 + else 3453 + ret = wl1271_cmd_template_set(wl, wlvif->role_id, 3454 + CMD_TEMPL_PROBE_RESPONSE, 3455 + beacon->data, 3456 + beacon->len, 0, 3457 + min_rate); 3458 + end_bcn: 3459 + dev_kfree_skb(beacon); 3460 + if (ret < 0) 3461 + goto out; 3462 + 3463 + out: 3464 + return ret; 3465 + } 3466 + 3393 3467 static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, 3394 3468 struct ieee80211_vif *vif, 3395 3469 struct ieee80211_bss_conf *bss_conf, ··· 3489 3401 3490 3402 if ((changed & BSS_CHANGED_AP_PROBE_RESP) && is_ap) { 3491 3403 u32 rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); 3492 - if (!wl1271_ap_set_probe_resp_tmpl(wl, rate, vif)) { 3493 - wl1271_debug(DEBUG_AP, "probe response updated"); 3494 - set_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags); 3495 - } 3404 + 3405 + wl1271_ap_set_probe_resp_tmpl(wl, rate, vif); 3496 3406 } 3497 3407 3498 3408 if ((changed & BSS_CHANGED_BEACON)) { 3499 - struct ieee80211_hdr *hdr; 3500 - u32 min_rate; 3501 - int ieoffset = offsetof(struct ieee80211_mgmt, 3502 - u.beacon.variable); 3503 - struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif); 3504 - u16 tmpl_id; 3505 - 3506 - if (!beacon) { 3507 - ret = -EINVAL; 3508 - goto out; 3509 - } 3510 - 3511 - wl1271_debug(DEBUG_MASTER, "beacon updated"); 3512 - 3513 - ret = wl1271_ssid_set(vif, beacon, ieoffset); 3514 - if (ret < 0) { 3515 - dev_kfree_skb(beacon); 3516 - goto out; 3517 - } 3518 - min_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); 3519 - tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON : 3520 - CMD_TEMPL_BEACON; 3521 - ret = wl1271_cmd_template_set(wl, wlvif->role_id, tmpl_id, 3522 - beacon->data, 3523 - beacon->len, 0, 3524 - min_rate); 3525 - if (ret < 0) { 3526 - dev_kfree_skb(beacon); 3527 - goto out; 3528 - } 3529 - 3530 - /* 3531 - * In case we already have a probe-resp beacon set explicitly 3532 - * by usermode, don't use the beacon data. 3533 - */ 3534 - if (test_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags)) 3535 - goto end_bcn; 3536 - 3537 - /* remove TIM ie from probe response */ 3538 - wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset); 3539 - 3540 - /* 3541 - * remove p2p ie from probe response. 3542 - * the fw reponds to probe requests that don't include 3543 - * the p2p ie. probe requests with p2p ie will be passed, 3544 - * and will be responded by the supplicant (the spec 3545 - * forbids including the p2p ie when responding to probe 3546 - * requests that didn't include it). 3547 - */ 3548 - wl12xx_remove_vendor_ie(beacon, WLAN_OUI_WFA, 3549 - WLAN_OUI_TYPE_WFA_P2P, ieoffset); 3550 - 3551 - hdr = (struct ieee80211_hdr *) beacon->data; 3552 - hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 3553 - IEEE80211_STYPE_PROBE_RESP); 3554 - if (is_ap) 3555 - ret = wl1271_ap_set_probe_resp_tmpl_legacy(wl, vif, 3556 - beacon->data, 3557 - beacon->len, 3558 - min_rate); 3559 - else 3560 - ret = wl1271_cmd_template_set(wl, wlvif->role_id, 3561 - CMD_TEMPL_PROBE_RESPONSE, 3562 - beacon->data, 3563 - beacon->len, 0, 3564 - min_rate); 3565 - end_bcn: 3566 - dev_kfree_skb(beacon); 3409 + ret = wlcore_set_beacon_template(wl, vif, is_ap); 3567 3410 if (ret < 0) 3568 3411 goto out; 3569 3412 } ··· 3529 3510 } 3530 3511 3531 3512 ret = wl1271_ap_init_templates(wl, vif); 3513 + if (ret < 0) 3514 + goto out; 3515 + 3516 + ret = wl1271_ap_set_probe_resp_tmpl(wl, wlvif->basic_rate, vif); 3517 + if (ret < 0) 3518 + goto out; 3519 + 3520 + ret = wlcore_set_beacon_template(wl, vif, true); 3532 3521 if (ret < 0) 3533 3522 goto out; 3534 3523 }