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.c206
1 files changed, 183 insertions, 23 deletions
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 71b5971da597..19f3d568f700 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -156,6 +156,12 @@ MODULE_PARM_DESC(workaround_interval,
156#define RNDIS_STATUS_ADAPTER_NOT_OPEN cpu_to_le32(0xc0010012) 156#define RNDIS_STATUS_ADAPTER_NOT_OPEN cpu_to_le32(0xc0010012)
157 157
158 158
159/* Known device types */
160#define RNDIS_UNKNOWN 0
161#define RNDIS_BCM4320A 1
162#define RNDIS_BCM4320B 2
163
164
159/* NDIS data structures. Taken from wpa_supplicant driver_ndis.c 165/* NDIS data structures. Taken from wpa_supplicant driver_ndis.c
160 * slightly modified for datatype endianess, etc 166 * slightly modified for datatype endianess, etc
161 */ 167 */
@@ -478,6 +484,7 @@ struct rndis_wlan_private {
478 struct ieee80211_rate rates[ARRAY_SIZE(rndis_rates)]; 484 struct ieee80211_rate rates[ARRAY_SIZE(rndis_rates)];
479 u32 cipher_suites[ARRAY_SIZE(rndis_cipher_suites)]; 485 u32 cipher_suites[ARRAY_SIZE(rndis_cipher_suites)];
480 486
487 int device_type;
481 int caps; 488 int caps;
482 int multicast_size; 489 int multicast_size;
483 490
@@ -810,7 +817,8 @@ exit_unlock:
810 return ret; 817 return ret;
811} 818}
812 819
813static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len) 820static int rndis_set_oid(struct usbnet *dev, __le32 oid, const void *data,
821 int len)
814{ 822{
815 struct rndis_wlan_private *priv = get_rndis_wlan_priv(dev); 823 struct rndis_wlan_private *priv = get_rndis_wlan_priv(dev);
816 union { 824 union {
@@ -994,7 +1002,18 @@ static int level_to_qual(int level)
994 */ 1002 */
995static int set_infra_mode(struct usbnet *usbdev, int mode); 1003static int set_infra_mode(struct usbnet *usbdev, int mode);
996static void restore_keys(struct usbnet *usbdev); 1004static void restore_keys(struct usbnet *usbdev);
997static int rndis_check_bssid_list(struct usbnet *usbdev); 1005static int rndis_check_bssid_list(struct usbnet *usbdev, u8 *match_bssid,
1006 bool *matched);
1007
1008static int rndis_start_bssid_list_scan(struct usbnet *usbdev)
1009{
1010 __le32 tmp;
1011
1012 /* Note: OID_802_11_BSSID_LIST_SCAN clears internal BSS list. */
1013 tmp = cpu_to_le32(1);
1014 return rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp,
1015 sizeof(tmp));
1016}
998 1017
999static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) 1018static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
1000{ 1019{
@@ -1015,7 +1034,7 @@ static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
1015 return ret; 1034 return ret;
1016} 1035}
1017 1036
1018static int set_bssid(struct usbnet *usbdev, u8 bssid[ETH_ALEN]) 1037static int set_bssid(struct usbnet *usbdev, const u8 *bssid)
1019{ 1038{
1020 int ret; 1039 int ret;
1021 1040
@@ -1031,7 +1050,9 @@ static int set_bssid(struct usbnet *usbdev, u8 bssid[ETH_ALEN])
1031 1050
1032static int clear_bssid(struct usbnet *usbdev) 1051static int clear_bssid(struct usbnet *usbdev)
1033{ 1052{
1034 u8 broadcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 1053 static const u8 broadcast_mac[ETH_ALEN] = {
1054 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
1055 };
1035 1056
1036 return set_bssid(usbdev, broadcast_mac); 1057 return set_bssid(usbdev, broadcast_mac);
1037} 1058}
@@ -1904,14 +1925,14 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
1904 struct usbnet *usbdev = netdev_priv(dev); 1925 struct usbnet *usbdev = netdev_priv(dev);
1905 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); 1926 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
1906 int ret; 1927 int ret;
1907 __le32 tmp; 1928 int delay = SCAN_DELAY_JIFFIES;
1908 1929
1909 netdev_dbg(usbdev->net, "cfg80211.scan\n"); 1930 netdev_dbg(usbdev->net, "cfg80211.scan\n");
1910 1931
1911 /* Get current bssid list from device before new scan, as new scan 1932 /* Get current bssid list from device before new scan, as new scan
1912 * clears internal bssid list. 1933 * clears internal bssid list.
1913 */ 1934 */
1914 rndis_check_bssid_list(usbdev); 1935 rndis_check_bssid_list(usbdev, NULL, NULL);
1915 1936
1916 if (!request) 1937 if (!request)
1917 return -EINVAL; 1938 return -EINVAL;
@@ -1921,13 +1942,13 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
1921 1942
1922 priv->scan_request = request; 1943 priv->scan_request = request;
1923 1944
1924 tmp = cpu_to_le32(1); 1945 ret = rndis_start_bssid_list_scan(usbdev);
1925 ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp,
1926 sizeof(tmp));
1927 if (ret == 0) { 1946 if (ret == 0) {
1947 if (priv->device_type == RNDIS_BCM4320A)
1948 delay = HZ;
1949
1928 /* Wait before retrieving scan results from device */ 1950 /* Wait before retrieving scan results from device */
1929 queue_delayed_work(priv->workqueue, &priv->scan_work, 1951 queue_delayed_work(priv->workqueue, &priv->scan_work, delay);
1930 SCAN_DELAY_JIFFIES);
1931 } 1952 }
1932 1953
1933 return ret; 1954 return ret;
@@ -1981,7 +2002,8 @@ static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev,
1981 GFP_KERNEL); 2002 GFP_KERNEL);
1982} 2003}
1983 2004
1984static int rndis_check_bssid_list(struct usbnet *usbdev) 2005static int rndis_check_bssid_list(struct usbnet *usbdev, u8 *match_bssid,
2006 bool *matched)
1985{ 2007{
1986 void *buf = NULL; 2008 void *buf = NULL;
1987 struct ndis_80211_bssid_list_ex *bssid_list; 2009 struct ndis_80211_bssid_list_ex *bssid_list;
@@ -2017,7 +2039,11 @@ resize_buf:
2017 count, len); 2039 count, len);
2018 2040
2019 while (count && ((void *)bssid + bssid_len) <= (buf + len)) { 2041 while (count && ((void *)bssid + bssid_len) <= (buf + len)) {
2020 rndis_bss_info_update(usbdev, bssid); 2042 if (rndis_bss_info_update(usbdev, bssid) && match_bssid &&
2043 matched) {
2044 if (compare_ether_addr(bssid->mac, match_bssid))
2045 *matched = true;
2046 }
2021 2047
2022 bssid = (void *)bssid + bssid_len; 2048 bssid = (void *)bssid + bssid_len;
2023 bssid_len = le32_to_cpu(bssid->length); 2049 bssid_len = le32_to_cpu(bssid->length);
@@ -2041,7 +2067,7 @@ static void rndis_get_scan_results(struct work_struct *work)
2041 if (!priv->scan_request) 2067 if (!priv->scan_request)
2042 return; 2068 return;
2043 2069
2044 ret = rndis_check_bssid_list(usbdev); 2070 ret = rndis_check_bssid_list(usbdev, NULL, NULL);
2045 2071
2046 cfg80211_scan_done(priv->scan_request, ret < 0); 2072 cfg80211_scan_done(priv->scan_request, ret < 0);
2047 2073
@@ -2495,6 +2521,91 @@ static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
2495 return rndis_set_oid(usbdev, OID_802_11_PMKID, &pmkid, sizeof(pmkid)); 2521 return rndis_set_oid(usbdev, OID_802_11_PMKID, &pmkid, sizeof(pmkid));
2496} 2522}
2497 2523
2524static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid,
2525 struct ndis_80211_assoc_info *info)
2526{
2527 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
2528 struct ieee80211_channel *channel;
2529 struct ndis_80211_conf config;
2530 struct ndis_80211_ssid ssid;
2531 s32 signal;
2532 u64 timestamp;
2533 u16 capability;
2534 u16 beacon_interval;
2535 __le32 rssi;
2536 u8 ie_buf[34];
2537 int len, ret, ie_len;
2538
2539 /* Get signal quality, in case of error use rssi=0 and ignore error. */
2540 len = sizeof(rssi);
2541 rssi = 0;
2542 ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len);
2543 signal = level_to_qual(le32_to_cpu(rssi));
2544
2545 netdev_dbg(usbdev->net, "%s(): OID_802_11_RSSI -> %d, "
2546 "rssi:%d, qual: %d\n", __func__, ret, le32_to_cpu(rssi),
2547 level_to_qual(le32_to_cpu(rssi)));
2548
2549 /* Get AP capabilities */
2550 if (info) {
2551 capability = le16_to_cpu(info->resp_ie.capa);
2552 } else {
2553 /* Set atleast ESS/IBSS capability */
2554 capability = (priv->infra_mode == NDIS_80211_INFRA_INFRA) ?
2555 WLAN_CAPABILITY_ESS : WLAN_CAPABILITY_IBSS;
2556 }
2557
2558 /* Get channel and beacon interval */
2559 len = sizeof(config);
2560 ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len);
2561 netdev_dbg(usbdev->net, "%s(): OID_802_11_CONFIGURATION -> %d\n",
2562 __func__, ret);
2563 if (ret >= 0) {
2564 beacon_interval = le16_to_cpu(config.beacon_period);
2565 channel = ieee80211_get_channel(priv->wdev.wiphy,
2566 KHZ_TO_MHZ(le32_to_cpu(config.ds_config)));
2567 if (!channel) {
2568 netdev_warn(usbdev->net, "%s(): could not get channel."
2569 "\n", __func__);
2570 return;
2571 }
2572 } else {
2573 netdev_warn(usbdev->net, "%s(): could not get configuration.\n",
2574 __func__);
2575 return;
2576 }
2577
2578 /* Get SSID, in case of error, use zero length SSID and ignore error. */
2579 len = sizeof(ssid);
2580 memset(&ssid, 0, sizeof(ssid));
2581 ret = rndis_query_oid(usbdev, OID_802_11_SSID, &ssid, &len);
2582 netdev_dbg(usbdev->net, "%s(): OID_802_11_SSID -> %d, len: %d, ssid: "
2583 "'%.32s'\n", __func__, ret,
2584 le32_to_cpu(ssid.length), ssid.essid);
2585
2586 if (le32_to_cpu(ssid.length) > 32)
2587 ssid.length = cpu_to_le32(32);
2588
2589 ie_buf[0] = WLAN_EID_SSID;
2590 ie_buf[1] = le32_to_cpu(ssid.length);
2591 memcpy(&ie_buf[2], ssid.essid, le32_to_cpu(ssid.length));
2592
2593 ie_len = le32_to_cpu(ssid.length) + 2;
2594
2595 /* no tsf */
2596 timestamp = 0;
2597
2598 netdev_dbg(usbdev->net, "%s(): channel:%d(freq), bssid:[%pM], tsf:%d, "
2599 "capa:%x, beacon int:%d, resp_ie(len:%d, essid:'%.32s'), "
2600 "signal:%d\n", __func__, (channel ? channel->center_freq : -1),
2601 bssid, (u32)timestamp, capability, beacon_interval, ie_len,
2602 ssid.essid, signal);
2603
2604 cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid,
2605 timestamp, capability, beacon_interval, ie_buf, ie_len,
2606 signal, GFP_KERNEL);
2607}
2608
2498/* 2609/*
2499 * workers, indication handlers, device poller 2610 * workers, indication handlers, device poller
2500 */ 2611 */
@@ -2507,6 +2618,7 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
2507 u8 *req_ie, *resp_ie; 2618 u8 *req_ie, *resp_ie;
2508 int ret, offset; 2619 int ret, offset;
2509 bool roamed = false; 2620 bool roamed = false;
2621 bool match_bss;
2510 2622
2511 if (priv->infra_mode == NDIS_80211_INFRA_INFRA && priv->connected) { 2623 if (priv->infra_mode == NDIS_80211_INFRA_INFRA && priv->connected) {
2512 /* received media connect indication while connected, either 2624 /* received media connect indication while connected, either
@@ -2558,6 +2670,13 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
2558 resp_ie_len = 2670 resp_ie_len =
2559 CONTROL_BUFFER_SIZE - offset; 2671 CONTROL_BUFFER_SIZE - offset;
2560 } 2672 }
2673 } else {
2674 /* Since rndis_wlan_craft_connected_bss() might use info
2675 * later and expects info to contain valid data if
2676 * non-null, free info and set NULL here.
2677 */
2678 kfree(info);
2679 info = NULL;
2561 } 2680 }
2562 } else if (WARN_ON(priv->infra_mode != NDIS_80211_INFRA_ADHOC)) 2681 } else if (WARN_ON(priv->infra_mode != NDIS_80211_INFRA_ADHOC))
2563 return; 2682 return;
@@ -2569,13 +2688,26 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
2569 netdev_dbg(usbdev->net, "link up work: [%pM]%s\n", 2688 netdev_dbg(usbdev->net, "link up work: [%pM]%s\n",
2570 bssid, roamed ? " roamed" : ""); 2689 bssid, roamed ? " roamed" : "");
2571 2690
2572 /* Internal bss list in device always contains at least the currently 2691 /* Internal bss list in device should contain at least the currently
2573 * connected bss and we can get it to cfg80211 with 2692 * connected bss and we can get it to cfg80211 with
2574 * rndis_check_bssid_list(). 2693 * rndis_check_bssid_list().
2575 * NOTE: This is true for Broadcom chip, but not mentioned in RNDIS 2694 *
2576 * spec. 2695 * NDIS spec says: "If the device is associated, but the associated
2696 * BSSID is not in its BSSID scan list, then the driver must add an
2697 * entry for the BSSID at the end of the data that it returns in
2698 * response to query of OID_802_11_BSSID_LIST."
2699 *
2700 * NOTE: Seems to be true for BCM4320b variant, but not BCM4320a.
2577 */ 2701 */
2578 rndis_check_bssid_list(usbdev); 2702 match_bss = false;
2703 rndis_check_bssid_list(usbdev, bssid, &match_bss);
2704
2705 if (!is_zero_ether_addr(bssid) && !match_bss) {
2706 /* Couldn't get bss from device, we need to manually craft bss
2707 * for cfg80211.
2708 */
2709 rndis_wlan_craft_connected_bss(usbdev, bssid, info);
2710 }
2579 2711
2580 if (priv->infra_mode == NDIS_80211_INFRA_INFRA) { 2712 if (priv->infra_mode == NDIS_80211_INFRA_INFRA) {
2581 if (!roamed) 2713 if (!roamed)
@@ -2934,8 +3066,21 @@ static void rndis_device_poller(struct work_struct *work)
2934 * also polls device with rndis_command() and catches for media link 3066 * also polls device with rndis_command() and catches for media link
2935 * indications. 3067 * indications.
2936 */ 3068 */
2937 if (!is_associated(usbdev)) 3069 if (!is_associated(usbdev)) {
3070 /* Workaround bad scanning in BCM4320a devices with active
3071 * background scanning when not associated.
3072 */
3073 if (priv->device_type == RNDIS_BCM4320A && priv->radio_on &&
3074 !priv->scan_request) {
3075 /* Get previous scan results */
3076 rndis_check_bssid_list(usbdev, NULL, NULL);
3077
3078 /* Initiate new scan */
3079 rndis_start_bssid_list_scan(usbdev);
3080 }
3081
2938 goto end; 3082 goto end;
3083 }
2939 3084
2940 len = sizeof(rssi); 3085 len = sizeof(rssi);
2941 ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len); 3086 ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len);
@@ -2992,10 +3137,12 @@ end:
2992/* 3137/*
2993 * driver/device initialization 3138 * driver/device initialization
2994 */ 3139 */
2995static void rndis_copy_module_params(struct usbnet *usbdev) 3140static void rndis_copy_module_params(struct usbnet *usbdev, int device_type)
2996{ 3141{
2997 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); 3142 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
2998 3143
3144 priv->device_type = device_type;
3145
2999 priv->param_country[0] = modparam_country[0]; 3146 priv->param_country[0] = modparam_country[0];
3000 priv->param_country[1] = modparam_country[1]; 3147 priv->param_country[1] = modparam_country[1];
3001 priv->param_country[2] = 0; 3148 priv->param_country[2] = 0;
@@ -3038,12 +3185,25 @@ static void rndis_copy_module_params(struct usbnet *usbdev)
3038 priv->param_workaround_interval = modparam_workaround_interval; 3185 priv->param_workaround_interval = modparam_workaround_interval;
3039} 3186}
3040 3187
3188static int unknown_early_init(struct usbnet *usbdev)
3189{
3190 /* copy module parameters for unknown so that iwconfig reports txpower
3191 * and workaround parameter is copied to private structure correctly.
3192 */
3193 rndis_copy_module_params(usbdev, RNDIS_UNKNOWN);
3194
3195 /* This is unknown device, so do not try set configuration parameters.
3196 */
3197
3198 return 0;
3199}
3200
3041static int bcm4320a_early_init(struct usbnet *usbdev) 3201static int bcm4320a_early_init(struct usbnet *usbdev)
3042{ 3202{
3043 /* copy module parameters for bcm4320a so that iwconfig reports txpower 3203 /* copy module parameters for bcm4320a so that iwconfig reports txpower
3044 * and workaround parameter is copied to private structure correctly. 3204 * and workaround parameter is copied to private structure correctly.
3045 */ 3205 */
3046 rndis_copy_module_params(usbdev); 3206 rndis_copy_module_params(usbdev, RNDIS_BCM4320A);
3047 3207
3048 /* bcm4320a doesn't handle configuration parameters well. Try 3208 /* bcm4320a doesn't handle configuration parameters well. Try
3049 * set any and you get partially zeroed mac and broken device. 3209 * set any and you get partially zeroed mac and broken device.
@@ -3057,7 +3217,7 @@ static int bcm4320b_early_init(struct usbnet *usbdev)
3057 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); 3217 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
3058 char buf[8]; 3218 char buf[8];
3059 3219
3060 rndis_copy_module_params(usbdev); 3220 rndis_copy_module_params(usbdev, RNDIS_BCM4320B);
3061 3221
3062 /* Early initialization settings, setting these won't have effect 3222 /* Early initialization settings, setting these won't have effect
3063 * if called after generic_rndis_bind(). 3223 * if called after generic_rndis_bind().
@@ -3320,7 +3480,7 @@ static const struct driver_info rndis_wlan_info = {
3320 .tx_fixup = rndis_tx_fixup, 3480 .tx_fixup = rndis_tx_fixup,
3321 .reset = rndis_wlan_reset, 3481 .reset = rndis_wlan_reset,
3322 .stop = rndis_wlan_stop, 3482 .stop = rndis_wlan_stop,
3323 .early_init = bcm4320a_early_init, 3483 .early_init = unknown_early_init,
3324 .indication = rndis_wlan_indication, 3484 .indication = rndis_wlan_indication,
3325}; 3485};
3326 3486