Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 266045
b: refs/heads/master
c: a2b1328
h: refs/heads/master
i:
  266043: 9aed9d1
v: v3
  • Loading branch information
Helmut Schaa authored and John W. Linville committed Sep 14, 2011
1 parent e502867 commit a6aa0ca
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 31 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: ead2bb64a38c471ad0a769f61921f330f062dd50
refs/heads/master: a2b1328a23c57fbb9c51e6660a11049c35d151f9
153 changes: 123 additions & 30 deletions trunk/drivers/net/wireless/rt2x00/rt2800lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->u.ht.ba_size);
rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
txdesc->key_idx : 0xff);
txdesc->key_idx : txdesc->u.ht.wcid);
rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
txdesc->length);
rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid);
Expand Down Expand Up @@ -910,11 +910,51 @@ static void rt2800_init_led(struct rt2x00_dev *rt2x00dev,
/*
* Configuration handlers.
*/
static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_crypto *crypto,
struct ieee80211_key_conf *key)
static void rt2800_config_wcid(struct rt2x00_dev *rt2x00dev,
const u8 *address,
int wcid)
{
struct mac_wcid_entry wcid_entry;
u32 offset;

offset = MAC_WCID_ENTRY(wcid);

memset(&wcid_entry, 0xff, sizeof(wcid_entry));
if (address)
memcpy(wcid_entry.mac, address, ETH_ALEN);

rt2800_register_multiwrite(rt2x00dev, offset,
&wcid_entry, sizeof(wcid_entry));
}

static void rt2800_delete_wcid_attr(struct rt2x00_dev *rt2x00dev, int wcid)
{
u32 offset;
offset = MAC_WCID_ATTR_ENTRY(wcid);
rt2800_register_write(rt2x00dev, offset, 0);
}

static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev,
int wcid, u32 bssidx)
{
u32 offset = MAC_WCID_ATTR_ENTRY(wcid);
u32 reg;

/*
* The BSS Idx numbers is split in a main value of 3 bits,
* and a extended field for adding one additional bit to the value.
*/
rt2800_register_read(rt2x00dev, offset, &reg);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7));
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,
(bssidx & 0x8) >> 3);
rt2800_register_write(rt2x00dev, offset, reg);
}

static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_crypto *crypto,
struct ieee80211_key_conf *key)
{
struct mac_iveiv_entry iveiv_entry;
u32 offset;
u32 reg;
Expand All @@ -934,14 +974,16 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,
(crypto->cipher & 0x7));
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER_EXT,
(crypto->cipher & 0x8) >> 3);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX,
(crypto->bssidx & 0x7));
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,
(crypto->bssidx & 0x8) >> 3);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher);
rt2800_register_write(rt2x00dev, offset, reg);
} else {
rt2800_register_write(rt2x00dev, offset, 0);
/* Delete the cipher without touching the bssidx */
rt2800_register_read(rt2x00dev, offset, &reg);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB, 0);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER, 0);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER_EXT, 0);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0);
rt2800_register_write(rt2x00dev, offset, reg);
}

offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
Expand All @@ -954,14 +996,6 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,
iveiv_entry.iv[3] |= key->keyidx << 6;
rt2800_register_multiwrite(rt2x00dev, offset,
&iveiv_entry, sizeof(iveiv_entry));

offset = MAC_WCID_ENTRY(key->hw_key_idx);

memset(&wcid_entry, 0, sizeof(wcid_entry));
if (crypto->cmd == SET_KEY)
memcpy(wcid_entry.mac, crypto->address, ETH_ALEN);
rt2800_register_multiwrite(rt2x00dev, offset,
&wcid_entry, sizeof(wcid_entry));
}

int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
Expand Down Expand Up @@ -1008,20 +1042,24 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
/*
* Update WCID information
*/
rt2800_config_wcid_attr(rt2x00dev, crypto, key);
rt2800_config_wcid(rt2x00dev, crypto->address, key->hw_key_idx);
rt2800_config_wcid_attr_bssidx(rt2x00dev, key->hw_key_idx,
crypto->bssidx);
rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);

return 0;
}
EXPORT_SYMBOL_GPL(rt2800_config_shared_key);

static inline int rt2800_find_pairwise_keyslot(struct rt2x00_dev *rt2x00dev)
static inline int rt2800_find_wcid(struct rt2x00_dev *rt2x00dev)
{
struct mac_wcid_entry wcid_entry;
int idx;
u32 offset, reg;
u32 offset;

/*
* Search for the first free pairwise key entry and return the
* corresponding index.
* Search for the first free WCID entry and return the corresponding
* index.
*
* Make sure the WCID starts _after_ the last possible shared key
* entry (>32).
Expand All @@ -1031,11 +1069,17 @@ static inline int rt2800_find_pairwise_keyslot(struct rt2x00_dev *rt2x00dev)
* first 222 entries.
*/
for (idx = 33; idx <= 222; idx++) {
offset = MAC_WCID_ATTR_ENTRY(idx);
rt2800_register_read(rt2x00dev, offset, &reg);
if (!reg)
offset = MAC_WCID_ENTRY(idx);
rt2800_register_multiread(rt2x00dev, offset, &wcid_entry,
sizeof(wcid_entry));
if (is_broadcast_ether_addr(wcid_entry.mac))
return idx;
}

/*
* Use -1 to indicate that we don't have any more space in the WCID
* table.
*/
return -1;
}

Expand All @@ -1045,13 +1089,15 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
{
struct hw_key_entry key_entry;
u32 offset;
int idx;

if (crypto->cmd == SET_KEY) {
idx = rt2800_find_pairwise_keyslot(rt2x00dev);
if (idx < 0)
/*
* Allow key configuration only for STAs that are
* known by the hw.
*/
if (crypto->wcid < 0)
return -ENOSPC;
key->hw_key_idx = idx;
key->hw_key_idx = crypto->wcid;

memcpy(key_entry.key, crypto->key,
sizeof(key_entry.key));
Expand All @@ -1068,12 +1114,59 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
/*
* Update WCID information
*/
rt2800_config_wcid_attr(rt2x00dev, crypto, key);
rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);

return 0;
}
EXPORT_SYMBOL_GPL(rt2800_config_pairwise_key);

int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
int wcid;
struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);

/*
* Find next free WCID.
*/
wcid = rt2800_find_wcid(rt2x00dev);

/*
* Store selected wcid even if it is invalid so that we can
* later decide if the STA is uploaded into the hw.
*/
sta_priv->wcid = wcid;

/*
* No space left in the device, however, we can still communicate
* with the STA -> No error.
*/
if (wcid < 0)
return 0;

/*
* Clean up WCID attributes and write STA address to the device.
*/
rt2800_delete_wcid_attr(rt2x00dev, wcid);
rt2800_config_wcid(rt2x00dev, sta->addr, wcid);
rt2800_config_wcid_attr_bssidx(rt2x00dev, wcid,
rt2x00lib_get_bssidx(rt2x00dev, vif));
return 0;
}
EXPORT_SYMBOL_GPL(rt2800_sta_add);

int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid)
{
/*
* Remove WCID entry, no need to clean the attributes as they will
* get renewed when the WCID is reused.
*/
rt2800_config_wcid(rt2x00dev, NULL, wcid);

return 0;
}
EXPORT_SYMBOL_GPL(rt2800_sta_remove);

void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
const unsigned int filter_flags)
{
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/net/wireless/rt2x00/rt2800lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_crypto *crypto,
struct ieee80211_key_conf *key);
int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid);
void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
const unsigned int filter_flags);
void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
Expand Down
4 changes: 4 additions & 0 deletions trunk/drivers/net/wireless/rt2x00/rt2800pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1015,6 +1015,8 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
.get_stats = rt2x00mac_get_stats,
.get_tkip_seq = rt2800_get_tkip_seq,
.set_rts_threshold = rt2800_set_rts_threshold,
.sta_add = rt2x00mac_sta_add,
.sta_remove = rt2x00mac_sta_remove,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2800_conf_tx,
.get_tsf = rt2800_get_tsf,
Expand Down Expand Up @@ -1076,6 +1078,8 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.config_erp = rt2800_config_erp,
.config_ant = rt2800_config_ant,
.config = rt2800_config,
.sta_add = rt2800_sta_add,
.sta_remove = rt2800_sta_remove,
};

static const struct data_queue_desc rt2800pci_queue_rx = {
Expand Down
4 changes: 4 additions & 0 deletions trunk/drivers/net/wireless/rt2x00/rt2800usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,8 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
.get_stats = rt2x00mac_get_stats,
.get_tkip_seq = rt2800_get_tkip_seq,
.set_rts_threshold = rt2800_set_rts_threshold,
.sta_add = rt2x00mac_sta_add,
.sta_remove = rt2x00mac_sta_remove,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2800_conf_tx,
.get_tsf = rt2800_get_tsf,
Expand Down Expand Up @@ -807,6 +809,8 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
.config_erp = rt2800_config_erp,
.config_ant = rt2800_config_ant,
.config = rt2800_config,
.sta_add = rt2800_sta_add,
.sta_remove = rt2800_sta_remove,
};

static const struct data_queue_desc rt2800usb_queue_rx = {
Expand Down

0 comments on commit a6aa0ca

Please sign in to comment.