diff options
Diffstat (limited to 'drivers/net/wireless/libertas/wext.c')
-rw-r--r-- | drivers/net/wireless/libertas/wext.c | 72 |
1 files changed, 45 insertions, 27 deletions
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index fd151afa00b5..da8179d78314 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -30,14 +30,6 @@ static inline void lbs_postpone_association_work(struct lbs_private *priv) queue_delayed_work(priv->work_thread, &priv->assoc_work, HZ / 2); } -static inline void lbs_do_association_work(struct lbs_private *priv) -{ - if (priv->surpriseremoved) - return; - cancel_delayed_work(&priv->assoc_work); - queue_delayed_work(priv->work_thread, &priv->assoc_work, 0); -} - static inline void lbs_cancel_association_work(struct lbs_private *priv) { cancel_delayed_work(&priv->assoc_work); @@ -1498,6 +1490,42 @@ out: return ret; } +/* + * WPA requires key installation to happen immediately after + * the 4-way handshake. We cannot defer key installation to + * the association worker. + * */ +static int install_wpa_key_now(struct lbs_private *priv, struct enc_key *pkey) +{ + int ret = 0; + uint16_t rsn = 0; + + /* disable_wep() does a proper WEP key removal, but it is deferred. + Here we just do the minimal necessary so we can successfully install + the WPA key. + */ + if (priv->mac_control & CMD_ACT_MAC_WEP_ENABLE) { + struct assoc_request ignored; + lbs_cmd_802_11_set_wep(priv, CMD_ACT_REMOVE, &ignored); + priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE; + lbs_set_mac_control(priv); + } + + + /* Get RSN disabled/enabled, in failure assume it's off */ + lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_GET, &rsn); + + if (!rsn) { /* Enable rsn only if needed */ + rsn = !rsn; + ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_SET, &rsn); + } + + if (!ret) + ret = lbs_set_key_material(priv, pkey); + + return ret; +} + /** * @brief Set Encryption key Extended (WPA/802.1x and WEP) * @@ -1583,10 +1611,8 @@ static int lbs_set_encodeext(struct net_device *dev, if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { pkey = &assoc_req->wpa_mcast_key; - set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags); } else { pkey = &assoc_req->wpa_unicast_key; - set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags); } memset(pkey, 0, sizeof (struct enc_key)); @@ -1613,29 +1639,21 @@ static int lbs_set_encodeext(struct net_device *dev, && assoc_req->secinfo.WPA2enabled == 0) { assoc_req->secinfo.WPAenabled = 1; assoc_req->secinfo.WPA2enabled = 1; - set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); } - /* Only disable wep if necessary: can't waste time here. */ - if (priv->mac_control & CMD_ACT_MAC_WEP_ENABLE) - disable_wep(assoc_req); + disable_wep(assoc_req); + mutex_unlock(&priv->lock); + ret = install_wpa_key_now(priv, pkey); + mutex_lock(&priv->lock); + } out: - if (ret == 0) { - /* 802.1x and WPA rekeying must happen as quickly as possible, - * especially during the 4-way handshake; thus if in - * infrastructure mode, and either (a) 802.1x is enabled or - * (b) WPA is being used, set the key right away. - */ - if (assoc_req->mode == IW_MODE_INFRA && - ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP))) { - lbs_do_association_work(priv); - } else - lbs_postpone_association_work(priv); - } else { + if (ret == 0) + lbs_postpone_association_work(priv); + else lbs_cancel_association_work(priv); - } + mutex_unlock(&priv->lock); lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); |