summaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorSara Sharon <sara.sharon@intel.com>2019-01-21 05:22:21 -0500
committerJohannes Berg <johannes.berg@intel.com>2019-02-08 07:51:50 -0500
commita3584f56de1c808d4383a275b4a74467b19e5645 (patch)
tree940309fe34cc6be5288298610121a0ca02926844 /net/wireless
parent1c8745f3ec6f46f5fa99dbcdf92381144ae1b37f (diff)
cfg80211: Properly track transmitting and non-transmitting BSS
When holding data of the non-transmitting BSS, we need to keep the transmitting BSS data on. Otherwise it will be released, and release the non-transmitting BSS with it. Signed-off-by: Sara Sharon <sara.sharon@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/core.h12
-rw-r--r--net/wireless/scan.c36
2 files changed, 46 insertions, 2 deletions
diff --git a/net/wireless/core.h b/net/wireless/core.h
index a50b92ac77a1..c20c75df60f5 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -153,6 +153,7 @@ struct cfg80211_internal_bss {
153 struct list_head list; 153 struct list_head list;
154 struct list_head hidden_list; 154 struct list_head hidden_list;
155 struct list_head nontrans_list; 155 struct list_head nontrans_list;
156 struct cfg80211_bss *transmitted_bss;
156 struct rb_node rbn; 157 struct rb_node rbn;
157 u64 ts_boottime; 158 u64 ts_boottime;
158 unsigned long ts; 159 unsigned long ts;
@@ -183,12 +184,23 @@ static inline struct cfg80211_internal_bss *bss_from_pub(struct cfg80211_bss *pu
183static inline void cfg80211_hold_bss(struct cfg80211_internal_bss *bss) 184static inline void cfg80211_hold_bss(struct cfg80211_internal_bss *bss)
184{ 185{
185 atomic_inc(&bss->hold); 186 atomic_inc(&bss->hold);
187 if (bss->transmitted_bss) {
188 bss = container_of(bss->transmitted_bss,
189 struct cfg80211_internal_bss, pub);
190 atomic_inc(&bss->hold);
191 }
186} 192}
187 193
188static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss) 194static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss)
189{ 195{
190 int r = atomic_dec_return(&bss->hold); 196 int r = atomic_dec_return(&bss->hold);
191 WARN_ON(r < 0); 197 WARN_ON(r < 0);
198 if (bss->transmitted_bss) {
199 bss = container_of(bss->transmitted_bss,
200 struct cfg80211_internal_bss, pub);
201 r = atomic_dec_return(&bss->hold);
202 WARN_ON(r < 0);
203 }
192} 204}
193 205
194 206
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 54feb7741c26..d5950a23e619 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -110,6 +110,12 @@ static inline void bss_ref_get(struct cfg80211_registered_device *rdev,
110 pub); 110 pub);
111 bss->refcount++; 111 bss->refcount++;
112 } 112 }
113 if (bss->transmitted_bss) {
114 bss = container_of(bss->transmitted_bss,
115 struct cfg80211_internal_bss,
116 pub);
117 bss->refcount++;
118 }
113} 119}
114 120
115static inline void bss_ref_put(struct cfg80211_registered_device *rdev, 121static inline void bss_ref_put(struct cfg80211_registered_device *rdev,
@@ -126,6 +132,18 @@ static inline void bss_ref_put(struct cfg80211_registered_device *rdev,
126 if (hbss->refcount == 0) 132 if (hbss->refcount == 0)
127 bss_free(hbss); 133 bss_free(hbss);
128 } 134 }
135
136 if (bss->transmitted_bss) {
137 struct cfg80211_internal_bss *tbss;
138
139 tbss = container_of(bss->transmitted_bss,
140 struct cfg80211_internal_bss,
141 pub);
142 tbss->refcount--;
143 if (tbss->refcount == 0)
144 bss_free(tbss);
145 }
146
129 bss->refcount--; 147 bss->refcount--;
130 if (bss->refcount == 0) 148 if (bss->refcount == 0)
131 bss_free(bss); 149 bss_free(bss);
@@ -1024,6 +1042,7 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *rdev,
1024static struct cfg80211_internal_bss * 1042static struct cfg80211_internal_bss *
1025cfg80211_bss_update(struct cfg80211_registered_device *rdev, 1043cfg80211_bss_update(struct cfg80211_registered_device *rdev,
1026 struct cfg80211_internal_bss *tmp, 1044 struct cfg80211_internal_bss *tmp,
1045 struct cfg80211_bss *trans_bss,
1027 bool signal_valid) 1046 bool signal_valid)
1028{ 1047{
1029 struct cfg80211_internal_bss *found = NULL; 1048 struct cfg80211_internal_bss *found = NULL;
@@ -1181,6 +1200,17 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
1181 goto drop; 1200 goto drop;
1182 } 1201 }
1183 1202
1203 /* This must be before the call to bss_ref_get */
1204 if (trans_bss) {
1205 struct cfg80211_internal_bss *pbss =
1206 container_of(trans_bss,
1207 struct cfg80211_internal_bss,
1208 pub);
1209
1210 new->transmitted_bss = trans_bss;
1211 bss_ref_get(rdev, pbss);
1212 }
1213
1184 list_add_tail(&new->list, &rdev->bss_list); 1214 list_add_tail(&new->list, &rdev->bss_list);
1185 rdev->bss_entries++; 1215 rdev->bss_entries++;
1186 rb_insert_bss(rdev, new); 1216 rb_insert_bss(rdev, new);
@@ -1336,7 +1366,8 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
1336 1366
1337 signal_valid = abs(data->chan->center_freq - channel->center_freq) <= 1367 signal_valid = abs(data->chan->center_freq - channel->center_freq) <=
1338 wiphy->max_adj_channel_rssi_comp; 1368 wiphy->max_adj_channel_rssi_comp;
1339 res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid); 1369 res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, trans_bss,
1370 signal_valid);
1340 if (!res) 1371 if (!res)
1341 return NULL; 1372 return NULL;
1342 1373
@@ -1639,7 +1670,8 @@ cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
1639 1670
1640 signal_valid = abs(data->chan->center_freq - channel->center_freq) <= 1671 signal_valid = abs(data->chan->center_freq - channel->center_freq) <=
1641 wiphy->max_adj_channel_rssi_comp; 1672 wiphy->max_adj_channel_rssi_comp;
1642 res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid); 1673 res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, trans_bss,
1674 signal_valid);
1643 if (!res) 1675 if (!res)
1644 return NULL; 1676 return NULL;
1645 1677