diff --git a/bes2600/ap.c b/bes2600/ap.c index 8a17545..99e2da2 100644 --- a/bes2600/ap.c +++ b/bes2600/ap.c @@ -63,8 +63,11 @@ int bes2600_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct bes2600_vif *priv = cw12xx_get_vif_from_ieee80211(vif); struct bes2600_link_entry *entry; struct sk_buff *skb; + struct sk_buff_head local_drain; struct bes2600_common *hw_priv = hw->priv; + __skb_queue_head_init(&local_drain); + #ifdef P2P_MULTIVIF WARN_ON(priv->if_id == CW12XX_GENERIC_IF_ID); #endif @@ -93,9 +96,17 @@ int bes2600_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) priv->sta_asleep_mask |= BIT(sta_priv->link_id); entry->status = BES2600_LINK_HARD; - while ((skb = skb_dequeue(&entry->rx_queue))) - ieee80211_rx_irqsafe(priv->hw, skb); + /* + * Patch C2: splice the rx_queue out under the lock then deliver + * after unlock. ieee80211_rx_ni() runs the mac80211 RX path + * synchronously (formerly ieee80211_rx_irqsafe deferred to a + * tasklet); calling it from inside spin_lock_bh would hold the + * lock across mac80211's full RX dispatch. + */ + skb_queue_splice_init(&entry->rx_queue, &local_drain); spin_unlock_bh(&priv->ps_state_lock); + while ((skb = __skb_dequeue(&local_drain))) + ieee80211_rx_ni(priv->hw, skb); #ifdef AP_AGGREGATE_FW_FIX hw_priv->connected_sta_cnt++; if(hw_priv->connected_sta_cnt>1) { diff --git a/bes2600/bes_chardev.c b/bes2600/bes_chardev.c index 02dcd43..844f1d0 100644 --- a/bes2600/bes_chardev.c +++ b/bes2600/bes_chardev.c @@ -181,7 +181,7 @@ static int bes2600_switch_wifi(bool on) return ret; } -int bes2600_switch_bt(bool on) +static int bes2600_switch_bt(bool on) { int ret = 0; long status = 0; @@ -234,6 +234,36 @@ int bes2600_switch_bt(bool on) return ret; } +/* + * Re-added for danctnix's bes2600_btuart.c (a danctnix-only file) which + * relies on the chardev utility API for BT power switching and bus-error + * checks. The userspace /dev/bes2600 chardev itself is removed by the + * remove-chardev-user-interface series; these in-kernel helpers stay. + * + * @wifi: 1 to turn on, 0 to turn off. Otherwise, leave unchanged + * @bt: 1 to turn on, 0 to turn off. Otherwise, leave unchanged + */ +int bes2600_chrdev_switch_subsys_glb(int wifi, int bt) +{ + int ret = 0; + + switch (wifi) { + case 0: ret = bes2600_switch_wifi(false); break; + case 1: ret = bes2600_switch_wifi(true); break; + default: break; + } + if (ret) + return ret; + + switch (bt) { + case 0: ret = bes2600_switch_bt(false); break; + case 1: ret = bes2600_switch_bt(true); break; + default: break; + } + return ret; +} +EXPORT_SYMBOL_GPL(bes2600_chrdev_switch_subsys_glb); + @@ -562,6 +592,7 @@ bool bes2600_chrdev_is_bus_error(void) return error; } +EXPORT_SYMBOL_GPL(bes2600_chrdev_is_bus_error); void bes2600_chrdev_update_signal_mode(void) { diff --git a/bes2600/sta.c b/bes2600/sta.c index 8af8150..2b63ff2 100644 --- a/bes2600/sta.c +++ b/bes2600/sta.c @@ -1500,7 +1500,7 @@ void bes2600_event_handler(struct work_struct *work) IEEE80211_STYPE_DEAUTH | IEEE80211_FCTL_TODS); deauth->u.deauth.reason_code = WLAN_REASON_DEAUTH_LEAVING; deauth->seq_ctrl = 0; - ieee80211_rx_irqsafe(priv->hw, skb); + ieee80211_rx_ni(priv->hw, skb); bes_devel(" Inactivity Deauth Frame sent for MAC SA %pM \t and DA %pM\n", deauth->sa, deauth->da); queue_work(priv->hw_priv->workqueue, &priv->set_tim_work); break; diff --git a/bes2600/txrx.c b/bes2600/txrx.c index cb718ad..9074972 100644 --- a/bes2600/txrx.c +++ b/bes2600/txrx.c @@ -1980,18 +1980,18 @@ void bes2600_rx_cb(struct bes2600_vif *priv, * path is taken. */ if (hw_priv->bes_power.pm_unsupported) { - ieee80211_rx_irqsafe(priv->hw, skb); + ieee80211_rx_ni(priv->hw, skb); } 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); + ieee80211_rx_ni(priv->hw, skb); spin_unlock_bh(&priv->ps_state_lock); } } else { - ieee80211_rx_irqsafe(priv->hw, skb); + ieee80211_rx_ni(priv->hw, skb); } *skb_p = NULL; diff --git a/bes2600/wsm.c b/bes2600/wsm.c index 908c965..2424181 100644 --- a/bes2600/wsm.c +++ b/bes2600/wsm.c @@ -2412,7 +2412,7 @@ int wsm_handle_rx(struct bes2600_common *hw_priv, int id, if (!hw_priv->beacon_bkp) hw_priv->beacon_bkp = \ skb_copy(hw_priv->beacon, GFP_ATOMIC); - ieee80211_rx_irqsafe(hw_priv->hw, hw_priv->beacon); + ieee80211_rx_ni(hw_priv->hw, hw_priv->beacon); hw_priv->beacon = hw_priv->beacon_bkp; hw_priv->beacon_bkp = NULL;