OSDN Git Service

brcmfmac: fix full timeout waiting for action frame on-channel tx
authorChung-Hsien Hsu <stanley.hsu@cypress.com>
Thu, 27 Sep 2018 14:59:49 +0000 (14:59 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 22 Nov 2019 13:44:22 +0000 (14:44 +0100)
[ Upstream commit fbf07000960d9c8a13fdc17c6de0230d681c7543 ]

The driver sends an action frame down and waits for a completion signal
triggered by the received BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE event
to continue the process. However, the action frame could be transmitted
either on the current channel or on an off channel. For the on-channel
case, only BRCMF_E_ACTION_FRAME_COMPLETE event will be received when
the frame is transmitted, which make the driver always wait a full
timeout duration. This patch has the completion signal be triggered by
receiving the BRCMF_E_ACTION_FRAME_COMPLETE event for the on-channel
case.

This change fixes WFA p2p certification 5.1.19 failure.

Signed-off-by: Chung-Hsien Hsu <stanley.hsu@cypress.com>
Signed-off-by: Chi-Hsien Lin <chi-hsien.lin@cypress.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/wireless/brcm80211/brcmfmac/p2p.c
drivers/net/wireless/brcm80211/brcmfmac/p2p.h

index e6c8b0d..7dae935 100644 (file)
@@ -1469,10 +1469,12 @@ int brcmf_p2p_notify_action_tx_complete(struct brcmf_if *ifp,
                return 0;
 
        if (e->event_code == BRCMF_E_ACTION_FRAME_COMPLETE) {
-               if (e->status == BRCMF_E_STATUS_SUCCESS)
+               if (e->status == BRCMF_E_STATUS_SUCCESS) {
                        set_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED,
                                &p2p->status);
-               else {
+                       if (!p2p->wait_for_offchan_complete)
+                               complete(&p2p->send_af_done);
+               } else {
                        set_bit(BRCMF_P2P_STATUS_ACTION_TX_NOACK, &p2p->status);
                        /* If there is no ack, we don't need to wait for
                         * WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE event
@@ -1523,6 +1525,17 @@ static s32 brcmf_p2p_tx_action_frame(struct brcmf_p2p_info *p2p,
        p2p->af_sent_channel = le32_to_cpu(af_params->channel);
        p2p->af_tx_sent_jiffies = jiffies;
 
+       if (test_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status) &&
+           p2p->af_sent_channel ==
+           ieee80211_frequency_to_channel(p2p->remain_on_channel.center_freq))
+               p2p->wait_for_offchan_complete = false;
+       else
+               p2p->wait_for_offchan_complete = true;
+
+       brcmf_dbg(TRACE, "Waiting for %s tx completion event\n",
+                 (p2p->wait_for_offchan_complete) ?
+                  "off-channel" : "on-channel");
+
        timeout = wait_for_completion_timeout(&p2p->send_af_done,
                                        msecs_to_jiffies(P2P_AF_MAX_WAIT_TIME));
 
index 5d49059..59e902a 100644 (file)
@@ -125,6 +125,7 @@ struct afx_hdl {
  * @gon_req_action: about to send go negotiation requets frame.
  * @block_gon_req_tx: drop tx go negotiation requets frame.
  * @p2pdev_dynamically: is p2p device if created by module param or supplicant.
+ * @wait_for_offchan_complete: wait for off-channel tx completion event.
  */
 struct brcmf_p2p_info {
        struct brcmf_cfg80211_info *cfg;
@@ -146,6 +147,7 @@ struct brcmf_p2p_info {
        bool gon_req_action;
        bool block_gon_req_tx;
        bool p2pdev_dynamically;
+       bool wait_for_offchan_complete;
 };
 
 s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced);