diff options
author | Felix Fietkau <nbd@openwrt.org> | 2014-06-11 06:47:55 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-06-19 15:49:17 -0400 |
commit | 78b21949711ee3c877f1aab5b51abe1981e1161d (patch) | |
tree | 317ab473cd8a8ca5a96fdd000a5fc70a644868be /drivers | |
parent | c083ce9980109065297aa2171d18980a0ac92bb9 (diff) |
ath9k: Implement hw_scan support
Implement hw_scan support for enabling multi-channel cuncurrency.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 24 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/channel.c | 31 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/init.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 187 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/pci.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 5 |
6 files changed, 255 insertions, 2 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index d5a586bbab7c..d6b0c4e55c95 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -35,6 +35,7 @@ extern struct ieee80211_ops ath9k_ops; | |||
35 | extern int ath9k_modparam_nohwcrypt; | 35 | extern int ath9k_modparam_nohwcrypt; |
36 | extern int led_blink; | 36 | extern int led_blink; |
37 | extern bool is_ath9k_unloaded; | 37 | extern bool is_ath9k_unloaded; |
38 | extern int ath9k_use_chanctx; | ||
38 | 39 | ||
39 | /*************************/ | 40 | /*************************/ |
40 | /* Descriptor Management */ | 41 | /* Descriptor Management */ |
@@ -332,12 +333,34 @@ struct ath_chanctx { | |||
332 | bool active; | 333 | bool active; |
333 | }; | 334 | }; |
334 | 335 | ||
336 | enum ath_offchannel_state { | ||
337 | ATH_OFFCHANNEL_IDLE, | ||
338 | ATH_OFFCHANNEL_PROBE_SEND, | ||
339 | ATH_OFFCHANNEL_PROBE_WAIT, | ||
340 | ATH_OFFCHANNEL_SUSPEND, | ||
341 | }; | ||
342 | |||
343 | struct ath_offchannel { | ||
344 | struct ath_chanctx chan; | ||
345 | struct timer_list timer; | ||
346 | struct cfg80211_scan_request *scan_req; | ||
347 | struct ieee80211_vif *scan_vif; | ||
348 | int scan_idx; | ||
349 | enum ath_offchannel_state state; | ||
350 | }; | ||
351 | |||
352 | void ath9k_fill_chanctx_ops(void); | ||
335 | void ath_chanctx_init(struct ath_softc *sc); | 353 | void ath_chanctx_init(struct ath_softc *sc); |
336 | void ath_chanctx_set_channel(struct ath_softc *sc, struct ath_chanctx *ctx, | 354 | void ath_chanctx_set_channel(struct ath_softc *sc, struct ath_chanctx *ctx, |
337 | struct cfg80211_chan_def *chandef); | 355 | struct cfg80211_chan_def *chandef); |
338 | void ath_chanctx_switch(struct ath_softc *sc, struct ath_chanctx *ctx, | 356 | void ath_chanctx_switch(struct ath_softc *sc, struct ath_chanctx *ctx, |
339 | struct cfg80211_chan_def *chandef); | 357 | struct cfg80211_chan_def *chandef); |
340 | void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx); | 358 | void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx); |
359 | void ath_offchannel_timer(unsigned long data); | ||
360 | void ath_offchannel_channel_change(struct ath_softc *sc); | ||
361 | void ath_chanctx_offchan_switch(struct ath_softc *sc, | ||
362 | struct ieee80211_channel *chan); | ||
363 | struct ath_chanctx *ath_chanctx_get_oper_chan(struct ath_softc *sc); | ||
341 | 364 | ||
342 | int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan); | 365 | int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan); |
343 | int ath_startrecv(struct ath_softc *sc); | 366 | int ath_startrecv(struct ath_softc *sc); |
@@ -771,6 +794,7 @@ struct ath_softc { | |||
771 | struct ath_chanctx *cur_chan; | 794 | struct ath_chanctx *cur_chan; |
772 | struct ath_chanctx *next_chan; | 795 | struct ath_chanctx *next_chan; |
773 | spinlock_t chan_lock; | 796 | spinlock_t chan_lock; |
797 | struct ath_offchannel offchannel; | ||
774 | 798 | ||
775 | #ifdef CONFIG_MAC80211_LEDS | 799 | #ifdef CONFIG_MAC80211_LEDS |
776 | bool led_registered; | 800 | bool led_registered; |
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 26fc98b3495b..c679a26045ac 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c | |||
@@ -228,6 +228,7 @@ void ath_chanctx_work(struct work_struct *work) | |||
228 | if (send_ps) | 228 | if (send_ps) |
229 | ath_chanctx_send_ps_frame(sc, false); | 229 | ath_chanctx_send_ps_frame(sc, false); |
230 | 230 | ||
231 | ath_offchannel_channel_change(sc); | ||
231 | mutex_unlock(&sc->mutex); | 232 | mutex_unlock(&sc->mutex); |
232 | } | 233 | } |
233 | 234 | ||
@@ -253,6 +254,14 @@ void ath_chanctx_init(struct ath_softc *sc) | |||
253 | INIT_LIST_HEAD(&ctx->acq[j]); | 254 | INIT_LIST_HEAD(&ctx->acq[j]); |
254 | } | 255 | } |
255 | sc->cur_chan = &sc->chanctx[0]; | 256 | sc->cur_chan = &sc->chanctx[0]; |
257 | ctx = &sc->offchannel.chan; | ||
258 | cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20); | ||
259 | INIT_LIST_HEAD(&ctx->vifs); | ||
260 | ctx->txpower = ATH_TXPOWER_MAX; | ||
261 | for (j = 0; j < ARRAY_SIZE(ctx->acq); j++) | ||
262 | INIT_LIST_HEAD(&ctx->acq[j]); | ||
263 | sc->offchannel.chan.offchannel = true; | ||
264 | |||
256 | } | 265 | } |
257 | 266 | ||
258 | void ath_chanctx_switch(struct ath_softc *sc, struct ath_chanctx *ctx, | 267 | void ath_chanctx_switch(struct ath_softc *sc, struct ath_chanctx *ctx, |
@@ -283,3 +292,25 @@ void ath_chanctx_set_channel(struct ath_softc *sc, struct ath_chanctx *ctx, | |||
283 | 292 | ||
284 | ath_set_channel(sc); | 293 | ath_set_channel(sc); |
285 | } | 294 | } |
295 | |||
296 | struct ath_chanctx *ath_chanctx_get_oper_chan(struct ath_softc *sc) | ||
297 | { | ||
298 | u8 i; | ||
299 | |||
300 | for (i = 0; i < ARRAY_SIZE(sc->chanctx); i++) { | ||
301 | if (!list_empty(&sc->chanctx[i].vifs)) | ||
302 | return &sc->chanctx[i]; | ||
303 | } | ||
304 | |||
305 | return &sc->chanctx[0]; | ||
306 | } | ||
307 | |||
308 | void ath_chanctx_offchan_switch(struct ath_softc *sc, | ||
309 | struct ieee80211_channel *chan) | ||
310 | { | ||
311 | struct cfg80211_chan_def chandef; | ||
312 | |||
313 | cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT); | ||
314 | |||
315 | ath_chanctx_switch(sc, &sc->offchannel.chan, &chandef); | ||
316 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 8bd3e422b82b..9f5e1e4931af 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -61,7 +61,7 @@ static int ath9k_ps_enable; | |||
61 | module_param_named(ps_enable, ath9k_ps_enable, int, 0444); | 61 | module_param_named(ps_enable, ath9k_ps_enable, int, 0444); |
62 | MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave"); | 62 | MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave"); |
63 | 63 | ||
64 | static int ath9k_use_chanctx; | 64 | int ath9k_use_chanctx; |
65 | module_param_named(use_chanctx, ath9k_use_chanctx, int, 0444); | 65 | module_param_named(use_chanctx, ath9k_use_chanctx, int, 0444); |
66 | MODULE_PARM_DESC(use_chanctx, "Enable channel context for concurrency"); | 66 | MODULE_PARM_DESC(use_chanctx, "Enable channel context for concurrency"); |
67 | 67 | ||
@@ -566,6 +566,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
566 | INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); | 566 | INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); |
567 | INIT_WORK(&sc->chanctx_work, ath_chanctx_work); | 567 | INIT_WORK(&sc->chanctx_work, ath_chanctx_work); |
568 | INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); | 568 | INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); |
569 | setup_timer(&sc->offchannel.timer, ath_offchannel_timer, | ||
570 | (unsigned long)sc); | ||
569 | 571 | ||
570 | /* | 572 | /* |
571 | * Cache line size is used to size and align various | 573 | * Cache line size is used to size and align various |
@@ -745,8 +747,11 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
745 | if (!ath9k_use_chanctx) { | 747 | if (!ath9k_use_chanctx) { |
746 | hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); | 748 | hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); |
747 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_WDS); | 749 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_WDS); |
748 | } else | 750 | } else { |
749 | hw->wiphy->n_iface_combinations = 1; | 751 | hw->wiphy->n_iface_combinations = 1; |
752 | hw->wiphy->max_scan_ssids = 255; | ||
753 | hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; | ||
754 | } | ||
750 | } | 755 | } |
751 | 756 | ||
752 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 757 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index d8a4510f963a..5da62ef1fc26 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -2159,6 +2159,193 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) | |||
2159 | clear_bit(ATH_OP_SCANNING, &common->op_flags); | 2159 | clear_bit(ATH_OP_SCANNING, &common->op_flags); |
2160 | } | 2160 | } |
2161 | 2161 | ||
2162 | static void | ||
2163 | ath_scan_next_channel(struct ath_softc *sc) | ||
2164 | { | ||
2165 | struct cfg80211_scan_request *req = sc->offchannel.scan_req; | ||
2166 | struct ieee80211_channel *chan; | ||
2167 | |||
2168 | if (sc->offchannel.scan_idx >= req->n_channels) { | ||
2169 | sc->offchannel.state = ATH_OFFCHANNEL_IDLE; | ||
2170 | ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc), NULL); | ||
2171 | return; | ||
2172 | } | ||
2173 | |||
2174 | chan = req->channels[sc->offchannel.scan_idx++]; | ||
2175 | sc->offchannel.state = ATH_OFFCHANNEL_PROBE_SEND; | ||
2176 | ath_chanctx_offchan_switch(sc, chan); | ||
2177 | } | ||
2178 | |||
2179 | static void ath_scan_complete(struct ath_softc *sc, bool abort) | ||
2180 | { | ||
2181 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
2182 | |||
2183 | ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc), NULL); | ||
2184 | sc->offchannel.scan_req = NULL; | ||
2185 | sc->offchannel.scan_vif = NULL; | ||
2186 | sc->offchannel.state = ATH_OFFCHANNEL_IDLE; | ||
2187 | ieee80211_scan_completed(sc->hw, abort); | ||
2188 | clear_bit(ATH_OP_SCANNING, &common->op_flags); | ||
2189 | ath9k_ps_restore(sc); | ||
2190 | |||
2191 | if (!sc->ps_idle) | ||
2192 | return; | ||
2193 | |||
2194 | ath_cancel_work(sc); | ||
2195 | } | ||
2196 | |||
2197 | static void ath_scan_send_probe(struct ath_softc *sc, | ||
2198 | struct cfg80211_ssid *ssid) | ||
2199 | { | ||
2200 | struct cfg80211_scan_request *req = sc->offchannel.scan_req; | ||
2201 | struct ieee80211_vif *vif = sc->offchannel.scan_vif; | ||
2202 | struct ath_tx_control txctl = {}; | ||
2203 | struct sk_buff *skb; | ||
2204 | struct ieee80211_tx_info *info; | ||
2205 | int band = sc->offchannel.chan.chandef.chan->band; | ||
2206 | |||
2207 | skb = ieee80211_probereq_get(sc->hw, vif, | ||
2208 | ssid->ssid, ssid->ssid_len, req->ie_len); | ||
2209 | if (!skb) | ||
2210 | return; | ||
2211 | |||
2212 | info = IEEE80211_SKB_CB(skb); | ||
2213 | if (req->no_cck) | ||
2214 | info->flags |= IEEE80211_TX_CTL_NO_CCK_RATE; | ||
2215 | |||
2216 | if (req->ie_len) | ||
2217 | memcpy(skb_put(skb, req->ie_len), req->ie, req->ie_len); | ||
2218 | |||
2219 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); | ||
2220 | |||
2221 | if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, NULL)) | ||
2222 | goto error; | ||
2223 | |||
2224 | txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; | ||
2225 | txctl.force_channel = true; | ||
2226 | if (ath_tx_start(sc->hw, skb, &txctl)) | ||
2227 | goto error; | ||
2228 | |||
2229 | return; | ||
2230 | |||
2231 | error: | ||
2232 | ieee80211_free_txskb(sc->hw, skb); | ||
2233 | } | ||
2234 | |||
2235 | static void ath_scan_channel_start(struct ath_softc *sc) | ||
2236 | { | ||
2237 | struct cfg80211_scan_request *req = sc->offchannel.scan_req; | ||
2238 | int i, dwell; | ||
2239 | |||
2240 | if ((sc->cur_chan->chandef.chan->flags & IEEE80211_CHAN_NO_IR) || | ||
2241 | !req->n_ssids) { | ||
2242 | dwell = HZ / 9; /* ~110 ms */ | ||
2243 | } else { | ||
2244 | dwell = HZ / 16; /* ~60 ms */ | ||
2245 | |||
2246 | for (i = 0; i < req->n_ssids; i++) | ||
2247 | ath_scan_send_probe(sc, &req->ssids[i]); | ||
2248 | } | ||
2249 | |||
2250 | sc->offchannel.state = ATH_OFFCHANNEL_PROBE_WAIT; | ||
2251 | mod_timer(&sc->offchannel.timer, jiffies + dwell); | ||
2252 | } | ||
2253 | |||
2254 | void ath_offchannel_channel_change(struct ath_softc *sc) | ||
2255 | { | ||
2256 | if (!sc->offchannel.scan_req) | ||
2257 | return; | ||
2258 | |||
2259 | switch (sc->offchannel.state) { | ||
2260 | case ATH_OFFCHANNEL_PROBE_SEND: | ||
2261 | if (sc->cur_chan->chandef.chan != | ||
2262 | sc->offchannel.chan.chandef.chan) | ||
2263 | return; | ||
2264 | |||
2265 | ath_scan_channel_start(sc); | ||
2266 | break; | ||
2267 | case ATH_OFFCHANNEL_IDLE: | ||
2268 | ath_scan_complete(sc, false); | ||
2269 | break; | ||
2270 | default: | ||
2271 | break; | ||
2272 | } | ||
2273 | } | ||
2274 | |||
2275 | void ath_offchannel_timer(unsigned long data) | ||
2276 | { | ||
2277 | struct ath_softc *sc = (struct ath_softc *)data; | ||
2278 | struct ath_chanctx *ctx = ath_chanctx_get_oper_chan(sc); | ||
2279 | |||
2280 | if (!sc->offchannel.scan_req) | ||
2281 | return; | ||
2282 | |||
2283 | switch (sc->offchannel.state) { | ||
2284 | case ATH_OFFCHANNEL_PROBE_WAIT: | ||
2285 | if (ctx->active) { | ||
2286 | sc->offchannel.state = ATH_OFFCHANNEL_SUSPEND; | ||
2287 | ath_chanctx_switch(sc, ctx, NULL); | ||
2288 | mod_timer(&sc->offchannel.timer, jiffies + HZ / 10); | ||
2289 | break; | ||
2290 | } | ||
2291 | /* fall through */ | ||
2292 | case ATH_OFFCHANNEL_SUSPEND: | ||
2293 | ath_scan_next_channel(sc); | ||
2294 | break; | ||
2295 | default: | ||
2296 | break; | ||
2297 | } | ||
2298 | } | ||
2299 | |||
2300 | static int ath9k_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
2301 | struct cfg80211_scan_request *req) | ||
2302 | { | ||
2303 | struct ath_softc *sc = hw->priv; | ||
2304 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
2305 | int ret = 0; | ||
2306 | |||
2307 | mutex_lock(&sc->mutex); | ||
2308 | |||
2309 | if (WARN_ON(sc->offchannel.scan_req)) { | ||
2310 | ret = -EBUSY; | ||
2311 | goto out; | ||
2312 | } | ||
2313 | |||
2314 | ath9k_ps_wakeup(sc); | ||
2315 | set_bit(ATH_OP_SCANNING, &common->op_flags); | ||
2316 | sc->offchannel.scan_vif = vif; | ||
2317 | sc->offchannel.scan_req = req; | ||
2318 | sc->offchannel.scan_idx = 0; | ||
2319 | sc->offchannel.chan.txpower = vif->bss_conf.txpower; | ||
2320 | |||
2321 | ath_scan_next_channel(sc); | ||
2322 | |||
2323 | out: | ||
2324 | mutex_unlock(&sc->mutex); | ||
2325 | |||
2326 | return ret; | ||
2327 | } | ||
2328 | |||
2329 | static void ath9k_cancel_hw_scan(struct ieee80211_hw *hw, | ||
2330 | struct ieee80211_vif *vif) | ||
2331 | { | ||
2332 | struct ath_softc *sc = hw->priv; | ||
2333 | |||
2334 | mutex_lock(&sc->mutex); | ||
2335 | del_timer_sync(&sc->offchannel.timer); | ||
2336 | ath_scan_complete(sc, true); | ||
2337 | mutex_unlock(&sc->mutex); | ||
2338 | } | ||
2339 | |||
2340 | void ath9k_fill_chanctx_ops(void) | ||
2341 | { | ||
2342 | if (!ath9k_use_chanctx) | ||
2343 | return; | ||
2344 | |||
2345 | ath9k_ops.hw_scan = ath9k_hw_scan; | ||
2346 | ath9k_ops.cancel_hw_scan = ath9k_cancel_hw_scan; | ||
2347 | } | ||
2348 | |||
2162 | struct ieee80211_ops ath9k_ops = { | 2349 | struct ieee80211_ops ath9k_ops = { |
2163 | .tx = ath9k_tx, | 2350 | .tx = ath9k_tx, |
2164 | .start = ath9k_start, | 2351 | .start = ath9k_start, |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 4dec09e565ed..7a2b2c5caced 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -843,6 +843,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
843 | return -ENODEV; | 843 | return -ENODEV; |
844 | } | 844 | } |
845 | 845 | ||
846 | ath9k_fill_chanctx_ops(); | ||
846 | hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops); | 847 | hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops); |
847 | if (!hw) { | 848 | if (!hw) { |
848 | dev_err(&pdev->dev, "No memory for ieee80211_hw\n"); | 849 | dev_err(&pdev->dev, "No memory for ieee80211_hw\n"); |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index de5684a33dd7..fec9e0b42f5d 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -374,6 +374,7 @@ void ath_rx_cleanup(struct ath_softc *sc) | |||
374 | 374 | ||
375 | u32 ath_calcrxfilter(struct ath_softc *sc) | 375 | u32 ath_calcrxfilter(struct ath_softc *sc) |
376 | { | 376 | { |
377 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
377 | u32 rfilt; | 378 | u32 rfilt; |
378 | 379 | ||
379 | if (config_enabled(CONFIG_ATH9K_TX99)) | 380 | if (config_enabled(CONFIG_ATH9K_TX99)) |
@@ -424,6 +425,10 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
424 | if (AR_SREV_9550(sc->sc_ah) || AR_SREV_9531(sc->sc_ah)) | 425 | if (AR_SREV_9550(sc->sc_ah) || AR_SREV_9531(sc->sc_ah)) |
425 | rfilt |= ATH9K_RX_FILTER_4ADDRESS; | 426 | rfilt |= ATH9K_RX_FILTER_4ADDRESS; |
426 | 427 | ||
428 | if (ath9k_use_chanctx && | ||
429 | test_bit(ATH_OP_SCANNING, &common->op_flags)) | ||
430 | rfilt |= ATH9K_RX_FILTER_BEACON; | ||
431 | |||
427 | return rfilt; | 432 | return rfilt; |
428 | 433 | ||
429 | } | 434 | } |