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

ath9k: Implement channel context ops

Add channel context operations (add, remove, change, assign and
unassign) to enable support for multiple channels.

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>

authored by

Felix Fietkau and committed by
John W. Linville
39305635 405393cf

+102 -12
+7
drivers/net/wireless/ath/ath9k/ath9k.h
··· 331 331 bool offchannel; 332 332 bool stopped; 333 333 bool active; 334 + bool assigned; 334 335 }; 335 336 336 337 enum ath_offchannel_state { ··· 357 356 }; 358 357 359 358 void ath9k_fill_chanctx_ops(void); 359 + static inline struct ath_chanctx * 360 + ath_chanctx_get(struct ieee80211_chanctx_conf *ctx) 361 + { 362 + struct ath_chanctx **ptr = (void *) ctx->drv_priv; 363 + return *ptr; 364 + } 360 365 void ath_chanctx_init(struct ath_softc *sc); 361 366 void ath_chanctx_set_channel(struct ath_softc *sc, struct ath_chanctx *ctx, 362 367 struct cfg80211_chan_def *chandef);
+1
drivers/net/wireless/ath/ath9k/init.c
··· 752 752 hw->wiphy->max_scan_ssids = 255; 753 753 hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; 754 754 hw->wiphy->max_remain_on_channel_duration = 10000; 755 + hw->chanctx_data_size = sizeof(void *); 755 756 } 756 757 } 757 758
+93 -11
drivers/net/wireless/ath/ath9k/main.c
··· 624 624 struct ath_softc *sc = hw->priv; 625 625 struct ath_hw *ah = sc->sc_ah; 626 626 struct ath_common *common = ath9k_hw_common(ah); 627 - struct ieee80211_channel *curchan = hw->conf.chandef.chan; 627 + struct ieee80211_channel *curchan = sc->cur_chan->chandef.chan; 628 628 struct ath_chanctx *ctx = sc->cur_chan; 629 629 struct ath9k_channel *init_channel; 630 630 int r; ··· 1039 1039 ath9k_beacon_assign_slot(sc, vif); 1040 1040 1041 1041 avp->vif = vif; 1042 - 1043 - /* XXX - will be removed once chanctx ops are added */ 1044 - avp->chanctx = sc->cur_chan; 1045 - list_add_tail(&avp->list, &sc->cur_chan->vifs); 1046 - ath_chanctx_check_active(sc, avp->chanctx); 1042 + if (!ath9k_use_chanctx) 1043 + avp->chanctx = sc->cur_chan; 1047 1044 1048 1045 an->sc = sc; 1049 1046 an->sta = NULL; ··· 1129 1132 } 1130 1133 spin_unlock_bh(&sc->sc_pcu_lock); 1131 1134 1132 - list_del(&avp->list); 1133 1135 sc->nvifs--; 1134 1136 sc->tx99_vif = NULL; 1135 1137 ··· 1140 1144 ath9k_ps_restore(sc); 1141 1145 1142 1146 ath_tx_node_cleanup(sc, &avp->mcast_node); 1143 - ath_chanctx_check_active(sc, avp->chanctx); 1144 1147 1145 1148 mutex_unlock(&sc->mutex); 1146 1149 } ··· 1266 1271 struct ath_common *common = ath9k_hw_common(ah); 1267 1272 struct ieee80211_conf *conf = &hw->conf; 1268 1273 struct ath_chanctx *ctx = sc->cur_chan; 1269 - bool reset_channel = false; 1270 1274 1271 1275 ath9k_ps_wakeup(sc); 1272 1276 mutex_lock(&sc->mutex); ··· 1281 1287 * The chip needs a reset to properly wake up from 1282 1288 * full sleep 1283 1289 */ 1284 - reset_channel = ah->chip_fullsleep; 1290 + ath_chanctx_set_channel(sc, ctx, &ctx->chandef); 1285 1291 } 1286 1292 } 1287 1293 ··· 1311 1317 } 1312 1318 } 1313 1319 1314 - if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) { 1320 + if (!ath9k_use_chanctx && (changed & IEEE80211_CONF_CHANGE_CHANNEL)) { 1315 1321 ctx->offchannel = !!(conf->flags & IEEE80211_CONF_OFFCHANNEL); 1316 1322 ath_chanctx_set_channel(sc, ctx, &hw->conf.chandef); 1317 1323 } ··· 2427 2433 return 0; 2428 2434 } 2429 2435 2436 + static int ath9k_add_chanctx(struct ieee80211_hw *hw, 2437 + struct ieee80211_chanctx_conf *conf) 2438 + { 2439 + struct ath_softc *sc = hw->priv; 2440 + struct ath_chanctx *ctx, **ptr; 2441 + int i; 2442 + 2443 + mutex_lock(&sc->mutex); 2444 + for (i = 0; i < ATH9K_NUM_CHANCTX; i++) { 2445 + if (!sc->chanctx[i].assigned) 2446 + break; 2447 + } 2448 + if (i == ATH9K_NUM_CHANCTX) { 2449 + mutex_unlock(&sc->mutex); 2450 + return -ENOSPC; 2451 + } 2452 + 2453 + ctx = &sc->chanctx[i]; 2454 + ptr = (void *) conf->drv_priv; 2455 + *ptr = ctx; 2456 + ctx->assigned = true; 2457 + ath_chanctx_set_channel(sc, ctx, &conf->def); 2458 + mutex_unlock(&sc->mutex); 2459 + 2460 + return 0; 2461 + } 2462 + 2463 + 2464 + static void ath9k_remove_chanctx(struct ieee80211_hw *hw, 2465 + struct ieee80211_chanctx_conf *conf) 2466 + { 2467 + struct ath_softc *sc = hw->priv; 2468 + struct ath_chanctx *ctx = ath_chanctx_get(conf); 2469 + 2470 + mutex_lock(&sc->mutex); 2471 + ctx->assigned = false; 2472 + mutex_unlock(&sc->mutex); 2473 + } 2474 + 2475 + static void ath9k_change_chanctx(struct ieee80211_hw *hw, 2476 + struct ieee80211_chanctx_conf *conf, 2477 + u32 changed) 2478 + { 2479 + struct ath_softc *sc = hw->priv; 2480 + struct ath_chanctx *ctx = ath_chanctx_get(conf); 2481 + 2482 + mutex_lock(&sc->mutex); 2483 + ath_chanctx_set_channel(sc, ctx, &conf->def); 2484 + mutex_unlock(&sc->mutex); 2485 + } 2486 + 2487 + static int ath9k_assign_vif_chanctx(struct ieee80211_hw *hw, 2488 + struct ieee80211_vif *vif, 2489 + struct ieee80211_chanctx_conf *conf) 2490 + { 2491 + struct ath_softc *sc = hw->priv; 2492 + struct ath_vif *avp = (void *)vif->drv_priv; 2493 + struct ath_chanctx *ctx = ath_chanctx_get(conf); 2494 + 2495 + mutex_lock(&sc->mutex); 2496 + avp->chanctx = ctx; 2497 + list_add_tail(&avp->list, &ctx->vifs); 2498 + ath_chanctx_check_active(sc, ctx); 2499 + mutex_unlock(&sc->mutex); 2500 + 2501 + return 0; 2502 + } 2503 + 2504 + static void ath9k_unassign_vif_chanctx(struct ieee80211_hw *hw, 2505 + struct ieee80211_vif *vif, 2506 + struct ieee80211_chanctx_conf *conf) 2507 + { 2508 + struct ath_softc *sc = hw->priv; 2509 + struct ath_vif *avp = (void *)vif->drv_priv; 2510 + struct ath_chanctx *ctx = ath_chanctx_get(conf); 2511 + 2512 + mutex_lock(&sc->mutex); 2513 + avp->chanctx = NULL; 2514 + list_del(&avp->list); 2515 + ath_chanctx_check_active(sc, ctx); 2516 + mutex_unlock(&sc->mutex); 2517 + } 2518 + 2430 2519 void ath9k_fill_chanctx_ops(void) 2431 2520 { 2432 2521 if (!ath9k_use_chanctx) ··· 2519 2442 ath9k_ops.cancel_hw_scan = ath9k_cancel_hw_scan; 2520 2443 ath9k_ops.remain_on_channel = ath9k_remain_on_channel; 2521 2444 ath9k_ops.cancel_remain_on_channel = ath9k_cancel_remain_on_channel; 2445 + ath9k_ops.add_chanctx = ath9k_add_chanctx; 2446 + ath9k_ops.remove_chanctx = ath9k_remove_chanctx; 2447 + ath9k_ops.change_chanctx = ath9k_change_chanctx; 2448 + ath9k_ops.assign_vif_chanctx = ath9k_assign_vif_chanctx; 2449 + ath9k_ops.unassign_vif_chanctx = ath9k_unassign_vif_chanctx; 2522 2450 } 2523 2451 2524 2452 struct ieee80211_ops ath9k_ops = {
+1 -1
drivers/net/wireless/ath/ath9k/tx99.c
··· 76 76 tx_info = IEEE80211_SKB_CB(skb); 77 77 memset(tx_info, 0, sizeof(*tx_info)); 78 78 rate = &tx_info->control.rates[0]; 79 - tx_info->band = hw->conf.chandef.chan->band; 79 + tx_info->band = sc->cur_chan->chandef.chan->band; 80 80 tx_info->flags = IEEE80211_TX_CTL_NO_ACK; 81 81 tx_info->control.vif = sc->tx99_vif; 82 82 rate->count = 1;