ath10k: fix channel switching
In the midst of chanctx patch review channel switching became broken which I failed to notice until now. Function ath10k_mac_vif_chan() reports current chandef which isn't updated until after switch_vif_chanctx() is returned from. Consequently the driver just restarted operation on channels it was residing already instead of switching to the new ones. Fixes: 500ff9f9389d ("ath10k: implement chanctx API") Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
This commit is contained in:
parent
089ab7a5af
commit
0e6eb417fc
@ -3949,83 +3949,6 @@ static int ath10k_config_ps(struct ath10k *ar)
|
|||||||
return ret;
|
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)
|
static int ath10k_mac_txpower_setup(struct ath10k *ar, int txpower)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -6365,6 +6288,7 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
|
|||||||
{
|
{
|
||||||
struct ath10k *ar = hw->priv;
|
struct ath10k *ar = hw->priv;
|
||||||
struct ath10k_vif *arvif;
|
struct ath10k_vif *arvif;
|
||||||
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
mutex_lock(&ar->conf_mutex);
|
mutex_lock(&ar->conf_mutex);
|
||||||
@ -6373,7 +6297,12 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
|
|||||||
"mac chanctx switch n_vifs %d mode %d\n",
|
"mac chanctx switch n_vifs %d mode %d\n",
|
||||||
n_vifs, mode);
|
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++) {
|
for (i = 0; i < n_vifs; i++) {
|
||||||
arvif = ath10k_vif_to_arvif(vifs[i].vif);
|
arvif = ath10k_vif_to_arvif(vifs[i].vif);
|
||||||
|
|
||||||
@ -6384,12 +6313,65 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
|
|||||||
vifs[i].new_ctx->def.chan->center_freq,
|
vifs[i].new_ctx->def.chan->center_freq,
|
||||||
vifs[i].old_ctx->def.width,
|
vifs[i].old_ctx->def.width,
|
||||||
vifs[i].new_ctx->def.width);
|
vifs[i].new_ctx->def.width);
|
||||||
|
|
||||||
|
if (WARN_ON(!arvif->is_started))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (WARN_ON(!arvif->is_up))
|
||||||
|
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 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);
|
ath10k_mac_update_rx_channel(ar, NULL, vifs, n_vifs);
|
||||||
spin_unlock_bh(&ar->data_lock);
|
spin_unlock_bh(&ar->data_lock);
|
||||||
|
|
||||||
/* FIXME: Reconfigure only affected vifs */
|
for (i = 0; i < n_vifs; i++) {
|
||||||
ath10k_mac_chan_reconfigure(ar);
|
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);
|
mutex_unlock(&ar->conf_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user