aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rndis_wlan.c
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>2010-11-09 12:25:56 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-11-16 16:37:04 -0500
commit5cb56af29be8d12f74afcb2c1de91e51a577bd52 (patch)
treef1e78de11a9d1ca92aeaaac13f2dae040858c33c /drivers/net/wireless/rndis_wlan.c
parentb5257c952dda24df7078c74b7b811b44c6e49206 (diff)
rndis_wlan: workaround poor scanning with BCM4320a
BCM4320a devices seem to sometimes do scanning pretty poorly. This can be workaround by issuing new scan every second, while not yet connected. By this new scanning method device catches beacons much faster. Fixes bug #20822. Reported-by: Luís Picciochi <Pitxyoki@gmail.com> Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rndis_wlan.c')
-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 0a423c49aab9..8a77ff68590b 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