iwl4965: workaround for firmware frame tx rejection
authorStanislaw Gruszka <sgruszka@redhat.com>
Wed, 12 Jun 2013 14:44:49 +0000 (16:44 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 12 Jun 2013 19:06:57 +0000 (15:06 -0400)
Firmware can reject to transmit frame on passive channel, when it
did not yet received any frame with valid CRC on that channel.
Workaround this problem in the driver.

Tested-by: Jake Edge <jake@lwn.net>
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/iwlegacy/4965-mac.c
drivers/net/wireless/iwlegacy/common.c

index 9a95045c97b6b4fe6041f457a1999ecfb7926d12..1c44bb59f6c816efe2a459994f2525c12e509abf 100644 (file)
@@ -588,6 +588,11 @@ il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr,
                return;
        }
 
+       if (unlikely(test_bit(IL_STOP_REASON_PASSIVE, &il->stop_reason))) {
+               il_wake_queues_by_reason(il, IL_STOP_REASON_PASSIVE);
+               D_INFO("Woke queues - frame received on passive channel\n");
+       }
+
        /* In case of HW accelerated crypto and bad decryption, drop */
        if (!il->cfg->mod_params->sw_crypto &&
            il_set_decrypted_flag(il, hdr, ampdu_status, stats))
@@ -2806,6 +2811,19 @@ il4965_hdl_tx(struct il_priv *il, struct il_rx_buf *rxb)
                return;
        }
 
+       /*
+        * Firmware will not transmit frame on passive channel, if it not yet
+        * received some valid frame on that channel. When this error happen
+        * we have to wait until firmware will unblock itself i.e. when we
+        * note received beacon or other frame. We unblock queues in
+        * il4965_pass_packet_to_mac80211 or in il_mac_bss_info_changed.
+        */
+       if (unlikely((status & TX_STATUS_MSK) == TX_STATUS_FAIL_PASSIVE_NO_RX) &&
+           il->iw_mode == NL80211_IFTYPE_STATION) {
+               il_stop_queues_by_reason(il, IL_STOP_REASON_PASSIVE);
+               D_INFO("Stopped queues - RX waiting on passive channel\n");
+       }
+
        spin_lock_irqsave(&il->sta_lock, flags);
        if (txq->sched_retry) {
                const u32 scd_ssn = il4965_get_scd_ssn(tx_resp);
index e9a3cbc409ae1d239fb7ff9c4a43436e9994f26d..3195aad440ddf6317b1b9b34d2e2f57e773755c3 100644 (file)
@@ -5306,6 +5306,17 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        if (changes & BSS_CHANGED_BSSID) {
                D_MAC80211("BSSID %pM\n", bss_conf->bssid);
 
+               /*
+                * On passive channel we wait with blocked queues to see if
+                * there is traffic on that channel. If no frame will be
+                * received (what is very unlikely since scan detects AP on
+                * that channel, but theoretically possible), mac80211 associate
+                * procedure will time out and mac80211 will call us with NULL
+                * bssid. We have to unblock queues on such condition.
+                */
+               if (is_zero_ether_addr(bss_conf->bssid))
+                       il_wake_queues_by_reason(il, IL_STOP_REASON_PASSIVE);
+
                /*
                 * If there is currently a HW scan going on in the background,
                 * then we need to cancel it, otherwise sometimes we are not