aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/key.c51
-rw-r--r--net/mac80211/tx.c14
3 files changed, 57 insertions, 11 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 25c15cc63319..4f2e424e8b1b 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -544,6 +544,9 @@ struct ieee80211_sub_if_data {
544 /* keys */ 544 /* keys */
545 struct list_head key_list; 545 struct list_head key_list;
546 546
547 /* count for keys needing tailroom space allocation */
548 int crypto_tx_tailroom_needed_cnt;
549
547 struct net_device *dev; 550 struct net_device *dev;
548 struct ieee80211_local *local; 551 struct ieee80211_local *local;
549 552
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index f825e2f0a57e..0af958c74342 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -61,6 +61,36 @@ static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key)
61 return NULL; 61 return NULL;
62} 62}
63 63
64static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata)
65{
66 /*
67 * When this count is zero, SKB resizing for allocating tailroom
68 * for IV or MMIC is skipped. But, this check has created two race
69 * cases in xmit path while transiting from zero count to one:
70 *
71 * 1. SKB resize was skipped because no key was added but just before
72 * the xmit key is added and SW encryption kicks off.
73 *
74 * 2. SKB resize was skipped because all the keys were hw planted but
75 * just before xmit one of the key is deleted and SW encryption kicks
76 * off.
77 *
78 * In both the above case SW encryption will find not enough space for
79 * tailroom and exits with WARN_ON. (See WARN_ONs at wpa.c)
80 *
81 * Solution has been explained at
82 * http://mid.gmane.org/1308590980.4322.19.camel@jlt3.sipsolutions.net
83 */
84
85 if (!sdata->crypto_tx_tailroom_needed_cnt++) {
86 /*
87 * Flush all XMIT packets currently using HW encryption or no
88 * encryption at all if the count transition is from 0 -> 1.
89 */
90 synchronize_net();
91 }
92}
93
64static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) 94static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
65{ 95{
66 struct ieee80211_sub_if_data *sdata; 96 struct ieee80211_sub_if_data *sdata;
@@ -101,6 +131,11 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
101 131
102 if (!ret) { 132 if (!ret) {
103 key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; 133 key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
134
135 if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
136 (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
137 sdata->crypto_tx_tailroom_needed_cnt--;
138
104 return 0; 139 return 0;
105 } 140 }
106 141
@@ -142,6 +177,10 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
142 sta = get_sta_for_key(key); 177 sta = get_sta_for_key(key);
143 sdata = key->sdata; 178 sdata = key->sdata;
144 179
180 if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
181 (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
182 increment_tailroom_need_count(sdata);
183
145 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 184 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
146 sdata = container_of(sdata->bss, 185 sdata = container_of(sdata->bss,
147 struct ieee80211_sub_if_data, 186 struct ieee80211_sub_if_data,
@@ -394,8 +433,10 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key)
394 ieee80211_aes_key_free(key->u.ccmp.tfm); 433 ieee80211_aes_key_free(key->u.ccmp.tfm);
395 if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) 434 if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC)
396 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); 435 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
397 if (key->local) 436 if (key->local) {
398 ieee80211_debugfs_key_remove(key); 437 ieee80211_debugfs_key_remove(key);
438 key->sdata->crypto_tx_tailroom_needed_cnt--;
439 }
399 440
400 kfree(key); 441 kfree(key);
401} 442}
@@ -452,6 +493,8 @@ int ieee80211_key_link(struct ieee80211_key *key,
452 else 493 else
453 old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]); 494 old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
454 495
496 increment_tailroom_need_count(sdata);
497
455 __ieee80211_key_replace(sdata, sta, pairwise, old_key, key); 498 __ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
456 __ieee80211_key_destroy(old_key); 499 __ieee80211_key_destroy(old_key);
457 500
@@ -498,8 +541,12 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
498 541
499 mutex_lock(&sdata->local->key_mtx); 542 mutex_lock(&sdata->local->key_mtx);
500 543
501 list_for_each_entry(key, &sdata->key_list, list) 544 sdata->crypto_tx_tailroom_needed_cnt = 0;
545
546 list_for_each_entry(key, &sdata->key_list, list) {
547 increment_tailroom_need_count(sdata);
502 ieee80211_key_enable_hw_accel(key); 548 ieee80211_key_enable_hw_accel(key);
549 }
503 550
504 mutex_unlock(&sdata->local->key_mtx); 551 mutex_unlock(&sdata->local->key_mtx);
505} 552}
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 3104c844b544..e8d0d2d22665 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1474,18 +1474,14 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
1474 1474
1475/* device xmit handlers */ 1475/* device xmit handlers */
1476 1476
1477static int ieee80211_skb_resize(struct ieee80211_local *local, 1477static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
1478 struct sk_buff *skb, 1478 struct sk_buff *skb,
1479 int head_need, bool may_encrypt) 1479 int head_need, bool may_encrypt)
1480{ 1480{
1481 struct ieee80211_local *local = sdata->local;
1481 int tail_need = 0; 1482 int tail_need = 0;
1482 1483
1483 /* 1484 if (may_encrypt && sdata->crypto_tx_tailroom_needed_cnt) {
1484 * This could be optimised, devices that do full hardware
1485 * crypto (including TKIP MMIC) need no tailroom... But we
1486 * have no drivers for such devices currently.
1487 */
1488 if (may_encrypt) {
1489 tail_need = IEEE80211_ENCRYPT_TAILROOM; 1485 tail_need = IEEE80211_ENCRYPT_TAILROOM;
1490 tail_need -= skb_tailroom(skb); 1486 tail_need -= skb_tailroom(skb);
1491 tail_need = max_t(int, tail_need, 0); 1487 tail_need = max_t(int, tail_need, 0);
@@ -1578,7 +1574,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
1578 headroom -= skb_headroom(skb); 1574 headroom -= skb_headroom(skb);
1579 headroom = max_t(int, 0, headroom); 1575 headroom = max_t(int, 0, headroom);
1580 1576
1581 if (ieee80211_skb_resize(local, skb, headroom, may_encrypt)) { 1577 if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) {
1582 dev_kfree_skb(skb); 1578 dev_kfree_skb(skb);
1583 rcu_read_unlock(); 1579 rcu_read_unlock();
1584 return; 1580 return;
@@ -1945,7 +1941,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1945 head_need += IEEE80211_ENCRYPT_HEADROOM; 1941 head_need += IEEE80211_ENCRYPT_HEADROOM;
1946 head_need += local->tx_headroom; 1942 head_need += local->tx_headroom;
1947 head_need = max_t(int, 0, head_need); 1943 head_need = max_t(int, 0, head_need);
1948 if (ieee80211_skb_resize(local, skb, head_need, true)) 1944 if (ieee80211_skb_resize(sdata, skb, head_need, true))
1949 goto fail; 1945 goto fail;
1950 } 1946 }
1951 1947