reorganize madwifi patches slightly
authorFelix Fietkau <nbd@openwrt.org>
Mon, 23 Mar 2009 12:11:17 +0000 (12:11 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Mon, 23 Mar 2009 12:11:17 +0000 (12:11 +0000)
SVN-Revision: 14988

package/madwifi/patches/400-changeset_r3402.patch [deleted file]
package/madwifi/patches/400-new_hal.patch [new file with mode: 0644]
package/madwifi/patches/406-monitor_r3711.patch
package/madwifi/patches/408-changeset_r3337.patch
package/madwifi/patches/411-autochannel_multi.patch [new file with mode: 0644]
package/madwifi/patches/450-new_hal.patch [deleted file]
package/madwifi/patches/460-autochannel_multi.patch [deleted file]

diff --git a/package/madwifi/patches/400-changeset_r3402.patch b/package/madwifi/patches/400-changeset_r3402.patch
deleted file mode 100644 (file)
index f43a6d9..0000000
+++ /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 (file)
index 0000000..a586b22
--- /dev/null
@@ -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
index d6d4a5b133a8a80d57c5902b352d5cce1d25f921..d0f4279ace2e13ba7015b4eb6ea77c434e89212d 100644 (file)
@@ -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);
index e1724725f5f84af6d1d9d6aadf01132f37d1d9da..b7980824126fd68a77a679381217c3cd2b5815d2 100644 (file)
@@ -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 (file)
index 0000000..ab48e70
--- /dev/null
@@ -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 (file)
index 0243b80..0000000
+++ /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 (file)
index ab48e70..0000000
+++ /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. */