huge madwifi update (work in progress, disabled by default, compiles but breaks at...
authorFelix Fietkau <nbd@openwrt.org>
Thu, 17 Jul 2008 02:30:08 +0000 (02:30 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Thu, 17 Jul 2008 02:30:08 +0000 (02:30 +0000)
SVN-Revision: 11851

45 files changed:
package/madwifi/Config.in
package/madwifi/Makefile
package/madwifi/patches-r3776/102-multicall_binary.patch [new file with mode: 0644]
package/madwifi/patches-r3776/104-autocreate_none.patch [new file with mode: 0644]
package/madwifi/patches-r3776/105-ratectl_attach.patch [new file with mode: 0644]
package/madwifi/patches-r3776/111-minstrel_crash.patch [new file with mode: 0644]
package/madwifi/patches-r3776/122-replayfail_workaround.patch [new file with mode: 0644]
package/madwifi/patches-r3776/123-ccmp_checks.patch [new file with mode: 0644]
package/madwifi/patches-r3776/124-linux24_compat.patch [new file with mode: 0644]
package/madwifi/patches-r3776/126-rxerr_frames.patch [new file with mode: 0644]
package/madwifi/patches-r3776/200-no_debug.patch [new file with mode: 0644]
package/madwifi/patches-r3776/201-no_debug_extra.patch [new file with mode: 0644]
package/madwifi/patches-r3776/300-napi_polling.patch [new file with mode: 0644]
package/madwifi/patches-r3776/301-pureg_fix.patch [new file with mode: 0644]
package/madwifi/patches-r3776/302-noise_get.patch [new file with mode: 0644]
package/madwifi/patches-r3776/303-bssid_alloc.patch [new file with mode: 0644]
package/madwifi/patches-r3776/304-erp_update.patch [new file with mode: 0644]
package/madwifi/patches-r3776/305-bssid_mask.patch [new file with mode: 0644]
package/madwifi/patches-r3776/306-queue.patch [new file with mode: 0644]
package/madwifi/patches-r3776/307-maxrate.patch [new file with mode: 0644]
package/madwifi/patches-r3776/308-minrate.patch [new file with mode: 0644]
package/madwifi/patches-r3776/309-performance.patch [new file with mode: 0644]
package/madwifi/patches-r3776/310-minstrel_sampling.patch [new file with mode: 0644]
package/madwifi/patches-r3776/311-protmode_trigger.patch [new file with mode: 0644]
package/madwifi/patches-r3776/312-ack_cts_rate.patch [new file with mode: 0644]
package/madwifi/patches-r3776/313-reset_channelchange.patch [new file with mode: 0644]
package/madwifi/patches-r3776/314-wisoc_softled.patch [new file with mode: 0644]
package/madwifi/patches-r3776/315-scanlist.patch [new file with mode: 0644]
package/madwifi/patches-r3776/316-ani_fix.patch [new file with mode: 0644]
package/madwifi/patches-r3776/317-devid.patch [new file with mode: 0644]
package/madwifi/patches-r3776/318-ifxmips_eeprom.patch [new file with mode: 0644]
package/madwifi/patches-r3776/319-eap_auth_disassoc.patch [new file with mode: 0644]
package/madwifi/patches-r3776/320-hidden_ssid.patch [new file with mode: 0644]
package/madwifi/patches-r3776/321-bgscan_rssi_thresh.patch [new file with mode: 0644]
package/madwifi/patches-r3776/322-ignore_broken_bssid.patch [new file with mode: 0644]
package/madwifi/patches-r3776/323-crash_fix.patch [new file with mode: 0644]
package/madwifi/patches-r3776/324-reassoc.patch [new file with mode: 0644]
package/madwifi/patches-r3776/325-sta_node_leave.patch [new file with mode: 0644]
package/madwifi/patches-r3776/326-bmiss_handling.patch [new file with mode: 0644]
package/madwifi/patches-r3776/327-rssi_disconnect.patch [new file with mode: 0644]
package/madwifi/patches-r3776/328-memory_alloc.patch [new file with mode: 0644]
package/madwifi/patches-r3776/329-turbo_chansearch.patch [new file with mode: 0644]
package/madwifi/patches-r3776/330-bstuck_thresh.patch [new file with mode: 0644]
package/madwifi/patches-r3776/331-linux24_fix.patch [new file with mode: 0644]
package/madwifi/patches-r3776/332-retransmit_check.patch [new file with mode: 0644]

index 7616607da3a20cbc61db7cf311c7918ae03b8d17..913bd0a1002381729723a8121d7a649b83d7e0b6 100644 (file)
@@ -5,6 +5,14 @@ config MADWIFI_DEBUG
        depends on EXPERIMENTAL && PACKAGE_kmod-madwifi
        default n
 
+config MADWIFI_TESTING
+       bool "Use the testing version of MadWiFi"
+       depends on PACKAGE_kmod-madwifi
+       default n
+       help
+         Use the testing version of MadWiFi, which is newer, but also less tested
+         May contain unexpected bugs :)
+
 choice
        prompt "Rate control algorithm selection"
        depends on PACKAGE_kmod-madwifi
index ac15b2c67c62e05fea35a0b0316ab15cb347f375..a27af52ab1100daafd597ce468b30d4edb3d2066 100644 (file)
@@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
 include $(INCLUDE_DIR)/kernel.mk
 
 PKG_NAME:=madwifi
-PKG_REV:=3314
+PKG_REV:=$(if $(CONFIG_MADWIFI_TESTING),3776,3314)
 PKG_VERSION:=r$(PKG_REV)
 # PKG_BRANCH:=madwifi-dfs
 PKG_RELEASE:=1
@@ -23,6 +23,8 @@ PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.gz
 
 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(if $(PKG_BRANCH),$(PKG_BRANCH),madwifi-trunk)-$(PKG_VERSION)
 
+PATCH_DIR=$(if $(CONFIG_MADWIFI_TESTING),./patches-r$(PKG_REV),./patches)
+
 include $(INCLUDE_DIR)/package.mk
 
 ifneq ($(CONFIG_TARGET_atheros),)
@@ -151,10 +153,14 @@ MAKE_ARGS:= \
        KERNELPATH="$(LINUX_DIR)" \
        LDOPTS="--no-warn-mismatch " \
        ATH_RATE="ath_rate/$(RATE_CONTROL)" \
-       WARNINGS="-Wno-unused" \
-       $(if $(CONFIG_MADWIFI_DEBUG),,DEBUG="") \
        DO_MULTI=1
 
+ifneq ($(CONFIG_MADWIFI_TESTING),)
+  MAKE_ARGS += $(if $(CONFIG_MADWIFI_DEBUG),,ATH_DEBUG=)
+else
+  MAKE_ARGS += $(if $(CONFIG_MADWIFI_DEBUG),,DEBUG=) WARNINGS="-Wno-unused"
+endif
+
 MAKE_VARS:= \
        COPTS="-DCONFIG_ATHEROS_RATE_DEFAULT='\"$(RATE_CONTROL)\"' -DATH_REVERSE_ENGINEERING=1" \
 
diff --git a/package/madwifi/patches-r3776/102-multicall_binary.patch b/package/madwifi/patches-r3776/102-multicall_binary.patch
new file mode 100644 (file)
index 0000000..3dcbb04
--- /dev/null
@@ -0,0 +1,383 @@
+Index: madwifi-trunk-r3776/tools/80211debug.c
+===================================================================
+--- madwifi-trunk-r3776.orig/tools/80211debug.c        2008-07-17 00:22:03.000000000 +0200
++++ madwifi-trunk-r3776/tools/80211debug.c     2008-07-17 00:23:16.000000000 +0200
+@@ -48,6 +48,7 @@
+ #include <ctype.h>
+ #include <getopt.h>
+ #include <err.h>
++#include "do_multi.h"
+ #undef ARRAY_SIZE
+ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+@@ -185,7 +186,7 @@
+ #endif /* __linux__ */
+ int
+-main(int argc, char *argv[])
++CMD(a80211debug)(int argc, char *argv[])
+ {
+       const char *ifname = "ath0";
+       const char *cp, *tp;
+Index: madwifi-trunk-r3776/tools/80211stats.c
+===================================================================
+--- madwifi-trunk-r3776.orig/tools/80211stats.c        2008-07-17 00:22:03.000000000 +0200
++++ madwifi-trunk-r3776/tools/80211stats.c     2008-07-17 00:23:16.000000000 +0200
+@@ -59,6 +59,7 @@
+ #include "net80211/ieee80211.h"
+ #include "net80211/ieee80211_crypto.h"
+ #include "net80211/ieee80211_ioctl.h"
++#include "do_multi.h"
+ #ifndef SIOCG80211STATS
+ #define       SIOCG80211STATS (SIOCDEVPRIVATE + 2)
+@@ -241,7 +242,7 @@
+ }
+ int
+-main(int argc, char *argv[])
++CMD(a80211stats)(int argc, char *argv[])
+ {
+       int c, len;
+       struct ieee80211req_sta_info *si;
+Index: madwifi-trunk-r3776/tools/athchans.c
+===================================================================
+--- madwifi-trunk-r3776.orig/tools/athchans.c  2008-07-17 00:22:03.000000000 +0200
++++ madwifi-trunk-r3776/tools/athchans.c       2008-07-17 00:23:16.000000000 +0200
+@@ -58,6 +58,7 @@
+ #include "net80211/ieee80211.h"
+ #include "net80211/ieee80211_crypto.h"
+ #include "net80211/ieee80211_ioctl.h"
++#include "do_multi.h"
+ static        int s = -1;
+ static const char *progname;
+@@ -140,8 +141,9 @@
+ }
+ #define       MAXCHAN ((int)(sizeof(struct ieee80211req_chanlist) * NBBY))
++
+ int
+-main(int argc, char *argv[])
++CMD(athchans)(int argc, char *argv[])
+ {
+       const char *ifname = "wifi0";
+       struct ieee80211req_chanlist chanlist;
+Index: madwifi-trunk-r3776/tools/athctrl.c
+===================================================================
+--- madwifi-trunk-r3776.orig/tools/athctrl.c   2008-07-17 00:22:03.000000000 +0200
++++ madwifi-trunk-r3776/tools/athctrl.c        2008-07-17 00:23:16.000000000 +0200
+@@ -52,6 +52,7 @@
+ #include <err.h>
+ #include <net/if.h>
++#include "do_multi.h"
+ static int
+ setsysctrl(const char *dev, const char *control , u_long value)
+@@ -88,7 +89,7 @@
+ }
+ int
+-main(int argc, char *argv[])
++CMD(athctrl)(int argc, char *argv[])
+ {
+       char device[IFNAMSIZ + 1];
+       int distance = -1;
+Index: madwifi-trunk-r3776/tools/athdebug.c
+===================================================================
+--- madwifi-trunk-r3776.orig/tools/athdebug.c  2008-07-17 00:22:03.000000000 +0200
++++ madwifi-trunk-r3776/tools/athdebug.c       2008-07-17 00:23:16.000000000 +0200
+@@ -51,6 +51,7 @@
+ #include <ctype.h>
+ #include <getopt.h>
+ #include <err.h>
++#include "do_multi.h"
+ #undef ARRAY_SIZE
+ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+@@ -194,7 +195,7 @@
+ #endif /* __linux__ */
+ int
+-main(int argc, char *argv[])
++CMD(athdebug)(int argc, char *argv[])
+ {
+ #ifdef __linux__
+       const char *ifname = "wifi0";
+Index: madwifi-trunk-r3776/tools/athkey.c
+===================================================================
+--- madwifi-trunk-r3776.orig/tools/athkey.c    2008-07-17 00:22:03.000000000 +0200
++++ madwifi-trunk-r3776/tools/athkey.c 2008-07-17 00:23:16.000000000 +0200
+@@ -58,6 +58,7 @@
+ #include "net80211/ieee80211.h"
+ #include "net80211/ieee80211_crypto.h"
+ #include "net80211/ieee80211_ioctl.h"
++#include "do_multi.h"
+ static int s = -1;
+ static const char *progname;
+@@ -213,8 +214,7 @@
+       exit(-1);
+ }
+-int
+-main(int argc, char *argv[])
++int CMD(athkey)(int argc, char *argv[])
+ {
+       const char *ifname = "wifi0";
+       struct ieee80211req_key setkey;
+Index: madwifi-trunk-r3776/tools/athstats.c
+===================================================================
+--- madwifi-trunk-r3776.orig/tools/athstats.c  2008-07-17 00:22:03.000000000 +0200
++++ madwifi-trunk-r3776/tools/athstats.c       2008-07-17 00:23:16.000000000 +0200
+@@ -65,6 +65,7 @@
+ #undef ARRAY_SIZE
+ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
++#include "do_multi.h"
+ static const struct {
+       u_int           phyerr;
+@@ -228,7 +229,7 @@
+ }
+ int
+-main(int argc, char *argv[])
++CMD(athstats)(int argc, char *argv[])
+ {
+ #ifdef __linux__
+       const char *ifname = "wifi0";
+Index: madwifi-trunk-r3776/tools/do_multi.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ madwifi-trunk-r3776/tools/do_multi.c       2008-07-17 00:46:52.000000000 +0200
+@@ -0,0 +1,36 @@
++#include <string.h>
++#include "do_multi.h"
++
++int
++main(int argc, char *argv[])
++{
++    char *progname;
++    int ret = 0;
++
++    progname = basename(argv[0]);
++
++    if(strcmp(progname, "80211debug") == 0)
++      ret = a80211debug_init(argc, argv);
++    if(strcmp(progname, "80211stats") == 0)
++      ret = a80211stats_init(argc, argv);
++    if(strcmp(progname, "athchans") == 0)
++      ret = athchans_init(argc, argv);
++    if(strcmp(progname, "athctrl") == 0)
++      ret =  athctrl_init(argc, argv);
++    if(strcmp(progname, "athdebug") == 0)
++      ret =  athdebug_init(argc, argv);
++    if(strcmp(progname, "athkey") == 0)
++      ret =  athkey_init(argc, argv);
++    if(strcmp(progname, "athstats") == 0)
++      ret =  athstats_init(argc, argv);
++    if(strcmp(progname, "wlanconfig") == 0)
++      ret =  wlanconfig_init(argc, argv);
++    if(strcmp(progname, "wpakey") == 0)
++      ret =  wpakey_init(argc, argv);
++    if(strcmp(progname, "athchans") == 0)
++      ret =  athchans_init(argc, argv);
++    if(strcmp(progname, "ath_info") == 0)
++      ret =  athinfo_init(argc, argv);
++
++    return ret;
++}
+Index: madwifi-trunk-r3776/tools/do_multi.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ madwifi-trunk-r3776/tools/do_multi.h       2008-07-17 00:23:16.000000000 +0200
+@@ -0,0 +1,15 @@
++#ifdef DO_MULTI
++int a80211debug_init(int argc, char *argv[]);
++int a80211stats_init(int argc, char *argv[]);
++int athchans_init(int argc, char *argv[]);
++int athctrl_init(int argc, char *argv[]);
++int athdebug_init(int argc, char *argv[]);
++int athkey_init(int argc, char *argv[]);
++int athstats_init(int argc, char *argv[]);
++int wlanconfig_init(int argc, char *argv[]);
++int athinfo_init(int argc, char *argv[]);
++
++#define CMD(name) name##_init
++#else
++#define CMD(name) main
++#endif
+Index: madwifi-trunk-r3776/tools/Makefile
+===================================================================
+--- madwifi-trunk-r3776.orig/tools/Makefile    2008-07-17 00:22:03.000000000 +0200
++++ madwifi-trunk-r3776/tools/Makefile 2008-07-17 00:45:15.000000000 +0200
+@@ -50,42 +50,43 @@
+ PROGRAMS = athstats 80211stats athkey athchans athctrl \
+       athdebug 80211debug wlanconfig wpakey
++OBJS = $(patsubst %,%.o,$(PROGRAMS)) ath_info/ath_info.o
+ SUBDIRS = ath_info
+-INCS = -I. -I$(HAL) -I$(TOP) -I$(ATH_HAL)
++INCS = -I. -I$(HAL) -I$(TOP) -I$(ATH_HAL) -I$(TOP)/ath
+ CFLAGS = -g -O2 -Wall
+ ALL_CFLAGS = $(CFLAGS) $(INCS)
+ LDFLAGS =
+-all: all-subdirs $(PROGRAMS)
++all: all-subdirs compile
+ all-subdirs:
+       for d in $(SUBDIRS); do \
+               $(MAKE) -C $$d || exit 1; \
+       done
+-athstats: athstats.c
+-      $(CC) -o athstats $(ALL_CFLAGS) -I$(TOP)/ath $(LDFLAGS) athstats.c
+-80211stats: 80211stats.c
+-      $(CC) -o 80211stats $(ALL_CFLAGS) $(LDFLAGS) 80211stats.c
+-athkey: athkey.c
+-      $(CC) -o athkey $(ALL_CFLAGS) $(LDFLAGS) athkey.c
+-athchans: athchans.c
+-      $(CC) -o athchans $(ALL_CFLAGS) $(LDFLAGS) athchans.c
+-athctrl: athctrl.c
+-      $(CC) -o athctrl $(ALL_CFLAGS) $(LDFLAGS) athctrl.c
+-athdebug: athdebug.c
+-      $(CC) -o athdebug $(ALL_CFLAGS) $(LDFLAGS) athdebug.c
+-wlanconfig: wlanconfig.c
+-      $(CC) -o wlanconfig $(ALL_CFLAGS) $(LDFLAGS) wlanconfig.c
+-80211debug: 80211debug.c
+-      $(CC) -o 80211debug $(ALL_CFLAGS) $(LDFLAGS) 80211debug.c
+-wpakey: wpakey.c
+-      $(CC) -o wpakey $(ALL_CFLAGS) $(LDFLAGS) wpakey.c
++%.o: %.c
++      ${CC} $(ALL_CFLAGS) -c -o $@  $<
++
++ifneq ($(DO_MULTI),)
++ALL_CFLAGS += -DDO_MULTI=1
++madwifi_multi: $(OBJS) do_multi.o
++      $(CC) $(LDFLAGS) -o $@ $^
++
++compile: madwifi_multi
++      for i in $(PROGRAMS); do \
++              ln -sf madwifi_multi $$i; \
++      done
++else
++$(PROGRAMS):
++      $(CC) $(ALL_CFLAGS) -o $@ $@.c
++
++compile: $(PROGRAMS)
++endif
+ install: all
+       install -d $(DESTDIR)$(BINDIR)
+-      for i in $(PROGRAMS); do \
++      for i in $(PROGRAMS) $(if $(DO_MULTI),madwifi_multi); do \
+               install $$i $(DESTDIR)$(BINDIR)/$$i; \
+               $(STRIP) $(DESTDIR)$(BINDIR)/$$i; \
+       done
+@@ -97,7 +98,7 @@
+       done
+ uninstall:
+-      for i in $(PROGRAMS); do \
++      for i in $(PROGRAMS) $(if $(DO_MULTI),madwifi_multi); do \
+               rm -f $(DESTDIR)$(BINDIR)/$$i; \
+       done
+       for i in $(PROGRAMS:=.8); do \
+@@ -108,7 +109,7 @@
+       done
+ clean:
+-      rm -f $(PROGRAMS) core a.out
++      rm -f $(if $(DO_MULTI), madwifi_multi) $(PROGRAMS) core a.out *.o
+       for d in $(SUBDIRS); do \
+               $(MAKE) -C $$d clean; \
+       done
+Index: madwifi-trunk-r3776/tools/wlanconfig.c
+===================================================================
+--- madwifi-trunk-r3776.orig/tools/wlanconfig.c        2008-07-17 00:22:03.000000000 +0200
++++ madwifi-trunk-r3776/tools/wlanconfig.c     2008-07-17 00:45:42.000000000 +0200
+@@ -61,6 +61,7 @@
+ #include "net80211/ieee80211.h"
+ #include "net80211/ieee80211_crypto.h"
+ #include "net80211/ieee80211_ioctl.h"
++#include "do_multi.h"
+ /*
+  * These are taken from ieee80211_node.h
+@@ -100,7 +101,7 @@
+ static int verbose = 0;
+ int
+-main(int argc, char *argv[])
++CMD(wlanconfig)(int argc, char *argv[])
+ {
+       const char *ifname, *cmd;
+       unsigned char bnounit = 0;
+Index: madwifi-trunk-r3776/tools/ath_info/Makefile
+===================================================================
+--- madwifi-trunk-r3776.orig/tools/ath_info/Makefile   2008-07-17 00:21:42.000000000 +0200
++++ madwifi-trunk-r3776/tools/ath_info/Makefile        2008-07-17 00:36:23.000000000 +0200
+@@ -15,13 +15,13 @@
+ PROGRAMS = ath_info
+ MANS = ath_info.8
+-all: $(PROGRAMS)
++all: $(if $(DO_MULTI),ath_info.o,$(PROGRAMS))
+ ath_info: ath_info.o
+       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
+ .c.o:
+-      $(CC) $(CFLAGS) -c $<
++      $(CC) $(CFLAGS) $(if $(DO_MULTI),-DDO_MULTI=1 -I..) -c $<
+ clean:
+       rm -f *.o $(PROGRAMS)
+Index: madwifi-trunk-r3776/tools/ath_info/ath_info.c
+===================================================================
+--- madwifi-trunk-r3776.orig/tools/ath_info/ath_info.c 2008-07-17 00:24:08.000000000 +0200
++++ madwifi-trunk-r3776/tools/ath_info/ath_info.c      2008-07-17 00:24:15.000000000 +0200
+@@ -28,6 +28,7 @@
+ #include <sys/mman.h>
+ #include <endian.h>
+ #include <byteswap.h>
++#include "do_multi.h"
+ #undef ARRAY_SIZE
+ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+@@ -1982,7 +1983,8 @@
+       printf("\n");
+ }
+-int main(int argc, char *argv[])
++int
++CMD(athinfo)(int argc, char *argv[])
+ {
+       unsigned long long dev_addr;
+       u_int16_t srev, phy_rev_5ghz, phy_rev_2ghz, ee_magic;
+Index: madwifi-trunk-r3776/tools/wpakey.c
+===================================================================
+--- madwifi-trunk-r3776.orig/tools/wpakey.c    2008-07-17 00:21:30.000000000 +0200
++++ madwifi-trunk-r3776/tools/wpakey.c 2008-07-17 00:46:18.000000000 +0200
+@@ -25,6 +25,7 @@
+ #include <unistd.h>
+ #include <sys/ioctl.h>
++#include "do_multi.h"
+ #define MACS "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx"
+ #define MACP(mac) (mac)[0], (mac)[1], (mac)[2], (mac)[3], (mac)[4], (mac)[5]
+@@ -234,7 +235,8 @@
+               "", dev);
+ }
+-int main(int argc, char** argv) {
++int
++CMD(wpakey)(int argc, char** argv) {
+       int keyidx = 0;
+       uint8_t mac[6];
+       int cipher = IEEE80211_CIPHER_AES_CCM;
diff --git a/package/madwifi/patches-r3776/104-autocreate_none.patch b/package/madwifi/patches-r3776/104-autocreate_none.patch
new file mode 100644 (file)
index 0000000..5796787
--- /dev/null
@@ -0,0 +1,13 @@
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 00:36:00.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 00:47:22.000000000 +0200
+@@ -482,7 +482,7 @@
+       HAL_STATUS status;
+       int error = 0;
+       unsigned int i;
+-      int autocreatemode = IEEE80211_M_STA;
++      int autocreatemode = -1;
+       u_int8_t csz;
+       sc->devid = devid;
diff --git a/package/madwifi/patches-r3776/105-ratectl_attach.patch b/package/madwifi/patches-r3776/105-ratectl_attach.patch
new file mode 100644 (file)
index 0000000..3748599
--- /dev/null
@@ -0,0 +1,25 @@
+Index: madwifi-trunk-r3776/net80211/ieee80211_rate.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_rate.c 2008-07-17 00:35:59.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_rate.c      2008-07-17 00:47:27.000000000 +0200
+@@ -100,8 +100,18 @@
+               ieee80211_load_module(buf);
+       if (!ratectls[id].attach) {
+-              printk(KERN_ERR "Error loading module \"%s\"\n", buf);
+-              return NULL;
++              /* pick the first available rate control module */
++              printk(KERN_INFO "Rate control module \"%s\" not available\n", buf);
++              for (id = 0; id < IEEE80211_RATE_MAX; id++) {
++                      if (ratectls[id].attach)
++                              break;
++              }
++              if (!ratectls[id].attach) {
++                      printk(KERN_ERR "No rate control module available");
++                      return NULL;
++              } else {
++                      printk(KERN_INFO "Using \"%s\" instead.\n", module_names[id]);
++              }
+       }
+       ctl = ratectls[id].attach(sc);
diff --git a/package/madwifi/patches-r3776/111-minstrel_crash.patch b/package/madwifi/patches-r3776/111-minstrel_crash.patch
new file mode 100644 (file)
index 0000000..250a21f
--- /dev/null
@@ -0,0 +1,14 @@
+Index: madwifi-trunk-r3776/ath_rate/minstrel/minstrel.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath_rate/minstrel/minstrel.c      2008-07-17 00:35:59.000000000 +0200
++++ madwifi-trunk-r3776/ath_rate/minstrel/minstrel.c   2008-07-17 00:47:36.000000000 +0200
+@@ -415,6 +415,9 @@
+                       return;
+               }
++              if (sn->num_rates <= 0)
++                      return;
++
+               if (sn->is_sampling) {
+                       sn->is_sampling = 0;
+                       if (sn->rs_sample_rate_slower)
diff --git a/package/madwifi/patches-r3776/122-replayfail_workaround.patch b/package/madwifi/patches-r3776/122-replayfail_workaround.patch
new file mode 100644 (file)
index 0000000..c016e72
--- /dev/null
@@ -0,0 +1,14 @@
+Index: madwifi-trunk-r3776/net80211/ieee80211_linux.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_linux.c        2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_linux.c     2008-07-17 00:49:54.000000000 +0200
+@@ -330,6 +330,9 @@
+               k->wk_cipher->ic_name, k->wk_keyix,
+               (unsigned long long)rsc);
++      /* disabled for now due to bogus events for unknown reasons */
++      return;
++
+       /* TODO: needed parameters: count, keyid, key type, src address, TSC */
+       snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=" MAC_FMT ")", tag,
+               k->wk_keyix,
diff --git a/package/madwifi/patches-r3776/123-ccmp_checks.patch b/package/madwifi/patches-r3776/123-ccmp_checks.patch
new file mode 100644 (file)
index 0000000..a0dba1c
--- /dev/null
@@ -0,0 +1,24 @@
+Index: madwifi-trunk-r3776/net80211/ieee80211_crypto_ccmp.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_crypto_ccmp.c  2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_crypto_ccmp.c       2008-07-17 00:49:59.000000000 +0200
+@@ -478,6 +478,9 @@
+       uint8_t *mic, *pos;
+       u_int space;
++      if (ctx->cc_tfm == NULL)
++              return 0;
++
+       ctx->cc_vap->iv_stats.is_crypto_ccmp++;
+       skb = skb0;
+@@ -592,6 +595,9 @@
+       uint8_t *pos, *mic;
+       u_int space;
++      if (ctx->cc_tfm == NULL)
++              return 0;
++
+       ctx->cc_vap->iv_stats.is_crypto_ccmp++;
+       skb = skb0;
diff --git a/package/madwifi/patches-r3776/124-linux24_compat.patch b/package/madwifi/patches-r3776/124-linux24_compat.patch
new file mode 100644 (file)
index 0000000..0ef7d92
--- /dev/null
@@ -0,0 +1,210 @@
+Index: madwifi-trunk-r3776/ath/if_athvar.h
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_athvar.h   2008-07-17 00:21:39.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_athvar.h        2008-07-17 00:50:03.000000000 +0200
+@@ -129,6 +129,11 @@
+ #define ATH_GET_NETDEV_DEV(ndev)      ((ndev)->class_dev.dev)
+ #endif
++#ifndef NETDEV_TX_OK
++#define NETDEV_TX_OK    0
++#define NETDEV_TX_BUSY  1
++#endif
++
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23)
+ static inline struct net_device *_alloc_netdev(int sizeof_priv, const char *mask,
+                                              void (*setup)(struct net_device *))
+Index: madwifi-trunk-r3776/ath/if_ath_radar.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath_radar.c        2008-07-17 00:21:39.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath_radar.c     2008-07-17 00:50:03.000000000 +0200
+@@ -89,6 +89,13 @@
+ #define nofloat_pct(_value, _pct) \
+       ( (_value * (1000 + _pct)) / 1000 )
++#ifndef list_for_each_entry_reverse
++#define list_for_each_entry_reverse(pos, head, member)                        \
++      for (pos = list_entry((head)->prev, typeof(*pos), member);      \
++           prefetch(pos->member.prev), &pos->member != (head);        \
++           pos = list_entry(pos->member.prev, typeof(*pos), member))
++#endif
++
+ struct radar_pattern_specification {
+       /* The name of the rule/specification (i.e. what did we detect) */
+       const char *name;
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 00:47:22.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 00:50:03.000000000 +0200
+@@ -4878,6 +4878,46 @@
+       return (txqs & (1 << qnum));
+ }
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
++static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
++{
++      int ret;
++      unsigned long flags;
++
++      local_irq_save(flags);
++      ret = v->counter;
++      if (likely(ret == old))
++              v->counter = new;
++      local_irq_restore(flags);
++
++      return ret;
++}
++
++/**
++ * atomic_add_unless - add unless the number is a given value
++ * @v: pointer of type atomic_t
++ * @a: the amount to add to v...
++ * @u: ...unless v is equal to u.
++ *
++ * Atomically adds @a to @v, so long as it was not @u.
++ * Returns non-zero if @v was not @u, and zero otherwise.
++ */
++static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
++{
++      int c, old;
++      c = atomic_read(v);
++      for (;;) {
++              if (unlikely(c == (u)))
++                      break;
++              old = atomic_cmpxchg((v), c, c + (a));
++              if (likely(old == c))
++                      break;
++              c = old;
++      }
++      return c != (u);
++}
++#endif
++
+ /*
+  * Generate beacon frame and queue cab data for a VAP.
+  */
+Index: madwifi-trunk-r3776/net80211/sort.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ madwifi-trunk-r3776/net80211/sort.c        2008-07-17 00:50:03.000000000 +0200
+@@ -0,0 +1,120 @@
++/*
++ * A fast, small, non-recursive O(nlog n) sort for the Linux kernel
++ *
++ * Jan 23 2005  Matt Mackall <mpm@selenic.com>
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++
++static void u32_swap(void *a, void *b, int size)
++{
++      u32 t = *(u32 *)a;
++      *(u32 *)a = *(u32 *)b;
++      *(u32 *)b = t;
++}
++
++static void generic_swap(void *a, void *b, int size)
++{
++      char t;
++
++      do {
++              t = *(char *)a;
++              *(char *)a++ = *(char *)b;
++              *(char *)b++ = t;
++      } while (--size > 0);
++}
++
++/**
++ * sort - sort an array of elements
++ * @base: pointer to data to sort
++ * @num: number of elements
++ * @size: size of each element
++ * @cmp: pointer to comparison function
++ * @swap: pointer to swap function or NULL
++ *
++ * This function does a heapsort on the given array. You may provide a
++ * swap function optimized to your element type.
++ *
++ * Sorting time is O(n log n) both on average and worst-case. While
++ * qsort is about 20% faster on average, it suffers from exploitable
++ * O(n*n) worst-case behavior and extra memory requirements that make
++ * it less suitable for kernel use.
++ */
++
++static void sort(void *base, size_t num, size_t size,
++        int (*cmp)(const void *, const void *),
++        void (*swap)(void *, void *, int size))
++{
++      /* pre-scale counters for performance */
++      int i = (num/2 - 1) * size, n = num * size, c, r;
++
++      if (!swap)
++              swap = (size == 4 ? u32_swap : generic_swap);
++
++      /* heapify */
++      for ( ; i >= 0; i -= size) {
++              for (r = i; r * 2 + size < n; r  = c) {
++                      c = r * 2 + size;
++                      if (c < n - size && cmp(base + c, base + c + size) < 0)
++                              c += size;
++                      if (cmp(base + r, base + c) >= 0)
++                              break;
++                      swap(base + r, base + c, size);
++              }
++      }
++
++      /* sort */
++      for (i = n - size; i >= 0; i -= size) {
++              swap(base, base + i, size);
++              for (r = 0; r * 2 + size < i; r = c) {
++                      c = r * 2 + size;
++                      if (c < i - size && cmp(base + c, base + c + size) < 0)
++                              c += size;
++                      if (cmp(base + r, base + c) >= 0)
++                              break;
++                      swap(base + r, base + c, size);
++              }
++      }
++}
++
++EXPORT_SYMBOL(sort);
++
++#if 0
++/* a simple boot-time regression test */
++
++int cmpint(const void *a, const void *b)
++{
++      return *(int *)a - *(int *)b;
++}
++
++static int sort_test(void)
++{
++      int *a, i, r = 1;
++
++      a = kmalloc(1000 * sizeof(int), GFP_KERNEL);
++      BUG_ON(!a);
++
++      printk("testing sort()\n");
++
++      for (i = 0; i < 1000; i++) {
++              r = (r * 725861) % 6599;
++              a[i] = r;
++      }
++
++      sort(a, 1000, sizeof(int), cmpint, NULL);
++
++      for (i = 0; i < 999; i++)
++              if (a[i] > a[i+1]) {
++                      printk("sort() failed!\n");
++                      break;
++              }
++
++      kfree(a);
++
++      return 0;
++}
++
++module_init(sort_test);
++#endif
diff --git a/package/madwifi/patches-r3776/126-rxerr_frames.patch b/package/madwifi/patches-r3776/126-rxerr_frames.patch
new file mode 100644 (file)
index 0000000..4639b5a
--- /dev/null
@@ -0,0 +1,29 @@
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 00:52:28.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 00:53:04.000000000 +0200
+@@ -6451,9 +6451,6 @@
+               rs = &bf->bf_dsstatus.ds_rxstat;
+               len = rs->rs_datalen;
+-              /* DMA sync. dies spectacularly if len == 0 */
+-              if (len == 0)
+-                      goto rx_next;
+               if (rs->rs_more) {
+                       /* Frame spans multiple descriptors; this
+                        * cannot happen yet as we don't support
+@@ -6513,8 +6510,12 @@
+                * setup again to receive another frame. 
+                * NB: Meta-data (rs, noise, tsf) in the ath_buf is still
+                * used. */
+-              bus_dma_sync_single(sc->sc_bdev,
+-                      bf->bf_skbaddr, len, BUS_DMA_FROMDEVICE);
++
++              /* DMA sync. dies spectacularly if len == 0 */
++              if (len != 0) {
++                      bus_dma_sync_single(sc->sc_bdev,
++                              bf->bf_skbaddr, len, BUS_DMA_FROMDEVICE);
++              }
+               skb = ath_rxbuf_take_skb(sc, bf);
+               sc->sc_stats.ast_ant_rx[rs->rs_antenna]++;
diff --git a/package/madwifi/patches-r3776/200-no_debug.patch b/package/madwifi/patches-r3776/200-no_debug.patch
new file mode 100644 (file)
index 0000000..b28782c
--- /dev/null
@@ -0,0 +1,444 @@
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 00:53:04.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 01:15:21.000000000 +0200
+@@ -323,8 +323,10 @@
+ static void ath_set_dfs_cac_time(struct ieee80211com *, unsigned int seconds);
+ static unsigned int ath_test_radar(struct ieee80211com *);
+-static unsigned int ath_dump_hal_map(struct ieee80211com *ic);
++#ifdef AR_DEBUG
++static unsigned int ath_dump_hal_map(struct ieee80211com *ic);
++#endif
+ static u_int32_t ath_get_clamped_maxtxpower(struct ath_softc *sc);
+ static u_int32_t ath_set_clamped_maxtxpower(struct ath_softc *sc, 
+               u_int32_t new_clamped_maxtxpower);
+@@ -334,7 +336,10 @@
+               unsigned int param, unsigned int value);
+ static u_int32_t ath_get_real_maxtxpower(struct ath_softc *sc);
++
++#ifdef AR_DEBUG
+ static int ath_txq_check(struct ath_softc *sc, struct ath_txq *txq, const char *msg);
++#endif
+ static int ath_countrycode = CTRY_DEFAULT;    /* country code */
+ static int ath_outdoor = AH_FALSE;            /* enable outdoor use */
+@@ -486,9 +491,11 @@
+       u_int8_t csz;
+       sc->devid = devid;
++#ifdef AR_DEBUG
+       ath_debug_global = (ath_debug & ATH_DEBUG_GLOBAL);
+       sc->sc_debug     = (ath_debug & ~ATH_DEBUG_GLOBAL);
+       DPRINTF(sc, ATH_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid);
++#endif
+       /* Allocate space for dynamically determined maximum VAP count */
+       sc->sc_bslot = 
+@@ -1014,7 +1021,9 @@
+       ic->ic_vap_delete = ath_vap_delete;
+       ic->ic_test_radar               = ath_test_radar;
++#ifdef AR_DEBUG
+       ic->ic_dump_hal_map             = ath_dump_hal_map;
++#endif
+       ic->ic_set_dfs_testmode         = ath_set_dfs_testmode;
+       ic->ic_get_dfs_testmode         = ath_get_dfs_testmode;
+@@ -1285,12 +1294,14 @@
+               /* If no default VAP debug flags are passed, allow a few to
+                * transfer down from the driver to new VAPs so we can have load
+                * time debugging for VAPs too. */
++#ifdef AR_DEBUG
+               vap->iv_debug = 0 |
+                       ((sc->sc_debug & ATH_DEBUG_RATE) ? IEEE80211_MSG_XRATE  : 0) | 
+                       ((sc->sc_debug & ATH_DEBUG_XMIT) ? IEEE80211_MSG_OUTPUT : 0) | 
+                       ((sc->sc_debug & ATH_DEBUG_RECV) ? IEEE80211_MSG_INPUT  : 0) |
+                       0
+                       ;
++#endif
+       }
+       ic->ic_debug = (sc->sc_default_ieee80211_debug & IEEE80211_MSG_IC);
+@@ -2811,6 +2822,7 @@
+ #endif
+ }
++#ifdef AR_DEBUG
+ static void
+ ath_txq_dump(struct ath_softc *sc, struct ath_txq *txq)
+ {
+@@ -2866,6 +2878,7 @@
+       return 1;
+ }
++#endif
+ /*
+  * Insert a buffer on a txq
+@@ -8384,7 +8397,9 @@
+ ath_tx_timeout(struct net_device *dev)
+ {
+       struct ath_softc *sc = dev->priv;
++#ifdef AR_DEBUG
+       int i;
++#endif
+       if (ath_chan_unavail(sc))
+               return;
+@@ -8393,12 +8408,14 @@
+               (dev->flags & IFF_RUNNING) ? "" : "NOT ",
+               sc->sc_invalid ? "in" : "");
++#ifdef AR_DEBUG
+       for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
+               if (ATH_TXQ_SETUP(sc, i)) {
+                       ath_txq_check(sc, &sc->sc_txq[i], __func__);
+                       ath_txq_dump(sc, &sc->sc_txq[i]);
+               }
+       }
++#endif
+       if ((dev->flags & IFF_RUNNING) && !sc->sc_invalid) {
+               sc->sc_stats.ast_watchdog++;
+@@ -10638,6 +10655,7 @@
+                               /* XXX validate? */
+                               sc->sc_ledpin = val;
+                               break;
++#ifdef AR_DEBUG
+                       case ATH_DEBUG:
+                               sc->sc_debug     = (val & ~ATH_DEBUG_GLOBAL);
+                               ath_debug_global = (val &  ATH_DEBUG_GLOBAL);
+@@ -10645,6 +10663,7 @@
+                                               "0x%08x.\n", val);
+                               break;
++#endif
+                       case ATH_TXANTENNA:
+                               /*
+                                * antenna can be:
+@@ -10818,9 +10837,11 @@
+               case ATH_REGDOMAIN:
+                       ath_hal_getregdomain(ah, &val);
+                       break;
++#ifdef AR_DEBUG
+               case ATH_DEBUG:
+                       val = sc->sc_debug | ath_debug_global;
+                       break;
++#endif
+               case ATH_TXANTENNA:
+                       val = sc->sc_txantenna;
+                       break;
+@@ -11939,6 +11960,7 @@
+ }
+ /* This is called by a private ioctl (iwpriv) to dump the HAL obfuscation table */
++#ifdef AR_DEBUG
+ static unsigned int
+ ath_dump_hal_map(struct ieee80211com *ic)
+ {
+@@ -11947,7 +11969,7 @@
+       ath_hal_dump_map(sc->sc_ah);
+       return 0;
+ }
+-
++#endif
+ /* If we are shutting down or blowing off the DFS channel availability check
+  * then we call this to stop the behavior before we take the rest of the
+  * necessary actions (such as a DFS reaction to radar). */
+Index: madwifi-trunk-r3776/ath_rate/amrr/amrr.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath_rate/amrr/amrr.c      2008-07-17 00:21:30.000000000 +0200
++++ madwifi-trunk-r3776/ath_rate/amrr/amrr.c   2008-07-17 00:53:20.000000000 +0200
+@@ -70,7 +70,9 @@
+ #include "amrr.h"
++#ifdef AR_DEBUG
+ #define       AMRR_DEBUG
++#endif
+ #ifdef AMRR_DEBUG
+ #define       DPRINTF(sc, _fmt, ...) do {                                     \
+       if (sc->sc_debug & 0x10)                                        \
+Index: madwifi-trunk-r3776/ath_rate/minstrel/minstrel.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath_rate/minstrel/minstrel.c      2008-07-17 00:47:36.000000000 +0200
++++ madwifi-trunk-r3776/ath_rate/minstrel/minstrel.c   2008-07-17 01:16:06.000000000 +0200
+@@ -117,7 +117,9 @@
+ #include "minstrel.h"
++#ifdef AR_DEBUG
+ #define       MINSTREL_DEBUG
++#endif
+ #ifdef MINSTREL_DEBUG
+ enum {
+               ATH_DEBUG_RATE          = 0x00000010    /* rate control */
+@@ -963,7 +965,9 @@
+               (struct ieee80211_node_table *)&vap->iv_ic->ic_sta;
+       unsigned int x = 0;
+       unsigned int this_tp, this_prob, this_eprob;
+-      struct ath_softc *sc = vap->iv_ic->ic_dev->priv;;
++#ifdef AR_DEBUG
++      struct ath_softc *sc = vap->iv_ic->ic_dev->priv;
++#endif
+       IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
+       TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
+Index: madwifi-trunk-r3776/ath_rate/onoe/onoe.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath_rate/onoe/onoe.c      2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/ath_rate/onoe/onoe.c   2008-07-17 00:53:20.000000000 +0200
+@@ -66,7 +66,9 @@
+ #include "onoe.h"
++#ifdef AR_DEBUG
+ #define       ONOE_DEBUG
++#endif
+ #ifdef ONOE_DEBUG
+ enum {
+       ATH_DEBUG_RATE  = 0x00000010,   /* rate control */
+Index: madwifi-trunk-r3776/ath_rate/sample/sample.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath_rate/sample/sample.c  2008-07-17 00:21:30.000000000 +0200
++++ madwifi-trunk-r3776/ath_rate/sample/sample.c       2008-07-17 00:53:20.000000000 +0200
+@@ -68,7 +68,9 @@
+ #include "sample.h"
+-#define       SAMPLE_DEBUG
++#ifdef AR_DEBUG
++#define SAMPLE_DEBUG
++#endif
+ #ifdef SAMPLE_DEBUG
+ enum {
+       ATH_DEBUG_RATE          = 0x00000010,   /* rate control */
+Index: madwifi-trunk-r3776/tools/do_multi.c
+===================================================================
+--- madwifi-trunk-r3776.orig/tools/do_multi.c  2008-07-17 00:46:52.000000000 +0200
++++ madwifi-trunk-r3776/tools/do_multi.c       2008-07-17 00:53:20.000000000 +0200
+@@ -9,16 +9,20 @@
+     progname = basename(argv[0]);
++#ifdef AR_DEBUG
+     if(strcmp(progname, "80211debug") == 0)
+       ret = a80211debug_init(argc, argv);
++#endif
+     if(strcmp(progname, "80211stats") == 0)
+       ret = a80211stats_init(argc, argv);
+     if(strcmp(progname, "athchans") == 0)
+       ret = athchans_init(argc, argv);
+     if(strcmp(progname, "athctrl") == 0)
+       ret =  athctrl_init(argc, argv);
++#ifdef AR_DEBUG
+     if(strcmp(progname, "athdebug") == 0)
+       ret =  athdebug_init(argc, argv);
++#endif
+     if(strcmp(progname, "athkey") == 0)
+       ret =  athkey_init(argc, argv);
+     if(strcmp(progname, "athstats") == 0)
+Index: madwifi-trunk-r3776/tools/Makefile
+===================================================================
+--- madwifi-trunk-r3776.orig/tools/Makefile    2008-07-17 00:45:15.000000000 +0200
++++ madwifi-trunk-r3776/tools/Makefile 2008-07-17 01:10:33.000000000 +0200
+@@ -39,6 +39,10 @@
+ ATH_HAL = $(TOP)/ath_hal
++ifndef ATH_DEBUG
++ATH_DEBUG=1
++endif
++
+ #
+ # Path to the HAL source code.
+ #
+@@ -46,17 +50,22 @@
+ HAL = $(TOP)/hal
+ endif
++INCS = -I. -I$(HAL) -I$(TOP) -I$(ATH_HAL) -I$(TOP)/ath
++CFLAGS = -g -O2 -Wall
++ALL_CFLAGS = $(CFLAGS) $(INCS)
++LDFLAGS =
+ PROGRAMS = athstats 80211stats athkey athchans athctrl \
+-      athdebug 80211debug wlanconfig wpakey
++      wlanconfig wpakey
++
++ifeq ($(ATH_DEBUG),1)
++  PROGRAMS += athdebug 80211debug
++  ALL_CFLAGS += -DAR_DEBUG
++endif
+ OBJS = $(patsubst %,%.o,$(PROGRAMS)) ath_info/ath_info.o
+ SUBDIRS = ath_info
+-INCS = -I. -I$(HAL) -I$(TOP) -I$(ATH_HAL) -I$(TOP)/ath
+-CFLAGS = -g -O2 -Wall
+-ALL_CFLAGS = $(CFLAGS) $(INCS)
+-LDFLAGS =
+ all: all-subdirs compile
+Index: madwifi-trunk-r3776/ath/if_ath_hal.h
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath_hal.h  2008-07-17 00:21:39.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath_hal.h       2008-07-17 00:53:20.000000000 +0200
+@@ -1263,6 +1263,7 @@
+            tail -f /var/log/messages | sed -f hal_unmangle.sed 
+  */
++#ifdef AR_DEBUG
+ static inline void ath_hal_dump_map(struct ath_hal *ah)
+ {
+ #ifdef CONFIG_KALLSYMS
+@@ -1527,7 +1528,7 @@
+ #endif                                /* #ifndef CONFIG_KALLSYMS */
+ }
+-
++#endif
+ #include "if_ath_hal_wrappers.h"
+ #include "if_ath_hal_extensions.h"
+Index: madwifi-trunk-r3776/net80211/ieee80211_var.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_var.h  2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_var.h       2008-07-17 00:53:20.000000000 +0200
+@@ -495,9 +495,10 @@
+       /* inject a fake radar signal -- used while on a 802.11h DFS channels */
+       unsigned int (*ic_test_radar)(struct ieee80211com *);
++#ifdef AR_DEBUG
+       /* dump HAL */
+       unsigned int (*ic_dump_hal_map)(struct ieee80211com *);
+-
++#endif
+       /* DFS channel availability check time (in seconds) */
+       void (*ic_set_dfs_cac_time)(struct ieee80211com *, unsigned int);
+       unsigned int (*ic_get_dfs_cac_time)(struct ieee80211com *);
+Index: madwifi-trunk-r3776/net80211/ieee80211_wireless.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_wireless.c     2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_wireless.c  2008-07-17 00:53:20.000000000 +0200
+@@ -1557,6 +1557,7 @@
+       return 0;
+ }
++#ifdef AR_DEBUG
+ static int 
+ ieee80211_ioctl_hal_map(struct net_device *dev, struct iw_request_info *info,
+        void *w, char *extra)
+@@ -1567,7 +1568,7 @@
+        params[0] = ic->ic_dump_hal_map(ic);
+        return 0;
+ }
+-
++#endif
+ static int
+ ieee80211_ioctl_radar(struct net_device *dev, struct iw_request_info *info,
+@@ -5296,8 +5297,10 @@
+         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,   "getwmmparams" },
+       { IEEE80211_IOCTL_RADAR,
+         0, 0, "doth_radar" },
++#ifdef AR_DEBUG
+       { IEEE80211_IOCTL_HALMAP,
+         0, 0, "dump_hal_map" },
++#endif
+       /*
+        * These depends on sub-ioctl support which added in version 12.
+        */
+@@ -5751,7 +5754,9 @@
+       set_priv(IEEE80211_IOCTL_SETMLME, ieee80211_ioctl_setmlme),
+       set_priv(IEEE80211_IOCTL_SETKEY, ieee80211_ioctl_setkey),
+       set_priv(IEEE80211_IOCTL_DELKEY, ieee80211_ioctl_delkey),
++#ifdef AR_DEBUG
+       set_priv(IEEE80211_IOCTL_HALMAP, ieee80211_ioctl_hal_map),
++#endif
+       set_priv(IEEE80211_IOCTL_ADDMAC, ieee80211_ioctl_addmac),
+       set_priv(IEEE80211_IOCTL_DELMAC, ieee80211_ioctl_delmac),
+       set_priv(IEEE80211_IOCTL_WDSADDMAC, ieee80211_ioctl_wdsmac),
+Index: madwifi-trunk-r3776/ath/if_ath_debug.h
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath_debug.h        2008-07-17 00:21:39.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath_debug.h     2008-07-17 00:53:20.000000000 +0200
+@@ -54,6 +54,10 @@
+       ATH_DEBUG_GLOBAL        = (ATH_DEBUG_SKB|ATH_DEBUG_SKB_REF)
+ };
++#define       EPRINTF(_sc, _fmt, ...) \
++              printk(KERN_ERR "%s: %s: " _fmt, \
++                      SC_DEV_NAME(_sc), __func__, ## __VA_ARGS__)
++
+ #ifdef AR_DEBUG
+ /* DEBUG-ONLY DEFINITIONS */
+@@ -68,20 +72,9 @@
+               ath_keyprint((_sc), __func__, _ix, _hk, _mac);          \
+ } while (0)
+-#else /* #ifdef AR_DEBUG */
+-
+-#define       DFLAG_ISSET(sc, _m)             0
+-#define       DPRINTF(sc, _m, _fmt, ...)
+-#define       KEYPRINTF(sc, k, ix, mac)
+-
+-#endif /* #ifdef AR_DEBUG */
+ #define       IFF_DUMPPKTS(_sc, _m)   DFLAG_ISSET((_sc), (_m))
+-#define       EPRINTF(_sc, _fmt, ...) \
+-              printk(KERN_ERR "%s: %s: " _fmt, \
+-                      SC_DEV_NAME(_sc), __func__, ## __VA_ARGS__)
+-
+ #define       WPRINTF(_sc, _fmt, ...) \
+               printk(KERN_WARNING "%s: %s: " _fmt, \
+                       SC_DEV_NAME(_sc), __func__, ## __VA_ARGS__)
+@@ -89,5 +82,14 @@
+ #define       IPRINTF(_sc, _fmt, ...) \
+               printk(KERN_INFO "%s: %s: " _fmt, \
+                       SC_DEV_NAME(_sc), __func__, ## __VA_ARGS__)
++#else
++#define       DFLAG_ISSET(sc, _m)             0
++#define       DPRINTF(sc, _m, _fmt, ...)
++#define       KEYPRINTF(sc, k, ix, mac)
++#define WPRINTF(...)
++#define IPRINTF(...)
++#define IFF_DUMPPKTS(...) 0
++
++#endif
+ #endif /* #ifndef _IF_ATH_DEBUG_H_ */
+Index: madwifi-trunk-r3776/ath/if_ath_pci.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath_pci.c  2008-07-17 00:21:39.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath_pci.c       2008-07-17 00:53:20.000000000 +0200
+@@ -134,8 +134,10 @@
+       u16 vdevice;
+       int i;
+-      if (pci_enable_device(pdev))
++      if (pci_enable_device(pdev)) {
++              printk(KERN_ERR "%s: failed to enable PCI device\n", dev_info);
+               return -EIO;
++      }
+       /* XXX 32-bit addressing only */
+       if (pci_set_dma_mask(pdev, 0xffffffff)) {
+@@ -244,8 +246,10 @@
+               sc->aps_sc.sc_ledpin = 1;
+       }
+-      if (ath_attach(vdevice, dev, NULL) != 0)
++      if ((i = ath_attach(vdevice, dev, NULL)) != 0) {
++              printk(KERN_ERR "%s: ath_attach failed: %d\n", dev_info, i);
+               goto bad4;
++      }
+       athname = ath_hal_probe(id->vendor, vdevice);
+       printk(KERN_INFO "%s: %s: %s: mem=0x%llx, irq=%d\n",
diff --git a/package/madwifi/patches-r3776/201-no_debug_extra.patch b/package/madwifi/patches-r3776/201-no_debug_extra.patch
new file mode 100644 (file)
index 0000000..693c1f9
--- /dev/null
@@ -0,0 +1,59 @@
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 01:15:21.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 01:20:11.000000000 +0200
+@@ -423,8 +423,8 @@
+               "defaults to '" DEF_RATE_CTL "'");
+ MODULE_PARM_DESC(intmit, "Enable interference mitigation by default.  Default is 0.");
+-static int    ath_debug = 0;
+ #ifdef AR_DEBUG
++static int    ath_debug = 0;
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))
+ MODULE_PARM(ath_debug, "i");
+ #else
+@@ -435,8 +435,8 @@
+ static void ath_printtxbuf(const struct ath_buf *, int);
+ #endif /* defined(AR_DEBUG) */
+-static int    ieee80211_debug = 0;
+ #ifdef AR_DEBUG
++static int    ieee80211_debug = 0;
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))
+ MODULE_PARM(ieee80211_debug, "i");
+ #else
+@@ -853,8 +853,10 @@
+       ic->ic_updateslot = ath_updateslot;
+       atomic_set(&ic->ic_node_counter, 0);
+       ic->ic_debug = 0;
++#ifdef AR_DEBUG
+       sc->sc_debug = (ath_debug & ~ATH_DEBUG_GLOBAL);
+       sc->sc_default_ieee80211_debug = ieee80211_debug;
++#endif
+       ic->ic_wme.wme_update = ath_wme_update;
+       ic->ic_uapsd_flush = ath_uapsd_flush;
+Index: madwifi-trunk-r3776/net80211/ieee80211_scan_ap.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_scan_ap.c      2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_scan_ap.c   2008-07-17 01:25:32.000000000 +0200
+@@ -790,15 +790,18 @@
+       struct ap_state *as = ss->ss_priv;
+       struct channel chans[ss_last]; /* actually ss_last-1 is required */
+       struct channel *c = NULL;
+-      struct pc_params params = { vap, ss, flags };
+       int benefit = 0;
+       int sta_assoc = 0;
++#ifdef IEEE80211_DEBUG
++      struct pc_params params = { vap, ss, flags };
++
+       for (i = 0; i < ss_last; i++) {
+               chans[i].chan = ss->ss_chans[i];
+               chans[i].orig = i;
+               chans[i].params = &params;
+       }
++#endif
+       sort(chans, ss_last, sizeof(*chans), pc_cmp, pc_swap);
diff --git a/package/madwifi/patches-r3776/300-napi_polling.patch b/package/madwifi/patches-r3776/300-napi_polling.patch
new file mode 100644 (file)
index 0000000..e7e5bfd
--- /dev/null
@@ -0,0 +1,538 @@
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 01:20:11.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 01:46:37.000000000 +0200
+@@ -182,7 +182,11 @@
+       struct sk_buff *, int, int, u_int64_t);
+ static void ath_setdefantenna(struct ath_softc *, u_int);
+ static struct ath_txq *ath_txq_setup(struct ath_softc *, int, int);
+-static void ath_rx_tasklet(TQUEUE_ARG);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++static int ath_rx_poll(struct napi_struct *napi, int budget);
++#else
++static int ath_rx_poll(struct net_device *dev, int *budget);
++#endif
+ static int ath_hardstart(struct sk_buff *, struct net_device *);
+ static int ath_mgtstart(struct ieee80211com *, struct sk_buff *);
+ #ifdef ATH_SUPERG_COMP
+@@ -331,6 +335,9 @@
+ static u_int32_t ath_set_clamped_maxtxpower(struct ath_softc *sc, 
+               u_int32_t new_clamped_maxtxpower);
++static void ath_poll_disable(struct net_device *dev);
++static void ath_poll_enable(struct net_device *dev);
++
+ static void ath_scanbufs(struct ath_softc *sc);
+ static int ath_debug_iwpriv(struct ieee80211com *ic, 
+               unsigned int param, unsigned int value);
+@@ -518,7 +525,6 @@
+       atomic_set(&sc->sc_txbuf_counter, 0);
+-      ATH_INIT_TQUEUE(&sc->sc_rxtq,           ath_rx_tasklet,         dev);
+       ATH_INIT_TQUEUE(&sc->sc_txtq,           ath_tx_tasklet,         dev);
+       ATH_INIT_TQUEUE(&sc->sc_bmisstq,        ath_bmiss_tasklet,      dev);
+       ATH_INIT_TQUEUE(&sc->sc_bstucktq,       ath_bstuck_tasklet,     dev);
+@@ -833,6 +839,12 @@
+       dev->set_mac_address = ath_set_mac_address;
+       dev->change_mtu = ath_change_mtu;
+       dev->tx_queue_len = ATH_TXBUF - ATH_TXBUF_MGT_RESERVED;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++      netif_napi_add(dev, &sc->sc_napi, ath_rx_poll, 64);
++#else
++      dev->poll = ath_rx_poll;
++      dev->weight = 64;
++#endif
+ #ifdef USE_HEADERLEN_RESV
+       dev->hard_header_len += sizeof(struct ieee80211_qosframe) +
+                               sizeof(struct llc) +
+@@ -1770,7 +1782,7 @@
+ }
+ static void
+-ath_intr_process_rx_descriptors(struct ath_softc *sc, int *pneedmark, u_int64_t hw_tsf)
++ath_intr_process_rx_descriptors(struct ath_softc *sc, int *pneedmark, u_int64_t hw_tsf, int schedule)
+ {
+       struct ath_hal *ah = sc->sc_ah;
+       struct ath_desc *ds;
+@@ -2252,8 +2264,25 @@
+       }
+       /* If we got something to process, schedule rx queue to handle it */
+-      if (count)
+-              ATH_SCHEDULE_TQUEUE(&sc->sc_rxtq, pneedmark);
++      if (count) {
++              sc->sc_isr &= ~HAL_INT_RX;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++              if (netif_rx_schedule_prep(sc->sc_dev, &sc->sc_napi))
++#else
++              if (netif_rx_schedule_prep(sc->sc_dev))
++#endif
++              {
++#ifndef ATH_PRECISE_TSF
++                      sc->sc_imask &= ~HAL_INT_RX;
++                      ath_hal_intrset(ah, sc->sc_imask);
++#endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++                      __netif_rx_schedule(sc->sc_dev, &sc->sc_napi);
++#else
++                      __netif_rx_schedule(sc->sc_dev);
++#endif
++              }
++      }
+       ATH_RXBUF_UNLOCK_IRQ(sc);
+ #undef PA2DESC
+ }
+@@ -2343,6 +2372,7 @@
+               (status & HAL_INT_GLOBAL)       ? " HAL_INT_GLOBAL"     : ""
+               );
++      sc->sc_isr = status;
+       status &= sc->sc_imask;                 /* discard unasked for bits */
+       /* As soon as we know we have a real interrupt we intend to service, 
+        * we will check to see if we need an initial hardware TSF reading. 
+@@ -2400,7 +2430,7 @@
+               }
+               if (status & (HAL_INT_RX | HAL_INT_RXPHY)) {
+                       /* NB: Will schedule rx tasklet if necessary. */
+-                      ath_intr_process_rx_descriptors(sc, &needmark, hw_tsf);
++                      ath_intr_process_rx_descriptors(sc, &needmark, hw_tsf, 1);
+               }
+               if (status & HAL_INT_TX) {
+ #ifdef ATH_SUPERG_DYNTURBO
+@@ -2426,6 +2456,11 @@
+                               }
+                       }
+ #endif
++                      /* disable transmit interrupt */
++                      sc->sc_isr &= ~HAL_INT_TX;
++                      ath_hal_intrset(ah, sc->sc_imask & ~HAL_INT_TX);
++                      sc->sc_imask &= ~HAL_INT_TX;
++
+                       ATH_SCHEDULE_TQUEUE(&sc->sc_txtq, &needmark);
+               }
+               if (status & HAL_INT_BMISS) {
+@@ -2617,6 +2652,7 @@
+       if (sc->sc_tx99 != NULL)
+               sc->sc_tx99->start(sc->sc_tx99);
+ #endif
++      ath_poll_enable(dev);
+ done:
+       ATH_UNLOCK(sc);
+@@ -2657,6 +2693,9 @@
+               if (sc->sc_tx99 != NULL)
+                       sc->sc_tx99->stop(sc->sc_tx99);
+ #endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++              ath_poll_disable(dev);
++#endif
+               netif_stop_queue(dev);  /* XXX re-enabled by ath_newstate */
+               dev->flags &= ~IFF_RUNNING;     /* NB: avoid recursion */
+               ieee80211_stop_running(ic);     /* stop all VAPs */
+@@ -4109,6 +4148,39 @@
+       return ath_keyset(sc, k, mac, vap->iv_bss);
+ }
++static void ath_poll_disable(struct net_device *dev)
++{
++      struct ath_softc *sc = dev->priv;
++
++      /*
++       * XXX Using in_softirq is not right since we might
++       * be called from other soft irq contexts than
++       * ath_rx_poll
++       */
++      if (!in_softirq()) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++              napi_disable(&sc->sc_napi);
++#else
++              netif_poll_disable(dev);
++#endif
++      }
++}
++
++static void ath_poll_enable(struct net_device *dev)
++{
++      struct ath_softc *sc = dev->priv;
++
++      /* NB: see above */
++      if (!in_softirq()) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++              napi_enable(&sc->sc_napi);
++#else
++              netif_poll_enable(dev);
++#endif
++      }
++}
++
++
+ /*
+  * Block/unblock tx+rx processing while a key change is done.
+  * We assume the caller serializes key management operations
+@@ -4119,33 +4191,26 @@
+ ath_key_update_begin(struct ieee80211vap *vap)
+ {
+       struct net_device *dev = vap->iv_ic->ic_dev;
+-      struct ath_softc *sc = dev->priv;
+       DPRINTF(sc, ATH_DEBUG_KEYCACHE, "Begin\n");
+       /*
+        * When called from the rx tasklet we cannot use
+        * tasklet_disable because it will block waiting
+        * for us to complete execution.
+-       *
+-       * XXX Using in_softirq is not right since we might
+-       * be called from other soft irq contexts than
+-       * ath_rx_tasklet.
+        */
+-      if (!in_softirq())
+-              tasklet_disable(&sc->sc_rxtq);
+-      netif_stop_queue(dev);
++      if ((dev->flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING))
++              netif_stop_queue(dev);
+ }
+ static void
+ ath_key_update_end(struct ieee80211vap *vap)
+ {
+       struct net_device *dev = vap->iv_ic->ic_dev;
+-      struct ath_softc *sc = dev->priv;
+       DPRINTF(sc, ATH_DEBUG_KEYCACHE, "End\n");
+-      netif_wake_queue(dev);
+-      if (!in_softirq())              /* NB: see above */
+-              tasklet_enable(&sc->sc_rxtq);
++
++      if ((dev->flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING))
++              netif_wake_queue(dev);
+ }
+ /*
+@@ -6405,15 +6470,25 @@
+       sc->sc_numrxotherant = 0;
+ }
+-static void
+-ath_rx_tasklet(TQUEUE_ARG data)
++static int
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++ath_rx_poll(struct napi_struct *napi, int budget)
++#else
++ath_rx_poll(struct net_device *dev, int *budget)
++#endif
+ {
+ #define       PA2DESC(_sc, _pa) \
+       ((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \
+               ((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))
+-      struct net_device *dev = (struct net_device *)data;
+-      struct ath_buf *bf;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++      struct ath_softc *sc = container_of(napi, struct ath_softc, sc_napi);
++      struct net_device *dev = sc->sc_dev;
++      u_int rx_limit = budget;
++#else
+       struct ath_softc *sc = dev->priv;
++      u_int rx_limit = min(dev->quota, *budget);
++#endif
++      struct ath_buf *bf;
+       struct ieee80211com *ic = &sc->sc_ic;
+       struct ath_hal *ah = sc ? sc->sc_ah : NULL;
+       struct ath_desc *ds;
+@@ -6421,6 +6496,7 @@
+       struct ieee80211_node *ni;
+       struct sk_buff *skb = NULL;
+       unsigned int len, phyerr, mic_fail = 0;
++      unsigned int early_stop = 0;
+       int type = -1; /* undefined */
+       int init_ret = 0;
+       int bf_processed = 0;
+@@ -6428,6 +6504,7 @@
+       int errors       = 0;
+       DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s started...\n", __func__);
++process_rx_again:
+       do {
+               /* Get next RX buffer pending processing by RX tasklet...
+                *  
+@@ -6457,6 +6534,10 @@
+                       break;
+               bf_processed++;
++              if (rx_limit-- < 0) {
++                      early_stop = 1;
++                      break;
++              }
+               ds  = bf->bf_desc;
+ #ifdef AR_DEBUG
+@@ -6491,6 +6572,7 @@
+                               sc->sc_stats.ast_rx_phyerr++;
+                               phyerr = rs->rs_phyerr & 0x1f;
+                               sc->sc_stats.ast_rx_phy[phyerr]++;
++                              goto rx_next;
+                       }
+                       if (rs->rs_status & HAL_RXERR_DECRYPT) {
+                               /* Decrypt error.  If the error occurred
+@@ -6689,6 +6771,33 @@
+               STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
+               ATH_RXBUF_UNLOCK_IRQ(sc);
+       } while (1);
++      if (!early_stop) {
++              unsigned long flags;
++              /* Check if more data is received while we were
++               * processing the descriptor chain.
++               */
++#ifndef ATH_PRECISE_TSF
++              local_irq_save(flags);
++              if (sc->sc_isr & HAL_INT_RX) {
++                      u_int64_t hw_tsf = ath_hal_gettsf64(ah);
++                      sc->sc_isr &= ~HAL_INT_RX;
++                      local_irq_restore(flags);
++                      ath_intr_process_rx_descriptors(sc, NULL, hw_tsf, 0);
++                      goto process_rx_again;
++              }
++              sc->sc_imask |= HAL_INT_RX;
++              ath_hal_intrset(ah, sc->sc_imask);
++              local_irq_restore(flags);
++#endif
++      }
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++      netif_rx_complete(dev, napi);
++#else
++      netif_rx_complete(dev);
++      *budget -= bf_processed;
++      dev->quota -= bf_processed;
++#endif
+       if (sc->sc_useintmit) 
+               ath_hal_rxmonitor(ah, &sc->sc_halstats, &sc->sc_curchan);
+@@ -6701,6 +6810,12 @@
+               " %d rx buf processed. %d were errors. %d skb accepted.\n",
+               __func__, bf_processed, errors, skb_accepted);
+ #undef PA2DESC
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++      return bf_processed;
++#else
++      return early_stop;
++#endif
+ }
+ #ifdef ATH_SUPERG_XR
+@@ -8306,12 +8421,24 @@
+ {
+       struct net_device *dev = (struct net_device *)data;
+       struct ath_softc *sc = dev->priv;
++      unsigned long flags;
++process_tx_again:
+       if (txqactive(sc->sc_ah, 0))
+               ath_tx_processq(sc, &sc->sc_txq[0]);
+       if (txqactive(sc->sc_ah, sc->sc_cabq->axq_qnum))
+               ath_tx_processq(sc, sc->sc_cabq);
++      local_irq_save(flags);
++      if (sc->sc_isr & HAL_INT_TX) {
++              sc->sc_isr &= ~HAL_INT_TX;
++              local_irq_restore(flags);
++              goto process_tx_again;
++      }
++      sc->sc_imask |= HAL_INT_TX;
++      ath_hal_intrset(sc->sc_ah, sc->sc_imask);
++      local_irq_restore(flags);
++
+       netif_wake_queue(dev);
+       if (sc->sc_softled)
+@@ -8327,7 +8454,9 @@
+ {
+       struct net_device *dev = (struct net_device *)data;
+       struct ath_softc *sc = dev->priv;
++      unsigned long flags;
++process_tx_again:
+       /*
+        * Process each active queue.
+        */
+@@ -8357,6 +8486,16 @@
+       if (sc->sc_uapsdq && txqactive(sc->sc_ah, sc->sc_uapsdq->axq_qnum))
+               ath_tx_processq(sc, sc->sc_uapsdq);
++      local_irq_save(flags);
++      if (sc->sc_isr & HAL_INT_TX) {
++              sc->sc_isr &= ~HAL_INT_TX;
++              local_irq_restore(flags);
++              goto process_tx_again;
++      }
++      sc->sc_imask |= HAL_INT_TX;
++      ath_hal_intrset(sc->sc_ah, sc->sc_imask);
++      local_irq_restore(flags);
++
+       netif_wake_queue(dev);
+       if (sc->sc_softled)
+@@ -10322,9 +10461,9 @@
+       dev->mtu = mtu;
+       if ((dev->flags & IFF_RUNNING) && !sc->sc_invalid) {
+               /* NB: the rx buffers may need to be reallocated */
+-              tasklet_disable(&sc->sc_rxtq);
++              ath_poll_disable(dev);
+               error = ath_reset(dev);
+-              tasklet_enable(&sc->sc_rxtq);
++              ath_poll_enable(dev);
+       }
+       ATH_UNLOCK(sc);
+Index: madwifi-trunk-r3776/ath/if_athvar.h
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_athvar.h   2008-07-17 00:52:28.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_athvar.h        2008-07-17 01:27:21.000000000 +0200
+@@ -56,6 +56,10 @@
+ # include     <asm/bitops.h>
+ #endif
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++#define irqs_disabled()                       0
++#endif
++
+ /*
+  * Deduce if tasklets are available.  If not then
+  * fall back to using the immediate work queue.
+@@ -644,6 +648,9 @@
+ struct ath_softc {
+       struct ieee80211com sc_ic;              /* NB: must be first */
+       struct net_device *sc_dev;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++      struct napi_struct sc_napi;
++#endif
+       void __iomem *sc_iobase;                /* address of the device */
+       struct semaphore sc_lock;               /* dev-level lock */
+       struct net_device_stats sc_devstats;    /* device statistics */
+@@ -756,7 +763,6 @@
+       struct ath_buf *sc_rxbufcur;            /* current rx buffer */
+       u_int32_t *sc_rxlink;                   /* link ptr in last RX desc */
+       spinlock_t sc_rxbuflock;
+-      struct ATH_TQ_STRUCT sc_rxtq;           /* rx intr tasklet */
+       struct ATH_TQ_STRUCT sc_rxorntq;        /* rxorn intr tasklet */
+       u_int16_t sc_cachelsz;                  /* cache line size */
+@@ -769,6 +775,7 @@
+       u_int sc_txintrperiod;                  /* tx interrupt batching */
+       struct ath_txq sc_txq[HAL_NUM_TX_QUEUES];
+       struct ath_txq *sc_ac2q[WME_NUM_AC];    /* WME AC -> h/w qnum */
++      HAL_INT sc_isr;                         /* unmasked ISR state */
+       struct ATH_TQ_STRUCT sc_txtq;           /* tx intr tasklet */
+       u_int8_t sc_grppoll_str[GRPPOLL_RATE_STR_LEN];
+       struct ath_descdma sc_bdma;             /* beacon descriptors */
+@@ -888,6 +895,8 @@
+ #define       ATH_TXBUF_LOCK_CHECK(_sc)
+ #endif
++#define ATH_DISABLE_INTR              local_irq_disable
++#define ATH_ENABLE_INTR               local_irq_enable
+ #define       ATH_RXBUF_LOCK_INIT(_sc)        spin_lock_init(&(_sc)->sc_rxbuflock)
+ #define       ATH_RXBUF_LOCK_DESTROY(_sc)
+Index: madwifi-trunk-r3776/net80211/ieee80211_skb.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_skb.c  2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_skb.c       2008-07-17 01:42:17.000000000 +0200
+@@ -73,7 +73,7 @@
+ #undef dev_queue_xmit
+ #undef kfree_skb
+ #undef kfree_skb_fast
+-#undef netif_rx
++#undef netif_receive_skb
+ #undef pskb_copy
+ #undef skb_clone
+ #undef skb_copy
+@@ -581,8 +581,8 @@
+               grp, vlan_tag);
+ }
+-int netif_rx_debug(struct sk_buff *skb, const char *func, int line) {
+-      return netif_rx(untrack_skb(skb, 0, __func__, __LINE__));
++int netif_receive_skb_debug(struct sk_buff *skb, const char *func, int line) {
++      return netif_receive_skb(untrack_skb(skb, 0, __func__, __LINE__));
+ }
+ struct sk_buff *alloc_skb_debug(unsigned int length, gfp_t gfp_mask,
+@@ -707,7 +707,7 @@
+ }
+ EXPORT_SYMBOL(vlan_hwaccel_rx_debug);
+-EXPORT_SYMBOL(netif_rx_debug);
++EXPORT_SYMBOL(netif_receive_skb_debug);
+ EXPORT_SYMBOL(alloc_skb_debug);
+ EXPORT_SYMBOL(dev_alloc_skb_debug);
+ EXPORT_SYMBOL(skb_clone_debug);
+Index: madwifi-trunk-r3776/net80211/ieee80211_skb.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_skb.h  2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_skb.h       2008-07-17 01:42:43.000000000 +0200
+@@ -115,7 +115,7 @@
+ int vlan_hwaccel_rx_debug(struct sk_buff *skb, struct vlan_group *grp,
+               unsigned short vlan_tag, const char *func, int line);
+-int netif_rx_debug(struct sk_buff *skb, const char *func, int line);
++int netif_receive_skb_debug(struct sk_buff *skb, const char *func, int line);
+ struct sk_buff *alloc_skb_debug(unsigned int length, gfp_t gfp_mask,
+               const char *func, int line);
+ struct sk_buff *dev_alloc_skb_debug(unsigned int length,
+@@ -150,7 +150,7 @@
+ #undef dev_queue_xmit
+ #undef kfree_skb
+ #undef kfree_skb_fast
+-#undef netif_rx
++#undef netif_receive_skb
+ #undef pskb_copy
+ #undef skb_clone
+ #undef skb_copy
+@@ -167,8 +167,8 @@
+       skb_copy_expand_debug(_skb, _newheadroom, _newtailroom, _gfp_mask, __func__, __LINE__)
+ #define vlan_hwaccel_rx(_skb, _grp, _tag) \
+       vlan_hwaccel_rx_debug(_skb, _grp, _tag, __func__, __LINE__)
+-#define netif_rx(_skb) \
+-      netif_rx_debug(_skb, __func__, __LINE__)
++#define netif_receive_skb(_skb) \
++      netif_receive_skb_debug(_skb, __func__, __LINE__)
+ #define       alloc_skb(_length, _gfp_mask) \
+       alloc_skb_debug(_length, _gfp_mask, __func__, __LINE__)
+ #define       dev_alloc_skb(_length) \
+Index: madwifi-trunk-r3776/net80211/ieee80211_input.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_input.c        2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_input.c     2008-07-17 01:41:16.000000000 +0200
+@@ -1185,7 +1185,7 @@
+                       ret = vlan_hwaccel_rx(skb,
+                                       vap->iv_vlgrp, ni->ni_vlan);
+               else
+-                      ret = netif_rx(skb);
++                      ret = netif_receive_skb(skb);
+               if (ret == NET_RX_DROP)
+                       vap->iv_devstats.rx_dropped++;
+               if (tni != NULL)
+@@ -2285,7 +2285,7 @@
+               if (SKB_NI(skb1) != NULL)
+                       ieee80211_unref_node(&SKB_NI(skb1));
+-              if (netif_rx(skb1) == NET_RX_DROP)
++              if (netif_receive_skb(skb1) == NET_RX_DROP)
+                       vap->iv_devstats.rx_dropped++;
+       }
+ }
+Index: madwifi-trunk-r3776/net80211/ieee80211_monitor.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_monitor.c      2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_monitor.c   2008-07-17 01:41:51.000000000 +0200
+@@ -580,7 +580,7 @@
+                       if (SKB_NI(skb1) != NULL)
+                               ieee80211_unref_node(&SKB_NI(skb1));
+-                      if (netif_rx(skb1) == NET_RX_DROP)
++                      if (netif_receive_skb(skb1) == NET_RX_DROP)
+                               vap->iv_devstats.rx_dropped++;
+                       skb1 = NULL;
+               }
diff --git a/package/madwifi/patches-r3776/301-pureg_fix.patch b/package/madwifi/patches-r3776/301-pureg_fix.patch
new file mode 100644 (file)
index 0000000..de8d83c
--- /dev/null
@@ -0,0 +1,178 @@
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 01:46:37.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 01:46:44.000000000 +0200
+@@ -4250,7 +4250,9 @@
+               rfilt |= HAL_RX_FILTER_PROM;
+       if (ic->ic_opmode == IEEE80211_M_STA ||
+           sc->sc_opmode == HAL_M_IBSS ||      /* NB: AHDEMO too */
+-          (sc->sc_nostabeacons) || sc->sc_scanning)
++          (sc->sc_nostabeacons) || sc->sc_scanning ||
++              ((ic->ic_opmode == IEEE80211_M_HOSTAP) &&
++               (ic->ic_protmode != IEEE80211_PROT_NONE)))
+               rfilt |= HAL_RX_FILTER_BEACON;
+       if (sc->sc_nmonvaps > 0)
+               rfilt |= (HAL_RX_FILTER_CONTROL | HAL_RX_FILTER_BEACON |
+Index: madwifi-trunk-r3776/net80211/ieee80211_input.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_input.c        2008-07-17 01:41:16.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_input.c     2008-07-17 01:46:44.000000000 +0200
+@@ -325,11 +325,12 @@
+                               bssid = wh->i_addr3;
+                       }
+                       /*
+-                       * Validate the bssid.
++                       * Validate the bssid. Let beacons get through though for 11g protection mode.
+                        */
+-#ifdef ATH_SUPERG_XR
+                       if (!IEEE80211_ADDR_EQ(bssid, vap->iv_bssid) &&
+-                          !IEEE80211_ADDR_EQ(bssid, dev->broadcast)) {
++                          !IEEE80211_ADDR_EQ(bssid, dev->broadcast) &&
++                              (subtype != IEEE80211_FC0_SUBTYPE_BEACON)) {
++#ifdef ATH_SUPERG_XR
+                               /*
+                                * allow MGT frames to vap->iv_xrvap.
+                                * this will allow roaming between  XR and normal vaps
+@@ -345,18 +346,14 @@
+                                       vap->iv_stats.is_rx_wrongbss++;
+                                       goto out;
+                               }
+-                      }
+ #else
+-                      if (!IEEE80211_ADDR_EQ(bssid, vap->iv_bssid) &&
+-                          !IEEE80211_ADDR_EQ(bssid, dev->broadcast)) {
+                               /* not interested in */
+                               IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
+                                       bssid, NULL, "%s", "not to bss");
+                               vap->iv_stats.is_rx_wrongbss++;
+                               goto out;
+-                      }
+-
+ #endif
++                      }
+                       break;
+               case IEEE80211_M_WDS:
+                       if (skb->len < sizeof(struct ieee80211_frame_addr4)) {
+@@ -3019,7 +3016,7 @@
+       u_int8_t *frm, *efrm;
+       u_int8_t *ssid, *rates, *xrates, *suppchan, *wpa, *rsn, *wme, *ath;
+       u_int8_t rate;
+-      int reassoc, resp, allocbs = 0;
++      int reassoc, resp, allocbs = 0, has_erp = 0;
+       u_int8_t qosinfo;
+       if (ni_or_null == NULL)
+@@ -3049,11 +3046,15 @@
+                *    o station mode when associated (to collect state
+                *      updates such as 802.11g slot time), or
+                *    o adhoc mode (to discover neighbors)
++               *    o ap mode in protection mode (beacons only)
+                * Frames otherwise received are discarded.
+                */
+               if (!((ic->ic_flags & IEEE80211_F_SCAN) ||
+                   (vap->iv_opmode == IEEE80211_M_STA && ni->ni_associd) ||
+-                  vap->iv_opmode == IEEE80211_M_IBSS)) {
++                  (vap->iv_opmode == IEEE80211_M_IBSS) ||
++                      ((subtype == IEEE80211_FC0_SUBTYPE_BEACON) &&
++                       (vap->iv_opmode == IEEE80211_M_HOSTAP) &&
++                       (ic->ic_protmode != IEEE80211_PROT_NONE)))) {
+                       vap->iv_stats.is_rx_mgtdiscard++;
+                       return 0;
+               }
+@@ -3137,6 +3138,7 @@
+                                       break;
+                               }
+                               scan.erp = frm[2];
++                              has_erp = 1;
+                               break;
+                       case IEEE80211_ELEMID_RSN:
+                               scan.rsn = frm;
+@@ -3374,6 +3376,20 @@
+                               ieee80211_bg_scan(vap);
+                       return 0;
+               }
++
++              /* Update AP protection mode when in 11G mode */
++              if ((vap->iv_opmode == IEEE80211_M_HOSTAP) &&
++                      IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) {
++
++                      /* Assume no ERP IE == 11b AP */
++                      if ((!has_erp || (has_erp && (scan.erp & IEEE80211_ERP_NON_ERP_PRESENT))) &&
++                              !(ic->ic_flags & IEEE80211_F_USEPROT)) {
++
++                              ic->ic_flags |= IEEE80211_F_USEPROT;
++                              ic->ic_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++                      }
++              }
++
+               /*
+                * If scanning, just pass information to the scan module.
+                */
+Index: madwifi-trunk-r3776/net80211/ieee80211_node.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_node.c 2008-07-17 00:53:20.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_node.c      2008-07-17 01:46:44.000000000 +0200
+@@ -345,10 +345,16 @@
+       /* Update country ie information */
+       ieee80211_build_countryie(ic);
+-      if (IEEE80211_IS_CHAN_HALF(chan))
++      if (IEEE80211_IS_CHAN_HALF(chan)) {
+               ni->ni_rates = ic->ic_sup_half_rates;
+-      else if (IEEE80211_IS_CHAN_QUARTER(chan))
++      } else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
+               ni->ni_rates = ic->ic_sup_quarter_rates;
++      }
++
++      if ((vap->iv_flags & IEEE80211_F_PUREG) &&
++              IEEE80211_IS_CHAN_ANYG(chan)) {
++              ieee80211_setpuregbasicrates(&ni->ni_rates);
++      }
+       (void) ieee80211_sta_join1(PASS_NODE(ni));
+ }
+Index: madwifi-trunk-r3776/net80211/ieee80211_proto.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_proto.c        2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_proto.c     2008-07-17 01:46:44.000000000 +0200
+@@ -599,6 +599,28 @@
+       { 4, { 2, 4, 11, 22 } },        /* IEEE80211_MODE_TURBO_G (mixed b/g) */
+ };
++static const struct ieee80211_rateset basicpureg[] = {
++    { 7, {2, 4, 11, 22, 12, 24, 48 } },
++};
++
++/*
++ * Mark basic rates for the 11g rate table based on the pureg setting
++ */
++void
++ieee80211_setpuregbasicrates(struct ieee80211_rateset *rs)
++{
++      int i, j;
++
++      for (i = 0; i < rs->rs_nrates; i++) {
++              rs->rs_rates[i] &= IEEE80211_RATE_VAL;
++              for (j = 0; j < basicpureg[0].rs_nrates; j++)
++                      if (basicpureg[0].rs_rates[j] == rs->rs_rates[i]) {
++                              rs->rs_rates[i] |= IEEE80211_RATE_BASIC;
++                              break;
++                      }
++      }
++}
++
+ /*
+  * Mark the basic rates for the 11g rate table based on the
+  * specified mode.  For 11b compatibility we mark only 11b
+Index: madwifi-trunk-r3776/net80211/ieee80211_var.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_var.h  2008-07-17 00:53:20.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_var.h       2008-07-17 01:46:44.000000000 +0200
+@@ -712,6 +712,7 @@
+ void ieee80211_build_sc_ie(struct ieee80211com *);
+ void ieee80211_dfs_action(struct ieee80211com *);
+ void ieee80211_expire_channel_excl_restrictions(struct ieee80211com *);
++void ieee80211_setpuregbasicrates(struct ieee80211_rateset *rs);
+ /*
+  * Iterate through ic_channels to enumerate all distinct ic_ieee channel numbers.
diff --git a/package/madwifi/patches-r3776/302-noise_get.patch b/package/madwifi/patches-r3776/302-noise_get.patch
new file mode 100644 (file)
index 0000000..98440f7
--- /dev/null
@@ -0,0 +1,44 @@
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 01:46:44.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 01:49:58.000000000 +0200
+@@ -8996,6 +8996,7 @@
+                       ATH_LONG_CALINTERVAL_SECS : 
+                       ATH_SHORT_CALINTERVAL_SECS;
+       }
++      ic->ic_channoise = ath_hal_get_channel_noise(ah, &(sc->sc_curchan));
+       DPRINTF(sc, ATH_DEBUG_CALIBRATE, "Channel %u [flags=%04x] -- IQ %s.\n",
+               sc->sc_curchan.channel, sc->sc_curchan.channelFlags,
+@@ -9051,6 +9052,7 @@
+       struct ath_softc *sc = dev->priv;
+       (void) ath_chan_set(sc, ic->ic_curchan);
++      ic->ic_channoise = ath_hal_get_channel_noise(sc->sc_ah, &(sc->sc_curchan));
+       /*
+        * If we are returning to our bss channel then mark state
+        * so the next recv'd beacon's TSF will be used to sync the
+Index: madwifi-trunk-r3776/net80211/ieee80211_wireless.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_wireless.c     2008-07-17 00:53:20.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_wireless.c  2008-07-17 01:49:58.000000000 +0200
+@@ -4396,6 +4396,7 @@
+       si->isi_state = ni->ni_flags;
+       si->isi_authmode = ni->ni_authmode;
+       si->isi_rssi = ic->ic_node_getrssi(ni);
++      si->isi_noise = ic->ic_channoise;
+       si->isi_capinfo = ni->ni_capinfo;
+       si->isi_athflags = ni->ni_ath_flags;
+       si->isi_erp = ni->ni_erp;
+Index: madwifi-trunk-r3776/net80211/ieee80211_ioctl.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_ioctl.h        2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_ioctl.h     2008-07-17 01:49:58.000000000 +0200
+@@ -312,6 +312,7 @@
+       u_int16_t isi_state;            /* state flags */
+       u_int8_t isi_authmode;          /* authentication algorithm */
+       u_int8_t isi_rssi;
++      int8_t isi_noise;
+       u_int16_t isi_capinfo;          /* capabilities */
+       u_int8_t isi_athflags;          /* Atheros capabilities */
+       u_int8_t isi_erp;               /* ERP element */
diff --git a/package/madwifi/patches-r3776/303-bssid_alloc.patch b/package/madwifi/patches-r3776/303-bssid_alloc.patch
new file mode 100644 (file)
index 0000000..c10a21c
--- /dev/null
@@ -0,0 +1,53 @@
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 01:49:58.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 01:57:39.000000000 +0200
+@@ -1333,7 +1333,7 @@
+               /* Use RadioTAP interface type for monitor mode. */
+               dev->type = ARPHRD_IEEE80211_RADIOTAP;
+-      if (flags & IEEE80211_CLONE_BSSID) {
++      if (!(flags & IEEE80211_CLONE_BSSID)) {
+               if (sc->sc_hasbmask) {
+                       struct ieee80211vap *v;
+                       uint64_t id_mask = 0;
+@@ -1347,11 +1347,12 @@
+                       TAILQ_FOREACH(v, &ic->ic_vaps, iv_next)
+                               id_mask |= (1 << ATH_GET_VAP_ID(v->iv_myaddr));
+-                      for (id = 1; id < ath_maxvaps; id++) {
++                      for (id = 0; id < ath_maxvaps; id++) {
+                               /* Get the first available slot. */
+                               if ((id_mask & (1 << id)) == 0) {
+                                       ATH_SET_VAP_BSSID(vap->iv_myaddr, id);
+                                       ATH_SET_VAP_BSSID(vap->iv_bssid, id);
++                                      sc->sc_bclast = id;
+                                       break;
+                               }
+                       }
+@@ -1359,7 +1360,12 @@
+                       EPRINTF(sc, "Unique BSSID requested on HW that does"
+                               "does not support the necessary features.");
+               }
++      } else {
++              /* share the BSSID of the last created VAP */
++              ATH_SET_VAP_BSSID(vap->iv_myaddr, sc->sc_bclast);
++              ATH_SET_VAP_BSSID(vap->iv_bssid, sc->sc_bclast);
+       }
++
+       avp->av_bslot = -1;
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
+       atomic_set(&avp->av_beacon_alloc, 0);
+Index: madwifi-trunk-r3776/ath/if_athvar.h
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_athvar.h   2008-07-17 01:27:21.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_athvar.h        2008-07-17 01:57:15.000000000 +0200
+@@ -802,7 +802,7 @@
+       } sc_updateslot;                        /* slot time update fsm */
+       int sc_slotupdate;                      /* slot to next advance fsm */
+       struct ieee80211vap **sc_bslot;         /* beacon xmit slots */
+-      int sc_bnext;                           /* next slot for beacon xmit */
++      int sc_bclast;                          /* last used slot for beacon xmit */
+       int sc_beacon_cal;                      /* use beacon timer for calibration */
+       long unsigned int sc_calinterval_sec;   /* current interval for calibration (in seconds) */
diff --git a/package/madwifi/patches-r3776/304-erp_update.patch b/package/madwifi/patches-r3776/304-erp_update.patch
new file mode 100644 (file)
index 0000000..796406e
--- /dev/null
@@ -0,0 +1,74 @@
+Index: madwifi-trunk-r3776/net80211/ieee80211_beacon.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_beacon.c       2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_beacon.c    2008-07-17 01:58:24.000000000 +0200
+@@ -544,10 +544,10 @@
+                       vap->iv_flags &= ~IEEE80211_F_XRUPDATE;
+               }
+ #endif
+-              if ((ic->ic_flags_ext & IEEE80211_FEXT_ERPUPDATE) && 
++              if ((vap->iv_flags_ext & IEEE80211_FEXT_ERPUPDATE) &&
+                               (bo->bo_erp != NULL)) {
+                       (void)ieee80211_add_erp(bo->bo_erp, ic);
+-                      ic->ic_flags_ext &= ~IEEE80211_FEXT_ERPUPDATE;
++                      vap->iv_flags_ext &= ~IEEE80211_FEXT_ERPUPDATE;
+               }
+       }
+       /* if it is a mode change beacon for dynamic turbo case */
+Index: madwifi-trunk-r3776/net80211/ieee80211_input.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_input.c        2008-07-17 01:46:44.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_input.c     2008-07-17 01:58:24.000000000 +0200
+@@ -3384,9 +3384,12 @@
+                       /* Assume no ERP IE == 11b AP */
+                       if ((!has_erp || (has_erp && (scan.erp & IEEE80211_ERP_NON_ERP_PRESENT))) &&
+                               !(ic->ic_flags & IEEE80211_F_USEPROT)) {
++                              struct ieee80211vap *tmpvap;
+                               ic->ic_flags |= IEEE80211_F_USEPROT;
+-                              ic->ic_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++                              TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
++                                      tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++                              }
+                       }
+               }
+Index: madwifi-trunk-r3776/net80211/ieee80211_node.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_node.c 2008-07-17 01:46:44.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_node.c      2008-07-17 01:58:24.000000000 +0200
+@@ -1741,8 +1741,12 @@
+               }
+               /* Update ERP element if this is first non ERP station */
+-              if (ic->ic_nonerpsta == 1)
+-                      ic->ic_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++              if (ic->ic_nonerpsta == 1) {
++                      struct ieee80211vap *tmpvap;
++                      TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
++                              tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++                      }
++              }
+       } else
+               ni->ni_flags |= IEEE80211_NODE_ERP;
+ }
+@@ -1945,6 +1949,8 @@
+               IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni,
+                       "non-ERP station leaves, count now %d", ic->ic_nonerpsta);
+               if (ic->ic_nonerpsta == 0) {
++                      struct ieee80211vap *tmpvap;
++
+                       IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,
+                               "%s: disable use of protection\n", __func__);
+                       ic->ic_flags &= ~IEEE80211_F_USEPROT;
+@@ -1956,7 +1962,9 @@
+                               ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
+                               ic->ic_flags &= ~IEEE80211_F_USEBARKER;
+                       }
+-                      ic->ic_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++                      TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
++                              tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++                      }
+               }
+       }
+ }
diff --git a/package/madwifi/patches-r3776/305-bssid_mask.patch b/package/madwifi/patches-r3776/305-bssid_mask.patch
new file mode 100644 (file)
index 0000000..24d2f9f
--- /dev/null
@@ -0,0 +1,13 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -8692,6 +8692,10 @@
+       sc->sc_rxbufcur = NULL;
++      /* configure bssid mask */
++      if (sc->sc_hasbmask)
++              ath_hal_setbssidmask(ah, sc->sc_bssidmask);
++
+       bf = STAILQ_FIRST(&sc->sc_rxbuf);
+       ath_hal_putrxbuf(ah, bf->bf_daddr);
+       ath_hal_rxena(ah);              /* enable recv descriptors */
diff --git a/package/madwifi/patches-r3776/306-queue.patch b/package/madwifi/patches-r3776/306-queue.patch
new file mode 100644 (file)
index 0000000..4b9665f
--- /dev/null
@@ -0,0 +1,46 @@
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 02:00:09.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 02:09:38.000000000 +0200
+@@ -8447,8 +8447,6 @@
+       ath_hal_intrset(sc->sc_ah, sc->sc_imask);
+       local_irq_restore(flags);
+-      netif_wake_queue(dev);
+-
+       if (sc->sc_softled)
+               ath_led_event(sc, ATH_LED_TX);
+ }
+@@ -8504,8 +8502,6 @@
+       ath_hal_intrset(sc->sc_ah, sc->sc_imask);
+       local_irq_restore(flags);
+-      netif_wake_queue(dev);
+-
+       if (sc->sc_softled)
+               ath_led_event(sc, ATH_LED_TX);
+ }
+@@ -8536,7 +8532,9 @@
+                               STAILQ_FIRST(&sc->sc_cabq->axq_q) ? "not setup" : "empty");
+               }
+       }
+-      netif_wake_queue(dev);
++
++      if (ath_get_buffers_available(sc) > ATH_TXBUF_MGT_RESERVED)
++              netif_wake_queue(dev);
+       if (sc->sc_softled)
+               ath_led_event(sc, ATH_LED_TX);
+Index: madwifi-trunk-r3776/net80211/ieee80211_input.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_input.c        2008-07-17 02:04:20.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_input.c     2008-07-17 02:05:45.000000000 +0200
+@@ -1116,7 +1116,7 @@
+           (vap->iv_flags & IEEE80211_F_NOBRIDGE) == 0) {
+               struct sk_buff *skb1 = NULL;
+-              if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
++              if (ETHER_IS_MULTICAST(eh->ether_dhost) && !netif_queue_stopped(dev)) {
+                       /* Create a SKB for the BSS to send out. */
+                       skb1 = skb_copy(skb, GFP_ATOMIC);
+                       if (skb1)
diff --git a/package/madwifi/patches-r3776/307-maxrate.patch b/package/madwifi/patches-r3776/307-maxrate.patch
new file mode 100644 (file)
index 0000000..fc3363d
--- /dev/null
@@ -0,0 +1,108 @@
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 02:20:52.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 02:20:53.000000000 +0200
+@@ -1299,6 +1299,7 @@
+       vap->iv_key_set = ath_key_set;
+       vap->iv_key_update_begin = ath_key_update_begin;
+       vap->iv_key_update_end = ath_key_update_end;
++      vap->iv_maxrateindex = 0;
+       if (sc->sc_default_ieee80211_debug) {
+               /* User specified defaults for new VAPs were provided, so
+                * use those (only). */
+Index: madwifi-trunk-r3776/ath_rate/sample/sample.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath_rate/sample/sample.c  2008-07-17 02:20:26.000000000 +0200
++++ madwifi-trunk-r3776/ath_rate/sample/sample.c       2008-07-17 02:20:53.000000000 +0200
+@@ -838,7 +838,12 @@
+       }
+       sn->static_rate_ndx = -1;
+-      sn->num_rates = ni->ni_rates.rs_nrates;
++      if (vap->iv_maxrateindex == 0 || ni->ni_rates.rs_nrates <= 0
++          || vap->iv_maxrateindex > ni->ni_rates.rs_nrates)
++              sn->num_rates = ni->ni_rates.rs_nrates;
++      else
++              sn->num_rates = vap->iv_maxrateindex;
++
+       for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
+               sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
+               sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
+Index: madwifi-trunk-r3776/net80211/ieee80211_var.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_var.h  2008-07-17 02:20:51.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_var.h       2008-07-17 02:20:53.000000000 +0200
+@@ -291,6 +291,7 @@
+       struct ieee80211_spy iv_spy;                    /* IWSPY support */
+       struct ieee80211_app_ie app_ie[IEEE80211_APPIE_NUM_OF_FRAME]; /* app-specified IEs by frame type */
+       u_int32_t app_filter;                           /* filters which management frames are forwarded to app */
++      int iv_maxrateindex;
+ };
+ /* Debug functions need the defintion of struct ieee80211vap because iv_debug 
+Index: madwifi-trunk-r3776/net80211/ieee80211_wireless.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_wireless.c     2008-07-17 02:20:51.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_wireless.c  2008-07-17 02:20:53.000000000 +0200
+@@ -2873,6 +2873,12 @@
+               else
+                       ic->ic_flags_ext &= ~IEEE80211_FEXT_MARKDFS;
+               break;
++      case IEEE80211_PARAM_MAXRATE:
++              if (value > 0)
++                      vap->iv_maxrateindex = value;
++              else
++                      vap->iv_maxrateindex = 0;
++              break;
+ #ifdef ATH_REVERSE_ENGINEERING
+       case IEEE80211_PARAM_DUMPREGS:
+               ieee80211_dump_registers(dev, info, w, extra);
+@@ -3211,6 +3217,9 @@
+               else
+                       param[0] = 0;
+               break;
++      case IEEE80211_PARAM_MAXRATE:
++              param[0] = vap->iv_maxrateindex;
++              break;
+       default:
+               return -EOPNOTSUPP;
+       }
+@@ -5666,6 +5675,10 @@
+         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "debug_scanbufs" },
+       { IEEE80211_PARAM_LEAKTXBUFS,
+         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "debug_leaktxbufs" },
++      {IEEE80211_PARAM_MAXRATE,
++       IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "maxrate"},
++      {IEEE80211_PARAM_MAXRATE,
++       0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_maxrate"},
+       
+ #ifdef ATH_REVERSE_ENGINEERING
+       /*
+Index: madwifi-trunk-r3776/net80211/ieee80211_ioctl.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_ioctl.h        2008-07-17 02:20:51.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_ioctl.h     2008-07-17 02:20:53.000000000 +0200
+@@ -650,6 +650,7 @@
+       IEEE80211_PARAM_RESETTXBUFS             = 80,   /* Reset transmit DMA */
+       IEEE80211_PARAM_SCANBUFS                = 81,   /* Heap analysis for TX DMA */
+       IEEE80211_PARAM_LEAKTXBUFS              = 82,   /* Leak tx buffers */
++      IEEE80211_PARAM_MAXRATE                 = 83,   /* Maximum rate (by table index) */
+ };
+ #define       SIOCG80211STATS                 (SIOCDEVPRIVATE+2)
+Index: madwifi-trunk-r3776/ath_rate/minstrel/minstrel.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath_rate/minstrel/minstrel.c      2008-07-17 02:22:27.000000000 +0200
++++ madwifi-trunk-r3776/ath_rate/minstrel/minstrel.c   2008-07-17 02:22:33.000000000 +0200
+@@ -644,6 +644,11 @@
+               return;
+       }
+       sn->static_rate_ndx = -1;
++      if (vap->iv_maxrateindex == 0 || ni->ni_rates.rs_nrates <= 0
++          || vap->iv_maxrateindex > ni->ni_rates.rs_nrates)
++              sn->num_rates = ni->ni_rates.rs_nrates;
++      else
++              sn->num_rates = vap->iv_maxrateindex;
+       sn->num_rates = ni->ni_rates.rs_nrates;
+       for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
diff --git a/package/madwifi/patches-r3776/308-minrate.patch b/package/madwifi/patches-r3776/308-minrate.patch
new file mode 100644 (file)
index 0000000..616aec9
--- /dev/null
@@ -0,0 +1,124 @@
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 02:20:53.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 02:23:00.000000000 +0200
+@@ -1300,6 +1300,7 @@
+       vap->iv_key_update_begin = ath_key_update_begin;
+       vap->iv_key_update_end = ath_key_update_end;
+       vap->iv_maxrateindex = 0;
++      vap->iv_minrateindex = 0;
+       if (sc->sc_default_ieee80211_debug) {
+               /* User specified defaults for new VAPs were provided, so
+                * use those (only). */
+Index: madwifi-trunk-r3776/ath_rate/minstrel/minstrel.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath_rate/minstrel/minstrel.c      2008-07-17 02:22:33.000000000 +0200
++++ madwifi-trunk-r3776/ath_rate/minstrel/minstrel.c   2008-07-17 02:27:44.000000000 +0200
+@@ -652,6 +652,8 @@
+       sn->num_rates = ni->ni_rates.rs_nrates;
+       for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
++              int idx = x;
++
+               sn->rs_rateattempts     [x] = 0;
+               sn->rs_thisprob         [x] = 0;
+               sn->rs_ratesuccess      [x] = 0;
+@@ -662,8 +664,12 @@
+               sn->rs_att_hist         [x] = 0;
+               sn->rs_this_tp          [x] = 0;
+-              sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
+-              sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
++              if (vap->iv_minrateindex && (vap->iv_minrateindex <
++                              ni->ni_rates.rs_nrates))
++                      idx = vap->iv_minrateindex;
++
++              sn->rates[x].rate = ni->ni_rates.rs_rates[idx] & IEEE80211_RATE_VAL;
++              sn->rates[x].rix = sc->sc_rixmap[sn->rates[idx].rate];
+               if (sn->rates[x].rix == 0xff) {
+                       DPRINTF(sc, "%s: %s ignore bogus rix at %d\n",
+                               dev_info, __func__, x);
+Index: madwifi-trunk-r3776/ath_rate/sample/sample.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath_rate/sample/sample.c  2008-07-17 02:20:53.000000000 +0200
++++ madwifi-trunk-r3776/ath_rate/sample/sample.c       2008-07-17 02:27:08.000000000 +0200
+@@ -845,8 +845,15 @@
+               sn->num_rates = vap->iv_maxrateindex;
+       for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
+-              sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
+-              sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
++              int idx = x;
++
++              if (vap->iv_minrateindex && vap->iv_minrateindex <
++                              ni->ni_rates.rs_nrates)
++                      idx = vap->iv_minrateindex;
++
++              sn->rates[x].rate = ni->ni_rates.rs_rates[idx] & IEEE80211_RATE_VAL;
++              sn->rates[x].rix = sc->sc_rixmap[sn->rates[idx].rate];
++
+               if (sn->rates[x].rix == 0xff) {
+                       DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s ignore bogus rix at %u\n",
+                               dev_info, __func__, x);
+Index: madwifi-trunk-r3776/net80211/ieee80211_ioctl.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_ioctl.h        2008-07-17 02:20:53.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_ioctl.h     2008-07-17 02:25:53.000000000 +0200
+@@ -651,6 +651,7 @@
+       IEEE80211_PARAM_SCANBUFS                = 81,   /* Heap analysis for TX DMA */
+       IEEE80211_PARAM_LEAKTXBUFS              = 82,   /* Leak tx buffers */
+       IEEE80211_PARAM_MAXRATE                 = 83,   /* Maximum rate (by table index) */
++      IEEE80211_PARAM_MINRATE                 = 84,   /* Minimum rate (by table index) */
+ };
+ #define       SIOCG80211STATS                 (SIOCDEVPRIVATE+2)
+Index: madwifi-trunk-r3776/net80211/ieee80211_var.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_var.h  2008-07-17 02:20:53.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_var.h       2008-07-17 02:23:00.000000000 +0200
+@@ -292,6 +292,7 @@
+       struct ieee80211_app_ie app_ie[IEEE80211_APPIE_NUM_OF_FRAME]; /* app-specified IEs by frame type */
+       u_int32_t app_filter;                           /* filters which management frames are forwarded to app */
+       int iv_maxrateindex;
++      int iv_minrateindex;
+ };
+ /* Debug functions need the defintion of struct ieee80211vap because iv_debug 
+Index: madwifi-trunk-r3776/net80211/ieee80211_wireless.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_wireless.c     2008-07-17 02:20:53.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_wireless.c  2008-07-17 02:26:17.000000000 +0200
+@@ -2879,6 +2879,12 @@
+               else
+                       vap->iv_maxrateindex = 0;
+               break;
++      case IEEE80211_PARAM_MINRATE:
++              if (value > 0)
++                      vap->iv_minrateindex = value;
++              else
++                      vap->iv_minrateindex = 0;
++              break;
+ #ifdef ATH_REVERSE_ENGINEERING
+       case IEEE80211_PARAM_DUMPREGS:
+               ieee80211_dump_registers(dev, info, w, extra);
+@@ -3220,6 +3226,9 @@
+       case IEEE80211_PARAM_MAXRATE:
+               param[0] = vap->iv_maxrateindex;
+               break;
++      case IEEE80211_PARAM_MINRATE:
++              param[0] = vap->iv_minrateindex;
++              break;
+       default:
+               return -EOPNOTSUPP;
+       }
+@@ -5679,6 +5688,10 @@
+        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "maxrate"},
+       {IEEE80211_PARAM_MAXRATE,
+        0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_maxrate"},
++      {IEEE80211_PARAM_MINRATE,
++       IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "minrate"},
++      {IEEE80211_PARAM_MINRATE,
++       0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_minrate"},
+       
+ #ifdef ATH_REVERSE_ENGINEERING
+       /*
diff --git a/package/madwifi/patches-r3776/309-performance.patch b/package/madwifi/patches-r3776/309-performance.patch
new file mode 100644 (file)
index 0000000..517c336
--- /dev/null
@@ -0,0 +1,221 @@
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 02:23:00.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 02:28:06.000000000 +0200
+@@ -3334,7 +3334,6 @@
+       struct ath_softc *sc = dev->priv;
+       struct ieee80211_node *ni = NULL;
+       struct ath_buf *bf = NULL;
+-      struct ether_header *eh;
+       ath_bufhead bf_head;
+       struct ath_buf *tbf;
+       struct sk_buff *tskb;
+@@ -3349,6 +3348,7 @@
+       */
+       int requeue = 0;
+ #ifdef ATH_SUPERG_FF
++      struct ether_header *eh;
+       unsigned int pktlen;
+       struct ieee80211com *ic = &sc->sc_ic;
+       struct ath_txq *txq = NULL;
+Index: madwifi-trunk-r3776/net80211/ieee80211_output.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_output.c       2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_output.c    2008-07-17 02:35:10.000000000 +0200
+@@ -280,7 +280,7 @@
+        * normal vap. */
+       if (vap->iv_xrvap && (ni == vap->iv_bss) &&
+           vap->iv_xrvap->iv_sta_assoc) {
+-              struct sk_buff *skb1 = skb_copy(skb, GFP_ATOMIC);
++              struct sk_buff *skb1 = skb_clone(skb, GFP_ATOMIC);
+               if (skb1) {
+                       memset(SKB_CB(skb1), 0, sizeof(struct ieee80211_cb));
+ #ifdef IEEE80211_DEBUG_REFCNT
+@@ -561,7 +561,7 @@
+       struct ieee80211_key *key, struct sk_buff *skb, int ismulticast)
+ {
+       /* XXX pre-calculate per node? */
+-      int need_headroom = LLC_SNAPFRAMELEN + hdrsize + IEEE80211_ADDR_LEN;
++      int need_headroom = LLC_SNAPFRAMELEN + hdrsize;
+       int need_tailroom = 0;
+ #ifdef ATH_SUPERG_FF
+       int isff = ATH_FF_MAGIC_PRESENT(skb);
+@@ -603,109 +603,56 @@
+                               need_tailroom += cip->ic_miclen;
+       }
+-      if (skb_shared(skb)) {
+-              /* Take our own reference to the node in the clone */
+-              ieee80211_ref_node(SKB_NI(skb));
+-              /* Unshare the node, decrementing users in the old skb */
+-              skb = skb_unshare(skb, GFP_ATOMIC);
++      need_headroom -= skb_headroom(skb);
++      if (isff)
++              need_tailroom -= skb_tailroom(skb2);
++      else
++              need_tailroom -= skb_tailroom(skb);
++
++      if (need_headroom < 0)
++              need_headroom = 0;
++      if (need_tailroom < 0)
++              need_tailroom = 0;
++
++      if (skb_cloned(skb) || (need_headroom > 0) ||
++              (!isff && (need_tailroom > 0))) {
++
++              if (pskb_expand_head(skb, need_headroom, need_tailroom, GFP_ATOMIC)) {
++                      IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
++                              "%s: cannot expand storage (tail)\n", __func__);
++                      goto error;
++              }
+       }
+ #ifdef ATH_SUPERG_FF
+       if (isff) {
+-              if (skb == NULL) {
+-                      IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+-                              "%s: cannot unshare for encapsulation\n",
+-                              __func__);
+-                      vap->iv_stats.is_tx_nobuf++;
+-                      ieee80211_dev_kfree_skb(&skb2);
+-
+-                      return NULL;
+-              }
++              inter_headroom -= skb_headroom(skb2);
++              if (inter_headroom < 0)
++                      inter_headroom = 0;
++              if ((skb_cloned(skb2) ||
++                      (inter_headroom > 0) || (need_tailroom > 0))) {
+-              /* first skb header */
+-              if (skb_headroom(skb) < need_headroom) {
+-                      struct sk_buff *tmp = skb;
+-                      skb = skb_realloc_headroom(skb, need_headroom);
+-                      if (skb == NULL) {
++                      if (pskb_expand_head(skb2, inter_headroom,
++                              need_tailroom, GFP_ATOMIC)) {
+                               IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+-                                      "%s: cannot expand storage (head1)\n",
+-                                      __func__);
+-                              vap->iv_stats.is_tx_nobuf++;
+-                              ieee80211_dev_kfree_skb(&skb2);
+-                              return NULL;
+-                      } else
+-                              ieee80211_skb_copy_noderef(tmp, skb);
+-                      ieee80211_dev_kfree_skb(&tmp);
+-                      /* NB: cb[] area was copied, but not next ptr. must do that
+-                       *     prior to return on success. */
+-              }
+-
+-              /* second skb with header and tail adjustments possible */
+-              if (skb_tailroom(skb2) < need_tailroom) {
+-                      int n = 0;
+-                      if (inter_headroom > skb_headroom(skb2))
+-                              n = inter_headroom - skb_headroom(skb2);
+-                      if (pskb_expand_head(skb2, n,
+-                          need_tailroom - skb_tailroom(skb2), GFP_ATOMIC)) {
+-                              ieee80211_dev_kfree_skb(&skb2);
+-                              IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+-                                      "%s: cannot expand storage (tail2)\n",
+-                                      __func__);
+-                              vap->iv_stats.is_tx_nobuf++;
+-                              /* this shouldn't happen, but don't send first ff either */
+-                              ieee80211_dev_kfree_skb(&skb);
++                                      "%s: cannot expand storage (tail)\n", __func__);
++                              goto error;
+                       }
+-              } else if (skb_headroom(skb2) < inter_headroom) {
+-                      struct sk_buff *tmp = skb2;
+-
+-                      skb2 = skb_realloc_headroom(skb2, inter_headroom);
+-                      if (skb2 == NULL) {
+-                              IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+-                                      "%s: cannot expand storage (head2)\n",
+-                                      __func__);
+-                              vap->iv_stats.is_tx_nobuf++;
+-                              /* this shouldn't happen, but don't send first ff either */
+-                              ieee80211_dev_kfree_skb(&skb);
+-                              skb = NULL;
+-                      } else
+-                              ieee80211_skb_copy_noderef(tmp, skb);
+-                      ieee80211_dev_kfree_skb(&tmp);
+               }
+-              if (skb) {
+-                      skb->next = skb2;
+-              }
+-              return skb;
++              skb->next = skb2;
+       }
+ #endif /* ATH_SUPERG_FF */
+-      if (skb == NULL) {
+-              IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+-                      "%s: cannot unshare for encapsulation\n", __func__);
+-              vap->iv_stats.is_tx_nobuf++;
+-      } else if (skb_tailroom(skb) < need_tailroom) {
+-              int n = 0;
+-              if (need_headroom > skb_headroom(skb))
+-                      n = need_headroom - skb_headroom(skb);
+-              if (pskb_expand_head(skb, n, need_tailroom - 
+-                                      skb_tailroom(skb), GFP_ATOMIC)) {
+-                      IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+-                              "%s: cannot expand storage (tail)\n", __func__);
+-                      vap->iv_stats.is_tx_nobuf++;
+-                      ieee80211_dev_kfree_skb(&skb);
+-              }
+-      } else if (skb_headroom(skb) < need_headroom) {
+-              struct sk_buff *tmp = skb;
+-              skb = skb_realloc_headroom(skb, need_headroom);
+-              /* Increment reference count after copy */
+-              if (skb == NULL) {
+-                      IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+-                              "%s: cannot expand storage (head)\n", __func__);
+-                      vap->iv_stats.is_tx_nobuf++;
+-              } else
+-                      ieee80211_skb_copy_noderef(tmp, skb);
+-              ieee80211_dev_kfree_skb(&tmp);
+-      }
+       return skb;
++
++error:
++      vap->iv_stats.is_tx_nobuf++;
++      ieee80211_dev_kfree_skb(&skb);
++#ifdef ATH_SUPERG_FF
++      if (skb2)
++              ieee80211_dev_kfree_skb(&skb2);
++#endif
++      return NULL;
+ }
+ #define       KEY_UNDEFINED(k)        ((k).wk_cipher == &ieee80211_cipher_none)
+Index: madwifi-trunk-r3776/net80211/ieee80211_input.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_input.c        2008-07-17 02:20:52.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_input.c     2008-07-17 02:30:28.000000000 +0200
+@@ -713,7 +713,7 @@
+                       /* ether_type must be length as FF frames are always LLC/SNAP encap'd */ 
+                       frame_len = ntohs(eh_tmp->ether_type); 
+-                      skb1 = skb_copy(skb, GFP_ATOMIC);
++                      skb1 = skb_clone(skb, GFP_ATOMIC);
+                       if (skb1 == NULL)
+                               goto err;
+                       ieee80211_skb_copy_noderef(skb, skb1);
+@@ -1118,7 +1118,7 @@
+               if (ETHER_IS_MULTICAST(eh->ether_dhost) && !netif_queue_stopped(dev)) {
+                       /* Create a SKB for the BSS to send out. */
+-                      skb1 = skb_copy(skb, GFP_ATOMIC);
++                      skb1 = skb_clone(skb, GFP_ATOMIC);
+                       if (skb1)
+                               SKB_NI(skb1) = ieee80211_ref_node(vap->iv_bss); 
+               }
+@@ -2265,7 +2265,7 @@
+       if (filter_type && ((vap->app_filter & filter_type) == filter_type)) {
+               struct sk_buff *skb1;
+-              skb1 = skb_copy(skb, GFP_ATOMIC);
++              skb1 = skb_clone(skb, GFP_ATOMIC);
+               if (skb1 == NULL)
+                       return;
+               /* We duplicate the reference after skb_copy */
diff --git a/package/madwifi/patches-r3776/310-minstrel_sampling.patch b/package/madwifi/patches-r3776/310-minstrel_sampling.patch
new file mode 100644 (file)
index 0000000..a395b3c
--- /dev/null
@@ -0,0 +1,92 @@
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 02:28:06.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 02:37:41.000000000 +0200
+@@ -8109,6 +8109,7 @@
+               ath_hal_setupxtxdesc(sc->sc_ah, ds, mrr.rate1, mrr.retries1,
+                                    mrr.rate2, mrr.retries2,
+                                    mrr.rate3, mrr.retries3);
++              bf->rcflags = mrr.privflags;
+       }
+ #ifndef ATH_SUPERG_FF
+Index: madwifi-trunk-r3776/ath/if_athvar.h
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_athvar.h   2008-07-17 02:20:51.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_athvar.h        2008-07-17 02:37:41.000000000 +0200
+@@ -454,6 +454,7 @@
+       u_int16_t bf_flags;                             /* tx descriptor flags */
+       u_int64_t bf_tsf;
+       int16_t bf_channoise;
++      unsigned int rcflags;
+ #ifdef ATH_SUPERG_FF
+       /* XXX: combine this with bf_skbaddr if it ever changes to accommodate
+        *      multiple segments.
+Index: madwifi-trunk-r3776/ath_rate/minstrel/minstrel.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath_rate/minstrel/minstrel.c      2008-07-17 02:27:44.000000000 +0200
++++ madwifi-trunk-r3776/ath_rate/minstrel/minstrel.c   2008-07-17 02:39:20.000000000 +0200
+@@ -341,18 +341,21 @@
+               if (sn->static_rate_ndx >= 0) {
+                           ndx = sn->static_rate_ndx;
+               } else {
++                      int delta;
++
+                       sn->packet_count++;
+                       sn->random_n = (sn->a * sn->random_n) + sn->b;
+                       offset = sn->random_n & 0xf;
+-                      if ((((100 * sn->sample_count) / sn->packet_count) < 
+-                                       ath_lookaround_rate) && 
+-                                      (offset < 2)) {
++                      delta = (sn->packet_count * ath_lookaround_rate / 100) - sn->sample_count;
++                      if ((delta > 0) && (offset < 2)) {
+                               sn->sample_count++;
+                               sn->is_sampling = 1;
+                               if (sn->packet_count >= 10000) {
+                                       sn->sample_count = 0;
+                                       sn->packet_count = 0;
++                              } else if (delta > sn->num_rates * 2) {
++                                      sn->sample_count += ((delta - sn->num_rates * 2) * ath_lookaround_rate) / 100;
+                               }
+                               /* Don't look for slowest rate (i.e. slowest
+@@ -420,11 +423,14 @@
+               if (sn->num_rates <= 0)
+                       return;
++              mrr->privflags = sn->is_sampling;
+               if (sn->is_sampling) {
+                       sn->is_sampling = 0;
+-                      if (sn->rs_sample_rate_slower)
++                      if (sn->rs_sample_rate_slower) {
+                               rc1 = sn->rs_sample_rate;
+-                      else
++                              if (sn->sample_count > 0)
++                                      sn->sample_count--;
++                      } else
+                               rc1 = sn->max_tp_rate;
+               } else {
+                       rc1 = sn->max_tp_rate2;
+@@ -552,6 +558,9 @@
+               if (tries <= tries1)
+                       return;
++              if (bf->rcflags)
++                      sn->sample_count++;
++
+               if  (tries2 < 0)
+                       return;
+               tries = tries - tries1;
+Index: madwifi-trunk-r3776/net80211/ieee80211_rate.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_rate.h 2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_rate.h      2008-07-17 02:37:41.000000000 +0200
+@@ -87,6 +87,7 @@
+       int retries2;
+       int rate3;
+       int retries3;
++      int privflags;
+ };
+ struct ieee80211_rate_ops {
diff --git a/package/madwifi/patches-r3776/311-protmode_trigger.patch b/package/madwifi/patches-r3776/311-protmode_trigger.patch
new file mode 100644 (file)
index 0000000..29fc629
--- /dev/null
@@ -0,0 +1,147 @@
+Index: madwifi-trunk-r3776/net80211/ieee80211.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211.c      2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211.c   2008-07-17 02:56:18.000000000 +0200
+@@ -347,7 +347,9 @@
+                       IEEE80211_MS_TO_TU(IEEE80211_BMISSTHRESH_DEFAULT_MS), 
+                       ic->ic_lintval), ic->ic_lintval);
+       }
+-              
++      ic->ic_protmode_timeout = IEEE80211_PROTMODE_TIMEOUT;
++      ic->ic_protmode_rssi = IEEE80211_PROTMODE_RSSITHR;
++
+       IEEE80211_LOCK_INIT(ic, "ieee80211com");
+       IEEE80211_VAPS_LOCK_INIT(ic, "ieee80211com_vaps");
+       TAILQ_INIT(&ic->ic_vaps);
+Index: madwifi-trunk-r3776/net80211/ieee80211_input.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_input.c        2008-07-17 02:30:28.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_input.c     2008-07-17 02:56:18.000000000 +0200
+@@ -3382,14 +3382,18 @@
+                       IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) {
+                       /* Assume no ERP IE == 11b AP */
+-                      if ((!has_erp || (has_erp && (scan.erp & IEEE80211_ERP_NON_ERP_PRESENT))) &&
+-                              !(ic->ic_flags & IEEE80211_F_USEPROT)) {
++                      if ((!has_erp || (has_erp &&
++                              (scan.erp & IEEE80211_ERP_NON_ERP_PRESENT))) &&
++                              (rssi > ic->ic_protmode_rssi)) {
+                               struct ieee80211vap *tmpvap;
+-                              ic->ic_flags |= IEEE80211_F_USEPROT;
+-                              TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
+-                                      tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++                              if (!(ic->ic_flags & IEEE80211_F_USEPROT)) {
++                                      ic->ic_flags |= IEEE80211_F_USEPROT;
++                                      TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
++                                              tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++                                      }
+                               }
++                              ic->ic_protmode_lasttrig = jiffies;
+                       }
+               }
+Index: madwifi-trunk-r3776/net80211/ieee80211_ioctl.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_ioctl.h        2008-07-17 02:25:53.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_ioctl.h     2008-07-17 02:56:52.000000000 +0200
+@@ -652,6 +652,8 @@
+       IEEE80211_PARAM_LEAKTXBUFS              = 82,   /* Leak tx buffers */
+       IEEE80211_PARAM_MAXRATE                 = 83,   /* Maximum rate (by table index) */
+       IEEE80211_PARAM_MINRATE                 = 84,   /* Minimum rate (by table index) */
++      IEEE80211_PARAM_PROTMODE_RSSI           = 85,   /* RSSI Threshold for enabling protection mode */
++      IEEE80211_PARAM_PROTMODE_TIMEOUT        = 86,   /* Timeout for expiring protection mode */
+ };
+ #define       SIOCG80211STATS                 (SIOCDEVPRIVATE+2)
+Index: madwifi-trunk-r3776/net80211/ieee80211_var.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_var.h  2008-07-17 02:23:00.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_var.h       2008-07-17 02:56:18.000000000 +0200
+@@ -138,6 +138,9 @@
+ #define       IEEE80211_APPIE_MAX     1024
++#define IEEE80211_PROTMODE_RSSITHR    15      /* default rssi threshold for protection mode trigger */
++#define IEEE80211_PROTMODE_TIMEOUT    30      /* timeout for keeping protection mode alive */
++
+ #define IEEE80211_PWRCONSTRAINT_VAL(ic) \
+       (((ic)->ic_bsschan->ic_maxregpower > (ic)->ic_curchanmaxpwr) ? \
+           (ic)->ic_bsschan->ic_maxregpower - (ic)->ic_curchanmaxpwr : 0)
+@@ -335,6 +338,9 @@
+       u_int16_t ic_newtxpowlimit;             /* tx power limit to change to (in 0.5 dBm) */
+       u_int16_t ic_uapsdmaxtriggers;          /* max triggers that could arrive */
+       u_int8_t ic_coverageclass;              /* coverage class */
++      u_int8_t ic_protmode_rssi;                      /* rssi threshold for protection mode */
++      u_int64_t ic_protmode_lasttrig;         /* last trigger for protection mode */
++      u_int16_t ic_protmode_timeout;          /* protection mode timeout */
+       /* Channel state:
+        *
+Index: madwifi-trunk-r3776/net80211/ieee80211_wireless.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_wireless.c     2008-07-17 02:26:17.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_wireless.c  2008-07-17 02:56:18.000000000 +0200
+@@ -2336,6 +2336,12 @@
+       case IEEE80211_PARAM_RSSI_EWMA:
+               ic->ic_rssi_ewma = value;
+               break;
++      case IEEE80211_PARAM_PROTMODE_TIMEOUT:
++              ic->ic_protmode_timeout = value;
++              break;
++      case IEEE80211_PARAM_PROTMODE_RSSI:
++              ic->ic_protmode_rssi = value;
++              break;
+       case IEEE80211_PARAM_MCASTCIPHER:
+               if ((vap->iv_caps & cipher2cap(value)) == 0 &&
+                   !ieee80211_crypto_available(vap, value))
+@@ -2992,6 +2998,12 @@
+       case IEEE80211_PARAM_RSSI_EWMA:
+               param[0] = ic->ic_rssi_ewma;
+               break;
++      case IEEE80211_PARAM_PROTMODE_TIMEOUT:
++              param[0] = ic->ic_protmode_timeout;
++              break;
++      case IEEE80211_PARAM_PROTMODE_RSSI:
++              param[0] = ic->ic_protmode_rssi;
++              break;
+       case IEEE80211_PARAM_MCASTCIPHER:
+               param[0] = rsn->rsn_mcastcipher;
+               break;
+@@ -5384,6 +5396,14 @@
+         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "protmode" },
+       { IEEE80211_PARAM_PROTMODE,
+         0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_protmode" },
++      { IEEE80211_PARAM_PROTMODE_RSSI,
++        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "protrssi" },
++      { IEEE80211_PARAM_PROTMODE_RSSI,
++        0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_protrssi" },
++      { IEEE80211_PARAM_PROTMODE_TIMEOUT,
++        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "prottime" },
++      { IEEE80211_PARAM_PROTMODE_TIMEOUT,
++        0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_prottime" },
+       { IEEE80211_PARAM_MCASTCIPHER,
+         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "mcastcipher" },
+       { IEEE80211_PARAM_MCASTCIPHER,
+Index: madwifi-trunk-r3776/net80211/ieee80211_node.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_node.c 2008-07-17 02:20:51.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_node.c      2008-07-17 02:56:18.000000000 +0200
+@@ -1591,6 +1591,17 @@
+       ieee80211_scan_timeout(ic);
+       ieee80211_timeout_stations(&ic->ic_sta);
++      if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
++              (ic->ic_protmode_lasttrig + ic->ic_protmode_timeout * HZ <
++                      jiffies)) {
++              struct ieee80211vap *tmpvap;
++
++              /* expire protection mode */
++              ic->ic_flags &= ~IEEE80211_F_USEPROT;
++              TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
++                      tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++              }
++      }
+       mod_timer(&ic->ic_inact, jiffies + IEEE80211_INACT_WAIT * HZ);
+ }
diff --git a/package/madwifi/patches-r3776/312-ack_cts_rate.patch b/package/madwifi/patches-r3776/312-ack_cts_rate.patch
new file mode 100644 (file)
index 0000000..3f172ca
--- /dev/null
@@ -0,0 +1,46 @@
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 02:37:41.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 03:04:02.000000000 +0200
+@@ -10889,8 +10889,13 @@
+                               break;
+ #endif
+                       case ATH_ACKRATE:
+-                              sc->sc_ackrate = val;
+-                              ath_set_ack_bitrate(sc, sc->sc_ackrate);
++                              if (val == -1)
++                                      sc->sc_ackrate_override = 0;
++                              else {
++                                      sc->sc_ackrate_override = 1;
++                                      sc->sc_ackrate = val;
++                                      ath_set_ack_bitrate(sc, sc->sc_ackrate);
++                              }
+                               break;
+                       case ATH_RP:
+                               ath_rp_record(sc,
+Index: madwifi-trunk-r3776/ath/if_athvar.h
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_athvar.h   2008-07-17 02:37:41.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_athvar.h        2008-07-17 03:04:02.000000000 +0200
+@@ -698,6 +698,7 @@
+       unsigned int    sc_hasclrkey:1;         /* CLR key supported */
+       unsigned int    sc_stagbeacons:1;       /* use staggered beacons */
+       unsigned int    sc_dfswait:1;           /* waiting on channel for radar detect */
++      unsigned int    sc_ackrate_override:1;  /* override ack rate */
+       unsigned int    sc_ackrate:1;           /* send acks at high bitrate */
+       unsigned int    sc_dfs_cac:1;           /* waiting on channel for radar detect */
+       unsigned int    sc_hasintmit:1;         /* Interference mitigation */
+Index: madwifi-trunk-r3776/ath/if_ath_hal_extensions.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath_hal_extensions.c       2008-07-17 00:21:39.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath_hal_extensions.c    2008-07-17 03:04:48.000000000 +0200
+@@ -129,6 +129,9 @@
+ int
+ ath_set_ack_bitrate(struct ath_softc *sc, int high)
+ {
++      if (!sc->sc_ackrate_override)
++              return 0;
++
+       if (ar_device(sc->devid) == 5212 || ar_device(sc->devid) == 5213) {
+               /* set ack to be sent at low bit-rate */
+               u_int32_t v = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
diff --git a/package/madwifi/patches-r3776/313-reset_channelchange.patch b/package/madwifi/patches-r3776/313-reset_channelchange.patch
new file mode 100644 (file)
index 0000000..20a9c26
--- /dev/null
@@ -0,0 +1,20 @@
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 03:04:02.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 03:06:03.000000000 +0200
+@@ -8865,14 +8865,7 @@
+                       hchan.channel,
+                       jiffies);
+-              /* ath_hal_reset with chanchange = AH_TRUE doesn't seem to
+-               * completely reset the state of the card.  According to
+-               * reports from ticket #1106, kismet and aircrack people they
+-               * needed to do the reset with chanchange = AH_FALSE in order
+-               * to receive traffic when peforming high velocity channel
+-               * changes. */
+-              if (!ath_hw_reset(sc, sc->sc_opmode, &hchan, AH_TRUE, &status)   ||
+-                  !ath_hw_reset(sc, sc->sc_opmode, &hchan, AH_FALSE, &status)) {
++              if (!ath_hw_reset(sc, sc->sc_opmode, &hchan, AH_TRUE, &status)) {
+                       EPRINTF(sc, "Unable to reset channel %u (%u MHz) "
+                               "flags 0x%x '%s' (HAL status %u)\n",
+                               ieee80211_chan2ieee(ic, chan), chan->ic_freq,
diff --git a/package/madwifi/patches-r3776/314-wisoc_softled.patch b/package/madwifi/patches-r3776/314-wisoc_softled.patch
new file mode 100644 (file)
index 0000000..ca5ffdc
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/ath/if_ath_ahb.c
++++ b/ath/if_ath_ahb.c
+@@ -245,6 +245,8 @@
+       num_activesc++;
+       /* Ready to process interrupts */
++      sc->aps_sc.sc_softled = 1; /* SoftLED over GPIO */
++      sc->aps_sc.sc_ledpin = config->board->sysLedGpio;
+       sc->aps_sc.sc_invalid = 0;
+       return 0;
diff --git a/package/madwifi/patches-r3776/315-scanlist.patch b/package/madwifi/patches-r3776/315-scanlist.patch
new file mode 100644 (file)
index 0000000..470a9bc
--- /dev/null
@@ -0,0 +1,892 @@
+Index: madwifi-trunk-r3776/net80211/ieee80211_scan_sta.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_scan_sta.c     2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_scan_sta.c  2008-07-17 03:10:02.000000000 +0200
+@@ -318,147 +318,6 @@
+ #undef ISPROBE
+ }
+-static struct ieee80211_channel *
+-find11gchannel(struct ieee80211com *ic, int i, int freq)
+-{
+-      struct ieee80211_channel *c;
+-      int j;
+-
+-      /*
+-       * The normal ordering in the channel list is b channel
+-       * immediately followed by g so optimize the search for
+-       * this.  We'll still do a full search just in case.
+-       */
+-      for (j = i+1; j < ic->ic_nchans; j++) {
+-              c = &ic->ic_channels[j];
+-              if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
+-                      return c;
+-      }
+-      for (j = 0; j < i; j++) {
+-              c = &ic->ic_channels[j];
+-              if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
+-                      return c;
+-      }
+-      return NULL;
+-}
+-static const u_int chanflags[] = {
+-      IEEE80211_CHAN_B,       /* IEEE80211_MODE_AUTO */
+-      IEEE80211_CHAN_A,       /* IEEE80211_MODE_11A */
+-      IEEE80211_CHAN_B,       /* IEEE80211_MODE_11B */
+-      IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_11G */
+-      IEEE80211_CHAN_FHSS,    /* IEEE80211_MODE_FH */
+-      IEEE80211_CHAN_A,       /* IEEE80211_MODE_TURBO_A */ /* for turbo mode look for AP in normal channel */
+-      IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_TURBO_G */
+-      IEEE80211_CHAN_ST,      /* IEEE80211_MODE_TURBO_STATIC_A */
+-};
+-
+-static void
+-add_channels(struct ieee80211com *ic,
+-      struct ieee80211_scan_state *ss,
+-      enum ieee80211_phymode mode, const u_int16_t freq[], int nfreq)
+-{
+-      struct ieee80211_channel *c, *cg;
+-      u_int modeflags;
+-      int i;
+-
+-      KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode));
+-      modeflags = chanflags[mode];
+-      for (i = 0; i < nfreq; i++) {
+-              c = ieee80211_find_channel(ic, freq[i], modeflags);
+-              if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee))
+-                      continue;
+-              if (mode == IEEE80211_MODE_AUTO) {
+-                      /*
+-                       * XXX special-case 11b/g channels so we select
+-                       *     the g channel if both are present.
+-                       */
+-                      if (IEEE80211_IS_CHAN_B(c) &&
+-                          (cg = find11gchannel(ic, i, c->ic_freq)) != NULL)
+-                              c = cg;
+-              }
+-              if (ss->ss_last >= IEEE80211_SCAN_MAX)
+-                      break;
+-              ss->ss_chans[ss->ss_last++] = c;
+-      }
+-}
+-
+-static const u_int16_t rcl1[] =               /* 8 FCC channel: 52, 56, 60, 64, 36, 40, 44, 48 */
+-{ 5260, 5280, 5300, 5320, 5180, 5200, 5220, 5240 };
+-static const u_int16_t rcl2[] =               /* 4 MKK channels: 34, 38, 42, 46 */
+-{ 5170, 5190, 5210, 5230 };
+-static const u_int16_t rcl3[] =               /* 2.4Ghz ch: 1,6,11,7,13 */
+-{ 2412, 2437, 2462, 2442, 2472 };
+-static const u_int16_t rcl4[] =               /* 5 FCC channel: 149, 153, 161, 165 */
+-{ 5745, 5765, 5785, 5805, 5825 };
+-static const u_int16_t rcl7[] =               /* 11 ETSI channel: 100,104,108,112,116,120,124,128,132,136,140 */
+-{ 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700 };
+-static const u_int16_t rcl8[] =               /* 2.4Ghz ch: 2,3,4,5,8,9,10,12 */
+-{ 2417, 2422, 2427, 2432, 2447, 2452, 2457, 2467 };
+-static const u_int16_t rcl9[] =               /* 2.4Ghz ch: 14 */
+-{ 2484 };
+-static const u_int16_t rcl10[] =      /* Added Korean channels 2312-2372 */
+-{ 2312, 2317, 2322, 2327, 2332, 2337, 2342, 2347, 2352, 2357, 2362, 2367, 2372 };
+-static const u_int16_t rcl11[] =      /* Added Japan channels in 4.9/5.0 spectrum */
+-{ 5040, 5060, 5080, 4920, 4940, 4960, 4980 };
+-#ifdef ATH_TURBO_SCAN
+-static const u_int16_t rcl5[] =               /* 3 static turbo channels */
+-{ 5210, 5250, 5290 };
+-static const u_int16_t rcl6[] =               /* 2 static turbo channels */
+-{ 5760, 5800 };
+-static const u_int16_t rcl6x[] =              /* 4 FCC3 turbo channels */
+-{ 5540, 5580, 5620, 5660 };
+-static const u_int16_t rcl12[] =              /* 2.4Ghz Turbo channel 6 */
+-{ 2437 };
+-static const u_int16_t rcl13[] =              /* dynamic Turbo channels */
+-{ 5200, 5240, 5280, 5765, 5805 };
+-#endif /* ATH_TURBO_SCAN */
+-
+-struct scanlist {
+-      u_int16_t       mode;
+-      u_int16_t       count;
+-      const u_int16_t *list;
+-};
+-
+-#define       IEEE80211_MODE_TURBO_STATIC_A   IEEE80211_MODE_MAX
+-#define       X(a)    .count = sizeof(a)/sizeof(a[0]), .list = a
+-
+-static const struct scanlist staScanTable[] = {
+-      { IEEE80211_MODE_11B,                   X(rcl3) },
+-      { IEEE80211_MODE_11A,                   X(rcl1) },
+-      { IEEE80211_MODE_11A,                   X(rcl2) },
+-      { IEEE80211_MODE_11B,                   X(rcl8) },
+-      { IEEE80211_MODE_11B,                   X(rcl9) },
+-      { IEEE80211_MODE_11A,                   X(rcl4) },
+-#ifdef ATH_TURBO_SCAN
+-      { IEEE80211_MODE_TURBO_STATIC_A,        X(rcl5) },
+-      { IEEE80211_MODE_TURBO_STATIC_A,        X(rcl6) },
+-      { IEEE80211_MODE_TURBO_A,               X(rcl6x) },
+-      { IEEE80211_MODE_TURBO_A,               X(rcl13) },
+-#endif /* ATH_TURBO_SCAN */
+-      { IEEE80211_MODE_11A,                   X(rcl7) },
+-      { IEEE80211_MODE_11B,                   X(rcl10) },
+-      { IEEE80211_MODE_11A,                   X(rcl11) },
+-#ifdef ATH_TURBO_SCAN
+-      { IEEE80211_MODE_TURBO_G,               X(rcl12) },
+-#endif /* ATH_TURBO_SCAN */
+-      { .list = NULL }
+-};
+-
+-#undef X
+-
+-static int
+-checktable(const struct scanlist *scan, const struct ieee80211_channel *c)
+-{
+-      int i;
+-
+-      for (; scan->list != NULL; scan++) {
+-              for (i = 0; i < scan->count; i++)
+-                      if (scan->list[i] == c->ic_freq)
+-                              return 1;
+-      }
+-      return 0;
+-}
+-
+ /*
+  * Start a station-mode scan by populating the channel list.
+  */
+@@ -467,81 +326,11 @@
+ {
+       struct ieee80211com *ic = vap->iv_ic;
+       struct sta_table *st = ss->ss_priv;
+-      const struct scanlist *scan;
+-      enum ieee80211_phymode mode;
+-      struct ieee80211_channel *c;
+-      int i;
+       ss->ss_last = 0;
+-      /*
+-       * Use the table of ordered channels to construct the list
+-       * of channels for scanning.  Any channels in the ordered
+-       * list not in the master list will be discarded.
+-       */
+-      for (scan = staScanTable; scan->list != NULL; scan++) {
+-              mode = scan->mode;
+-              if (vap->iv_des_mode != IEEE80211_MODE_AUTO) {
+-                      /*
+-                       * If a desired mode was specified, scan only 
+-                       * channels that satisfy that constraint.
+-                       */
+-                      if (vap->iv_des_mode != mode) {
+-                              /*
+-                               * The scan table marks 2.4Ghz channels as b
+-                               * so if the desired mode is 11g, then use
+-                               * the 11b channel list but upgrade the mode.
+-                               */
+-                              if (vap->iv_des_mode != IEEE80211_MODE_11G ||
+-                                  mode != IEEE80211_MODE_11B)
+-                                      continue;
+-                              mode = IEEE80211_MODE_11G;      /* upgrade */
+-                      }
+-              } else {
+-                      /*
+-                       * This lets ieee80211_scan_add_channels
+-                       * upgrade an 11b channel to 11g if available.
+-                       */
+-                      if (mode == IEEE80211_MODE_11B)
+-                              mode = IEEE80211_MODE_AUTO;
+-              }
+-              /* XR does not operate on turbo channels */
+-              if ((vap->iv_flags & IEEE80211_F_XR) &&
+-                  (mode == IEEE80211_MODE_TURBO_A ||
+-                   mode == IEEE80211_MODE_TURBO_G))
+-                      continue;
+-              /*
+-               * Add the list of the channels; any that are not
+-               * in the master channel list will be discarded.
+-               */
+-              add_channels(ic, ss, mode, scan->list, scan->count);
+-      }
+-
+-      /*
+-       * Add the channels from the ic (from HAL) that are not present
+-       * in the staScanTable.
+-       */
+-      for (i = 0; i < ic->ic_nchans; i++) {
+-              c = &ic->ic_channels[i];
+-              /*
+-               * scan dynamic turbo channels in normal mode.
+-               */
+-              if (IEEE80211_IS_CHAN_DTURBO(c))
+-                      continue;
+-              mode = ieee80211_chan2mode(c);
+-              if (vap->iv_des_mode != IEEE80211_MODE_AUTO) {
+-                      /*
+-                       * If a desired mode was specified, scan only 
+-                       * channels that satisfy that constraint.
+-                       */
+-                      if (vap->iv_des_mode != mode)
+-                              continue;
+-
+-              }
+-              if (!checktable(staScanTable, c))
+-                      ss->ss_chans[ss->ss_last++] = c;
+-      }
+-
++      ieee80211_scan_add_channels(ic, ss, vap->iv_des_mode);
+       ss->ss_next = 0;
++
+       /* XXX tunables */
+       /* 
+        * The scanner will stay on station for ss_maxdwell ms (using a 
+@@ -750,17 +539,7 @@
+       fail = 0;
+       if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, se->se_chan)))
+               fail |= 0x01;
+-      /*
+-       * NB: normally the desired mode is used to construct
+-       * the channel list, but it's possible for the scan
+-       * cache to include entries for stations outside this
+-       * list so we check the desired mode here to weed them
+-       * out.
+-       */
+-      if (vap->iv_des_mode != IEEE80211_MODE_AUTO &&
+-          (se->se_chan->ic_flags & IEEE80211_CHAN_ALLTURBO) !=
+-          chanflags[vap->iv_des_mode])
+-              fail |= 0x01;
++
+       if (vap->iv_opmode == IEEE80211_M_IBSS) {
+               if ((se->se_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
+                       fail |= 0x02;
+@@ -1175,78 +954,6 @@
+       .scan_default           = ieee80211_sta_join,
+ };
+-/*
+- * Start an adhoc-mode scan by populating the channel list.
+- */
+-static int
+-adhoc_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
+-{
+-      struct ieee80211com *ic = vap->iv_ic;
+-      struct sta_table *st = ss->ss_priv;
+-      const struct scanlist *scan;
+-      enum ieee80211_phymode mode;
+-
+-      ss->ss_last = 0;
+-      /*
+-       * Use the table of ordered channels to construct the list
+-       * of channels for scanning.  Any channels in the ordered
+-       * list not in the master list will be discarded.
+-       */
+-      for (scan = staScanTable; scan->list != NULL; scan++) {
+-              mode = scan->mode;
+-              if (vap->iv_des_mode != IEEE80211_MODE_AUTO) {
+-                      /*
+-                       * If a desired mode was specified, scan only 
+-                       * channels that satisfy that constraint.
+-                       */
+-                      if (vap->iv_des_mode != mode) {
+-                              /*
+-                               * The scan table marks 2.4Ghz channels as b
+-                               * so if the desired mode is 11g, then use
+-                               * the 11b channel list but upgrade the mode.
+-                               */
+-                              if (vap->iv_des_mode != IEEE80211_MODE_11G ||
+-                                  mode != IEEE80211_MODE_11B)
+-                                      continue;
+-                              mode = IEEE80211_MODE_11G;      /* upgrade */
+-                      }
+-              } else {
+-                      /*
+-                       * This lets ieee80211_scan_add_channels
+-                       * upgrade an 11b channel to 11g if available.
+-                       */
+-                      if (mode == IEEE80211_MODE_11B)
+-                              mode = IEEE80211_MODE_AUTO;
+-              }
+-              /* XR does not operate on turbo channels */
+-              if ((vap->iv_flags & IEEE80211_F_XR) &&
+-                  (mode == IEEE80211_MODE_TURBO_A ||
+-                   mode == IEEE80211_MODE_TURBO_G))
+-                      continue;
+-              /*
+-               * Add the list of the channels; any that are not
+-               * in the master channel list will be discarded.
+-               */
+-              add_channels(ic, ss, mode, scan->list, scan->count);
+-      }
+-      ss->ss_next = 0;
+-      /* XXX tunables */
+-      ss->ss_mindwell = msecs_to_jiffies(200);        /* 200ms */
+-      ss->ss_maxdwell = msecs_to_jiffies(200);        /* 200ms */
+-
+-#ifdef IEEE80211_DEBUG
+-      if (ieee80211_msg_scan(vap)) {
+-              printk("%s: scan set ", vap->iv_dev->name);
+-              ieee80211_scan_dump_channels(ss);
+-              printk(" dwell min %ld max %ld\n",
+-                      ss->ss_mindwell, ss->ss_maxdwell);
+-      }
+-#endif /* IEEE80211_DEBUG */
+-
+-      st->st_newscan = 1;
+-
+-      return 0;
+-}
+ /*
+  * Select a channel to start an adhoc network on.
+@@ -1412,7 +1119,7 @@
+       .scan_name              = "default",
+       .scan_attach            = sta_attach,
+       .scan_detach            = sta_detach,
+-      .scan_start             = adhoc_start,
++      .scan_start             = sta_start,
+       .scan_restart           = sta_restart,
+       .scan_cancel            = sta_cancel,
+       .scan_end               = adhoc_pick_bss,
+Index: madwifi-trunk-r3776/net80211/ieee80211.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211.c      2008-07-17 02:56:18.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211.c   2008-07-17 03:07:53.000000000 +0200
+@@ -292,6 +292,11 @@
+                       ("channel with bogus ieee number %u", c->ic_ieee));
+               setbit(ic->ic_chan_avail, c->ic_ieee);
++              if (c->ic_scanflags & IEEE80211_NOSCAN_DEFAULT)
++                      c->ic_scanflags |= IEEE80211_NOSCAN_SET;
++              else
++                      c->ic_scanflags &= ~IEEE80211_NOSCAN_SET;
++
+               /* Identify mode capabilities. */
+               if (IEEE80211_IS_CHAN_A(c))
+                       ic->ic_modecaps |= 1 << IEEE80211_MODE_11A;
+Index: madwifi-trunk-r3776/net80211/_ieee80211.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/_ieee80211.h     2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/net80211/_ieee80211.h  2008-07-17 03:07:53.000000000 +0200
+@@ -132,6 +132,11 @@
+       IEEE80211_SCAN_FIRST    = 2,    /* take first suitable candidate */
+ };
++enum ieee80211_scanflags {
++      IEEE80211_NOSCAN_DEFAULT = (1 << 0),
++      IEEE80211_NOSCAN_SET     = (1 << 1),
++};
++
+ /*
+  * Channels are specified by frequency and attributes.
+  */
+@@ -142,6 +147,7 @@
+       int8_t ic_maxregpower;  /* maximum regulatory tx power in dBm */
+       int8_t ic_maxpower;     /* maximum tx power in dBm */
+       int8_t ic_minpower;     /* minimum tx power in dBm */
++      u_int8_t ic_scanflags;
+ };
+ #define       IEEE80211_CHAN_MAX      255
+Index: madwifi-trunk-r3776/net80211/ieee80211_ioctl.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_ioctl.h        2008-07-17 02:56:52.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_ioctl.h     2008-07-17 03:07:53.000000000 +0200
+@@ -556,6 +556,7 @@
+ #define       IEEE80211_IOCTL_WDSADDMAC       (SIOCIWFIRSTPRIV+26)
+ #define       IEEE80211_IOCTL_WDSDELMAC       (SIOCIWFIRSTPRIV+28)
+ #define       IEEE80211_IOCTL_KICKMAC         (SIOCIWFIRSTPRIV+30)
++#define       IEEE80211_IOCTL_SETSCANLIST     (SIOCIWFIRSTPRIV+31)
+ enum {
+       IEEE80211_WMMPARAMS_CWMIN       = 1,
+Index: madwifi-trunk-r3776/net80211/ieee80211_scan_ap.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_scan_ap.c      2008-07-17 02:20:50.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_scan_ap.c   2008-07-17 03:09:25.000000000 +0200
+@@ -200,131 +200,7 @@
+ static int ap_flush(struct ieee80211_scan_state *);
+ static void action_tasklet(IEEE80211_TQUEUE_ARG);
+-static struct ieee80211_channel *find11gchannel(struct ieee80211com *ic, 
+-              int i, int freq);
+-static const u_int chanflags[] = {
+-      IEEE80211_CHAN_B,       /* IEEE80211_MODE_AUTO */
+-      IEEE80211_CHAN_A,       /* IEEE80211_MODE_11A */
+-      IEEE80211_CHAN_B,       /* IEEE80211_MODE_11B */
+-      IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_11G */
+-      IEEE80211_CHAN_FHSS,    /* IEEE80211_MODE_FH */
+-      IEEE80211_CHAN_A,       /* IEEE80211_MODE_TURBO_A */ /* for turbo mode 
+-                                                            * look for AP in 
+-                                                            * normal channel 
+-                                                            */
+-      IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_TURBO_G */
+-      IEEE80211_CHAN_ST,      /* IEEE80211_MODE_TURBO_STATIC_A */
+-};
+-
+-static const u_int16_t rcl1[] =               /* 8 FCC channel: 52, 56, 60, 64, 
+-                                       *                36, 40, 44, 48 */
+-{ 5260, 5280, 5300, 5320, 5180, 5200, 5220, 5240 };
+-static const u_int16_t rcl2[] =               /* 4 MKK channels: 34, 38, 42, 46 */
+-{ 5170, 5190, 5210, 5230 };
+-static const u_int16_t rcl3[] =               /* 2.4Ghz ch: 1,6,11,7,13 */
+-{ 2412, 2437, 2462, 2442, 2472 };
+-static const u_int16_t rcl4[] =               /* 5 FCC channel: 149, 153, 161, 165 */
+-{ 5745, 5765, 5785, 5805, 5825 };
+-static const u_int16_t rcl7[] =               /* 11 ETSI channel: 100, 104, 108, 112,
+-                                       *                  116, 120, 124, 128, 
+-                                       *                  132, 136, 140 */
+-{ 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700 };
+-static const u_int16_t rcl8[] =               /* 2.4Ghz ch: 2,3,4,5,8,9,10,12 */
+-{ 2417, 2422, 2427, 2432, 2447, 2452, 2457, 2467 };
+-static const u_int16_t rcl9[] =               /* 2.4Ghz ch: 14 */
+-{ 2484 };
+-static const u_int16_t rcl10[] =      /* Added Korean channels 2312-2372 */
+-{ 2312, 2317, 2322, 2327, 2332, 2337, 2342, 2347, 2352, 2357, 2362, 2367, 2372 };
+-static const u_int16_t rcl11[] =      /* Added Japan channels in 4.9/5.0 spectrum */
+-{ 5040, 5060, 5080, 4920, 4940, 4960, 4980 };
+-#ifdef ATH_TURBO_SCAN
+-static const u_int16_t rcl5[] =               /* 3 static turbo channels */
+-{ 5210, 5250, 5290 };
+-static const u_int16_t rcl6[] =               /* 2 static turbo channels */
+-{ 5760, 5800 };
+-static const u_int16_t rcl6x[] =              /* 4 FCC3 turbo channels */
+-{ 5540, 5580, 5620, 5660 };
+-static const u_int16_t rcl12[] =              /* 2.4Ghz Turbo channel 6 */
+-{ 2437 };
+-static const u_int16_t rcl13[] =              /* dynamic Turbo channels */
+-{ 5200, 5240, 5280, 5765, 5805 };
+-#endif /* ATH_TURBO_SCAN */
+-
+-struct scanlist {
+-      u_int16_t       mode;
+-      u_int16_t       count;
+-      const u_int16_t *list;
+-};
+-
+-#define       IEEE80211_MODE_TURBO_STATIC_A   IEEE80211_MODE_MAX
+-#define       X(a)    .count = ARRAY_SIZE(a), .list = a
+-
+-static const struct scanlist staScanTable[] = {
+-      { IEEE80211_MODE_11B,                   X(rcl3)  },
+-      { IEEE80211_MODE_11A,                   X(rcl1)  },
+-      { IEEE80211_MODE_11A,                   X(rcl2)  },
+-      { IEEE80211_MODE_11B,                   X(rcl8)  },
+-      { IEEE80211_MODE_11B,                   X(rcl9)  },
+-      { IEEE80211_MODE_11A,                   X(rcl4)  },
+-#ifdef ATH_TURBO_SCAN
+-      { IEEE80211_MODE_TURBO_STATIC_A,        X(rcl5)  },
+-      { IEEE80211_MODE_TURBO_STATIC_A,        X(rcl6)  },
+-      { IEEE80211_MODE_TURBO_A,               X(rcl6x) },
+-      { IEEE80211_MODE_TURBO_A,               X(rcl13) },
+-#endif /* ATH_TURBO_SCAN */
+-      { IEEE80211_MODE_11A,                   X(rcl7)  },
+-      { IEEE80211_MODE_11B,                   X(rcl10) },
+-      { IEEE80211_MODE_11A,                   X(rcl11) },
+-#ifdef ATH_TURBO_SCAN
+-      { IEEE80211_MODE_TURBO_G,               X(rcl12) },
+-#endif /* ATH_TURBO_SCAN */
+-      { .list = NULL }
+-};
+-
+-#undef X
+-/* This function must be invoked with locks acquired */
+-static void
+-add_channels(struct ieee80211com *ic,
+-      struct ieee80211_scan_state *ss,
+-      enum ieee80211_phymode mode, const u_int16_t freq[], int nfreq)
+-{
+-      struct ieee80211_channel *c, *cg;
+-      u_int modeflags;
+-      int i;
+-
+-      KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode));
+-      modeflags = chanflags[mode];
+-      for (i = 0; i < nfreq; i++) {
+-              c = ieee80211_find_channel(ic, freq[i], modeflags);
+-              if ((c == NULL) || isclr(ic->ic_chan_active, c->ic_ieee))
+-                      continue;
+-              if (mode == IEEE80211_MODE_AUTO) {
+-                      /* XXX special-case 11b/g channels so we select
+-                       *     the g channel if both are present. */
+-                      if (IEEE80211_IS_CHAN_B(c) &&
+-                          (cg = find11gchannel(ic, i, c->ic_freq)) != NULL)
+-                              c = cg;
+-              }
+-              if (ss->ss_last >= IEEE80211_SCAN_MAX)
+-                      break;
+-              ss->ss_chans[ss->ss_last++] = c;
+-      }
+-}
+-
+-/* This function must be invoked with locks acquired */
+-static int
+-checktable(const struct scanlist *scan, const struct ieee80211_channel *c)
+-{
+-      int i;
+-
+-      for (; scan->list != NULL; scan++) {
+-              for (i = 0; i < scan->count; i++)
+-                      if (scan->list[i] == c->ic_freq)
+-                              return 1;
+-      }
+-      return 0;
+-}
+ /*
+  * Attach prior to any scanning work.
+@@ -398,29 +274,6 @@
+               ieee80211_saveie(iep, ie);
+ }
+-/* This function must be invoked with locks acquired */
+-static struct ieee80211_channel *
+-find11gchannel(struct ieee80211com *ic, int i, int freq)
+-{
+-      struct ieee80211_channel *c;
+-      int j;
+-
+-      /* The normal ordering in the channel list is b channel
+-       * immediately followed by g so optimize the search for
+-       * this.  We'll still do a full search just in case. */
+-      for (j = i + 1; j < ic->ic_nchans; j++) {
+-              c = &ic->ic_channels[j];
+-              if ((c->ic_freq == freq) && IEEE80211_IS_CHAN_ANYG(c))
+-                      return c;
+-      }
+-      for (j = 0; j < i; j++) {
+-              c = &ic->ic_channels[j];
+-              if ((c->ic_freq == freq) && IEEE80211_IS_CHAN_ANYG(c))
+-                      return c;
+-      }
+-      return NULL;
+-}
+-
+ /*
+  * Start an ap scan by populating the channel list.
+  */
+@@ -429,90 +282,14 @@
+ {
+       struct ap_state *as         = ss->ss_priv;
+       struct ieee80211com *ic     = NULL;
+-      const struct scanlist *sl   = NULL;
+-      struct ieee80211_channel *c = NULL;
+-      int i;
+-      unsigned int mode = 0;
+       SCAN_AP_LOCK_IRQ(as);
+       ic = vap->iv_ic;
+       /* 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;
+-      if (as->as_vap_desired_mode != IEEE80211_MODE_AUTO) {
+-              as->as_required_mode = chanflags[as->as_vap_desired_mode];
+-              if ((vap->iv_ath_cap & IEEE80211_ATHC_TURBOP) && 
+-                  (as->as_required_mode != IEEE80211_CHAN_ST)) {
+-                      /* Fixup for dynamic turbo flags */
+-                      if (as->as_vap_desired_mode == IEEE80211_MODE_11G)
+-                              as->as_required_mode = IEEE80211_CHAN_108G;
+-                      else
+-                              as->as_required_mode = IEEE80211_CHAN_108A;
+-              }
+-      }
+-
+-      ss->ss_last = 0;
+-      /* Use the table of ordered channels to construct the list
+-       * of channels for scanning.  Any channels in the ordered
+-       * list not in the master list will be discarded. */
+-      for (sl = staScanTable; sl->list != NULL; sl++) {
+-              mode = sl->mode;
+-
+-              /* The scan table marks 2.4Ghz channels as b
+-               * so if the desired mode is 11g, then use
+-               * the 11b channel list but upgrade the mode. */
+-              if (as->as_vap_desired_mode &&
+-                  (as->as_vap_desired_mode != mode) && 
+-                  (as->as_vap_desired_mode == IEEE80211_MODE_11G) && 
+-                  (mode == IEEE80211_MODE_11B))
+-                      mode = IEEE80211_MODE_11G;
+-
+-              /* If we are in "AUTO" mode, upgrade the mode to auto. 
+-               * This lets add_channels upgrade an 11b channel to 
+-               * 11g if available. */
+-              if (!as->as_vap_desired_mode && (mode == IEEE80211_MODE_11B))
+-                      mode = IEEE80211_MODE_AUTO;
+-
+-              /* Add the list of the channels; any that are not
+-               * in the master channel list will be discarded. */
+-              add_channels(ic, ss, mode, sl->list, sl->count);
+-      }
+-
+-      /* Add the channels from the ic (from HAL) that are not present
+-       * in the staScanTable, assuming they pass the sanity checks... */
+-      for (i = 0; i < ic->ic_nchans; i++) {
+-              c = &ic->ic_channels[i];
+-
+-              /* XR is not supported on turbo channels */
+-              if (IEEE80211_IS_CHAN_TURBO(c) && vap->iv_flags & IEEE80211_F_XR)
+-                      continue;
++      ieee80211_scan_add_channels(ic, ss, vap->iv_des_mode);
+-              /* Dynamic channels are scanned in base mode */
+-              if (!as->as_required_mode && !IEEE80211_IS_CHAN_ST(c))
+-                      continue;
+-
+-              /* Use any 11g channel instead of 11b one. */
+-              if (vap->iv_des_mode == IEEE80211_MODE_AUTO && 
+-                  IEEE80211_IS_CHAN_B(c) &&
+-                  find11gchannel(ic, i, c->ic_freq))
+-                      continue;
+-
+-              /* Do not add channels already put into the scan list by the
+-               * scan table - these have already been filtered by mode
+-               * and for whether they are in the active channel list. */
+-              if (checktable(staScanTable, c))
+-                      continue;
+-
+-              /* Make sure the channel is active */
+-              if ((c == NULL) || isclr(ic->ic_chan_active, c->ic_ieee))
+-                      continue;
+-
+-              /* Don't overrun */
+-              if (ss->ss_last >= IEEE80211_SCAN_MAX)
+-                      break;
+-
+-              ss->ss_chans[ss->ss_last++] = c;
+-      }
+       ss->ss_next = 0;
+       /* XXX tunables */
+       ss->ss_mindwell = msecs_to_jiffies(200);        /* 200ms */
+@@ -834,13 +611,6 @@
+               if (IEEE80211_IS_CHAN_RADAR(c->chan))
+                       continue;
+-              /* Do not select 802.11a ST if mode is specified and is not 
+-               * 802.11a ST */
+-              if (as->as_required_mode &&
+-                  IEEE80211_IS_CHAN_STURBO(c->chan) &&
+-                  (as->as_vap_desired_mode != IEEE80211_MODE_TURBO_STATIC_A))
+-                      continue;
+-
+               /* Verify mode matches any fixed mode specified */
+               if ((c->chan->ic_flags & as->as_required_mode) != 
+                               as->as_required_mode)
+Index: madwifi-trunk-r3776/net80211/ieee80211_scan.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_scan.c 2008-07-17 00:49:51.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_scan.c      2008-07-17 03:07:53.000000000 +0200
+@@ -969,6 +969,80 @@
+       }
+ }
++static const u_int chanflags[] = {
++      0,      /* IEEE80211_MODE_AUTO */
++      IEEE80211_CHAN_A,       /* IEEE80211_MODE_11A */
++      IEEE80211_CHAN_B,       /* IEEE80211_MODE_11B */
++      IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_11G */
++      IEEE80211_CHAN_FHSS,    /* IEEE80211_MODE_FH */
++      IEEE80211_CHAN_A,       /* IEEE80211_MODE_TURBO_A */ /* for turbo mode look for AP in normal channel */
++      IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_TURBO_G */
++      IEEE80211_CHAN_ST,      /* IEEE80211_MODE_TURBO_STATIC_A */
++};
++
++static struct ieee80211_channel *
++find11gchannel(struct ieee80211com *ic, int i, int freq)
++{
++      struct ieee80211_channel *c;
++      int j;
++
++      /*
++       * The normal ordering in the channel list is b channel
++       * immediately followed by g so optimize the search for
++       * this.  We'll still do a full search just in case.
++       */
++      for (j = i+1; j < ic->ic_nchans; j++) {
++              c = &ic->ic_channels[j];
++              if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
++                      return c;
++      }
++      for (j = 0; j < i; j++) {
++              c = &ic->ic_channels[j];
++              if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
++                      return c;
++      }
++      return NULL;
++}
++
++
++void
++ieee80211_scan_add_channels(struct ieee80211com *ic,
++      struct ieee80211_scan_state *ss,
++      enum ieee80211_phymode mode)
++{
++      struct ieee80211_channel *c, *cg;
++      u_int modeflags;
++      int i;
++
++      KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode));
++      modeflags = chanflags[mode];
++      for (i = 0; i < ic->ic_nchans; i++) {
++              c = &ic->ic_channels[i];
++              if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee))
++                      continue;
++              if (c->ic_scanflags & IEEE80211_NOSCAN_SET)
++                      continue;
++              if (modeflags &&
++                      ((c->ic_flags & IEEE80211_CHAN_ALLTURBO) !=
++                       (modeflags & IEEE80211_CHAN_ALLTURBO)))
++                      continue;
++              if (mode == IEEE80211_MODE_AUTO) {
++                      /*
++                       * XXX special-case 11b/g channels so we select
++                       *     the g channel if both are present.
++                       */
++                      if (IEEE80211_IS_CHAN_B(c) &&
++                          (cg = find11gchannel(ic, i, c->ic_freq)) != NULL)
++                              continue;
++              }
++              if (ss->ss_last >= IEEE80211_SCAN_MAX)
++                      break;
++              ss->ss_chans[ss->ss_last++] = c;
++      }
++}
++EXPORT_SYMBOL(ieee80211_scan_add_channels);
++
++
+ /*
+  * Execute radar channel change. This is called when a radar/dfs
+  * signal is detected.  AP mode only.  Return 1 on success, 0 on
+Index: madwifi-trunk-r3776/net80211/ieee80211_scan.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_scan.h 2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_scan.h      2008-07-17 03:07:53.000000000 +0200
+@@ -219,4 +219,7 @@
+ void ieee80211_scanner_unregister(enum ieee80211_opmode,
+       const struct ieee80211_scanner *);
+ void ieee80211_scanner_unregister_all(const struct ieee80211_scanner *);
++void ieee80211_scan_add_channels(struct ieee80211com *ic,
++      struct ieee80211_scan_state *ss,
++      enum ieee80211_phymode mode);
+ #endif /* _NET80211_IEEE80211_SCAN_H_ */
+Index: madwifi-trunk-r3776/net80211/ieee80211_wireless.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_wireless.c     2008-07-17 02:56:18.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_wireless.c  2008-07-17 03:08:16.000000000 +0200
+@@ -3911,6 +3911,106 @@
+       return ieee80211_ioctl_setmlme(dev, info, w, (char *)&mlme);
+ }
++static inline void setflag(struct ieee80211_channel *c, int flag)
++{
++      if (flag)
++              c->ic_scanflags |= IEEE80211_NOSCAN_SET;
++      else
++              c->ic_scanflags &= ~IEEE80211_NOSCAN_SET;
++}
++
++static void setscanflag(struct ieee80211com *ic, int min, int max, int set)
++{
++      int i;
++
++      for (i = 0; i < ic->ic_nchans; i++) {
++              struct ieee80211_channel *c = &ic->ic_channels[i];
++
++              if (min == -1) {
++                      if (!(c->ic_scanflags & IEEE80211_NOSCAN_DEFAULT))
++                              setflag(c, set);
++              } else if ((c->ic_freq >= min) && (c->ic_freq <= max)) {
++                      setflag(c, set);
++              }
++      }
++}
++
++static int
++ieee80211_ioctl_setscanlist(struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_point *data, char *extra)
++{
++      struct ieee80211vap *vap = dev->priv;
++      struct ieee80211com *ic = vap->iv_ic;
++      char *s, *next;
++      int val = 1;
++
++      if (data->length <= 0)
++              return -EINVAL;
++
++      s = kmalloc(data->length + 1, GFP_KERNEL);
++      if (!s)
++              return -ENOMEM;
++
++      memset(s, 0, data->length + 1);
++      if (copy_from_user(s, data->pointer, data->length))
++              return -EFAULT;
++
++      s[data->length - 1] = '\0';             /* ensure null termination */
++
++      switch(*s) {
++              case '-':
++                      val = 1;
++                      break;
++              case '+':
++                      val = 0;
++                      break;
++              default:
++                      goto error;
++      }
++      s++;
++      next = s;
++      do {
++              next = strchr(s, ',');
++              if (next) {
++                      *next = 0;
++                      next++;
++              }
++              if (!strcmp(s, "ALL")) {
++                      setscanflag(ic, 0, 10000, val);
++              } else if (!strcmp(s, "REG")) {
++                      setscanflag(ic, -1, -1, val);
++              } else {
++                      int min, max;
++                      char *n, *end = NULL;
++
++                      n = strchr(s, '-');
++                      if (n) {
++                              *n = 0;
++                              n++;
++                      }
++                      min = simple_strtoul(s, &end, 10);
++                      if (end && *end)
++                              goto error;
++                      if (n) {
++                              max = simple_strtoul(n, &end, 10);
++                              if (end && *end)
++                                      goto error;
++                      } else {
++                              max = min;
++                      }
++                      setscanflag(ic, min, max, val);
++              }
++              s = next;
++      } while (next);
++      return 0;
++
++error:
++      if (s)
++              kfree(s);
++      return -EINVAL;
++}
++
+ static int
+ ieee80211_ioctl_addmac(struct net_device *dev, struct iw_request_info *info,
+       void *w, char *extra)
+@@ -5712,6 +5812,8 @@
+        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "minrate"},
+       {IEEE80211_PARAM_MINRATE,
+        0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_minrate"},
++      { IEEE80211_IOCTL_SETSCANLIST,
++       IW_PRIV_TYPE_CHAR | 255, 0, "setscanlist"},
+       
+ #ifdef ATH_REVERSE_ENGINEERING
+       /*
+@@ -5809,6 +5911,7 @@
+       set_priv(IEEE80211_IOCTL_WDSADDMAC, ieee80211_ioctl_wdsmac),
+       set_priv(IEEE80211_IOCTL_WDSDELMAC, ieee80211_ioctl_wdsdelmac),
+       set_priv(IEEE80211_IOCTL_KICKMAC, ieee80211_ioctl_kickmac),
++      set_priv(IEEE80211_IOCTL_SETSCANLIST, ieee80211_ioctl_setscanlist),
+ #ifdef ATH_REVERSE_ENGINEERING
+       set_priv(IEEE80211_IOCTL_READREG, ieee80211_ioctl_readreg),
+       set_priv(IEEE80211_IOCTL_WRITEREG, ieee80211_ioctl_writereg),
diff --git a/package/madwifi/patches-r3776/316-ani_fix.patch b/package/madwifi/patches-r3776/316-ani_fix.patch
new file mode 100644 (file)
index 0000000..d14deac
--- /dev/null
@@ -0,0 +1,740 @@
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 03:06:03.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 03:53:09.000000000 +0200
+@@ -343,6 +343,8 @@
+               unsigned int param, unsigned int value);
+ static u_int32_t ath_get_real_maxtxpower(struct ath_softc *sc);
++static int ath_setintmit(struct ath_softc *sc);
++static u_int32_t ath_calcrxfilter(struct ath_softc *sc);
+ #ifdef AR_DEBUG
+ static int ath_txq_check(struct ath_softc *sc, struct ath_txq *txq, const char *msg);
+@@ -356,7 +358,6 @@
+ static char *ratectl = DEF_RATE_CTL;
+ static int rfkill = 0;
+ static int hal_tpc = 0;
+-static int intmit = 0;
+ static int countrycode = CTRY_DEFAULT;
+ static int maxvaps = ATH_MAXVAPS_DEFAULT;
+ static int outdoor = 0;
+@@ -398,7 +399,6 @@
+ #endif
+ MODULE_PARM(autocreate, "s");
+ MODULE_PARM(ratectl, "s");
+-MODULE_PARM(intmit, "i");
+ #else
+ #include <linux/moduleparam.h>
+ module_param(beacon_cal, int, 0600);
+@@ -412,7 +412,6 @@
+ #endif
+ module_param(autocreate, charp, 0600);
+ module_param(ratectl, charp, 0600);
+-module_param(intmit, int, 0600);
+ #endif
+ MODULE_PARM_DESC(countrycode, "Override default country code.  Default is 0.");
+ MODULE_PARM_DESC(maxvaps, "Maximum VAPs.  Default is 4.");
+@@ -428,7 +427,6 @@
+               "'none' to disable");
+ MODULE_PARM_DESC(ratectl, "Rate control algorithm [amrr|minstrel|onoe|sample], "
+               "defaults to '" DEF_RATE_CTL "'");
+-MODULE_PARM_DESC(intmit, "Enable interference mitigation by default.  Default is 0.");
+ #ifdef AR_DEBUG
+ static int    ath_debug = 0;
+@@ -585,23 +583,13 @@
+       if (ath_hal_hastxpowlimit(ah)) {
+               ic->ic_caps |= IEEE80211_C_TXPMGT;
+       }
+-      /* Interference mitigation/ambient noise immunity (ANI).
+-       * In modes other than HAL_M_STA, it causes receive sensitivity
+-       * problems for OFDM. */
++      /* Interference mitigation/ambient noise immunity (ANI). */
+       sc->sc_hasintmit = ath_hal_hasintmit(ah);
+-      sc->sc_useintmit = (intmit && sc->sc_hasintmit);
+-      if (!sc->sc_hasintmit && intmit) {
+-              WPRINTF(sc, "Interference mitigation was requested, but is not"
+-                              "supported by the HAL/hardware.\n");
+-              intmit = 0; /* Stop use in future ath_attach(). */
+-      }
+-      else {
+-              ath_hal_setintmit(ah, sc->sc_useintmit);
+-              DPRINTF(sc, ATH_DEBUG_ANY, "Interference mitigation is "
+-                      "supported.  Currently %s.\n",
+-                      (sc->sc_useintmit ? "enabled" : "disabled"));
+-      }
++      /* auto, mode dependent */
++      sc->sc_useintmit = -1;
++      sc->sc_noise_immunity = -1;
++      sc->sc_ofdm_weak_det = -1;
+       sc->sc_dmasize_stomp = 0;
+       /*
+@@ -614,15 +602,6 @@
+       sc->sc_mrretry = ath_hal_setupxtxdesc(ah, NULL, 0,0, 0,0, 0,0);
+       /*
+-       * Check if the device has hardware counters for PHY
+-       * errors.  If so we need to enable the MIB interrupt
+-       * so we can act on stat triggers.
+-       */
+-      sc->sc_needmib = ath_hal_hwphycounters(ah) && 
+-              sc->sc_hasintmit && 
+-              sc->sc_useintmit;
+-
+-      /*
+        * Get the hardware key cache size.
+        */
+       sc->sc_keymax = ath_hal_keycachesize(ah);
+@@ -1593,37 +1572,6 @@
+       ath_init(dev);
+ }
+-/* NB: Int. mit. was not implemented so that it could be enabled/disabled,
+- * and actually in 0.9.30.13 HAL it really can't even be disabled because
+- * it will start adjusting registers even when we turn off the capability
+- * in the HAL.
+- *
+- * NB: This helper function basically clobbers all the related registers
+- * if we have disabled int. mit. cap, allowing us to turn it on and off and
+- * work around the bug preventing it from being disabled. */
+-static inline void ath_override_intmit_if_disabled(struct ath_softc *sc) {
+-      /* Restore int. mit. registers if they were turned off. */
+-      if (sc->sc_hasintmit && !sc->sc_useintmit)
+-              ath_hal_restore_default_intmit(sc->sc_ah);
+-      /* Sanity check... remove later. */
+-      if (!sc->sc_useintmit) {
+-              ath_hal_verify_default_intmit(sc->sc_ah);
+-              /* If we don't have int. mit. and we don't have DFS on channel,
+-               * it is safe to filter error packets. */
+-              if (!ath_radar_is_dfs_required(sc, &sc->sc_curchan)) {
+-                      ath_hal_setrxfilter(sc->sc_ah,
+-                              ath_hal_getrxfilter(sc->sc_ah) & 
+-                              ~HAL_RX_FILTER_PHYERR);
+-              }
+-      }
+-      else {
+-              /* Make sure that we have errors in RX filter because ANI needs
+-               * them. */
+-              ath_hal_setrxfilter(sc->sc_ah, 
+-                      ath_hal_getrxfilter(sc->sc_ah) | HAL_RX_FILTER_PHYERR);
+-      }
+-}
+-
+ static HAL_BOOL ath_hw_reset(struct ath_softc *sc, HAL_OPMODE opmode,
+               HAL_CHANNEL *channel, HAL_BOOL bChannelChange,
+               HAL_STATUS *status)
+@@ -1698,11 +1646,7 @@
+               ath_hal_settpc(sc->sc_ah, hal_tpc);
+       }
+ #endif
+-#if 0 /* Setting via HAL does not work, so it is done manually below. */
+-      if (sc->sc_hasintmit)
+-              ath_hal_setintmit(sc->sc_ah, sc->sc_useintmit);
+-#endif
+-      ath_override_intmit_if_disabled(sc);
++      ath_setintmit(sc);
+       if (sc->sc_dmasize_stomp)
+               ath_hal_set_dmasize_pcie(sc->sc_ah);
+       if (sc->sc_softled)
+@@ -2496,7 +2440,6 @@
+                       /* Let the HAL handle the event. */
+                       ath_hal_mibevent(ah, &sc->sc_halstats);
+-                      ath_override_intmit_if_disabled(sc);
+               }
+       }
+       if (needmark)
+@@ -2564,6 +2507,55 @@
+       return flags;
+ }
++static int ath_setintmit(struct ath_softc *sc)
++{
++      struct ath_hal *ah = sc->sc_ah;
++      int ret;
++      int val;
++
++      if (!sc->sc_hasintmit)
++              return 0;
++
++      switch(sc->sc_useintmit) {
++              case 0: /* disabled */
++              case 1: /* enabled */
++                      val = sc->sc_useintmit;
++                      break;
++              default:
++                      if (sc->sc_opmode != IEEE80211_M_MONITOR)
++                              val = 1;
++                      else
++                              val = 0;
++                      break;
++      }
++      ret = ath_hal_setintmit(ah, val);
++      if (val)
++              goto done;
++
++      /* manual settings */
++      if ((sc->sc_noise_immunity >= 0) && (sc->sc_noise_immunity <= 5))
++              ath_hal_setcapability(ah, HAL_CAP_INTMIT, 2, sc->sc_noise_immunity, NULL);
++      if ((sc->sc_ofdm_weak_det == 0) || (sc->sc_ofdm_weak_det == 1))
++              ath_hal_setcapability(ah, HAL_CAP_INTMIT, 3, sc->sc_ofdm_weak_det, NULL);
++
++done:
++      if (!sc->sc_imask)
++              goto out;
++
++      /* MIB interrupt handling */
++      sc->sc_needmib = ath_hal_hwphycounters(ah) &&
++              sc->sc_useintmit;
++      if (sc->sc_needmib)
++              sc->sc_imask |= HAL_INT_MIB;
++      else
++              sc->sc_imask &= ~HAL_INT_MIB;
++      ath_hal_intrset(sc->sc_ah, sc->sc_imask);
++      ath_calcrxfilter(sc);
++
++out:
++      return ret;
++}
++
+ /*
+  * Context: process context
+  */
+@@ -4248,8 +4240,7 @@
+       u_int32_t rfilt;
+       /* Preserve the current Phy. radar and err. filters. */
+-      rfilt = (ath_hal_getrxfilter(ah) &
+-                      (HAL_RX_FILTER_PHYERR | HAL_RX_FILTER_PHYRADAR)) |
++      rfilt = (ath_hal_getrxfilter(ah) & HAL_RX_FILTER_PHYRADAR) |
+                HAL_RX_FILTER_UCAST | HAL_RX_FILTER_BCAST |
+                HAL_RX_FILTER_MCAST;
+       if (ic->ic_opmode != IEEE80211_M_STA)
+@@ -4265,6 +4256,8 @@
+       if (sc->sc_nmonvaps > 0)
+               rfilt |= (HAL_RX_FILTER_CONTROL | HAL_RX_FILTER_BEACON |
+                         HAL_RX_FILTER_PROBEREQ | HAL_RX_FILTER_PROM);
++      if (sc->sc_hasintmit && !sc->sc_needmib && ath_hal_getintmit(ah, NULL))
++              rfilt |= HAL_RX_FILTER_PHYERR;
+       if (sc->sc_curchan.privFlags & CHANNEL_DFS)
+               rfilt |= (HAL_RX_FILTER_PHYERR | HAL_RX_FILTER_PHYRADAR);
+       return rfilt;
+@@ -6809,8 +6802,7 @@
+       dev->quota -= bf_processed;
+ #endif
+-      if (sc->sc_useintmit) 
+-              ath_hal_rxmonitor(ah, &sc->sc_halstats, &sc->sc_curchan);
++      ath_hal_rxmonitor(ah, &sc->sc_halstats, &sc->sc_curchan);
+       if (!bf_processed)
+               DPRINTF(sc, ATH_DEBUG_RX_PROC,
+                       "Warning: %s got scheduled when no receive "
+@@ -8726,7 +8718,6 @@
+       ath_hal_rxena(ah);              /* enable recv descriptors */
+       ath_mode_init(dev);             /* set filters, etc. */
+       ath_hal_startpcurecv(ah);       /* re-enable PCU/DMA engine */
+-      ath_override_intmit_if_disabled(sc);
+       return 0;
+ }
+@@ -10632,8 +10623,10 @@
+       ATH_RP_IGNORED          = 24,
+       ATH_RADAR_IGNORED       = 25,
+       ATH_MAXVAPS             = 26,
+-        ATH_INTMIT            = 27,
+-      ATH_DISTANCE            = 28,
++      ATH_DISTANCE            = 27,
++      ATH_INTMIT                      = 28,
++      ATH_NOISE_IMMUNITY      = 29,
++      ATH_OFDM_WEAK_DET       = 30
+ };
+ static inline int 
+@@ -10695,6 +10688,48 @@
+ }
+ static int
++ath_sysctl_set_intmit(struct ath_softc *sc, long ctl, u_int val)
++{
++      int ret;
++
++      switch(ctl) {
++      case ATH_INTMIT:
++              sc->sc_intmit = val;
++              break;
++      case ATH_NOISE_IMMUNITY:
++              sc->sc_noise_immunity = val;
++              break;
++      case ATH_OFDM_WEAK_DET:
++              sc->sc_ofdm_weak_det = val;
++              break;
++      default:
++              return -EINVAL;
++      }
++      ret = ath_setintmit(sc);
++      return ret;
++}
++
++static int
++ath_sysctl_get_intmit(struct ath_softc *sc, long ctl, u_int *val)
++{
++      struct ath_hal *ah = sc->sc_ah;
++
++      switch(ctl) {
++      case ATH_INTMIT:
++              *val = (ath_hal_getcapability(ah, HAL_CAP_INTMIT, 1, NULL) == HAL_OK);
++              break;
++      case ATH_NOISE_IMMUNITY:
++              return ath_hal_getcapability(ah, HAL_CAP_INTMIT, 2, val);
++      case ATH_OFDM_WEAK_DET:
++              return ath_hal_getcapability(ah, HAL_CAP_INTMIT, 3, val);
++      default:
++              return -EINVAL;
++      }
++      return 0;
++}
++
++
++static int
+ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl, write, filp, buffer, lenp, ppos)
+ {
+       struct ath_softc *sc = ctl->extra1;
+@@ -10933,30 +10968,13 @@
+                               sc->sc_radar_ignored = val;
+                               break;
+                       case ATH_INTMIT:
+-                              if (!sc->sc_hasintmit) {
++                      case ATH_NOISE_IMMUNITY:
++                      case ATH_OFDM_WEAK_DET:
++                              if (!sc->sc_hasintmit)
+                                       ret = -EOPNOTSUPP;
+-                                      break;
+-                              }
+-                              if (sc->sc_useintmit == val)
+-                                      break;
+-                              sc->sc_useintmit = val; 
+-                              sc->sc_needmib = ath_hal_hwphycounters(ah) && 
+-                                      sc->sc_useintmit;
+-                              /* Update the HAL and MIB interrupt mask bits */
+-                              ath_hal_setintmit(ah, !!val); 
+-                              sc->sc_imask = (sc->sc_imask & ~HAL_INT_MIB) | 
+-                                      (sc->sc_needmib ? HAL_INT_MIB : 0);
+-                              ath_hal_intrset(sc->sc_ah, sc->sc_imask);
+-                              /* Only do a reset if device is valid and UP 
+-                               * and we just made a change to the settings. */
+-                              if (sc->sc_dev && !sc->sc_invalid &&
+-                                  (sc->sc_dev->flags & IFF_RUNNING))
+-                                      ath_reset(sc->sc_dev); 
+-                              /* NB: Run this step to cleanup if HAL doesn't 
+-                               * obey capability flags and hangs onto ANI
+-                               * settings. */
+-                              ath_override_intmit_if_disabled(sc);
+-                                break; 
++                              else
++                                      ret = ath_sysctl_set_intmit(sc, (long)ctl->extra2, val);
++                              break;
+                       default:
+                               ret = -EINVAL;
+                               break;
+@@ -11028,9 +11046,14 @@
+               case ATH_RADAR_IGNORED:
+                       val = sc->sc_radar_ignored;
+                       break;
+-                case ATH_INTMIT: 
+-                      val = sc->sc_useintmit; 
+-                      break; 
++              case ATH_INTMIT:
++              case ATH_NOISE_IMMUNITY:
++              case ATH_OFDM_WEAK_DET:
++                      if (!sc->sc_hasintmit)
++                              ret = -EOPNOTSUPP;
++                      else
++                              ret = ath_sysctl_get_intmit(sc, (long)ctl->extra2, &val);
++                      break;
+               default:
+                       ret = -EINVAL;
+                       break;
+@@ -11412,6 +11435,24 @@
+         .maxlen       = sizeof(ath_xchanmode),
+         .proc_handler = proc_dointvec
+       },
++      { .ctl_name     = CTL_AUTO,
++        .procname     = "intmit",
++        .mode         = 0644,
++        .proc_handler = ath_sysctl_halparam,
++        .extra2       = (void *)ATH_INTMIT,
++      },
++      { .ctl_name     = CTL_AUTO,
++        .procname     = "noise_immunity",
++        .mode         = 0644,
++        .proc_handler = ath_sysctl_halparam,
++        .extra2       = (void *)ATH_NOISE_IMMUNITY,
++      },
++      { .ctl_name     = CTL_AUTO,
++        .procname     = "ofdm_weak_det",
++        .mode         = 0644,
++        .proc_handler = ath_sysctl_halparam,
++        .extra2       = (void *)ATH_OFDM_WEAK_DET,
++      },
+       { 0 }
+ };
+ static ctl_table ath_ath_table[] = {
+Index: madwifi-trunk-r3776/ath/if_athvar.h
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_athvar.h   2008-07-17 03:04:02.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_athvar.h        2008-07-17 03:12:36.000000000 +0200
+@@ -712,6 +712,10 @@
+       unsigned int sc_txcont_power; /* Continuous transmit power in 0.5dBm units */
+       unsigned int sc_txcont_rate;  /* Continuous transmit rate in Mbps */
++      int8_t sc_intmit; /* Interference mitigation enabled, -1 = auto, based on mode, 0/1 = off/on */
++      int8_t sc_noise_immunity; /* Noise immunity level, 0-4, -1 == auto) */
++      int8_t sc_ofdm_weak_det; /* OFDM weak frames detection, -1 == auto */
++
+       /* rate tables */
+       const HAL_RATE_TABLE *sc_rates[IEEE80211_MODE_MAX];
+       const HAL_RATE_TABLE *sc_currates;      /* current rate table */
+Index: madwifi-trunk-r3776/ath/if_ath_hal_extensions.h
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath_hal_extensions.h       2008-07-17 00:21:39.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath_hal_extensions.h    2008-07-17 03:50:03.000000000 +0200
+@@ -237,296 +237,18 @@
+       AR5K_DMASIZE_512B
+ };
+-
+-int ath_set_ack_bitrate(struct ath_softc *sc, int);
+-int ar_device(int devid);
+-const char * ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val);
+-
+-static inline unsigned long field_width(unsigned long mask, unsigned long shift)
+-{
+-      unsigned long r = 0;
+-      unsigned long x = mask >> shift;
+-      if ( 0 == mask )  return  0;
+-#if  BITS_PER_LONG >= 64
+-      if ( x & (~0UL<<32) )  { x >>= 32;  r += 32; }
+-#endif
+-      if ( x & 0xffff0000 )  { x >>= 16;  r += 16; }
+-      if ( x & 0x0000ff00 )  { x >>=  8;  r +=  8; }
+-      if ( x & 0x000000f0 )  { x >>=  4;  r +=  4; }
+-      if ( x & 0x0000000c )  { x >>=  2;  r +=  2; }
+-      if ( x & 0x00000002 )  {            r +=  1; }
+-      return r+1;
+-}
+-
+-static inline u_int32_t get_field(struct ath_hal *ah, u_int32_t reg, u_int32_t mask, u_int32_t shift, int is_signed) {
+-      unsigned long x = ((OS_REG_READ(ah, reg) & mask) >> shift);
+-      if (is_signed) {
+-              unsigned long c =(-1) << (field_width(mask, shift)-1);
+-              return (x + c) ^ c;
+-      }
+-      return x;
+-}
+-
+ static inline void set_field(struct ath_hal *ah, u_int32_t reg, u_int32_t mask, u_int32_t shift, u_int32_t value) {
+       OS_REG_WRITE(ah, reg, 
+                         (OS_REG_READ(ah, reg) & ~mask) | 
+                         ((value << shift) & mask));
+ }
+-static inline u_int32_t field_eq(struct ath_hal *ah, u_int32_t reg, 
+-                               u_int32_t mask, u_int32_t shift, 
+-                               u_int32_t value, int is_signed) {
+-      return  (get_field(ah, reg, mask, shift, is_signed) & (mask >> shift)) == 
+-              (value & (mask >> shift));
+-}
+-
+-static inline void override_warning(struct ath_hal *ah, const char *name,
+-                                  u_int32_t reg, u_int32_t mask,
+-                                  u_int32_t shift, u_int32_t expected, int is_signed) {
+-
+-      if (!field_eq(ah, reg, mask, shift, expected, is_signed)) 
+-              printk("%s: Correcting 0x%04x[%s] from 0x%x (%d) to 0x%x (%d).\n", 
+-                     SC_DEV_NAME(ah->ah_sc),
+-                     reg,
+-                     name, 
+-                     (get_field(ah, reg, mask, shift, is_signed) & (mask >> shift)),
+-                     get_field(ah, reg, mask, shift, is_signed), 
+-                     (expected & (mask >> shift)), /* not sign extended */
+-                     expected);
+-#if 0 /* NB: For checking to see if HAL is fixed or not */
+-      else {
+-                      printk("%s: Keeping 0x%04x[%s] - 0x%x (%d).\n",
+-                             SC_DEV_NAME(ah->ah_sc),
+-                             reg,
+-                             name, 
+-                             (get_field(ah, reg, mask, shift, is_signed) & (mask >> shift)),
+-                             get_field(ah, reg, mask, shift, is_signed));
+-      }
+-#endif
+-}
+-
+-static inline void verification_warning(struct ath_hal *ah, const char *name,
+-    u_int32_t reg, u_int32_t mask, 
+-    u_int32_t shift, u_int32_t expected, int is_signed) {
+-
+-      int ret = field_eq(ah, reg, mask, shift, expected, is_signed);
+-      if (!ret) {
+-              printk("%s: %s verification of %s default value "
+-                     "[found=0x%x (%d) expected=0x%x (%d)].\n", 
+-                     SC_DEV_NAME(ah->ah_sc),
+-                     (ret ? "PASSED" : "FAILED"),
+-                      name, 
+-                     (get_field(ah, reg, mask, shift, is_signed) & (mask >> shift)), 
+-                     get_field(ah, reg, mask, shift, is_signed), 
+-                     (expected & (mask >> shift)), /* not sign extended */
+-                     expected);
+-              ath_hal_print_decoded_register(ah, NULL, reg, 
+-                                             OS_REG_READ(ah, reg), OS_REG_READ(ah, reg), 0);
+-      }
+-}
+-
+-#define GET_FIELD(ah, __reg, __mask, __signed) \
+-      get_field(ah, __reg, __mask, __mask ## _S, __signed)
+ #define SET_FIELD(ah, __reg, __mask, __value) \
+       set_field(ah, __reg, __mask, __mask ## _S, __value);
+-#define FIELD_EQ(ah, __reg, __mask, __value, __signed) \
+-      field_eq(ah, __reg, __mask, __mask ## _S, __value, __signed)
+-
+-#if 0 /* NB: These are working at this point, and HAL tweaks them a lot */
+-#define OVERRIDE_WARNING(ah, __reg, __mask, __expected, __signed) \
+-      override_warning(ah, #__mask, __reg, __mask, __mask ## _S, __expected, __signed)
+-#else
+-#define OVERRIDE_WARNING(ah, __reg, __mask, __expected, __signed) 
+-#endif
+-      
+-#define VERIFICATION_WARNING(ah, __reg, __mask, __signed) \
+-      verification_warning(ah, #__mask, __reg, __mask, __mask ## _S, DEFAULT_ ## __mask, __signed)
+-#define VERIFICATION_WARNING_SW(ah, __reg, __mask, __signed) \
+-      verification_warning(ah, #__mask, __reg, __mask, __mask ## _S, DEFAULT_ENABLE_ ## __reg ? __mask ## _ON : __mask ## _OFF, __signed)
+-
+-static inline void ath_hal_set_noise_immunity(struct ath_hal *ah,
+-                                            int agc_desired_size, 
+-                                            int agc_coarse_hi,
+-                                            int agc_coarse_lo, 
+-                                            int sig_firpwr) 
+-{
+-      ATH_HAL_LOCK_IRQ(ah->ah_sc);
+-      ath_hal_set_function(__func__);
+-      ath_hal_set_device(SC_DEV_NAME(ah->ah_sc));
+-
+-#if 0 /* NB: These are working at this point, and HAL tweaks them a lot */
+-      OVERRIDE_WARNING(ah, AR5K_PHY_AGCSIZE, AR5K_PHY_AGCSIZE_DESIRED, agc_desired_size, 1);
+-      OVERRIDE_WARNING(ah, AR5K_PHY_AGCCOARSE, AR5K_PHY_AGCCOARSE_LO, agc_coarse_lo, 1);
+-      OVERRIDE_WARNING(ah, AR5K_PHY_AGCCOARSE, AR5K_PHY_AGCCOARSE_HI, agc_coarse_hi, 1);
+-      OVERRIDE_WARNING(ah, AR5K_PHY_SIG, AR5K_PHY_SIG_FIRPWR, sig_firpwr, 1);
+-#endif
+-
+-      SET_FIELD(ah, AR5K_PHY_AGCSIZE, AR5K_PHY_AGCSIZE_DESIRED, agc_desired_size);
+-      SET_FIELD(ah, AR5K_PHY_AGCCOARSE, AR5K_PHY_AGCCOARSE_LO, agc_coarse_lo);
+-      SET_FIELD(ah, AR5K_PHY_AGCCOARSE, AR5K_PHY_AGCCOARSE_HI, agc_coarse_hi);
+-      SET_FIELD(ah, AR5K_PHY_SIG, AR5K_PHY_SIG_FIRPWR, sig_firpwr);
+-
+-      ath_hal_set_function(NULL);
+-      ath_hal_set_device(NULL);
+-      ATH_HAL_UNLOCK_IRQ(ah->ah_sc);
+-}
+-
+-static inline void ath_hal_set_ofdm_weak_det(struct ath_hal *ah, 
+-      int low_m1, int low_m2, int low_m2_count, int low_self_corr,
+-      int high_m1, int high_m2, int high_m2_count)
+-{
+-      ATH_HAL_LOCK_IRQ(ah->ah_sc);
+-      ath_hal_set_function(__func__);
+-      ath_hal_set_device(SC_DEV_NAME(ah->ah_sc));
+-
+-      OVERRIDE_WARNING(ah, AR5K_PHY_WEAK_OFDM_LOW, AR5K_PHY_WEAK_OFDM_LOW_M1, low_m1, 0);
+-      OVERRIDE_WARNING(ah, AR5K_PHY_WEAK_OFDM_LOW, AR5K_PHY_WEAK_OFDM_LOW_M2, low_m2, 0);
+-      OVERRIDE_WARNING(ah, AR5K_PHY_WEAK_OFDM_LOW, AR5K_PHY_WEAK_OFDM_LOW_M2_COUNT, low_m2_count, 0);
+-      OVERRIDE_WARNING(ah, AR5K_PHY_WEAK_OFDM_LOW, AR5K_PHY_WEAK_OFDM_LOW_SELFCOR, low_self_corr, 0);
+-      OVERRIDE_WARNING(ah, AR5K_PHY_WEAK_OFDM_HIGH, AR5K_PHY_WEAK_OFDM_HIGH_M1, high_m1, 0);
+-      OVERRIDE_WARNING(ah, AR5K_PHY_WEAK_OFDM_HIGH, AR5K_PHY_WEAK_OFDM_HIGH_M2, high_m2, 0);
+-      OVERRIDE_WARNING(ah, AR5K_PHY_WEAK_OFDM_HIGH, AR5K_PHY_WEAK_OFDM_HIGH_M2_COUNT, high_m2_count, 0);
+-
+-      SET_FIELD(ah, AR5K_PHY_WEAK_OFDM_LOW, AR5K_PHY_WEAK_OFDM_LOW_M1, low_m1);
+-      SET_FIELD(ah, AR5K_PHY_WEAK_OFDM_LOW, AR5K_PHY_WEAK_OFDM_LOW_M2, low_m2);
+-      SET_FIELD(ah, AR5K_PHY_WEAK_OFDM_LOW, AR5K_PHY_WEAK_OFDM_LOW_M2_COUNT, low_m2_count);
+-      SET_FIELD(ah, AR5K_PHY_WEAK_OFDM_LOW, AR5K_PHY_WEAK_OFDM_LOW_SELFCOR, low_self_corr);
+-      SET_FIELD(ah, AR5K_PHY_WEAK_OFDM_HIGH, AR5K_PHY_WEAK_OFDM_HIGH_M1, high_m1);
+-      SET_FIELD(ah, AR5K_PHY_WEAK_OFDM_HIGH, AR5K_PHY_WEAK_OFDM_HIGH_M2, high_m2);
+-      SET_FIELD(ah, AR5K_PHY_WEAK_OFDM_HIGH, AR5K_PHY_WEAK_OFDM_HIGH_M2_COUNT, high_m2_count);
+-
+-      ath_hal_set_function(NULL);
+-      ath_hal_set_device(NULL);
+-      ATH_HAL_UNLOCK_IRQ(ah->ah_sc);
+-}
+-
+-static inline void ath_hal_set_cck_weak_det(struct ath_hal *ah, int thresh)
+-{
+-      ATH_HAL_LOCK_IRQ(ah->ah_sc);
+-      ath_hal_set_function(__func__);
+-      ath_hal_set_device(SC_DEV_NAME(ah->ah_sc));
+-
+-      OVERRIDE_WARNING(ah, AR5K_PHY_WEAK_CCK, AR5K_PHY_WEAK_CCK_THRESH, thresh, 0);
+-
+-      SET_FIELD(ah, AR5K_PHY_WEAK_CCK, AR5K_PHY_WEAK_CCK_THRESH, thresh);
+-
+-      ath_hal_set_function(NULL);
+-      ath_hal_set_device(NULL);
+-      ATH_HAL_UNLOCK_IRQ(ah->ah_sc);
+-}
+-
+-static inline void ath_hal_set_sig_firstep(struct ath_hal *ah, int firstep)
+-{
+-      ATH_HAL_LOCK_IRQ(ah->ah_sc);
+-      ath_hal_set_function(__func__);
+-      ath_hal_set_device(SC_DEV_NAME(ah->ah_sc));
+-      OVERRIDE_WARNING(ah, AR5K_PHY_SIG, AR5K_PHY_SIG_FIRSTEP, firstep, 0);
+-
+-      SET_FIELD(ah, AR5K_PHY_SIG, AR5K_PHY_SIG_FIRSTEP, firstep);
+-
+-      ath_hal_set_function(NULL);
+-      ath_hal_set_device(NULL);
+-      ATH_HAL_UNLOCK_IRQ(ah->ah_sc);
+-}
+-
+-static inline void ath_hal_set_spur_immunity(struct ath_hal *ah, int thresh)
+-{
+-      ATH_HAL_LOCK_IRQ(ah->ah_sc);
+-      ath_hal_set_function(__func__);
+-      ath_hal_set_device(SC_DEV_NAME(ah->ah_sc));
+-
+-      OVERRIDE_WARNING(ah, AR5K_PHY_SPUR, AR5K_PHY_SPUR_THRESH, thresh, 0);
+-
+-      SET_FIELD(ah, AR5K_PHY_SPUR, AR5K_PHY_SPUR_THRESH, thresh);
+-
+-      ath_hal_set_function(NULL);
+-      ath_hal_set_device(NULL);
+-      ATH_HAL_UNLOCK_IRQ(ah->ah_sc);
+-}
+-
+-static inline void ath_hal_restore_default_noise_immunity(struct ath_hal *ah) {
+-
+-      ath_hal_set_noise_immunity(ah, 
+-              DEFAULT_AR5K_PHY_AGCSIZE_DESIRED, 
+-              DEFAULT_AR5K_PHY_AGCCOARSE_HI,
+-              DEFAULT_AR5K_PHY_AGCCOARSE_LO,
+-              DEFAULT_AR5K_PHY_SIG_FIRPWR);
+-}
+-
+-static inline void ath_hal_enable_ofdm_weak_det(struct ath_hal *ah, int enable) {
+-      if (enable)
+-              ath_hal_set_ofdm_weak_det(ah, 
+-                      AR5K_PHY_WEAK_OFDM_LOW_M1_ON,
+-                      AR5K_PHY_WEAK_OFDM_LOW_M2_ON,
+-                      AR5K_PHY_WEAK_OFDM_LOW_M2_COUNT_ON,
+-                      AR5K_PHY_WEAK_OFDM_LOW_SELFCOR_ON,
+-                      AR5K_PHY_WEAK_OFDM_HIGH_M1_ON,
+-                      AR5K_PHY_WEAK_OFDM_HIGH_M2_ON,
+-                      AR5K_PHY_WEAK_OFDM_HIGH_M2_COUNT_ON);
+-      else
+-              ath_hal_set_ofdm_weak_det(ah, 
+-                      AR5K_PHY_WEAK_OFDM_LOW_M1_OFF,
+-                      AR5K_PHY_WEAK_OFDM_LOW_M2_OFF,
+-                      AR5K_PHY_WEAK_OFDM_LOW_M2_COUNT_OFF,
+-                      AR5K_PHY_WEAK_OFDM_LOW_SELFCOR_OFF,
+-                      AR5K_PHY_WEAK_OFDM_HIGH_M1_OFF,
+-                      AR5K_PHY_WEAK_OFDM_HIGH_M2_OFF,
+-                      AR5K_PHY_WEAK_OFDM_HIGH_M2_COUNT_OFF);
+-}
+-
+-static inline void ath_hal_enable_cck_weak_det(struct ath_hal *ah, int enable) {
+-      ath_hal_set_cck_weak_det(ah, enable 
+-                               ? AR5K_PHY_WEAK_CCK_THRESH_ON 
+-                               : AR5K_PHY_WEAK_CCK_THRESH_OFF);
+-}
+-
+-static inline void ath_hal_restore_default_ofdm_weak_det(struct ath_hal *ah) {
+-      ath_hal_enable_ofdm_weak_det(ah, DEFAULT_ENABLE_AR5K_PHY_WEAK_OFDM);
+-}
+-
+-static inline void ath_hal_restore_default_cck_weak_det(struct ath_hal *ah) {
+-      ath_hal_enable_cck_weak_det(ah, DEFAULT_ENABLE_AR5K_PHY_WEAK_CCK);
+-}
+-
+-static inline void ath_hal_restore_default_sig_firstep(struct ath_hal *ah) {
+-
+-      ath_hal_set_sig_firstep(ah, 
+-              DEFAULT_AR5K_PHY_SIG_FIRSTEP);
+-}
+-
+-static inline void ath_hal_restore_default_spur_immunity(struct ath_hal *ah) {
+-
+-      ath_hal_set_spur_immunity(ah, 
+-              DEFAULT_AR5K_PHY_SPUR_THRESH);
+-}
+-
+-static inline void ath_hal_restore_default_intmit(struct ath_hal *ah) {
+-      ath_hal_restore_default_noise_immunity(ah);
+-      ath_hal_restore_default_ofdm_weak_det(ah);
+-      ath_hal_restore_default_cck_weak_det(ah);
+-      ath_hal_restore_default_sig_firstep(ah);
+-      ath_hal_restore_default_spur_immunity(ah);
+-
+-}
+-
+-static inline void ath_hal_verify_default_intmit(struct ath_hal *ah) {
+-      /* Just a list of all the fields above, for sanity checks... */
+-      VERIFICATION_WARNING(ah, AR5K_PHY_AGCSIZE, AR5K_PHY_AGCSIZE_DESIRED, 1);
+-      VERIFICATION_WARNING(ah, AR5K_PHY_AGCCOARSE, AR5K_PHY_AGCCOARSE_LO, 1);
+-      VERIFICATION_WARNING(ah, AR5K_PHY_AGCCOARSE, AR5K_PHY_AGCCOARSE_HI, 1);
+-      VERIFICATION_WARNING(ah, AR5K_PHY_SIG, AR5K_PHY_SIG_FIRPWR, 1);
+-      VERIFICATION_WARNING_SW(ah, AR5K_PHY_WEAK_OFDM_LOW, AR5K_PHY_WEAK_OFDM_LOW_M1, 0);
+-      VERIFICATION_WARNING_SW(ah, AR5K_PHY_WEAK_OFDM_LOW, AR5K_PHY_WEAK_OFDM_LOW_M2, 0);
+-      VERIFICATION_WARNING_SW(ah, AR5K_PHY_WEAK_OFDM_LOW, AR5K_PHY_WEAK_OFDM_LOW_M2_COUNT, 0);
+-      VERIFICATION_WARNING_SW(ah, AR5K_PHY_WEAK_OFDM_LOW, AR5K_PHY_WEAK_OFDM_LOW_SELFCOR, 0);
+-      VERIFICATION_WARNING_SW(ah, AR5K_PHY_WEAK_OFDM_HIGH, AR5K_PHY_WEAK_OFDM_HIGH_M1, 0);
+-      VERIFICATION_WARNING_SW(ah, AR5K_PHY_WEAK_OFDM_HIGH, AR5K_PHY_WEAK_OFDM_HIGH_M2, 0);
+-      VERIFICATION_WARNING_SW(ah, AR5K_PHY_WEAK_OFDM_HIGH, AR5K_PHY_WEAK_OFDM_HIGH_M2_COUNT, 0);
+-      VERIFICATION_WARNING_SW(ah, AR5K_PHY_WEAK_CCK, AR5K_PHY_WEAK_CCK_THRESH, 0);
+-      VERIFICATION_WARNING(ah, AR5K_PHY_SIG, AR5K_PHY_SIG_FIRSTEP, 0);
+-      VERIFICATION_WARNING(ah, AR5K_PHY_SPUR, AR5K_PHY_SPUR_THRESH, 0);
+-}
++int ath_set_ack_bitrate(struct ath_softc *sc, int);
++int ar_device(int devid);
++const char * ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val);
+ static inline void ath_hal_set_dmasize_pcie(struct ath_hal *ah) {
+       SET_FIELD(ah, AR5K_TXCFG, AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
+Index: madwifi-trunk-r3776/ath/if_ath_hal.h
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath_hal.h  2008-07-17 00:53:20.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath_hal.h       2008-07-17 03:41:25.000000000 +0200
+@@ -79,7 +79,7 @@
+       ath_hal_set_function(__func__);
+       ath_hal_set_device(SC_DEV_NAME(ah->ah_sc));
+       ret =
+-          ah->ah_getDiagState(ah, request, args, argsize, *result,
++          ah->ah_getDiagState(ah, request, args, argsize, result,
+                               resultsize);
+       ath_hal_set_function(NULL);
+       ath_hal_set_device(NULL);
+Index: madwifi-trunk-r3776/scripts/if_ath_hal_generator.pl
+===================================================================
+--- madwifi-trunk-r3776.orig/scripts/if_ath_hal_generator.pl   2008-07-17 00:21:30.000000000 +0200
++++ madwifi-trunk-r3776/scripts/if_ath_hal_generator.pl        2008-07-17 03:46:30.000000000 +0200
+@@ -145,7 +145,9 @@
+     "ah_waitForBeaconDone"        => "ath_hal_waitforbeacon",
+     "ah_writeAssocid"             => "ath_hal_setassocid",
+     "ah_clrMulticastFilterIndex"  => "ath_hal_clearmcastfilter",
+-    "ah_detectCardPresent"        => "ath_hal_detectcardpresent"
++    "ah_detectCardPresent"        => "ath_hal_detectcardpresent",
++    "ah_setSifsTime"              => "ath_hal_setsifstime",
++    "ah_getSifsTime"              => "ath_hal_getsifstime"
+ );
+ #
+@@ -254,7 +256,7 @@
+     foreach (@parameters) {
+         s/ \*/\* /;
+-        /^((?:(?:const|struct|\*)\s*)*)([^\s]+\*?)\s*([^\s]*)\s*/;
++        /^((?:(?:const|struct|\*)\s*)*)([^\s]+\**)\s*([^\s]*)\s*/;
+         my $type = "$1$2";
+         my $name = "$3";
+         if ( 0 == length($name) ) {
diff --git a/package/madwifi/patches-r3776/317-devid.patch b/package/madwifi/patches-r3776/317-devid.patch
new file mode 100644 (file)
index 0000000..d22d005
--- /dev/null
@@ -0,0 +1,19 @@
+Index: madwifi-trunk-r3776/ath/if_ath_pci.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath_pci.c  2008-07-17 00:53:20.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath_pci.c       2008-07-17 03:54:06.000000000 +0200
+@@ -114,11 +114,13 @@
+       { 0x168c, 0x0023, PCI_ANY_ID, PCI_ANY_ID },
+       { 0x168c, 0x0024, PCI_ANY_ID, PCI_ANY_ID },
+       { 0x168c, 0x9013, PCI_ANY_ID, PCI_ANY_ID }, /* sonicwall */
++      { 0x168c, 0xff1a, PCI_ANY_ID, PCI_ANY_ID },
+       { 0 }
+ };
+ static u16 ath_devidmap[][2] = {
+-      { 0x9013, 0x0013 }
++      { 0x9013, 0x0013 },
++      { 0xff1a, 0x001a }
+ };
+ static int
diff --git a/package/madwifi/patches-r3776/318-ifxmips_eeprom.patch b/package/madwifi/patches-r3776/318-ifxmips_eeprom.patch
new file mode 100644 (file)
index 0000000..4fcc592
--- /dev/null
@@ -0,0 +1,87 @@
+Index: madwifi-trunk-r3776/ath_hal/ah_os.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath_hal/ah_os.c   2008-07-17 00:21:30.000000000 +0200
++++ madwifi-trunk-r3776/ath_hal/ah_os.c        2008-07-17 04:00:18.000000000 +0200
+@@ -917,9 +917,56 @@
+  * NB: see the comments in ah_osdep.h about byte-swapping register
+  *     reads and writes to understand what's going on below.
+  */
++
++#ifdef CONFIG_IFXMIPS
++extern int ifxmips_has_brn_block(void);
++static int ifxmips_emulate = 0;
++#define EEPROM_EMULATION 1
++#endif
++
++#ifdef EEPROM_EMULATION
++static int ath_hal_eeprom(struct ath_hal *ah, unsigned long addr, int val, int write)
++{
++      static int addrsel = 0;
++      static int rc = 0;
++
++      if (write) {
++              if(addr == 0x6000) {
++                      addrsel = val * 2;
++                      rc = 0;
++              }
++      } else {
++              switch(addr)
++              {
++              case 0x600c:
++                      if(rc++ < 2)
++                              val = 0x00000000;
++                      else
++                              val = 0x00000002;
++                      break;
++              case 0x6004:
++                      val = cpu_to_le16(__raw_readw((u16 *) KSEG1ADDR(0xb07f0400 + addrsel)));
++                      /* this forces the regdomain to 0x00 (worldwide), as the original setting
++                       * causes issues with the HAL */
++                      if (addrsel == 0x17e)
++                              val = 0;
++                      break;
++              }
++      }
++      return val;
++}
++#endif
++
+ void __ahdecl
+ ath_hal_reg_write(struct ath_hal *ah, u_int address, u_int32_t value)
+ {
++#ifdef EEPROM_EMULATION
++      if((address >= 0x6000) && (address <= 0x6010) && ifxmips_emulate) {
++              ath_hal_eeprom(ah, address, value, 1);
++              return;
++      }
++#endif
++
+       _trace_regop(ah, REGOP_WRITE, address, value);
+       _OS_REG_WRITE(ah, address, value);
+ }
+@@ -929,7 +976,14 @@
+ u_int32_t __ahdecl
+ ath_hal_reg_read(struct ath_hal *ah, u_int address)
+ {
+-      u_int32_t val = _OS_REG_READ(ah, address);
++      u_int32_t val;
++
++#ifdef EEPROM_EMULATION
++      if((address >= 0x6000) && (address <= 0x6010) && ifxmips_emulate)
++              val = ath_hal_eeprom(ah, address, 0, 0);
++      else
++#endif
++              val = _OS_REG_READ(ah, address);
+       _trace_regop(ah, REGOP_READ, address, val);
+       return val;
+ }
+@@ -1123,6 +1177,9 @@
+ #ifdef MMIOTRACE
+       kmmio_logmsg = _kmmio_logmsg;
+ #endif
++#ifdef CONFIG_IFXMIPS
++      ifxmips_emulate = ifxmips_has_brn_block();
++#endif
+       sep = "";
+       for (i = 0; ath_hal_buildopts[i] != NULL; i++) {
diff --git a/package/madwifi/patches-r3776/319-eap_auth_disassoc.patch b/package/madwifi/patches-r3776/319-eap_auth_disassoc.patch
new file mode 100644 (file)
index 0000000..38f39d5
--- /dev/null
@@ -0,0 +1,89 @@
+This patch causes STA mode interfaces to disassociate if transmission of assoc/auth
+critical packets failed.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 03:53:09.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 04:00:42.000000000 +0200
+@@ -8272,6 +8272,18 @@
+ #endif
+                               if (ts->ts_status & HAL_TXERR_XRETRY) {
+                                       sc->sc_stats.ast_tx_xretries++;
++                                      if (SKB_CB(bf->bf_skb)->auth_pkt && (ni->ni_vap->iv_opmode == IEEE80211_M_STA)) {
++                                              struct ieee80211com *ic = &sc->sc_ic;
++
++                                              /* if roaming is enabled, try reassociating, otherwise
++                                               * disassociate and go back to the scan state */
++                                              IEEE80211_VAPS_LOCK_BH(ic);
++                                              if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
++                                                      ni->ni_vap->iv_newstate(ni->ni_vap, IEEE80211_S_ASSOC, 1);
++                                              else
++                                                      ni->ni_vap->iv_newstate(ni->ni_vap, IEEE80211_S_SCAN, 0);
++                                              IEEE80211_VAPS_UNLOCK_BH(ic);
++                                      }
+                                       if (ni->ni_flags & IEEE80211_NODE_UAPSD_TRIG) {
+                                               ni->ni_stats.ns_tx_eosplost++;
+                                               DPRINTF(sc, ATH_DEBUG_UAPSD,
+Index: madwifi-trunk-r3776/net80211/ieee80211_linux.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_linux.c        2008-07-17 00:49:54.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_linux.c     2008-07-17 04:01:27.000000000 +0200
+@@ -158,6 +158,7 @@
+               SKB_NI(skb) = NULL;
+               SKB_CB(skb)->flags = 0;
++              SKB_CB(skb)->auth_pkt = 0;
+               skb_reserve(skb, sizeof(struct ieee80211_frame));
+               *frm = skb_put(skb, pktlen);
+Index: madwifi-trunk-r3776/net80211/ieee80211_linux.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_linux.h        2008-07-17 00:53:20.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_linux.h     2008-07-17 04:02:15.000000000 +0200
+@@ -411,6 +411,7 @@
+ #define M_SKB_TRACKED 0x20
+       void            (*next_destructor)(struct sk_buff *skb);
+ #endif
++      u_int8_t auth_pkt;
+ };
+ struct __assert {
+Index: madwifi-trunk-r3776/net80211/ieee80211_output.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_output.c       2008-07-17 02:35:10.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_output.c    2008-07-17 04:00:42.000000000 +0200
+@@ -773,6 +773,8 @@
+       else
+               hdrsize = sizeof(struct ieee80211_frame);
++      SKB_CB(skb)->auth_pkt = (eh.ether_type == __constant_htons(ETHERTYPE_PAE));
++
+       switch (vap->iv_opmode) {
+       case IEEE80211_M_IBSS:
+       case IEEE80211_M_AHDEMO:
+@@ -1617,6 +1619,7 @@
+       ie->param_len = frm - &ie->param_oui[0];
+       return frm;
+ }
++
+ #endif
+ /*
+  * Send a probe request frame with the specified ssid
+@@ -1881,6 +1884,7 @@
+                               sizeof(u_int16_t)+IEEE80211_CHALLENGE_LEN : 0));
+               if (skb == NULL)
+                       senderr(ENOMEM, is_tx_nobuf);
++              SKB_CB(skb)->auth_pkt = 1;
+               ((__le16 *)frm)[0] =
+                       (is_shared_key) ? htole16(IEEE80211_AUTH_ALG_SHARED)
+@@ -1955,6 +1959,7 @@
+                       vap->app_ie[IEEE80211_APPIE_FRAME_ASSOC_REQ].length);
+               if (skb == NULL)
+                       senderr(ENOMEM, is_tx_nobuf);
++              SKB_CB(skb)->auth_pkt = 1;
+               capinfo = 0;
+               if (vap->iv_opmode == IEEE80211_M_IBSS)
diff --git a/package/madwifi/patches-r3776/320-hidden_ssid.patch b/package/madwifi/patches-r3776/320-hidden_ssid.patch
new file mode 100644 (file)
index 0000000..d5a7083
--- /dev/null
@@ -0,0 +1,40 @@
+This patch fixes the detection of hidden SSIDs as transmitted
+by some cisco systems.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+Index: madwifi-trunk-r3776/net80211/ieee80211_scan_sta.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_scan_sta.c     2008-07-17 03:10:02.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_scan_sta.c  2008-07-17 04:02:41.000000000 +0200
+@@ -209,6 +209,19 @@
+               ieee80211_saveie(iep, ie);
+ }
++
++static inline int is_empty_ssid(u_int8_t *ssid)
++{
++      if (!ssid)
++              return 1;
++      if (ssid[1] == 0)
++              return 1;
++      if ((ssid[1] == 1) && (ssid[2] == 0))
++              return 1;
++      return 0;
++}
++
++
+ /*
+  * Process a beacon or probe response frame; create an
+  * entry in the scan cache or update any previous entry.
+@@ -252,8 +265,8 @@
+       ise = &se->base;
+       /* XXX ap beaconing multiple ssid w/ same bssid */
+-      if (sp->ssid[1] != 0 &&
+-          (ISPROBE(subtype) || ise->se_ssid[1] == 0))
++      if (!is_empty_ssid(sp->ssid) &&
++          (ISPROBE(subtype) || is_empty_ssid(ise->se_ssid)))
+               memcpy(ise->se_ssid, sp->ssid, 2 + sp->ssid[1]);
+       memcpy(ise->se_rates, sp->rates, 
diff --git a/package/madwifi/patches-r3776/321-bgscan_rssi_thresh.patch b/package/madwifi/patches-r3776/321-bgscan_rssi_thresh.patch
new file mode 100644 (file)
index 0000000..5819193
--- /dev/null
@@ -0,0 +1,137 @@
+Add an optional background scanning threshold triggered by low rssi
+(useful for passing updated scan results to the supplicant ahead of
+time, before losing connectivity entirely)
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+Index: madwifi-trunk-r3776/net80211/ieee80211_ioctl.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_ioctl.h        2008-07-17 03:07:53.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_ioctl.h     2008-07-17 04:03:30.000000000 +0200
+@@ -655,6 +655,7 @@
+       IEEE80211_PARAM_MINRATE                 = 84,   /* Minimum rate (by table index) */
+       IEEE80211_PARAM_PROTMODE_RSSI           = 85,   /* RSSI Threshold for enabling protection mode */
+       IEEE80211_PARAM_PROTMODE_TIMEOUT        = 86,   /* Timeout for expiring protection mode */
++      IEEE80211_PARAM_BGSCAN_THRESH           = 87,   /* bg scan rssi threshold */
+ };
+ #define       SIOCG80211STATS                 (SIOCDEVPRIVATE+2)
+Index: madwifi-trunk-r3776/net80211/ieee80211_var.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_var.h  2008-07-17 02:56:18.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_var.h       2008-07-17 04:03:07.000000000 +0200
+@@ -92,6 +92,8 @@
+ #define       IEEE80211_BGSCAN_IDLE_MIN       100     /* min idle time (ms) */
+ #define       IEEE80211_BGSCAN_IDLE_DEFAULT   250     /* default idle time (ms) */
++#define IEEE80211_BGSCAN_TRIGGER_INTVL 20 /* min trigger interval for thresh based bgscan (secs) */
++
+ #define IEEE80211_COVERAGE_CLASS_MAX  31      /* max coverage class */
+ #define IEEE80211_REGCLASSIDS_MAX     10      /* max regclass id list */
+@@ -229,6 +231,9 @@
+       u_int8_t iv_nickname[IEEE80211_NWID_LEN];
+       u_int iv_bgscanidle;                            /* bg scan idle threshold */
+       u_int iv_bgscanintvl;                           /* bg scan min interval */
++      u_int iv_bgscanthr;                                     /* bg scan rssi threshold */
++      u_int iv_bgscantrintvl;                         /* bg scan trigger interval */
++      unsigned long iv_bgscanthr_next;                /* last trigger for bgscan */
+       u_int iv_scanvalid;                             /* scan cache valid threshold */
+       struct ieee80211_roam iv_roam;                  /* sta-mode roaming state */
+@@ -612,6 +617,7 @@
+ #define IEEE80211_FEXT_SWBMISS                0x00000400      /* CONF: use software beacon timer */
+ #define IEEE80211_FEXT_DROPUNENC_EAPOL        0x00000800      /* CONF: drop unencrypted eapol frames */
+ #define IEEE80211_FEXT_APPIE_UPDATE   0x00001000      /* STATE: beacon APP IE updated */
++#define IEEE80211_FEXT_BGSCAN_THR     0x00002000      /* bgscan due to low rssi */
+ #define IEEE80211_COM_UAPSD_ENABLE(_ic)               ((_ic)->ic_flags_ext |= IEEE80211_FEXT_UAPSD)
+ #define IEEE80211_COM_UAPSD_DISABLE(_ic)      ((_ic)->ic_flags_ext &= ~IEEE80211_FEXT_UAPSD)
+Index: madwifi-trunk-r3776/net80211/ieee80211_wireless.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_wireless.c     2008-07-17 03:08:16.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_wireless.c  2008-07-17 04:03:07.000000000 +0200
+@@ -2778,6 +2778,9 @@
+               else
+                       retv = EINVAL;
+               break;
++      case IEEE80211_PARAM_BGSCAN_THRESH:
++              vap->iv_bgscanthr = value;
++              break;
+       case IEEE80211_PARAM_MCAST_RATE:
+               /* units are in KILObits per second */
+               if (value >= 256 && value <= 54000)
+@@ -3181,6 +3184,9 @@
+       case IEEE80211_PARAM_BGSCAN_INTERVAL:
+               param[0] = vap->iv_bgscanintvl / HZ;    /* seconds */
+               break;
++      case IEEE80211_PARAM_BGSCAN_THRESH:
++              param[0] = vap->iv_bgscanthr;   /* rssi */
++              break;
+       case IEEE80211_PARAM_MCAST_RATE:
+               param[0] = vap->iv_mcast_rate;  /* seconds */
+               break;
+@@ -5704,6 +5710,10 @@
+         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bgscanintvl" },
+       { IEEE80211_PARAM_BGSCAN_INTERVAL,
+         0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_bgscanintvl" },
++      { IEEE80211_PARAM_BGSCAN_THRESH,
++        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bgscanthr" },
++      { IEEE80211_PARAM_BGSCAN_THRESH,
++        0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_bgscanthr" },
+       { IEEE80211_PARAM_MCAST_RATE,
+         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "mcast_rate" },
+       { IEEE80211_PARAM_MCAST_RATE,
+Index: madwifi-trunk-r3776/net80211/ieee80211_input.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_input.c        2008-07-17 02:56:18.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_input.c     2008-07-17 04:03:07.000000000 +0200
+@@ -2984,8 +2984,10 @@
+ {
+       struct ieee80211com *ic = vap->iv_ic;
++      vap->iv_bgscantrintvl = (vap->iv_bgscantrintvl + 1) % 4;
+       return ((ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN) &&
+-              time_after(jiffies, ic->ic_lastdata + vap->iv_bgscanidle));
++              (((ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN_THR) && !vap->iv_bgscantrintvl) ||
++                      time_after(jiffies, ic->ic_lastdata + vap->iv_bgscanidle)));
+ }
+ static __inline int
+@@ -3229,6 +3231,23 @@
+                       /* record tsf of last beacon */
+                       memcpy(ni->ni_tstamp.data, scan.tstamp,
+                               sizeof(ni->ni_tstamp));
++
++                      /* When rssi is low, start doing bgscans more frequently to allow
++                       * the supplicant to make a better switching decision */
++                      if ((rssi < vap->iv_bgscanthr) &&
++                                      (!vap->iv_bgscanthr_next ||
++                                              !time_before(jiffies, vap->iv_bgscanthr_next)) &&
++                                      !(ic->ic_flags & IEEE80211_F_SCAN)) {
++                              int ret;
++
++                              ic->ic_lastdata = 0;
++                              ic->ic_lastscan = 0;
++                              ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN_THR;
++                              ret = ieee80211_bg_scan(vap);
++                              if (ret)
++                                      vap->iv_bgscanthr_next = jiffies + msecs_to_jiffies(IEEE80211_BGSCAN_TRIGGER_INTVL * 1000);
++                      }
++
+                       if (ni->ni_intval != scan.bintval) {
+                               IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni,
+                                               "beacon interval divergence: "
+Index: madwifi-trunk-r3776/net80211/ieee80211_scan.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_scan.c 2008-07-17 03:07:53.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_scan.c      2008-07-17 04:03:07.000000000 +0200
+@@ -793,7 +793,7 @@
+                               ieee80211_sta_pwrsave(vap, 0);
+                               if (ss->ss_next >= ss->ss_last) {
+                                       ieee80211_notify_scan_done(vap);
+-                                      ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN;
++                                      ic->ic_flags_ext &= ~(IEEE80211_FEXT_BGSCAN|IEEE80211_FEXT_BGSCAN_THR);
+                               }
+                       }
+                       SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_CANCEL;
diff --git a/package/madwifi/patches-r3776/322-ignore_broken_bssid.patch b/package/madwifi/patches-r3776/322-ignore_broken_bssid.patch
new file mode 100644 (file)
index 0000000..f185dbf
--- /dev/null
@@ -0,0 +1,20 @@
+Some misconfigured APs broadcast NULL BSSIDs, which can confuse the STA
+Ignore those when scanning.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+Index: madwifi-trunk-r3776/net80211/ieee80211_scan_sta.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_scan_sta.c     2008-07-17 04:02:41.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_scan_sta.c  2008-07-17 04:03:54.000000000 +0200
+@@ -242,6 +242,10 @@
+       struct ieee80211_scan_entry *ise;
+       int hash;
++      /* workaround for broken APs that broadcast NULL BSSIDs */
++      if (memcmp(wh->i_addr3, "\x00\x00\x00\x00\x00\x00", 6) == 0)
++              return 0;
++
+       hash = STA_HASH(macaddr);
+       SCAN_STA_LOCK_IRQ(st);
+       LIST_FOREACH(se, &st->st_hash[hash], se_hash)
diff --git a/package/madwifi/patches-r3776/323-crash_fix.patch b/package/madwifi/patches-r3776/323-crash_fix.patch
new file mode 100644 (file)
index 0000000..ad75bff
--- /dev/null
@@ -0,0 +1,23 @@
+Index: madwifi-trunk-r3776/net80211/ieee80211_node.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_node.c 2008-07-17 02:56:18.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_node.c      2008-07-17 04:05:43.000000000 +0200
+@@ -1999,11 +1999,13 @@
+       /* From this point onwards we can no longer find the node,
+        * so no more references are generated
+        */
+-      ieee80211_remove_wds_addr(nt, ni->ni_macaddr);
+-      ieee80211_del_wds_node(nt, ni);
+-      IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
+-      node_table_leave_locked(nt, ni);
+-      IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
++      if (nt) {
++              ieee80211_remove_wds_addr(nt, ni->ni_macaddr);
++              ieee80211_del_wds_node(nt, ni);
++              IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
++              node_table_leave_locked(nt, ni);
++              IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
++      }
+       /*
+        * If node wasn't previously associated all
diff --git a/package/madwifi/patches-r3776/324-reassoc.patch b/package/madwifi/patches-r3776/324-reassoc.patch
new file mode 100644 (file)
index 0000000..12c5b91
--- /dev/null
@@ -0,0 +1,33 @@
+Add a preliminary fix for the reassoc check, but disable reassoc entirely for now
+until we've figured out why it fails frequently.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+Index: madwifi-trunk-r3776/net80211/ieee80211_node.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_node.c 2008-07-17 04:05:43.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_node.c      2008-07-17 04:05:55.000000000 +0200
+@@ -561,10 +561,9 @@
+ EXPORT_SYMBOL(ieee80211_ibss_merge);
+ static __inline int
+-ssid_equal(const struct ieee80211_node *a, const struct ieee80211_node *b)
++bssid_equal(const struct ieee80211_node *a, const struct ieee80211_node *b)
+ {
+-      return (a->ni_esslen == b->ni_esslen &&
+-              memcmp(a->ni_essid, b->ni_essid, a->ni_esslen) == 0);
++      return (memcmp(a->ni_bssid, b->ni_bssid, IEEE80211_ADDR_LEN) == 0);
+ }
+ /*
+@@ -596,8 +595,8 @@
+        * Check if old+new node have the same ssid in which
+        * case we can reassociate when operating in sta mode.
+        */
+-      canreassoc = ((obss != NULL) &&
+-              (vap->iv_state == IEEE80211_S_RUN) && ssid_equal(obss, selbs));
++      canreassoc = 0; /* ((obss != NULL) &&
++              (vap->iv_state == IEEE80211_S_RUN) && bssid_equal(obss, selbs)); */
+       vap->iv_bss = selbs;
+       IEEE80211_ADDR_COPY(vap->iv_bssid, selbs->ni_bssid);
+       if (obss != NULL)
diff --git a/package/madwifi/patches-r3776/325-sta_node_leave.patch b/package/madwifi/patches-r3776/325-sta_node_leave.patch
new file mode 100644 (file)
index 0000000..e1f51b6
--- /dev/null
@@ -0,0 +1,61 @@
+Drop stale AP nodes from the client list when disconnecting.
+Fixes some reassoc issues.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+Index: madwifi-trunk-r3776/net80211/ieee80211_proto.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_proto.c        2008-07-17 02:20:51.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_proto.c     2008-07-17 04:06:47.000000000 +0200
+@@ -1352,7 +1352,7 @@
+                               IEEE80211_SEND_MGMT(ni,
+                                       IEEE80211_FC0_SUBTYPE_DISASSOC,
+                                       IEEE80211_REASON_ASSOC_LEAVE);
+-                              ieee80211_sta_leave(ni);
++                              ieee80211_node_leave(ni);
+                               break;
+                       case IEEE80211_M_HOSTAP:
+                               ieee80211_iterate_nodes(&ic->ic_sta,
+@@ -1362,6 +1362,7 @@
+                               break;
+                       }
+                       goto reset;
++              case IEEE80211_S_AUTH:
+               case IEEE80211_S_ASSOC:
+                       switch (vap->iv_opmode) {
+                       case IEEE80211_M_STA:
+@@ -1380,7 +1381,6 @@
+               case IEEE80211_S_SCAN:
+                       ieee80211_cancel_scan(vap);
+                       goto reset;
+-              case IEEE80211_S_AUTH:
+               reset:
+                       ieee80211_reset_bss(vap);
+                       break;
+@@ -1436,7 +1436,7 @@
+                       break;
+               case IEEE80211_S_RUN:           /* beacon miss */
+                       if (vap->iv_opmode == IEEE80211_M_STA) {
+-                              ieee80211_sta_leave(ni);
++                              ieee80211_node_leave(ni);
+                               vap->iv_flags &= ~IEEE80211_F_SIBSS;    /* XXX */
+                               if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
+                                       ieee80211_check_scan(vap,
+@@ -1487,7 +1487,7 @@
+                               vap->iv_state = ostate; /* stay RUN */
+                               break;
+                       case IEEE80211_FC0_SUBTYPE_DEAUTH:
+-                              ieee80211_sta_leave(ni);
++                              ieee80211_node_leave(ni);
+                               if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
+                                       /* try to reauth */
+                                       IEEE80211_SEND_MGMT(ni,
+@@ -1514,7 +1514,7 @@
+                               IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
+                       break;
+               case IEEE80211_S_RUN:
+-                      ieee80211_sta_leave(ni);
++                      ieee80211_node_leave(ni);
+                       if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
+                               /* NB: caller specifies ASSOC/REASSOC by arg */
+                               IEEE80211_SEND_MGMT(ni, arg ?
diff --git a/package/madwifi/patches-r3776/326-bmiss_handling.patch b/package/madwifi/patches-r3776/326-bmiss_handling.patch
new file mode 100644 (file)
index 0000000..668c935
--- /dev/null
@@ -0,0 +1,108 @@
+Improve the beacon miss handling. Instead of just dropping the connection,
+send a directed probe request to the AP to see if it's still responding.
+Schedule a software beacon miss timer in this case, which adds a timeout
+for the APs probe response.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+Index: madwifi-trunk-r3776/net80211/ieee80211_input.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_input.c        2008-07-17 04:03:07.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_input.c     2008-07-17 04:06:33.000000000 +0200
+@@ -3369,12 +3369,17 @@
+                       }
+                       /* WDS/Repeater: re-schedule software beacon timer for 
+-                       * STA. */
+-                      if ((vap->iv_state == IEEE80211_S_RUN) &&
+-                          (vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS)) {
+-                              mod_timer(&vap->iv_swbmiss, 
++                       * STA. Reset consecutive bmiss counter as well */
++                      IEEE80211_LOCK_IRQ(ic);
++                      if (vap->iv_state == IEEE80211_S_RUN) {
++                              vap->iv_bmiss_count = 0;
++                              if (vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS)
++                                      mod_timer(&vap->iv_swbmiss,
+                                               jiffies + vap->iv_swbmiss_period);
++                              else
++                                      del_timer(&vap->iv_swbmiss);
+                       }
++                      IEEE80211_UNLOCK_IRQ(ic);
+                       /* If scanning, pass the info to the scan module.
+                        * Otherwise, check if it's the right time to do
+Index: madwifi-trunk-r3776/net80211/ieee80211_proto.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_proto.c        2008-07-17 04:06:18.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_proto.c     2008-07-17 04:06:33.000000000 +0200
+@@ -1213,6 +1213,8 @@
+       }
+       /* XXX locking */
+       TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
++              int count;
++
+               IEEE80211_DPRINTF(vap,
+                       IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
+                       "%s\n", "beacon miss");
+@@ -1225,6 +1227,29 @@
+               if (vap->iv_opmode != IEEE80211_M_STA ||
+                   vap->iv_state != IEEE80211_S_RUN)
+                       continue;
++
++              IEEE80211_LOCK_IRQ(ic);
++              count = vap->iv_bmiss_count++;
++              if (count) {
++                      /* if the counter was already above zero, reset it
++                       * here, since we're going to do the bmiss handling
++                       * in any case */
++                      vap->iv_bmiss_count = 0;
++              } else {
++                      /* schedule the software beacon miss timer, it will be
++                       * cancelled, if the probe request is acked */
++                      mod_timer(&vap->iv_swbmiss, jiffies + vap->iv_swbmiss_period);
++              }
++              IEEE80211_UNLOCK_IRQ(ic);
++
++              if (!count) {
++                      ieee80211_send_probereq(vap->iv_bss, vap->iv_myaddr,
++                              vap->iv_bss->ni_bssid, vap->iv_bss->ni_bssid,
++                              vap->iv_bss->ni_essid, vap->iv_bss->ni_esslen,
++                              NULL, 0);
++                      continue;
++              }
++
+               if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
+ #ifdef ATH_SUPERG_DYNTURBO
+                       /* 
+@@ -1621,14 +1646,14 @@
+               }
+               /* WDS/Repeater: Start software beacon timer for STA */
++              vap->iv_swbmiss.function = ieee80211_sta_swbmiss;
++              vap->iv_swbmiss.data = (unsigned long) vap;
++              vap->iv_swbmiss_period = IEEE80211_TU_TO_JIFFIES(
++                      vap->iv_ic->ic_bmissthreshold * ni->ni_intval);
++
+               if (ostate != IEEE80211_S_RUN &&
+                   (vap->iv_opmode == IEEE80211_M_STA &&
+                    vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS)) {
+-                      vap->iv_swbmiss.function = ieee80211_sta_swbmiss;
+-                      vap->iv_swbmiss.data = (unsigned long) vap;
+-                      vap->iv_swbmiss_period = IEEE80211_TU_TO_JIFFIES(
+-                              vap->iv_ic->ic_bmissthreshold * ni->ni_intval);
+-
+                       mod_timer(&vap->iv_swbmiss, jiffies + vap->iv_swbmiss_period);
+               }
+Index: madwifi-trunk-r3776/net80211/ieee80211_var.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_var.h  2008-07-17 04:03:07.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_var.h       2008-07-17 04:06:33.000000000 +0200
+@@ -292,6 +292,7 @@
+       struct timer_list iv_swbmiss;                   /* software beacon miss timer */
+       u_int16_t iv_swbmiss_period;                    /* software beacon miss timer period */
++      u_int16_t iv_bmiss_count;                       /* consecutive beacon miss counter */
+       struct ieee80211_nsparams iv_nsparams;          /* new state parameters for tasklet for stajoin1 */
+       struct IEEE80211_TQ_STRUCT iv_stajoin1tq;       /* tasklet for newstate action called from stajoin1tq */
+       unsigned int iv_nsdone;                         /* Done with scheduled newstate tasklet */
diff --git a/package/madwifi/patches-r3776/327-rssi_disconnect.patch b/package/madwifi/patches-r3776/327-rssi_disconnect.patch
new file mode 100644 (file)
index 0000000..1ce8e2a
--- /dev/null
@@ -0,0 +1,99 @@
+Add an optional threshold for low-rssi disconnection. This can be useful
+when letting wpa_supplicant control roaming.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+Index: madwifi-trunk-r3776/net80211/ieee80211_ioctl.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_ioctl.h        2008-07-17 04:03:30.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_ioctl.h     2008-07-17 04:07:29.000000000 +0200
+@@ -656,6 +656,8 @@
+       IEEE80211_PARAM_PROTMODE_RSSI           = 85,   /* RSSI Threshold for enabling protection mode */
+       IEEE80211_PARAM_PROTMODE_TIMEOUT        = 86,   /* Timeout for expiring protection mode */
+       IEEE80211_PARAM_BGSCAN_THRESH           = 87,   /* bg scan rssi threshold */
++      IEEE80211_PARAM_RSSI_DIS_THR    = 88,   /* rssi threshold for disconnection */
++      IEEE80211_PARAM_RSSI_DIS_COUNT  = 89,   /* counter for rssi threshold */
+ };
+ #define       SIOCG80211STATS                 (SIOCDEVPRIVATE+2)
+Index: madwifi-trunk-r3776/net80211/ieee80211_wireless.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_wireless.c     2008-07-17 04:03:07.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_wireless.c  2008-07-17 04:07:56.000000000 +0200
+@@ -2832,6 +2832,12 @@
+       case IEEE80211_PARAM_ROAM_RATE_11G:
+               vap->iv_roam.rate11g = value;
+               break;
++      case IEEE80211_PARAM_RSSI_DIS_THR:
++              vap->iv_rssi_dis_thr = value;
++              break;
++      case IEEE80211_PARAM_RSSI_DIS_COUNT:
++              vap->iv_rssi_dis_max = value;
++              break;
+       case IEEE80211_PARAM_UAPSDINFO:
+               if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
+                       if (ic->ic_caps & IEEE80211_C_UAPSD) {
+@@ -3220,6 +3226,12 @@
+       case IEEE80211_PARAM_ROAM_RATE_11G:
+               param[0] = vap->iv_roam.rate11g;
+               break;
++      case IEEE80211_PARAM_RSSI_DIS_THR:
++              param[0] = vap->iv_rssi_dis_thr;
++              break;
++      case IEEE80211_PARAM_RSSI_DIS_COUNT:
++              param[0] = vap->iv_rssi_dis_max;
++              break;
+       case IEEE80211_PARAM_UAPSDINFO:
+               if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
+                       if (IEEE80211_VAP_UAPSD_ENABLED(vap))
+@@ -5770,6 +5782,14 @@
+         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rate11g_x2" },
+       { IEEE80211_PARAM_ROAM_RATE_11G,
+         0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_rate11g_x2" },
++      { IEEE80211_PARAM_RSSI_DIS_THR,
++        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rssi_disthr" },
++      { IEEE80211_PARAM_RSSI_DIS_THR,
++        0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_rssi_disthr" },
++      { IEEE80211_PARAM_RSSI_DIS_COUNT,
++        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rssi_discnt" },
++      { IEEE80211_PARAM_RSSI_DIS_COUNT,
++        0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_rssi_discnt" },
+       { IEEE80211_PARAM_UAPSDINFO,
+         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "uapsd" },
+       { IEEE80211_PARAM_UAPSDINFO,
+Index: madwifi-trunk-r3776/net80211/ieee80211_input.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_input.c        2008-07-17 04:07:08.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_input.c     2008-07-17 04:09:03.000000000 +0200
+@@ -3234,6 +3234,17 @@
+                       /* When rssi is low, start doing bgscans more frequently to allow
+                        * the supplicant to make a better switching decision */
++                      if ((vap->iv_rssi_dis_thr > 0) && (vap->iv_rssi_dis_max > 0)) {
++                              if ((rssi > 0) && (rssi < vap->iv_rssi_dis_thr)) {
++                                      if (++vap->iv_rssi_dis_trig > vap->iv_rssi_dis_max) {
++                                              vap->iv_rssi_dis_trig = 0;
++                                              ieee80211_node_leave(ni);
++                                              return 0;
++                                      }
++                              } else {
++                                      vap->iv_rssi_dis_trig = 0;
++                              }
++                      }
+                       if ((rssi < vap->iv_bgscanthr) &&
+                                       (!vap->iv_bgscanthr_next ||
+                                               !time_before(jiffies, vap->iv_bgscanthr_next)) &&
+Index: madwifi-trunk-r3776/net80211/ieee80211_var.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_var.h  2008-07-17 04:07:08.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_var.h       2008-07-17 04:07:10.000000000 +0200
+@@ -233,6 +233,9 @@
+       u_int iv_bgscanintvl;                           /* bg scan min interval */
+       u_int iv_bgscanthr;                                     /* bg scan rssi threshold */
+       u_int iv_bgscantrintvl;                         /* bg scan trigger interval */
++      u_int iv_rssi_dis_thr;                          /* rssi disassoc threshold */
++      u_int iv_rssi_dis_max;                          /* max beacons below disconnect threshold */
++      u_int iv_rssi_dis_trig;                         /* rssi disassoc trigger count */
+       unsigned long iv_bgscanthr_next;                /* last trigger for bgscan */
+       u_int iv_scanvalid;                             /* scan cache valid threshold */
+       struct ieee80211_roam iv_roam;                  /* sta-mode roaming state */
diff --git a/package/madwifi/patches-r3776/328-memory_alloc.patch b/package/madwifi/patches-r3776/328-memory_alloc.patch
new file mode 100644 (file)
index 0000000..18d648c
--- /dev/null
@@ -0,0 +1,13 @@
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 04:00:42.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 04:11:45.000000000 +0200
+@@ -504,7 +504,7 @@
+       /* Allocate space for dynamically determined maximum VAP count */
+       sc->sc_bslot = 
+-              kzalloc(ath_maxvaps * sizeof(struct ieee80211vap), GFP_KERNEL);
++              kzalloc(ath_maxvaps * sizeof(struct ieee80211vap *), GFP_KERNEL);
+       /*
+        * Cache line size is used to size and align various
diff --git a/package/madwifi/patches-r3776/329-turbo_chansearch.patch b/package/madwifi/patches-r3776/329-turbo_chansearch.patch
new file mode 100644 (file)
index 0000000..2c718c0
--- /dev/null
@@ -0,0 +1,12 @@
+Index: madwifi-trunk-r3776/net80211/ieee80211.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211.c      2008-07-17 03:07:53.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211.c   2008-07-17 04:12:08.000000000 +0200
+@@ -695,6 +695,7 @@
+       int i;
+       /* Brute force search */
++      flags &= IEEE80211_CHAN_ALLTURBO;
+       for (i = 0; i < ic->ic_nchans; i++) {
+               c = &ic->ic_channels[i];
+               if (c->ic_freq == freq &&
diff --git a/package/madwifi/patches-r3776/330-bstuck_thresh.patch b/package/madwifi/patches-r3776/330-bstuck_thresh.patch
new file mode 100644 (file)
index 0000000..e2e502d
--- /dev/null
@@ -0,0 +1,54 @@
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c      2008-07-17 04:11:45.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c   2008-07-17 04:12:51.000000000 +0200
+@@ -354,6 +354,7 @@
+ static int ath_outdoor = AH_FALSE;            /* enable outdoor use */
+ static int ath_xchanmode = AH_TRUE;           /* enable extended channels */
+ static int ath_maxvaps = ATH_MAXVAPS_DEFAULT;   /* set default maximum vaps */
++static int bstuck_thresh = BSTUCK_THRESH;       /* Stuck beacon count required for reset */
+ static char *autocreate = "sta";
+ static char *ratectl = DEF_RATE_CTL;
+ static int rfkill = 0;
+@@ -397,6 +398,7 @@
+ #ifdef ATH_CAP_TPC
+ MODULE_PARM(hal_tpc, "i");
+ #endif
++MODULE_PARM(bstuck_thresh, "i");
+ MODULE_PARM(autocreate, "s");
+ MODULE_PARM(ratectl, "s");
+ #else
+@@ -410,6 +412,7 @@
+ #ifdef ATH_CAP_TPC
+ module_param(hal_tpc, int, 0600);
+ #endif
++module_param(bstuck_thresh, int, 0600);
+ module_param(autocreate, charp, 0600);
+ module_param(ratectl, charp, 0600);
+ #endif
+@@ -422,6 +425,7 @@
+ MODULE_PARM_DESC(hal_tpc, "Disables manual per-packet transmit power control and "
+               "lets this be managed by the HAL.  Default is OFF.");
+ #endif
++MODULE_PARM_DESC(bstuck_thresh, "Override default stuck beacon threshold");
+ MODULE_PARM_DESC(autocreate, "Create ath device in "
+               "[sta|ap|wds|adhoc|ahdemo|monitor] mode. defaults to sta, use "
+               "'none' to disable");
+@@ -5238,7 +5242,7 @@
+               DPRINTF(sc, ATH_DEBUG_BEACON_PROC,
+                       "Missed %u consecutive beacons (n_beacon=%u)\n",
+                       sc->sc_bmisscount, n_beacon);
+-              if (sc->sc_bmisscount > BSTUCK_THRESH)
++              if (sc->sc_bmisscount > bstuck_thresh)
+                       ATH_SCHEDULE_TQUEUE(&sc->sc_bstucktq, needmark);
+               return;
+       }
+@@ -5409,7 +5413,7 @@
+        *     check will be true, in which case return
+        *     without resetting the driver.
+        */
+-      if (sc->sc_bmisscount <= BSTUCK_THRESH)
++      if (sc->sc_bmisscount <= bstuck_thresh)
+               return;
+       EPRINTF(sc, "Stuck beacon; resetting (beacon miss count: %u)\n",
+               sc->sc_bmisscount);
diff --git a/package/madwifi/patches-r3776/331-linux24_fix.patch b/package/madwifi/patches-r3776/331-linux24_fix.patch
new file mode 100644 (file)
index 0000000..968f37d
--- /dev/null
@@ -0,0 +1,17 @@
+Index: madwifi-trunk-r3776/ath_hal/Makefile
+===================================================================
+--- madwifi-trunk-r3776.orig/ath_hal/Makefile  2008-07-17 00:21:30.000000000 +0200
++++ madwifi-trunk-r3776/ath_hal/Makefile       2008-07-17 04:13:34.000000000 +0200
+@@ -79,10 +79,11 @@
+ quiet_cmd_uudecode = UUDECODE $@
+       cmd_uudecode = $(obj)/uudecode -o $@ $<
+-$(obj)/$(TARGET).hal.o: $(HAL)/public/$(TARGET).hal.o.uu $(obj)/uudecode
+ ifdef LINUX24
++$(TARGET).hal.o: $(HAL)/public/$(TARGET).hal.o.uu $(obj)/uudecode
+       $(Q)$(obj)/uudecode -o $@ $<
+ else
++$(obj)/$(TARGET).hal.o: $(HAL)/public/$(TARGET).hal.o.uu $(obj)/uudecode
+       $(call if_changed,uudecode)
+ endif
+ # Replace as many hashed names as possible with meaningful
diff --git a/package/madwifi/patches-r3776/332-retransmit_check.patch b/package/madwifi/patches-r3776/332-retransmit_check.patch
new file mode 100644 (file)
index 0000000..2e2f919
--- /dev/null
@@ -0,0 +1,26 @@
+Index: madwifi-trunk-r3776/net80211/ieee80211.h
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211.h      2008-07-17 04:14:08.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211.h   2008-07-17 04:14:13.000000000 +0200
+@@ -174,8 +174,6 @@
+ #define       IEEE80211_SEQ_SEQ_MASK                  0xfff0
+ #define       IEEE80211_SEQ_SEQ_SHIFT                 4
+-#define       IEEE80211_SEQ_LEQ(a,b)  ((int)((a)-(b)) <= 0)
+-
+ #define       IEEE80211_NWID_LEN                      32
+ #define       IEEE80211_QOS_TXOP                      0x00ff
+Index: madwifi-trunk-r3776/net80211/ieee80211_input.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_input.c        2008-07-17 04:14:08.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_input.c     2008-07-17 04:14:13.000000000 +0200
+@@ -406,7 +406,7 @@
+                               tid = 0;
+                       rxseq = le16toh(*(__le16 *)wh->i_seq);
+                       if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
+-                          IEEE80211_SEQ_LEQ(rxseq, ni->ni_rxseqs[tid])) {
++                          (rxseq == ni->ni_rxseqs[tid])) {
+                               /* duplicate, discard */
+                               IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
+                                       bssid, "duplicate",