Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+55 −2
Original line number Original line Diff line number Diff line
@@ -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,
	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)
{
{
	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,
{
{
	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,
{
{
	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)
	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,
				      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,
	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,
	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,
	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,
	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,
{
{
	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,
	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,
	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,
{
{
	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,
{
{
	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)
	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,
	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,
					    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)
	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)
		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)
{
{
	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,
	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)
	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)
	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)
	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)
		}), 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