From 5430ba363f03200f0a619426b9cbe2e84971c917 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 20 Nov 2010 02:26:41 +0000 Subject: mac80211: update to latest wireless-testing + more stability work git-svn-id: svn://svn.openwrt.org/openwrt/trunk@24044 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/mac80211/patches/311-pending_work.patch | 279 ++++++++++++++++++++++++ 1 file changed, 279 insertions(+) create mode 100644 package/mac80211/patches/311-pending_work.patch (limited to 'package/mac80211/patches/311-pending_work.patch') diff --git a/package/mac80211/patches/311-pending_work.patch b/package/mac80211/patches/311-pending_work.patch new file mode 100644 index 0000000000..68b57234fc --- /dev/null +++ b/package/mac80211/patches/311-pending_work.patch @@ -0,0 +1,279 @@ +--- a/drivers/net/wireless/ath/ath9k/mac.c ++++ b/drivers/net/wireless/ath/ath9k/mac.c +@@ -766,14 +766,6 @@ void ath9k_hw_startpcureceive(struct ath + } + EXPORT_SYMBOL(ath9k_hw_startpcureceive); + +-void ath9k_hw_stoppcurecv(struct ath_hw *ah) +-{ +- REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); +- +- ath9k_hw_disable_mib_counters(ah); +-} +-EXPORT_SYMBOL(ath9k_hw_stoppcurecv); +- + void ath9k_hw_abortpcurecv(struct ath_hw *ah) + { + REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS); +--- a/drivers/net/wireless/ath/ath9k/mac.h ++++ b/drivers/net/wireless/ath/ath9k/mac.h +@@ -691,7 +691,6 @@ void ath9k_hw_setuprxdesc(struct ath_hw + bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); + void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); + void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning); +-void ath9k_hw_stoppcurecv(struct ath_hw *ah); + void ath9k_hw_abortpcurecv(struct ath_hw *ah); + bool ath9k_hw_stopdmarecv(struct ath_hw *ah); + int ath9k_hw_beaconq_setup(struct ath_hw *ah); +--- a/drivers/net/wireless/ath/ath9k/recv.c ++++ b/drivers/net/wireless/ath/ath9k/recv.c +@@ -518,7 +518,7 @@ bool ath_stoprecv(struct ath_softc *sc) + bool stopped; + + spin_lock_bh(&sc->rx.rxbuflock); +- ath9k_hw_stoppcurecv(ah); ++ ath9k_hw_abortpcurecv(ah); + ath9k_hw_setrxfilter(ah, 0); + stopped = ath9k_hw_stopdmarecv(ah); + +--- a/drivers/net/wireless/ath/ath9k/xmit.c ++++ b/drivers/net/wireless/ath/ath9k/xmit.c +@@ -163,6 +163,7 @@ static void ath_tx_flush_tid(struct ath_ + bf = list_first_entry(&tid->buf_q, struct ath_buf, list); + list_move_tail(&bf->list, &bf_head); + ++ spin_unlock_bh(&txq->axq_lock); + fi = get_frame_info(bf->bf_mpdu); + if (fi->retries) { + ath_tx_update_baw(sc, tid, fi->seqno); +@@ -170,6 +171,7 @@ static void ath_tx_flush_tid(struct ath_ + } else { + ath_tx_send_normal(sc, txq, tid, &bf_head); + } ++ spin_lock_bh(&txq->axq_lock); + } + + spin_unlock_bh(&txq->axq_lock); +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -349,6 +349,7 @@ struct ieee80211_if_managed { + struct work_struct chswitch_work; + struct work_struct beacon_connection_loss_work; + ++ unsigned long beacon_timeout; + unsigned long probe_timeout; + int probe_send_count; + +@@ -1269,6 +1270,8 @@ void ieee80211_send_nullfunc(struct ieee + int powersave); + void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, + struct ieee80211_hdr *hdr); ++void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_hdr *hdr); + void ieee80211_beacon_connection_loss_work(struct work_struct *work); + + void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -28,13 +28,19 @@ + #include "rate.h" + #include "led.h" + ++#define IEEE80211_MAX_NULLFUNC_TRIES 2 + #define IEEE80211_MAX_PROBE_TRIES 5 + + /* +- * beacon loss detection timeout +- * XXX: should depend on beacon interval ++ * Beacon loss timeout is calculated as N frames times the ++ * advertised beacon interval. This may need to be somewhat ++ * higher than what hardware might detect to account for ++ * delays in the host processing frames. But since we also ++ * probe on beacon miss before declaring the connection lost ++ * default to what we want. + */ +-#define IEEE80211_BEACON_LOSS_TIME (2 * HZ) ++#define IEEE80211_BEACON_LOSS_COUNT 7 ++ + /* + * Time the connection can be idle before we probe + * it to see if we can still talk to the AP. +@@ -45,7 +51,7 @@ + * a probe request because of beacon loss or for + * checking the connection still works. + */ +-#define IEEE80211_PROBE_WAIT (HZ / 2) ++#define IEEE80211_PROBE_WAIT (HZ / 5) + + /* + * Weight given to the latest Beacon frame when calculating average signal +@@ -121,7 +127,7 @@ void ieee80211_sta_reset_beacon_monitor( + return; + + mod_timer(&sdata->u.mgd.bcn_mon_timer, +- round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME)); ++ round_jiffies_up(jiffies + sdata->u.mgd.beacon_timeout)); + } + + void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata) +@@ -871,6 +877,9 @@ static void ieee80211_set_associated(str + bss_info_changed |= ieee80211_handle_bss_capability(sdata, + cbss->capability, bss->has_erp_value, bss->erp_value); + ++ sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec( ++ IEEE80211_BEACON_LOSS_COUNT * bss_conf->beacon_int)); ++ + sdata->u.mgd.associated = cbss; + memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); + +@@ -1026,6 +1035,50 @@ void ieee80211_sta_rx_notify(struct ieee + ieee80211_sta_reset_conn_monitor(sdata); + } + ++static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) ++{ ++ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; ++ ++ if (!(ifmgd->flags & (IEEE80211_STA_BEACON_POLL | ++ IEEE80211_STA_CONNECTION_POLL))) ++ return; ++ ++ ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | ++ IEEE80211_STA_BEACON_POLL); ++ mutex_lock(&sdata->local->iflist_mtx); ++ ieee80211_recalc_ps(sdata->local, -1); ++ mutex_unlock(&sdata->local->iflist_mtx); ++ ++ if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) ++ return; ++ ++ /* ++ * We've received a probe response, but are not sure whether ++ * we have or will be receiving any beacons or data, so let's ++ * schedule the timers again, just in case. ++ */ ++ ieee80211_sta_reset_beacon_monitor(sdata); ++ ++ mod_timer(&ifmgd->conn_mon_timer, ++ round_jiffies_up(jiffies + ++ IEEE80211_CONNECTION_IDLE_TIME)); ++} ++ ++void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_hdr *hdr) ++{ ++ if (!ieee80211_is_data(hdr->frame_control) && ++ !ieee80211_is_nullfunc(hdr->frame_control)) ++ return; ++ ++ ieee80211_sta_reset_conn_monitor(sdata); ++ ++ if (ieee80211_is_nullfunc(hdr->frame_control)) { ++ sdata->u.mgd.probe_send_count = 0; ++ ieee80211_queue_work(&sdata->local->hw, &sdata->work); ++ } ++} ++ + static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) + { + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; +@@ -1041,8 +1094,19 @@ static void ieee80211_mgd_probe_ap_send( + if (ifmgd->probe_send_count >= unicast_limit) + dst = NULL; + +- ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); +- ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0); ++ /* ++ * When the hardware reports an accurate Tx ACK status, it's ++ * better to send a nullfunc frame instead of a probe request, ++ * as it will kick us off the AP quickly if we aren't associated ++ * anymore. The timeout will be reset if the frame is ACKed by ++ * the AP. ++ */ ++ if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) ++ ieee80211_send_nullfunc(sdata->local, sdata, 0); ++ else { ++ ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); ++ ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0); ++ } + + ifmgd->probe_send_count++; + ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; +@@ -1509,29 +1573,8 @@ static void ieee80211_rx_mgmt_probe_resp + ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); + + if (ifmgd->associated && +- memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0 && +- ifmgd->flags & (IEEE80211_STA_BEACON_POLL | +- IEEE80211_STA_CONNECTION_POLL)) { +- ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | +- IEEE80211_STA_BEACON_POLL); +- mutex_lock(&sdata->local->iflist_mtx); +- ieee80211_recalc_ps(sdata->local, -1); +- mutex_unlock(&sdata->local->iflist_mtx); +- +- if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) +- return; +- +- /* +- * We've received a probe response, but are not sure whether +- * we have or will be receiving any beacons or data, so let's +- * schedule the timers again, just in case. +- */ +- ieee80211_sta_reset_beacon_monitor(sdata); +- +- mod_timer(&ifmgd->conn_mon_timer, +- round_jiffies_up(jiffies + +- IEEE80211_CONNECTION_IDLE_TIME)); +- } ++ memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0) ++ ieee80211_reset_ap_probe(sdata); + } + + /* +@@ -1881,12 +1924,22 @@ void ieee80211_sta_work(struct ieee80211 + IEEE80211_STA_CONNECTION_POLL) && + ifmgd->associated) { + u8 bssid[ETH_ALEN]; ++ int max_tries; ++ ++ /* ACK received for nullfunc probing frame */ ++ if (!ifmgd->probe_send_count) ++ ieee80211_reset_ap_probe(sdata); ++ ++ if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) ++ max_tries = IEEE80211_MAX_NULLFUNC_TRIES; ++ else ++ max_tries = IEEE80211_MAX_PROBE_TRIES; + + memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); + if (time_is_after_jiffies(ifmgd->probe_timeout)) + run_again(ifmgd, ifmgd->probe_timeout); + +- else if (ifmgd->probe_send_count < IEEE80211_MAX_PROBE_TRIES) { ++ else if (ifmgd->probe_send_count < max_tries) { + #ifdef CONFIG_MAC80211_VERBOSE_DEBUG + wiphy_debug(local->hw.wiphy, + "%s: No probe response from AP %pM" +@@ -2012,6 +2065,8 @@ void ieee80211_sta_restart(struct ieee80 + add_timer(&ifmgd->timer); + if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) + add_timer(&ifmgd->chswitch_timer); ++ ieee80211_sta_reset_beacon_monitor(sdata); ++ ieee80211_send_nullfunc(sdata->local, sdata, 0); + } + #endif + +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -155,6 +155,10 @@ static void ieee80211_frame_acked(struct + + ieee80211_queue_work(&local->hw, &local->recalc_smps); + } ++ ++ if ((sdata->vif.type == NL80211_IFTYPE_STATION) && ++ (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) ++ ieee80211_sta_tx_notify(sdata, (void *) skb->data); + } + + void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) -- cgit v1.2.3