diff options
-rw-r--r-- | include/net/ieee80211.h | 1 | ||||
-rw-r--r-- | include/net/ieee80211_crypt.h | 1 | ||||
-rw-r--r-- | net/ieee80211/ieee80211_crypt.c | 33 | ||||
-rw-r--r-- | net/ieee80211/ieee80211_module.c | 2 |
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); | |||
82 | void ieee80211_crypt_deinit_handler(unsigned long); | 82 | void ieee80211_crypt_deinit_handler(unsigned long); |
83 | void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee, | 83 | void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee, |
84 | struct ieee80211_crypt_data **crypt); | 84 | struct ieee80211_crypt_data **crypt); |
85 | void 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 */ | ||
71 | void 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 | ||
65 | void ieee80211_crypt_deinit_handler(unsigned long data) | 80 | void 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 | ||
79 | void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee, | 97 | void 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) | |||
250 | EXPORT_SYMBOL(ieee80211_crypt_deinit_entries); | 270 | EXPORT_SYMBOL(ieee80211_crypt_deinit_entries); |
251 | EXPORT_SYMBOL(ieee80211_crypt_deinit_handler); | 271 | EXPORT_SYMBOL(ieee80211_crypt_deinit_handler); |
252 | EXPORT_SYMBOL(ieee80211_crypt_delayed_deinit); | 272 | EXPORT_SYMBOL(ieee80211_crypt_delayed_deinit); |
273 | EXPORT_SYMBOL(ieee80211_crypt_quiescing); | ||
253 | 274 | ||
254 | EXPORT_SYMBOL(ieee80211_register_crypto_ops); | 275 | EXPORT_SYMBOL(ieee80211_register_crypto_ops); |
255 | EXPORT_SYMBOL(ieee80211_unregister_crypto_ops); | 276 | EXPORT_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 | ||