From 8d2aec4be23ee93ec14031b0520f2fe15cce404f Mon Sep 17 00:00:00 2001 From: nbd Date: Sat, 20 Nov 2010 02:55:30 +0000 Subject: [PATCH] mac80211: backport a few fixes git-svn-id: svn://svn.openwrt.org/openwrt/branches/backfire@24045 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../mac80211/patches/310-cfg80211_fixes.patch | 178 ++++++++++++++++++ .../patches/592-ath9k_reset_fix.patch | 11 ++ 2 files changed, 189 insertions(+) create mode 100644 package/mac80211/patches/310-cfg80211_fixes.patch create mode 100644 package/mac80211/patches/592-ath9k_reset_fix.patch diff --git a/package/mac80211/patches/310-cfg80211_fixes.patch b/package/mac80211/patches/310-cfg80211_fixes.patch new file mode 100644 index 000000000..34b78d177 --- /dev/null +++ b/package/mac80211/patches/310-cfg80211_fixes.patch @@ -0,0 +1,178 @@ +--- a/include/net/regulatory.h ++++ b/include/net/regulatory.h +@@ -43,6 +43,12 @@ enum environment_cap { + * @intersect: indicates whether the wireless core should intersect + * the requested regulatory domain with the presently set regulatory + * domain. ++ * @processed: indicates whether or not this requests has already been ++ * processed. When the last request is processed it means that the ++ * currently regulatory domain set on cfg80211 is updated from ++ * CRDA and can be used by other regulatory requests. When a ++ * the last request is not yet processed we must yield until it ++ * is processed before processing any new requests. + * @country_ie_checksum: checksum of the last processed and accepted + * country IE + * @country_ie_env: lets us know if the AP is telling us we are outdoor, +@@ -54,6 +60,7 @@ struct regulatory_request { + enum nl80211_reg_initiator initiator; + char alpha2[2]; + bool intersect; ++ bool processed; + enum environment_cap country_ie_env; + struct list_head list; + }; +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -96,6 +96,9 @@ struct reg_beacon { + struct ieee80211_channel chan; + }; + ++static void reg_todo(struct work_struct *work); ++static DECLARE_WORK(reg_work, reg_todo); ++ + /* We keep a static world regulatory domain in case of the absence of CRDA */ + static const struct ieee80211_regdomain world_regdom = { + .n_reg_rules = 5, +@@ -1215,6 +1218,21 @@ static int ignore_request(struct wiphy * + return -EINVAL; + } + ++static void reg_set_request_processed(void) ++{ ++ bool need_more_processing = false; ++ ++ last_request->processed = true; ++ ++ spin_lock(®_requests_lock); ++ if (!list_empty(®_requests_list)) ++ need_more_processing = true; ++ spin_unlock(®_requests_lock); ++ ++ if (need_more_processing) ++ schedule_work(®_work); ++} ++ + /** + * __regulatory_hint - hint to the wireless core a regulatory domain + * @wiphy: if the hint comes from country information from an AP, this +@@ -1290,8 +1308,10 @@ new_request: + * have applied the requested regulatory domain before we just + * inform userspace we have processed the request + */ +- if (r == -EALREADY) ++ if (r == -EALREADY) { + nl80211_send_reg_change_event(last_request); ++ reg_set_request_processed(); ++ } + return r; + } + +@@ -1307,16 +1327,13 @@ static void reg_process_hint(struct regu + + BUG_ON(!reg_request->alpha2); + +- mutex_lock(&cfg80211_mutex); +- mutex_lock(®_mutex); +- + if (wiphy_idx_valid(reg_request->wiphy_idx)) + wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); + + if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && + !wiphy) { + kfree(reg_request); +- goto out; ++ return; + } + + r = __regulatory_hint(wiphy, reg_request); +@@ -1324,28 +1341,46 @@ static void reg_process_hint(struct regu + if (r == -EALREADY && wiphy && + wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) + wiphy_update_regulatory(wiphy, initiator); +-out: +- mutex_unlock(®_mutex); +- mutex_unlock(&cfg80211_mutex); + } + +-/* Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_* */ ++/* ++ * Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_* ++ * Regulatory hints come on a first come first serve basis and we ++ * must process each one atomically. ++ */ + static void reg_process_pending_hints(void) +- { ++{ + struct regulatory_request *reg_request; + ++ mutex_lock(&cfg80211_mutex); ++ mutex_lock(®_mutex); ++ ++ /* When last_request->processed becomes true this will be rescheduled */ ++ if (last_request && !last_request->processed) { ++ REG_DBG_PRINT("Pending regulatory request, waiting " ++ "for it to be processed..."); ++ goto out; ++ } ++ + spin_lock(®_requests_lock); +- while (!list_empty(®_requests_list)) { +- reg_request = list_first_entry(®_requests_list, +- struct regulatory_request, +- list); +- list_del_init(®_request->list); + ++ if (list_empty(®_requests_list)) { + spin_unlock(®_requests_lock); +- reg_process_hint(reg_request); +- spin_lock(®_requests_lock); ++ goto out; + } ++ ++ reg_request = list_first_entry(®_requests_list, ++ struct regulatory_request, ++ list); ++ list_del_init(®_request->list); ++ + spin_unlock(®_requests_lock); ++ ++ reg_process_hint(reg_request); ++ ++out: ++ mutex_unlock(®_mutex); ++ mutex_unlock(&cfg80211_mutex); + } + + /* Processes beacon hints -- this has nothing to do with country IEs */ +@@ -1392,8 +1427,6 @@ static void reg_todo(struct work_struct + reg_process_pending_beacon_hints(); + } + +-static DECLARE_WORK(reg_work, reg_todo); +- + static void queue_regulatory_request(struct regulatory_request *request) + { + if (isalpha(request->alpha2[0])) +@@ -1428,12 +1461,7 @@ static int regulatory_hint_core(const ch + request->alpha2[1] = alpha2[1]; + request->initiator = NL80211_REGDOM_SET_BY_CORE; + +- /* +- * This ensures last_request is populated once modules +- * come swinging in and calling regulatory hints and +- * wiphy_apply_custom_regulatory(). +- */ +- reg_process_hint(request); ++ queue_regulatory_request(request); + + return 0; + } +@@ -1959,6 +1987,8 @@ int set_regdom(const struct ieee80211_re + + nl80211_send_reg_change_event(last_request); + ++ reg_set_request_processed(); ++ + mutex_unlock(®_mutex); + + return r; diff --git a/package/mac80211/patches/592-ath9k_reset_fix.patch b/package/mac80211/patches/592-ath9k_reset_fix.patch new file mode 100644 index 000000000..18f9a0546 --- /dev/null +++ b/package/mac80211/patches/592-ath9k_reset_fix.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/ath/ath9k/recv.c ++++ b/drivers/net/wireless/ath/ath9k/recv.c +@@ -517,7 +517,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); + -- 2.35.1