diff options
| -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 | } |
