at76c50x-usb: Make WEP encryption working.
authorAndrea Merello <andrea.merello@gmail.com>
Sat, 24 May 2014 15:16:18 +0000 (17:16 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 29 May 2014 17:08:10 +0000 (13:08 -0400)
Currently the driver uses HW encryption.
Whenever mac80211 calls the set_key() callback the driver restarts the
whole HW configuration procedure, in order to set (also) the new
WEP key.
However, by doing this, it causes the card to loose association information,
and the HW becomes unable to communicate with the BSS.

This patch adds support for sending another HW command, that sets only
the wep key, instead of resetting all.
Mac80211 key-set requests are thus handled via this new command.

Tested on my at76c503

Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/at76c50x-usb.c
drivers/net/wireless/at76c50x-usb.h

index 9e6e9fc27d6a4cf66a9ec8753fa8be0ad1de4a32..10fd12ec85be909501bd831ba8174f03f1b5cd2e 100644 (file)
@@ -2039,6 +2039,44 @@ static void at76_configure_filter(struct ieee80211_hw *hw,
        ieee80211_queue_work(hw, &priv->work_set_promisc);
 }
 
+static int at76_set_wep(struct at76_priv *priv)
+{
+       int ret = 0;
+       struct mib_mac_wep *mib_data = &priv->mib_buf.data.wep_mib;
+
+       priv->mib_buf.type = MIB_MAC_WEP;
+       priv->mib_buf.size = sizeof(struct mib_mac_wep);
+       priv->mib_buf.index = 0;
+
+       memset(mib_data, 0, sizeof(*mib_data));
+
+       if (priv->wep_enabled) {
+               if (priv->wep_keys_len[priv->wep_key_id] > WEP_SMALL_KEY_LEN)
+                       mib_data->encryption_level = 2;
+               else
+                       mib_data->encryption_level = 1;
+
+               /* always exclude unencrypted if WEP is active */
+               mib_data->exclude_unencrypted = 1;
+       } else {
+               mib_data->exclude_unencrypted = 0;
+               mib_data->encryption_level = 0;
+       }
+
+       mib_data->privacy_invoked = priv->wep_enabled;
+       mib_data->wep_default_key_id = priv->wep_key_id;
+       memcpy(mib_data->wep_default_keyvalue, priv->wep_keys,
+              sizeof(priv->wep_keys));
+
+       ret = at76_set_mib(priv, &priv->mib_buf);
+
+       if (ret < 0)
+               wiphy_err(priv->hw->wiphy,
+                         "set_mib (wep) failed: %d\n", ret);
+
+       return ret;
+}
+
 static int at76_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                        struct ieee80211_vif *vif, struct ieee80211_sta *sta,
                        struct ieee80211_key_conf *key)
@@ -2081,7 +2119,7 @@ static int at76_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                        priv->wep_enabled = 1;
        }
 
-       at76_startup_device(priv);
+       at76_set_wep(priv);
 
        mutex_unlock(&priv->mtx);
 
index f14a65473fe8466062bf70a156dd620038787fb5..4718aa59f0510ba04ae07cbffd73ff4e1f4f0b7e 100644 (file)
@@ -219,18 +219,6 @@ struct at76_req_join {
        u8 reserved;
 } __packed;
 
-struct set_mib_buffer {
-       u8 type;
-       u8 size;
-       u8 index;
-       u8 reserved;
-       union {
-               u8 byte;
-               __le16 word;
-               u8 addr[ETH_ALEN];
-       } data;
-} __packed;
-
 struct mib_local {
        u16 reserved0;
        u8 beacon_enable;
@@ -334,6 +322,19 @@ struct mib_mdomain {
        u8 channel_list[14];    /* 0 for invalid channels */
 } __packed;
 
+struct set_mib_buffer {
+       u8 type;
+       u8 size;
+       u8 index;
+       u8 reserved;
+       union {
+               u8 byte;
+               __le16 word;
+               u8 addr[ETH_ALEN];
+               struct mib_mac_wep wep_mib;
+       } data;
+} __packed;
+
 struct at76_fw_header {
        __le32 crc;             /* CRC32 of the whole image */
        __le32 board_type;      /* firmware compatibility code */