1
0

312-mac80211-Use-rhltable-instead-of-rhashtable.patch 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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
  4. mac80211 currently uses rhashtable with insecure_elasticity set
  5. to true. The latter is because of duplicate objects. What's
  6. more, mac80211 walks the rhashtable chains by hand which is broken
  7. as rhashtable may contain multiple tables due to resizing or
  8. rehashing.
  9. This patch fixes it by converting it to the newly added rhltable
  10. interface which is designed for use with duplicate objects.
  11. With rhltable a lookup returns a list of objects instead of a
  12. single one. This is then fed into the existing for_each_sta_info
  13. macro.
  14. This patch also deletes the sta_addr_hash function since rhashtable
  15. defaults to jhash.
  16. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
  17. ---
  18. --- a/net/mac80211/ieee80211_i.h
  19. +++ b/net/mac80211/ieee80211_i.h
  20. @@ -1233,7 +1233,7 @@ struct ieee80211_local {
  21. spinlock_t tim_lock;
  22. unsigned long num_sta;
  23. struct list_head sta_list;
  24. - struct rhashtable sta_hash;
  25. + struct rhltable sta_hash;
  26. struct timer_list sta_cleanup;
  27. int sta_generation;
  28. --- a/net/mac80211/rx.c
  29. +++ b/net/mac80211/rx.c
  30. @@ -4004,7 +4004,7 @@ static void __ieee80211_rx_handle_packet
  31. __le16 fc;
  32. struct ieee80211_rx_data rx;
  33. struct ieee80211_sub_if_data *prev;
  34. - struct rhash_head *tmp;
  35. + struct rhlist_head *tmp;
  36. int err = 0;
  37. fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
  38. @@ -4047,13 +4047,10 @@ static void __ieee80211_rx_handle_packet
  39. goto out;
  40. } else if (ieee80211_is_data(fc)) {
  41. struct sta_info *sta, *prev_sta;
  42. - const struct bucket_table *tbl;
  43. prev_sta = NULL;
  44. - tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
  45. -
  46. - for_each_sta_info(local, tbl, hdr->addr2, sta, tmp) {
  47. + for_each_sta_info(local, hdr->addr2, sta, tmp) {
  48. if (!prev_sta) {
  49. prev_sta = sta;
  50. continue;
  51. --- a/net/mac80211/sta_info.c
  52. +++ b/net/mac80211/sta_info.c
  53. @@ -67,12 +67,10 @@
  54. static const struct rhashtable_params sta_rht_params = {
  55. .nelem_hint = 3, /* start small */
  56. - .insecure_elasticity = true, /* Disable chain-length checks. */
  57. .automatic_shrinking = true,
  58. .head_offset = offsetof(struct sta_info, hash_node),
  59. .key_offset = offsetof(struct sta_info, addr),
  60. .key_len = ETH_ALEN,
  61. - .hashfn = sta_addr_hash,
  62. .max_size = CPTCFG_MAC80211_STA_HASH_MAX_SIZE,
  63. };
  64. @@ -80,8 +78,8 @@ static const struct rhashtable_params st
  65. static int sta_info_hash_del(struct ieee80211_local *local,
  66. struct sta_info *sta)
  67. {
  68. - return rhashtable_remove_fast(&local->sta_hash, &sta->hash_node,
  69. - sta_rht_params);
  70. + return rhltable_remove(&local->sta_hash, &sta->hash_node,
  71. + sta_rht_params);
  72. }
  73. static void __cleanup_single_sta(struct sta_info *sta)
  74. @@ -157,19 +155,22 @@ static void cleanup_single_sta(struct st
  75. sta_info_free(local, sta);
  76. }
  77. +struct rhlist_head *sta_info_hash_lookup(struct ieee80211_local *local,
  78. + const u8 *addr)
  79. +{
  80. + return rhltable_lookup(&local->sta_hash, addr, sta_rht_params);
  81. +}
  82. +
  83. /* protected by RCU */
  84. struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
  85. const u8 *addr)
  86. {
  87. struct ieee80211_local *local = sdata->local;
  88. + struct rhlist_head *tmp;
  89. struct sta_info *sta;
  90. - struct rhash_head *tmp;
  91. - const struct bucket_table *tbl;
  92. rcu_read_lock();
  93. - tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
  94. -
  95. - for_each_sta_info(local, tbl, addr, sta, tmp) {
  96. + for_each_sta_info(local, addr, sta, tmp) {
  97. if (sta->sdata == sdata) {
  98. rcu_read_unlock();
  99. /* this is safe as the caller must already hold
  100. @@ -190,14 +191,11 @@ struct sta_info *sta_info_get_bss(struct
  101. const u8 *addr)
  102. {
  103. struct ieee80211_local *local = sdata->local;
  104. + struct rhlist_head *tmp;
  105. struct sta_info *sta;
  106. - struct rhash_head *tmp;
  107. - const struct bucket_table *tbl;
  108. rcu_read_lock();
  109. - tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
  110. -
  111. - for_each_sta_info(local, tbl, addr, sta, tmp) {
  112. + for_each_sta_info(local, addr, sta, tmp) {
  113. if (sta->sdata == sdata ||
  114. (sta->sdata->bss && sta->sdata->bss == sdata->bss)) {
  115. rcu_read_unlock();
  116. @@ -263,8 +261,8 @@ void sta_info_free(struct ieee80211_loca
  117. static int sta_info_hash_add(struct ieee80211_local *local,
  118. struct sta_info *sta)
  119. {
  120. - return rhashtable_insert_fast(&local->sta_hash, &sta->hash_node,
  121. - sta_rht_params);
  122. + return rhltable_insert(&local->sta_hash, &sta->hash_node,
  123. + sta_rht_params);
  124. }
  125. static void sta_deliver_ps_frames(struct work_struct *wk)
  126. @@ -453,9 +451,9 @@ static int sta_info_insert_check(struct
  127. is_multicast_ether_addr(sta->sta.addr)))
  128. return -EINVAL;
  129. - /* Strictly speaking this isn't necessary as we hold the mutex, but
  130. - * the rhashtable code can't really deal with that distinction. We
  131. - * do require the mutex for correctness though.
  132. + /* The RCU read lock is required by rhashtable due to
  133. + * asynchronous resize/rehash. We also require the mutex
  134. + * for correctness.
  135. */
  136. rcu_read_lock();
  137. lockdep_assert_held(&sdata->local->sta_mtx);
  138. @@ -1043,16 +1041,11 @@ static void sta_info_cleanup(unsigned lo
  139. round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL));
  140. }
  141. -u32 sta_addr_hash(const void *key, u32 length, u32 seed)
  142. -{
  143. - return jhash(key, ETH_ALEN, seed);
  144. -}
  145. -
  146. int sta_info_init(struct ieee80211_local *local)
  147. {
  148. int err;
  149. - err = rhashtable_init(&local->sta_hash, &sta_rht_params);
  150. + err = rhltable_init(&local->sta_hash, &sta_rht_params);
  151. if (err)
  152. return err;
  153. @@ -1068,7 +1061,7 @@ int sta_info_init(struct ieee80211_local
  154. void sta_info_stop(struct ieee80211_local *local)
  155. {
  156. del_timer_sync(&local->sta_cleanup);
  157. - rhashtable_destroy(&local->sta_hash);
  158. + rhltable_destroy(&local->sta_hash);
  159. }
  160. @@ -1138,17 +1131,14 @@ struct ieee80211_sta *ieee80211_find_sta
  161. const u8 *localaddr)
  162. {
  163. struct ieee80211_local *local = hw_to_local(hw);
  164. + struct rhlist_head *tmp;
  165. struct sta_info *sta;
  166. - struct rhash_head *tmp;
  167. - const struct bucket_table *tbl;
  168. -
  169. - tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
  170. /*
  171. * Just return a random station if localaddr is NULL
  172. * ... first in list.
  173. */
  174. - for_each_sta_info(local, tbl, addr, sta, tmp) {
  175. + for_each_sta_info(local, addr, sta, tmp) {
  176. if (localaddr &&
  177. !ether_addr_equal(sta->sdata->vif.addr, localaddr))
  178. continue;
  179. --- a/net/mac80211/sta_info.h
  180. +++ b/net/mac80211/sta_info.h
  181. @@ -455,7 +455,7 @@ struct sta_info {
  182. /* General information, mostly static */
  183. struct list_head list, free_list;
  184. struct rcu_head rcu_head;
  185. - struct rhash_head hash_node;
  186. + struct rhlist_head hash_node;
  187. u8 addr[ETH_ALEN];
  188. struct ieee80211_local *local;
  189. struct ieee80211_sub_if_data *sdata;
  190. @@ -638,6 +638,9 @@ rcu_dereference_protected_tid_tx(struct
  191. */
  192. #define STA_INFO_CLEANUP_INTERVAL (10 * HZ)
  193. +struct rhlist_head *sta_info_hash_lookup(struct ieee80211_local *local,
  194. + const u8 *addr);
  195. +
  196. /*
  197. * Get a STA info, must be under RCU read lock.
  198. */
  199. @@ -647,17 +650,9 @@ struct sta_info *sta_info_get(struct iee
  200. struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
  201. const u8 *addr);
  202. -u32 sta_addr_hash(const void *key, u32 length, u32 seed);
  203. -
  204. -#define _sta_bucket_idx(_tbl, _a) \
  205. - rht_bucket_index(_tbl, sta_addr_hash(_a, ETH_ALEN, (_tbl)->hash_rnd))
  206. -
  207. -#define for_each_sta_info(local, tbl, _addr, _sta, _tmp) \
  208. - rht_for_each_entry_rcu(_sta, _tmp, tbl, \
  209. - _sta_bucket_idx(tbl, _addr), \
  210. - hash_node) \
  211. - /* compare address and run code only if it matches */ \
  212. - if (ether_addr_equal(_sta->addr, (_addr)))
  213. +#define for_each_sta_info(local, _addr, _sta, _tmp) \
  214. + rhl_for_each_entry_rcu(_sta, _tmp, \
  215. + sta_info_hash_lookup(local, _addr), hash_node)
  216. /*
  217. * Get STA info by index, BROKEN!
  218. --- a/net/mac80211/status.c
  219. +++ b/net/mac80211/status.c
  220. @@ -759,8 +759,8 @@ void ieee80211_tx_status(struct ieee8021
  221. struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  222. __le16 fc;
  223. struct ieee80211_supported_band *sband;
  224. + struct rhlist_head *tmp;
  225. struct sta_info *sta;
  226. - struct rhash_head *tmp;
  227. int retry_count;
  228. int rates_idx;
  229. bool send_to_cooked;
  230. @@ -768,7 +768,6 @@ void ieee80211_tx_status(struct ieee8021
  231. struct ieee80211_bar *bar;
  232. int shift = 0;
  233. int tid = IEEE80211_NUM_TIDS;
  234. - const struct bucket_table *tbl;
  235. rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
  236. @@ -777,9 +776,7 @@ void ieee80211_tx_status(struct ieee8021
  237. sband = local->hw.wiphy->bands[info->band];
  238. fc = hdr->frame_control;
  239. - tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
  240. -
  241. - for_each_sta_info(local, tbl, hdr->addr1, sta, tmp) {
  242. + for_each_sta_info(local, hdr->addr1, sta, tmp) {
  243. /* skip wrong virtual interface */
  244. if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr))
  245. continue;