1 From: Herbert Xu <herbert@gondor.apana.org.au>
2 Date: Mon, 19 Sep 2016 19:00:10 +0800
3 Subject: [PATCH] mac80211: Use rhltable instead of rhashtable
5 mac80211 currently uses rhashtable with insecure_elasticity set
6 to true. The latter is because of duplicate objects. What's
7 more, mac80211 walks the rhashtable chains by hand which is broken
8 as rhashtable may contain multiple tables due to resizing or
11 This patch fixes it by converting it to the newly added rhltable
12 interface which is designed for use with duplicate objects.
14 With rhltable a lookup returns a list of objects instead of a
15 single one. This is then fed into the existing for_each_sta_info
18 This patch also deletes the sta_addr_hash function since rhashtable
21 Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
24 --- a/net/mac80211/ieee80211_i.h
25 +++ b/net/mac80211/ieee80211_i.h
26 @@ -1233,7 +1233,7 @@ struct ieee80211_local {
28 unsigned long num_sta;
29 struct list_head sta_list;
30 - struct rhashtable sta_hash;
31 + struct rhltable sta_hash;
32 struct timer_list sta_cleanup;
35 --- a/net/mac80211/rx.c
36 +++ b/net/mac80211/rx.c
37 @@ -4004,7 +4004,7 @@ static void __ieee80211_rx_handle_packet
39 struct ieee80211_rx_data rx;
40 struct ieee80211_sub_if_data *prev;
41 - struct rhash_head *tmp;
42 + struct rhlist_head *tmp;
45 fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
46 @@ -4047,13 +4047,10 @@ static void __ieee80211_rx_handle_packet
48 } else if (ieee80211_is_data(fc)) {
49 struct sta_info *sta, *prev_sta;
50 - const struct bucket_table *tbl;
54 - tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
56 - for_each_sta_info(local, tbl, hdr->addr2, sta, tmp) {
57 + for_each_sta_info(local, hdr->addr2, sta, tmp) {
61 --- a/net/mac80211/sta_info.c
62 +++ b/net/mac80211/sta_info.c
65 static const struct rhashtable_params sta_rht_params = {
66 .nelem_hint = 3, /* start small */
67 - .insecure_elasticity = true, /* Disable chain-length checks. */
68 .automatic_shrinking = true,
69 .head_offset = offsetof(struct sta_info, hash_node),
70 .key_offset = offsetof(struct sta_info, addr),
72 - .hashfn = sta_addr_hash,
73 .max_size = CPTCFG_MAC80211_STA_HASH_MAX_SIZE,
76 @@ -80,8 +78,8 @@ static const struct rhashtable_params st
77 static int sta_info_hash_del(struct ieee80211_local *local,
80 - return rhashtable_remove_fast(&local->sta_hash, &sta->hash_node,
82 + return rhltable_remove(&local->sta_hash, &sta->hash_node,
86 static void __cleanup_single_sta(struct sta_info *sta)
87 @@ -157,19 +155,22 @@ static void cleanup_single_sta(struct st
88 sta_info_free(local, sta);
91 +struct rhlist_head *sta_info_hash_lookup(struct ieee80211_local *local,
94 + return rhltable_lookup(&local->sta_hash, addr, sta_rht_params);
97 /* protected by RCU */
98 struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
101 struct ieee80211_local *local = sdata->local;
102 + struct rhlist_head *tmp;
103 struct sta_info *sta;
104 - struct rhash_head *tmp;
105 - const struct bucket_table *tbl;
108 - tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
110 - for_each_sta_info(local, tbl, addr, sta, tmp) {
111 + for_each_sta_info(local, addr, sta, tmp) {
112 if (sta->sdata == sdata) {
114 /* this is safe as the caller must already hold
115 @@ -190,14 +191,11 @@ struct sta_info *sta_info_get_bss(struct
118 struct ieee80211_local *local = sdata->local;
119 + struct rhlist_head *tmp;
120 struct sta_info *sta;
121 - struct rhash_head *tmp;
122 - const struct bucket_table *tbl;
125 - tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
127 - for_each_sta_info(local, tbl, addr, sta, tmp) {
128 + for_each_sta_info(local, addr, sta, tmp) {
129 if (sta->sdata == sdata ||
130 (sta->sdata->bss && sta->sdata->bss == sdata->bss)) {
132 @@ -263,8 +261,8 @@ void sta_info_free(struct ieee80211_loca
133 static int sta_info_hash_add(struct ieee80211_local *local,
134 struct sta_info *sta)
136 - return rhashtable_insert_fast(&local->sta_hash, &sta->hash_node,
138 + return rhltable_insert(&local->sta_hash, &sta->hash_node,
142 static void sta_deliver_ps_frames(struct work_struct *wk)
143 @@ -453,9 +451,9 @@ static int sta_info_insert_check(struct
144 is_multicast_ether_addr(sta->sta.addr)))
147 - /* Strictly speaking this isn't necessary as we hold the mutex, but
148 - * the rhashtable code can't really deal with that distinction. We
149 - * do require the mutex for correctness though.
150 + /* The RCU read lock is required by rhashtable due to
151 + * asynchronous resize/rehash. We also require the mutex
155 lockdep_assert_held(&sdata->local->sta_mtx);
156 @@ -1043,16 +1041,11 @@ static void sta_info_cleanup(unsigned lo
157 round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL));
160 -u32 sta_addr_hash(const void *key, u32 length, u32 seed)
162 - return jhash(key, ETH_ALEN, seed);
165 int sta_info_init(struct ieee80211_local *local)
169 - err = rhashtable_init(&local->sta_hash, &sta_rht_params);
170 + err = rhltable_init(&local->sta_hash, &sta_rht_params);
174 @@ -1068,7 +1061,7 @@ int sta_info_init(struct ieee80211_local
175 void sta_info_stop(struct ieee80211_local *local)
177 del_timer_sync(&local->sta_cleanup);
178 - rhashtable_destroy(&local->sta_hash);
179 + rhltable_destroy(&local->sta_hash);
183 @@ -1138,17 +1131,14 @@ struct ieee80211_sta *ieee80211_find_sta
186 struct ieee80211_local *local = hw_to_local(hw);
187 + struct rhlist_head *tmp;
188 struct sta_info *sta;
189 - struct rhash_head *tmp;
190 - const struct bucket_table *tbl;
192 - tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
195 * Just return a random station if localaddr is NULL
198 - for_each_sta_info(local, tbl, addr, sta, tmp) {
199 + for_each_sta_info(local, addr, sta, tmp) {
201 !ether_addr_equal(sta->sdata->vif.addr, localaddr))
203 --- a/net/mac80211/sta_info.h
204 +++ b/net/mac80211/sta_info.h
205 @@ -455,7 +455,7 @@ struct sta_info {
206 /* General information, mostly static */
207 struct list_head list, free_list;
208 struct rcu_head rcu_head;
209 - struct rhash_head hash_node;
210 + struct rhlist_head hash_node;
212 struct ieee80211_local *local;
213 struct ieee80211_sub_if_data *sdata;
214 @@ -638,6 +638,9 @@ rcu_dereference_protected_tid_tx(struct
216 #define STA_INFO_CLEANUP_INTERVAL (10 * HZ)
218 +struct rhlist_head *sta_info_hash_lookup(struct ieee80211_local *local,
222 * Get a STA info, must be under RCU read lock.
224 @@ -647,17 +650,9 @@ struct sta_info *sta_info_get(struct iee
225 struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
228 -u32 sta_addr_hash(const void *key, u32 length, u32 seed);
230 -#define _sta_bucket_idx(_tbl, _a) \
231 - rht_bucket_index(_tbl, sta_addr_hash(_a, ETH_ALEN, (_tbl)->hash_rnd))
233 -#define for_each_sta_info(local, tbl, _addr, _sta, _tmp) \
234 - rht_for_each_entry_rcu(_sta, _tmp, tbl, \
235 - _sta_bucket_idx(tbl, _addr), \
237 - /* compare address and run code only if it matches */ \
238 - if (ether_addr_equal(_sta->addr, (_addr)))
239 +#define for_each_sta_info(local, _addr, _sta, _tmp) \
240 + rhl_for_each_entry_rcu(_sta, _tmp, \
241 + sta_info_hash_lookup(local, _addr), hash_node)
244 * Get STA info by index, BROKEN!
245 --- a/net/mac80211/status.c
246 +++ b/net/mac80211/status.c
247 @@ -759,8 +759,8 @@ void ieee80211_tx_status(struct ieee8021
248 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
250 struct ieee80211_supported_band *sband;
251 + struct rhlist_head *tmp;
252 struct sta_info *sta;
253 - struct rhash_head *tmp;
257 @@ -768,7 +768,6 @@ void ieee80211_tx_status(struct ieee8021
258 struct ieee80211_bar *bar;
260 int tid = IEEE80211_NUM_TIDS;
261 - const struct bucket_table *tbl;
263 rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
265 @@ -777,9 +776,7 @@ void ieee80211_tx_status(struct ieee8021
266 sband = local->hw.wiphy->bands[info->band];
267 fc = hdr->frame_control;
269 - tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
271 - for_each_sta_info(local, tbl, hdr->addr1, sta, tmp) {
272 + for_each_sta_info(local, hdr->addr1, sta, tmp) {
273 /* skip wrong virtual interface */
274 if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr))