[v3 PATCH 2/2] mac80211: Use rhltable instead of rhashtable

2016-09-19 Thread Herbert Xu
mac80211 currently uses rhashtable with insecure_elasticity set
to true.  The latter is because of duplicate objects.  What's
more, mac80211 walks the rhashtable chains by hand which is broken
as rhashtable may contain multiple tables due to resizing or
rehashing.

This patch fixes it by converting it to the newly added rhltable
interface which is designed for use with duplicate objects.

With rhltable a lookup returns a list of objects instead of a
single one.  This is then fed into the existing for_each_sta_info
macro.

This patch also deletes the sta_addr_hash function since rhashtable
defaults to jhash.

Signed-off-by: Herbert Xu 
---

 net/mac80211/ieee80211_i.h |2 -
 net/mac80211/rx.c  |7 +-
 net/mac80211/sta_info.c|   52 ++---
 net/mac80211/sta_info.h|   19 ++--
 net/mac80211/status.c  |7 +-
 5 files changed, 33 insertions(+), 54 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f56d342..1a52cd4 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1208,7 +1208,7 @@ struct ieee80211_local {
spinlock_t tim_lock;
unsigned long num_sta;
struct list_head sta_list;
-   struct rhashtable sta_hash;
+   struct rhltable sta_hash;
struct timer_list sta_cleanup;
int sta_generation;
 
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 9dce3b1..5e26dc6 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3940,7 +3940,7 @@ static void __ieee80211_rx_handle_packet(struct 
ieee80211_hw *hw,
__le16 fc;
struct ieee80211_rx_data rx;
struct ieee80211_sub_if_data *prev;
-   struct rhash_head *tmp;
+   struct rhlist_head *tmp;
int err = 0;
 
fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
@@ -3983,13 +3983,10 @@ static void __ieee80211_rx_handle_packet(struct 
ieee80211_hw *hw,
goto out;
} else if (ieee80211_is_data(fc)) {
struct sta_info *sta, *prev_sta;
-   const struct bucket_table *tbl;
 
prev_sta = NULL;
 
-   tbl = rht_dereference_rcu(local->sta_hash.tbl, 
>sta_hash);
-
-   for_each_sta_info(local, tbl, hdr->addr2, sta, tmp) {
+   for_each_sta_info(local, hdr->addr2, sta, tmp) {
if (!prev_sta) {
prev_sta = sta;
continue;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 19f14c9..198d0bd 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -67,12 +67,10 @@
 
 static const struct rhashtable_params sta_rht_params = {
.nelem_hint = 3, /* start small */
-   .insecure_elasticity = true, /* Disable chain-length checks. */
.automatic_shrinking = true,
.head_offset = offsetof(struct sta_info, hash_node),
.key_offset = offsetof(struct sta_info, addr),
.key_len = ETH_ALEN,
-   .hashfn = sta_addr_hash,
.max_size = CONFIG_MAC80211_STA_HASH_MAX_SIZE,
 };
 
@@ -80,8 +78,8 @@ static const struct rhashtable_params sta_rht_params = {
 static int sta_info_hash_del(struct ieee80211_local *local,
 struct sta_info *sta)
 {
-   return rhashtable_remove_fast(>sta_hash, >hash_node,
- sta_rht_params);
+   return rhltable_remove(>sta_hash, >hash_node,
+  sta_rht_params);
 }
 
 static void __cleanup_single_sta(struct sta_info *sta)
@@ -157,19 +155,22 @@ static void cleanup_single_sta(struct sta_info *sta)
sta_info_free(local, sta);
 }
 
+struct rhlist_head *sta_info_hash_lookup(struct ieee80211_local *local,
+const u8 *addr)
+{
+   return rhltable_lookup(>sta_hash, addr, sta_rht_params);
+}
+
 /* protected by RCU */
 struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
  const u8 *addr)
 {
struct ieee80211_local *local = sdata->local;
+   struct rhlist_head *tmp;
struct sta_info *sta;
-   struct rhash_head *tmp;
-   const struct bucket_table *tbl;
 
rcu_read_lock();
-   tbl = rht_dereference_rcu(local->sta_hash.tbl, >sta_hash);
-
-   for_each_sta_info(local, tbl, addr, sta, tmp) {
+   for_each_sta_info(local, addr, sta, tmp) {
if (sta->sdata == sdata) {
rcu_read_unlock();
/* this is safe as the caller must already hold
@@ -190,14 +191,11 @@ struct sta_info *sta_info_get_bss(struct 
ieee80211_sub_if_data *sdata,
  const u8 *addr)
 {
struct ieee80211_local *local = sdata->local;
+   struct rhlist_head *tmp;
struct sta_info *sta;
-   struct rhash_head *tmp;
-   const struct bucket_table *tbl;
 

[v2 PATCH 2/2] mac80211: Use rhltable instead of rhashtable

2016-09-19 Thread Herbert Xu
mac80211 currently uses rhashtable with insecure_elasticity set
to true.  The latter is because of duplicate objects.  What's
more, mac80211 walks the rhashtable chains by hand which is broken
as rhashtable may contain multiple tables due to resizing or
rehashing.

This patch fixes it by converting it to the newly added rhltable
interface which is designed for use with duplicate objects.

With rhltable a lookup returns a list of objects instead of a
single one.  This is then fed into the existing for_each_sta_info
macro.

This patch also deletes the sta_addr_hash function since rhashtable
defaults to jhash.

Signed-off-by: Herbert Xu 
---

 net/mac80211/ieee80211_i.h |2 -
 net/mac80211/rx.c  |7 +-
 net/mac80211/sta_info.c|   52 ++---
 net/mac80211/sta_info.h|   19 ++--
 net/mac80211/status.c  |7 +-
 5 files changed, 33 insertions(+), 54 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f56d342..1a52cd4 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1208,7 +1208,7 @@ struct ieee80211_local {
spinlock_t tim_lock;
unsigned long num_sta;
struct list_head sta_list;
-   struct rhashtable sta_hash;
+   struct rhltable sta_hash;
struct timer_list sta_cleanup;
int sta_generation;
 
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 9dce3b1..5e26dc6 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3940,7 +3940,7 @@ static void __ieee80211_rx_handle_packet(struct 
ieee80211_hw *hw,
__le16 fc;
struct ieee80211_rx_data rx;
struct ieee80211_sub_if_data *prev;
-   struct rhash_head *tmp;
+   struct rhlist_head *tmp;
int err = 0;
 
fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
@@ -3983,13 +3983,10 @@ static void __ieee80211_rx_handle_packet(struct 
ieee80211_hw *hw,
goto out;
} else if (ieee80211_is_data(fc)) {
struct sta_info *sta, *prev_sta;
-   const struct bucket_table *tbl;
 
prev_sta = NULL;
 
-   tbl = rht_dereference_rcu(local->sta_hash.tbl, 
>sta_hash);
-
-   for_each_sta_info(local, tbl, hdr->addr2, sta, tmp) {
+   for_each_sta_info(local, hdr->addr2, sta, tmp) {
if (!prev_sta) {
prev_sta = sta;
continue;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 19f14c9..198d0bd 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -67,12 +67,10 @@
 
 static const struct rhashtable_params sta_rht_params = {
.nelem_hint = 3, /* start small */
-   .insecure_elasticity = true, /* Disable chain-length checks. */
.automatic_shrinking = true,
.head_offset = offsetof(struct sta_info, hash_node),
.key_offset = offsetof(struct sta_info, addr),
.key_len = ETH_ALEN,
-   .hashfn = sta_addr_hash,
.max_size = CONFIG_MAC80211_STA_HASH_MAX_SIZE,
 };
 
@@ -80,8 +78,8 @@ static const struct rhashtable_params sta_rht_params = {
 static int sta_info_hash_del(struct ieee80211_local *local,
 struct sta_info *sta)
 {
-   return rhashtable_remove_fast(>sta_hash, >hash_node,
- sta_rht_params);
+   return rhltable_remove(>sta_hash, >hash_node,
+  sta_rht_params);
 }
 
 static void __cleanup_single_sta(struct sta_info *sta)
@@ -157,19 +155,22 @@ static void cleanup_single_sta(struct sta_info *sta)
sta_info_free(local, sta);
 }
 
+struct rhlist_head *sta_info_hash_lookup(struct ieee80211_local *local,
+const u8 *addr)
+{
+   return rhltable_lookup(>sta_hash, addr, sta_rht_params);
+}
+
 /* protected by RCU */
 struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
  const u8 *addr)
 {
struct ieee80211_local *local = sdata->local;
+   struct rhlist_head *tmp;
struct sta_info *sta;
-   struct rhash_head *tmp;
-   const struct bucket_table *tbl;
 
rcu_read_lock();
-   tbl = rht_dereference_rcu(local->sta_hash.tbl, >sta_hash);
-
-   for_each_sta_info(local, tbl, addr, sta, tmp) {
+   for_each_sta_info(local, addr, sta, tmp) {
if (sta->sdata == sdata) {
rcu_read_unlock();
/* this is safe as the caller must already hold
@@ -190,14 +191,11 @@ struct sta_info *sta_info_get_bss(struct 
ieee80211_sub_if_data *sdata,
  const u8 *addr)
 {
struct ieee80211_local *local = sdata->local;
+   struct rhlist_head *tmp;
struct sta_info *sta;
-   struct rhash_head *tmp;
-   const struct bucket_table *tbl;
 

[PATCH 2/2] mac80211: Use rhltable instead of rhashtable

2016-09-18 Thread Herbert Xu
mac80211 currently uses rhashtable with insecure_elasticity set
to true.  The latter is because of duplicate objects.  What's
more, mac80211 walks the rhashtable chains by hand which is broken
as rhashtable may contain multiple tables due to resizing or
rehashing.

This patch fixes it by converting it to the newly added rhltable
interface which is designed for use with duplicate objects.

With rhltable a lookup returns a list of objects instead of a
single one.  This is then fed into the existing for_each_sta_info
macro.

This patch also deletes the sta_addr_hash function since rhashtable
defaults to jhash.

Signed-off-by: Herbert Xu 
---

 net/mac80211/ieee80211_i.h |2 -
 net/mac80211/rx.c  |7 +-
 net/mac80211/sta_info.c|   52 ++---
 net/mac80211/sta_info.h|   19 ++--
 net/mac80211/status.c  |7 +-
 5 files changed, 33 insertions(+), 54 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f56d342..1a52cd4 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1208,7 +1208,7 @@ struct ieee80211_local {
spinlock_t tim_lock;
unsigned long num_sta;
struct list_head sta_list;
-   struct rhashtable sta_hash;
+   struct rhltable sta_hash;
struct timer_list sta_cleanup;
int sta_generation;
 
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 9dce3b1..5e26dc6 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3940,7 +3940,7 @@ static void __ieee80211_rx_handle_packet(struct 
ieee80211_hw *hw,
__le16 fc;
struct ieee80211_rx_data rx;
struct ieee80211_sub_if_data *prev;
-   struct rhash_head *tmp;
+   struct rhlist_head *tmp;
int err = 0;
 
fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
@@ -3983,13 +3983,10 @@ static void __ieee80211_rx_handle_packet(struct 
ieee80211_hw *hw,
goto out;
} else if (ieee80211_is_data(fc)) {
struct sta_info *sta, *prev_sta;
-   const struct bucket_table *tbl;
 
prev_sta = NULL;
 
-   tbl = rht_dereference_rcu(local->sta_hash.tbl, 
>sta_hash);
-
-   for_each_sta_info(local, tbl, hdr->addr2, sta, tmp) {
+   for_each_sta_info(local, hdr->addr2, sta, tmp) {
if (!prev_sta) {
prev_sta = sta;
continue;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 19f14c9..198d0bd 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -67,12 +67,10 @@
 
 static const struct rhashtable_params sta_rht_params = {
.nelem_hint = 3, /* start small */
-   .insecure_elasticity = true, /* Disable chain-length checks. */
.automatic_shrinking = true,
.head_offset = offsetof(struct sta_info, hash_node),
.key_offset = offsetof(struct sta_info, addr),
.key_len = ETH_ALEN,
-   .hashfn = sta_addr_hash,
.max_size = CONFIG_MAC80211_STA_HASH_MAX_SIZE,
 };
 
@@ -80,8 +78,8 @@ static const struct rhashtable_params sta_rht_params = {
 static int sta_info_hash_del(struct ieee80211_local *local,
 struct sta_info *sta)
 {
-   return rhashtable_remove_fast(>sta_hash, >hash_node,
- sta_rht_params);
+   return rhltable_remove(>sta_hash, >hash_node,
+  sta_rht_params);
 }
 
 static void __cleanup_single_sta(struct sta_info *sta)
@@ -157,19 +155,22 @@ static void cleanup_single_sta(struct sta_info *sta)
sta_info_free(local, sta);
 }
 
+struct rhlist_head *sta_info_hash_lookup(struct ieee80211_local *local,
+const u8 *addr)
+{
+   return rhltable_lookup(>sta_hash, addr, sta_rht_params);
+}
+
 /* protected by RCU */
 struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
  const u8 *addr)
 {
struct ieee80211_local *local = sdata->local;
+   struct rhlist_head *tmp;
struct sta_info *sta;
-   struct rhash_head *tmp;
-   const struct bucket_table *tbl;
 
rcu_read_lock();
-   tbl = rht_dereference_rcu(local->sta_hash.tbl, >sta_hash);
-
-   for_each_sta_info(local, tbl, addr, sta, tmp) {
+   for_each_sta_info(local, addr, sta, tmp) {
if (sta->sdata == sdata) {
rcu_read_unlock();
/* this is safe as the caller must already hold
@@ -190,14 +191,11 @@ struct sta_info *sta_info_get_bss(struct 
ieee80211_sub_if_data *sdata,
  const u8 *addr)
 {
struct ieee80211_local *local = sdata->local;
+   struct rhlist_head *tmp;
struct sta_info *sta;
-   struct rhash_head *tmp;
-   const struct bucket_table *tbl;