diff options
-rw-r--r-- | include/net/mac80211.h | 2 | ||||
-rw-r--r-- | net/mac80211/iface.c | 12 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 19 |
3 files changed, 27 insertions, 6 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index b4bef1152c05..8e3668b44c29 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -1666,6 +1666,8 @@ struct ieee80211_tx_control { | |||
1666 | * @sta: station table entry, %NULL for per-vif queue | 1666 | * @sta: station table entry, %NULL for per-vif queue |
1667 | * @tid: the TID for this queue (unused for per-vif queue) | 1667 | * @tid: the TID for this queue (unused for per-vif queue) |
1668 | * @ac: the AC for this queue | 1668 | * @ac: the AC for this queue |
1669 | * @drv_priv: data area for driver use, will always be aligned to | ||
1670 | * sizeof(void *). | ||
1669 | * | 1671 | * |
1670 | * The driver can obtain packets from this queue by calling | 1672 | * The driver can obtain packets from this queue by calling |
1671 | * ieee80211_tx_dequeue(). | 1673 | * ieee80211_tx_dequeue(). |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index b4ac596a7cb7..bab5c63c0bad 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -819,13 +819,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
819 | * (because if we remove a STA after ops->remove_interface() | 819 | * (because if we remove a STA after ops->remove_interface() |
820 | * the driver will have removed the vif info already!) | 820 | * the driver will have removed the vif info already!) |
821 | * | 821 | * |
822 | * This is relevant only in WDS mode, in all other modes we've | 822 | * In WDS mode a station must exist here and be flushed, for |
823 | * already removed all stations when disconnecting or similar, | 823 | * AP_VLANs stations may exist since there's nothing else that |
824 | * so warn otherwise. | 824 | * would have removed them, but in other modes there shouldn't |
825 | * be any stations. | ||
825 | */ | 826 | */ |
826 | flushed = sta_info_flush(sdata); | 827 | flushed = sta_info_flush(sdata); |
827 | WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || | 828 | WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
828 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)); | 829 | ((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || |
830 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1))); | ||
829 | 831 | ||
830 | /* don't count this interface for promisc/allmulti while it is down */ | 832 | /* don't count this interface for promisc/allmulti while it is down */ |
831 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | 833 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 12971b71d0fa..2880f2ae99ab 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -66,6 +66,7 @@ | |||
66 | 66 | ||
67 | static const struct rhashtable_params sta_rht_params = { | 67 | static const struct rhashtable_params sta_rht_params = { |
68 | .nelem_hint = 3, /* start small */ | 68 | .nelem_hint = 3, /* start small */ |
69 | .automatic_shrinking = true, | ||
69 | .head_offset = offsetof(struct sta_info, hash_node), | 70 | .head_offset = offsetof(struct sta_info, hash_node), |
70 | .key_offset = offsetof(struct sta_info, sta.addr), | 71 | .key_offset = offsetof(struct sta_info, sta.addr), |
71 | .key_len = ETH_ALEN, | 72 | .key_len = ETH_ALEN, |
@@ -157,8 +158,24 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | |||
157 | const u8 *addr) | 158 | const u8 *addr) |
158 | { | 159 | { |
159 | struct ieee80211_local *local = sdata->local; | 160 | struct ieee80211_local *local = sdata->local; |
161 | struct sta_info *sta; | ||
162 | struct rhash_head *tmp; | ||
163 | const struct bucket_table *tbl; | ||
164 | |||
165 | rcu_read_lock(); | ||
166 | tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash); | ||
160 | 167 | ||
161 | return rhashtable_lookup_fast(&local->sta_hash, addr, sta_rht_params); | 168 | for_each_sta_info(local, tbl, addr, sta, tmp) { |
169 | if (sta->sdata == sdata) { | ||
170 | rcu_read_unlock(); | ||
171 | /* this is safe as the caller must already hold | ||
172 | * another rcu read section or the mutex | ||
173 | */ | ||
174 | return sta; | ||
175 | } | ||
176 | } | ||
177 | rcu_read_unlock(); | ||
178 | return NULL; | ||
162 | } | 179 | } |
163 | 180 | ||
164 | /* | 181 | /* |