Skip to content

Commit a3584f5

Browse files
sara-sjmberg-intel
authored andcommitted
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 <[email protected]> Signed-off-by: Johannes Berg <[email protected]>
1 parent 1c8745f commit a3584f5

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

net/wireless/core.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ struct cfg80211_internal_bss {
153153
struct list_head list;
154154
struct list_head hidden_list;
155155
struct list_head nontrans_list;
156+
struct cfg80211_bss *transmitted_bss;
156157
struct rb_node rbn;
157158
u64 ts_boottime;
158159
unsigned long ts;
@@ -183,12 +184,23 @@ static inline struct cfg80211_internal_bss *bss_from_pub(struct cfg80211_bss *pu
183184
static inline void cfg80211_hold_bss(struct cfg80211_internal_bss *bss)
184185
{
185186
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+
}
186192
}
187193

188194
static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss)
189195
{
190196
int r = atomic_dec_return(&bss->hold);
191197
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+
}
192204
}
193205

194206

net/wireless/scan.c

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ static inline void bss_ref_get(struct cfg80211_registered_device *rdev,
110110
pub);
111111
bss->refcount++;
112112
}
113+
if (bss->transmitted_bss) {
114+
bss = container_of(bss->transmitted_bss,
115+
struct cfg80211_internal_bss,
116+
pub);
117+
bss->refcount++;
118+
}
113119
}
114120

115121
static 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,
126132
if (hbss->refcount == 0)
127133
bss_free(hbss);
128134
}
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+
129147
bss->refcount--;
130148
if (bss->refcount == 0)
131149
bss_free(bss);
@@ -1024,6 +1042,7 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *rdev,
10241042
static struct cfg80211_internal_bss *
10251043
cfg80211_bss_update(struct cfg80211_registered_device *rdev,
10261044
struct cfg80211_internal_bss *tmp,
1045+
struct cfg80211_bss *trans_bss,
10271046
bool signal_valid)
10281047
{
10291048
struct cfg80211_internal_bss *found = NULL;
@@ -1181,6 +1200,17 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
11811200
goto drop;
11821201
}
11831202

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+
11841214
list_add_tail(&new->list, &rdev->bss_list);
11851215
rdev->bss_entries++;
11861216
rb_insert_bss(rdev, new);
@@ -1336,7 +1366,8 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
13361366

13371367
signal_valid = abs(data->chan->center_freq - channel->center_freq) <=
13381368
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);
13401371
if (!res)
13411372
return NULL;
13421373

@@ -1639,7 +1670,8 @@ cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
16391670

16401671
signal_valid = abs(data->chan->center_freq - channel->center_freq) <=
16411672
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);
16431675
if (!res)
16441676
return NULL;
16451677

0 commit comments

Comments
 (0)