Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 236719
b: refs/heads/master
c: fcdc403
h: refs/heads/master
i:
  236717: 14bbe28
  236715: 996fa18
  236711: e36105c
  236703: d140271
v: v3
  • Loading branch information
Nishant Sarmukadam authored and John W. Linville committed Jan 19, 2011
1 parent 4876441 commit 9aca693
Show file tree
Hide file tree
Showing 2 changed files with 278 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d9a07d4980514e701555c4f03b865a54c4c48b4a
refs/heads/master: fcdc403c31ed5bb5f3baf42f4e2b5e7198fef0c0
280 changes: 277 additions & 3 deletions trunk/drivers/net/wireless/mwl8k.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ struct mwl8k_vif {
bool is_hw_crypto_enabled;
};
#define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv))
#define IEEE80211_KEY_CONF(_u8) ((struct ieee80211_key_conf *)(_u8))

struct mwl8k_sta {
/* Index into station database. Returned by UPDATE_STADB. */
Expand Down Expand Up @@ -352,6 +353,7 @@ static const struct ieee80211_rate mwl8k_rates_50[] = {
#define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203
#define MWL8K_CMD_BSS_START 0x1100 /* per-vif */
#define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */
#define MWL8K_CMD_UPDATE_ENCRYPTION 0x1122 /* per-vif */
#define MWL8K_CMD_UPDATE_STADB 0x1123

static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize)
Expand Down Expand Up @@ -390,6 +392,7 @@ static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize)
MWL8K_CMDNAME(SET_RATEADAPT_MODE);
MWL8K_CMDNAME(BSS_START);
MWL8K_CMDNAME(SET_NEW_STN);
MWL8K_CMDNAME(UPDATE_ENCRYPTION);
MWL8K_CMDNAME(UPDATE_STADB);
default:
snprintf(buf, bufsize, "0x%x", cmd);
Expand Down Expand Up @@ -3240,6 +3243,274 @@ static int mwl8k_cmd_set_new_stn_del(struct ieee80211_hw *hw,
return rc;
}

/*
* CMD_UPDATE_ENCRYPTION.
*/

#define MAX_ENCR_KEY_LENGTH 16
#define MIC_KEY_LENGTH 8

struct mwl8k_cmd_update_encryption {
struct mwl8k_cmd_pkt header;

__le32 action;
__le32 reserved;
__u8 mac_addr[6];
__u8 encr_type;

} __attribute__((packed));

struct mwl8k_cmd_set_key {
struct mwl8k_cmd_pkt header;

__le32 action;
__le32 reserved;
__le16 length;
__le16 key_type_id;
__le32 key_info;
__le32 key_id;
__le16 key_len;
__u8 key_material[MAX_ENCR_KEY_LENGTH];
__u8 tkip_tx_mic_key[MIC_KEY_LENGTH];
__u8 tkip_rx_mic_key[MIC_KEY_LENGTH];
__le16 tkip_rsc_low;
__le32 tkip_rsc_high;
__le16 tkip_tsc_low;
__le32 tkip_tsc_high;
__u8 mac_addr[6];
} __attribute__((packed));

enum {
MWL8K_ENCR_ENABLE,
MWL8K_ENCR_SET_KEY,
MWL8K_ENCR_REMOVE_KEY,
MWL8K_ENCR_SET_GROUP_KEY,
};

#define MWL8K_UPDATE_ENCRYPTION_TYPE_WEP 0
#define MWL8K_UPDATE_ENCRYPTION_TYPE_DISABLE 1
#define MWL8K_UPDATE_ENCRYPTION_TYPE_TKIP 4
#define MWL8K_UPDATE_ENCRYPTION_TYPE_MIXED 7
#define MWL8K_UPDATE_ENCRYPTION_TYPE_AES 8

enum {
MWL8K_ALG_WEP,
MWL8K_ALG_TKIP,
MWL8K_ALG_CCMP,
};

#define MWL8K_KEY_FLAG_TXGROUPKEY 0x00000004
#define MWL8K_KEY_FLAG_PAIRWISE 0x00000008
#define MWL8K_KEY_FLAG_TSC_VALID 0x00000040
#define MWL8K_KEY_FLAG_WEP_TXKEY 0x01000000
#define MWL8K_KEY_FLAG_MICKEY_VALID 0x02000000

static int mwl8k_cmd_update_encryption_enable(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u8 *addr,
u8 encr_type)
{
struct mwl8k_cmd_update_encryption *cmd;
int rc;

cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;

cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_ENCRYPTION);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
cmd->action = cpu_to_le32(MWL8K_ENCR_ENABLE);
memcpy(cmd->mac_addr, addr, ETH_ALEN);
cmd->encr_type = encr_type;

rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
kfree(cmd);

return rc;
}

static int mwl8k_encryption_set_cmd_info(struct mwl8k_cmd_set_key *cmd,
u8 *addr,
struct ieee80211_key_conf *key)
{
cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_ENCRYPTION);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
cmd->length = cpu_to_le16(sizeof(*cmd) -
offsetof(struct mwl8k_cmd_set_key, length));
cmd->key_id = cpu_to_le32(key->keyidx);
cmd->key_len = cpu_to_le16(key->keylen);
memcpy(cmd->mac_addr, addr, ETH_ALEN);

switch (key->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
cmd->key_type_id = cpu_to_le16(MWL8K_ALG_WEP);
if (key->keyidx == 0)
cmd->key_info = cpu_to_le32(MWL8K_KEY_FLAG_WEP_TXKEY);

break;
case WLAN_CIPHER_SUITE_TKIP:
cmd->key_type_id = cpu_to_le16(MWL8K_ALG_TKIP);
cmd->key_info = (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
? cpu_to_le32(MWL8K_KEY_FLAG_PAIRWISE)
: cpu_to_le32(MWL8K_KEY_FLAG_TXGROUPKEY);
cmd->key_info |= cpu_to_le32(MWL8K_KEY_FLAG_MICKEY_VALID
| MWL8K_KEY_FLAG_TSC_VALID);
break;
case WLAN_CIPHER_SUITE_CCMP:
cmd->key_type_id = cpu_to_le16(MWL8K_ALG_CCMP);
cmd->key_info = (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
? cpu_to_le32(MWL8K_KEY_FLAG_PAIRWISE)
: cpu_to_le32(MWL8K_KEY_FLAG_TXGROUPKEY);
break;
default:
return -ENOTSUPP;
}

return 0;
}

static int mwl8k_cmd_encryption_set_key(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u8 *addr,
struct ieee80211_key_conf *key)
{
struct mwl8k_cmd_set_key *cmd;
int rc;
int keymlen;
u32 action;
u8 idx;
struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);

cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;

rc = mwl8k_encryption_set_cmd_info(cmd, addr, key);
if (rc < 0)
goto done;

idx = key->keyidx;

if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
action = MWL8K_ENCR_SET_KEY;
else
action = MWL8K_ENCR_SET_GROUP_KEY;

switch (key->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
if (!mwl8k_vif->wep_key_conf[idx].enabled) {
memcpy(mwl8k_vif->wep_key_conf[idx].key, key,
sizeof(*key) + key->keylen);
mwl8k_vif->wep_key_conf[idx].enabled = 1;
}

keymlen = 0;
action = MWL8K_ENCR_SET_KEY;
break;
case WLAN_CIPHER_SUITE_TKIP:
keymlen = MAX_ENCR_KEY_LENGTH + 2 * MIC_KEY_LENGTH;
break;
case WLAN_CIPHER_SUITE_CCMP:
keymlen = key->keylen;
break;
default:
rc = -ENOTSUPP;
goto done;
}

memcpy(cmd->key_material, key->key, keymlen);
cmd->action = cpu_to_le32(action);

rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
done:
kfree(cmd);

return rc;
}

static int mwl8k_cmd_encryption_remove_key(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u8 *addr,
struct ieee80211_key_conf *key)
{
struct mwl8k_cmd_set_key *cmd;
int rc;
struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);

cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;

rc = mwl8k_encryption_set_cmd_info(cmd, addr, key);
if (rc < 0)
goto done;

if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
WLAN_CIPHER_SUITE_WEP104)
mwl8k_vif->wep_key_conf[key->keyidx].enabled = 0;

cmd->action = cpu_to_le32(MWL8K_ENCR_REMOVE_KEY);

rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
done:
kfree(cmd);

return rc;
}

static int mwl8k_set_key(struct ieee80211_hw *hw,
enum set_key_cmd cmd_param,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key)
{
int rc = 0;
u8 encr_type;
u8 *addr;
struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);

if (vif->type == NL80211_IFTYPE_STATION)
return -EOPNOTSUPP;

if (sta == NULL)
addr = hw->wiphy->perm_addr;
else
addr = sta->addr;

if (cmd_param == SET_KEY) {
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
rc = mwl8k_cmd_encryption_set_key(hw, vif, addr, key);
if (rc)
goto out;

if ((key->cipher == WLAN_CIPHER_SUITE_WEP40)
|| (key->cipher == WLAN_CIPHER_SUITE_WEP104))
encr_type = MWL8K_UPDATE_ENCRYPTION_TYPE_WEP;
else
encr_type = MWL8K_UPDATE_ENCRYPTION_TYPE_MIXED;

rc = mwl8k_cmd_update_encryption_enable(hw, vif, addr,
encr_type);
if (rc)
goto out;

mwl8k_vif->is_hw_crypto_enabled = true;

} else {
rc = mwl8k_cmd_encryption_remove_key(hw, vif, addr, key);

if (rc)
goto out;

mwl8k_vif->is_hw_crypto_enabled = false;

}
out:
return rc;
}

/*
* CMD_UPDATE_STADB.
*/
Expand Down Expand Up @@ -4010,25 +4281,27 @@ static int mwl8k_sta_add(struct ieee80211_hw *hw,
{
struct mwl8k_priv *priv = hw->priv;
int ret;
int i;
struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
struct ieee80211_key_conf *key;

if (!priv->ap_fw) {
ret = mwl8k_cmd_update_stadb_add(hw, vif, sta);
if (ret >= 0) {
MWL8K_STA(sta)->peer_id = ret;
return 0;
ret = 0;
}

} else {
ret = mwl8k_cmd_set_new_stn_add(hw, vif, sta);
return ret;
}

for (i = 0; i < NUM_WEP_KEYS; i++) {
key = IEEE80211_KEY_CONF(mwl8k_vif->wep_key_conf[i].key);
if (mwl8k_vif->wep_key_conf[i].enabled)
mwl8k_set_key(hw, SET_KEY, vif, sta, key);
}
return mwl8k_cmd_set_new_stn_add(hw, vif, sta);
return ret;
}

static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue,
Expand Down Expand Up @@ -4106,6 +4379,7 @@ static const struct ieee80211_ops mwl8k_ops = {
.bss_info_changed = mwl8k_bss_info_changed,
.prepare_multicast = mwl8k_prepare_multicast,
.configure_filter = mwl8k_configure_filter,
.set_key = mwl8k_set_key,
.set_rts_threshold = mwl8k_set_rts_threshold,
.sta_add = mwl8k_sta_add,
.sta_remove = mwl8k_sta_remove,
Expand Down

0 comments on commit 9aca693

Please sign in to comment.