diff --git a/bes2600/txrx.c b/bes2600/txrx.c index 84c34bc..bf17777 100644 --- a/bes2600/txrx.c +++ b/bes2600/txrx.c @@ -1942,13 +1942,31 @@ void bes2600_rx_cb(struct bes2600_vif *priv, if (unlikely(bes2600_itp_rxed(hw_priv, skb))) consume_skb(skb); else if (unlikely(early_data)) { - spin_lock_bh(&priv->ps_state_lock); - /* Double-check status with lock held */ - if (entry->status == BES2600_LINK_SOFT) - skb_queue_tail(&entry->rx_queue, skb); - else + /* + * Patch E: when c7 has latched pm_unsupported (firmware + * doesn't honour PSM, see feedback_bes2600_firmware_no_psm), + * AP-side power-save state machine is dead and link entries + * never transition to BES2600_LINK_SOFT. The double-check + * branch under ps_state_lock is unreachable in that case, + * so skip the per-frame lock acquisition entirely and + * deliver to mac80211 directly. + * + * On firmware that does honour PSM (the latch self-clears + * if a real PM_INDICATION ever arrives — see c7), this + * predicate flips back to false and the original locked + * path is taken. + */ + if (hw_priv->bes_power.pm_unsupported) { ieee80211_rx_irqsafe(priv->hw, skb); - spin_unlock_bh(&priv->ps_state_lock); + } else { + spin_lock_bh(&priv->ps_state_lock); + /* Double-check status with lock held */ + if (entry->status == BES2600_LINK_SOFT) + skb_queue_tail(&entry->rx_queue, skb); + else + ieee80211_rx_irqsafe(priv->hw, skb); + spin_unlock_bh(&priv->ps_state_lock); + } } else { ieee80211_rx_irqsafe(priv->hw, skb); }