From: Felix Fietkau Date: Mon, 23 Mar 2009 12:11:17 +0000 (+0000) Subject: reorganize madwifi patches slightly X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=39643cdbed63fc2f0be06793ebaf5cb9a36995e1;p=librecmc%2Flibrecmc.git reorganize madwifi patches slightly SVN-Revision: 14988 --- diff --git a/package/madwifi/patches/400-changeset_r3402.patch b/package/madwifi/patches/400-changeset_r3402.patch deleted file mode 100644 index f43a6d90d2..0000000000 --- a/package/madwifi/patches/400-changeset_r3402.patch +++ /dev/null @@ -1,35 +0,0 @@ ---- a/ath_hal/ah_os.h -+++ b/ath_hal/ah_os.h -@@ -194,10 +194,6 @@ extern u_int32_t __ahdecl ath_hal_getupt - */ - #if (AH_BYTE_ORDER == AH_BIG_ENDIAN) - #define is_reg_le(__reg) ((0x4000 <= (__reg) && (__reg) < 0x5000)) --#else --#define is_reg_le(__reg) 1 --#endif -- - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) - #define _OS_REG_WRITE(_ah, _reg, _val) do { \ - is_reg_le(_reg) ? \ -@@ -219,6 +215,21 @@ extern u_int32_t __ahdecl ath_hal_getupt - readl((_ah)->ah_sh + (_reg)) : \ - cpu_to_le32(readl((_ah)->ah_sh + (_reg)))) - #endif /* KERNEL_VERSION(2,6,12) */ -+#else /* AH_BYTE_ORDER != AH_BIG_ENDIAN */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) -+#define _OS_REG_WRITE(_ah, _reg, _val) do { \ -+ iowrite32((_val), (_ah)->ah_sh + (_reg)); \ -+ } while (0) -+#define _OS_REG_READ(_ah, _reg) \ -+ ioread32((_ah)->ah_sh + (_reg)) -+#else -+#define _OS_REG_WRITE(_ah, _reg, _val) do { \ -+ writel((_val), (_ah)->ah_sh + (_reg)); \ -+ } while (0) -+#define _OS_REG_READ(_ah, _reg) \ -+ readl((_ah)->ah_sh + (_reg)) -+#endif /* KERNEL_VERSION(2,6,12) */ -+#endif /* AH_BYTE_ORDER != AH_BIG_ENDIAN */ - - /* - * The functions in this section are not intended to be invoked by MadWifi diff --git a/package/madwifi/patches/400-new_hal.patch b/package/madwifi/patches/400-new_hal.patch new file mode 100644 index 0000000000..a586b2266a --- /dev/null +++ b/package/madwifi/patches/400-new_hal.patch @@ -0,0 +1,124 @@ +--- a/ath/if_ath.c ++++ b/ath/if_ath.c +@@ -606,6 +606,14 @@ ath_attach(u_int16_t devid, struct net_d + } + sc->sc_ah = ah; + ++ /* WAR for AR7100 PCI bug */ ++#ifdef CONFIG_ATHEROS_AR71XX ++ if ((ar_device(sc->devid) >= 5210) && (ar_device(sc->devid) < 5416)) { ++ ath_hal_setcapability(ah, HAL_CAP_DMABURST_RX, 0, HAL_DMABURST_4B, NULL); ++ ath_hal_setcapability(ah, HAL_CAP_DMABURST_TX, 0, HAL_DMABURST_4B, NULL); ++ } ++#endif ++ + /* + * Check if the MAC has multi-rate retry support. + * We do this by trying to setup a fake extended +@@ -7553,7 +7561,7 @@ ath_txq_setup(struct ath_softc *sc, int + if (qtype == HAL_TX_QUEUE_UAPSD) + qi.tqi_qflags = HAL_TXQ_TXDESCINT_ENABLE; + else +- qi.tqi_qflags = HAL_TXQ_TXEOLINT_ENABLE | ++ qi.tqi_qflags = HAL_TXQ_TXEOLINT_ENABLE | HAL_TXQ_TXOKINT_ENABLE | + HAL_TXQ_TXDESCINT_ENABLE; + qnum = ath_hal_setuptxqueue(ah, qtype, &qi); + if (qnum == -1) { +--- a/ath_hal/ah_os.c ++++ b/ath_hal/ah_os.c +@@ -126,6 +126,13 @@ ath_hal_printf(struct ath_hal *ah, const + } + EXPORT_SYMBOL(ath_hal_printf); + ++void __ahdecl ++ath_hal_printstr(struct ath_hal *ah, const char *str) ++{ ++ printk("%s", str); ++} ++EXPORT_SYMBOL(ath_hal_printstr); ++ + /* + * Format an Ethernet MAC for printing. + */ +--- a/ath_hal/ah_os.h ++++ b/ath_hal/ah_os.h +@@ -156,69 +156,23 @@ extern u_int32_t __ahdecl ath_hal_getupt + #endif + #endif /* AH_BYTE_ORDER */ + +-/* +- * Some big-endian architectures don't set CONFIG_GENERIC_IOMAP, but fail to +- * implement iowrite32be and ioread32be. Provide compatibility macros when +- * it's needed. +- * +- * As of Linux 2.6.24, only MIPS, PARISC and PowerPC implement iowrite32be and +- * ioread32be as functions. +- * +- * The downside or the replacement macros it that we may be byte-swapping data +- * for the second time, so the native implementations should be preferred. +- */ +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)) && \ +- !defined(CONFIG_GENERIC_IOMAP) && (AH_BYTE_ORDER == AH_BIG_ENDIAN) && \ +- !defined(__mips__) && !defined(__hppa__) && !defined(__powerpc__) +-# ifndef iowrite32be +-# define iowrite32be(_val, _addr) iowrite32(swab32((_val)), (_addr)) +-# endif +-# ifndef ioread32be +-# define ioread32be(_addr) swab32(ioread32((_addr))) +-# endif +-#endif ++#define IS_SWAPPED(_ah, _reg) \ ++ ((_ah)->ah_swapped && \ ++ (((0x4000 <= (_reg)) && ((_reg) < 0x5000)) || \ ++ ((0x7000 <= (_reg)) && ((_reg) < 0x8000)))) ++ ++#define SWAPREG(_ah, _reg, _val) \ ++ (IS_SWAPPED(_ah, _reg) ? cpu_to_le32(_val) : (_val)) + + /* + * The register accesses are done using target-specific functions when + * debugging is enabled (AH_DEBUG) or it's explicitly requested for the target. +- * +- * The hardware registers use little-endian byte order natively. Big-endian +- * systems are configured by HAL to enable hardware byte-swap of register reads +- * and writes at reset. This avoid the need to byte-swap the data in software. +- * However, the registers in a certain area from 0x4000 to 0x4fff (PCI clock +- * domain registers) are not byte swapped! +- * +- * Since Linux I/O primitives default to little-endian operations, we only +- * need to suppress byte-swapping on big-endian systems outside the area used +- * by the PCI clock domain registers. + */ +-#if (AH_BYTE_ORDER == AH_BIG_ENDIAN) +-#define is_reg_le(__reg) ((0x4000 <= (__reg) && (__reg) < 0x5000)) +-#else +-#define is_reg_le(__reg) 1 +-#endif +- +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) +-#define _OS_REG_WRITE(_ah, _reg, _val) do { \ +- is_reg_le(_reg) ? \ +- iowrite32((_val), (_ah)->ah_sh + (_reg)) : \ +- iowrite32be((_val), (_ah)->ah_sh + (_reg)); \ +- } while (0) +-#define _OS_REG_READ(_ah, _reg) \ +- (is_reg_le(_reg) ? \ +- ioread32((_ah)->ah_sh + (_reg)) : \ +- ioread32be((_ah)->ah_sh + (_reg))) +-#else + #define _OS_REG_WRITE(_ah, _reg, _val) do { \ +- writel(is_reg_le(_reg) ? \ +- (_val) : cpu_to_le32(_val), \ +- (_ah)->ah_sh + (_reg)); \ +- } while (0) ++ __raw_writel(SWAPREG(_ah, _reg, _val), (_ah)->ah_sh + (_reg)); \ ++} while (0) + #define _OS_REG_READ(_ah, _reg) \ +- (is_reg_le(_reg) ? \ +- readl((_ah)->ah_sh + (_reg)) : \ +- cpu_to_le32(readl((_ah)->ah_sh + (_reg)))) +-#endif /* KERNEL_VERSION(2,6,12) */ ++ SWAPREG(_ah, _reg, __raw_readl((_ah)->ah_sh + (_reg))) + + /* + * The functions in this section are not intended to be invoked by MadWifi diff --git a/package/madwifi/patches/406-monitor_r3711.patch b/package/madwifi/patches/406-monitor_r3711.patch index d6d4a5b133..d0f4279ace 100644 --- a/package/madwifi/patches/406-monitor_r3711.patch +++ b/package/madwifi/patches/406-monitor_r3711.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -6511,7 +6511,7 @@ ath_capture(struct net_device *dev, cons +@@ -6519,7 +6519,7 @@ ath_capture(struct net_device *dev, cons /* Never copy the SKB, as it is ours on the RX side, and this is the * last process on the TX side and we only modify our own headers. */ @@ -9,7 +9,7 @@ if (tskb == NULL) { DPRINTF(sc, ATH_DEBUG_ANY, "Dropping; ath_skb_removepad failed!\n"); -@@ -6519,6 +6519,8 @@ ath_capture(struct net_device *dev, cons +@@ -6527,6 +6527,8 @@ ath_capture(struct net_device *dev, cons } ieee80211_input_monitor(ic, tskb, bf, tx, tsf, sc); diff --git a/package/madwifi/patches/408-changeset_r3337.patch b/package/madwifi/patches/408-changeset_r3337.patch index e1724725f5..b798082412 100644 --- a/package/madwifi/patches/408-changeset_r3337.patch +++ b/package/madwifi/patches/408-changeset_r3337.patch @@ -10,7 +10,7 @@ Please let us know if you think your name should be mentioned here! --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -3130,7 +3130,7 @@ ath_tx_startraw(struct net_device *dev, +@@ -3138,7 +3138,7 @@ ath_tx_startraw(struct net_device *dev, struct ath_softc *sc = dev->priv; struct ath_hal *ah = sc->sc_ah; struct ieee80211_phy_params *ph = (struct ieee80211_phy_params *) diff --git a/package/madwifi/patches/411-autochannel_multi.patch b/package/madwifi/patches/411-autochannel_multi.patch new file mode 100644 index 0000000000..ab48e70b2c --- /dev/null +++ b/package/madwifi/patches/411-autochannel_multi.patch @@ -0,0 +1,347 @@ +--- a/net80211/ieee80211_scan.c ++++ b/net80211/ieee80211_scan.c +@@ -97,6 +97,123 @@ struct scan_state { + static void scan_restart_pwrsav(unsigned long); + static void scan_next(unsigned long); + ++spinlock_t channel_lock = SPIN_LOCK_UNLOCKED; ++static LIST_HEAD(channels_inuse); ++ ++struct channel_inuse { ++ struct list_head list; ++ struct ieee80211com *ic; ++ u16 freq; ++ u8 bw; ++}; ++ ++static inline u32 ++get_signal(u8 bw, u8 distance) ++{ ++ u32 v; ++ ++ /* signal = 1 - (distance / bw)^2 [scale: 100] */ ++ v = 100 * distance / bw; ++ v = (100 - ((v * v) / 100)); ++ return v; ++} ++ ++static u32 ++get_overlap(u16 f1, u16 f2, u8 b1, u8 b2) ++{ ++ u32 v; ++ u16 d, c; ++ ++ /* add offsets for sidechannel interference */ ++ b1 += (b1 / 5); ++ b2 += (b2 / 5); ++ ++ /* use only one direction */ ++ b1 /= 2; ++ b2 /= 2; ++ ++ if (f1 + b1 < f2 - b2) ++ return 0; ++ ++ d = f2 - f1; ++ c = d * b1 / (b1 + b2); ++ v = get_signal(b1, c); ++ ++ return v * v / 100; ++} ++ ++static u8 ++get_channel_bw(struct ieee80211_channel *c) ++{ ++ switch(c->ic_flags & ( ++ IEEE80211_CHAN_HALF | ++ IEEE80211_CHAN_QUARTER | ++ IEEE80211_CHAN_TURBO | ++ IEEE80211_CHAN_STURBO)) { ++ case IEEE80211_CHAN_QUARTER: ++ return 5; ++ case IEEE80211_CHAN_HALF: ++ return 10; ++ case IEEE80211_CHAN_TURBO: ++ case IEEE80211_CHAN_STURBO: ++ return 40; ++ default: ++ return 20; ++ } ++} ++ ++/* must be called with channel_lock held */ ++u32 ++ieee80211_scan_get_bias(struct ieee80211_channel *c) ++{ ++ struct channel_inuse *ch; ++ u8 bw = get_channel_bw(c); ++ u32 bias = 0; ++ ++ list_for_each_entry(ch, &channels_inuse, list) { ++ if (ch->freq == c->ic_freq) { ++ bias += 50; ++ continue; ++ } ++ if (c->ic_freq < ch->freq) ++ bias += get_overlap(c->ic_freq, ch->freq, bw, ch->bw); ++ else ++ bias += get_overlap(ch->freq, c->ic_freq, ch->bw, bw); ++ } ++ return min(bias, (u32) 100); ++} ++EXPORT_SYMBOL(ieee80211_scan_get_bias); ++ ++/* must be called with channel_lock held */ ++void ++ieee80211_scan_set_bss_channel(struct ieee80211com *ic, struct ieee80211_channel *c) ++{ ++ unsigned long flags; ++ struct channel_inuse *ch; ++ ++ list_for_each_entry(ch, &channels_inuse, list) { ++ if (ch->ic == ic) ++ goto found; ++ } ++ ch = NULL; ++found: ++ if (c && (c != IEEE80211_CHAN_ANYC)) { ++ if (!ch) { ++ ch = kmalloc(sizeof(struct channel_inuse), GFP_ATOMIC); ++ ch->ic = ic; ++ INIT_LIST_HEAD(&ch->list); ++ list_add(&ch->list, &channels_inuse); ++ } ++ ch->freq = c->ic_freq; ++ ch->bw = get_channel_bw(c); ++ } else if (ch) { ++ list_del(&ch->list); ++ kfree(ch); ++ } ++} ++EXPORT_SYMBOL(ieee80211_scan_set_bss_channel); ++ ++ + void + ieee80211_scan_attach(struct ieee80211com *ic) + { +@@ -1155,7 +1272,7 @@ ieee80211_scan_dfs_action(struct ieee802 + IEEE80211_RADAR_CHANCHANGE_TBTT_COUNT; + ic->ic_flags |= IEEE80211_F_CHANSWITCH; + } else { +- ++ unsigned long flags; + IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, + "%s: directly switching to channel " + "%3d (%4d MHz)\n", __func__, +@@ -1166,6 +1283,9 @@ ieee80211_scan_dfs_action(struct ieee802 + * change the channel here. */ + change_channel(ic, new_channel); + ic->ic_bsschan = new_channel; ++ spin_lock_irqsave(&channel_lock, flags); ++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); ++ spin_unlock_irqrestore(&channel_lock, flags); + if (vap->iv_bss) + vap->iv_bss->ni_chan = new_channel; + } +--- a/net80211/ieee80211_scan.h ++++ b/net80211/ieee80211_scan.h +@@ -35,6 +35,7 @@ + + #define IEEE80211_SCAN_MAX IEEE80211_CHAN_MAX + ++extern spinlock_t channel_lock; + struct ieee80211_scanner; + struct ieee80211_scan_entry; + +@@ -116,6 +117,8 @@ void ieee80211_scan_flush(struct ieee802 + struct ieee80211_scan_entry; + typedef int ieee80211_scan_iter_func(void *, const struct ieee80211_scan_entry *); + int ieee80211_scan_iterate(struct ieee80211com *, ieee80211_scan_iter_func *, void *); ++u32 ieee80211_scan_get_bias(struct ieee80211_channel *c); ++void ieee80211_scan_set_bss_channel(struct ieee80211com *ic, struct ieee80211_channel *c); + + /* + * Parameters supplied when adding/updating an entry in a +--- a/net80211/ieee80211.c ++++ b/net80211/ieee80211.c +@@ -373,8 +373,16 @@ void + ieee80211_ifdetach(struct ieee80211com *ic) + { + struct ieee80211vap *vap; ++ unsigned long flags; + int count; + ++ /* mark the channel as no longer in use */ ++ ic->ic_bsschan = IEEE80211_CHAN_ANYC; ++ spin_lock_irqsave(&channel_lock, flags); ++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); ++ spin_unlock_irqrestore(&channel_lock, flags); ++ ++ + /* bring down all vaps */ + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { + ieee80211_stop(vap->iv_dev); +--- a/net80211/ieee80211_input.c ++++ b/net80211/ieee80211_input.c +@@ -2772,6 +2772,7 @@ static void + ieee80211_doth_switch_channel(struct ieee80211vap *vap) + { + struct ieee80211com *ic = vap->iv_ic; ++ unsigned long flags; + + IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, + "%s: Channel switch to %3d (%4d MHz) NOW!\n", +@@ -2794,6 +2795,9 @@ ieee80211_doth_switch_channel(struct iee + + ic->ic_curchan = ic->ic_bsschan = vap->iv_csa_chan; + ic->ic_set_channel(ic); ++ spin_lock_irqsave(&channel_lock, flags); ++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); ++ spin_unlock_irqrestore(&channel_lock, flags); + } + + static void +--- a/net80211/ieee80211_node.c ++++ b/net80211/ieee80211_node.c +@@ -308,6 +308,7 @@ ieee80211_create_ibss(struct ieee80211va + { + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_node *ni; ++ unsigned long flags; + + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, + "%s: creating ibss on channel %u\n", __func__, +@@ -386,6 +387,9 @@ ieee80211_create_ibss(struct ieee80211va + ic->ic_bsschan = chan; + ieee80211_node_set_chan(ic, ni); + ic->ic_curmode = ieee80211_chan2mode(chan); ++ spin_lock_irqsave(&channel_lock, flags); ++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); ++ spin_unlock_irqrestore(&channel_lock, flags); + + /* Update country ie information */ + ieee80211_build_countryie(ic); +@@ -622,6 +626,7 @@ ieee80211_sta_join1(struct ieee80211_nod + struct ieee80211vap *vap = selbs->ni_vap; + struct ieee80211com *ic = selbs->ni_ic; + struct ieee80211_node *obss; ++ unsigned long flags; + int canreassoc; + + if (vap->iv_opmode == IEEE80211_M_IBSS) { +@@ -650,6 +655,9 @@ ieee80211_sta_join1(struct ieee80211_nod + ic->ic_curchan = ic->ic_bsschan; + ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan); + ic->ic_set_channel(ic); ++ spin_lock_irqsave(&channel_lock, flags); ++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); ++ spin_unlock_irqrestore(&channel_lock, flags); + /* + * Set the erp state (mostly the slot time) to deal with + * the auto-select case; this should be redundant if the +--- a/net80211/ieee80211_proto.c ++++ b/net80211/ieee80211_proto.c +@@ -1225,6 +1225,7 @@ ieee80211_dturbo_switch(struct ieee80211 + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + #endif + struct ieee80211_channel *chan; ++ unsigned long flags; + + chan = ieee80211_find_channel(ic, ic->ic_bsschan->ic_freq, newflags); + if (chan == NULL) { /* XXX should not happen */ +@@ -1243,6 +1244,9 @@ ieee80211_dturbo_switch(struct ieee80211 + ic->ic_bsschan = chan; + ic->ic_curchan = chan; + ic->ic_set_channel(ic); ++ spin_lock_irqsave(&channel_lock, flags); ++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); ++ spin_unlock_irqrestore(&channel_lock, flags); + /* NB: do not need to reset ERP state because in sta mode */ + } + EXPORT_SYMBOL(ieee80211_dturbo_switch); +--- a/net80211/ieee80211_wireless.c ++++ b/net80211/ieee80211_wireless.c +@@ -4076,8 +4076,13 @@ ieee80211_ioctl_setchanlist(struct net_d + if (nchan == 0) /* no valid channels, disallow */ + return -EINVAL; + if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */ +- isclr(chanlist, ic->ic_bsschan->ic_ieee)) ++ isclr(chanlist, ic->ic_bsschan->ic_ieee)) { ++ unsigned long flags; + ic->ic_bsschan = IEEE80211_CHAN_ANYC; /* invalidate */ ++ spin_lock_irqsave(&channel_lock, flags); ++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); ++ spin_unlock_irqrestore(&channel_lock, flags); ++ } + + memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active)); + /* update Supported Channels information element */ +--- a/net80211/ieee80211_scan_ap.c ++++ b/net80211/ieee80211_scan_ap.c +@@ -213,9 +213,15 @@ ap_start(struct ieee80211_scan_state *ss + struct ieee80211com *ic = NULL; + int i; + unsigned int mode = 0; ++ unsigned long sflags; + + SCAN_AP_LOCK_IRQ(as); + ic = vap->iv_ic; ++ ++ spin_lock_irqsave(&channel_lock, sflags); ++ ieee80211_scan_set_bss_channel(ic, NULL); ++ spin_unlock_irqrestore(&channel_lock, sflags); ++ + /* Determine mode flags to match, or leave zero for auto mode */ + as->as_vap_desired_mode = vap->iv_des_mode; + as->as_required_mode = 0; +@@ -429,8 +435,10 @@ pc_cmp_idletime(struct ieee80211_channel + if (!a->ic_idletime || !b->ic_idletime) + return 0; + +- /* a is better than b (return < 0) when a has more idle time than b */ +- return b->ic_idletime - a->ic_idletime; ++ /* a is better than b (return < 0) when a has more idle and less bias time than b */ ++ return ++ ((100 - (u32) a->ic_idletime) + ieee80211_scan_get_bias(a)) - ++ ((100 - (u32) b->ic_idletime) + ieee80211_scan_get_bias(b)); + } + + +@@ -616,6 +624,7 @@ ap_end(struct ieee80211_scan_state *ss, + struct ap_state *as = ss->ss_priv; + struct ieee80211_channel *bestchan = NULL; + struct ieee80211com *ic = NULL; ++ unsigned long sflags; + int res = 1; + + SCAN_AP_LOCK_IRQ(as); +@@ -624,8 +633,11 @@ ap_end(struct ieee80211_scan_state *ss, + ("wrong opmode %u", vap->iv_opmode)); + + ic = vap->iv_ic; ++ spin_lock_irqsave(&channel_lock, sflags); ++ ieee80211_scan_set_bss_channel(ic, NULL); + bestchan = pick_channel(ss, vap, flags); + if (bestchan == NULL) { ++ spin_unlock_irqrestore(&channel_lock, sflags); + if (ss->ss_last > 0) { + /* no suitable channel, should not happen */ + printk(KERN_ERR "%s: %s: no suitable channel! " +@@ -644,6 +656,7 @@ ap_end(struct ieee80211_scan_state *ss, + bestchan->ic_freq, bestchan->ic_flags & + ~IEEE80211_CHAN_TURBO)) == NULL) { + /* should never happen ?? */ ++ spin_unlock_irqrestore(&channel_lock, sflags); + SCAN_AP_UNLOCK_IRQ_EARLY(as); + return 0; + } +@@ -656,6 +669,9 @@ ap_end(struct ieee80211_scan_state *ss, + as->as_action = action; + as->as_selbss = se; + ++ ieee80211_scan_set_bss_channel(ic, bestchan); ++ spin_unlock_irqrestore(&channel_lock, sflags); ++ + /* Must defer action to avoid possible recursive call through + * 80211 state machine, which would result in recursive + * locking. */ diff --git a/package/madwifi/patches/450-new_hal.patch b/package/madwifi/patches/450-new_hal.patch deleted file mode 100644 index 0243b80787..0000000000 --- a/package/madwifi/patches/450-new_hal.patch +++ /dev/null @@ -1,135 +0,0 @@ ---- a/ath_hal/ah_os.h -+++ b/ath_hal/ah_os.h -@@ -156,80 +156,23 @@ extern u_int32_t __ahdecl ath_hal_getupt - #endif - #endif /* AH_BYTE_ORDER */ - --/* -- * Some big-endian architectures don't set CONFIG_GENERIC_IOMAP, but fail to -- * implement iowrite32be and ioread32be. Provide compatibility macros when -- * it's needed. -- * -- * As of Linux 2.6.24, only MIPS, PARISC and PowerPC implement iowrite32be and -- * ioread32be as functions. -- * -- * The downside or the replacement macros it that we may be byte-swapping data -- * for the second time, so the native implementations should be preferred. -- */ --#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)) && \ -- !defined(CONFIG_GENERIC_IOMAP) && (AH_BYTE_ORDER == AH_BIG_ENDIAN) && \ -- !defined(__mips__) && !defined(__hppa__) && !defined(__powerpc__) --# ifndef iowrite32be --# define iowrite32be(_val, _addr) iowrite32(swab32((_val)), (_addr)) --# endif --# ifndef ioread32be --# define ioread32be(_addr) swab32(ioread32((_addr))) --# endif --#endif -+#define IS_SWAPPED(_ah, _reg) \ -+ ((_ah)->ah_swapped && \ -+ (((0x4000 <= (_reg)) && ((_reg) < 0x5000)) || \ -+ ((0x7000 <= (_reg)) && ((_reg) < 0x8000)))) -+ -+#define SWAPREG(_ah, _reg, _val) \ -+ (IS_SWAPPED(_ah, _reg) ? cpu_to_le32(_val) : (_val)) - - /* - * The register accesses are done using target-specific functions when - * debugging is enabled (AH_DEBUG) or it's explicitly requested for the target. -- * -- * The hardware registers use little-endian byte order natively. Big-endian -- * systems are configured by HAL to enable hardware byte-swap of register reads -- * and writes at reset. This avoid the need to byte-swap the data in software. -- * However, the registers in a certain area from 0x4000 to 0x4fff (PCI clock -- * domain registers) are not byte swapped! -- * -- * Since Linux I/O primitives default to little-endian operations, we only -- * need to suppress byte-swapping on big-endian systems outside the area used -- * by the PCI clock domain registers. - */ --#if (AH_BYTE_ORDER == AH_BIG_ENDIAN) --#define is_reg_le(__reg) ((0x4000 <= (__reg) && (__reg) < 0x5000)) --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) --#define _OS_REG_WRITE(_ah, _reg, _val) do { \ -- is_reg_le(_reg) ? \ -- iowrite32((_val), (_ah)->ah_sh + (_reg)) : \ -- iowrite32be((_val), (_ah)->ah_sh + (_reg)); \ -- } while (0) --#define _OS_REG_READ(_ah, _reg) \ -- (is_reg_le(_reg) ? \ -- ioread32((_ah)->ah_sh + (_reg)) : \ -- ioread32be((_ah)->ah_sh + (_reg))) --#else --#define _OS_REG_WRITE(_ah, _reg, _val) do { \ -- writel(is_reg_le(_reg) ? \ -- (_val) : cpu_to_le32(_val), \ -- (_ah)->ah_sh + (_reg)); \ -- } while (0) --#define _OS_REG_READ(_ah, _reg) \ -- (is_reg_le(_reg) ? \ -- readl((_ah)->ah_sh + (_reg)) : \ -- cpu_to_le32(readl((_ah)->ah_sh + (_reg)))) --#endif /* KERNEL_VERSION(2,6,12) */ --#else /* AH_BYTE_ORDER != AH_BIG_ENDIAN */ --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) --#define _OS_REG_WRITE(_ah, _reg, _val) do { \ -- iowrite32((_val), (_ah)->ah_sh + (_reg)); \ -- } while (0) --#define _OS_REG_READ(_ah, _reg) \ -- ioread32((_ah)->ah_sh + (_reg)) --#else - #define _OS_REG_WRITE(_ah, _reg, _val) do { \ -- writel((_val), (_ah)->ah_sh + (_reg)); \ -- } while (0) -+ __raw_writel(SWAPREG(_ah, _reg, _val), (_ah)->ah_sh + (_reg)); \ -+} while (0) - #define _OS_REG_READ(_ah, _reg) \ -- readl((_ah)->ah_sh + (_reg)) --#endif /* KERNEL_VERSION(2,6,12) */ --#endif /* AH_BYTE_ORDER != AH_BIG_ENDIAN */ -+ SWAPREG(_ah, _reg, __raw_readl((_ah)->ah_sh + (_reg))) - - /* - * The functions in this section are not intended to be invoked by MadWifi ---- a/ath/if_ath.c -+++ b/ath/if_ath.c -@@ -606,6 +606,14 @@ ath_attach(u_int16_t devid, struct net_d - } - sc->sc_ah = ah; - -+ /* WAR for AR7100 PCI bug */ -+#ifdef CONFIG_ATHEROS_AR71XX -+ if ((ar_device(sc->devid) >= 5210) && (ar_device(sc->devid) < 5416)) { -+ ath_hal_setcapability(ah, HAL_CAP_DMABURST_RX, 0, HAL_DMABURST_4B, NULL); -+ ath_hal_setcapability(ah, HAL_CAP_DMABURST_TX, 0, HAL_DMABURST_4B, NULL); -+ } -+#endif -+ - /* - * Check if the MAC has multi-rate retry support. - * We do this by trying to setup a fake extended -@@ -7555,7 +7563,7 @@ ath_txq_setup(struct ath_softc *sc, int - if (qtype == HAL_TX_QUEUE_UAPSD) - qi.tqi_qflags = HAL_TXQ_TXDESCINT_ENABLE; - else -- qi.tqi_qflags = HAL_TXQ_TXEOLINT_ENABLE | -+ qi.tqi_qflags = HAL_TXQ_TXEOLINT_ENABLE | HAL_TXQ_TXOKINT_ENABLE | - HAL_TXQ_TXDESCINT_ENABLE; - qnum = ath_hal_setuptxqueue(ah, qtype, &qi); - if (qnum == -1) { ---- a/ath_hal/ah_os.c -+++ b/ath_hal/ah_os.c -@@ -126,6 +126,13 @@ ath_hal_printf(struct ath_hal *ah, const - } - EXPORT_SYMBOL(ath_hal_printf); - -+void __ahdecl -+ath_hal_printstr(struct ath_hal *ah, const char *str) -+{ -+ printk("%s", str); -+} -+EXPORT_SYMBOL(ath_hal_printstr); -+ - /* - * Format an Ethernet MAC for printing. - */ diff --git a/package/madwifi/patches/460-autochannel_multi.patch b/package/madwifi/patches/460-autochannel_multi.patch deleted file mode 100644 index ab48e70b2c..0000000000 --- a/package/madwifi/patches/460-autochannel_multi.patch +++ /dev/null @@ -1,347 +0,0 @@ ---- a/net80211/ieee80211_scan.c -+++ b/net80211/ieee80211_scan.c -@@ -97,6 +97,123 @@ struct scan_state { - static void scan_restart_pwrsav(unsigned long); - static void scan_next(unsigned long); - -+spinlock_t channel_lock = SPIN_LOCK_UNLOCKED; -+static LIST_HEAD(channels_inuse); -+ -+struct channel_inuse { -+ struct list_head list; -+ struct ieee80211com *ic; -+ u16 freq; -+ u8 bw; -+}; -+ -+static inline u32 -+get_signal(u8 bw, u8 distance) -+{ -+ u32 v; -+ -+ /* signal = 1 - (distance / bw)^2 [scale: 100] */ -+ v = 100 * distance / bw; -+ v = (100 - ((v * v) / 100)); -+ return v; -+} -+ -+static u32 -+get_overlap(u16 f1, u16 f2, u8 b1, u8 b2) -+{ -+ u32 v; -+ u16 d, c; -+ -+ /* add offsets for sidechannel interference */ -+ b1 += (b1 / 5); -+ b2 += (b2 / 5); -+ -+ /* use only one direction */ -+ b1 /= 2; -+ b2 /= 2; -+ -+ if (f1 + b1 < f2 - b2) -+ return 0; -+ -+ d = f2 - f1; -+ c = d * b1 / (b1 + b2); -+ v = get_signal(b1, c); -+ -+ return v * v / 100; -+} -+ -+static u8 -+get_channel_bw(struct ieee80211_channel *c) -+{ -+ switch(c->ic_flags & ( -+ IEEE80211_CHAN_HALF | -+ IEEE80211_CHAN_QUARTER | -+ IEEE80211_CHAN_TURBO | -+ IEEE80211_CHAN_STURBO)) { -+ case IEEE80211_CHAN_QUARTER: -+ return 5; -+ case IEEE80211_CHAN_HALF: -+ return 10; -+ case IEEE80211_CHAN_TURBO: -+ case IEEE80211_CHAN_STURBO: -+ return 40; -+ default: -+ return 20; -+ } -+} -+ -+/* must be called with channel_lock held */ -+u32 -+ieee80211_scan_get_bias(struct ieee80211_channel *c) -+{ -+ struct channel_inuse *ch; -+ u8 bw = get_channel_bw(c); -+ u32 bias = 0; -+ -+ list_for_each_entry(ch, &channels_inuse, list) { -+ if (ch->freq == c->ic_freq) { -+ bias += 50; -+ continue; -+ } -+ if (c->ic_freq < ch->freq) -+ bias += get_overlap(c->ic_freq, ch->freq, bw, ch->bw); -+ else -+ bias += get_overlap(ch->freq, c->ic_freq, ch->bw, bw); -+ } -+ return min(bias, (u32) 100); -+} -+EXPORT_SYMBOL(ieee80211_scan_get_bias); -+ -+/* must be called with channel_lock held */ -+void -+ieee80211_scan_set_bss_channel(struct ieee80211com *ic, struct ieee80211_channel *c) -+{ -+ unsigned long flags; -+ struct channel_inuse *ch; -+ -+ list_for_each_entry(ch, &channels_inuse, list) { -+ if (ch->ic == ic) -+ goto found; -+ } -+ ch = NULL; -+found: -+ if (c && (c != IEEE80211_CHAN_ANYC)) { -+ if (!ch) { -+ ch = kmalloc(sizeof(struct channel_inuse), GFP_ATOMIC); -+ ch->ic = ic; -+ INIT_LIST_HEAD(&ch->list); -+ list_add(&ch->list, &channels_inuse); -+ } -+ ch->freq = c->ic_freq; -+ ch->bw = get_channel_bw(c); -+ } else if (ch) { -+ list_del(&ch->list); -+ kfree(ch); -+ } -+} -+EXPORT_SYMBOL(ieee80211_scan_set_bss_channel); -+ -+ - void - ieee80211_scan_attach(struct ieee80211com *ic) - { -@@ -1155,7 +1272,7 @@ ieee80211_scan_dfs_action(struct ieee802 - IEEE80211_RADAR_CHANCHANGE_TBTT_COUNT; - ic->ic_flags |= IEEE80211_F_CHANSWITCH; - } else { -- -+ unsigned long flags; - IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, - "%s: directly switching to channel " - "%3d (%4d MHz)\n", __func__, -@@ -1166,6 +1283,9 @@ ieee80211_scan_dfs_action(struct ieee802 - * change the channel here. */ - change_channel(ic, new_channel); - ic->ic_bsschan = new_channel; -+ spin_lock_irqsave(&channel_lock, flags); -+ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); -+ spin_unlock_irqrestore(&channel_lock, flags); - if (vap->iv_bss) - vap->iv_bss->ni_chan = new_channel; - } ---- a/net80211/ieee80211_scan.h -+++ b/net80211/ieee80211_scan.h -@@ -35,6 +35,7 @@ - - #define IEEE80211_SCAN_MAX IEEE80211_CHAN_MAX - -+extern spinlock_t channel_lock; - struct ieee80211_scanner; - struct ieee80211_scan_entry; - -@@ -116,6 +117,8 @@ void ieee80211_scan_flush(struct ieee802 - struct ieee80211_scan_entry; - typedef int ieee80211_scan_iter_func(void *, const struct ieee80211_scan_entry *); - int ieee80211_scan_iterate(struct ieee80211com *, ieee80211_scan_iter_func *, void *); -+u32 ieee80211_scan_get_bias(struct ieee80211_channel *c); -+void ieee80211_scan_set_bss_channel(struct ieee80211com *ic, struct ieee80211_channel *c); - - /* - * Parameters supplied when adding/updating an entry in a ---- a/net80211/ieee80211.c -+++ b/net80211/ieee80211.c -@@ -373,8 +373,16 @@ void - ieee80211_ifdetach(struct ieee80211com *ic) - { - struct ieee80211vap *vap; -+ unsigned long flags; - int count; - -+ /* mark the channel as no longer in use */ -+ ic->ic_bsschan = IEEE80211_CHAN_ANYC; -+ spin_lock_irqsave(&channel_lock, flags); -+ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); -+ spin_unlock_irqrestore(&channel_lock, flags); -+ -+ - /* bring down all vaps */ - TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { - ieee80211_stop(vap->iv_dev); ---- a/net80211/ieee80211_input.c -+++ b/net80211/ieee80211_input.c -@@ -2772,6 +2772,7 @@ static void - ieee80211_doth_switch_channel(struct ieee80211vap *vap) - { - struct ieee80211com *ic = vap->iv_ic; -+ unsigned long flags; - - IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, - "%s: Channel switch to %3d (%4d MHz) NOW!\n", -@@ -2794,6 +2795,9 @@ ieee80211_doth_switch_channel(struct iee - - ic->ic_curchan = ic->ic_bsschan = vap->iv_csa_chan; - ic->ic_set_channel(ic); -+ spin_lock_irqsave(&channel_lock, flags); -+ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); -+ spin_unlock_irqrestore(&channel_lock, flags); - } - - static void ---- a/net80211/ieee80211_node.c -+++ b/net80211/ieee80211_node.c -@@ -308,6 +308,7 @@ ieee80211_create_ibss(struct ieee80211va - { - struct ieee80211com *ic = vap->iv_ic; - struct ieee80211_node *ni; -+ unsigned long flags; - - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: creating ibss on channel %u\n", __func__, -@@ -386,6 +387,9 @@ ieee80211_create_ibss(struct ieee80211va - ic->ic_bsschan = chan; - ieee80211_node_set_chan(ic, ni); - ic->ic_curmode = ieee80211_chan2mode(chan); -+ spin_lock_irqsave(&channel_lock, flags); -+ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); -+ spin_unlock_irqrestore(&channel_lock, flags); - - /* Update country ie information */ - ieee80211_build_countryie(ic); -@@ -622,6 +626,7 @@ ieee80211_sta_join1(struct ieee80211_nod - struct ieee80211vap *vap = selbs->ni_vap; - struct ieee80211com *ic = selbs->ni_ic; - struct ieee80211_node *obss; -+ unsigned long flags; - int canreassoc; - - if (vap->iv_opmode == IEEE80211_M_IBSS) { -@@ -650,6 +655,9 @@ ieee80211_sta_join1(struct ieee80211_nod - ic->ic_curchan = ic->ic_bsschan; - ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan); - ic->ic_set_channel(ic); -+ spin_lock_irqsave(&channel_lock, flags); -+ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); -+ spin_unlock_irqrestore(&channel_lock, flags); - /* - * Set the erp state (mostly the slot time) to deal with - * the auto-select case; this should be redundant if the ---- a/net80211/ieee80211_proto.c -+++ b/net80211/ieee80211_proto.c -@@ -1225,6 +1225,7 @@ ieee80211_dturbo_switch(struct ieee80211 - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - #endif - struct ieee80211_channel *chan; -+ unsigned long flags; - - chan = ieee80211_find_channel(ic, ic->ic_bsschan->ic_freq, newflags); - if (chan == NULL) { /* XXX should not happen */ -@@ -1243,6 +1244,9 @@ ieee80211_dturbo_switch(struct ieee80211 - ic->ic_bsschan = chan; - ic->ic_curchan = chan; - ic->ic_set_channel(ic); -+ spin_lock_irqsave(&channel_lock, flags); -+ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); -+ spin_unlock_irqrestore(&channel_lock, flags); - /* NB: do not need to reset ERP state because in sta mode */ - } - EXPORT_SYMBOL(ieee80211_dturbo_switch); ---- a/net80211/ieee80211_wireless.c -+++ b/net80211/ieee80211_wireless.c -@@ -4076,8 +4076,13 @@ ieee80211_ioctl_setchanlist(struct net_d - if (nchan == 0) /* no valid channels, disallow */ - return -EINVAL; - if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */ -- isclr(chanlist, ic->ic_bsschan->ic_ieee)) -+ isclr(chanlist, ic->ic_bsschan->ic_ieee)) { -+ unsigned long flags; - ic->ic_bsschan = IEEE80211_CHAN_ANYC; /* invalidate */ -+ spin_lock_irqsave(&channel_lock, flags); -+ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); -+ spin_unlock_irqrestore(&channel_lock, flags); -+ } - - memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active)); - /* update Supported Channels information element */ ---- a/net80211/ieee80211_scan_ap.c -+++ b/net80211/ieee80211_scan_ap.c -@@ -213,9 +213,15 @@ ap_start(struct ieee80211_scan_state *ss - struct ieee80211com *ic = NULL; - int i; - unsigned int mode = 0; -+ unsigned long sflags; - - SCAN_AP_LOCK_IRQ(as); - ic = vap->iv_ic; -+ -+ spin_lock_irqsave(&channel_lock, sflags); -+ ieee80211_scan_set_bss_channel(ic, NULL); -+ spin_unlock_irqrestore(&channel_lock, sflags); -+ - /* Determine mode flags to match, or leave zero for auto mode */ - as->as_vap_desired_mode = vap->iv_des_mode; - as->as_required_mode = 0; -@@ -429,8 +435,10 @@ pc_cmp_idletime(struct ieee80211_channel - if (!a->ic_idletime || !b->ic_idletime) - return 0; - -- /* a is better than b (return < 0) when a has more idle time than b */ -- return b->ic_idletime - a->ic_idletime; -+ /* a is better than b (return < 0) when a has more idle and less bias time than b */ -+ return -+ ((100 - (u32) a->ic_idletime) + ieee80211_scan_get_bias(a)) - -+ ((100 - (u32) b->ic_idletime) + ieee80211_scan_get_bias(b)); - } - - -@@ -616,6 +624,7 @@ ap_end(struct ieee80211_scan_state *ss, - struct ap_state *as = ss->ss_priv; - struct ieee80211_channel *bestchan = NULL; - struct ieee80211com *ic = NULL; -+ unsigned long sflags; - int res = 1; - - SCAN_AP_LOCK_IRQ(as); -@@ -624,8 +633,11 @@ ap_end(struct ieee80211_scan_state *ss, - ("wrong opmode %u", vap->iv_opmode)); - - ic = vap->iv_ic; -+ spin_lock_irqsave(&channel_lock, sflags); -+ ieee80211_scan_set_bss_channel(ic, NULL); - bestchan = pick_channel(ss, vap, flags); - if (bestchan == NULL) { -+ spin_unlock_irqrestore(&channel_lock, sflags); - if (ss->ss_last > 0) { - /* no suitable channel, should not happen */ - printk(KERN_ERR "%s: %s: no suitable channel! " -@@ -644,6 +656,7 @@ ap_end(struct ieee80211_scan_state *ss, - bestchan->ic_freq, bestchan->ic_flags & - ~IEEE80211_CHAN_TURBO)) == NULL) { - /* should never happen ?? */ -+ spin_unlock_irqrestore(&channel_lock, sflags); - SCAN_AP_UNLOCK_IRQ_EARLY(as); - return 0; - } -@@ -656,6 +669,9 @@ ap_end(struct ieee80211_scan_state *ss, - as->as_action = action; - as->as_selbss = se; - -+ ieee80211_scan_set_bss_channel(ic, bestchan); -+ spin_unlock_irqrestore(&channel_lock, sflags); -+ - /* Must defer action to avoid possible recursive call through - * 80211 state machine, which would result in recursive - * locking. */