diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/net/wireless/rndis_wlan.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/net/wireless/rndis_wlan.c')
-rw-r--r-- | drivers/net/wireless/rndis_wlan.c | 420 |
1 files changed, 363 insertions, 57 deletions
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 719573bbbf81..29f938930667 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 | ||
@@ -156,6 +157,12 @@ MODULE_PARM_DESC(workaround_interval, | |||
156 | #define RNDIS_STATUS_ADAPTER_NOT_OPEN cpu_to_le32(0xc0010012) | 157 | #define RNDIS_STATUS_ADAPTER_NOT_OPEN cpu_to_le32(0xc0010012) |
157 | 158 | ||
158 | 159 | ||
160 | /* Known device types */ | ||
161 | #define RNDIS_UNKNOWN 0 | ||
162 | #define RNDIS_BCM4320A 1 | ||
163 | #define RNDIS_BCM4320B 2 | ||
164 | |||
165 | |||
159 | /* NDIS data structures. Taken from wpa_supplicant driver_ndis.c | 166 | /* NDIS data structures. Taken from wpa_supplicant driver_ndis.c |
160 | * slightly modified for datatype endianess, etc | 167 | * slightly modified for datatype endianess, etc |
161 | */ | 168 | */ |
@@ -233,6 +240,12 @@ enum ndis_80211_addwep_bits { | |||
233 | NDIS_80211_ADDWEP_TRANSMIT_KEY = cpu_to_le32(1 << 31) | 240 | NDIS_80211_ADDWEP_TRANSMIT_KEY = cpu_to_le32(1 << 31) |
234 | }; | 241 | }; |
235 | 242 | ||
243 | enum 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 | |||
236 | struct ndis_80211_auth_request { | 249 | struct ndis_80211_auth_request { |
237 | __le32 length; | 250 | __le32 length; |
238 | u8 bssid[6]; | 251 | u8 bssid[6]; |
@@ -472,12 +485,16 @@ struct rndis_wlan_private { | |||
472 | struct mutex command_lock; | 485 | struct mutex command_lock; |
473 | unsigned long work_pending; | 486 | unsigned long work_pending; |
474 | int last_qual; | 487 | int last_qual; |
488 | s32 cqm_rssi_thold; | ||
489 | u32 cqm_rssi_hyst; | ||
490 | int last_cqm_event_rssi; | ||
475 | 491 | ||
476 | struct ieee80211_supported_band band; | 492 | struct ieee80211_supported_band band; |
477 | struct ieee80211_channel channels[ARRAY_SIZE(rndis_channels)]; | 493 | struct ieee80211_channel channels[ARRAY_SIZE(rndis_channels)]; |
478 | struct ieee80211_rate rates[ARRAY_SIZE(rndis_rates)]; | 494 | struct ieee80211_rate rates[ARRAY_SIZE(rndis_rates)]; |
479 | u32 cipher_suites[ARRAY_SIZE(rndis_cipher_suites)]; | 495 | u32 cipher_suites[ARRAY_SIZE(rndis_cipher_suites)]; |
480 | 496 | ||
497 | int device_type; | ||
481 | int caps; | 498 | int caps; |
482 | int multicast_size; | 499 | int multicast_size; |
483 | 500 | ||
@@ -493,10 +510,10 @@ struct rndis_wlan_private { | |||
493 | 510 | ||
494 | /* hardware state */ | 511 | /* hardware state */ |
495 | bool radio_on; | 512 | bool radio_on; |
513 | int power_mode; | ||
496 | int infra_mode; | 514 | int infra_mode; |
497 | bool connected; | 515 | bool connected; |
498 | u8 bssid[ETH_ALEN]; | 516 | u8 bssid[ETH_ALEN]; |
499 | struct ndis_80211_ssid essid; | ||
500 | __le32 current_command_oid; | 517 | __le32 current_command_oid; |
501 | 518 | ||
502 | /* encryption stuff */ | 519 | /* encryption stuff */ |
@@ -540,14 +557,14 @@ static int rndis_set_channel(struct wiphy *wiphy, struct net_device *dev, | |||
540 | struct ieee80211_channel *chan, enum nl80211_channel_type channel_type); | 557 | struct ieee80211_channel *chan, enum nl80211_channel_type channel_type); |
541 | 558 | ||
542 | static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, | 559 | static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, |
543 | u8 key_index, const u8 *mac_addr, | 560 | u8 key_index, bool pairwise, const u8 *mac_addr, |
544 | struct key_params *params); | 561 | struct key_params *params); |
545 | 562 | ||
546 | static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev, | 563 | static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev, |
547 | u8 key_index, const u8 *mac_addr); | 564 | u8 key_index, bool pairwise, const u8 *mac_addr); |
548 | 565 | ||
549 | static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, | 566 | static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, |
550 | u8 key_index); | 567 | u8 key_index, bool unicast, bool multicast); |
551 | 568 | ||
552 | static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev, | 569 | static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev, |
553 | u8 *mac, struct station_info *sinfo); | 570 | u8 *mac, struct station_info *sinfo); |
@@ -563,7 +580,14 @@ static int rndis_del_pmksa(struct wiphy *wiphy, struct net_device *netdev, | |||
563 | 580 | ||
564 | static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev); | 581 | static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev); |
565 | 582 | ||
566 | static struct cfg80211_ops rndis_config_ops = { | 583 | static int rndis_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, |
584 | bool enabled, int timeout); | ||
585 | |||
586 | static int rndis_set_cqm_rssi_config(struct wiphy *wiphy, | ||
587 | struct net_device *dev, | ||
588 | s32 rssi_thold, u32 rssi_hyst); | ||
589 | |||
590 | static const struct cfg80211_ops rndis_config_ops = { | ||
567 | .change_virtual_intf = rndis_change_virtual_intf, | 591 | .change_virtual_intf = rndis_change_virtual_intf, |
568 | .scan = rndis_scan, | 592 | .scan = rndis_scan, |
569 | .set_wiphy_params = rndis_set_wiphy_params, | 593 | .set_wiphy_params = rndis_set_wiphy_params, |
@@ -582,6 +606,8 @@ static struct cfg80211_ops rndis_config_ops = { | |||
582 | .set_pmksa = rndis_set_pmksa, | 606 | .set_pmksa = rndis_set_pmksa, |
583 | .del_pmksa = rndis_del_pmksa, | 607 | .del_pmksa = rndis_del_pmksa, |
584 | .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, | ||
585 | }; | 611 | }; |
586 | 612 | ||
587 | static void *rndis_wiphy_privid = &rndis_wiphy_privid; | 613 | static void *rndis_wiphy_privid = &rndis_wiphy_privid; |
@@ -680,6 +706,7 @@ static const char *oid_to_string(__le32 oid) | |||
680 | OID_STR(OID_802_11_ADD_KEY); | 706 | OID_STR(OID_802_11_ADD_KEY); |
681 | OID_STR(OID_802_11_REMOVE_KEY); | 707 | OID_STR(OID_802_11_REMOVE_KEY); |
682 | OID_STR(OID_802_11_ASSOCIATION_INFORMATION); | 708 | OID_STR(OID_802_11_ASSOCIATION_INFORMATION); |
709 | OID_STR(OID_802_11_CAPABILITY); | ||
683 | OID_STR(OID_802_11_PMKID); | 710 | OID_STR(OID_802_11_PMKID); |
684 | OID_STR(OID_802_11_NETWORK_TYPES_SUPPORTED); | 711 | OID_STR(OID_802_11_NETWORK_TYPES_SUPPORTED); |
685 | OID_STR(OID_802_11_NETWORK_TYPE_IN_USE); | 712 | OID_STR(OID_802_11_NETWORK_TYPE_IN_USE); |
@@ -690,6 +717,7 @@ static const char *oid_to_string(__le32 oid) | |||
690 | OID_STR(OID_802_11_RTS_THRESHOLD); | 717 | OID_STR(OID_802_11_RTS_THRESHOLD); |
691 | OID_STR(OID_802_11_SUPPORTED_RATES); | 718 | OID_STR(OID_802_11_SUPPORTED_RATES); |
692 | OID_STR(OID_802_11_CONFIGURATION); | 719 | OID_STR(OID_802_11_CONFIGURATION); |
720 | OID_STR(OID_802_11_POWER_MODE); | ||
693 | OID_STR(OID_802_11_BSSID_LIST); | 721 | OID_STR(OID_802_11_BSSID_LIST); |
694 | #undef OID_STR | 722 | #undef OID_STR |
695 | } | 723 | } |
@@ -810,7 +838,8 @@ exit_unlock: | |||
810 | return ret; | 838 | return ret; |
811 | } | 839 | } |
812 | 840 | ||
813 | static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len) | 841 | static int rndis_set_oid(struct usbnet *dev, __le32 oid, const void *data, |
842 | int len) | ||
814 | { | 843 | { |
815 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(dev); | 844 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(dev); |
816 | union { | 845 | union { |
@@ -994,7 +1023,18 @@ static int level_to_qual(int level) | |||
994 | */ | 1023 | */ |
995 | static int set_infra_mode(struct usbnet *usbdev, int mode); | 1024 | static int set_infra_mode(struct usbnet *usbdev, int mode); |
996 | static void restore_keys(struct usbnet *usbdev); | 1025 | static void restore_keys(struct usbnet *usbdev); |
997 | static int rndis_check_bssid_list(struct usbnet *usbdev); | 1026 | static int rndis_check_bssid_list(struct usbnet *usbdev, u8 *match_bssid, |
1027 | bool *matched); | ||
1028 | |||
1029 | static int rndis_start_bssid_list_scan(struct usbnet *usbdev) | ||
1030 | { | ||
1031 | __le32 tmp; | ||
1032 | |||
1033 | /* Note: OID_802_11_BSSID_LIST_SCAN clears internal BSS list. */ | ||
1034 | tmp = cpu_to_le32(1); | ||
1035 | return rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp, | ||
1036 | sizeof(tmp)); | ||
1037 | } | ||
998 | 1038 | ||
999 | static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) | 1039 | static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) |
1000 | { | 1040 | { |
@@ -1007,7 +1047,6 @@ static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) | |||
1007 | return ret; | 1047 | return ret; |
1008 | } | 1048 | } |
1009 | if (ret == 0) { | 1049 | if (ret == 0) { |
1010 | memcpy(&priv->essid, ssid, sizeof(priv->essid)); | ||
1011 | priv->radio_on = true; | 1050 | priv->radio_on = true; |
1012 | netdev_dbg(usbdev->net, "%s(): radio_on = true\n", __func__); | 1051 | netdev_dbg(usbdev->net, "%s(): radio_on = true\n", __func__); |
1013 | } | 1052 | } |
@@ -1015,7 +1054,7 @@ static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) | |||
1015 | return ret; | 1054 | return ret; |
1016 | } | 1055 | } |
1017 | 1056 | ||
1018 | static int set_bssid(struct usbnet *usbdev, u8 bssid[ETH_ALEN]) | 1057 | static int set_bssid(struct usbnet *usbdev, const u8 *bssid) |
1019 | { | 1058 | { |
1020 | int ret; | 1059 | int ret; |
1021 | 1060 | ||
@@ -1031,7 +1070,9 @@ static int set_bssid(struct usbnet *usbdev, u8 bssid[ETH_ALEN]) | |||
1031 | 1070 | ||
1032 | static int clear_bssid(struct usbnet *usbdev) | 1071 | static int clear_bssid(struct usbnet *usbdev) |
1033 | { | 1072 | { |
1034 | u8 broadcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | 1073 | static const u8 broadcast_mac[ETH_ALEN] = { |
1074 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | ||
1075 | }; | ||
1035 | 1076 | ||
1036 | return set_bssid(usbdev, broadcast_mac); | 1077 | return set_bssid(usbdev, broadcast_mac); |
1037 | } | 1078 | } |
@@ -1904,14 +1945,14 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev, | |||
1904 | struct usbnet *usbdev = netdev_priv(dev); | 1945 | struct usbnet *usbdev = netdev_priv(dev); |
1905 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 1946 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
1906 | int ret; | 1947 | int ret; |
1907 | __le32 tmp; | 1948 | int delay = SCAN_DELAY_JIFFIES; |
1908 | 1949 | ||
1909 | netdev_dbg(usbdev->net, "cfg80211.scan\n"); | 1950 | netdev_dbg(usbdev->net, "cfg80211.scan\n"); |
1910 | 1951 | ||
1911 | /* Get current bssid list from device before new scan, as new scan | 1952 | /* Get current bssid list from device before new scan, as new scan |
1912 | * clears internal bssid list. | 1953 | * clears internal bssid list. |
1913 | */ | 1954 | */ |
1914 | rndis_check_bssid_list(usbdev); | 1955 | rndis_check_bssid_list(usbdev, NULL, NULL); |
1915 | 1956 | ||
1916 | if (!request) | 1957 | if (!request) |
1917 | return -EINVAL; | 1958 | return -EINVAL; |
@@ -1921,13 +1962,13 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev, | |||
1921 | 1962 | ||
1922 | priv->scan_request = request; | 1963 | priv->scan_request = request; |
1923 | 1964 | ||
1924 | tmp = cpu_to_le32(1); | 1965 | 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) { | 1966 | if (ret == 0) { |
1967 | if (priv->device_type == RNDIS_BCM4320A) | ||
1968 | delay = HZ; | ||
1969 | |||
1928 | /* Wait before retrieving scan results from device */ | 1970 | /* Wait before retrieving scan results from device */ |
1929 | queue_delayed_work(priv->workqueue, &priv->scan_work, | 1971 | queue_delayed_work(priv->workqueue, &priv->scan_work, delay); |
1930 | SCAN_DELAY_JIFFIES); | ||
1931 | } | 1972 | } |
1932 | 1973 | ||
1933 | return ret; | 1974 | return ret; |
@@ -1946,8 +1987,8 @@ static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev, | |||
1946 | int ie_len, bssid_len; | 1987 | int ie_len, bssid_len; |
1947 | u8 *ie; | 1988 | u8 *ie; |
1948 | 1989 | ||
1949 | netdev_dbg(usbdev->net, " found bssid: '%.32s' [%pM]\n", | 1990 | netdev_dbg(usbdev->net, " found bssid: '%.32s' [%pM], len: %d\n", |
1950 | bssid->ssid.essid, bssid->mac); | 1991 | bssid->ssid.essid, bssid->mac, le32_to_cpu(bssid->length)); |
1951 | 1992 | ||
1952 | /* parse bssid structure */ | 1993 | /* parse bssid structure */ |
1953 | bssid_len = le32_to_cpu(bssid->length); | 1994 | bssid_len = le32_to_cpu(bssid->length); |
@@ -1981,49 +2022,98 @@ static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev, | |||
1981 | GFP_KERNEL); | 2022 | GFP_KERNEL); |
1982 | } | 2023 | } |
1983 | 2024 | ||
1984 | static int rndis_check_bssid_list(struct usbnet *usbdev) | 2025 | static 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 | |||
2044 | static 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 | |||
2058 | static int rndis_check_bssid_list(struct usbnet *usbdev, u8 *match_bssid, | ||
2059 | bool *matched) | ||
1985 | { | 2060 | { |
1986 | void *buf = NULL; | 2061 | void *buf = NULL; |
1987 | struct ndis_80211_bssid_list_ex *bssid_list; | 2062 | struct ndis_80211_bssid_list_ex *bssid_list; |
1988 | struct ndis_80211_bssid_ex *bssid; | 2063 | struct ndis_80211_bssid_ex *bssid; |
1989 | int ret = -EINVAL, len, count, bssid_len; | 2064 | int ret = -EINVAL, len, count, bssid_len, real_count, new_len; |
1990 | bool resized = false; | ||
1991 | 2065 | ||
1992 | netdev_dbg(usbdev->net, "check_bssid_list\n"); | 2066 | netdev_dbg(usbdev->net, "%s()\n", __func__); |
1993 | 2067 | ||
1994 | len = CONTROL_BUFFER_SIZE; | 2068 | len = CONTROL_BUFFER_SIZE; |
1995 | resize_buf: | 2069 | resize_buf: |
1996 | buf = kmalloc(len, GFP_KERNEL); | 2070 | buf = kzalloc(len, GFP_KERNEL); |
1997 | if (!buf) { | 2071 | if (!buf) { |
1998 | ret = -ENOMEM; | 2072 | ret = -ENOMEM; |
1999 | goto out; | 2073 | goto out; |
2000 | } | 2074 | } |
2001 | 2075 | ||
2002 | ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len); | 2076 | /* BSSID-list might have got bigger last time we checked, keep |
2003 | 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)) | ||
2004 | goto out; | 2082 | goto out; |
2005 | 2083 | ||
2006 | if (!resized && len > CONTROL_BUFFER_SIZE) { | 2084 | if (new_len > len) { |
2007 | resized = true; | 2085 | len = new_len; |
2008 | kfree(buf); | 2086 | kfree(buf); |
2009 | goto resize_buf; | 2087 | goto resize_buf; |
2010 | } | 2088 | } |
2011 | 2089 | ||
2090 | len = new_len; | ||
2091 | |||
2012 | bssid_list = buf; | 2092 | bssid_list = buf; |
2013 | bssid = bssid_list->bssid; | ||
2014 | bssid_len = le32_to_cpu(bssid->length); | ||
2015 | count = le32_to_cpu(bssid_list->num_items); | 2093 | count = le32_to_cpu(bssid_list->num_items); |
2016 | netdev_dbg(usbdev->net, "check_bssid_list: %d BSSIDs found (buflen: %d)\n", | 2094 | real_count = 0; |
2017 | count, len); | 2095 | netdev_dbg(usbdev->net, "%s(): buflen: %d\n", __func__, len); |
2018 | 2096 | ||
2019 | while (count && ((void *)bssid + bssid_len) <= (buf + len)) { | 2097 | bssid_len = 0; |
2020 | rndis_bss_info_update(usbdev, bssid); | 2098 | bssid = next_bssid_list_item(bssid_list->bssid, &bssid_len, buf, len); |
2021 | 2099 | ||
2022 | bssid = (void *)bssid + bssid_len; | 2100 | /* Device returns incorrect 'num_items'. Workaround by ignoring the |
2023 | bssid_len = le32_to_cpu(bssid->length); | 2101 | * received 'num_items' and walking through full bssid buffer instead. |
2024 | count--; | 2102 | */ |
2103 | while (check_bssid_list_item(bssid, bssid_len, buf, len)) { | ||
2104 | if (rndis_bss_info_update(usbdev, bssid) && match_bssid && | ||
2105 | matched) { | ||
2106 | if (compare_ether_addr(bssid->mac, match_bssid)) | ||
2107 | *matched = true; | ||
2108 | } | ||
2109 | |||
2110 | real_count++; | ||
2111 | bssid = next_bssid_list_item(bssid, &bssid_len, buf, len); | ||
2025 | } | 2112 | } |
2026 | 2113 | ||
2114 | netdev_dbg(usbdev->net, "%s(): num_items from device: %d, really found:" | ||
2115 | " %d\n", __func__, count, real_count); | ||
2116 | |||
2027 | out: | 2117 | out: |
2028 | kfree(buf); | 2118 | kfree(buf); |
2029 | return ret; | 2119 | return ret; |
@@ -2041,7 +2131,7 @@ static void rndis_get_scan_results(struct work_struct *work) | |||
2041 | if (!priv->scan_request) | 2131 | if (!priv->scan_request) |
2042 | return; | 2132 | return; |
2043 | 2133 | ||
2044 | ret = rndis_check_bssid_list(usbdev); | 2134 | ret = rndis_check_bssid_list(usbdev, NULL, NULL); |
2045 | 2135 | ||
2046 | cfg80211_scan_done(priv->scan_request, ret < 0); | 2136 | cfg80211_scan_done(priv->scan_request, ret < 0); |
2047 | 2137 | ||
@@ -2308,8 +2398,8 @@ static int rndis_set_channel(struct wiphy *wiphy, struct net_device *netdev, | |||
2308 | } | 2398 | } |
2309 | 2399 | ||
2310 | static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, | 2400 | static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, |
2311 | u8 key_index, const u8 *mac_addr, | 2401 | u8 key_index, bool pairwise, const u8 *mac_addr, |
2312 | struct key_params *params) | 2402 | struct key_params *params) |
2313 | { | 2403 | { |
2314 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | 2404 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); |
2315 | struct usbnet *usbdev = priv->usbdev; | 2405 | struct usbnet *usbdev = priv->usbdev; |
@@ -2344,7 +2434,7 @@ static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, | |||
2344 | } | 2434 | } |
2345 | 2435 | ||
2346 | static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev, | 2436 | static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev, |
2347 | u8 key_index, const u8 *mac_addr) | 2437 | u8 key_index, bool pairwise, const u8 *mac_addr) |
2348 | { | 2438 | { |
2349 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | 2439 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); |
2350 | struct usbnet *usbdev = priv->usbdev; | 2440 | struct usbnet *usbdev = priv->usbdev; |
@@ -2355,7 +2445,7 @@ static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev, | |||
2355 | } | 2445 | } |
2356 | 2446 | ||
2357 | static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, | 2447 | static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, |
2358 | u8 key_index) | 2448 | u8 key_index, bool unicast, bool multicast) |
2359 | { | 2449 | { |
2360 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | 2450 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); |
2361 | struct usbnet *usbdev = priv->usbdev; | 2451 | struct usbnet *usbdev = priv->usbdev; |
@@ -2365,6 +2455,9 @@ static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, | |||
2365 | 2455 | ||
2366 | priv->encr_tx_key_index = key_index; | 2456 | priv->encr_tx_key_index = key_index; |
2367 | 2457 | ||
2458 | if (is_wpa_key(priv, key_index)) | ||
2459 | return 0; | ||
2460 | |||
2368 | key = priv->encr_keys[key_index]; | 2461 | key = priv->encr_keys[key_index]; |
2369 | 2462 | ||
2370 | return add_wep_key(usbdev, key.material, key.len, key_index); | 2463 | return add_wep_key(usbdev, key.material, key.len, key_index); |
@@ -2495,6 +2588,139 @@ 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)); | 2588 | return rndis_set_oid(usbdev, OID_802_11_PMKID, &pmkid, sizeof(pmkid)); |
2496 | } | 2589 | } |
2497 | 2590 | ||
2591 | static 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 | if (priv->device_type != RNDIS_BCM4320B) | ||
2601 | return -ENOTSUPP; | ||
2602 | |||
2603 | netdev_dbg(usbdev->net, "%s(): %s, %d\n", __func__, | ||
2604 | enabled ? "enabled" : "disabled", | ||
2605 | timeout); | ||
2606 | |||
2607 | if (enabled) | ||
2608 | power_mode = NDIS_80211_POWER_MODE_FAST_PSP; | ||
2609 | else | ||
2610 | power_mode = NDIS_80211_POWER_MODE_CAM; | ||
2611 | |||
2612 | if (power_mode == priv->power_mode) | ||
2613 | return 0; | ||
2614 | |||
2615 | priv->power_mode = power_mode; | ||
2616 | |||
2617 | mode = cpu_to_le32(power_mode); | ||
2618 | ret = rndis_set_oid(usbdev, OID_802_11_POWER_MODE, &mode, sizeof(mode)); | ||
2619 | |||
2620 | netdev_dbg(usbdev->net, "%s(): OID_802_11_POWER_MODE -> %d\n", | ||
2621 | __func__, ret); | ||
2622 | |||
2623 | return ret; | ||
2624 | } | ||
2625 | |||
2626 | static int rndis_set_cqm_rssi_config(struct wiphy *wiphy, | ||
2627 | struct net_device *dev, | ||
2628 | s32 rssi_thold, u32 rssi_hyst) | ||
2629 | { | ||
2630 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | ||
2631 | |||
2632 | priv->cqm_rssi_thold = rssi_thold; | ||
2633 | priv->cqm_rssi_hyst = rssi_hyst; | ||
2634 | priv->last_cqm_event_rssi = 0; | ||
2635 | |||
2636 | return 0; | ||
2637 | } | ||
2638 | |||
2639 | static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid, | ||
2640 | struct ndis_80211_assoc_info *info) | ||
2641 | { | ||
2642 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | ||
2643 | struct ieee80211_channel *channel; | ||
2644 | struct ndis_80211_conf config; | ||
2645 | struct ndis_80211_ssid ssid; | ||
2646 | s32 signal; | ||
2647 | u64 timestamp; | ||
2648 | u16 capability; | ||
2649 | u16 beacon_interval; | ||
2650 | __le32 rssi; | ||
2651 | u8 ie_buf[34]; | ||
2652 | int len, ret, ie_len; | ||
2653 | |||
2654 | /* Get signal quality, in case of error use rssi=0 and ignore error. */ | ||
2655 | len = sizeof(rssi); | ||
2656 | rssi = 0; | ||
2657 | ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len); | ||
2658 | signal = level_to_qual(le32_to_cpu(rssi)); | ||
2659 | |||
2660 | netdev_dbg(usbdev->net, "%s(): OID_802_11_RSSI -> %d, " | ||
2661 | "rssi:%d, qual: %d\n", __func__, ret, le32_to_cpu(rssi), | ||
2662 | level_to_qual(le32_to_cpu(rssi))); | ||
2663 | |||
2664 | /* Get AP capabilities */ | ||
2665 | if (info) { | ||
2666 | capability = le16_to_cpu(info->resp_ie.capa); | ||
2667 | } else { | ||
2668 | /* Set atleast ESS/IBSS capability */ | ||
2669 | capability = (priv->infra_mode == NDIS_80211_INFRA_INFRA) ? | ||
2670 | WLAN_CAPABILITY_ESS : WLAN_CAPABILITY_IBSS; | ||
2671 | } | ||
2672 | |||
2673 | /* Get channel and beacon interval */ | ||
2674 | len = sizeof(config); | ||
2675 | ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len); | ||
2676 | netdev_dbg(usbdev->net, "%s(): OID_802_11_CONFIGURATION -> %d\n", | ||
2677 | __func__, ret); | ||
2678 | if (ret >= 0) { | ||
2679 | beacon_interval = le16_to_cpu(config.beacon_period); | ||
2680 | channel = ieee80211_get_channel(priv->wdev.wiphy, | ||
2681 | KHZ_TO_MHZ(le32_to_cpu(config.ds_config))); | ||
2682 | if (!channel) { | ||
2683 | netdev_warn(usbdev->net, "%s(): could not get channel." | ||
2684 | "\n", __func__); | ||
2685 | return; | ||
2686 | } | ||
2687 | } else { | ||
2688 | netdev_warn(usbdev->net, "%s(): could not get configuration.\n", | ||
2689 | __func__); | ||
2690 | return; | ||
2691 | } | ||
2692 | |||
2693 | /* Get SSID, in case of error, use zero length SSID and ignore error. */ | ||
2694 | len = sizeof(ssid); | ||
2695 | memset(&ssid, 0, sizeof(ssid)); | ||
2696 | ret = rndis_query_oid(usbdev, OID_802_11_SSID, &ssid, &len); | ||
2697 | netdev_dbg(usbdev->net, "%s(): OID_802_11_SSID -> %d, len: %d, ssid: " | ||
2698 | "'%.32s'\n", __func__, ret, | ||
2699 | le32_to_cpu(ssid.length), ssid.essid); | ||
2700 | |||
2701 | if (le32_to_cpu(ssid.length) > 32) | ||
2702 | ssid.length = cpu_to_le32(32); | ||
2703 | |||
2704 | ie_buf[0] = WLAN_EID_SSID; | ||
2705 | ie_buf[1] = le32_to_cpu(ssid.length); | ||
2706 | memcpy(&ie_buf[2], ssid.essid, le32_to_cpu(ssid.length)); | ||
2707 | |||
2708 | ie_len = le32_to_cpu(ssid.length) + 2; | ||
2709 | |||
2710 | /* no tsf */ | ||
2711 | timestamp = 0; | ||
2712 | |||
2713 | netdev_dbg(usbdev->net, "%s(): channel:%d(freq), bssid:[%pM], tsf:%d, " | ||
2714 | "capa:%x, beacon int:%d, resp_ie(len:%d, essid:'%.32s'), " | ||
2715 | "signal:%d\n", __func__, (channel ? channel->center_freq : -1), | ||
2716 | bssid, (u32)timestamp, capability, beacon_interval, ie_len, | ||
2717 | ssid.essid, signal); | ||
2718 | |||
2719 | cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid, | ||
2720 | timestamp, capability, beacon_interval, ie_buf, ie_len, | ||
2721 | signal, GFP_KERNEL); | ||
2722 | } | ||
2723 | |||
2498 | /* | 2724 | /* |
2499 | * workers, indication handlers, device poller | 2725 | * workers, indication handlers, device poller |
2500 | */ | 2726 | */ |
@@ -2507,6 +2733,7 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) | |||
2507 | u8 *req_ie, *resp_ie; | 2733 | u8 *req_ie, *resp_ie; |
2508 | int ret, offset; | 2734 | int ret, offset; |
2509 | bool roamed = false; | 2735 | bool roamed = false; |
2736 | bool match_bss; | ||
2510 | 2737 | ||
2511 | if (priv->infra_mode == NDIS_80211_INFRA_INFRA && priv->connected) { | 2738 | if (priv->infra_mode == NDIS_80211_INFRA_INFRA && priv->connected) { |
2512 | /* received media connect indication while connected, either | 2739 | /* received media connect indication while connected, either |
@@ -2558,6 +2785,13 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) | |||
2558 | resp_ie_len = | 2785 | resp_ie_len = |
2559 | CONTROL_BUFFER_SIZE - offset; | 2786 | CONTROL_BUFFER_SIZE - offset; |
2560 | } | 2787 | } |
2788 | } else { | ||
2789 | /* Since rndis_wlan_craft_connected_bss() might use info | ||
2790 | * later and expects info to contain valid data if | ||
2791 | * non-null, free info and set NULL here. | ||
2792 | */ | ||
2793 | kfree(info); | ||
2794 | info = NULL; | ||
2561 | } | 2795 | } |
2562 | } else if (WARN_ON(priv->infra_mode != NDIS_80211_INFRA_ADHOC)) | 2796 | } else if (WARN_ON(priv->infra_mode != NDIS_80211_INFRA_ADHOC)) |
2563 | return; | 2797 | return; |
@@ -2569,13 +2803,26 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) | |||
2569 | netdev_dbg(usbdev->net, "link up work: [%pM]%s\n", | 2803 | netdev_dbg(usbdev->net, "link up work: [%pM]%s\n", |
2570 | bssid, roamed ? " roamed" : ""); | 2804 | bssid, roamed ? " roamed" : ""); |
2571 | 2805 | ||
2572 | /* Internal bss list in device always contains at least the currently | 2806 | /* Internal bss list in device should contain at least the currently |
2573 | * connected bss and we can get it to cfg80211 with | 2807 | * connected bss and we can get it to cfg80211 with |
2574 | * rndis_check_bssid_list(). | 2808 | * rndis_check_bssid_list(). |
2575 | * NOTE: This is true for Broadcom chip, but not mentioned in RNDIS | 2809 | * |
2576 | * spec. | 2810 | * NDIS spec says: "If the device is associated, but the associated |
2811 | * BSSID is not in its BSSID scan list, then the driver must add an | ||
2812 | * entry for the BSSID at the end of the data that it returns in | ||
2813 | * response to query of OID_802_11_BSSID_LIST." | ||
2814 | * | ||
2815 | * NOTE: Seems to be true for BCM4320b variant, but not BCM4320a. | ||
2577 | */ | 2816 | */ |
2578 | rndis_check_bssid_list(usbdev); | 2817 | match_bss = false; |
2818 | rndis_check_bssid_list(usbdev, bssid, &match_bss); | ||
2819 | |||
2820 | if (!is_zero_ether_addr(bssid) && !match_bss) { | ||
2821 | /* Couldn't get bss from device, we need to manually craft bss | ||
2822 | * for cfg80211. | ||
2823 | */ | ||
2824 | rndis_wlan_craft_connected_bss(usbdev, bssid, info); | ||
2825 | } | ||
2579 | 2826 | ||
2580 | if (priv->infra_mode == NDIS_80211_INFRA_INFRA) { | 2827 | if (priv->infra_mode == NDIS_80211_INFRA_INFRA) { |
2581 | if (!roamed) | 2828 | if (!roamed) |
@@ -2583,7 +2830,8 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) | |||
2583 | req_ie_len, resp_ie, | 2830 | req_ie_len, resp_ie, |
2584 | resp_ie_len, 0, GFP_KERNEL); | 2831 | resp_ie_len, 0, GFP_KERNEL); |
2585 | else | 2832 | else |
2586 | cfg80211_roamed(usbdev->net, bssid, req_ie, req_ie_len, | 2833 | cfg80211_roamed(usbdev->net, NULL, bssid, |
2834 | req_ie, req_ie_len, | ||
2587 | resp_ie, resp_ie_len, GFP_KERNEL); | 2835 | resp_ie, resp_ie_len, GFP_KERNEL); |
2588 | } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) | 2836 | } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) |
2589 | cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); | 2837 | cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); |
@@ -2918,6 +3166,32 @@ static int rndis_wlan_get_caps(struct usbnet *usbdev, struct wiphy *wiphy) | |||
2918 | return retval; | 3166 | return retval; |
2919 | } | 3167 | } |
2920 | 3168 | ||
3169 | static void rndis_do_cqm(struct usbnet *usbdev, s32 rssi) | ||
3170 | { | ||
3171 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | ||
3172 | enum nl80211_cqm_rssi_threshold_event event; | ||
3173 | int thold, hyst, last_event; | ||
3174 | |||
3175 | if (priv->cqm_rssi_thold >= 0 || rssi >= 0) | ||
3176 | return; | ||
3177 | if (priv->infra_mode != NDIS_80211_INFRA_INFRA) | ||
3178 | return; | ||
3179 | |||
3180 | last_event = priv->last_cqm_event_rssi; | ||
3181 | thold = priv->cqm_rssi_thold; | ||
3182 | hyst = priv->cqm_rssi_hyst; | ||
3183 | |||
3184 | if (rssi < thold && (last_event == 0 || rssi < last_event - hyst)) | ||
3185 | event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW; | ||
3186 | else if (rssi > thold && (last_event == 0 || rssi > last_event + hyst)) | ||
3187 | event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; | ||
3188 | else | ||
3189 | return; | ||
3190 | |||
3191 | priv->last_cqm_event_rssi = rssi; | ||
3192 | cfg80211_cqm_rssi_notify(usbdev->net, event, GFP_KERNEL); | ||
3193 | } | ||
3194 | |||
2921 | #define DEVICE_POLLER_JIFFIES (HZ) | 3195 | #define DEVICE_POLLER_JIFFIES (HZ) |
2922 | static void rndis_device_poller(struct work_struct *work) | 3196 | static void rndis_device_poller(struct work_struct *work) |
2923 | { | 3197 | { |
@@ -2934,13 +3208,28 @@ static void rndis_device_poller(struct work_struct *work) | |||
2934 | * also polls device with rndis_command() and catches for media link | 3208 | * also polls device with rndis_command() and catches for media link |
2935 | * indications. | 3209 | * indications. |
2936 | */ | 3210 | */ |
2937 | if (!is_associated(usbdev)) | 3211 | if (!is_associated(usbdev)) { |
3212 | /* Workaround bad scanning in BCM4320a devices with active | ||
3213 | * background scanning when not associated. | ||
3214 | */ | ||
3215 | if (priv->device_type == RNDIS_BCM4320A && priv->radio_on && | ||
3216 | !priv->scan_request) { | ||
3217 | /* Get previous scan results */ | ||
3218 | rndis_check_bssid_list(usbdev, NULL, NULL); | ||
3219 | |||
3220 | /* Initiate new scan */ | ||
3221 | rndis_start_bssid_list_scan(usbdev); | ||
3222 | } | ||
3223 | |||
2938 | goto end; | 3224 | goto end; |
3225 | } | ||
2939 | 3226 | ||
2940 | len = sizeof(rssi); | 3227 | len = sizeof(rssi); |
2941 | ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len); | 3228 | ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len); |
2942 | if (ret == 0) | 3229 | if (ret == 0) { |
2943 | priv->last_qual = level_to_qual(le32_to_cpu(rssi)); | 3230 | priv->last_qual = level_to_qual(le32_to_cpu(rssi)); |
3231 | rndis_do_cqm(usbdev, le32_to_cpu(rssi)); | ||
3232 | } | ||
2944 | 3233 | ||
2945 | netdev_dbg(usbdev->net, "dev-poller: OID_802_11_RSSI -> %d, rssi:%d, qual: %d\n", | 3234 | netdev_dbg(usbdev->net, "dev-poller: OID_802_11_RSSI -> %d, rssi:%d, qual: %d\n", |
2946 | ret, le32_to_cpu(rssi), level_to_qual(le32_to_cpu(rssi))); | 3235 | ret, le32_to_cpu(rssi), level_to_qual(le32_to_cpu(rssi))); |
@@ -2992,10 +3281,12 @@ end: | |||
2992 | /* | 3281 | /* |
2993 | * driver/device initialization | 3282 | * driver/device initialization |
2994 | */ | 3283 | */ |
2995 | static void rndis_copy_module_params(struct usbnet *usbdev) | 3284 | static void rndis_copy_module_params(struct usbnet *usbdev, int device_type) |
2996 | { | 3285 | { |
2997 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 3286 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
2998 | 3287 | ||
3288 | priv->device_type = device_type; | ||
3289 | |||
2999 | priv->param_country[0] = modparam_country[0]; | 3290 | priv->param_country[0] = modparam_country[0]; |
3000 | priv->param_country[1] = modparam_country[1]; | 3291 | priv->param_country[1] = modparam_country[1]; |
3001 | priv->param_country[2] = 0; | 3292 | priv->param_country[2] = 0; |
@@ -3038,12 +3329,25 @@ static void rndis_copy_module_params(struct usbnet *usbdev) | |||
3038 | priv->param_workaround_interval = modparam_workaround_interval; | 3329 | priv->param_workaround_interval = modparam_workaround_interval; |
3039 | } | 3330 | } |
3040 | 3331 | ||
3332 | static int unknown_early_init(struct usbnet *usbdev) | ||
3333 | { | ||
3334 | /* copy module parameters for unknown so that iwconfig reports txpower | ||
3335 | * and workaround parameter is copied to private structure correctly. | ||
3336 | */ | ||
3337 | rndis_copy_module_params(usbdev, RNDIS_UNKNOWN); | ||
3338 | |||
3339 | /* This is unknown device, so do not try set configuration parameters. | ||
3340 | */ | ||
3341 | |||
3342 | return 0; | ||
3343 | } | ||
3344 | |||
3041 | static int bcm4320a_early_init(struct usbnet *usbdev) | 3345 | static int bcm4320a_early_init(struct usbnet *usbdev) |
3042 | { | 3346 | { |
3043 | /* copy module parameters for bcm4320a so that iwconfig reports txpower | 3347 | /* copy module parameters for bcm4320a so that iwconfig reports txpower |
3044 | * and workaround parameter is copied to private structure correctly. | 3348 | * and workaround parameter is copied to private structure correctly. |
3045 | */ | 3349 | */ |
3046 | rndis_copy_module_params(usbdev); | 3350 | rndis_copy_module_params(usbdev, RNDIS_BCM4320A); |
3047 | 3351 | ||
3048 | /* bcm4320a doesn't handle configuration parameters well. Try | 3352 | /* bcm4320a doesn't handle configuration parameters well. Try |
3049 | * set any and you get partially zeroed mac and broken device. | 3353 | * set any and you get partially zeroed mac and broken device. |
@@ -3057,7 +3361,7 @@ static int bcm4320b_early_init(struct usbnet *usbdev) | |||
3057 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 3361 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
3058 | char buf[8]; | 3362 | char buf[8]; |
3059 | 3363 | ||
3060 | rndis_copy_module_params(usbdev); | 3364 | rndis_copy_module_params(usbdev, RNDIS_BCM4320B); |
3061 | 3365 | ||
3062 | /* Early initialization settings, setting these won't have effect | 3366 | /* Early initialization settings, setting these won't have effect |
3063 | * if called after generic_rndis_bind(). | 3367 | * if called after generic_rndis_bind(). |
@@ -3187,13 +3491,15 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf) | |||
3187 | 3491 | ||
3188 | set_default_iw_params(usbdev); | 3492 | set_default_iw_params(usbdev); |
3189 | 3493 | ||
3494 | priv->power_mode = -1; | ||
3495 | |||
3190 | /* set default rts/frag */ | 3496 | /* set default rts/frag */ |
3191 | rndis_set_wiphy_params(wiphy, | 3497 | rndis_set_wiphy_params(wiphy, |
3192 | WIPHY_PARAM_FRAG_THRESHOLD | WIPHY_PARAM_RTS_THRESHOLD); | 3498 | WIPHY_PARAM_FRAG_THRESHOLD | WIPHY_PARAM_RTS_THRESHOLD); |
3193 | 3499 | ||
3194 | /* turn radio on */ | 3500 | /* turn radio off on init */ |
3195 | priv->radio_on = true; | 3501 | priv->radio_on = false; |
3196 | disassociate(usbdev, true); | 3502 | disassociate(usbdev, false); |
3197 | netif_carrier_off(usbdev->net); | 3503 | netif_carrier_off(usbdev->net); |
3198 | 3504 | ||
3199 | return 0; | 3505 | return 0; |
@@ -3320,7 +3626,7 @@ static const struct driver_info rndis_wlan_info = { | |||
3320 | .tx_fixup = rndis_tx_fixup, | 3626 | .tx_fixup = rndis_tx_fixup, |
3321 | .reset = rndis_wlan_reset, | 3627 | .reset = rndis_wlan_reset, |
3322 | .stop = rndis_wlan_stop, | 3628 | .stop = rndis_wlan_stop, |
3323 | .early_init = bcm4320a_early_init, | 3629 | .early_init = unknown_early_init, |
3324 | .indication = rndis_wlan_indication, | 3630 | .indication = rndis_wlan_indication, |
3325 | }; | 3631 | }; |
3326 | 3632 | ||