aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/ieee80211.h1
-rw-r--r--include/net/ieee80211_crypt.h1
-rw-r--r--net/ieee80211/ieee80211_crypt.c33
-rw-r--r--net/ieee80211/ieee80211_module.c2
4 files changed, 31 insertions, 6 deletions
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index fa14360dbc9d..6cc0674e5606 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -684,6 +684,7 @@ struct ieee80211_device {
684 struct ieee80211_crypt_data *crypt[WEP_KEYS]; 684 struct ieee80211_crypt_data *crypt[WEP_KEYS];
685 int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */ 685 int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
686 struct timer_list crypt_deinit_timer; 686 struct timer_list crypt_deinit_timer;
687 int crypt_quiesced;
687 688
688 int bcrx_sta_key; /* use individual keys to override default keys even 689 int bcrx_sta_key; /* use individual keys to override default keys even
689 * with RX of broad/multicast frames */ 690 * with RX of broad/multicast frames */
diff --git a/include/net/ieee80211_crypt.h b/include/net/ieee80211_crypt.h
index e2064edb957d..536e9a9e6718 100644
--- a/include/net/ieee80211_crypt.h
+++ b/include/net/ieee80211_crypt.h
@@ -82,5 +82,6 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int);
82void ieee80211_crypt_deinit_handler(unsigned long); 82void ieee80211_crypt_deinit_handler(unsigned long);
83void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee, 83void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
84 struct ieee80211_crypt_data **crypt); 84 struct ieee80211_crypt_data **crypt);
85void ieee80211_crypt_quiescing(struct ieee80211_device *ieee);
85 86
86#endif 87#endif
diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c
index 0c366299db0f..60d3166facce 100644
--- a/net/ieee80211/ieee80211_crypt.c
+++ b/net/ieee80211/ieee80211_crypt.c
@@ -44,6 +44,10 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force)
44 unsigned long flags; 44 unsigned long flags;
45 45
46 spin_lock_irqsave(&ieee->lock, flags); 46 spin_lock_irqsave(&ieee->lock, flags);
47
48 if (list_empty(&ieee->crypt_deinit_list))
49 goto unlock;
50
47 for (ptr = ieee->crypt_deinit_list.next, n = ptr->next; 51 for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
48 ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) { 52 ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
49 entry = list_entry(ptr, struct ieee80211_crypt_data, list); 53 entry = list_entry(ptr, struct ieee80211_crypt_data, list);
@@ -59,21 +63,35 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force)
59 } 63 }
60 kfree(entry); 64 kfree(entry);
61 } 65 }
66 unlock:
67 spin_unlock_irqrestore(&ieee->lock, flags);
68}
69
70/* After this, crypt_deinit_list won't accept new members */
71void ieee80211_crypt_quiescing(struct ieee80211_device *ieee)
72{
73 unsigned long flags;
74
75 spin_lock_irqsave(&ieee->lock, flags);
76 ieee->crypt_quiesced = 1;
62 spin_unlock_irqrestore(&ieee->lock, flags); 77 spin_unlock_irqrestore(&ieee->lock, flags);
63} 78}
64 79
65void ieee80211_crypt_deinit_handler(unsigned long data) 80void ieee80211_crypt_deinit_handler(unsigned long data)
66{ 81{
67 struct ieee80211_device *ieee = (struct ieee80211_device *)data; 82 struct ieee80211_device *ieee = (struct ieee80211_device *)data;
83 unsigned long flags;
68 84
69 ieee80211_crypt_deinit_entries(ieee, 0); 85 ieee80211_crypt_deinit_entries(ieee, 0);
70 if (!list_empty(&ieee->crypt_deinit_list)) { 86
87 spin_lock_irqsave(&ieee->lock, flags);
88 if (!list_empty(&ieee->crypt_deinit_list) && !ieee->crypt_quiesced) {
71 printk(KERN_DEBUG "%s: entries remaining in delayed crypt " 89 printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
72 "deletion list\n", ieee->dev->name); 90 "deletion list\n", ieee->dev->name);
73 ieee->crypt_deinit_timer.expires = jiffies + HZ; 91 ieee->crypt_deinit_timer.expires = jiffies + HZ;
74 add_timer(&ieee->crypt_deinit_timer); 92 add_timer(&ieee->crypt_deinit_timer);
75 } 93 }
76 94 spin_unlock_irqrestore(&ieee->lock, flags);
77} 95}
78 96
79void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee, 97void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
@@ -93,10 +111,12 @@ void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
93 * locking. */ 111 * locking. */
94 112
95 spin_lock_irqsave(&ieee->lock, flags); 113 spin_lock_irqsave(&ieee->lock, flags);
96 list_add(&tmp->list, &ieee->crypt_deinit_list); 114 if (!ieee->crypt_quiesced) {
97 if (!timer_pending(&ieee->crypt_deinit_timer)) { 115 list_add(&tmp->list, &ieee->crypt_deinit_list);
98 ieee->crypt_deinit_timer.expires = jiffies + HZ; 116 if (!timer_pending(&ieee->crypt_deinit_timer)) {
99 add_timer(&ieee->crypt_deinit_timer); 117 ieee->crypt_deinit_timer.expires = jiffies + HZ;
118 add_timer(&ieee->crypt_deinit_timer);
119 }
100 } 120 }
101 spin_unlock_irqrestore(&ieee->lock, flags); 121 spin_unlock_irqrestore(&ieee->lock, flags);
102} 122}
@@ -250,6 +270,7 @@ static void __exit ieee80211_crypto_deinit(void)
250EXPORT_SYMBOL(ieee80211_crypt_deinit_entries); 270EXPORT_SYMBOL(ieee80211_crypt_deinit_entries);
251EXPORT_SYMBOL(ieee80211_crypt_deinit_handler); 271EXPORT_SYMBOL(ieee80211_crypt_deinit_handler);
252EXPORT_SYMBOL(ieee80211_crypt_delayed_deinit); 272EXPORT_SYMBOL(ieee80211_crypt_delayed_deinit);
273EXPORT_SYMBOL(ieee80211_crypt_quiescing);
253 274
254EXPORT_SYMBOL(ieee80211_register_crypto_ops); 275EXPORT_SYMBOL(ieee80211_register_crypto_ops);
255EXPORT_SYMBOL(ieee80211_unregister_crypto_ops); 276EXPORT_SYMBOL(ieee80211_unregister_crypto_ops);
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index 4b43ae1235f9..82a4fd713b28 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -138,6 +138,7 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
138 init_timer(&ieee->crypt_deinit_timer); 138 init_timer(&ieee->crypt_deinit_timer);
139 ieee->crypt_deinit_timer.data = (unsigned long)ieee; 139 ieee->crypt_deinit_timer.data = (unsigned long)ieee;
140 ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler; 140 ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
141 ieee->crypt_quiesced = 0;
141 142
142 spin_lock_init(&ieee->lock); 143 spin_lock_init(&ieee->lock);
143 144
@@ -161,6 +162,7 @@ void free_ieee80211(struct net_device *dev)
161 162
162 int i; 163 int i;
163 164
165 ieee80211_crypt_quiescing(ieee);
164 del_timer_sync(&ieee->crypt_deinit_timer); 166 del_timer_sync(&ieee->crypt_deinit_timer);
165 ieee80211_crypt_deinit_entries(ieee, 1); 167 ieee80211_crypt_deinit_entries(ieee, 1);
166 168