diff options
author | David S. Miller <davem@davemloft.net> | 2015-06-23 01:03:18 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-06-23 01:03:18 -0700 |
commit | fa433354f042105fc7a299253f904bb48dae0950 (patch) | |
tree | 7dc747d4f994713699a37080b0774f8315a1e1ef /drivers/net/wireless/ath/ath10k/mac.c | |
parent | 10ea5165e44ec8467e393a84ecfbf5732605d504 (diff) | |
parent | 40b503c76481aecf811a29a14a80c13b429b5e14 (diff) | |
download | blackbird-op-linux-fa433354f042105fc7a299253f904bb48dae0950.tar.gz blackbird-op-linux-fa433354f042105fc7a299253f904bb48dae0950.zip |
Merge tag 'wireless-drivers-next-for-davem-2015-06-18' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next
Kalle Valo says:
====================
Major changes:
mwifiex:
* enhancements for AP mode: support verbose information in station
dump command and also information about AP link.
* enable power save by default
brcmfmac:
* fix module reload issue for PCIe
* improving msgbuf protocol for PCIe devices
* rework .get_station() cfg80211 callback operation
* determine interface combinations upon device feature support
ath9k:
* ath9k_htc: add support of channel switch
wil6210:
* add modparam for bcast ring size
* support hidden SSID
* add per-MCS Rx stats
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/mac.c')
-rw-r--r-- | drivers/net/wireless/ath/ath10k/mac.c | 211 |
1 files changed, 82 insertions, 129 deletions
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 609ca8619ebd..218b6af63447 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3949,83 +3949,6 @@ static int ath10k_config_ps(struct ath10k *ar) return ret; } -static void ath10k_mac_chan_reconfigure(struct ath10k *ar) -{ - struct ath10k_vif *arvif; - struct cfg80211_chan_def def; - int ret; - - lockdep_assert_held(&ar->conf_mutex); - - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac chan reconfigure\n"); - - /* First stop monitor interface. Some FW versions crash if there's a - * lone monitor interface. */ - if (ar->monitor_started) - ath10k_monitor_stop(ar); - - list_for_each_entry(arvif, &ar->arvifs, list) { - if (!arvif->is_started) - continue; - - if (!arvif->is_up) - continue; - - if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) - continue; - - ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); - if (ret) { - ath10k_warn(ar, "failed to down vdev %d: %d\n", - arvif->vdev_id, ret); - continue; - } - } - - /* all vdevs are downed now - attempt to restart and re-up them */ - - list_for_each_entry(arvif, &ar->arvifs, list) { - if (!arvif->is_started) - continue; - - if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) - continue; - - ret = ath10k_mac_setup_bcn_tmpl(arvif); - if (ret) - ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n", - ret); - - ret = ath10k_mac_setup_prb_tmpl(arvif); - if (ret) - ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n", - ret); - - if (WARN_ON(ath10k_mac_vif_chan(arvif->vif, &def))) - continue; - - ret = ath10k_vdev_restart(arvif, &def); - if (ret) { - ath10k_warn(ar, "failed to restart vdev %d: %d\n", - arvif->vdev_id, ret); - continue; - } - - if (!arvif->is_up) - continue; - - ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, - arvif->bssid); - if (ret) { - ath10k_warn(ar, "failed to bring vdev up %d: %d\n", - arvif->vdev_id, ret); - continue; - } - } - - ath10k_monitor_recalc(ar); -} - static int ath10k_mac_txpower_setup(struct ath10k *ar, int txpower) { int ret; @@ -6144,7 +6067,10 @@ static int ath10k_ampdu_action(struct ieee80211_hw *hw, } static void -ath10k_mac_update_rx_channel(struct ath10k *ar) +ath10k_mac_update_rx_channel(struct ath10k *ar, + struct ieee80211_chanctx_conf *ctx, + struct ieee80211_vif_chanctx_switch *vifs, + int n_vifs) { struct cfg80211_chan_def *def = NULL; @@ -6154,6 +6080,9 @@ ath10k_mac_update_rx_channel(struct ath10k *ar) lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->data_lock); + WARN_ON(ctx && vifs); + WARN_ON(vifs && n_vifs != 1); + /* FIXME: Sort of an optimization and a workaround. Peers and vifs are * on a linked list now. Doing a lookup peer -> vif -> chanctx for each * ppdu on Rx may reduce performance on low-end systems. It should be @@ -6165,36 +6094,28 @@ ath10k_mac_update_rx_channel(struct ath10k *ar) * affected much. */ rcu_read_lock(); - if (ath10k_mac_num_chanctxs(ar) == 1) { + if (!ctx && ath10k_mac_num_chanctxs(ar) == 1) { ieee80211_iter_chan_contexts_atomic(ar->hw, ath10k_mac_get_any_chandef_iter, &def); + + if (vifs) + def = &vifs[0].new_ctx->def; + ar->rx_channel = def->chan; + } else if (ctx && ath10k_mac_num_chanctxs(ar) == 0) { + ar->rx_channel = ctx->def.chan; } else { ar->rx_channel = NULL; } rcu_read_unlock(); } -static void -ath10k_mac_chan_ctx_init(struct ath10k *ar, - struct ath10k_chanctx *arctx, - struct ieee80211_chanctx_conf *conf) -{ - lockdep_assert_held(&ar->conf_mutex); - lockdep_assert_held(&ar->data_lock); - - memset(arctx, 0, sizeof(*arctx)); - - arctx->conf = *conf; -} - static int ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { struct ath10k *ar = hw->priv; - struct ath10k_chanctx *arctx = (void *)ctx->drv_priv; ath10k_dbg(ar, ATH10K_DBG_MAC, "mac chanctx add freq %hu width %d ptr %p\n", @@ -6203,8 +6124,7 @@ ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); spin_lock_bh(&ar->data_lock); - ath10k_mac_chan_ctx_init(ar, arctx, ctx); - ath10k_mac_update_rx_channel(ar); + ath10k_mac_update_rx_channel(ar, ctx, NULL, 0); spin_unlock_bh(&ar->data_lock); ath10k_recalc_radar_detection(ar); @@ -6228,7 +6148,7 @@ ath10k_mac_op_remove_chanctx(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); spin_lock_bh(&ar->data_lock); - ath10k_mac_update_rx_channel(ar); + ath10k_mac_update_rx_channel(ar, NULL, NULL, 0); spin_unlock_bh(&ar->data_lock); ath10k_recalc_radar_detection(ar); @@ -6243,16 +6163,12 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw, u32 changed) { struct ath10k *ar = hw->priv; - struct ath10k_chanctx *arctx = (void *)ctx->drv_priv; mutex_lock(&ar->conf_mutex); ath10k_dbg(ar, ATH10K_DBG_MAC, - "mac chanctx change freq %hu->%hu width %d->%d ptr %p changed %x\n", - arctx->conf.def.chan->center_freq, - ctx->def.chan->center_freq, - arctx->conf.def.width, ctx->def.width, - ctx, changed); + "mac chanctx change freq %hu width %d ptr %p changed %x\n", + ctx->def.chan->center_freq, ctx->def.width, ctx, changed); /* This shouldn't really happen because channel switching should use * switch_vif_chanctx(). @@ -6260,10 +6176,6 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw, if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL)) goto unlock; - spin_lock_bh(&ar->data_lock); - arctx->conf = *ctx; - spin_unlock_bh(&ar->data_lock); - ath10k_recalc_radar_detection(ar); /* FIXME: How to configure Rx chains properly? */ @@ -6283,7 +6195,6 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { struct ath10k *ar = hw->priv; - struct ath10k_chanctx *arctx = (void *)ctx->drv_priv; struct ath10k_vif *arvif = (void *)vif->drv_priv; int ret; @@ -6298,11 +6209,11 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, return -EBUSY; } - ret = ath10k_vdev_start(arvif, &arctx->conf.def); + ret = ath10k_vdev_start(arvif, &ctx->def); if (ret) { ath10k_warn(ar, "failed to start vdev %i addr %pM on freq %d: %d\n", arvif->vdev_id, vif->addr, - arctx->conf.def.chan->center_freq, ret); + ctx->def.chan->center_freq, ret); goto err; } @@ -6377,7 +6288,7 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw, { struct ath10k *ar = hw->priv; struct ath10k_vif *arvif; - struct ath10k_chanctx *arctx_new, *arctx_old; + int ret; int i; mutex_lock(&ar->conf_mutex); @@ -6386,38 +6297,81 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw, "mac chanctx switch n_vifs %d mode %d\n", n_vifs, mode); - spin_lock_bh(&ar->data_lock); + /* First stop monitor interface. Some FW versions crash if there's a + * lone monitor interface. + */ + if (ar->monitor_started) + ath10k_monitor_stop(ar); + for (i = 0; i < n_vifs; i++) { arvif = ath10k_vif_to_arvif(vifs[i].vif); - arctx_new = (void *)vifs[i].new_ctx->drv_priv; - arctx_old = (void *)vifs[i].old_ctx->drv_priv; ath10k_dbg(ar, ATH10K_DBG_MAC, - "mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d ptr %p->%p\n", + "mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d\n", arvif->vdev_id, vifs[i].old_ctx->def.chan->center_freq, vifs[i].new_ctx->def.chan->center_freq, vifs[i].old_ctx->def.width, - vifs[i].new_ctx->def.width, - arctx_old, arctx_new); + vifs[i].new_ctx->def.width); - if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS) { - ath10k_mac_chan_ctx_init(ar, arctx_new, - vifs[i].new_ctx); - } + if (WARN_ON(!arvif->is_started)) + continue; - arctx_new->conf = *vifs[i].new_ctx; + if (WARN_ON(!arvif->is_up)) + continue; - /* FIXME: ath10k_mac_chan_reconfigure() uses current, i.e. not - * yet updated chanctx_conf pointer. - */ - arctx_old->conf = *vifs[i].new_ctx; + ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); + if (ret) { + ath10k_warn(ar, "failed to down vdev %d: %d\n", + arvif->vdev_id, ret); + continue; + } } - ath10k_mac_update_rx_channel(ar); + + /* All relevant vdevs are downed and associated channel resources + * should be available for the channel switch now. + */ + + spin_lock_bh(&ar->data_lock); + ath10k_mac_update_rx_channel(ar, NULL, vifs, n_vifs); spin_unlock_bh(&ar->data_lock); - /* FIXME: Reconfigure only affected vifs */ - ath10k_mac_chan_reconfigure(ar); + for (i = 0; i < n_vifs; i++) { + arvif = ath10k_vif_to_arvif(vifs[i].vif); + + if (WARN_ON(!arvif->is_started)) + continue; + + if (WARN_ON(!arvif->is_up)) + continue; + + ret = ath10k_mac_setup_bcn_tmpl(arvif); + if (ret) + ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n", + ret); + + ret = ath10k_mac_setup_prb_tmpl(arvif); + if (ret) + ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n", + ret); + + ret = ath10k_vdev_restart(arvif, &vifs[i].new_ctx->def); + if (ret) { + ath10k_warn(ar, "failed to restart vdev %d: %d\n", + arvif->vdev_id, ret); + continue; + } + + ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, + arvif->bssid); + if (ret) { + ath10k_warn(ar, "failed to bring vdev up %d: %d\n", + arvif->vdev_id, ret); + continue; + } + } + + ath10k_monitor_recalc(ar); mutex_unlock(&ar->conf_mutex); return 0; @@ -6914,7 +6868,6 @@ int ath10k_mac_register(struct ath10k *ar) ar->hw->vif_data_size = sizeof(struct ath10k_vif); ar->hw->sta_data_size = sizeof(struct ath10k_sta); - ar->hw->chanctx_data_size = sizeof(struct ath10k_chanctx); ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL; |