aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2011-11-08 11:46:54 -0500
committerLuciano Coelho <coelho@ti.com>2011-12-01 08:55:46 -0500
commit560f00241b6d95bde73a570c29d6919b36fdf852 (patch)
tree20c0ea98fcc0dd27db468a8accef19d33769f87c
parentf6efe96edd9c41c624c8f4ddbc4930c1a2d8f1e1 (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.c57
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h1
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
3302static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, 3302static 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
3321static 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);
3515end_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
3482out: 3521out:
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
273struct wl1271_link { 274struct wl1271_link {