aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rndis_wlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rndis_wlan.c')
-rw-r--r--drivers/net/wireless/rndis_wlan.c192
1 files changed, 167 insertions, 25 deletions
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 4a4f00591447..848cc2cce247 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -129,6 +129,7 @@ MODULE_PARM_DESC(workaround_interval,
129#define OID_802_11_RTS_THRESHOLD cpu_to_le32(0x0d01020a) 129#define OID_802_11_RTS_THRESHOLD cpu_to_le32(0x0d01020a)
130#define OID_802_11_SUPPORTED_RATES cpu_to_le32(0x0d01020e) 130#define OID_802_11_SUPPORTED_RATES cpu_to_le32(0x0d01020e)
131#define OID_802_11_CONFIGURATION cpu_to_le32(0x0d010211) 131#define OID_802_11_CONFIGURATION cpu_to_le32(0x0d010211)
132#define OID_802_11_POWER_MODE cpu_to_le32(0x0d010216)
132#define OID_802_11_BSSID_LIST cpu_to_le32(0x0d010217) 133#define OID_802_11_BSSID_LIST cpu_to_le32(0x0d010217)
133 134
134 135
@@ -239,6 +240,12 @@ enum ndis_80211_addwep_bits {
239 NDIS_80211_ADDWEP_TRANSMIT_KEY = cpu_to_le32(1 << 31) 240 NDIS_80211_ADDWEP_TRANSMIT_KEY = cpu_to_le32(1 << 31)
240}; 241};
241 242
243enum ndis_80211_power_mode {
244 NDIS_80211_POWER_MODE_CAM,
245 NDIS_80211_POWER_MODE_MAX_PSP,
246 NDIS_80211_POWER_MODE_FAST_PSP,
247};
248
242struct ndis_80211_auth_request { 249struct ndis_80211_auth_request {
243 __le32 length; 250 __le32 length;
244 u8 bssid[6]; 251 u8 bssid[6];
@@ -478,6 +485,9 @@ struct rndis_wlan_private {
478 struct mutex command_lock; 485 struct mutex command_lock;
479 unsigned long work_pending; 486 unsigned long work_pending;
480 int last_qual; 487 int last_qual;
488 s32 cqm_rssi_thold;
489 u32 cqm_rssi_hyst;
490 int last_cqm_event_rssi;
481 491
482 struct ieee80211_supported_band band; 492 struct ieee80211_supported_band band;
483 struct ieee80211_channel channels[ARRAY_SIZE(rndis_channels)]; 493 struct ieee80211_channel channels[ARRAY_SIZE(rndis_channels)];
@@ -500,10 +510,10 @@ struct rndis_wlan_private {
500 510
501 /* hardware state */ 511 /* hardware state */
502 bool radio_on; 512 bool radio_on;
513 int power_mode;
503 int infra_mode; 514 int infra_mode;
504 bool connected; 515 bool connected;
505 u8 bssid[ETH_ALEN]; 516 u8 bssid[ETH_ALEN];
506 struct ndis_80211_ssid essid;
507 __le32 current_command_oid; 517 __le32 current_command_oid;
508 518
509 /* encryption stuff */ 519 /* encryption stuff */
@@ -570,7 +580,14 @@ static int rndis_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
570 580
571static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev); 581static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev);
572 582
573static struct cfg80211_ops rndis_config_ops = { 583static int rndis_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
584 bool enabled, int timeout);
585
586static int rndis_set_cqm_rssi_config(struct wiphy *wiphy,
587 struct net_device *dev,
588 s32 rssi_thold, u32 rssi_hyst);
589
590static const struct cfg80211_ops rndis_config_ops = {
574 .change_virtual_intf = rndis_change_virtual_intf, 591 .change_virtual_intf = rndis_change_virtual_intf,
575 .scan = rndis_scan, 592 .scan = rndis_scan,
576 .set_wiphy_params = rndis_set_wiphy_params, 593 .set_wiphy_params = rndis_set_wiphy_params,
@@ -589,6 +606,8 @@ static struct cfg80211_ops rndis_config_ops = {
589 .set_pmksa = rndis_set_pmksa, 606 .set_pmksa = rndis_set_pmksa,
590 .del_pmksa = rndis_del_pmksa, 607 .del_pmksa = rndis_del_pmksa,
591 .flush_pmksa = rndis_flush_pmksa, 608 .flush_pmksa = rndis_flush_pmksa,
609 .set_power_mgmt = rndis_set_power_mgmt,
610 .set_cqm_rssi_config = rndis_set_cqm_rssi_config,
592}; 611};
593 612
594static void *rndis_wiphy_privid = &rndis_wiphy_privid; 613static void *rndis_wiphy_privid = &rndis_wiphy_privid;
@@ -687,6 +706,7 @@ static const char *oid_to_string(__le32 oid)
687 OID_STR(OID_802_11_ADD_KEY); 706 OID_STR(OID_802_11_ADD_KEY);
688 OID_STR(OID_802_11_REMOVE_KEY); 707 OID_STR(OID_802_11_REMOVE_KEY);
689 OID_STR(OID_802_11_ASSOCIATION_INFORMATION); 708 OID_STR(OID_802_11_ASSOCIATION_INFORMATION);
709 OID_STR(OID_802_11_CAPABILITY);
690 OID_STR(OID_802_11_PMKID); 710 OID_STR(OID_802_11_PMKID);
691 OID_STR(OID_802_11_NETWORK_TYPES_SUPPORTED); 711 OID_STR(OID_802_11_NETWORK_TYPES_SUPPORTED);
692 OID_STR(OID_802_11_NETWORK_TYPE_IN_USE); 712 OID_STR(OID_802_11_NETWORK_TYPE_IN_USE);
@@ -697,6 +717,7 @@ static const char *oid_to_string(__le32 oid)
697 OID_STR(OID_802_11_RTS_THRESHOLD); 717 OID_STR(OID_802_11_RTS_THRESHOLD);
698 OID_STR(OID_802_11_SUPPORTED_RATES); 718 OID_STR(OID_802_11_SUPPORTED_RATES);
699 OID_STR(OID_802_11_CONFIGURATION); 719 OID_STR(OID_802_11_CONFIGURATION);
720 OID_STR(OID_802_11_POWER_MODE);
700 OID_STR(OID_802_11_BSSID_LIST); 721 OID_STR(OID_802_11_BSSID_LIST);
701#undef OID_STR 722#undef OID_STR
702 } 723 }
@@ -1026,7 +1047,6 @@ static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
1026 return ret; 1047 return ret;
1027 } 1048 }
1028 if (ret == 0) { 1049 if (ret == 0) {
1029 memcpy(&priv->essid, ssid, sizeof(priv->essid));
1030 priv->radio_on = true; 1050 priv->radio_on = true;
1031 netdev_dbg(usbdev->net, "%s(): radio_on = true\n", __func__); 1051 netdev_dbg(usbdev->net, "%s(): radio_on = true\n", __func__);
1032 } 1052 }
@@ -1967,8 +1987,8 @@ static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev,
1967 int ie_len, bssid_len; 1987 int ie_len, bssid_len;
1968 u8 *ie; 1988 u8 *ie;
1969 1989
1970 netdev_dbg(usbdev->net, " found bssid: '%.32s' [%pM]\n", 1990 netdev_dbg(usbdev->net, " found bssid: '%.32s' [%pM], len: %d\n",
1971 bssid->ssid.essid, bssid->mac); 1991 bssid->ssid.essid, bssid->mac, le32_to_cpu(bssid->length));
1972 1992
1973 /* parse bssid structure */ 1993 /* parse bssid structure */
1974 bssid_len = le32_to_cpu(bssid->length); 1994 bssid_len = le32_to_cpu(bssid->length);
@@ -2002,54 +2022,98 @@ static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev,
2002 GFP_KERNEL); 2022 GFP_KERNEL);
2003} 2023}
2004 2024
2025static struct ndis_80211_bssid_ex *next_bssid_list_item(
2026 struct ndis_80211_bssid_ex *bssid,
2027 int *bssid_len, void *buf, int len)
2028{
2029 void *buf_end, *bssid_end;
2030
2031 buf_end = (char *)buf + len;
2032 bssid_end = (char *)bssid + *bssid_len;
2033
2034 if ((int)(buf_end - bssid_end) < sizeof(bssid->length)) {
2035 *bssid_len = 0;
2036 return NULL;
2037 } else {
2038 bssid = (void *)((char *)bssid + *bssid_len);
2039 *bssid_len = le32_to_cpu(bssid->length);
2040 return bssid;
2041 }
2042}
2043
2044static bool check_bssid_list_item(struct ndis_80211_bssid_ex *bssid,
2045 int bssid_len, void *buf, int len)
2046{
2047 void *buf_end, *bssid_end;
2048
2049 if (!bssid || bssid_len <= 0 || bssid_len > len)
2050 return false;
2051
2052 buf_end = (char *)buf + len;
2053 bssid_end = (char *)bssid + bssid_len;
2054
2055 return (int)(buf_end - bssid_end) >= 0 && (int)(bssid_end - buf) >= 0;
2056}
2057
2005static int rndis_check_bssid_list(struct usbnet *usbdev, u8 *match_bssid, 2058static int rndis_check_bssid_list(struct usbnet *usbdev, u8 *match_bssid,
2006 bool *matched) 2059 bool *matched)
2007{ 2060{
2008 void *buf = NULL; 2061 void *buf = NULL;
2009 struct ndis_80211_bssid_list_ex *bssid_list; 2062 struct ndis_80211_bssid_list_ex *bssid_list;
2010 struct ndis_80211_bssid_ex *bssid; 2063 struct ndis_80211_bssid_ex *bssid;
2011 int ret = -EINVAL, len, count, bssid_len; 2064 int ret = -EINVAL, len, count, bssid_len, real_count, new_len;
2012 bool resized = false;
2013 2065
2014 netdev_dbg(usbdev->net, "check_bssid_list\n"); 2066 netdev_dbg(usbdev->net, "%s()\n", __func__);
2015 2067
2016 len = CONTROL_BUFFER_SIZE; 2068 len = CONTROL_BUFFER_SIZE;
2017resize_buf: 2069resize_buf:
2018 buf = kmalloc(len, GFP_KERNEL); 2070 buf = kzalloc(len, GFP_KERNEL);
2019 if (!buf) { 2071 if (!buf) {
2020 ret = -ENOMEM; 2072 ret = -ENOMEM;
2021 goto out; 2073 goto out;
2022 } 2074 }
2023 2075
2024 ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len); 2076 /* BSSID-list might have got bigger last time we checked, keep
2025 if (ret != 0) 2077 * resizing until it won't get any bigger.
2078 */
2079 new_len = len;
2080 ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &new_len);
2081 if (ret != 0 || new_len < sizeof(struct ndis_80211_bssid_list_ex))
2026 goto out; 2082 goto out;
2027 2083
2028 if (!resized && len > CONTROL_BUFFER_SIZE) { 2084 if (new_len > len) {
2029 resized = true; 2085 len = new_len;
2030 kfree(buf); 2086 kfree(buf);
2031 goto resize_buf; 2087 goto resize_buf;
2032 } 2088 }
2033 2089
2090 len = new_len;
2091
2034 bssid_list = buf; 2092 bssid_list = buf;
2035 bssid = bssid_list->bssid;
2036 bssid_len = le32_to_cpu(bssid->length);
2037 count = le32_to_cpu(bssid_list->num_items); 2093 count = le32_to_cpu(bssid_list->num_items);
2038 netdev_dbg(usbdev->net, "check_bssid_list: %d BSSIDs found (buflen: %d)\n", 2094 real_count = 0;
2039 count, len); 2095 netdev_dbg(usbdev->net, "%s(): buflen: %d\n", __func__, len);
2040 2096
2041 while (count && ((void *)bssid + bssid_len) <= (buf + len)) { 2097 bssid_len = 0;
2098 bssid = next_bssid_list_item(bssid_list->bssid, &bssid_len, buf, len);
2099
2100 /* Device returns incorrect 'num_items'. Workaround by ignoring the
2101 * received 'num_items' and walking through full bssid buffer instead.
2102 */
2103 while (check_bssid_list_item(bssid, bssid_len, buf, len)) {
2042 if (rndis_bss_info_update(usbdev, bssid) && match_bssid && 2104 if (rndis_bss_info_update(usbdev, bssid) && match_bssid &&
2043 matched) { 2105 matched) {
2044 if (compare_ether_addr(bssid->mac, match_bssid)) 2106 if (compare_ether_addr(bssid->mac, match_bssid))
2045 *matched = true; 2107 *matched = true;
2046 } 2108 }
2047 2109
2048 bssid = (void *)bssid + bssid_len; 2110 real_count++;
2049 bssid_len = le32_to_cpu(bssid->length); 2111 bssid = next_bssid_list_item(bssid, &bssid_len, buf, len);
2050 count--;
2051 } 2112 }
2052 2113
2114 netdev_dbg(usbdev->net, "%s(): num_items from device: %d, really found:"
2115 " %d\n", __func__, count, real_count);
2116
2053out: 2117out:
2054 kfree(buf); 2118 kfree(buf);
2055 return ret; 2119 return ret;
@@ -2391,6 +2455,9 @@ static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
2391 2455
2392 priv->encr_tx_key_index = key_index; 2456 priv->encr_tx_key_index = key_index;
2393 2457
2458 if (is_wpa_key(priv, key_index))
2459 return 0;
2460
2394 key = priv->encr_keys[key_index]; 2461 key = priv->encr_keys[key_index];
2395 2462
2396 return add_wep_key(usbdev, key.material, key.len, key_index); 2463 return add_wep_key(usbdev, key.material, key.len, key_index);
@@ -2521,6 +2588,51 @@ static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
2521 return rndis_set_oid(usbdev, OID_802_11_PMKID, &pmkid, sizeof(pmkid)); 2588 return rndis_set_oid(usbdev, OID_802_11_PMKID, &pmkid, sizeof(pmkid));
2522} 2589}
2523 2590
2591static int rndis_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
2592 bool enabled, int timeout)
2593{
2594 struct rndis_wlan_private *priv = wiphy_priv(wiphy);
2595 struct usbnet *usbdev = priv->usbdev;
2596 int power_mode;
2597 __le32 mode;
2598 int ret;
2599
2600 netdev_dbg(usbdev->net, "%s(): %s, %d\n", __func__,
2601 enabled ? "enabled" : "disabled",
2602 timeout);
2603
2604 if (enabled)
2605 power_mode = NDIS_80211_POWER_MODE_FAST_PSP;
2606 else
2607 power_mode = NDIS_80211_POWER_MODE_CAM;
2608
2609 if (power_mode == priv->power_mode)
2610 return 0;
2611
2612 priv->power_mode = power_mode;
2613
2614 mode = cpu_to_le32(power_mode);
2615 ret = rndis_set_oid(usbdev, OID_802_11_POWER_MODE, &mode, sizeof(mode));
2616
2617 netdev_dbg(usbdev->net, "%s(): OID_802_11_POWER_MODE -> %d\n",
2618 __func__, ret);
2619
2620 return ret;
2621}
2622
2623static int rndis_set_cqm_rssi_config(struct wiphy *wiphy,
2624 struct net_device *dev,
2625 s32 rssi_thold, u32 rssi_hyst)
2626{
2627 struct rndis_wlan_private *priv = wiphy_priv(wiphy);
2628
2629 priv->cqm_rssi_thold = rssi_thold;
2630 priv->cqm_rssi_hyst = rssi_hyst;
2631 priv->last_cqm_event_rssi = 0;
2632
2633 return 0;
2634}
2635
2524static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid, 2636static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid,
2525 struct ndis_80211_assoc_info *info) 2637 struct ndis_80211_assoc_info *info)
2526{ 2638{
@@ -3050,6 +3162,32 @@ static int rndis_wlan_get_caps(struct usbnet *usbdev, struct wiphy *wiphy)
3050 return retval; 3162 return retval;
3051} 3163}
3052 3164
3165static void rndis_do_cqm(struct usbnet *usbdev, s32 rssi)
3166{
3167 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
3168 enum nl80211_cqm_rssi_threshold_event event;
3169 int thold, hyst, last_event;
3170
3171 if (priv->cqm_rssi_thold >= 0 || rssi >= 0)
3172 return;
3173 if (priv->infra_mode != NDIS_80211_INFRA_INFRA)
3174 return;
3175
3176 last_event = priv->last_cqm_event_rssi;
3177 thold = priv->cqm_rssi_thold;
3178 hyst = priv->cqm_rssi_hyst;
3179
3180 if (rssi < thold && (last_event == 0 || rssi < last_event - hyst))
3181 event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
3182 else if (rssi > thold && (last_event == 0 || rssi > last_event + hyst))
3183 event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
3184 else
3185 return;
3186
3187 priv->last_cqm_event_rssi = rssi;
3188 cfg80211_cqm_rssi_notify(usbdev->net, event, GFP_KERNEL);
3189}
3190
3053#define DEVICE_POLLER_JIFFIES (HZ) 3191#define DEVICE_POLLER_JIFFIES (HZ)
3054static void rndis_device_poller(struct work_struct *work) 3192static void rndis_device_poller(struct work_struct *work)
3055{ 3193{
@@ -3084,8 +3222,10 @@ static void rndis_device_poller(struct work_struct *work)
3084 3222
3085 len = sizeof(rssi); 3223 len = sizeof(rssi);
3086 ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len); 3224 ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len);
3087 if (ret == 0) 3225 if (ret == 0) {
3088 priv->last_qual = level_to_qual(le32_to_cpu(rssi)); 3226 priv->last_qual = level_to_qual(le32_to_cpu(rssi));
3227 rndis_do_cqm(usbdev, le32_to_cpu(rssi));
3228 }
3089 3229
3090 netdev_dbg(usbdev->net, "dev-poller: OID_802_11_RSSI -> %d, rssi:%d, qual: %d\n", 3230 netdev_dbg(usbdev->net, "dev-poller: OID_802_11_RSSI -> %d, rssi:%d, qual: %d\n",
3091 ret, le32_to_cpu(rssi), level_to_qual(le32_to_cpu(rssi))); 3231 ret, le32_to_cpu(rssi), level_to_qual(le32_to_cpu(rssi)));
@@ -3347,13 +3487,15 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
3347 3487
3348 set_default_iw_params(usbdev); 3488 set_default_iw_params(usbdev);
3349 3489
3490 priv->power_mode = -1;
3491
3350 /* set default rts/frag */ 3492 /* set default rts/frag */
3351 rndis_set_wiphy_params(wiphy, 3493 rndis_set_wiphy_params(wiphy,
3352 WIPHY_PARAM_FRAG_THRESHOLD | WIPHY_PARAM_RTS_THRESHOLD); 3494 WIPHY_PARAM_FRAG_THRESHOLD | WIPHY_PARAM_RTS_THRESHOLD);
3353 3495
3354 /* turn radio on */ 3496 /* turn radio off on init */
3355 priv->radio_on = true; 3497 priv->radio_on = false;
3356 disassociate(usbdev, true); 3498 disassociate(usbdev, false);
3357 netif_carrier_off(usbdev->net); 3499 netif_carrier_off(usbdev->net);
3358 3500
3359 return 0; 3501 return 0;