Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ath9k: Fetch appropriate operating channel context

Retrieve appropriate operating channel context while switching
between operating and off channels.

Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Rajkumar Manoharan and committed by
John W. Linville
c4dc0d04 39305635

+34 -24
+6 -1
drivers/net/wireless/ath/ath9k/ath9k.h
··· 355 355 struct ieee80211_vif *roc_vif; 356 356 int roc_duration; 357 357 }; 358 + #define ath_for_each_chanctx(_sc, _ctx) \ 359 + for (ctx = &sc->chanctx[0]; \ 360 + ctx <= &sc->chanctx[ARRAY_SIZE(sc->chanctx) - 1]; \ 361 + ctx++) 358 362 359 363 void ath9k_fill_chanctx_ops(void); 360 364 static inline struct ath_chanctx * ··· 377 373 void ath_offchannel_channel_change(struct ath_softc *sc); 378 374 void ath_chanctx_offchan_switch(struct ath_softc *sc, 379 375 struct ieee80211_channel *chan); 380 - struct ath_chanctx *ath_chanctx_get_oper_chan(struct ath_softc *sc); 376 + struct ath_chanctx *ath_chanctx_get_oper_chan(struct ath_softc *sc, 377 + bool active); 381 378 382 379 int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan); 383 380 int ath_startrecv(struct ath_softc *sc);
+9 -5
drivers/net/wireless/ath/ath9k/channel.c
··· 293 293 ath_set_channel(sc); 294 294 } 295 295 296 - struct ath_chanctx *ath_chanctx_get_oper_chan(struct ath_softc *sc) 296 + struct ath_chanctx *ath_chanctx_get_oper_chan(struct ath_softc *sc, bool active) 297 297 { 298 - u8 i; 298 + struct ath_chanctx *ctx; 299 299 300 - for (i = 0; i < ARRAY_SIZE(sc->chanctx); i++) { 301 - if (!list_empty(&sc->chanctx[i].vifs)) 302 - return &sc->chanctx[i]; 300 + ath_for_each_chanctx(sc, ctx) { 301 + if (!ctx->assigned || list_empty(&ctx->vifs)) 302 + continue; 303 + if (active && !ctx->active) 304 + continue; 305 + 306 + return ctx; 303 307 } 304 308 305 309 return &sc->chanctx[0];
+19 -18
drivers/net/wireless/ath/ath9k/main.c
··· 2161 2161 2162 2162 if (sc->offchannel.scan_idx >= req->n_channels) { 2163 2163 sc->offchannel.state = ATH_OFFCHANNEL_IDLE; 2164 - ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc), NULL); 2164 + ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc, false), 2165 + NULL); 2165 2166 return; 2166 2167 } 2167 2168 ··· 2185 2184 sc->offchannel.state = ATH_OFFCHANNEL_ROC_START; 2186 2185 ath_chanctx_offchan_switch(sc, sc->offchannel.roc_chan); 2187 2186 } else { 2188 - ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc), NULL); 2187 + ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc, false), 2188 + NULL); 2189 2189 sc->offchannel.state = ATH_OFFCHANNEL_IDLE; 2190 2190 if (sc->ps_idle) 2191 2191 ath_cancel_work(sc); ··· 2312 2310 void ath_offchannel_timer(unsigned long data) 2313 2311 { 2314 2312 struct ath_softc *sc = (struct ath_softc *)data; 2315 - struct ath_chanctx *ctx = ath_chanctx_get_oper_chan(sc); 2313 + struct ath_chanctx *ctx; 2316 2314 2317 2315 switch (sc->offchannel.state) { 2318 2316 case ATH_OFFCHANNEL_PROBE_WAIT: 2319 2317 if (!sc->offchannel.scan_req) 2320 2318 return; 2321 2319 2320 + /* get first active channel context */ 2321 + ctx = ath_chanctx_get_oper_chan(sc, true); 2322 2322 if (ctx->active) { 2323 2323 sc->offchannel.state = ATH_OFFCHANNEL_SUSPEND; 2324 2324 ath_chanctx_switch(sc, ctx, NULL); ··· 2336 2332 break; 2337 2333 case ATH_OFFCHANNEL_ROC_START: 2338 2334 case ATH_OFFCHANNEL_ROC_WAIT: 2335 + ctx = ath_chanctx_get_oper_chan(sc, false); 2339 2336 sc->offchannel.state = ATH_OFFCHANNEL_ROC_DONE; 2340 2337 ath_chanctx_switch(sc, ctx, NULL); 2341 2338 break; ··· 2437 2432 { 2438 2433 struct ath_softc *sc = hw->priv; 2439 2434 struct ath_chanctx *ctx, **ptr; 2440 - int i; 2441 2435 2442 2436 mutex_lock(&sc->mutex); 2443 - for (i = 0; i < ATH9K_NUM_CHANCTX; i++) { 2444 - if (!sc->chanctx[i].assigned) 2445 - break; 2446 - } 2447 - if (i == ATH9K_NUM_CHANCTX) { 2437 + 2438 + ath_for_each_chanctx(sc, ctx) { 2439 + if (ctx->assigned) 2440 + continue; 2441 + 2442 + ptr = (void *) conf->drv_priv; 2443 + *ptr = ctx; 2444 + ctx->assigned = true; 2445 + ath_chanctx_set_channel(sc, ctx, &conf->def); 2448 2446 mutex_unlock(&sc->mutex); 2449 - return -ENOSPC; 2447 + return 0; 2450 2448 } 2451 - 2452 - ctx = &sc->chanctx[i]; 2453 - ptr = (void *) conf->drv_priv; 2454 - *ptr = ctx; 2455 - ctx->assigned = true; 2456 - ath_chanctx_set_channel(sc, ctx, &conf->def); 2457 2449 mutex_unlock(&sc->mutex); 2458 - 2459 - return 0; 2450 + return -ENOSPC; 2460 2451 } 2461 2452 2462 2453