aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx
diff options
context:
space:
mode:
authorJuuso Oikarinen <juuso.oikarinen@nokia.com>2010-11-24 01:16:57 -0500
committerLuciano Coelho <luciano.coelho@nokia.com>2010-11-26 08:33:41 -0500
commit2f6724b24525fc989c0707974b23d96b36132385 (patch)
treeca2890e52f4a17efe2019189652ea09591e10163 /drivers/net/wireless/wl12xx
parent573c67cf819d52d2e12adf75a9a8cfbd216190a3 (diff)
wl1271: Fix setting of the hardware connection monitoring probe-req template
The probe-request template used in the hardware connection monitoring feature thus far has been an empty one, without the SSID IE and without supported rate IEs. This causes problems with some AP's. Additionally, after connected scans, the template for connection maintenance would remain to be the one last used for scanning - potentially incorrect. Fix these by getting a pre-filled directed probe-request template for the associated-to AP from mac80211. Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com> Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx')
-rw-r--r--drivers/net/wireless/wl12xx/cmd.c28
-rw-r--r--drivers/net/wireless/wl12xx/cmd.h2
-rw-r--r--drivers/net/wireless/wl12xx/main.c34
-rw-r--r--drivers/net/wireless/wl12xx/scan.c4
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h3
5 files changed, 58 insertions, 13 deletions
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index f3d0541aaad6..8e438e27e496 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -611,6 +611,34 @@ out:
611 return ret; 611 return ret;
612} 612}
613 613
614struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
615 struct sk_buff *skb)
616{
617 int ret;
618
619 if (!skb)
620 skb = ieee80211_ap_probereq_get(wl->hw, wl->vif);
621 if (!skb)
622 goto out;
623
624 wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len);
625
626 if (wl->band == IEEE80211_BAND_2GHZ)
627 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
628 skb->data, skb->len, 0,
629 wl->conf.tx.basic_rate);
630 else
631 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
632 skb->data, skb->len, 0,
633 wl->conf.tx.basic_rate_5);
634
635 if (ret < 0)
636 wl1271_error("Unable to set ap probe request template.");
637
638out:
639 return skb;
640}
641
614int wl1271_build_qos_null_data(struct wl1271 *wl) 642int wl1271_build_qos_null_data(struct wl1271 *wl)
615{ 643{
616 struct ieee80211_qos_hdr template; 644 struct ieee80211_qos_hdr template;
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 16d1bf814e76..111d112544fc 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -49,6 +49,8 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid);
49int wl1271_cmd_build_probe_req(struct wl1271 *wl, 49int wl1271_cmd_build_probe_req(struct wl1271 *wl,
50 const u8 *ssid, size_t ssid_len, 50 const u8 *ssid, size_t ssid_len,
51 const u8 *ie, size_t ie_len, u8 band); 51 const u8 *ie, size_t ie_len, u8 band);
52struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
53 struct sk_buff *skb);
52int wl1271_build_qos_null_data(struct wl1271 *wl); 54int wl1271_build_qos_null_data(struct wl1271 *wl);
53int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); 55int wl1271_cmd_build_klv_null_data(struct wl1271 *wl);
54int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); 56int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id);
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 97eb186b5a8a..b2432dab4b51 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1814,21 +1814,21 @@ out:
1814 return ret; 1814 return ret;
1815} 1815}
1816 1816
1817static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *beacon) 1817static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb,
1818 int offset)
1818{ 1819{
1819 u8 *ptr = beacon->data + 1820 u8 *ptr = skb->data + offset;
1820 offsetof(struct ieee80211_mgmt, u.beacon.variable);
1821 1821
1822 /* find the location of the ssid in the beacon */ 1822 /* find the location of the ssid in the beacon */
1823 while (ptr < beacon->data + beacon->len) { 1823 while (ptr < skb->data + skb->len) {
1824 if (ptr[0] == WLAN_EID_SSID) { 1824 if (ptr[0] == WLAN_EID_SSID) {
1825 wl->ssid_len = ptr[1]; 1825 wl->ssid_len = ptr[1];
1826 memcpy(wl->ssid, ptr+2, wl->ssid_len); 1826 memcpy(wl->ssid, ptr+2, wl->ssid_len);
1827 return; 1827 return;
1828 } 1828 }
1829 ptr += ptr[1]; 1829 ptr += (ptr[1] + 2);
1830 } 1830 }
1831 wl1271_error("ad-hoc beacon template has no SSID!\n"); 1831 wl1271_error("No SSID in IEs!\n");
1832} 1832}
1833 1833
1834static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, 1834static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
@@ -1871,8 +1871,11 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
1871 1871
1872 if (beacon) { 1872 if (beacon) {
1873 struct ieee80211_hdr *hdr; 1873 struct ieee80211_hdr *hdr;
1874 int ieoffset = offsetof(struct ieee80211_mgmt,
1875 u.beacon.variable);
1876
1877 wl1271_ssid_set(wl, beacon, ieoffset);
1874 1878
1875 wl1271_ssid_set(wl, beacon);
1876 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, 1879 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON,
1877 beacon->data, 1880 beacon->data,
1878 beacon->len, 0, 1881 beacon->len, 0,
@@ -1952,6 +1955,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
1952 if (changed & BSS_CHANGED_ASSOC) { 1955 if (changed & BSS_CHANGED_ASSOC) {
1953 if (bss_conf->assoc) { 1956 if (bss_conf->assoc) {
1954 u32 rates; 1957 u32 rates;
1958 int ieoffset;
1955 wl->aid = bss_conf->aid; 1959 wl->aid = bss_conf->aid;
1956 set_assoc = true; 1960 set_assoc = true;
1957 1961
@@ -1980,13 +1984,13 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
1980 goto out_sleep; 1984 goto out_sleep;
1981 1985
1982 /* 1986 /*
1983 * The SSID is intentionally set to NULL here - the 1987 * Get a template for hardware connection maintenance
1984 * firmware will set the probe request with a
1985 * broadcast SSID regardless of what we set in the
1986 * template.
1987 */ 1988 */
1988 ret = wl1271_cmd_build_probe_req(wl, NULL, 0, 1989 dev_kfree_skb(wl->probereq);
1989 NULL, 0, wl->band); 1990 wl->probereq = wl1271_cmd_build_ap_probe_req(wl, NULL);
1991 ieoffset = offsetof(struct ieee80211_mgmt,
1992 u.probe_req.variable);
1993 wl1271_ssid_set(wl, wl->probereq, ieoffset);
1990 1994
1991 /* enable the connection monitoring feature */ 1995 /* enable the connection monitoring feature */
1992 ret = wl1271_acx_conn_monit_params(wl, true); 1996 ret = wl1271_acx_conn_monit_params(wl, true);
@@ -2009,6 +2013,10 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
2009 clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); 2013 clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
2010 wl->aid = 0; 2014 wl->aid = 0;
2011 2015
2016 /* free probe-request template */
2017 dev_kfree_skb(wl->probereq);
2018 wl->probereq = NULL;
2019
2012 /* re-enable dynamic ps - just in case */ 2020 /* re-enable dynamic ps - just in case */
2013 ieee80211_enable_dyn_ps(wl->vif); 2021 ieee80211_enable_dyn_ps(wl->vif);
2014 2022
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index f3f2c5b011ee..6f897b9d90ca 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -51,6 +51,10 @@ void wl1271_scan_complete_work(struct work_struct *work)
51 wl->scan.req = NULL; 51 wl->scan.req = NULL;
52 ieee80211_scan_completed(wl->hw, false); 52 ieee80211_scan_completed(wl->hw, false);
53 53
54 /* restore hardware connection monitoring template */
55 if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
56 wl1271_cmd_build_ap_probe_req(wl, wl->probereq);
57
54 if (wl->scan.failed) { 58 if (wl->scan.failed) {
55 wl1271_info("Scan completed due to error."); 59 wl1271_info("Scan completed due to error.");
56 ieee80211_queue_work(wl->hw, &wl->recovery_work); 60 ieee80211_queue_work(wl->hw, &wl->recovery_work);
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 3c836e6063e6..9f8aa695c3af 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -431,6 +431,9 @@ struct wl1271 {
431 struct wl1271_scan scan; 431 struct wl1271_scan scan;
432 struct delayed_work scan_complete_work; 432 struct delayed_work scan_complete_work;
433 433
434 /* probe-req template for the current AP */
435 struct sk_buff *probereq;
436
434 /* Our association ID */ 437 /* Our association ID */
435 u16 aid; 438 u16 aid;
436 439