summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavier Cardona <javier@cozybit.com>2008-11-06 16:04:44 -0800
committerDeepak Saxena <dsaxena@laptop.org>2008-11-11 12:10:26 -0800
commit4c4cb9ac0f7373d092cbe6b9ad58e324c6a5647b (patch)
tree7d98d99f9252f175d9506a4d2241e7950131c888
parentfd3ef663a9b2729a6f626326d6692fc77323f11d (diff)
downloadlwn-4c4cb9ac0f7373d092cbe6b9ad58e324c6a5647b.tar.gz
lwn-4c4cb9ac0f7373d092cbe6b9ad58e324c6a5647b.zip
libertas: Decouple RSN enable/disable from WPA key installation.
Signed-off-by: Javier Cardona <javier@cozybit.com>
-rw-r--r--drivers/net/wireless/libertas/assoc.c52
-rw-r--r--drivers/net/wireless/libertas/cmd.c5
-rw-r--r--drivers/net/wireless/libertas/defs.h3
-rw-r--r--drivers/net/wireless/libertas/dev.h13
-rw-r--r--drivers/net/wireless/libertas/main.c11
-rw-r--r--drivers/net/wireless/libertas/wext.c64
6 files changed, 35 insertions, 113 deletions
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index 2238e0412858..6cf6a23a882c 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -343,41 +343,6 @@ out:
}
-static int assoc_helper_wpa_keys(struct lbs_private *priv,
- struct assoc_request * assoc_req)
-{
- int ret = 0;
- unsigned int flags = assoc_req->flags;
-
- lbs_deb_enter(LBS_DEB_ASSOC);
-
- /* Work around older firmware bug where WPA unicast and multicast
- * keys must be set independently. Seen in SDIO parts with firmware
- * version 5.0.11p0.
- */
-
- if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
- clear_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
- ret = lbs_set_key_material(priv, &assoc_req->wpa_unicast_key);
- assoc_req->flags = flags;
- }
-
- if (ret)
- goto out;
-
- if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
- clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
-
- ret = lbs_set_key_material(priv, &assoc_req->wpa_mcast_key);
- assoc_req->flags = flags;
- }
-
-out:
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
- return ret;
-}
-
-
static int assoc_helper_wpa_ie(struct lbs_private *priv,
struct assoc_request * assoc_req)
{
@@ -605,13 +570,6 @@ void lbs_association_worker(struct work_struct *work)
goto out;
}
- if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)
- || test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
- ret = assoc_helper_wpa_keys(priv, assoc_req);
- if (ret)
- goto out;
- }
-
/* SSID/BSSID should be the _last_ config option set, because they
* trigger the association attempt.
*/
@@ -718,16 +676,6 @@ struct assoc_request *lbs_get_association_request(struct lbs_private *priv)
if (!test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags))
assoc_req->wep_tx_keyidx = priv->wep_tx_keyidx;
- if (!test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
- memcpy(&assoc_req->wpa_mcast_key, &priv->wpa_mcast_key,
- sizeof(struct enc_key));
- }
-
- if (!test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
- memcpy(&assoc_req->wpa_unicast_key, &priv->wpa_unicast_key,
- sizeof(struct enc_key));
- }
-
if (!test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
memcpy(&assoc_req->secinfo, &priv->secinfo,
sizeof(struct lbs_802_11_security));
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 10ec0905befe..5b5ef6085972 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -444,10 +444,15 @@ int lbs_set_key_material(struct lbs_private *priv, struct enc_key *key)
if (ret)
goto out;
+ key->flags |= KEY_INFO_WPA_INSTALLED;
if (key->flags & KEY_INFO_WPA_ENABLED)
lbs_deb_cmd("SET_WPA_KEY: %s%s installed\n",
key->flags & KEY_INFO_WPA_UNICAST ? "PTK" : "",
key->flags & KEY_INFO_WPA_MCAST ? "GTK" : "");
+ else
+ lbs_deb_cmd("SET_WPA_KEY: %s%s cleared\n",
+ key->flags & KEY_INFO_WPA_UNICAST ? "PTK" : "",
+ key->flags & KEY_INFO_WPA_MCAST ? "GTK" : "");
out:
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index 98c5dff632fb..8de989fb5ff2 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -386,7 +386,8 @@ enum KEY_TYPE_ID {
enum KEY_INFO_WPA {
KEY_INFO_WPA_MCAST = 0x01,
KEY_INFO_WPA_UNICAST = 0x02,
- KEY_INFO_WPA_ENABLED = 0x04
+ KEY_INFO_WPA_ENABLED = 0x04,
+ KEY_INFO_WPA_INSTALLED = 0x08
};
/** SNMP_MIB_VALUE_e */
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index 0c07a0b2f221..c4e3d29dcc37 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -143,7 +143,8 @@ struct lbs_private {
wait_queue_head_t waitq;
struct workqueue_struct *work_thread;
- struct work_struct mcast_work;
+ struct work_struct mcast_work;
+ struct work_struct wpa_key_work;
struct delayed_work scan_work;
struct delayed_work assoc_work;
@@ -340,10 +341,8 @@ struct assoc_request {
#define ASSOC_FLAG_BSSID 5
#define ASSOC_FLAG_WEP_KEYS 6
#define ASSOC_FLAG_WEP_TX_KEYIDX 7
-#define ASSOC_FLAG_WPA_MCAST_KEY 8
-#define ASSOC_FLAG_WPA_UCAST_KEY 9
-#define ASSOC_FLAG_SECINFO 10
-#define ASSOC_FLAG_WPA_IE 11
+#define ASSOC_FLAG_SECINFO 8
+#define ASSOC_FLAG_WPA_IE 9
unsigned long flags;
u8 ssid[IW_ESSID_MAX_SIZE + 1];
@@ -357,10 +356,6 @@ struct assoc_request {
struct enc_key wep_keys[4];
u16 wep_tx_keyidx;
- /** WPA keys */
- struct enc_key wpa_mcast_key;
- struct enc_key wpa_unicast_key;
-
struct lbs_802_11_security secinfo;
/** WPA Information Elements*/
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 6ccd395d0972..37a5fc43ab28 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -622,6 +622,16 @@ static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd,
return i;
}
+static void wpa_key_worker(struct work_struct *work)
+{
+ struct lbs_private *priv =
+ container_of(work, struct lbs_private, wpa_key_work);
+ if (!(priv->wpa_mcast_key.flags & KEY_INFO_WPA_INSTALLED))
+ lbs_set_key_material(priv, &priv->wpa_mcast_key);
+ else if (!(priv->wpa_unicast_key.flags & KEY_INFO_WPA_INSTALLED))
+ lbs_set_key_material(priv, &priv->wpa_unicast_key);
+}
+
static void lbs_set_mcast_worker(struct work_struct *work)
{
struct lbs_private *priv = container_of(work, struct lbs_private, mcast_work);
@@ -1176,6 +1186,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker);
INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker);
INIT_WORK(&priv->sync_channel, lbs_sync_channel);
+ INIT_WORK(&priv->wpa_key_work, wpa_key_worker);
sprintf(priv->mesh_ssid, "mesh");
priv->mesh_ssid_len = 4;
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index 0a27dbef48cb..3df9dc57f8b9 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -30,6 +30,13 @@ 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_schedule_wpa_key_work(struct lbs_private *priv)
+{
+ if (priv->surpriseremoved)
+ return;
+ queue_work(priv->work_thread, &priv->wpa_key_work);
+}
+
static inline void lbs_cancel_association_work(struct lbs_private *priv)
{
cancel_delayed_work(&priv->assoc_work);
@@ -1294,14 +1301,6 @@ static void disable_wpa(struct assoc_request *assoc_req)
{
lbs_deb_enter(LBS_DEB_WEXT);
- memset(&assoc_req->wpa_mcast_key, 0, sizeof (struct enc_key));
- assoc_req->wpa_mcast_key.flags = KEY_INFO_WPA_MCAST;
- set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
-
- memset(&assoc_req->wpa_unicast_key, 0, sizeof (struct enc_key));
- assoc_req->wpa_unicast_key.flags = KEY_INFO_WPA_UNICAST;
- set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
-
assoc_req->secinfo.WPAenabled = 0;
assoc_req->secinfo.WPA2enabled = 0;
set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
@@ -1490,42 +1489,6 @@ 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)
*
@@ -1557,7 +1520,9 @@ static int lbs_set_encodeext(struct net_device *dev,
if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) {
disable_wep (assoc_req);
- disable_wpa (assoc_req);
+ memset(&priv->wpa_mcast_key, 0, sizeof(struct enc_key));
+ memset(&priv->wpa_unicast_key, 0, sizeof(struct enc_key));
+ lbs_schedule_wpa_key_work(priv);
} else if (alg == IW_ENCODE_ALG_WEP) {
u16 is_default = 0, index, set_tx_key = 0;
@@ -1610,9 +1575,9 @@ static int lbs_set_encodeext(struct net_device *dev,
}
if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
- pkey = &assoc_req->wpa_mcast_key;
+ pkey = &priv->wpa_mcast_key;
} else {
- pkey = &assoc_req->wpa_unicast_key;
+ pkey = &priv->wpa_unicast_key;
}
memset(pkey, 0, sizeof (struct enc_key));
@@ -1642,10 +1607,7 @@ static int lbs_set_encodeext(struct net_device *dev,
}
disable_wep(assoc_req);
- mutex_unlock(&priv->lock);
- ret = install_wpa_key_now(priv, pkey);
- mutex_lock(&priv->lock);
-
+ lbs_schedule_wpa_key_work(priv);
}
out: