Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 256181
b: refs/heads/master
c: 3bff186
h: refs/heads/master
i:
  256179: 1a7b94a
v: v3
  • Loading branch information
Yogesh Ashok Powar authored and John W. Linville committed Jul 5, 2011
1 parent 9a4718e commit 3f51daa
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 12 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: 252e735d64880b011f6cdeb41ebcac2eaeb58fd3
refs/heads/master: 3bff1865186c6bb97855f0c13e3850543dce9cef
3 changes: 3 additions & 0 deletions trunk/net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,9 @@ struct ieee80211_sub_if_data {
/* keys */
struct list_head key_list;

/* count for keys needing tailroom space allocation */
int crypto_tx_tailroom_needed_cnt;

struct net_device *dev;
struct ieee80211_local *local;

Expand Down
51 changes: 49 additions & 2 deletions trunk/net/mac80211/key.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,36 @@ static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key)
return NULL;
}

static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata)
{
/*
* When this count is zero, SKB resizing for allocating tailroom
* for IV or MMIC is skipped. But, this check has created two race
* cases in xmit path while transiting from zero count to one:
*
* 1. SKB resize was skipped because no key was added but just before
* the xmit key is added and SW encryption kicks off.
*
* 2. SKB resize was skipped because all the keys were hw planted but
* just before xmit one of the key is deleted and SW encryption kicks
* off.
*
* In both the above case SW encryption will find not enough space for
* tailroom and exits with WARN_ON. (See WARN_ONs at wpa.c)
*
* Solution has been explained at
* http://mid.gmane.org/1308590980.4322.19.camel@jlt3.sipsolutions.net
*/

if (!sdata->crypto_tx_tailroom_needed_cnt++) {
/*
* Flush all XMIT packets currently using HW encryption or no
* encryption at all if the count transition is from 0 -> 1.
*/
synchronize_net();
}
}

static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
{
struct ieee80211_sub_if_data *sdata;
Expand Down Expand Up @@ -101,6 +131,11 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)

if (!ret) {
key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;

if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
sdata->crypto_tx_tailroom_needed_cnt--;

return 0;
}

Expand Down Expand Up @@ -142,6 +177,10 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
sta = get_sta_for_key(key);
sdata = key->sdata;

if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
increment_tailroom_need_count(sdata);

if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
sdata = container_of(sdata->bss,
struct ieee80211_sub_if_data,
Expand Down Expand Up @@ -394,8 +433,10 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key)
ieee80211_aes_key_free(key->u.ccmp.tfm);
if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC)
ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
if (key->local)
if (key->local) {
ieee80211_debugfs_key_remove(key);
key->sdata->crypto_tx_tailroom_needed_cnt--;
}

kfree(key);
}
Expand Down Expand Up @@ -452,6 +493,8 @@ int ieee80211_key_link(struct ieee80211_key *key,
else
old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]);

increment_tailroom_need_count(sdata);

__ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
__ieee80211_key_destroy(old_key);

Expand Down Expand Up @@ -498,8 +541,12 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)

mutex_lock(&sdata->local->key_mtx);

list_for_each_entry(key, &sdata->key_list, list)
sdata->crypto_tx_tailroom_needed_cnt = 0;

list_for_each_entry(key, &sdata->key_list, list) {
increment_tailroom_need_count(sdata);
ieee80211_key_enable_hw_accel(key);
}

mutex_unlock(&sdata->local->key_mtx);
}
Expand Down
14 changes: 5 additions & 9 deletions trunk/net/mac80211/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1474,18 +1474,14 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,

/* device xmit handlers */

static int ieee80211_skb_resize(struct ieee80211_local *local,
static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb,
int head_need, bool may_encrypt)
{
struct ieee80211_local *local = sdata->local;
int tail_need = 0;

/*
* This could be optimised, devices that do full hardware
* crypto (including TKIP MMIC) need no tailroom... But we
* have no drivers for such devices currently.
*/
if (may_encrypt) {
if (may_encrypt && sdata->crypto_tx_tailroom_needed_cnt) {
tail_need = IEEE80211_ENCRYPT_TAILROOM;
tail_need -= skb_tailroom(skb);
tail_need = max_t(int, tail_need, 0);
Expand Down Expand Up @@ -1578,7 +1574,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
headroom -= skb_headroom(skb);
headroom = max_t(int, 0, headroom);

if (ieee80211_skb_resize(local, skb, headroom, may_encrypt)) {
if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) {
dev_kfree_skb(skb);
rcu_read_unlock();
return;
Expand Down Expand Up @@ -1945,7 +1941,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
head_need += IEEE80211_ENCRYPT_HEADROOM;
head_need += local->tx_headroom;
head_need = max_t(int, 0, head_need);
if (ieee80211_skb_resize(local, skb, head_need, true))
if (ieee80211_skb_resize(sdata, skb, head_need, true))
goto fail;
}

Expand Down

0 comments on commit 3f51daa

Please sign in to comment.