Commit 548db54c authored by Michal Kazior's avatar Michal Kazior Committed by Kalle Valo

ath10k: improve locking

Add more lockdep asserts and a few conf_mutex
locks. It's better to be on the safe side.
Signed-off-by: default avatarMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent edb8236d
...@@ -43,6 +43,8 @@ static int ath10k_send_key(struct ath10k_vif *arvif, ...@@ -43,6 +43,8 @@ static int ath10k_send_key(struct ath10k_vif *arvif,
.macaddr = macaddr, .macaddr = macaddr,
}; };
lockdep_assert_held(&arvif->ar->conf_mutex);
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
arg.key_flags = WMI_KEY_PAIRWISE; arg.key_flags = WMI_KEY_PAIRWISE;
else else
...@@ -87,6 +89,8 @@ static int ath10k_install_key(struct ath10k_vif *arvif, ...@@ -87,6 +89,8 @@ static int ath10k_install_key(struct ath10k_vif *arvif,
struct ath10k *ar = arvif->ar; struct ath10k *ar = arvif->ar;
int ret; int ret;
lockdep_assert_held(&ar->conf_mutex);
INIT_COMPLETION(ar->install_key_done); INIT_COMPLETION(ar->install_key_done);
ret = ath10k_send_key(arvif, key, cmd, macaddr); ret = ath10k_send_key(arvif, key, cmd, macaddr);
...@@ -372,6 +376,8 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar) ...@@ -372,6 +376,8 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar)
{ {
int ret; int ret;
lockdep_assert_held(&ar->conf_mutex);
ret = wait_for_completion_timeout(&ar->vdev_setup_done, ret = wait_for_completion_timeout(&ar->vdev_setup_done,
ATH10K_VDEV_SETUP_TIMEOUT_HZ); ATH10K_VDEV_SETUP_TIMEOUT_HZ);
if (ret == 0) if (ret == 0)
...@@ -605,6 +611,8 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif, ...@@ -605,6 +611,8 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif,
{ {
int ret = 0; int ret = 0;
lockdep_assert_held(&arvif->ar->conf_mutex);
if (!info->enable_beacon) { if (!info->enable_beacon) {
ath10k_vdev_stop(arvif); ath10k_vdev_stop(arvif);
return; return;
...@@ -631,6 +639,8 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif, ...@@ -631,6 +639,8 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif,
{ {
int ret = 0; int ret = 0;
lockdep_assert_held(&arvif->ar->conf_mutex);
if (!info->ibss_joined) { if (!info->ibss_joined) {
ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id, self_peer); ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id, self_peer);
if (ret) if (ret)
...@@ -680,6 +690,8 @@ static void ath10k_ps_iter(void *data, u8 *mac, struct ieee80211_vif *vif) ...@@ -680,6 +690,8 @@ static void ath10k_ps_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
enum wmi_sta_ps_mode psmode; enum wmi_sta_ps_mode psmode;
int ret; int ret;
lockdep_assert_held(&arvif->ar->conf_mutex);
if (vif->type != NL80211_IFTYPE_STATION) if (vif->type != NL80211_IFTYPE_STATION)
return; return;
...@@ -722,6 +734,8 @@ static void ath10k_peer_assoc_h_basic(struct ath10k *ar, ...@@ -722,6 +734,8 @@ static void ath10k_peer_assoc_h_basic(struct ath10k *ar,
struct ieee80211_bss_conf *bss_conf, struct ieee80211_bss_conf *bss_conf,
struct wmi_peer_assoc_complete_arg *arg) struct wmi_peer_assoc_complete_arg *arg)
{ {
lockdep_assert_held(&ar->conf_mutex);
memcpy(arg->addr, sta->addr, ETH_ALEN); memcpy(arg->addr, sta->addr, ETH_ALEN);
arg->vdev_id = arvif->vdev_id; arg->vdev_id = arvif->vdev_id;
arg->peer_aid = sta->aid; arg->peer_aid = sta->aid;
...@@ -764,6 +778,8 @@ static void ath10k_peer_assoc_h_crypto(struct ath10k *ar, ...@@ -764,6 +778,8 @@ static void ath10k_peer_assoc_h_crypto(struct ath10k *ar,
const u8 *rsnie = NULL; const u8 *rsnie = NULL;
const u8 *wpaie = NULL; const u8 *wpaie = NULL;
lockdep_assert_held(&ar->conf_mutex);
bss = cfg80211_get_bss(ar->hw->wiphy, ar->hw->conf.chandef.chan, bss = cfg80211_get_bss(ar->hw->wiphy, ar->hw->conf.chandef.chan,
info->bssid, NULL, 0, 0, 0); info->bssid, NULL, 0, 0, 0);
if (bss) { if (bss) {
...@@ -804,6 +820,8 @@ static void ath10k_peer_assoc_h_rates(struct ath10k *ar, ...@@ -804,6 +820,8 @@ static void ath10k_peer_assoc_h_rates(struct ath10k *ar,
u32 ratemask; u32 ratemask;
int i; int i;
lockdep_assert_held(&ar->conf_mutex);
sband = ar->hw->wiphy->bands[ar->hw->conf.chandef.chan->band]; sband = ar->hw->wiphy->bands[ar->hw->conf.chandef.chan->band];
ratemask = sta->supp_rates[ar->hw->conf.chandef.chan->band]; ratemask = sta->supp_rates[ar->hw->conf.chandef.chan->band];
rates = sband->bitrates; rates = sband->bitrates;
...@@ -827,6 +845,8 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar, ...@@ -827,6 +845,8 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
int smps; int smps;
int i, n; int i, n;
lockdep_assert_held(&ar->conf_mutex);
if (!ht_cap->ht_supported) if (!ht_cap->ht_supported)
return; return;
...@@ -905,6 +925,8 @@ static void ath10k_peer_assoc_h_qos_ap(struct ath10k *ar, ...@@ -905,6 +925,8 @@ static void ath10k_peer_assoc_h_qos_ap(struct ath10k *ar,
u32 uapsd = 0; u32 uapsd = 0;
u32 max_sp = 0; u32 max_sp = 0;
lockdep_assert_held(&ar->conf_mutex);
if (sta->wme) if (sta->wme)
arg->peer_flags |= WMI_PEER_QOS; arg->peer_flags |= WMI_PEER_QOS;
...@@ -1056,6 +1078,8 @@ static int ath10k_peer_assoc(struct ath10k *ar, ...@@ -1056,6 +1078,8 @@ static int ath10k_peer_assoc(struct ath10k *ar,
{ {
struct wmi_peer_assoc_complete_arg arg; struct wmi_peer_assoc_complete_arg arg;
lockdep_assert_held(&ar->conf_mutex);
memset(&arg, 0, sizeof(struct wmi_peer_assoc_complete_arg)); memset(&arg, 0, sizeof(struct wmi_peer_assoc_complete_arg));
ath10k_peer_assoc_h_basic(ar, arvif, sta, bss_conf, &arg); ath10k_peer_assoc_h_basic(ar, arvif, sta, bss_conf, &arg);
...@@ -1079,6 +1103,8 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, ...@@ -1079,6 +1103,8 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
struct ieee80211_sta *ap_sta; struct ieee80211_sta *ap_sta;
int ret; int ret;
lockdep_assert_held(&ar->conf_mutex);
rcu_read_lock(); rcu_read_lock();
ap_sta = ieee80211_find_sta(vif, bss_conf->bssid); ap_sta = ieee80211_find_sta(vif, bss_conf->bssid);
...@@ -1119,6 +1145,8 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw, ...@@ -1119,6 +1145,8 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
int ret; int ret;
lockdep_assert_held(&ar->conf_mutex);
/* /*
* For some reason, calling VDEV-DOWN before VDEV-STOP * For some reason, calling VDEV-DOWN before VDEV-STOP
* makes the FW to send frames via HTT after disassociation. * makes the FW to send frames via HTT after disassociation.
...@@ -1152,6 +1180,8 @@ static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif, ...@@ -1152,6 +1180,8 @@ static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif,
{ {
int ret = 0; int ret = 0;
lockdep_assert_held(&ar->conf_mutex);
ret = ath10k_peer_assoc(ar, arvif, sta, NULL); ret = ath10k_peer_assoc(ar, arvif, sta, NULL);
if (ret) { if (ret) {
ath10k_warn("WMI peer assoc failed for %pM\n", sta->addr); ath10k_warn("WMI peer assoc failed for %pM\n", sta->addr);
...@@ -1172,6 +1202,8 @@ static int ath10k_station_disassoc(struct ath10k *ar, struct ath10k_vif *arvif, ...@@ -1172,6 +1202,8 @@ static int ath10k_station_disassoc(struct ath10k *ar, struct ath10k_vif *arvif,
{ {
int ret = 0; int ret = 0;
lockdep_assert_held(&ar->conf_mutex);
ret = ath10k_clear_peer_keys(arvif, sta->addr); ret = ath10k_clear_peer_keys(arvif, sta->addr);
if (ret) { if (ret) {
ath10k_warn("could not clear all peer wep keys (%d)\n", ret); ath10k_warn("could not clear all peer wep keys (%d)\n", ret);
...@@ -1198,6 +1230,8 @@ static int ath10k_update_channel_list(struct ath10k *ar) ...@@ -1198,6 +1230,8 @@ static int ath10k_update_channel_list(struct ath10k *ar)
int ret; int ret;
int i; int i;
lockdep_assert_held(&ar->conf_mutex);
bands = hw->wiphy->bands; bands = hw->wiphy->bands;
for (band = 0; band < IEEE80211_NUM_BANDS; band++) { for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
if (!bands[band]) if (!bands[band])
...@@ -1284,6 +1318,8 @@ static void ath10k_reg_notifier(struct wiphy *wiphy, ...@@ -1284,6 +1318,8 @@ static void ath10k_reg_notifier(struct wiphy *wiphy,
struct ath10k *ar = hw->priv; struct ath10k *ar = hw->priv;
int ret; int ret;
mutex_lock(&ar->conf_mutex);
ath_reg_notifier_apply(wiphy, request, &ar->ath_common.regulatory); ath_reg_notifier_apply(wiphy, request, &ar->ath_common.regulatory);
ret = ath10k_update_channel_list(ar); ret = ath10k_update_channel_list(ar);
...@@ -1301,6 +1337,8 @@ static void ath10k_reg_notifier(struct wiphy *wiphy, ...@@ -1301,6 +1337,8 @@ static void ath10k_reg_notifier(struct wiphy *wiphy,
regpair->reg_5ghz_ctl); regpair->reg_5ghz_ctl);
if (ret) if (ret)
ath10k_warn("could not set pdev regdomain (%d)\n", ret); ath10k_warn("could not set pdev regdomain (%d)\n", ret);
mutex_unlock(&ar->conf_mutex);
} }
/***************/ /***************/
...@@ -1678,6 +1716,8 @@ static int ath10k_start(struct ieee80211_hw *hw) ...@@ -1678,6 +1716,8 @@ static int ath10k_start(struct ieee80211_hw *hw)
struct ath10k *ar = hw->priv; struct ath10k *ar = hw->priv;
int ret; int ret;
mutex_lock(&ar->conf_mutex);
ret = ath10k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS, 1); ret = ath10k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS, 1);
if (ret) if (ret)
ath10k_warn("could not enable WMI_PDEV_PARAM_PMF_QOS (%d)\n", ath10k_warn("could not enable WMI_PDEV_PARAM_PMF_QOS (%d)\n",
...@@ -1688,6 +1728,7 @@ static int ath10k_start(struct ieee80211_hw *hw) ...@@ -1688,6 +1728,7 @@ static int ath10k_start(struct ieee80211_hw *hw)
ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n", ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n",
ret); ret);
mutex_unlock(&ar->conf_mutex);
return 0; return 0;
} }
...@@ -1695,9 +1736,11 @@ static void ath10k_stop(struct ieee80211_hw *hw) ...@@ -1695,9 +1736,11 @@ static void ath10k_stop(struct ieee80211_hw *hw)
{ {
struct ath10k *ar = hw->priv; struct ath10k *ar = hw->priv;
/* avoid leaks in case FW never confirms scan for offchannel */ mutex_lock(&ar->conf_mutex);
cancel_work_sync(&ar->offchan_tx_work);
ath10k_offchan_tx_purge(ar); ath10k_offchan_tx_purge(ar);
mutex_unlock(&ar->conf_mutex);
cancel_work_sync(&ar->offchan_tx_work);
} }
static int ath10k_config(struct ieee80211_hw *hw, u32 changed) static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
...@@ -2381,6 +2424,8 @@ static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif, ...@@ -2381,6 +2424,8 @@ static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif,
u32 value = 0; u32 value = 0;
int ret = 0; int ret = 0;
lockdep_assert_held(&ar->conf_mutex);
if (arvif->vdev_type != WMI_VDEV_TYPE_STA) if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
return 0; return 0;
...@@ -2576,6 +2621,8 @@ static void ath10k_set_rts_iter(void *data, u8 *mac, struct ieee80211_vif *vif) ...@@ -2576,6 +2621,8 @@ static void ath10k_set_rts_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
u32 rts = ar_iter->ar->hw->wiphy->rts_threshold; u32 rts = ar_iter->ar->hw->wiphy->rts_threshold;
lockdep_assert_held(&arvif->ar->conf_mutex);
rts = min_t(u32, rts, ATH10K_RTS_MAX); rts = min_t(u32, rts, ATH10K_RTS_MAX);
ar_iter->ret = ath10k_wmi_vdev_set_param(ar_iter->ar, arvif->vdev_id, ar_iter->ret = ath10k_wmi_vdev_set_param(ar_iter->ar, arvif->vdev_id,
...@@ -2614,6 +2661,8 @@ static void ath10k_set_frag_iter(void *data, u8 *mac, struct ieee80211_vif *vif) ...@@ -2614,6 +2661,8 @@ static void ath10k_set_frag_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
u32 frag = ar_iter->ar->hw->wiphy->frag_threshold; u32 frag = ar_iter->ar->hw->wiphy->frag_threshold;
int ret; int ret;
lockdep_assert_held(&arvif->ar->conf_mutex);
frag = clamp_t(u32, frag, frag = clamp_t(u32, frag,
ATH10K_FRAGMT_THRESHOLD_MIN, ATH10K_FRAGMT_THRESHOLD_MIN,
ATH10K_FRAGMT_THRESHOLD_MAX); ATH10K_FRAGMT_THRESHOLD_MAX);
...@@ -2659,6 +2708,8 @@ static void ath10k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) ...@@ -2659,6 +2708,8 @@ static void ath10k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
if (drop) if (drop)
return; return;
mutex_lock(&ar->conf_mutex);
ret = wait_event_timeout(ar->htt.empty_tx_wq, ({ ret = wait_event_timeout(ar->htt.empty_tx_wq, ({
bool empty; bool empty;
spin_lock_bh(&ar->htt.tx_lock); spin_lock_bh(&ar->htt.tx_lock);
...@@ -2669,6 +2720,8 @@ static void ath10k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) ...@@ -2669,6 +2720,8 @@ static void ath10k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
}), ATH10K_FLUSH_TIMEOUT_HZ); }), ATH10K_FLUSH_TIMEOUT_HZ);
if (ret <= 0) if (ret <= 0)
ath10k_warn("tx not flushed\n"); ath10k_warn("tx not flushed\n");
mutex_unlock(&ar->conf_mutex);
} }
/* TODO: Implement this function properly /* TODO: Implement this function properly
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment