diff options
author | Arik Nemtsov <arik@wizery.com> | 2011-11-08 11:46:54 -0500 |
---|---|---|
committer | Luciano Coelho <coelho@ti.com> | 2011-12-01 08:55:46 -0500 |
commit | 560f00241b6d95bde73a570c29d6919b36fdf852 (patch) | |
tree | 20c0ea98fcc0dd27db468a8accef19d33769f87c | |
parent | f6efe96edd9c41c624c8f4ddbc4930c1a2d8f1e1 (diff) |
wl12xx: configure probe-resp template according to notification
When operating in AP-mode, replace our probe-response template when a
notification is recieved from mac80211. We preserve the "legacy" way of
configuring a probe-response according to beacon for IBSS mode and for
versions of hostapd that do not support this feature.
Signed-off-by: Guy Eilam <guy@wizery.com>
Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 57 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl12xx.h | 1 |
2 files changed, 51 insertions, 7 deletions
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index dbb088eadf71..3750a6e479f3 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -3299,11 +3299,30 @@ static void wl12xx_remove_vendor_ie(struct sk_buff *skb, | |||
3299 | skb_trim(skb, skb->len - len); | 3299 | skb_trim(skb, skb->len - len); |
3300 | } | 3300 | } |
3301 | 3301 | ||
3302 | static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, | 3302 | static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, u32 rates) |
3303 | struct ieee80211_vif *vif, | 3303 | { |
3304 | u8 *probe_rsp_data, | 3304 | struct sk_buff *skb; |
3305 | size_t probe_rsp_len, | 3305 | int ret; |
3306 | u32 rates) | 3306 | |
3307 | skb = ieee80211_proberesp_get(wl->hw, wl->vif); | ||
3308 | if (!skb) | ||
3309 | return -EINVAL; | ||
3310 | |||
3311 | ret = wl1271_cmd_template_set(wl, | ||
3312 | CMD_TEMPL_AP_PROBE_RESPONSE, | ||
3313 | skb->data, | ||
3314 | skb->len, 0, | ||
3315 | rates); | ||
3316 | |||
3317 | dev_kfree_skb(skb); | ||
3318 | return ret; | ||
3319 | } | ||
3320 | |||
3321 | static int wl1271_ap_set_probe_resp_tmpl_legacy(struct wl1271 *wl, | ||
3322 | struct ieee80211_vif *vif, | ||
3323 | u8 *probe_rsp_data, | ||
3324 | size_t probe_rsp_len, | ||
3325 | u32 rates) | ||
3307 | { | 3326 | { |
3308 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | 3327 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); |
3309 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | 3328 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
@@ -3416,6 +3435,16 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, | |||
3416 | wlvif->beacon_int = bss_conf->beacon_int; | 3435 | wlvif->beacon_int = bss_conf->beacon_int; |
3417 | } | 3436 | } |
3418 | 3437 | ||
3438 | if ((changed & BSS_CHANGED_AP_PROBE_RESP) && is_ap) { | ||
3439 | u32 rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); | ||
3440 | ret = wl1271_ap_set_probe_resp_tmpl(wl, rate); | ||
3441 | if (ret < 0) | ||
3442 | goto out; | ||
3443 | |||
3444 | wl1271_debug(DEBUG_AP, "probe response updated"); | ||
3445 | set_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags); | ||
3446 | } | ||
3447 | |||
3419 | if ((changed & BSS_CHANGED_BEACON)) { | 3448 | if ((changed & BSS_CHANGED_BEACON)) { |
3420 | struct ieee80211_hdr *hdr; | 3449 | struct ieee80211_hdr *hdr; |
3421 | u32 min_rate; | 3450 | u32 min_rate; |
@@ -3424,8 +3453,10 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, | |||
3424 | struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif); | 3453 | struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif); |
3425 | u16 tmpl_id; | 3454 | u16 tmpl_id; |
3426 | 3455 | ||
3427 | if (!beacon) | 3456 | if (!beacon) { |
3457 | ret = -EINVAL; | ||
3428 | goto out; | 3458 | goto out; |
3459 | } | ||
3429 | 3460 | ||
3430 | wl1271_debug(DEBUG_MASTER, "beacon updated"); | 3461 | wl1271_debug(DEBUG_MASTER, "beacon updated"); |
3431 | 3462 | ||
@@ -3446,6 +3477,13 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, | |||
3446 | goto out; | 3477 | goto out; |
3447 | } | 3478 | } |
3448 | 3479 | ||
3480 | /* | ||
3481 | * In case we already have a probe-resp beacon set explicitly | ||
3482 | * by usermode, don't use the beacon data. | ||
3483 | */ | ||
3484 | if (test_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags)) | ||
3485 | goto end_bcn; | ||
3486 | |||
3449 | /* remove TIM ie from probe response */ | 3487 | /* remove TIM ie from probe response */ |
3450 | wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset); | 3488 | wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset); |
3451 | 3489 | ||
@@ -3464,7 +3502,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, | |||
3464 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 3502 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
3465 | IEEE80211_STYPE_PROBE_RESP); | 3503 | IEEE80211_STYPE_PROBE_RESP); |
3466 | if (is_ap) | 3504 | if (is_ap) |
3467 | ret = wl1271_ap_set_probe_resp_tmpl(wl, vif, | 3505 | ret = wl1271_ap_set_probe_resp_tmpl_legacy(wl, vif, |
3468 | beacon->data, | 3506 | beacon->data, |
3469 | beacon->len, | 3507 | beacon->len, |
3470 | min_rate); | 3508 | min_rate); |
@@ -3474,12 +3512,15 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, | |||
3474 | beacon->data, | 3512 | beacon->data, |
3475 | beacon->len, 0, | 3513 | beacon->len, 0, |
3476 | min_rate); | 3514 | min_rate); |
3515 | end_bcn: | ||
3477 | dev_kfree_skb(beacon); | 3516 | dev_kfree_skb(beacon); |
3478 | if (ret < 0) | 3517 | if (ret < 0) |
3479 | goto out; | 3518 | goto out; |
3480 | } | 3519 | } |
3481 | 3520 | ||
3482 | out: | 3521 | out: |
3522 | if (ret != 0) | ||
3523 | wl1271_error("beacon info change failed: %d", ret); | ||
3483 | return ret; | 3524 | return ret; |
3484 | } | 3525 | } |
3485 | 3526 | ||
@@ -3536,6 +3577,8 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, | |||
3536 | goto out; | 3577 | goto out; |
3537 | 3578 | ||
3538 | clear_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags); | 3579 | clear_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags); |
3580 | clear_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, | ||
3581 | &wlvif->flags); | ||
3539 | wl1271_debug(DEBUG_AP, "stopped AP"); | 3582 | wl1271_debug(DEBUG_AP, "stopped AP"); |
3540 | } | 3583 | } |
3541 | } | 3584 | } |
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index e58e801f7aea..f1c911774bfd 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h | |||
@@ -268,6 +268,7 @@ enum wl12xx_vif_flags { | |||
268 | WLVIF_FLAG_RX_STREAMING_STARTED, | 268 | WLVIF_FLAG_RX_STREAMING_STARTED, |
269 | WLVIF_FLAG_PSPOLL_FAILURE, | 269 | WLVIF_FLAG_PSPOLL_FAILURE, |
270 | WLVIF_FLAG_CS_PROGRESS, | 270 | WLVIF_FLAG_CS_PROGRESS, |
271 | WLVIF_FLAG_AP_PROBE_RESP_SET, | ||
271 | }; | 272 | }; |
272 | 273 | ||
273 | struct wl1271_link { | 274 | struct wl1271_link { |