From: Karthikeyan Periyasamy Subject: [PATCH] ath11k: avoid RCU cpu stall The following problems can result in RCU CPU stall warning 1. A CPU looping in an RCU read-side critical section 2. A CPU looping with interrupts disabled 3. A CPU looping with preemption disabled 4. A CPU looping with bottom halves disabled scenario 1: As per the above step 4, avoid spin_lock_bh() while reporting low_ack to user. scenario 2: As per the above step 1 & 4, avoid rcu_read_lock() while reporting mgmt rx through bottom halve disable call ieee80211_rx_ni() Signed-off-by: Karthikeyan Periyasamy --- --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -7429,6 +7429,7 @@ static void ath11k_mgmt_rx_event(struct struct ieee80211_vif *vif; struct ath11k_vif *arvif; struct ath11k_mgmt_frame_stats *mgmt_stats; + struct ieee80211_hw *hw; u16 frm_type = 0; if (ath11k_pull_mgmt_rx_params_tlv(ab, skb, &rx_ev) != 0) { @@ -7459,6 +7460,8 @@ static void ath11k_mgmt_rx_event(struct goto exit; } + hw = ar->hw; + if (rx_ev.status & WMI_RX_STATUS_ERR_MIC) status->flag |= RX_FLAG_MMIC_ERROR; @@ -7559,8 +7562,11 @@ skip_mgmt_stats: status->freq, status->band, status->signal, status->rate_idx); - ieee80211_rx_ni(ar->hw, skb); + rcu_read_unlock(); + + ieee80211_rx_ni(hw, skb); + return; exit: rcu_read_unlock(); } @@ -7913,6 +7919,7 @@ static void ath11k_peer_sta_kickout_even struct ieee80211_sta *sta; struct ath11k_peer *peer; struct ath11k *ar; + u32 vdev_id; if (ath11k_pull_peer_sta_kickout_ev(ab, skb, &arg) != 0) { ath11k_warn(ab, "failed to extract peer sta kickout event"); @@ -7926,15 +7933,20 @@ static void ath11k_peer_sta_kickout_even peer = ath11k_peer_find_by_addr(ab, arg.mac_addr); if (!peer) { + spin_unlock_bh(&ab->base_lock); ath11k_warn(ab, "peer not found %pM\n", arg.mac_addr); goto exit; } - ar = ath11k_mac_get_ar_by_vdev_id(ab, peer->vdev_id); + vdev_id = peer->vdev_id; + + spin_unlock_bh(&ab->base_lock); + + ar = ath11k_mac_get_ar_by_vdev_id(ab, vdev_id); if (!ar) { ath11k_warn(ab, "invalid vdev id in peer sta kickout ev %d", - peer->vdev_id); + vdev_id); goto exit; } @@ -7949,7 +7961,6 @@ static void ath11k_peer_sta_kickout_even ieee80211_report_low_ack(sta, 10); exit: - spin_unlock_bh(&ab->base_lock); rcu_read_unlock(); }