aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/rndis_wlan.c67
1 files changed, 56 insertions, 11 deletions
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 0a423c49aab..8a77ff68590 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
@@ -997,6 +1004,16 @@ static void restore_keys(struct usbnet *usbdev);
997static int rndis_check_bssid_list(struct usbnet *usbdev, u8 *match_bssid, 1004static int rndis_check_bssid_list(struct usbnet *usbdev, u8 *match_bssid,
998 bool *matched); 1005 bool *matched);
999 1006
1007static int rndis_start_bssid_list_scan(struct usbnet *usbdev)
1008{
1009 __le32 tmp;
1010
1011 /* Note: OID_802_11_BSSID_LIST_SCAN clears internal BSS list. */
1012 tmp = cpu_to_le32(1);
1013 return rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp,
1014 sizeof(tmp));
1015}
1016
1000static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) 1017static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
1001{ 1018{
1002 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); 1019 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
@@ -1905,7 +1922,7 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
1905 struct usbnet *usbdev = netdev_priv(dev); 1922 struct usbnet *usbdev = netdev_priv(dev);
1906 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); 1923 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
1907 int ret; 1924 int ret;
1908 __le32 tmp; 1925 int delay = SCAN_DELAY_JIFFIES;
1909 1926
1910 netdev_dbg(usbdev->net, "cfg80211.scan\n"); 1927 netdev_dbg(usbdev->net, "cfg80211.scan\n");
1911 1928
@@ -1922,13 +1939,13 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
1922 1939
1923 priv->scan_request = request; 1940 priv->scan_request = request;
1924 1941
1925 tmp = cpu_to_le32(1); 1942 ret = rndis_start_bssid_list_scan(usbdev);
1926 ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp,
1927 sizeof(tmp));
1928 if (ret == 0) { 1943 if (ret == 0) {
1944 if (priv->device_type == RNDIS_BCM4320A)
1945 delay = HZ;
1946
1929 /* Wait before retrieving scan results from device */ 1947 /* Wait before retrieving scan results from device */
1930 queue_delayed_work(priv->workqueue, &priv->scan_work, 1948 queue_delayed_work(priv->workqueue, &priv->scan_work, delay);
1931 SCAN_DELAY_JIFFIES);
1932 } 1949 }
1933 1950
1934 return ret; 1951 return ret;
@@ -3046,8 +3063,21 @@ static void rndis_device_poller(struct work_struct *work)
3046 * also polls device with rndis_command() and catches for media link 3063 * also polls device with rndis_command() and catches for media link
3047 * indications. 3064 * indications.
3048 */ 3065 */
3049 if (!is_associated(usbdev)) 3066 if (!is_associated(usbdev)) {
3067 /* Workaround bad scanning in BCM4320a devices with active
3068 * background scanning when not associated.
3069 */
3070 if (priv->device_type == RNDIS_BCM4320A && priv->radio_on &&
3071 !priv->scan_request) {
3072 /* Get previous scan results */
3073 rndis_check_bssid_list(usbdev, NULL, NULL);
3074
3075 /* Initiate new scan */
3076 rndis_start_bssid_list_scan(usbdev);
3077 }
3078
3050 goto end; 3079 goto end;
3080 }
3051 3081
3052 len = sizeof(rssi); 3082 len = sizeof(rssi);
3053 ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len); 3083 ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len);
@@ -3104,10 +3134,12 @@ end:
3104/* 3134/*
3105 * driver/device initialization 3135 * driver/device initialization
3106 */ 3136 */
3107static void rndis_copy_module_params(struct usbnet *usbdev) 3137static void rndis_copy_module_params(struct usbnet *usbdev, int device_type)
3108{ 3138{
3109 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); 3139 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
3110 3140
3141 priv->device_type = device_type;
3142
3111 priv->param_country[0] = modparam_country[0]; 3143 priv->param_country[0] = modparam_country[0];
3112 priv->param_country[1] = modparam_country[1]; 3144 priv->param_country[1] = modparam_country[1];
3113 priv->param_country[2] = 0; 3145 priv->param_country[2] = 0;
@@ -3150,12 +3182,25 @@ static void rndis_copy_module_params(struct usbnet *usbdev)
3150 priv->param_workaround_interval = modparam_workaround_interval; 3182 priv->param_workaround_interval = modparam_workaround_interval;
3151} 3183}
3152 3184
3185static int unknown_early_init(struct usbnet *usbdev)
3186{
3187 /* copy module parameters for unknown so that iwconfig reports txpower
3188 * and workaround parameter is copied to private structure correctly.
3189 */
3190 rndis_copy_module_params(usbdev, RNDIS_UNKNOWN);
3191
3192 /* This is unknown device, so do not try set configuration parameters.
3193 */
3194
3195 return 0;
3196}
3197
3153static int bcm4320a_early_init(struct usbnet *usbdev) 3198static int bcm4320a_early_init(struct usbnet *usbdev)
3154{ 3199{
3155 /* copy module parameters for bcm4320a so that iwconfig reports txpower 3200 /* copy module parameters for bcm4320a so that iwconfig reports txpower
3156 * and workaround parameter is copied to private structure correctly. 3201 * and workaround parameter is copied to private structure correctly.
3157 */ 3202 */
3158 rndis_copy_module_params(usbdev); 3203 rndis_copy_module_params(usbdev, RNDIS_BCM4320A);
3159 3204
3160 /* bcm4320a doesn't handle configuration parameters well. Try 3205 /* bcm4320a doesn't handle configuration parameters well. Try
3161 * set any and you get partially zeroed mac and broken device. 3206 * set any and you get partially zeroed mac and broken device.
@@ -3169,7 +3214,7 @@ static int bcm4320b_early_init(struct usbnet *usbdev)
3169 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); 3214 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
3170 char buf[8]; 3215 char buf[8];
3171 3216
3172 rndis_copy_module_params(usbdev); 3217 rndis_copy_module_params(usbdev, RNDIS_BCM4320B);
3173 3218
3174 /* Early initialization settings, setting these won't have effect 3219 /* Early initialization settings, setting these won't have effect
3175 * if called after generic_rndis_bind(). 3220 * if called after generic_rndis_bind().
@@ -3432,7 +3477,7 @@ static const struct driver_info rndis_wlan_info = {
3432 .tx_fixup = rndis_tx_fixup, 3477 .tx_fixup = rndis_tx_fixup,
3433 .reset = rndis_wlan_reset, 3478 .reset = rndis_wlan_reset,
3434 .stop = rndis_wlan_stop, 3479 .stop = rndis_wlan_stop,
3435 .early_init = bcm4320a_early_init, 3480 .early_init = unknown_early_init,
3436 .indication = rndis_wlan_indication, 3481 .indication = rndis_wlan_indication,
3437}; 3482};
3438 3483