mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-24 12:09:35 +07:00
ath10k: fix offchannel tx failure when no ath10k_mac_tx_frm_has_freq
Offchannel management frames were failing: [18099.253732] ath10k_pci 0000:01:00.0: timed out waiting for offchannel skb cf0e3780 [18102.293686] ath10k_pci 0000:01:00.0: timed out waiting for offchannel skb cf0e3780 [18105.333653] ath10k_pci 0000:01:00.0: timed out waiting for offchannel skb cf0e3780 [18108.373712] ath10k_pci 0000:01:00.0: timed out waiting for offchannel skb cf0e3780 [18111.413687] ath10k_pci 0000:01:00.0: timed out waiting for offchannel skb cf0e36c0 [18114.453726] ath10k_pci 0000:01:00.0: timed out waiting for offchannel skb cf0e3f00 [18117.493773] ath10k_pci 0000:01:00.0: timed out waiting for offchannel skb cf0e36c0 [18120.533631] ath10k_pci 0000:01:00.0: timed out waiting for offchannel skb cf0e3f00 This bug appears to have been added between 4.0 (which works for us), and 4.4, which does not work. I think this is because the tx-offchannel logic gets in a loop when ath10k_mac_tx_frm_has_freq(ar) is false, so pkt is never actually sent to the firmware for transmit. This patch fixes the problem on 4.9 for me, and now HS20 clients can work again with my firmware. Antonio: tested with 10.4-3.5.3-00057 on QCA4019 and QCA9888 Signed-off-by: Ben Greear <greearb@candelatech.com> Tested-by: Antonio Quartulli <antonio.quartulli@kaiwoo.ai> [kvalo@codeaurora.org: improve commit log, remove unneeded parenthesis] Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
parent
cd486e627e
commit
cc6df017e5
@ -3708,7 +3708,7 @@ static int ath10k_mac_tx(struct ath10k *ar,
|
|||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
enum ath10k_hw_txrx_mode txmode,
|
enum ath10k_hw_txrx_mode txmode,
|
||||||
enum ath10k_mac_tx_path txpath,
|
enum ath10k_mac_tx_path txpath,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb, bool noque_offchan)
|
||||||
{
|
{
|
||||||
struct ieee80211_hw *hw = ar->hw;
|
struct ieee80211_hw *hw = ar->hw;
|
||||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||||
@ -3738,10 +3738,10 @@ static int ath10k_mac_tx(struct ath10k *ar,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
|
if (!noque_offchan && info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
|
||||||
if (!ath10k_mac_tx_frm_has_freq(ar)) {
|
if (!ath10k_mac_tx_frm_has_freq(ar)) {
|
||||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %pK\n",
|
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac queued offchannel skb %pK len %d\n",
|
||||||
skb);
|
skb, skb->len);
|
||||||
|
|
||||||
skb_queue_tail(&ar->offchan_tx_queue, skb);
|
skb_queue_tail(&ar->offchan_tx_queue, skb);
|
||||||
ieee80211_queue_work(hw, &ar->offchan_tx_work);
|
ieee80211_queue_work(hw, &ar->offchan_tx_work);
|
||||||
@ -3803,8 +3803,8 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
|||||||
|
|
||||||
mutex_lock(&ar->conf_mutex);
|
mutex_lock(&ar->conf_mutex);
|
||||||
|
|
||||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac offchannel skb %pK\n",
|
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac offchannel skb %pK len %d\n",
|
||||||
skb);
|
skb, skb->len);
|
||||||
|
|
||||||
hdr = (struct ieee80211_hdr *)skb->data;
|
hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
peer_addr = ieee80211_get_DA(hdr);
|
peer_addr = ieee80211_get_DA(hdr);
|
||||||
@ -3850,7 +3850,7 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
|||||||
txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
|
txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
|
||||||
txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode);
|
txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode);
|
||||||
|
|
||||||
ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb);
|
ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb, true);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ath10k_warn(ar, "failed to transmit offchannel frame: %d\n",
|
ath10k_warn(ar, "failed to transmit offchannel frame: %d\n",
|
||||||
ret);
|
ret);
|
||||||
@ -3860,8 +3860,8 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
|||||||
time_left =
|
time_left =
|
||||||
wait_for_completion_timeout(&ar->offchan_tx_completed, 3 * HZ);
|
wait_for_completion_timeout(&ar->offchan_tx_completed, 3 * HZ);
|
||||||
if (time_left == 0)
|
if (time_left == 0)
|
||||||
ath10k_warn(ar, "timed out waiting for offchannel skb %pK\n",
|
ath10k_warn(ar, "timed out waiting for offchannel skb %pK, len: %d\n",
|
||||||
skb);
|
skb, skb->len);
|
||||||
|
|
||||||
if (!peer && tmp_peer_created) {
|
if (!peer && tmp_peer_created) {
|
||||||
ret = ath10k_peer_delete(ar, vdev_id, peer_addr);
|
ret = ath10k_peer_delete(ar, vdev_id, peer_addr);
|
||||||
@ -4097,7 +4097,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
|
|||||||
spin_unlock_bh(&ar->htt.tx_lock);
|
spin_unlock_bh(&ar->htt.tx_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb);
|
ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb, false);
|
||||||
if (unlikely(ret)) {
|
if (unlikely(ret)) {
|
||||||
ath10k_warn(ar, "failed to push frame: %d\n", ret);
|
ath10k_warn(ar, "failed to push frame: %d\n", ret);
|
||||||
|
|
||||||
@ -4378,7 +4378,7 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw,
|
|||||||
spin_unlock_bh(&ar->htt.tx_lock);
|
spin_unlock_bh(&ar->htt.tx_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb);
|
ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb, false);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ath10k_warn(ar, "failed to transmit frame: %d\n", ret);
|
ath10k_warn(ar, "failed to transmit frame: %d\n", ret);
|
||||||
if (is_htt) {
|
if (is_htt) {
|
||||||
|
Loading…
Reference in New Issue
Block a user