include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=madwifi
-PKG_VERSION:=0.9.2.1
+PKG_VERSION:=r2313-20070505
PKG_RELEASE:=1
-PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
-PKG_SOURCE_URL:=@SF/$(PKG_NAME)
-PKG_MD5SUM:=bf5509fccd3852e22551826063b1b61e
+PKG_SOURCE:=madwifi-ng-refcount-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://snapshots.madwifi.org/madwifi-ng-refcount
+PKG_MD5SUM:=01ee9dfb1f174be6e009f9697f7267b8
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/madwifi-ng-refcount-r2313-20070505
include $(INCLUDE_DIR)/package.mk
-RATE_CONTROL:=sample
+RATE_CONTROL:=minstrel
ifeq ($(ARCH),mips)
HAL_TARGET:=mips-be-elf
URL:=http://madwifi.org/
VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE)
FILES:= \
- $(PKG_BUILD_DIR)/ath/ath_hal.$(LINUX_KMOD_SUFFIX) \
+ $(PKG_BUILD_DIR)/ath_hal/ath_hal.$(LINUX_KMOD_SUFFIX) \
$(BUS_MODULES) \
$(PKG_BUILD_DIR)/ath_rate/$(RATE_CONTROL)/ath_rate_$(RATE_CONTROL).$(LINUX_KMOD_SUFFIX) \
$(PKG_BUILD_DIR)/net80211/wlan*.$(LINUX_KMOD_SUFFIX)
KERNELPATH="$(LINUX_DIR)" \
LDOPTS="--no-warn-mismatch " \
ATH_RATE="ath_rate/$(RATE_CONTROL)" \
- DOMULTI=1
+ WARNINGS="" \
+ DOMULTI=1 \
+ V=1
ifeq ($(findstring AHB,$(BUS)),AHB)
define Build/Compile/ahb
- $(MAKE) $(MADWIFI_MAKEOPTS) BUS="AHB" modules
+ COPTS="-DCONFIG_ATHEROS_RATE_DEFAULT='\"$(RATE_CONTROL)\"'" $(MAKE) $(MADWIFI_MAKEOPTS) BUS="AHB" modules
endef
endif
ifeq ($(findstring PCI,$(BUS)),PCI)
define Build/Compile/pci
- $(MAKE) $(MADWIFI_MAKEOPTS) BUS="PCI" modules
+ COPTS="-DCONFIG_ATHEROS_RATE_DEFAULT='\"$(RATE_CONTROL)\"'" $(MAKE) $(MADWIFI_MAKEOPTS) BUS="PCI" modules
endef
endif
-diff -Nur madwifi-0.9.2.1/hal/public/mips-be-elf.inc madwifi-0.9.2.1-owrt/hal/public/mips-be-elf.inc
---- madwifi-0.9.2.1/hal/public/mips-be-elf.inc 2006-05-27 04:48:16.000000000 +0200
-+++ madwifi-0.9.2.1-owrt/hal/public/mips-be-elf.inc 2007-03-11 19:50:19.000000000 +0100
+diff -urN madwifi-ng-refcount-r2313-20070505.old/hal/public/mips-be-elf.inc madwifi-ng-refcount-r2313-20070505.dev/hal/public/mips-be-elf.inc
+--- madwifi-ng-refcount-r2313-20070505.old/hal/public/mips-be-elf.inc 2006-05-27 04:48:16.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/hal/public/mips-be-elf.inc 2007-05-13 18:17:54.962213512 +0200
@@ -71,5 +71,5 @@
LDOPTS= -EB
-COPTS+= -G 0 -EB -mno-abicalls -fno-pic -mips2 -Wa,--trap \
+COPTS+= -G 0 -mno-abicalls -fno-pic -mips32 -Wa,--trap \
-fno-strict-aliasing -fno-common -fomit-frame-pointer -mlong-calls
-diff -Nur madwifi-0.9.2.1/hal/public/mips-le-elf.inc madwifi-0.9.2.1-owrt/hal/public/mips-le-elf.inc
---- madwifi-0.9.2.1/hal/public/mips-le-elf.inc 2006-05-27 04:48:16.000000000 +0200
-+++ madwifi-0.9.2.1-owrt/hal/public/mips-le-elf.inc 2007-03-11 19:50:19.000000000 +0100
+diff -urN madwifi-ng-refcount-r2313-20070505.old/hal/public/mips-le-elf.inc madwifi-ng-refcount-r2313-20070505.dev/hal/public/mips-le-elf.inc
+--- madwifi-ng-refcount-r2313-20070505.old/hal/public/mips-le-elf.inc 2006-05-27 04:48:16.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/hal/public/mips-le-elf.inc 2007-05-13 18:17:54.963213360 +0200
@@ -68,5 +68,5 @@
LDOPTS= -EL
-COPTS+= -G 0 -EL -mno-abicalls -fno-pic -mips2 -Wa,--trap \
+COPTS+= -G 0 -mno-abicalls -fno-pic -mips32 -Wa,--trap \
-fno-strict-aliasing -fno-common -fomit-frame-pointer -mlong-calls
-diff -Nur madwifi-0.9.2.1/hal/public/xscale-be-elf.inc madwifi-0.9.2.1-owrt/hal/public/xscale-be-elf.inc
---- madwifi-0.9.2.1/hal/public/xscale-be-elf.inc 2006-05-27 04:48:16.000000000 +0200
-+++ madwifi-0.9.2.1-owrt/hal/public/xscale-be-elf.inc 2007-03-11 19:50:19.000000000 +0100
-@@ -77,5 +77,5 @@
-
- LDOPTS= -EB
- COPTS+= -DAH_BYTE_ORDER=AH_BIG_ENDIAN
--COPTS+= -march=armv4 -mbig-endian -fno-strict-aliasing -fno-common -mapcs-32 \
-+COPTS+= -march=armv5te -mtune=xscale -mbig-endian -fno-strict-aliasing -fno-common \
- -mtune=xscale -mshort-load-bytes -msoft-float -mfp=2
-diff -Nur madwifi-0.9.2.1/hal/public/xscale-le-elf.inc madwifi-0.9.2.1-owrt/hal/public/xscale-le-elf.inc
---- madwifi-0.9.2.1/hal/public/xscale-le-elf.inc 2006-05-27 04:48:16.000000000 +0200
-+++ madwifi-0.9.2.1-owrt/hal/public/xscale-le-elf.inc 2007-03-11 19:53:53.000000000 +0100
-@@ -78,5 +78,5 @@
-
- LDOPTS= -EL
- COPTS+= -DAH_BYTE_ORDER=AH_LITTLE_ENDIAN
--COPTS+= -march=armv4 -mlittle-endian -fno-strict-aliasing -fno-common \
-- -mapcs-32 -mtune=xscale -mshort-load-bytes -msoft-float -mfp=2
-+COPTS+= -march=armv5te -mtune=xscale -mlittle-endian -fno-strict-aliasing -fno-common \
-+ -mshort-load-bytes
-diff -Nur madwifi-0.9.2.1/Makefile madwifi-0.9.2.1-owrt/Makefile
---- madwifi-0.9.2.1/Makefile 2006-07-14 07:15:56.000000000 +0200
-+++ madwifi-0.9.2.1-owrt/Makefile 2007-03-11 19:50:19.000000000 +0100
-@@ -54,7 +54,7 @@
+diff -urN madwifi-ng-refcount-r2313-20070505.old/Makefile madwifi-ng-refcount-r2313-20070505.dev/Makefile
+--- madwifi-ng-refcount-r2313-20070505.old/Makefile 2007-03-08 20:59:06.000000000 +0100
++++ madwifi-ng-refcount-r2313-20070505.dev/Makefile 2007-05-13 18:17:54.963213360 +0200
+@@ -56,7 +56,7 @@
all: modules tools
--- /dev/null
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath_hal/ah_os.h madwifi-ng-refcount-r2313-20070505.dev/ath_hal/ah_os.h
+--- madwifi-ng-refcount-r2313-20070505.old/ath_hal/ah_os.h 2007-05-04 02:10:06.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/ath_hal/ah_os.h 2007-05-13 18:17:55.040201656 +0200
+@@ -149,7 +149,7 @@
+ (0x4000 <= (_reg) && (_reg) < 0x5000) ? \
+ writel((_val), (_ah)->ah_sh + (_reg)) : \
+ ({__raw_writel((_val), (_ah)->ah_sh + (_reg)); \
+- mb(); });
++ mb(); }); \
+ } while (0)
+ #define _OS_REG_READ(_ah, _reg) \
+ ((0x4000 <= (_reg) && (_reg) < 0x5000) ? \
+++ /dev/null
---- madwifi.old/Makefile.inc 2006-07-14 07:15:56.000000000 +0200
-+++ madwifi.dev/Makefile.inc 2006-08-30 05:20:27.000000000 +0200
-@@ -181,7 +181,7 @@
- #
- TOOLS= $(DEPTH)/tools
-
--COPTS+= -Werror
-+# COPTS+= -Werror
- INCS= -include $(obj)/$(DEPTH)/include/compat.h -I$(obj)/$(DEPTH)/include
-
- ifeq ($(strip $(BUS)),AHB)
-diff -urN madwifi-0.9.2.old/tools/80211debug.c madwifi-0.9.2.dev/tools/80211debug.c
---- madwifi-0.9.2.old/tools/80211debug.c 2006-03-10 14:23:50.000000000 +0100
-+++ madwifi-0.9.2.dev/tools/80211debug.c 2006-08-29 17:49:50.000000000 +0200
+diff -urN madwifi-ng-refcount-r2313-20070505.old/tools/80211debug.c madwifi-ng-refcount-r2313-20070505.dev/tools/80211debug.c
+--- madwifi-ng-refcount-r2313-20070505.old/tools/80211debug.c 2006-12-08 18:20:08.000000000 +0100
++++ madwifi-ng-refcount-r2313-20070505.dev/tools/80211debug.c 2007-05-13 18:17:55.115190256 +0200
@@ -49,6 +49,10 @@
#include <getopt.h>
#include <err.h>
const char *ifname = "ath0";
const char *cp, *tp;
const char *sep;
-diff -urN madwifi-0.9.2.old/tools/80211stats.c madwifi-0.9.2.dev/tools/80211stats.c
---- madwifi-0.9.2.old/tools/80211stats.c 2006-05-27 08:21:18.000000000 +0200
-+++ madwifi-0.9.2.dev/tools/80211stats.c 2006-08-29 17:49:50.000000000 +0200
-@@ -58,6 +58,10 @@
+diff -urN madwifi-ng-refcount-r2313-20070505.old/tools/80211stats.c madwifi-ng-refcount-r2313-20070505.dev/tools/80211stats.c
+--- madwifi-ng-refcount-r2313-20070505.old/tools/80211stats.c 2007-02-07 22:06:25.000000000 +0100
++++ madwifi-ng-refcount-r2313-20070505.dev/tools/80211stats.c 2007-05-13 18:17:55.116190104 +0200
+@@ -60,6 +60,10 @@
#include "net80211/ieee80211_crypto.h"
#include "net80211/ieee80211_ioctl.h"
#ifndef SIOCG80211STATS
#define SIOCG80211STATS (SIOCDEVPRIVATE + 2)
#endif
-@@ -241,9 +245,19 @@
+@@ -243,9 +247,19 @@
#undef STAT
}
int c, len;
struct ieee80211req_sta_info *si;
u_int8_t buf[24*1024], *cp;
-diff -urN madwifi-0.9.2.old/tools/athchans.c madwifi-0.9.2.dev/tools/athchans.c
---- madwifi-0.9.2.old/tools/athchans.c 2006-02-01 21:07:11.000000000 +0100
-+++ madwifi-0.9.2.dev/tools/athchans.c 2006-08-29 17:49:50.000000000 +0200
-@@ -57,6 +57,10 @@
+diff -urN madwifi-ng-refcount-r2313-20070505.old/tools/athchans.c madwifi-ng-refcount-r2313-20070505.dev/tools/athchans.c
+--- madwifi-ng-refcount-r2313-20070505.old/tools/athchans.c 2007-02-07 22:06:25.000000000 +0100
++++ madwifi-ng-refcount-r2313-20070505.dev/tools/athchans.c 2007-05-13 18:17:55.116190104 +0200
+@@ -59,6 +59,10 @@
#include "net80211/ieee80211_crypto.h"
#include "net80211/ieee80211_ioctl.h"
static int s = -1;
const char *progname;
-@@ -134,9 +138,20 @@
+@@ -136,9 +140,20 @@
}
#define MAXCHAN ((int)(sizeof(struct ieee80211req_chanlist) * NBBY))
const char *ifname = "wifi0";
struct ieee80211req_chanlist chanlist;
int c;
-diff -urN madwifi-0.9.2.old/tools/athctrl.c madwifi-0.9.2.dev/tools/athctrl.c
---- madwifi-0.9.2.old/tools/athctrl.c 2006-02-03 13:03:03.000000000 +0100
-+++ madwifi-0.9.2.dev/tools/athctrl.c 2006-08-29 17:49:50.000000000 +0200
+diff -urN madwifi-ng-refcount-r2313-20070505.old/tools/athctrl.c madwifi-ng-refcount-r2313-20070505.dev/tools/athctrl.c
+--- madwifi-ng-refcount-r2313-20070505.old/tools/athctrl.c 2006-02-03 13:03:03.000000000 +0100
++++ madwifi-ng-refcount-r2313-20070505.dev/tools/athctrl.c 2007-05-13 18:17:55.117189952 +0200
@@ -53,6 +53,10 @@
#include <net/if.h>
char device[IFNAMSIZ + 1];
int distance = -1;
int c;
-diff -urN madwifi-0.9.2.old/tools/athdebug.c madwifi-0.9.2.dev/tools/athdebug.c
---- madwifi-0.9.2.old/tools/athdebug.c 2006-05-05 06:17:59.000000000 +0200
-+++ madwifi-0.9.2.dev/tools/athdebug.c 2006-08-29 17:49:50.000000000 +0200
+diff -urN madwifi-ng-refcount-r2313-20070505.old/tools/athdebug.c madwifi-ng-refcount-r2313-20070505.dev/tools/athdebug.c
+--- madwifi-ng-refcount-r2313-20070505.old/tools/athdebug.c 2006-12-08 18:20:08.000000000 +0100
++++ madwifi-ng-refcount-r2313-20070505.dev/tools/athdebug.c 2007-05-13 18:17:55.117189952 +0200
@@ -52,6 +52,10 @@
#include <getopt.h>
#include <err.h>
#ifdef __linux__
const char *ifname = "wifi0";
#else
-diff -urN madwifi-0.9.2.old/tools/athkey.c madwifi-0.9.2.dev/tools/athkey.c
---- madwifi-0.9.2.old/tools/athkey.c 2006-02-01 21:07:11.000000000 +0100
-+++ madwifi-0.9.2.dev/tools/athkey.c 2006-08-29 17:49:50.000000000 +0200
-@@ -57,6 +57,10 @@
+diff -urN madwifi-ng-refcount-r2313-20070505.old/tools/athkey.c madwifi-ng-refcount-r2313-20070505.dev/tools/athkey.c
+--- madwifi-ng-refcount-r2313-20070505.old/tools/athkey.c 2007-02-07 22:06:25.000000000 +0100
++++ madwifi-ng-refcount-r2313-20070505.dev/tools/athkey.c 2007-05-13 18:17:55.117189952 +0200
+@@ -59,6 +59,10 @@
#include "net80211/ieee80211_crypto.h"
#include "net80211/ieee80211_ioctl.h"
static int s = -1;
const char *progname;
-@@ -207,9 +211,19 @@
+@@ -209,9 +213,19 @@
exit(-1);
}
const char *ifname = "wifi0";
struct ieee80211req_key setkey;
struct ieee80211req_del_key delkey;
-diff -urN madwifi-0.9.2.old/tools/athstats.c madwifi-0.9.2.dev/tools/athstats.c
---- madwifi-0.9.2.old/tools/athstats.c 2006-05-05 06:20:50.000000000 +0200
-+++ madwifi-0.9.2.dev/tools/athstats.c 2006-08-29 17:49:50.000000000 +0200
-@@ -64,6 +64,10 @@
- #include "ah_desc.h"
+diff -urN madwifi-ng-refcount-r2313-20070505.old/tools/athstats.c madwifi-ng-refcount-r2313-20070505.dev/tools/athstats.c
+--- madwifi-ng-refcount-r2313-20070505.old/tools/athstats.c 2007-04-04 23:25:20.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/tools/athstats.c 2007-05-13 18:17:55.118189800 +0200
+@@ -63,6 +63,10 @@
+ #include "wireless_copy.h"
#include "if_athioctl.h"
+#ifdef DOMULTI
static const struct {
u_int phyerr;
const char* desc;
-@@ -227,9 +231,20 @@
+@@ -226,9 +230,20 @@
signalled = 1;
}
#ifdef __linux__
const char *ifname = "wifi0";
#else
-diff -urN madwifi-0.9.2.old/tools/do_multi.c madwifi-0.9.2.dev/tools/do_multi.c
---- madwifi-0.9.2.old/tools/do_multi.c 1970-01-01 01:00:00.000000000 +0100
-+++ madwifi-0.9.2.dev/tools/do_multi.c 2006-08-29 17:49:50.000000000 +0200
+diff -urN madwifi-ng-refcount-r2313-20070505.old/tools/do_multi.c madwifi-ng-refcount-r2313-20070505.dev/tools/do_multi.c
+--- madwifi-ng-refcount-r2313-20070505.old/tools/do_multi.c 1970-01-01 01:00:00.000000000 +0100
++++ madwifi-ng-refcount-r2313-20070505.dev/tools/do_multi.c 2007-05-13 18:17:55.118189800 +0200
@@ -0,0 +1,30 @@
+#include <string.h>
+#include "do_multi.h"
+
+ return ret;
+}
-diff -urN madwifi-0.9.2.old/tools/do_multi.h madwifi-0.9.2.dev/tools/do_multi.h
---- madwifi-0.9.2.old/tools/do_multi.h 1970-01-01 01:00:00.000000000 +0100
-+++ madwifi-0.9.2.dev/tools/do_multi.h 2006-08-29 17:49:50.000000000 +0200
+diff -urN madwifi-ng-refcount-r2313-20070505.old/tools/do_multi.h madwifi-ng-refcount-r2313-20070505.dev/tools/do_multi.h
+--- madwifi-ng-refcount-r2313-20070505.old/tools/do_multi.h 1970-01-01 01:00:00.000000000 +0100
++++ madwifi-ng-refcount-r2313-20070505.dev/tools/do_multi.h 2007-05-13 18:17:55.118189800 +0200
@@ -0,0 +1,9 @@
+
+int a80211debug_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[]);
-diff -urN madwifi-0.9.2.old/tools/Makefile madwifi-0.9.2.dev/tools/Makefile
---- madwifi-0.9.2.old/tools/Makefile 2006-07-14 07:15:56.000000000 +0200
-+++ madwifi-0.9.2.dev/tools/Makefile 2006-08-29 17:49:50.000000000 +0200
+diff -urN madwifi-ng-refcount-r2313-20070505.old/tools/Makefile madwifi-ng-refcount-r2313-20070505.dev/tools/Makefile
+--- madwifi-ng-refcount-r2313-20070505.old/tools/Makefile 2007-04-04 23:25:20.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/tools/Makefile 2007-05-13 18:17:55.119189648 +0200
@@ -49,6 +49,12 @@
ALL= athstats 80211stats athkey athchans athctrl \
+ done
+
athstats: athstats.c
- $(CC) -o athstats $(ALL_CFLAGS) -I../ath $(LDFLAGS) athstats.c
+ $(CC) -o athstats $(ALL_CFLAGS) -I$(TOP)/ath $(LDFLAGS) athstats.c
80211stats: 80211stats.c
-diff -urN madwifi-0.9.2.old/tools/wlanconfig.c madwifi-0.9.2.dev/tools/wlanconfig.c
---- madwifi-0.9.2.old/tools/wlanconfig.c 2006-05-14 09:17:29.000000000 +0200
-+++ madwifi-0.9.2.dev/tools/wlanconfig.c 2006-08-29 17:49:50.000000000 +0200
-@@ -60,6 +60,10 @@
+diff -urN madwifi-ng-refcount-r2313-20070505.old/tools/wlanconfig.c madwifi-ng-refcount-r2313-20070505.dev/tools/wlanconfig.c
+--- madwifi-ng-refcount-r2313-20070505.old/tools/wlanconfig.c 2007-05-04 02:10:06.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/tools/wlanconfig.c 2007-05-13 18:17:55.119189648 +0200
+@@ -62,6 +62,10 @@
#include "net80211/ieee80211_crypto.h"
#include "net80211/ieee80211_ioctl.h"
-diff -urN madwifi-0.9.2.old/ath/if_ath.c madwifi-0.9.2.dev/ath/if_ath.c
---- madwifi-0.9.2.old/ath/if_ath.c 2006-07-08 08:47:19.000000000 +0200
-+++ madwifi-0.9.2.dev/ath/if_ath.c 2006-08-29 17:49:50.000000000 +0200
-@@ -251,7 +251,7 @@
- static int ath_outdoor = AH_FALSE; /* enable outdoor use */
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c
+--- madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c 2007-05-04 23:09:29.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c 2007-05-13 18:17:55.201177184 +0200
+@@ -260,7 +260,7 @@
static int ath_xchanmode = AH_TRUE; /* enable extended channels */
static char *autocreate = NULL;
+ static char *ratectl = DEF_RATE_CTL;
-static int rfkill = -1;
+static int rfkill = 0;
static int countrycode = -1;
-diff -urN madwifi-0.9.2.old/ath/if_ath.c madwifi-0.9.2.dev/ath/if_ath.c
---- madwifi-0.9.2.old/ath/if_ath.c 2006-08-29 17:49:50.000000000 +0200
-+++ madwifi-0.9.2.dev/ath/if_ath.c 2006-08-29 17:49:50.000000000 +0200
-@@ -387,7 +387,7 @@
- struct ath_hal *ah;
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c
+--- madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c 2007-05-13 18:17:55.278165480 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c 2007-05-13 18:17:55.287164112 +0200
+@@ -401,7 +401,7 @@
HAL_STATUS status;
- int error = 0, i;
+ int error = 0;
+ unsigned int i;
- int autocreatemode = IEEE80211_M_STA;
+ int autocreatemode = -1;
u_int8_t csz;
--- /dev/null
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_rate.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_rate.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_rate.c 2007-04-04 23:25:20.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_rate.c 2007-05-13 18:17:55.368151800 +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);
+++ /dev/null
-The fix for CVE-2006-6332 in r1842 was not entirely correct. In
-encode_ie() the bound check did not consider that each byte from
-the IE causes two bytes to be written into buffer. That could
-lead to a kernel oops, but does not allow code injection. This is
-now fixed.
-
-Due to the type of this problem it does not trigger another
-urgent security bugfix release. v0.9.3 is at the door anyway.
-
-Reported-by: Joachim Gleisner <jg@suse.de>
-
-Index: trunk/net80211/ieee80211_wireless.c
-===================================================================
---- trunk/net80211/ieee80211_wireless.c (revision 1846)
-+++ trunk/net80211/ieee80211_wireless.c (revision 1847)
-@@ -1566,8 +1566,8 @@
- bufsize -= leader_len;
- p += leader_len;
-- if (bufsize < ielen)
-- return 0;
-- for (i = 0; i < ielen && bufsize > 2; i++)
-+ for (i = 0; i < ielen && bufsize > 2; i++) {
- p += sprintf(p, "%02x", ie[i]);
-+ bufsize -= 2;
-+ }
- return (i == ielen ? p - (u_int8_t *)buf : 0);
- }
+++ /dev/null
-Index: trunk/ath/if_ath.c
-===================================================================
---- trunk/ath/if_ath.c (revision 1751)
-+++ trunk/ath/if_ath.c (revision 1752)
-@@ -1600,5 +1600,9 @@
- */
- irqreturn_t
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
-+ath_intr(int irq, void *dev_id)
-+#else
- ath_intr(int irq, void *dev_id, struct pt_regs *regs)
-+#endif
- {
- struct net_device *dev = dev_id;
-Index: trunk/ath/if_athvar.h
-===================================================================
---- trunk/ath/if_athvar.h (revision 1726)
-+++ trunk/ath/if_athvar.h (revision 1752)
-@@ -727,5 +727,9 @@
- void ath_suspend(struct net_device *);
- void ath_shutdown(struct net_device *);
--irqreturn_t ath_intr(int, void *, struct pt_regs *);
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
-+irqreturn_t ath_intr(int, void *);
-+#else
-+irqreturn_t ath_intr(int, void *, struct pt_regs *regs);
-+#endif
- int ath_ioctl_ethtool(struct ath_softc *, int, void __user *);
- void bus_read_cachesize(struct ath_softc *, u_int8_t *);
--- /dev/null
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath_rate/minstrel/minstrel.c madwifi-ng-refcount-r2313-20070505.dev/ath_rate/minstrel/minstrel.c
+--- madwifi-ng-refcount-r2313-20070505.old/ath_rate/minstrel/minstrel.c 2007-04-25 22:29:55.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/ath_rate/minstrel/minstrel.c 2007-05-13 18:17:55.533126720 +0200
+@@ -543,6 +543,9 @@
+ unsigned int i, column_index;
+ int newIndex;
+ u_int8_t random_bytes[12];
++
++ if (num_sample_rates < 0)
++ return;
+
+ for(column_index = 0; column_index < MINSTREL_COLUMNS; column_index++) {
+ for (i = 0; i <= IEEE80211_RATE_MAXSIZE; i++)
+++ /dev/null
---- madwifi-0.9.2/hal/linux/ah_osdep.c.orig 2006-12-04 23:37:56.000000000 +0100
-+++ madwifi-0.9.2/hal/linux/ah_osdep.c 2006-12-04 23:38:06.000000000 +0100
-@@ -41,7 +41,7 @@
- #define EXPORT_SYMTAB
- #endif
-
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/init.h>
---- madwifi-0.9.2/ath/if_ath.c.orig 2006-12-04 23:42:57.000000000 +0100
-+++ madwifi-0.9.2/ath/if_ath.c 2006-12-04 23:43:09.000000000 +0100
-@@ -44,7 +44,7 @@
- */
- #include "opt_ah.h"
-
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/init.h>
---- madwifi-0.9.2/ath/if_ath_pci.c.orig 2006-12-04 23:44:55.000000000 +0100
-+++ madwifi-0.9.2/ath/if_ath_pci.c 2006-12-04 23:46:03.000000000 +0100
-@@ -42,7 +42,7 @@
- #define EXPORT_SYMTAB
- #endif
-
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/init.h>
---- madwifi-0.9.2/ath_rate/sample/sample.c.orig 2006-12-04 23:50:56.000000000 +0100
-+++ madwifi-0.9.2/ath_rate/sample/sample.c 2006-12-04 23:51:11.000000000 +0100
-@@ -41,7 +41,7 @@
- * John Bicket's SampleRate control algorithm.
- */
-
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/init.h>
-diff -urN madwifi-0.9.2.orig/ath/if_ath_ahb.c madwifi-0.9.2/ath/if_ath_ahb.c
---- madwifi-0.9.2.orig/ath/if_ath_ahb.c 2006-05-22 06:39:55.000000000 +0200
-+++ madwifi-0.9.2/ath/if_ath_ahb.c 2006-12-04 23:56:43.000000000 +0100
-@@ -10,7 +10,7 @@
- #define EXPORT_SYMTAB
- #endif
-
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/init.h>
-diff -urN madwifi-0.9.2.orig/ath_rate/amrr/amrr.c madwifi-0.9.2/ath_rate/amrr/amrr.c
---- madwifi-0.9.2.orig/ath_rate/amrr/amrr.c 2006-07-04 12:23:35.000000000 +0200
-+++ madwifi-0.9.2/ath_rate/amrr/amrr.c 2006-12-04 23:56:43.000000000 +0100
-@@ -43,7 +43,7 @@
- * "IEEE 802.11 Rate Adaptation: A Practical Approach" by
- * Mathieu Lacage, Hossein Manshaei, Thierry Turletti
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/init.h>
-diff -urN madwifi-0.9.2.orig/ath_rate/onoe/onoe.c madwifi-0.9.2/ath_rate/onoe/onoe.c
---- madwifi-0.9.2.orig/ath_rate/onoe/onoe.c 2006-07-04 12:23:35.000000000 +0200
-+++ madwifi-0.9.2/ath_rate/onoe/onoe.c 2006-12-04 23:56:43.000000000 +0100
-@@ -39,7 +39,7 @@
- /*
- * Atsushi Onoe's rate control algorithm.
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/init.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211_acl.c madwifi-0.9.2/net80211/ieee80211_acl.c
---- madwifi-0.9.2.orig/net80211/ieee80211_acl.c 2006-05-31 23:05:08.000000000 +0200
-+++ madwifi-0.9.2/net80211/ieee80211_acl.c 2006-12-04 23:56:49.000000000 +0100
-@@ -45,7 +45,7 @@
- * and if found the frame is either accepted (ACL_POLICY_ALLOW)
- * or rejected (ACL_POLICY_DENT).
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/skbuff.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211_beacon.c madwifi-0.9.2/net80211/ieee80211_beacon.c
---- madwifi-0.9.2.orig/net80211/ieee80211_beacon.c 2006-05-19 22:42:19.000000000 +0200
-+++ madwifi-0.9.2/net80211/ieee80211_beacon.c 2006-12-04 23:56:49.000000000 +0100
-@@ -38,7 +38,7 @@
- /*
- * IEEE 802.11 beacon handling routines
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/skbuff.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211.c madwifi-0.9.2/net80211/ieee80211.c
---- madwifi-0.9.2.orig/net80211/ieee80211.c 2006-07-04 12:22:11.000000000 +0200
-+++ madwifi-0.9.2/net80211/ieee80211.c 2006-12-04 23:56:49.000000000 +0100
-@@ -38,7 +38,7 @@
- /*
- * IEEE 802.11 generic handler
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/skbuff.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211_crypto.c madwifi-0.9.2/net80211/ieee80211_crypto.c
---- madwifi-0.9.2.orig/net80211/ieee80211_crypto.c 2006-02-01 21:07:11.000000000 +0100
-+++ madwifi-0.9.2/net80211/ieee80211_crypto.c 2006-12-04 23:56:49.000000000 +0100
-@@ -38,7 +38,7 @@
- /*
- * IEEE 802.11 generic crypto support.
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/kmod.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211_crypto_ccmp.c madwifi-0.9.2/net80211/ieee80211_crypto_ccmp.c
---- madwifi-0.9.2.orig/net80211/ieee80211_crypto_ccmp.c 2006-06-13 16:09:51.000000000 +0200
-+++ madwifi-0.9.2/net80211/ieee80211_crypto_ccmp.c 2006-12-04 23:56:49.000000000 +0100
-@@ -38,7 +38,7 @@
- * AP driver. The code is used with the consent of the author and
- * it's license is included below.
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/skbuff.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211_crypto_none.c madwifi-0.9.2/net80211/ieee80211_crypto_none.c
---- madwifi-0.9.2.orig/net80211/ieee80211_crypto_none.c 2006-02-01 21:07:11.000000000 +0100
-+++ madwifi-0.9.2/net80211/ieee80211_crypto_none.c 2006-12-04 23:56:49.000000000 +0100
-@@ -34,7 +34,7 @@
- /*
- * IEEE 802.11 NULL crypto support.
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/skbuff.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211_crypto_tkip.c madwifi-0.9.2/net80211/ieee80211_crypto_tkip.c
---- madwifi-0.9.2.orig/net80211/ieee80211_crypto_tkip.c 2006-02-01 21:07:11.000000000 +0100
-+++ madwifi-0.9.2/net80211/ieee80211_crypto_tkip.c 2006-12-04 23:56:49.000000000 +0100
-@@ -38,7 +38,7 @@
- * AP driver. The code is used with the consent of the author and
- * it's license is included below.
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/skbuff.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211_crypto_wep.c madwifi-0.9.2/net80211/ieee80211_crypto_wep.c
---- madwifi-0.9.2.orig/net80211/ieee80211_crypto_wep.c 2006-02-06 21:20:57.000000000 +0100
-+++ madwifi-0.9.2/net80211/ieee80211_crypto_wep.c 2006-12-04 23:56:49.000000000 +0100
-@@ -34,7 +34,7 @@
- /*
- * IEEE 802.11 WEP crypto support.
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/skbuff.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211_input.c madwifi-0.9.2/net80211/ieee80211_input.c
---- madwifi-0.9.2.orig/net80211/ieee80211_input.c 2006-07-06 05:23:08.000000000 +0200
-+++ madwifi-0.9.2/net80211/ieee80211_input.c 2006-12-04 23:56:50.000000000 +0100
-@@ -38,7 +38,7 @@
- /*
- * IEEE 802.11 input handling.
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/skbuff.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211_linux.c madwifi-0.9.2/net80211/ieee80211_linux.c
---- madwifi-0.9.2.orig/net80211/ieee80211_linux.c 2006-07-21 10:59:10.000000000 +0200
-+++ madwifi-0.9.2/net80211/ieee80211_linux.c 2006-12-04 23:56:49.000000000 +0100
-@@ -33,7 +33,7 @@
- /*
- * IEEE 802.11 support (Linux-specific code)
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/kmod.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211_monitor.c madwifi-0.9.2/net80211/ieee80211_monitor.c
---- madwifi-0.9.2.orig/net80211/ieee80211_monitor.c 2006-04-21 18:57:59.000000000 +0200
-+++ madwifi-0.9.2/net80211/ieee80211_monitor.c 2006-12-04 23:56:49.000000000 +0100
-@@ -34,7 +34,7 @@
- /*
- * IEEE 802.11 monitor mode
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/kmod.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211_node.c madwifi-0.9.2/net80211/ieee80211_node.c
---- madwifi-0.9.2.orig/net80211/ieee80211_node.c 2006-06-13 10:50:37.000000000 +0200
-+++ madwifi-0.9.2/net80211/ieee80211_node.c 2006-12-04 23:56:49.000000000 +0100
-@@ -38,7 +38,7 @@
- /*
- * IEEE 802.11 node handling support.
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/skbuff.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211_output.c madwifi-0.9.2/net80211/ieee80211_output.c
---- madwifi-0.9.2.orig/net80211/ieee80211_output.c 2006-06-10 04:17:05.000000000 +0200
-+++ madwifi-0.9.2/net80211/ieee80211_output.c 2006-12-04 23:56:49.000000000 +0100
-@@ -38,7 +38,7 @@
- /*
- * IEEE 802.11 output handling.
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/skbuff.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211_power.c madwifi-0.9.2/net80211/ieee80211_power.c
---- madwifi-0.9.2.orig/net80211/ieee80211_power.c 2006-06-10 04:17:05.000000000 +0200
-+++ madwifi-0.9.2/net80211/ieee80211_power.c 2006-12-04 23:56:49.000000000 +0100
-@@ -38,7 +38,7 @@
- /*
- * IEEE 802.11 power save support.
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/skbuff.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211_proto.c madwifi-0.9.2/net80211/ieee80211_proto.c
---- madwifi-0.9.2.orig/net80211/ieee80211_proto.c 2006-06-09 22:41:19.000000000 +0200
-+++ madwifi-0.9.2/net80211/ieee80211_proto.c 2006-12-04 23:56:49.000000000 +0100
-@@ -38,7 +38,7 @@
- /*
- * IEEE 802.11 protocol support.
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/kmod.h>
- #include <linux/module.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211_scan_ap.c madwifi-0.9.2/net80211/ieee80211_scan_ap.c
---- madwifi-0.9.2.orig/net80211/ieee80211_scan_ap.c 2006-02-01 21:07:11.000000000 +0100
-+++ madwifi-0.9.2/net80211/ieee80211_scan_ap.c 2006-12-04 23:56:49.000000000 +0100
-@@ -37,7 +37,7 @@
- /*
- * IEEE 802.11 ap scanning support.
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/skbuff.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211_scan.c madwifi-0.9.2/net80211/ieee80211_scan.c
---- madwifi-0.9.2.orig/net80211/ieee80211_scan.c 2006-04-21 18:57:59.000000000 +0200
-+++ madwifi-0.9.2/net80211/ieee80211_scan.c 2006-12-04 23:56:49.000000000 +0100
-@@ -37,7 +37,7 @@
- /*
- * IEEE 802.11 scanning support.
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/skbuff.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211_scan_sta.c madwifi-0.9.2/net80211/ieee80211_scan_sta.c
---- madwifi-0.9.2.orig/net80211/ieee80211_scan_sta.c 2006-07-02 09:19:37.000000000 +0200
-+++ madwifi-0.9.2/net80211/ieee80211_scan_sta.c 2006-12-04 23:56:49.000000000 +0100
-@@ -37,7 +37,7 @@
- /*
- * IEEE 802.11 station scanning support.
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/skbuff.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211_wireless.c madwifi-0.9.2/net80211/ieee80211_wireless.c
---- madwifi-0.9.2.orig/net80211/ieee80211_wireless.c 2006-07-06 05:23:08.000000000 +0200
-+++ madwifi-0.9.2/net80211/ieee80211_wireless.c 2006-12-04 23:56:49.000000000 +0100
-@@ -39,7 +39,7 @@
- /*
- * Wireless extensions support for 802.11 common code.
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
-
- #ifdef CONFIG_NET_WIRELESS
- #include <linux/version.h>
-diff -urN madwifi-0.9.2.orig/net80211/ieee80211_xauth.c madwifi-0.9.2/net80211/ieee80211_xauth.c
---- madwifi-0.9.2.orig/net80211/ieee80211_xauth.c 2006-02-01 21:07:11.000000000 +0100
-+++ madwifi-0.9.2/net80211/ieee80211_xauth.c 2006-12-04 23:56:49.000000000 +0100
-@@ -46,7 +46,7 @@
- * of the available callbacks--the user mode authenticator process works
- * entirely from messages about stations joining and leaving.
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/init.h>
-diff -urN madwifi-0.9.2.orig/net80211/if_media.c madwifi-0.9.2/net80211/if_media.c
---- madwifi-0.9.2.orig/net80211/if_media.c 2006-05-31 23:05:08.000000000 +0200
-+++ madwifi-0.9.2/net80211/if_media.c 2006-12-04 23:56:49.000000000 +0100
-@@ -49,7 +49,7 @@
- #define EXPORT_SYMTAB
- #endif
-
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
-diff -urN madwifi-0.9.2.orig/regression/ccmp/test_ccmp.c madwifi-0.9.2/regression/ccmp/test_ccmp.c
---- madwifi-0.9.2.orig/regression/ccmp/test_ccmp.c 2006-02-01 21:07:11.000000000 +0100
-+++ madwifi-0.9.2/regression/ccmp/test_ccmp.c 2006-12-04 23:56:50.000000000 +0100
-@@ -44,7 +44,7 @@
- * you want; e.g. insmod ccmp_test tests=7 will run only test mpdu's
- * 1, 2, and 3.
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/init.h>
-diff -urN madwifi-0.9.2.orig/regression/tkip/test_tkip.c madwifi-0.9.2/regression/tkip/test_tkip.c
---- madwifi-0.9.2.orig/regression/tkip/test_tkip.c 2006-02-01 21:07:11.000000000 +0100
-+++ madwifi-0.9.2/regression/tkip/test_tkip.c 2006-12-04 23:56:50.000000000 +0100
-@@ -34,7 +34,7 @@
- /*
- * TKIP test module.
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/init.h>
-diff -urN madwifi-0.9.2.orig/regression/wep/test_wep.c madwifi-0.9.2/regression/wep/test_wep.c
---- madwifi-0.9.2.orig/regression/wep/test_wep.c 2006-02-01 21:07:11.000000000 +0100
-+++ madwifi-0.9.2/regression/wep/test_wep.c 2006-12-04 23:56:50.000000000 +0100
-@@ -44,7 +44,7 @@
- * you want; e.g. insmod wep_test tests=7 will run only test mpdu's
- * 1, 2, and 3.
- */
--#include <linux/config.h>
-+#include <linux/autoconf.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/init.h>
+++ /dev/null
-diff -ur madwifi.old/ath/if_ath_ahb.c madwifi.dev/ath/if_ath_ahb.c
---- madwifi.old/ath/if_ath_ahb.c 2006-12-16 00:56:39.000000000 +0100
-+++ madwifi.dev/ath/if_ath_ahb.c 2006-12-16 00:57:08.000000000 +0100
-@@ -27,6 +27,7 @@
- #include "if_athvar.h"
- #include "ah_devid.h"
- #include "if_ath_ahb.h"
-+#include "ah_soc.h"
-
- struct ath_ahb_softc {
- struct ath_softc aps_sc;
-@@ -176,6 +177,9 @@
- int
- ahb_enable_wmac(u_int16_t devid, u_int16_t wlanNum)
- {
-+ u_int32_t reset;
-+ u_int32_t enable;
-+
- if ((devid & AR5315_REV_MAJ_M) == AR5315_REV_MAJ) {
- u_int32_t reg;
- u_int32_t *en = (u_int32_t *) AR5315_AHB_ARB_CTL;
-@@ -203,17 +207,32 @@
- /* wait for the MAC to wakeup */
- while (REG_READ(AR5315_PCI_MAC_PCICFG) & AR5315_PCI_MAC_PCICFG_SPWR_DN);
- } else {
-- u_int32_t *en = (u_int32_t *)AR531X_ENABLE;
- switch (wlanNum) {
- case AR531X_WLAN0_NUM:
-- *en |= AR531X_ENABLE_WLAN0;
-+ reset = (AR531X_RESET_WLAN0 |
-+ AR531X_RESET_WARM_WLAN0_MAC |
-+ AR531X_RESET_WARM_WLAN0_BB);
-+ enable = AR531X_ENABLE_WLAN0;
- break;
- case AR531X_WLAN1_NUM:
-- *en |= AR531X_ENABLE_WLAN1;
-+ reset = (AR531X_RESET_WLAN1 |
-+ AR531X_RESET_WARM_WLAN1_MAC |
-+ AR531X_RESET_WARM_WLAN1_BB);
-+ enable = AR531X_ENABLE_WLAN1;
- break;
- default:
- return -ENODEV;
- }
-+ /* reset the MAC or suffer lots of AHB PROC errors */
-+ REG_WRITE(AR531X_RESETCTL, REG_READ(AR531X_RESETCTL) | reset);
-+ mdelay(15);
-+
-+ /* take it out of reset */
-+ REG_WRITE(AR531X_RESETCTL, REG_READ(AR531X_RESETCTL) & ~reset);
-+ udelay(25);
-+
-+ /* enable it */
-+ REG_WRITE(AR531X_ENABLE, REG_READ(AR531X_ENABLE) | enable);
- }
- return 0;
- }
-@@ -221,6 +240,7 @@
- int
- ahb_disable_wmac(u_int16_t devid, u_int16_t wlanNum)
- {
-+ u_int32_t enable;
- if ((devid & AR5315_REV_MAJ_M) == AR5315_REV_MAJ) {
- u_int32_t *en = (u_int32_t *) AR5315_AHB_ARB_CTL;
-
-@@ -229,17 +249,17 @@
- /* Enable Arbitration for WLAN */
- *en &= ~AR5315_ARB_WLAN;
- } else {
-- u_int32_t *en = (u_int32_t *)AR531X_ENABLE;
- switch (wlanNum) {
- case AR531X_WLAN0_NUM:
-- *en &= ~AR531X_ENABLE_WLAN0;
-+ enable = AR531X_ENABLE_WLAN0;
- break;
- case AR531X_WLAN1_NUM:
-- *en &= ~AR531X_ENABLE_WLAN1;
-+ enable = AR531X_ENABLE_WLAN1;
- break;
- default:
- return -ENODEV;
- }
-+ REG_WRITE(AR531X_ENABLE, REG_READ(AR531X_ENABLE) & ~enable);
- }
- return 0;
- }
-@@ -326,13 +346,18 @@
- }
- dev->mem_end = dev->mem_start + AR531X_WLANX_LEN;
- sc->aps_sc.sc_bdev = NULL;
--
-+
- if (request_irq(dev->irq, ath_intr, SA_SHIRQ, dev->name, dev)) {
- printk(KERN_WARNING "%s: request_irq failed\n", dev->name);
- goto bad3;
- }
--
-- if (ath_attach(devid, dev) != 0)
-+
-+ struct ar531x_config config;
-+ config.board = ar5312_boardConfig;
-+ config.radio = radioConfig;
-+ config.unit = wlanNum;
-+ config.tag = NULL;
-+ if (ath_attach(devid, dev, &config) != 0)
- goto bad4;
- athname = ath_hal_probe(ATHEROS_VENDOR_ID, devid);
- printk(KERN_INFO "%s: %s: mem=0x%lx, irq=%d\n",
-diff -ur madwifi.old/ath/if_ath_ahb.h madwifi.dev/ath/if_ath_ahb.h
---- madwifi.old/ath/if_ath_ahb.h 2006-12-16 00:56:39.000000000 +0100
-+++ madwifi.dev/ath/if_ath_ahb.h 2006-12-16 00:57:08.000000000 +0100
-@@ -10,6 +10,7 @@
-
- #include <asm/io.h>
- #include <asm/uaccess.h>
-+
- #define AR531X_WLAN0_NUM 0
- #define AR531X_WLAN1_NUM 1
-
-@@ -70,9 +71,18 @@
- #define AR531X_WLAN1 0xb8500000
- #define AR531X_WLANX_LEN 0x000ffffc
-
-+#define AR531X_RESETCTL 0xbc003020
-+#define AR531X_RESET_WLAN0 0x00000004 /* mac & bb */
-+#define AR531X_RESET_WLAN1 0x00000200 /* mac & bb */
-+#define AR531X_RESET_WARM_WLAN0_MAC 0x00002000
-+#define AR531X_RESET_WARM_WLAN0_BB 0x00004000
-+#define AR531X_RESET_WARM_WLAN1_MAC 0x00020000
-+#define AR531X_RESET_WARM_WLAN1_BB 0x00040000
-+
- #define AR531X_ENABLE 0xbc003080
--#define AR531X_ENABLE_WLAN1 0x8
--#define AR531X_ENABLE_WLAN0 0x1
-+#define AR531X_ENABLE_WLAN0 0x0001
-+#define AR531X_ENABLE_WLAN1 0x0018 /* both DMA and PIO */
-+
- #define AR531X_RADIO_MASK_OFF 0xc8
- #define AR531X_RADIO0_MASK 0x0003
- #define AR531X_RADIO1_MASK 0x000c
-diff -ur madwifi.old/ath/if_ath.c madwifi.dev/ath/if_ath.c
---- madwifi.old/ath/if_ath.c 2006-12-16 00:56:39.000000000 +0100
-+++ madwifi.dev/ath/if_ath.c 2006-12-16 00:57:08.000000000 +0100
-@@ -380,7 +380,7 @@
- } while(0)
-
- int
--ath_attach(u_int16_t devid, struct net_device *dev)
-+ath_attach(u_int16_t devid, struct net_device *dev, HAL_BUS_TAG tag)
- {
- struct ath_softc *sc = dev->priv;
- struct ieee80211com *ic = &sc->sc_ic;
-@@ -421,7 +421,7 @@
- * built with an ah.h that does not correspond to the hal
- * module loaded in the kernel.
- */
-- ah = _ath_hal_attach(devid, sc, NULL, (void *) dev->mem_start, &status);
-+ ah = _ath_hal_attach(devid, sc, tag, (void *) dev->mem_start, &status);
- if (ah == NULL) {
- printk(KERN_ERR "%s: unable to attach hardware: '%s' (HAL status %u)\n",
- dev->name, ath_get_hal_status_desc(status), status);
-diff -ur madwifi.old/ath/if_ath_pci.c madwifi.dev/ath/if_ath_pci.c
---- madwifi.old/ath/if_ath_pci.c 2006-12-16 00:56:39.000000000 +0100
-+++ madwifi.dev/ath/if_ath_pci.c 2006-12-16 00:57:08.000000000 +0100
-@@ -218,7 +218,7 @@
- break;
- }
- }
-- if (ath_attach(vdevice, dev) != 0)
-+ if (ath_attach(vdevice, dev, NULL) != 0)
- goto bad4;
-
- athname = ath_hal_probe(id->vendor, vdevice);
-diff -ur madwifi.old/ath/if_athvar.h madwifi.dev/ath/if_athvar.h
---- madwifi.old/ath/if_athvar.h 2006-12-16 00:56:39.000000000 +0100
-+++ madwifi.dev/ath/if_athvar.h 2006-12-16 00:57:08.000000000 +0100
-@@ -681,7 +681,7 @@
- #define ATH_LOCK(_sc) down(&(_sc)->sc_lock)
- #define ATH_UNLOCK(_sc) up(&(_sc)->sc_lock)
-
--int ath_attach(u_int16_t, struct net_device *);
-+int ath_attach(u_int16_t, struct net_device *, HAL_BUS_TAG);
- int ath_detach(struct net_device *);
- void ath_resume(struct net_device *);
- void ath_suspend(struct net_device *);
-diff -ur madwifi.old/THANKS madwifi.dev/THANKS
---- madwifi.old/THANKS 2006-12-16 00:56:39.000000000 +0100
-+++ madwifi.dev/THANKS 2006-12-16 00:58:33.000000000 +0100
-@@ -102,6 +102,7 @@
- Joe Parks
- Pavel Novak
- Wade Mealing
-+Mats Hojlund
-
- Apologies to anyone whose name was unintentionally left off.
- Please let us know if you think your name should be mentioned here!
+++ /dev/null
-diff -ur madwifi.old/ath/if_ath_ahb.c madwifi.dev/ath/if_ath_ahb.c
---- madwifi.old/ath/if_ath_ahb.c 2007-02-04 04:07:15.810701232 +0100
-+++ madwifi.dev/ath/if_ath_ahb.c 2007-02-04 04:14:02.699844680 +0100
-@@ -17,6 +17,9 @@
- #include <linux/if.h>
- #include <linux/netdevice.h>
- #include <linux/cache.h>
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
-+#include <linux/platform_device.h>
-+#endif
-
- #include <asm/io.h>
- #include <asm/uaccess.h>
-@@ -39,6 +42,7 @@
- static struct ath_ahb_softc *sclist[2] = {NULL, NULL};
- static u_int8_t num_activesc = 0;
-
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
- static struct ar531x_boarddata *ar5312_boardConfig = NULL;
- static char *radioConfig = NULL;
-
-@@ -136,6 +140,8 @@
- data[i] = eepromAddr[off];
- }
-
-+#endif
-+
- /* set bus cachesize in 4B word units */
- void
- bus_read_cachesize(struct ath_softc *sc, u_int8_t *csz)
-@@ -180,7 +186,8 @@
- u_int32_t reset;
- u_int32_t enable;
-
-- if ((devid & AR5315_REV_MAJ_M) == AR5315_REV_MAJ) {
-+ if (((devid & AR5315_REV_MAJ_M) == AR5315_REV_MAJ) ||
-+ ((devid & AR5315_REV_MAJ_M) == AR5317_REV_MAJ)) {
- u_int32_t reg;
- u_int32_t *en = (u_int32_t *) AR5315_AHB_ARB_CTL;
-
-@@ -241,7 +248,8 @@
- ahb_disable_wmac(u_int16_t devid, u_int16_t wlanNum)
- {
- u_int32_t enable;
-- if ((devid & AR5315_REV_MAJ_M) == AR5315_REV_MAJ) {
-+ if (((devid & AR5315_REV_MAJ_M) == AR5315_REV_MAJ) ||
-+ ((devid & AR5315_REV_MAJ_M) == AR5317_REV_MAJ)) {
- u_int32_t *en = (u_int32_t *) AR5315_AHB_ARB_CTL;
-
- KASSERT(wlanNum == 0, ("invalid wlan # %d", wlanNum) );
-@@ -265,12 +273,12 @@
- }
-
-
-+
- int
--exit_ath_wmac(u_int16_t wlanNum)
-+exit_ath_wmac(u_int16_t wlanNum, struct ar531x_config *config)
- {
- struct ath_ahb_softc *sc = sclist[wlanNum];
- struct net_device *dev;
-- const char *sysType;
- u_int16_t devid;
-
- if (sc == NULL)
-@@ -280,13 +288,17 @@
- ath_detach(dev);
- if (dev->irq)
- free_irq(dev->irq, dev);
-- sysType = get_system_type();
-- if (!strcmp(sysType, "Atheros AR5315"))
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
-+ devid = (u32) config->tag;
-+#else
-+ if (!strcmp(get_system_type(), "Atheros AR5315"))
- devid = (u_int16_t) (sysRegRead(AR5315_SREV) &
- (AR5315_REV_MAJ_M | AR5315_REV_MIN_M));
- else
- devid = (u_int16_t) ((sysRegRead(AR531X_REV) >> 8) &
- (AR531X_REV_MAJ | AR531X_REV_MIN));
-+#endif
-
- ahb_disable_wmac(devid, wlanNum);
- free_netdev(dev);
-@@ -295,7 +307,7 @@
- }
-
- int
--init_ath_wmac(u_int16_t devid, u_int16_t wlanNum)
-+init_ath_wmac(u_int16_t devid, u_int16_t wlanNum, struct ar531x_config *config)
- {
- const char *athname;
- struct net_device *dev;
-@@ -329,7 +341,8 @@
-
- switch (wlanNum) {
- case AR531X_WLAN0_NUM:
-- if ((devid & AR5315_REV_MAJ_M) == AR5315_REV_MAJ) {
-+ if (((devid & AR5315_REV_MAJ_M) == AR5315_REV_MAJ) ||
-+ ((devid & AR5315_REV_MAJ_M) == AR5317_REV_MAJ)) {
- dev->irq = AR5315_IRQ_WLAN0_INTRS;
- dev->mem_start = AR5315_WLAN0;
- } else {
-@@ -352,12 +365,7 @@
- goto bad3;
- }
-
-- struct ar531x_config config;
-- config.board = ar5312_boardConfig;
-- config.radio = radioConfig;
-- config.unit = wlanNum;
-- config.tag = NULL;
-- if (ath_attach(devid, dev, &config) != 0)
-+ if (ath_attach(devid, dev, config) != 0)
- goto bad4;
- athname = ath_hal_probe(ATHEROS_VENDOR_ID, devid);
- printk(KERN_INFO "%s: %s: mem=0x%lx, irq=%d\n",
-@@ -379,24 +387,63 @@
- return -ENODEV;
- }
-
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
-+static int ahb_wmac_probe(struct platform_device *pdev)
-+{
-+ u32 devid;
-+ struct ar531x_config *config;
-+
-+ config = (struct ar531x_config *) pdev->dev.platform_data;
-+ devid = (u32) config->tag;
-+ config->tag = NULL;
-+
-+ return init_ath_wmac((u_int16_t) devid, pdev->id, config);
-+}
-+
-+
-+static int ahb_wmac_remove(struct platform_device *pdev)
-+{
-+ exit_ath_wmac(pdev->id, (struct ar531x_config *) pdev->dev.platform_data);
-+
-+ return 0;
-+}
-+
-+struct platform_driver ahb_wmac_driver = {
-+ .driver.name = "ar531x-wmac",
-+ .probe = ahb_wmac_probe,
-+ .remove = ahb_wmac_remove
-+};
-+
-+#else
-+
- int
- init_ahb(void)
- {
- int ret;
- u_int16_t devid, radioMask;
- const char *sysType;
-+ struct ar531x_config config;
-+
- sysType = get_system_type();
-+
-+ /* Probe to find out the silicon revision and enable the
-+ correct number of macs */
-+ if (!ar5312SetupFlash())
-+ return -ENODEV;
-+
-+ config.board = ar5312_boardConfig;
-+ config.radio = radioConfig;
-+ config.unit = wlanNum;
-+ config.tag = NULL;
-+
- if (!strcmp(sysType,"Atheros AR5315")) {
- devid = (u_int16_t) (sysRegRead(AR5315_SREV) &
- (AR5315_REV_MAJ_M | AR5315_REV_MIN_M));
-- if ((devid & AR5315_REV_MAJ_M) == AR5315_REV_MAJ)
-+ if (((devid & AR5315_REV_MAJ_M) == AR5315_REV_MAJ) ||
-+ ((devid & AR5315_REV_MAJ_M) == AR5317_REV_MAJ))
- return init_ath_wmac(devid, 0);
- }
-
-- /* Probe to find out the silicon revision and enable the
-- correct number of macs */
-- if (!ar5312SetupFlash())
-- return -ENODEV;
- devid = (u_int16_t) ((sysRegRead(AR531X_REV) >>8) &
- (AR531X_REV_MAJ | AR531X_REV_MIN));
- switch (devid) {
-@@ -420,6 +467,7 @@
- return 0;
- }
-
-+#endif
-
- /*
- * Module glue.
-@@ -460,13 +508,19 @@
- {
- printk(KERN_INFO "%s: %s\n", dev_info, version);
-
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
-+ platform_driver_register(&ahb_wmac_driver);
-+#else
- if (init_ahb() != 0) {
- printk("ath_ahb: No devices found, driver not installed.\n");
- return (-ENODEV);
- }
-+#endif
-+
- #ifdef CONFIG_SYSCTL
- ath_sysctl_register();
- #endif
-+
- return 0;
- }
- module_init(init_ath_ahb);
-@@ -477,8 +531,13 @@
- #ifdef CONFIG_SYSCTL
- ath_sysctl_unregister();
- #endif
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
-+ platform_driver_unregister(&ahb_wmac_driver);
-+#else
- exit_ath_wmac(AR531X_WLAN0_NUM);
- exit_ath_wmac(AR531X_WLAN1_NUM);
-+#endif
-
- printk(KERN_INFO "%s: driver unloaded\n", dev_info);
- }
-diff -ur madwifi.old/ath/if_ath_ahb.h madwifi.dev/ath/if_ath_ahb.h
---- madwifi.old/ath/if_ath_ahb.h 2007-02-04 04:07:15.810701232 +0100
-+++ madwifi.dev/ath/if_ath_ahb.h 2007-02-04 04:06:49.070766320 +0100
-@@ -59,6 +59,7 @@
- #define AR5315_SREV 0xb1000014
-
- #define AR5315_REV_MAJ 0x0080
-+#define AR5317_REV_MAJ 0x0090
- #define AR5315_REV_MAJ_M 0x00f0
- #define AR5315_REV_MAJ_S 4
- #define AR5315_REV_MIN_M 0x000f
-Doing ifconfig athX down/ifconfig athX up several times provokes kernel crash.
-See http://madwifi.org/ticket/914. But if ath_hal_phydisable() is skipped -
-I observe NO CRASH whatsoever ... :\ Weird.
-
-Signed-off-by: Mindaugas Kriaučiūnas <mindaugas.kriauciunas@gmail.com>
-Signed-off-by: Žilvinas Valinskas <valins@soften.ktu.lt>
-
-Index: madwifi-ng-trunk/ath/if_ath.c
-===================================================================
---- madwifi-ng-trunk.orig/ath/if_ath.c 2006-10-16 17:40:50.000000000 +0300
-+++ madwifi-ng-trunk/ath/if_ath.c 2006-10-18 16:17:32.000000000 +0300
-@@ -1997,7 +1997,10 @@
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c
+--- madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c 2007-05-13 18:17:55.362152712 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c 2007-05-13 18:17:55.614114408 +0200
+@@ -2003,7 +2003,10 @@
ath_draintxq(sc);
if (!sc->sc_invalid) {
ath_stoprecv(sc);
-WDS related crash is observed. This causes by possible random memory
-writes/accesss. Note how wds is freed, yet it will be used further in
-loop ...
-
-Other usages in the tree of LIST_FOREACH() when element is found and
-acted up on element, loop is immediately break (either via break, or
-return). But not in this case ...
-
-Signed-off-by: Mindaugas Kriaučiūnas <mindaugas.kriauciunas@gmail.com>
-Signed-off-by: Žilvinas Valinskas <valins@soften.ktu.lt>
-
-Index: madwifi-ng-trunk/net80211/ieee80211_node.c
-===================================================================
---- madwifi-ng-trunk.orig/net80211/ieee80211_node.c 2006-09-25 13:28:08.000000000 +0300
-+++ madwifi-ng-trunk/net80211/ieee80211_node.c 2006-10-18 15:59:40.000000000 +0300
-@@ -961,11 +961,11 @@
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_node.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_node.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_node.c 2007-05-04 23:09:29.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_node.c 2007-05-13 18:17:55.697101792 +0200
+@@ -981,11 +981,11 @@
ieee80211_del_wds_node(struct ieee80211_node_table *nt, struct ieee80211_node *ni)
{
int hash;
- struct ieee80211_wds_addr *wds;
+ struct ieee80211_wds_addr *wds, *next;
- IEEE80211_NODE_LOCK_IRQ(nt);
+ IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
for (hash = 0; hash < IEEE80211_NODE_HASHSIZE; hash++) {
- LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) {
+ LIST_FOREACH_SAFE(wds, &nt->nt_wds_hash[hash], wds_hash, next) {
if (wds->wds_ni == ni) {
- if (ieee80211_node_dectestref(ni)) {
- _ieee80211_free_node(ni);
-@@ -984,11 +984,11 @@
+ LIST_REMOVE(wds, wds_hash);
+ ieee80211_unref_node(&wds->wds_ni);
+@@ -1002,11 +1002,11 @@
{
struct ieee80211_node_table *nt = (struct ieee80211_node_table *)data;
int hash;
- struct ieee80211_wds_addr *wds;
+ struct ieee80211_wds_addr *wds, *next;
- IEEE80211_NODE_LOCK_IRQ(nt);
+ IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
for (hash = 0; hash < IEEE80211_NODE_HASHSIZE; hash++) {
- LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) {
+ LIST_FOREACH_SAFE(wds, &nt->nt_wds_hash[hash], wds_hash, next) {
if (wds->wds_agingcount != WDS_AGING_STATIC) {
if (!wds->wds_agingcount) {
- if (ieee80211_node_dectestref(wds->wds_ni)) {
+ LIST_REMOVE(wds, wds_hash);
+++ /dev/null
-This patch fixes a bug in net80211/ieee80211_wireless.c preventing
-the user from setting a certain BSSID by
-"iwconfig athX ap XX:XX:XX:XX:XX:XX".
-It furthermore prevents merging to another IBSS in ad-hoc mode
-if a BSSID was set previously by the above command.
-It was tested with the snapshot madwifi-ng-r1696-20060730.
-
-Signed-off-by: Joerg Albert <jal2@gmx.de>
-
-diff -ru madwifi-ng-r1696-20060730/ath/if_ath.c madwifi-ng-r1696-20060730.work/ath/if_ath.c
---- madwifi-ng-r1696-20060730/ath/if_ath.c 2006-07-08 08:47:19.000000000 +0200
-+++ madwifi-ng-r1696-20060730.work/ath/if_ath.c 2006-08-03 20:38:12.000000000 +0200
-@@ -5316,7 +5316,10 @@
- * ath_newstate as the state machine will go from
- * RUN -> RUN when this happens.
- */
-- if (le64_to_cpu(ni->ni_tstamp.tsf) >= tsf) {
-+ /* jal: added: don't merge if we have a desired
-+ BSSID */
-+ if (!(vap->iv_flags & IEEE80211_F_DESBSSID) &&
-+ le64_to_cpu(ni->ni_tstamp.tsf) >= tsf) {
- DPRINTF(sc, ATH_DEBUG_STATE,
- "ibss merge, rstamp %u tsf %llu "
- "tstamp %llu\n", rstamp, (long long) tsf,
-diff -ru madwifi-ng-r1696-20060730/net80211/ieee80211_wireless.c madwifi-ng-r1696-20060730.work/net80211/ieee80211_wireless.c
---- madwifi-ng-r1696-20060730/net80211/ieee80211_wireless.c 2006-07-29 03:31:11.000000000 +0200
-+++ madwifi-ng-r1696-20060730.work/net80211/ieee80211_wireless.c 2006-08-03 21:23:30.000000000 +0200
-@@ -539,7 +539,7 @@
- *
- * anything else specifies a particular AP.
- */
-- if (IEEE80211_ADDR_EQ(vap->iv_des_bssid, zero_bssid))
-+ if (IEEE80211_ADDR_EQ(&ap_addr->sa_data, zero_bssid))
- vap->iv_flags &= ~IEEE80211_F_DESBSSID;
- else {
- IEEE80211_ADDR_COPY(vap->iv_des_bssid, &ap_addr->sa_data);
--- /dev/null
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c
+--- madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c 2007-05-13 18:17:55.691102704 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c 2007-05-13 18:17:55.783088720 +0200
+@@ -5704,7 +5704,8 @@
+ * frame; it'll be dropped where it's not wanted.
+ */
+ if (ds->ds_rxstat.rs_keyix != HAL_RXKEYIX_INVALID &&
+- (ni = sc->sc_keyixmap[ds->ds_rxstat.rs_keyix]) != NULL) {
++ (ni = sc->sc_keyixmap[ds->ds_rxstat.rs_keyix]) != NULL &&
++ ieee80211_check_rxnode(ni, (const struct ieee80211_frame_min *) skb->data)) {
+ struct ath_node *an;
+ /*
+ * Fast path: node is present in the key map;
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_node.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_node.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_node.c 2007-05-13 18:17:55.773090240 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_node.c 2007-05-13 18:17:55.784088568 +0200
+@@ -1268,8 +1268,6 @@
+ IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
+
+ return ni;
+-#undef IS_PSPOLL
+-#undef IS_CTL
+ }
+ #ifdef IEEE80211_DEBUG_REFCNT
+ EXPORT_SYMBOL(ieee80211_find_rxnode_debug);
+@@ -1277,6 +1275,20 @@
+ EXPORT_SYMBOL(ieee80211_find_rxnode);
+ #endif
+
++int
++ieee80211_check_rxnode(struct ieee80211_node *ni,
++ const struct ieee80211_frame_min *wh)
++{
++ if (IS_CTL(wh) && !IS_PSPOLL(wh) /*&& !IS_RTS(ah)*/)
++ return IEEE80211_ADDR_EQ(ni->ni_macaddr, wh->i_addr1);
++ else
++ return IEEE80211_ADDR_EQ(ni->ni_macaddr, wh->i_addr2);
++}
++
++EXPORT_SYMBOL(ieee80211_check_rxnode);
++#undef IS_PSPOLL
++#undef IS_CTL
++
+ /*
+ * Return a reference to the appropriate node for sending
+ * a data frame. This handles node discovery in adhoc networks.
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_node.h madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_node.h
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_node.h 2007-04-04 04:39:58.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_node.h 2007-05-13 18:17:55.784088568 +0200
+@@ -318,6 +318,8 @@
+ *pni = NULL; /* guard against use */
+ }
+
++int ieee80211_check_rxnode(struct ieee80211_node *ni,
++ const struct ieee80211_frame_min *wh);
+ int ieee80211_add_wds_addr(struct ieee80211_node_table *, struct ieee80211_node *,
+ const u_int8_t *, u_int8_t);
+ void ieee80211_remove_wds_addr(struct ieee80211_node_table *, const u_int8_t *);
--- /dev/null
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_scan.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_scan.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_scan.c 2007-04-25 22:29:55.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_scan.c 2007-05-13 18:17:55.868075800 +0200
+@@ -291,7 +291,8 @@
+ struct ieee80211com *ic = vap->iv_ic;
+ int delay;
+
+- ieee80211_sta_pwrsave(vap, 1);
++ if (vap->iv_opmode != IEEE80211_M_IBSS)
++ ieee80211_sta_pwrsave(vap, 1);
+ /*
+ * Use an initial 1ms delay to ensure the null
+ * data frame has a chance to go out.
--- /dev/null
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_output.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_output.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_output.c 2007-04-25 22:29:55.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_output.c 2007-05-13 18:17:55.947063792 +0200
+@@ -942,7 +942,7 @@
+ llc->llc_snap.org_code[0] = 0;
+ llc->llc_snap.org_code[1] = 0;
+ llc->llc_snap.org_code[2] = 0;
+- llc->llc_snap.ether_type = eh.ether_type;
++ llc->llc_snap.ether_type = eh2.ether_type;
+
+ eh_inter = (struct ether_header *) skb_push(skb2, sizeof(struct ether_header));
+ if (eh_inter == NULL) {
+@@ -952,7 +952,7 @@
+ return NULL;
+ }
+
+- memcpy(eh_inter, &eh2, sizeof(struct ether_header) - sizeof eh.ether_type);
++ memcpy(eh_inter, &eh2, sizeof(struct ether_header) - sizeof eh2.ether_type);
+ eh_inter->ether_type = htons(payload);
+
+ /* variable length pad */
--- /dev/null
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_input.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_input.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_input.c 2007-05-04 02:10:06.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_input.c 2007-05-13 18:17:56.027051632 +0200
+@@ -2854,7 +2854,7 @@
+ IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
+ memcpy(ni->ni_tstamp.data, scan.tstamp,
+ sizeof(ni->ni_tstamp));
+- ni->ni_intval = scan.bintval;
++ ni->ni_intval = IEEE80211_BINTVAL_SANITISE(scan.bintval);
+ ni->ni_capinfo = scan.capinfo;
+ ni->ni_chan = ic->ic_curchan;
+ ni->ni_fhdwell = scan.fhdwell;
+@@ -3279,7 +3279,7 @@
+ ni->ni_rssi = rssi;
+ ni->ni_rstamp = rstamp;
+ ni->ni_last_rx = jiffies;
+- ni->ni_intval = bintval;
++ ni->ni_intval = IEEE80211_BINTVAL_SANITISE(bintval);
+ ni->ni_capinfo = capinfo;
+ ni->ni_chan = ic->ic_curchan;
+ ni->ni_fhdwell = vap->iv_bss->ni_fhdwell;
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_node.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_node.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_node.c 2007-05-13 18:17:55.862076712 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_node.c 2007-05-13 18:17:56.028051480 +0200
+@@ -658,7 +658,7 @@
+ memcpy(ni->ni_essid, se->se_ssid + 2, ni->ni_esslen);
+ ni->ni_rstamp = se->se_rstamp;
+ ni->ni_tstamp.tsf = se->se_tstamp.tsf;
+- ni->ni_intval = se->se_intval;
++ ni->ni_intval = IEEE80211_BINTVAL_SANITISE(se->se_intval);
+ ni->ni_capinfo = se->se_capinfo;
+ ni->ni_chan = se->se_chan;
+ ni->ni_timoff = se->se_timoff;
+@@ -1191,7 +1191,7 @@
+ memcpy(ni->ni_essid, sp->ssid + 2, sp->ssid[1]);
+ IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
+ memcpy(ni->ni_tstamp.data, sp->tstamp, sizeof(ni->ni_tstamp));
+- ni->ni_intval = sp->bintval;
++ ni->ni_intval = IEEE80211_BINTVAL_SANITISE(sp->bintval);
+ ni->ni_capinfo = sp->capinfo;
+ ni->ni_chan = ic->ic_curchan;
+ ni->ni_fhdwell = sp->fhdwell;
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_scan.h madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_scan.h
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_scan.h 2007-04-04 04:39:58.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_scan.h 2007-05-13 18:17:56.029051328 +0200
+@@ -131,7 +131,7 @@
+ u_int8_t bchan;
+ u_int8_t fhindex;
+ u_int8_t erp;
+- u_int8_t bintval;
++ u_int16_t bintval;
+ u_int8_t timoff;
+ u_int8_t *tim;
+ u_int8_t *tstamp;
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_var.h madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_var.h
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_var.h 2007-04-25 22:29:55.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_var.h 2007-05-13 18:17:56.029051328 +0200
+@@ -61,6 +61,12 @@
+ #define IEEE80211_BINTVAL_MAX 500 /* max beacon interval (TU's) */
+ #define IEEE80211_BINTVAL_MIN 25 /* min beacon interval (TU's) */
+ #define IEEE80211_BINTVAL_DEFAULT 100 /* default beacon interval (TU's) */
++#define IEEE80211_BINTVAL_VALID(_bi) \
++ ((IEEE80211_BINTVAL_MIN <= (_bi)) && \
++ ((_bi) <= IEEE80211_BINTVAL_MAX))
++#define IEEE80211_BINTVAL_SANITISE(_bi) \
++ (IEEE80211_BINTVAL_VALID(_bi) ? \
++ (_bi) : IEEE80211_BINTVAL_DEFAULT)
+
+ #define IEEE80211_BGSCAN_INTVAL_MIN 15 /* min bg scan intvl (secs) */
+ #define IEEE80211_BGSCAN_INTVAL_DEFAULT (5*60) /* default bg scan intvl */
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_wireless.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_wireless.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_wireless.c 2007-05-04 02:10:06.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_wireless.c 2007-05-13 18:17:56.031051024 +0200
+@@ -1271,12 +1271,16 @@
+ case IW_POWER_UNICAST_R:
+ case IW_POWER_ALL_R:
+ case IW_POWER_ON:
+- ic->ic_flags |= IEEE80211_F_PMGTON;
+-
++ if (wrq->flags & IW_POWER_PERIOD) {
++ if (IEEE80211_BINTVAL_VALID(wrq->value))
++ ic->ic_lintval = IEEE80211_MS_TO_TU(wrq->value);
++ else
++ return -EINVAL;
++ }
+ if (wrq->flags & IW_POWER_TIMEOUT)
+ ic->ic_holdover = IEEE80211_MS_TO_TU(wrq->value);
+- if (wrq->flags & IW_POWER_PERIOD)
+- ic->ic_lintval = IEEE80211_MS_TO_TU(wrq->value);
++
++ ic->ic_flags |= IEEE80211_F_PMGTON;
+ break;
+ default:
+ return -EINVAL;
+@@ -2364,8 +2368,7 @@
+ if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
+ vap->iv_opmode != IEEE80211_M_IBSS)
+ return -EINVAL;
+- if (IEEE80211_BINTVAL_MIN <= value &&
+- value <= IEEE80211_BINTVAL_MAX) {
++ if (IEEE80211_BINTVAL_VALID(value)) {
+ ic->ic_lintval = value; /* XXX multi-bss */
+ retv = ENETRESET; /* requires restart */
+ } else
--- /dev/null
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c
+--- madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c 2007-05-13 18:17:55.862076712 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c 2007-05-13 18:17:56.119037648 +0200
+@@ -4411,16 +4411,31 @@
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211_node *ni;
+- u_int32_t nexttbtt, intval;
++ u_int32_t nexttbtt = 0;
++ u_int32_t intval;
++ u_int64_t tsf, hw_tsf;
++ u_int32_t tsftu, hw_tsftu;
++ int should_reset_tsf = 0;
+
+ if (vap == NULL)
+ vap = TAILQ_FIRST(&ic->ic_vaps); /* XXX */
+
+ ni = vap->iv_bss;
+
+- /* extract tstamp from last beacon and convert to TU */
+- nexttbtt = TSF_TO_TU(LE_READ_4(ni->ni_tstamp.data + 4),
+- LE_READ_4(ni->ni_tstamp.data));
++ hw_tsf = ath_hal_gettsf64(ah);
++ tsf = le64_to_cpu(ni->ni_tstamp.tsf);
++ hw_tsftu = hw_tsf >> 10;
++ tsftu = tsf >> 10;
++
++ /* we should reset hw TSF only once, so we increment
++ ni_tstamp.tsf to avoid resetting the hw TSF multiple
++ times */
++
++ if (tsf == 0) {
++ should_reset_tsf = 1;
++ ni->ni_tstamp.tsf = cpu_to_le64(1);
++ }
++
+ /* XXX conditionalize multi-bss support? */
+ if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
+ /*
+@@ -4434,20 +4449,61 @@
+ if (sc->sc_stagbeacons)
+ intval /= ATH_BCBUF; /* for staggered beacons */
+ if ((sc->sc_nostabeacons) &&
+- (vap->iv_opmode == IEEE80211_M_HOSTAP))
+- nexttbtt = 0;
++ (vap->iv_opmode == IEEE80211_M_HOSTAP))
++ should_reset_tsf = 1;
+ } else
+ intval = ni->ni_intval & HAL_BEACON_PERIOD;
+- if (nexttbtt == 0) /* e.g. for ap mode */
++
++#define FUDGE 2
++ sc->sc_syncbeacon = 0;
++ if (should_reset_tsf) {
++
++ /* We just created the interface and TSF will be reset to
++ zero, so next beacon will be sent at the next intval
++ time */
++
+ nexttbtt = intval;
+- else if (intval) /* NB: can be 0 for monitor mode */
+- nexttbtt = roundup(nexttbtt, intval);
+- DPRINTF(sc, ATH_DEBUG_BEACON, "%s: nexttbtt %u intval %u (%u)\n",
+- __func__, nexttbtt, intval, ni->ni_intval);
++ } else if (intval) { /* NB: can be 0 for monitor mode */
++ if (tsf == 1) {
++
++ /* We do not receive any beacons or probe response. Since
++ a beacon should be sent every 'intval' ms, we compute
++ the next beacon timestamp using the hardware TSF. We
++ ensure that it is at least FUDGE ms ahead of the
++ current TSF. Otherwise, we use the next beacon
++ timestamp again */
++
++ nexttbtt = roundup(hw_tsftu +1, intval);
++ while (nexttbtt <= hw_tsftu + FUDGE) {
++ nexttbtt += intval;
++ }
++ } else {
++ if (tsf > hw_tsf) {
++
++ /* We do receive a beacon from someone else in the past,
++ but the hw TSF has not been updated (otherwise we
++ would have tsf >= hw_tsf). Since we cannot use the
++ hardware TSF, we will do nothing and wait for the
++ next beacon. In order to do so, we set sc->syncbeacon
++ again */
++
++ sc->sc_syncbeacon = 1;
++ goto ath_beacon_config_debug;
++ } else {
++ /* We do receive a beacon in the past, normal case. We
++ make sure that the timestamp is at least FUDGE ms
++ ahead of the hardware TSF */
++
++ nexttbtt = tsftu + intval;
++ while (nexttbtt <= hw_tsftu + FUDGE) {
++ nexttbtt += intval;
++ }
++ }
++ }
++ }
++
+ if (ic->ic_opmode == IEEE80211_M_STA && !(sc->sc_nostabeacons)) {
+ HAL_BEACON_STATE bs;
+- u_int64_t tsf;
+- u_int32_t tsftu;
+ int dtimperiod, dtimcount;
+ int cfpperiod, cfpcount;
+
+@@ -4463,13 +4519,13 @@
+ dtimcount = 0; /* XXX? */
+ cfpperiod = 1; /* NB: no PCF support yet */
+ cfpcount = 0;
+-#define FUDGE 2
+ /*
+ * Pull nexttbtt forward to reflect the current
+ * TSF and calculate dtim+cfp state for the result.
+ */
+- tsf = ath_hal_gettsf64(ah);
+- tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
++ nexttbtt = tsftu;
++ if (nexttbtt == 0) /* e.g. for ap mode */
++ nexttbtt = intval;
+ do {
+ nexttbtt += intval;
+ if (--dtimcount < 0) {
+@@ -4477,7 +4533,7 @@
+ if (--cfpcount < 0)
+ cfpcount = cfpperiod - 1;
+ }
+- } while (nexttbtt < tsftu);
++ } while (nexttbtt < hw_tsftu + FUDGE);
+ #undef FUDGE
+ memset(&bs, 0, sizeof(bs));
+ bs.bs_intval = intval;
+@@ -4529,7 +4585,7 @@
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+ "%s: tsf %llu tsf:tu %u intval %u nexttbtt %u dtim %u nextdtim %u bmiss %u sleep %u cfp:period %u maxdur %u next %u timoffset %u\n",
+ __func__,
+- (long long) tsf, tsftu,
++ (long long) hw_tsf, hw_tsftu,
+ bs.bs_intval,
+ bs.bs_nexttbtt,
+ bs.bs_dtimperiod,
+@@ -4548,7 +4604,7 @@
+ ath_hal_intrset(ah, sc->sc_imask);
+ } else {
+ ath_hal_intrset(ah, 0);
+- if (nexttbtt == intval)
++ if (should_reset_tsf)
+ intval |= HAL_BEACON_RESET_TSF;
+ if (ic->ic_opmode == IEEE80211_M_IBSS) {
+ /*
+@@ -4585,8 +4641,40 @@
+ if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_hasveol)
+ ath_beacon_start_adhoc(sc, vap);
+ }
+- sc->sc_syncbeacon = 0;
+ #undef TSF_TO_TU
++
++ ath_beacon_config_debug:
++
++ /* we print all debug messages here, in order to preserve the
++ time critical aspect of this function */
++
++ DPRINTF(sc, ATH_DEBUG_BEACON,
++ "%s: ni=%p tsf=%llu hw_tsf=%llu tsftu=%u hw_tsftu=%u\n",
++ __func__, ni, tsf, hw_tsf, tsftu, hw_tsftu);
++
++ if (should_reset_tsf) {
++ /* we just created the interface */
++ DPRINTF(sc, ATH_DEBUG_BEACON, "%s: first beacon\n",__func__);
++ } else {
++ if (tsf == 1) {
++ /* we do not receive any beacons or probe response */
++ DPRINTF(sc, ATH_DEBUG_BEACON,
++ "%s: no beacon received...\n",__func__);
++ } else {
++ if (tsf > hw_tsf) {
++ /* we do receive a beacon and the hw TSF has not been updated */
++ DPRINTF(sc, ATH_DEBUG_BEACON,
++ "%s: beacon received, but TSF is incorrect\n",__func__);
++ } else {
++ /* we do receive a beacon in the past, normal case */
++ DPRINTF(sc, ATH_DEBUG_BEACON,
++ "%s: beacon received, TSF is correct\n",__func__);
++ }
++ }
++ }
++
++ DPRINTF(sc, ATH_DEBUG_BEACON, "%s: nexttbtt=%u intval=%u\n",
++ __func__,nexttbtt, intval & HAL_BEACON_PERIOD);
+ }
+
+ static int
--- /dev/null
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_node.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_node.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_node.c 2007-05-13 18:17:56.107039472 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_node.c 2007-05-13 18:17:56.202025032 +0200
+@@ -919,6 +919,7 @@
+
+ ni->ni_vap = vap;
+ ni->ni_ic = ic;
++ ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2mode(ic->ic_curchan)];
+ } else {
+ /* XXX msg */
+ vap->iv_stats.is_rx_nodealloc++;
--- /dev/null
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c
+--- madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c 2007-05-13 18:17:56.196025944 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c 2007-05-13 18:17:56.284012568 +0200
+@@ -1711,6 +1711,7 @@
+ }
+ #endif
+ ATH_SCHEDULE_TQUEUE(&sc->sc_txtq, &needmark);
++ sc->sc_tx_start = 0;
+ }
+ if (status & HAL_INT_BMISS) {
+ sc->sc_stats.ast_bmiss++;
+@@ -2264,6 +2265,15 @@
+ txq->axq_link = &lastds->ds_link;
+ ath_hal_txstart(ah, txq->axq_qnum);
+ sc->sc_dev->trans_start = jiffies;
++ if (sc->sc_tx_start) {
++ if (jiffies > sc->sc_tx_start + 2 * HZ) {
++ printk("%s: Tx queue stuck. Resetting hardware...\n", sc->sc_dev->name);
++ ath_reset(sc->sc_dev);
++ sc->sc_tx_start = 0;
++ }
++ } else {
++ sc->sc_tx_start = jiffies;
++ }
+ }
+ ATH_TXQ_UNLOCK(txq);
+
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath/if_athvar.h madwifi-ng-refcount-r2313-20070505.dev/ath/if_athvar.h
+--- madwifi-ng-refcount-r2313-20070505.old/ath/if_athvar.h 2007-05-04 23:09:29.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/ath/if_athvar.h 2007-05-13 18:17:56.285012416 +0200
+@@ -689,6 +689,14 @@
+ #endif
+ u_int sc_slottimeconf; /* manual override for slottime */
+ int16_t sc_channoise; /* Measured noise of current channel (dBm) */
++
++ /*
++ * Several MiniPCI cards and most SoC revs frequently cease all transmission
++ * when operating in IBSS mode. The reason for this is unknown and could potentially
++ * be a hardware bug. This variable contains the timestamp of the last successful
++ * transmission and is checked when enqueueing new frames
++ */
++ unsigned long sc_tx_start;
+ };
+
+ typedef void (*ath_callback) (struct ath_softc *);
--- /dev/null
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath/if_ath_ahb.c madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath_ahb.c
+--- madwifi-ng-refcount-r2313-20070505.old/ath/if_ath_ahb.c 2007-03-08 20:59:06.000000000 +0100
++++ madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath_ahb.c 2007-05-13 18:17:56.367999800 +0200
+@@ -274,12 +274,12 @@
+ }
+
+
++
+ static int
+-exit_ath_wmac(u_int16_t wlanNum)
++exit_ath_wmac(u_int16_t wlanNum, struct ar531x_config *config)
+ {
+ struct ath_ahb_softc *sc = sclist[wlanNum];
+ struct net_device *dev;
+- const char *sysType;
+ u_int16_t devid;
+
+ if (sc == NULL)
+@@ -289,13 +289,17 @@
+ ath_detach(dev);
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+- sysType = get_system_type();
+- if (!strcmp(sysType, "Atheros AR5315"))
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
++ devid = (u32) config->tag;
++#else
++ if (!strcmp(get_system_type(), "Atheros AR5315"))
+ devid = (u_int16_t) (sysRegRead(AR5315_SREV) &
+ (AR5315_REV_MAJ_M | AR5315_REV_MIN_M));
+ else
+ devid = (u_int16_t) ((sysRegRead(AR531X_REV) >> 8) &
+ (AR531X_REV_MAJ | AR531X_REV_MIN));
++#endif
+
+ ahb_disable_wmac(devid, wlanNum);
+ free_netdev(dev);
+@@ -401,7 +405,7 @@
+
+ static int ahb_wmac_remove(struct platform_device *pdev)
+ {
+- exit_ath_wmac(pdev->id);
++ exit_ath_wmac(pdev->id, (struct ar531x_config *) pdev->dev.platform_data);
+
+ return 0;
+ }
+@@ -439,7 +443,7 @@
+ (AR5315_REV_MAJ_M | AR5315_REV_MIN_M));
+ if (((devid & AR5315_REV_MAJ_M) == AR5315_REV_MAJ) ||
+ ((devid & AR5315_REV_MAJ_M) == AR5317_REV_MAJ))
+- return init_ath_wmac(devid, 0, &config);
++ return init_ath_wmac(devid, 0);
+ }
+
+ devid = (u_int16_t) ((sysRegRead(AR531X_REV) >>8) &
+@@ -452,11 +456,11 @@
+ ar5312BspEepromRead(2 * AR531X_RADIO_MASK_OFF, 2,
+ (char *) &radioMask);
+ if ((radioMask & AR531X_RADIO0_MASK) != 0)
+- if ((ret = init_ath_wmac(devid, 0, &config)) !=0 )
++ if ((ret = init_ath_wmac(devid, 0)) !=0 )
+ return ret;
+ /* XXX: Fall through?! */
+ case AR5212_AR2313_REV8:
+- if ((ret = init_ath_wmac(devid, 1, &config)) != 0)
++ if ((ret = init_ath_wmac(devid, 1)) != 0)
+ return ret;
+ break;
+ default:
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c
+--- madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c 2007-05-13 18:17:56.362000712 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c 2007-05-13 18:17:56.371999192 +0200
+@@ -2490,6 +2490,7 @@
+ DPRINTF(sc,ATH_DEBUG_XMIT, \
+ "%s: discard, no xmit buf\n", __func__); \
+ sc->sc_stats.ast_tx_nobuf++; \
++ goto hardstart_fail; \
+ }
+
+ /*
+@@ -2676,14 +2677,13 @@
+ else if (an->an_tx_ffbuf[skb->priority]) {
+ DPRINTF(sc, ATH_DEBUG_XMIT | ATH_DEBUG_FF,
+ "%s: Out-Of-Order fast-frame\n", __func__);
+- ATH_TXQ_UNLOCK(txq);
++ ATH_TXQ_UNLOCK_BH(txq);
+ } else
+- ATH_TXQ_UNLOCK(txq);
++ ATH_TXQ_UNLOCK_BH(txq);
+
+ ff_flushdone:
+ ATH_HARDSTART_GET_TX_BUF_WITH_LOCK;
+- if (bf == NULL)
+- goto hardstart_fail;
++ ATH_HARDSTART_REL_TX_BUF_WITH_TXQLOCK_OFF;
+ }
+
+ ff_bypass:
+@@ -5668,6 +5668,7 @@
+ sc->sc_stats.ast_rx_phyerr++;
+ phyerr = ds->ds_rxstat.rs_phyerr & 0x1f;
+ sc->sc_stats.ast_rx_phy[phyerr]++;
++ goto rx_next;
+ }
+ if (ds->ds_rxstat.rs_status & HAL_RXERR_DECRYPT) {
+ /*
+@@ -7662,6 +7663,7 @@
+ ath_draintxq(struct ath_softc *sc)
+ {
+ struct ath_hal *ah = sc->sc_ah;
++ int npend = 0;
+ unsigned int i;
+
+ /* XXX return value */
+@@ -7670,9 +7672,24 @@
+ DPRINTF(sc, ATH_DEBUG_RESET, "%s: beacon queue 0x%x\n",
+ __func__, ath_hal_gettxbuf(ah, sc->sc_bhalq));
+ for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
+- if (ATH_TXQ_SETUP(sc, i))
++ if (ATH_TXQ_SETUP(sc, i)) {
+ ath_tx_stopdma(sc, &sc->sc_txq[i]);
++
++ /* The TxDMA may not really be stopped.
++ * Double check the hal tx pending count */
++ npend += ath_hal_numtxpending(ah, sc->sc_txq[i].axq_qnum);
++ }
++ }
++
++ if (npend) {
++ HAL_STATUS status;
++
++ /* TxDMA not stopped, reset the hal */
++ DPRINTF(sc, ATH_DEBUG_RESET, "%s: Unable to stop TxDMA. Reset HAL!\n", __func__);
++ if (!ath_hal_reset(ah, sc->sc_ic.ic_opmode, &sc->sc_curchan, AH_TRUE, &status))
++ printk("%s: unable to reset hardware; hal status %u\n", __func__, status);
+ }
++
+ sc->sc_dev->trans_start = jiffies;
+ netif_start_queue(sc->sc_dev); /* XXX move to callers */
+ for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
-diff -ur madwifi.old/ath/if_ath.c madwifi.dev/ath/if_ath.c
---- madwifi.old/ath/if_ath.c 2007-02-20 23:24:27.274770480 +0100
-+++ madwifi.dev/ath/if_ath.c 2007-02-20 23:26:49.917085552 +0100
-@@ -72,7 +72,7 @@
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c
+--- madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c 2007-05-13 18:17:56.449987336 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c 2007-05-13 18:17:56.457986120 +0200
+@@ -75,7 +75,7 @@
#include <net80211/if_llc.h>
#endif
-#define AR_DEBUG
+#undef AR_DEBUG
- #include "if_athrate.h"
#include "net80211/if_athproto.h"
-@@ -347,7 +347,7 @@
- ath_keyprint(__func__, ix, hk, mac); \
+ #include "if_athvar.h"
+@@ -359,7 +359,7 @@
+ ath_keyprint(sc, __func__, ix, hk, mac); \
} while (0)
#else /* defined(AR_DEBUG) */
-#define IFF_DUMPPKTS(sc, _m) netif_msg_dumppkts(&sc->sc_ic)
#define DPRINTF(sc, _m, _fmt, ...)
#define KEYPRINTF(sc, k, ix, mac)
#endif /* defined(AR_DEBUG) */
-diff -ur madwifi.old/ath_rate/amrr/amrr.c madwifi.dev/ath_rate/amrr/amrr.c
---- madwifi.old/ath_rate/amrr/amrr.c 2007-02-20 23:24:27.274770480 +0100
-+++ madwifi.dev/ath_rate/amrr/amrr.c 2007-02-20 23:23:54.714720360 +0100
-@@ -67,7 +67,7 @@
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath_rate/amrr/amrr.c madwifi-ng-refcount-r2313-20070505.dev/ath_rate/amrr/amrr.c
+--- madwifi-ng-refcount-r2313-20070505.old/ath_rate/amrr/amrr.c 2007-04-09 23:08:06.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/ath_rate/amrr/amrr.c 2007-05-13 18:17:56.457986120 +0200
+@@ -69,7 +69,7 @@
#include "amrr.h"
#ifdef AMRR_DEBUG
#define DPRINTF(sc, _fmt, ...) do { \
if (sc->sc_debug & 0x10) \
-diff -ur madwifi.old/ath_rate/onoe/onoe.c madwifi.dev/ath_rate/onoe/onoe.c
---- madwifi.old/ath_rate/onoe/onoe.c 2007-02-20 23:24:27.275770328 +0100
-+++ madwifi.dev/ath_rate/onoe/onoe.c 2007-02-20 23:23:54.714720360 +0100
-@@ -63,7 +63,7 @@
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath_rate/minstrel/minstrel.c madwifi-ng-refcount-r2313-20070505.dev/ath_rate/minstrel/minstrel.c
+--- madwifi-ng-refcount-r2313-20070505.old/ath_rate/minstrel/minstrel.c 2007-05-13 18:17:55.605115776 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/ath_rate/minstrel/minstrel.c 2007-05-13 18:17:56.458985968 +0200
+@@ -117,7 +117,7 @@
+ #include "minstrel.h"
+
+ /* XXX: Use standard debug functions */
+-#define MINSTREL_DEBUG 10
++#undef MINSTREL_DEBUG
+ #ifdef MINSTREL_DEBUG
+ enum {
+ ATH_DEBUG_RATE = 0x00000010 /* rate control */
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath_rate/onoe/onoe.c madwifi-ng-refcount-r2313-20070505.dev/ath_rate/onoe/onoe.c
+--- madwifi-ng-refcount-r2313-20070505.old/ath_rate/onoe/onoe.c 2007-04-09 23:08:06.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/ath_rate/onoe/onoe.c 2007-05-13 18:17:56.458985968 +0200
+@@ -65,7 +65,7 @@
#include "onoe.h"
#ifdef ONOE_DEBUG
enum {
ATH_DEBUG_RATE = 0x00000010, /* rate control */
-diff -ur madwifi.old/ath_rate/sample/sample.c madwifi.dev/ath_rate/sample/sample.c
---- madwifi.old/ath_rate/sample/sample.c 2007-02-20 23:24:27.275770328 +0100
-+++ madwifi.dev/ath_rate/sample/sample.c 2007-02-20 23:23:54.715720208 +0100
-@@ -65,7 +65,7 @@
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath_rate/sample/sample.c madwifi-ng-refcount-r2313-20070505.dev/ath_rate/sample/sample.c
+--- madwifi-ng-refcount-r2313-20070505.old/ath_rate/sample/sample.c 2007-04-09 23:08:06.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/ath_rate/sample/sample.c 2007-05-13 18:17:56.459985816 +0200
+@@ -67,7 +67,7 @@
#include "sample.h"
#ifdef SAMPLE_DEBUG
enum {
ATH_DEBUG_RATE = 0x00000010 /* rate control */
-diff -ur madwifi.old/net80211/ieee80211_proto.c madwifi.dev/net80211/ieee80211_proto.c
---- madwifi.old/net80211/ieee80211_proto.c 2007-02-20 23:23:54.682725000 +0100
-+++ madwifi.dev/net80211/ieee80211_proto.c 2007-02-20 23:26:03.244180912 +0100
-@@ -307,6 +307,7 @@
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_proto.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_proto.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_proto.c 2007-02-01 21:49:37.000000000 +0100
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_proto.c 2007-05-13 18:17:56.460985664 +0200
+@@ -312,6 +312,7 @@
}
EXPORT_SYMBOL(ieee80211_print_essid);
void
ieee80211_dump_pkt(struct ieee80211com *ic,
const u_int8_t *buf, int len, int rate, int rssi)
-@@ -385,6 +386,7 @@
+@@ -390,6 +391,7 @@
}
}
EXPORT_SYMBOL(ieee80211_dump_pkt);
int
ieee80211_fix_rate(struct ieee80211_node *ni, int flags)
-diff -ur madwifi.old/net80211/ieee80211_proto.h madwifi.dev/net80211/ieee80211_proto.h
---- madwifi.old/net80211/ieee80211_proto.h 2006-06-10 04:17:05.000000000 +0200
-+++ madwifi.dev/net80211/ieee80211_proto.h 2007-02-20 23:27:28.791175792 +0100
-@@ -246,7 +246,11 @@
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_proto.h madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_proto.h
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_proto.h 2007-01-30 05:01:29.000000000 +0100
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_proto.h 2007-05-13 18:17:56.460985664 +0200
+@@ -247,7 +247,11 @@
#endif
int ieee80211_new_state(struct ieee80211vap *, enum ieee80211_state, int);
void ieee80211_print_essid(const u_int8_t *, int);
struct sk_buff *ieee80211_getcfframe(struct ieee80211vap *, int);
/*
-diff -ur madwifi.old/net80211/ieee80211_var.h madwifi.dev/net80211/ieee80211_var.h
---- madwifi.old/net80211/ieee80211_var.h 2007-02-20 23:24:27.276770176 +0100
-+++ madwifi.dev/net80211/ieee80211_var.h 2007-02-20 23:23:54.715720208 +0100
-@@ -37,7 +37,7 @@
- /*
- * Definitions for IEEE 802.11 drivers.
- */
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_var.h madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_var.h
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_var.h 2007-05-13 18:17:56.107039472 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_var.h 2007-05-13 18:17:56.461985512 +0200
+@@ -35,8 +35,8 @@
+ #ifndef _NET80211_IEEE80211_VAR_H_
+ #define _NET80211_IEEE80211_VAR_H_
+
-#define IEEE80211_DEBUG
+-#define IEEE80211_DEBUG_REFCNT /* Node reference count debugging */
+#undef IEEE80211_DEBUG
- #undef IEEE80211_DEBUG_REFCNT /* node refcnt stuff */
++#undef IEEE80211_DEBUG_REFCNT /* Node reference count debugging */
+ /* Definitions for IEEE 802.11 drivers. */
#include <net80211/ieee80211_linux.h>
-diff -ur madwifi.old/tools/do_multi.c madwifi.dev/tools/do_multi.c
---- madwifi.old/tools/do_multi.c 2007-02-20 23:24:27.276770176 +0100
-+++ madwifi.dev/tools/do_multi.c 2007-02-20 23:23:54.715720208 +0100
+diff -urN madwifi-ng-refcount-r2313-20070505.old/tools/do_multi.c madwifi-ng-refcount-r2313-20070505.dev/tools/do_multi.c
+--- madwifi-ng-refcount-r2313-20070505.old/tools/do_multi.c 2007-05-13 18:17:55.192178552 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/tools/do_multi.c 2007-05-13 18:17:56.461985512 +0200
@@ -9,16 +9,20 @@
progname = basename(argv[0]);
if(strcmp(progname, "athkey") == 0)
ret = athkey_init(argc, argv);
if(strcmp(progname, "athstats") == 0)
-diff -ur madwifi.old/tools/Makefile madwifi.dev/tools/Makefile
---- madwifi.old/tools/Makefile 2007-02-20 23:24:27.276770176 +0100
-+++ madwifi.dev/tools/Makefile 2007-02-20 23:23:54.716720056 +0100
+diff -urN madwifi-ng-refcount-r2313-20070505.old/tools/Makefile madwifi-ng-refcount-r2313-20070505.dev/tools/Makefile
+--- madwifi-ng-refcount-r2313-20070505.old/tools/Makefile 2007-05-13 18:17:55.192178552 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/tools/Makefile 2007-05-13 18:17:56.461985512 +0200
@@ -52,7 +52,7 @@
ifdef DOMULTI
--- /dev/null
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c
+--- madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c 2007-05-13 18:17:56.576968032 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c 2007-05-13 18:17:56.594965296 +0200
+@@ -170,7 +170,7 @@
+ int, u_int32_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);
++static int ath_rx_poll(struct net_device *dev, int *budget);
+ static int ath_hardstart(struct sk_buff *, struct net_device *);
+ static int ath_mgtstart(struct ieee80211com *, struct sk_buff *);
+ #ifdef ATH_SUPERG_COMP
+@@ -420,7 +420,6 @@
+ ATH_TXBUF_LOCK_INIT(sc);
+ ATH_RXBUF_LOCK_INIT(sc);
+
+- 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);
+@@ -674,6 +673,8 @@
+ dev->set_mac_address = ath_set_mac_address;
+ dev->change_mtu = ath_change_mtu;
+ dev->tx_queue_len = ATH_TXBUF - 1; /* 1 for mgmt frame */
++ dev->poll = ath_rx_poll;
++ dev->weight = 64;
+ #ifdef USE_HEADERLEN_RESV
+ dev->hard_header_len += sizeof(struct ieee80211_qosframe) +
+ sizeof(struct llc) +
+@@ -1645,6 +1646,7 @@
+ */
+ ath_hal_getisr(ah, &status); /* NB: clears ISR too */
+ DPRINTF(sc, ATH_DEBUG_INTR, "%s: status 0x%x\n", __func__, status);
++ sc->sc_isr = status;
+ status &= sc->sc_imask; /* discard unasked for bits */
+ if (status & HAL_INT_FATAL) {
+ sc->sc_stats.ast_hardware++;
+@@ -1684,7 +1686,12 @@
+ * might take too long to fire */
+ ath_hal_process_noisefloor(ah);
+ sc->sc_channoise = ath_hal_get_channel_noise(ah, &(sc->sc_curchan));
+- ATH_SCHEDULE_TQUEUE(&sc->sc_rxtq, &needmark);
++ sc->sc_isr &= ~HAL_INT_RX;
++ if (netif_rx_schedule_prep(dev)) {
++ sc->sc_imask &= ~HAL_INT_RX;
++ ath_hal_intrset(ah, sc->sc_imask);
++ __netif_rx_schedule(dev);
++ }
+ }
+ if (status & HAL_INT_TX) {
+ #ifdef ATH_SUPERG_DYNTURBO
+@@ -1710,6 +1717,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);
+ sc->sc_tx_start = 0;
+ }
+@@ -2221,12 +2233,13 @@
+ * Insert the frame on the outbound list and
+ * pass it on to the hardware.
+ */
+- ATH_TXQ_LOCK(txq);
++ ATH_TXQ_LOCK_BH(txq);
+ if (ni && ni->ni_vap && txq == &ATH_VAP(ni->ni_vap)->av_mcastq) {
+ /*
+ * The CAB queue is started from the SWBA handler since
+ * frames only go out on DTIM and to avoid possible races.
+ */
++ sc->sc_imask &= ~HAL_INT_SWBA;
+ ath_hal_intrset(ah, sc->sc_imask & ~HAL_INT_SWBA);
+ ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
+ DPRINTF(sc, ATH_DEBUG_TX_PROC, "%s: txq depth = %d\n", __func__, txq->axq_depth);
+@@ -2242,6 +2255,7 @@
+ ito64(bf->bf_daddr), bf->bf_desc);
+ }
+ txq->axq_link = &lastds->ds_link;
++ sc->sc_imask |= HAL_INT_SWBA;
+ ath_hal_intrset(ah, sc->sc_imask);
+ } else {
+ ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
+@@ -2275,7 +2289,7 @@
+ sc->sc_tx_start = jiffies;
+ }
+ }
+- ATH_TXQ_UNLOCK(txq);
++ ATH_TXQ_UNLOCK_BH(txq);
+
+ sc->sc_devstats.tx_packets++;
+ sc->sc_devstats.tx_bytes += framelen;
+@@ -2426,8 +2440,14 @@
+ unsigned int pktlen;
+ int framecnt;
+
++ /*
++ * NB: using _BH style locking even though this function may be called
++ * at interrupt time (within tasklet or bh). This should be harmless
++ * and this function calls others (i.e., ath_tx_start()) which do
++ * the same.
++ */
+ for (;;) {
+- ATH_TXQ_LOCK(txq);
++ ATH_TXQ_LOCK_BH(txq);
+
+ bf_ff = TAILQ_LAST(&txq->axq_stageq, axq_headtype);
+ if ((!bf_ff) || ath_ff_flushdonetest(txq, bf_ff)) {
+@@ -2441,7 +2461,7 @@
+ ATH_NODE(ni)->an_tx_ffbuf[bf_ff->bf_skb->priority] = NULL;
+ TAILQ_REMOVE(&txq->axq_stageq, bf_ff, bf_stagelist);
+
+- ATH_TXQ_UNLOCK(txq);
++ ATH_TXQ_UNLOCK_BH(txq);
+
+ /* encap and xmit */
+ bf_ff->bf_skb = ieee80211_encap(ni, bf_ff->bf_skb, &framecnt);
+@@ -2462,15 +2482,16 @@
+ }
+ bf_ff->bf_node = NULL;
+
+- ATH_TXBUF_LOCK_IRQ(sc);
++ ATH_TXBUF_LOCK_BH(sc);
+ STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf_ff, bf_list);
+- ATH_TXBUF_UNLOCK_IRQ(sc);
++ ATH_TXBUF_UNLOCK_BH(sc);
+ }
++ ATH_TXQ_UNLOCK_BH(txq);
+ }
+ #endif
+
+ #define ATH_HARDSTART_GET_TX_BUF_WITH_LOCK \
+- ATH_TXBUF_LOCK_IRQ(sc); \
++ ATH_TXBUF_LOCK_BH(sc); \
+ bf = STAILQ_FIRST(&sc->sc_txbuf); \
+ if (bf != NULL) { \
+ STAILQ_REMOVE_HEAD(&sc->sc_txbuf, bf_list); \
+@@ -2485,10 +2506,21 @@
+ sc->sc_devstopped = 1; \
+ ATH_SCHEDULE_TQUEUE(&sc->sc_txtq, NULL); \
+ } \
+- ATH_TXBUF_UNLOCK_IRQ(sc); \
++
++#define ATH_HARDSTART_REL_TX_BUF_WITH_TXQLOCK_OFF \
++ ATH_TXBUF_UNLOCK_BH(sc); \
++ if (bf == NULL) { /* NB: should not happen */ \
++ DPRINTF(sc,ATH_DEBUG_XMIT,"%s: discard, no xmit buf\n", __func__); \
++ sc->sc_stats.ast_tx_nobuf++; \
++ goto hardstart_fail; \
++ }
++
++#define ATH_HARDSTART_REL_TX_BUF_WITH_TXQLOCK_ON \
++ ATH_TXBUF_UNLOCK_BH(sc); \
+ if (bf == NULL) { /* NB: should not happen */ \
+ DPRINTF(sc,ATH_DEBUG_XMIT, \
+ "%s: discard, no xmit buf\n", __func__); \
++ ATH_TXQ_UNLOCK_BH(txq); \
+ sc->sc_stats.ast_tx_nobuf++; \
+ goto hardstart_fail; \
+ }
+@@ -2552,6 +2584,7 @@
+ if (M_FLAG_GET(skb, M_UAPSD)) {
+ /* bypass FF handling */
+ ATH_HARDSTART_GET_TX_BUF_WITH_LOCK;
++ ATH_HARDSTART_REL_TX_BUF_WITH_TXQLOCK_OFF;
+ if (bf == NULL)
+ goto hardstart_fail;
+ goto ff_bypass;
+@@ -2573,7 +2606,7 @@
+ /* NB: use this lock to protect an->an_ff_txbuf in athff_can_aggregate()
+ * call too.
+ */
+- ATH_TXQ_LOCK(txq);
++ ATH_TXQ_LOCK_BH(txq);
+ if (athff_can_aggregate(sc, eh, an, skb, vap->iv_fragthreshold, &ff_flush)) {
+
+ if (an->an_tx_ffbuf[skb->priority]) { /* i.e., frame on the staging queue */
+@@ -2583,7 +2616,7 @@
+ TAILQ_REMOVE(&txq->axq_stageq, bf, bf_stagelist);
+ an->an_tx_ffbuf[skb->priority] = NULL;
+
+- ATH_TXQ_UNLOCK(txq);
++ ATH_TXQ_UNLOCK_BH(txq);
+
+ /*
+ * chain skbs and add FF magic
+@@ -2610,6 +2643,7 @@
+ * to give the buffer back.
+ */
+ ATH_HARDSTART_GET_TX_BUF_WITH_LOCK;
++ ATH_HARDSTART_REL_TX_BUF_WITH_TXQLOCK_ON;
+ if (bf == NULL) {
+ ATH_TXQ_UNLOCK(txq);
+ goto hardstart_fail;
+@@ -2624,7 +2658,7 @@
+
+ TAILQ_INSERT_HEAD(&txq->axq_stageq, bf, bf_stagelist);
+
+- ATH_TXQ_UNLOCK(txq);
++ ATH_TXQ_UNLOCK_BH(txq);
+
+ return 0;
+ }
+@@ -2635,7 +2669,7 @@
+ TAILQ_REMOVE(&txq->axq_stageq, bf_ff, bf_stagelist);
+ an->an_tx_ffbuf[skb->priority] = NULL;
+
+- ATH_TXQ_UNLOCK(txq);
++ ATH_TXQ_UNLOCK_BH(txq);
+
+ /* encap and xmit */
+ bf_ff->bf_skb = ieee80211_encap(ni, bf_ff->bf_skb, &framecnt);
+@@ -2665,9 +2699,9 @@
+ }
+ bf_ff->bf_node = NULL;
+
+- ATH_TXBUF_LOCK(sc);
++ ATH_TXBUF_LOCK_BH(sc);
+ STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf_ff, bf_list);
+- ATH_TXBUF_UNLOCK(sc);
++ ATH_TXBUF_UNLOCK_BH(sc);
+ goto ff_flushdone;
+ }
+ /*
+@@ -2691,6 +2725,7 @@
+ #else /* ATH_SUPERG_FF */
+
+ ATH_HARDSTART_GET_TX_BUF_WITH_LOCK;
++ ATH_HARDSTART_REL_TX_BUF_WITH_TXQLOCK_OFF;
+
+ #endif /* ATH_SUPERG_FF */
+
+@@ -2712,7 +2747,7 @@
+ * Allocate 1 ath_buf for each frame given 1 was
+ * already alloc'd
+ */
+- ATH_TXBUF_LOCK(sc);
++ ATH_TXBUF_LOCK_BH(sc);
+ for (bfcnt = 1; bfcnt < framecnt; ++bfcnt) {
+ if ((tbf = STAILQ_FIRST(&sc->sc_txbuf)) != NULL) {
+ STAILQ_REMOVE_HEAD(&sc->sc_txbuf, bf_list);
+@@ -2733,11 +2768,11 @@
+ STAILQ_INSERT_TAIL(&sc->sc_txbuf, tbf, bf_list);
+ }
+ }
+- ATH_TXBUF_UNLOCK(sc);
++ ATH_TXBUF_UNLOCK_BH(sc);
+ STAILQ_INIT(&bf_head);
+ goto hardstart_fail;
+ }
+- ATH_TXBUF_UNLOCK(sc);
++ ATH_TXBUF_UNLOCK_BH(sc);
+
+ while ((bf = STAILQ_FIRST(&bf_head)) != NULL && skb != NULL) {
+ unsigned int nextfraglen = 0;
+@@ -2773,7 +2808,7 @@
+
+ hardstart_fail:
+ if (!STAILQ_EMPTY(&bf_head)) {
+- ATH_TXBUF_LOCK(sc);
++ ATH_TXBUF_LOCK_BH(sc);
+ STAILQ_FOREACH_SAFE(tbf, &bf_head, bf_list, tempbf) {
+ tbf->bf_skb = NULL;
+ tbf->bf_node = NULL;
+@@ -2783,7 +2818,7 @@
+
+ STAILQ_INSERT_TAIL(&sc->sc_txbuf, tbf, bf_list);
+ }
+- ATH_TXBUF_UNLOCK(sc);
++ ATH_TXBUF_UNLOCK_BH(sc);
+ }
+
+ /* free sk_buffs */
+@@ -2826,7 +2861,7 @@
+ /*
+ * Grab a TX buffer and associated resources.
+ */
+- ATH_TXBUF_LOCK_IRQ(sc);
++ ATH_TXBUF_LOCK_BH(sc);
+ bf = STAILQ_FIRST(&sc->sc_txbuf);
+ if (bf != NULL)
+ STAILQ_REMOVE_HEAD(&sc->sc_txbuf, bf_list);
+@@ -2837,7 +2872,7 @@
+ sc->sc_devstopped=1;
+ ATH_SCHEDULE_TQUEUE(&sc->sc_txtq, NULL);
+ }
+- ATH_TXBUF_UNLOCK_IRQ(sc);
++ ATH_TXBUF_UNLOCK_BH(sc);
+ if (bf == NULL) {
+ printk("ath_mgtstart: discard, no xmit buf\n");
+ sc->sc_stats.ast_tx_nobufmgt++;
+@@ -2866,9 +2901,9 @@
+ bf->bf_skb = NULL;
+ bf->bf_node = NULL;
+
+- ATH_TXBUF_LOCK_IRQ(sc);
++ ATH_TXBUF_LOCK_BH(sc);
+ STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
+- ATH_TXBUF_UNLOCK_IRQ(sc);
++ ATH_TXBUF_UNLOCK_BH(sc);
+ }
+ dev_kfree_skb_any(skb);
+ skb = NULL;
+@@ -3336,10 +3371,10 @@
+ *
+ * XXX Using in_softirq is not right since we might
+ * be called from other soft irq contexts than
+- * ath_rx_tasklet.
++ * ath_rx_poll
+ */
+ if (!in_softirq())
+- tasklet_disable(&sc->sc_rxtq);
++ netif_poll_disable(dev);
+ netif_stop_queue(dev);
+ }
+
+@@ -3352,7 +3387,7 @@
+ DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__);
+ netif_start_queue(dev);
+ if (!in_softirq()) /* NB: see above */
+- tasklet_enable(&sc->sc_rxtq);
++ netif_poll_enable(dev);
+ }
+
+ /*
+@@ -4912,9 +4947,9 @@
+ bf->bf_node = NULL;
+ bf->bf_desc->ds_link = 0;
+
+- ATH_TXBUF_LOCK_IRQ(sc);
++ ATH_TXBUF_LOCK_BH(sc);
+ STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
+- ATH_TXBUF_UNLOCK_IRQ(sc);
++ ATH_TXBUF_UNLOCK_BH(sc);
+
+ an->an_uapsd_overflowqdepth--;
+ }
+@@ -5585,13 +5620,12 @@
+ sc->sc_rxotherant = 0;
+ }
+
+-static void
+-ath_rx_tasklet(TQUEUE_ARG data)
++static int
++ath_rx_poll(struct net_device *dev, int *budget)
+ {
+ #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;
+ struct ath_softc *sc = dev->priv;
+ struct ieee80211com *ic = &sc->sc_ic;
+@@ -5602,11 +5636,15 @@
+ unsigned int len;
+ int type;
+ u_int phyerr;
++ int processed = 0, early_stop = 0;
++ int rx_limit = dev->quota;
+
+ /* Let the 802.11 layer know about the new noise floor */
+ ic->ic_channoise = sc->sc_channoise;
+
+ DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s\n", __func__);
++
++process_rx_again:
+ do {
+ bf = STAILQ_FIRST(&sc->sc_rxbuf);
+ if (bf == NULL) { /* XXX ??? can this happen */
+@@ -5630,6 +5668,13 @@
+ /* NB: never process the self-linked entry at the end */
+ break;
+ }
++
++ processed++;
++ if (rx_limit-- < 0) {
++ early_stop = 1;
++ break;
++ }
++
+ skb = bf->bf_skb;
+ if (skb == NULL) { /* XXX ??? can this happen */
+ printk("%s: no skbuff (%s)\n", dev->name, __func__);
+@@ -5878,6 +5923,25 @@
+ STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
+ ATH_RXBUF_UNLOCK_IRQ(sc);
+ } while (ath_rxbuf_init(sc, bf) == 0);
++ if (!early_stop) {
++ /* Check if more data is received while we were
++ * processing the descriptor chain.
++ */
++ ATH_DISABLE_INTR();
++ if (sc->sc_isr & HAL_INT_RX) {
++ sc->sc_isr &= ~HAL_INT_RX;
++ ATH_ENABLE_INTR();
++ ath_uapsd_processtriggers(sc);
++ goto process_rx_again;
++ }
++ netif_rx_complete(dev);
++
++ sc->sc_imask |= HAL_INT_RX;
++ ath_hal_intrset(ah, sc->sc_imask);
++ ATH_ENABLE_INTR();
++ }
++
++ *budget -= processed;
+
+ /* rx signal state monitoring */
+ ath_hal_rxmonitor(ah, &sc->sc_halstats, &sc->sc_curchan);
+@@ -5885,6 +5949,7 @@
+ sc->sc_rtasksched = 1;
+ schedule_work(&sc->sc_radartask);
+ }
++ return early_stop;
+ #undef PA2DESC
+ }
+
+@@ -6160,22 +6225,22 @@
+ }
+ }
+
+- ATH_TXBUF_LOCK_IRQ(sc);
++ ATH_TXBUF_LOCK_BH(sc);
+ bf = STAILQ_FIRST(&sc->sc_grppollbuf);
+ if (bf != NULL)
+ STAILQ_REMOVE_HEAD(&sc->sc_grppollbuf, bf_list);
+ else {
+ DPRINTF(sc, ATH_DEBUG_XMIT, "%s: No more TxBufs\n", __func__);
+- ATH_TXBUF_UNLOCK_IRQ_EARLY(sc);
++ ATH_TXBUF_UNLOCK_BH(sc);
+ return;
+ }
+ /* XXX use a counter and leave at least one for mgmt frames */
+ if (STAILQ_EMPTY(&sc->sc_grppollbuf)) {
+ DPRINTF(sc, ATH_DEBUG_XMIT, "%s: No more TxBufs left\n", __func__);
+- ATH_TXBUF_UNLOCK_IRQ_EARLY(sc);
++ ATH_TXBUF_UNLOCK_BH(sc);
+ return;
+ }
+- ATH_TXBUF_UNLOCK_IRQ(sc);
++ ATH_TXBUF_UNLOCK_BH(sc);
+
+ bf->bf_skbaddr = bus_map_single(sc->sc_bdev,
+ skb->data, skb->len, BUS_DMA_TODEVICE);
+@@ -6641,9 +6706,9 @@
+ dev_kfree_skb(lastbuf->bf_skb);
+ lastbuf->bf_skb = NULL;
+ ieee80211_unref_node(&lastbuf->bf_node);
+- ATH_TXBUF_LOCK_IRQ(sc);
++ ATH_TXBUF_LOCK_BH(sc);
+ STAILQ_INSERT_TAIL(&sc->sc_txbuf, lastbuf, bf_list);
+- ATH_TXBUF_UNLOCK_IRQ(sc);
++ ATH_TXBUF_UNLOCK_BH(sc);
+
+ /*
+ * move oldest from overflow to delivery
+@@ -7462,9 +7527,6 @@
+ if (sc->sc_reapcount > ATH_TXBUF_FREE_THRESHOLD) {
+ if (!sc->sc_dfswait)
+ netif_start_queue(sc->sc_dev);
+- DPRINTF(sc, ATH_DEBUG_TX_PROC,
+- "%s: tx tasklet restart the queue\n",
+- __func__);
+ sc->sc_reapcount = 0;
+ sc->sc_devstopped = 0;
+ } else
+@@ -7499,11 +7561,22 @@
+ struct net_device *dev = (struct net_device *)data;
+ struct ath_softc *sc = dev->priv;
+
++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);
+
++ ATH_DISABLE_INTR();
++ if (sc->sc_isr & HAL_INT_TX) {
++ sc->sc_isr &= ~HAL_INT_TX;
++ ATH_ENABLE_INTR();
++ goto process_tx_again;
++ }
++ sc->sc_imask |= HAL_INT_TX;
++ ath_hal_intrset(sc->sc_ah, sc->sc_imask);
++ ATH_ENABLE_INTR();
++
+ netif_wake_queue(dev);
+
+ if (sc->sc_softled)
+@@ -7520,6 +7593,7 @@
+ struct net_device *dev = (struct net_device *)data;
+ struct ath_softc *sc = dev->priv;
+
++process_tx_again:
+ /*
+ * Process each active queue.
+ */
+@@ -7540,6 +7614,16 @@
+ if (sc->sc_uapsdq && txqactive(sc->sc_ah, sc->sc_uapsdq->axq_qnum))
+ ath_tx_processq(sc, sc->sc_uapsdq);
+
++ ATH_DISABLE_INTR();
++ if (sc->sc_isr & HAL_INT_TX) {
++ sc->sc_isr &= ~HAL_INT_TX;
++ ATH_ENABLE_INTR();
++ goto process_tx_again;
++ }
++ sc->sc_imask |= HAL_INT_TX;
++ ath_hal_intrset(sc->sc_ah, sc->sc_imask);
++ ATH_ENABLE_INTR();
++
+ netif_wake_queue(dev);
+
+ if (sc->sc_softled)
+@@ -7557,6 +7641,7 @@
+ unsigned int i;
+
+ /* Process each active queue. */
++process_tx_again:
+ for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
+ if (ATH_TXQ_SETUP(sc, i) && txqactive(sc->sc_ah, i))
+ ath_tx_processq(sc, &sc->sc_txq[i]);
+@@ -7565,6 +7650,16 @@
+ ath_tx_processq(sc, sc->sc_xrtxq);
+ #endif
+
++ ATH_DISABLE_INTR();
++ if (sc->sc_isr & HAL_INT_TX) {
++ sc->sc_isr &= ~HAL_INT_TX;
++ ATH_ENABLE_INTR();
++ goto process_tx_again;
++ }
++ sc->sc_imask |= HAL_INT_TX;
++ ath_hal_intrset(sc->sc_ah, sc->sc_imask);
++ ATH_ENABLE_INTR();
++
+ netif_wake_queue(dev);
+
+ if (sc->sc_softled)
+@@ -9221,9 +9316,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);
++ netif_poll_disable(dev);
+ error = ath_reset(dev);
+- tasklet_enable(&sc->sc_rxtq);
++ netif_poll_enable(dev);
+ }
+ ATH_UNLOCK(sc);
+
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath/if_athvar.h madwifi-ng-refcount-r2313-20070505.dev/ath/if_athvar.h
+--- madwifi-ng-refcount-r2313-20070505.old/ath/if_athvar.h 2007-05-13 18:17:56.363000560 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/ath/if_athvar.h 2007-05-13 18:17:56.595965144 +0200
+@@ -47,6 +47,10 @@
+ #include "if_athioctl.h"
+ #include "net80211/ieee80211.h" /* XXX for WME_NUM_AC */
+
++#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.
+@@ -477,8 +481,12 @@
+ #define ATH_TXQ_LOCK_DESTROY(_tq)
+ #define ATH_TXQ_LOCK(_tq) spin_lock(&(_tq)->axq_lock)
+ #define ATH_TXQ_UNLOCK(_tq) spin_unlock(&(_tq)->axq_lock)
+-#define ATH_TXQ_LOCK_BH(_tq) spin_lock_bh(&(_tq)->axq_lock)
+-#define ATH_TXQ_UNLOCK_BH(_tq) spin_unlock_bh(&(_tq)->axq_lock)
++#define ATH_TXQ_LOCK_BH(_tq) \
++ if (!irqs_disabled()) \
++ spin_lock_bh(&(_tq)->axq_lock)
++#define ATH_TXQ_UNLOCK_BH(_tq) \
++ if (!irqs_disabled()) \
++ spin_unlock_bh(&(_tq)->axq_lock)
+ #define ATH_TXQ_LOCK_IRQ(_tq) do { \
+ unsigned long __axq_lockflags; \
+ spin_lock_irqsave(&(_tq)->axq_lock, __axq_lockflags);
+@@ -627,7 +635,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_int8_t sc_defant; /* current default antenna */
+ u_int8_t sc_rxotherant; /* rx's on non-default antenna*/
+@@ -640,6 +647,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 */
+@@ -706,8 +714,12 @@
+ #define ATH_TXBUF_LOCK_DESTROY(_sc)
+ #define ATH_TXBUF_LOCK(_sc) spin_lock(&(_sc)->sc_txbuflock)
+ #define ATH_TXBUF_UNLOCK(_sc) spin_unlock(&(_sc)->sc_txbuflock)
+-#define ATH_TXBUF_LOCK_BH(_sc) spin_lock_bh(&(_sc)->sc_txbuflock)
+-#define ATH_TXBUF_UNLOCK_BH(_sc) spin_unlock_bh(&(_sc)->sc_txbuflock)
++#define ATH_TXBUF_LOCK_BH(_sc) \
++ if (!irqs_disabled()) \
++ spin_lock_bh(&(_sc)->sc_txbuflock)
++#define ATH_TXBUF_UNLOCK_BH(_sc) \
++ if (!irqs_disabled()) \
++ spin_unlock_bh(&(_sc)->sc_txbuflock)
+ #define ATH_TXBUF_LOCK_IRQ(_sc) do { \
+ unsigned long __txbuflockflags; \
+ spin_lock_irqsave(&(_sc)->sc_txbuflock, __txbuflockflags);
+@@ -725,8 +737,12 @@
+ #define ATH_RXBUF_LOCK_DESTROY(_sc)
+ #define ATH_RXBUF_LOCK(_sc) spin_lock(&(_sc)->sc_rxbuflock)
+ #define ATH_RXBUF_UNLOCK(_sc) spin_unlock(&(_sc)->sc_rxbuflock)
+-#define ATH_RXBUF_LOCK_BH(_sc) spin_lock_bh(&(_sc)->sc_rxbuflock)
+-#define ATH_RXBUF_UNLOCK_BH(_sc) spin_unlock_bh(&(_sc)->sc_rxbuflock)
++#define ATH_RXBUF_LOCK_BH(_sc) \
++ if (!irqs_disabled()) \
++ spin_lock_bh(&(_sc)->sc_rxbuflock)
++#define ATH_RXBUF_UNLOCK_BH(_sc) \
++ if (!irqs_disabled()) \
++ spin_unlock_bh(&(_sc)->sc_rxbuflock)
+ #define ATH_RXBUF_LOCK_IRQ(_sc) do { \
+ unsigned long __rxbuflockflags; \
+ spin_lock_irqsave(&(_sc)->sc_rxbuflock, __rxbuflockflags);
+@@ -736,6 +752,8 @@
+ #define ATH_RXBUF_UNLOCK_IRQ_EARLY(_sc) \
+ spin_unlock_irqrestore(&(_sc)->sc_rxbuflock, __rxbuflockflags);
+
++#define ATH_DISABLE_INTR local_irq_disable
++#define ATH_ENABLE_INTR local_irq_enable
+
+ /* Protects the device from concurrent accesses */
+ #define ATH_LOCK_INIT(_sc) init_MUTEX(&(_sc)->sc_lock)
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_beacon.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_beacon.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_beacon.c 2007-01-30 05:01:29.000000000 +0100
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_beacon.c 2007-05-13 18:17:56.596964992 +0200
+@@ -286,7 +286,7 @@
+ int len_changed = 0;
+ u_int16_t capinfo;
+
+- IEEE80211_LOCK(ic);
++ IEEE80211_BEACON_LOCK(ic);
+
+ if ((ic->ic_flags & IEEE80211_F_DOTH) &&
+ (vap->iv_flags & IEEE80211_F_CHANSWITCH) &&
+@@ -547,7 +547,7 @@
+ vap->iv_flags_ext &= ~IEEE80211_FEXT_APPIE_UPDATE;
+ }
+
+- IEEE80211_UNLOCK(ic);
++ IEEE80211_BEACON_UNLOCK(ic);
+
+ return len_changed;
+ }
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_input.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_input.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_input.c 2007-05-13 18:17:56.106039624 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_input.c 2007-05-13 18:17:56.597964840 +0200
+@@ -1148,8 +1148,9 @@
+ if (ni->ni_vlan != 0 && vap->iv_vlgrp != NULL) {
+ /* attach vlan tag */
+ vlan_hwaccel_receive_skb(skb, vap->iv_vlgrp, ni->ni_vlan);
+- } else
+- netif_rx(skb);
++ } else {
++ netif_receive_skb(skb);
++ }
+ dev->last_rx = jiffies;
+ }
+ }
+@@ -3623,9 +3624,9 @@
+ }
+
+ /* Okay, take the first queued packet and put it out... */
+- IEEE80211_NODE_SAVEQ_LOCK(ni);
++ IEEE80211_NODE_SAVEQ_LOCK_IRQ(ni);
+ IEEE80211_NODE_SAVEQ_DEQUEUE(ni, skb, qlen);
+- IEEE80211_NODE_SAVEQ_UNLOCK(ni);
++ IEEE80211_NODE_SAVEQ_UNLOCK_IRQ(ni);
+ if (skb == NULL) {
+ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_POWER, wh->i_addr2,
+ "%s", "recv ps-poll, but queue empty");
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_linux.h madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_linux.h
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_linux.h 2007-05-04 02:10:06.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_linux.h 2007-05-13 18:17:56.598964688 +0200
+@@ -31,6 +31,10 @@
+
+ #include <linux/wireless.h>
+
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++#define irqs_disabled() 0
++#endif
++
+ /*
+ * Task deferral
+ *
+@@ -86,8 +90,12 @@
+ } while (0)
+ #define IEEE80211_UNLOCK_IRQ_EARLY(_ic) \
+ spin_unlock_irqrestore(&(_ic)->ic_comlock, __ilockflags);
+-#define IEEE80211_LOCK_BH(_ic) spin_lock_bh(&(_ic)->ic_comlock)
+-#define IEEE80211_UNLOCK_BH(_ic) spin_unlock_bh(&(_ic)->ic_comlock)
++#define IEEE80211_LOCK_BH(_ic) \
++ if (!irqs_disabled()) \
++ spin_lock_bh(&(_ic)->ic_comlock)
++#define IEEE80211_UNLOCK_BH(_ic) \
++ if (!irqs_disabled()) \
++ spin_unlock_bh(&(_ic)->ic_comlock)
+ #define IEEE80211_LOCK(_ic) spin_lock(&(_ic)->ic_comlock)
+ #define IEEE80211_UNLOCK(_ic) spin_unlock(&(_ic)->ic_comlock)
+
+@@ -104,15 +112,22 @@
+ #define IEEE80211_VAPS_LOCK_DESTROY(_ic)
+ #define IEEE80211_VAPS_LOCK(_ic) spin_lock(&(_ic)->ic_vapslock);
+ #define IEEE80211_VAPS_UNLOCK(_ic) spin_unlock(&(_ic)->ic_vapslock);
+-#define IEEE80211_VAPS_LOCK_BH(_ic) spin_lock_bh(&(_ic)->ic_vapslock);
+-#define IEEE80211_VAPS_UNLOCK_BH(_ic) spin_unlock_bh(&(_ic)->ic_vapslock);
+-#define IEEE80211_VAPS_LOCK_IRQ(_ic) do { \
+- int _vaps_lockflags; \
+- spin_lock_irqsave(&(_ic)->ic_vapslock, _vaps_lockflags);
+-#define IEEE80211_VAPS_UNLOCK_IRQ(_ic) \
+- spin_unlock_irqrestore(&(_ic)->ic_vapslock, _vaps_lockflags); \
+-} while (0)
+-#define IEEE80211_VAPS_UNLOCK_IRQ_EARLY(_ic) spin_unlock_irqrestore(&(_ic)->ic_vapslock, _vaps_lockflags)
++#define IEEE80211_VAPS_LOCK_BH(_ic) \
++ if (!irqs_disabled()) \
++ spin_lock_bh(&(_ic)->ic_vapslock);
++#define IEEE80211_VAPS_UNLOCK_BH(_ic) \
++ if (!irqs_disabled()) \
++ spin_unlock_bh(&(_ic)->ic_vapslock);
++#define IEEE80211_VAPS_LOCK_IRQ(_ic) do { \
++ unsigned long __vlockflags=0; \
++ unsigned int __vlocked=0; \
++ __vlocked=spin_is_locked(&(_ic)->ic_vapslock); \
++ if(!__vlocked) spin_lock_irqsave(&(_ic)->ic_vapslock, __vlockflags);
++#define IEEE80211_VAPS_UNLOCK_IRQ(_ic) \
++ if(!__vlocked) spin_unlock_irqrestore(&(_ic)->ic_vapslock, __vlockflags); \
++} while (0);
++#define IEEE80211_VAPS_UNLOCK_IRQ_EARLY(_ic) \
++ if (!__vlocked) spin_unlock_irqrestore(&(_ic)->ic_vapslock, _vaps_lockflags)
+
+ #if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
+ #define IEEE80211_VAPS_LOCK_ASSERT(_ic) \
+@@ -122,6 +137,11 @@
+ #define IEEE80211_VAPS_LOCK_ASSERT(_ic)
+ #endif
+
++/*
++ * Beacon locking definitions; piggyback on com lock.
++ */
++#define IEEE80211_BEACON_LOCK(_ic) IEEE80211_LOCK_IRQ(_ic)
++#define IEEE80211_BEACON_UNLOCK(_ic) IEEE80211_UNLOCK_IRQ(_ic)
+
+ /*
+ * Node locking definitions.
+@@ -191,8 +211,12 @@
+ typedef spinlock_t ieee80211_scan_lock_t;
+ #define IEEE80211_SCAN_LOCK_INIT(_nt, _name) spin_lock_init(&(_nt)->nt_scanlock)
+ #define IEEE80211_SCAN_LOCK_DESTROY(_nt)
+-#define IEEE80211_SCAN_LOCK_BH(_nt) spin_lock_bh(&(_nt)->nt_scanlock)
+-#define IEEE80211_SCAN_UNLOCK_BH(_nt) spin_unlock_bh(&(_nt)->nt_scanlock)
++#define IEEE80211_SCAN_LOCK_BH(_nt) \
++ if (!irqs_disabled()) \
++ spin_lock_bh(&(_nt)->nt_scanlock)
++#define IEEE80211_SCAN_UNLOCK_BH(_nt) \
++ if (!irqs_disabled()) \
++ spin_unlock_bh(&(_nt)->nt_scanlock)
+ #define IEEE80211_SCAN_LOCK_IRQ(_nt) do { \
+ unsigned long __scan_lockflags; \
+ spin_lock_irqsave(&(_nt)->nt_scanlock, __scan_lockflags);
+@@ -217,8 +241,12 @@
+ #define ACL_LOCK_DESTROY(_as)
+ #define ACL_LOCK(_as) spin_lock(&(_as)->as_lock)
+ #define ACL_UNLOCK(_as) spin_unlock(&(_as)->as_lock)
+-#define ACL_LOCK_BH(_as) spin_lock_bh(&(_as)->as_lock)
+-#define ACL_UNLOCK_BH(_as) spin_unlock_bh(&(_as)->as_lock)
++#define ACL_LOCK_BH(_as) \
++ if (!irqs_disabled()) \
++ spin_lock_bh(&(_as)->as_lock)
++#define ACL_UNLOCK_BH(_as) \
++ if (!irqs_disabled()) \
++ spin_unlock_bh(&(_as)->as_lock)
+
+ #if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
+ #define ACL_LOCK_ASSERT(_as) \
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_node.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_node.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_node.c 2007-05-13 18:17:56.273014240 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_node.c 2007-05-13 18:17:56.599964536 +0200
+@@ -1567,7 +1567,7 @@
+ struct ieee80211_node *ni;
+ u_int gen;
+
+- IEEE80211_SCAN_LOCK_IRQ(nt);
++ IEEE80211_SCAN_LOCK_BH(nt);
+ gen = ++nt->nt_scangen;
+
+ restart:
+@@ -1587,7 +1587,7 @@
+ }
+ IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
+
+- IEEE80211_SCAN_UNLOCK_IRQ(nt);
++ IEEE80211_SCAN_UNLOCK_BH(nt);
+ }
+ EXPORT_SYMBOL(ieee80211_iterate_dev_nodes);
+
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_power.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_power.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_power.c 2007-04-25 22:29:55.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_power.c 2007-05-13 18:17:56.599964536 +0200
+@@ -147,7 +147,7 @@
+ #endif
+ struct sk_buff *skb;
+
+- IEEE80211_NODE_SAVEQ_LOCK(ni);
++ IEEE80211_NODE_SAVEQ_LOCK_IRQ(ni);
+ while ((skb = skb_peek(&ni->ni_savedq)) != NULL &&
+ M_AGE_GET(skb) < IEEE80211_INACT_WAIT) {
+ IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
+@@ -159,7 +159,7 @@
+ }
+ if (skb != NULL)
+ M_AGE_SUB(skb, IEEE80211_INACT_WAIT);
+- IEEE80211_NODE_SAVEQ_UNLOCK(ni);
++ IEEE80211_NODE_SAVEQ_UNLOCK_IRQ(ni);
+
+ IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
+ "discard %u frames for age", discard);
+@@ -185,7 +185,7 @@
+ KASSERT(aid < vap->iv_max_aid,
+ ("bogus aid %u, max %u", aid, vap->iv_max_aid));
+
+- IEEE80211_LOCK(ni->ni_ic);
++ IEEE80211_BEACON_LOCK(ni->ni_ic);
+ if (set != (isset(vap->iv_tim_bitmap, aid) != 0)) {
+ if (set) {
+ setbit(vap->iv_tim_bitmap, aid);
+@@ -196,7 +196,7 @@
+ }
+ vap->iv_flags |= IEEE80211_F_TIMUPDATE;
+ }
+- IEEE80211_UNLOCK(ni->ni_ic);
++ IEEE80211_BEACON_UNLOCK(ni->ni_ic);
+ }
+
+ /*
+@@ -297,9 +297,9 @@
+ struct sk_buff *skb;
+ int qlen;
+
+- IEEE80211_NODE_SAVEQ_LOCK(ni);
++ IEEE80211_NODE_SAVEQ_LOCK_IRQ(ni);
+ IEEE80211_NODE_SAVEQ_DEQUEUE(ni, skb, qlen);
+- IEEE80211_NODE_SAVEQ_UNLOCK(ni);
++ IEEE80211_NODE_SAVEQ_UNLOCK_IRQ(ni);
+ if (skb == NULL)
+ break;
+ /*
+@@ -363,9 +363,9 @@
+ for (;;) {
+ struct sk_buff *skb;
+
+- IEEE80211_NODE_SAVEQ_LOCK(ni);
++ IEEE80211_NODE_SAVEQ_LOCK_IRQ(ni);
+ skb = __skb_dequeue(&ni->ni_savedq);
+- IEEE80211_NODE_SAVEQ_UNLOCK(ni);
++ IEEE80211_NODE_SAVEQ_UNLOCK_IRQ(ni);
+ if (skb == NULL)
+ break;
+ ieee80211_parent_queue_xmit(skb);
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_proto.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_proto.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_proto.c 2007-05-13 18:17:56.578967728 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_proto.c 2007-05-13 18:17:56.600964384 +0200
+@@ -635,9 +635,9 @@
+ {
+ struct ieee80211com *ic = vap->iv_ic;
+
+- IEEE80211_LOCK(ic);
++ IEEE80211_BEACON_LOCK(ic);
+ ieee80211_wme_initparams_locked(vap);
+- IEEE80211_UNLOCK(ic);
++ IEEE80211_BEACON_UNLOCK(ic);
+ }
+
+ void
+@@ -920,9 +920,9 @@
+ struct ieee80211com *ic = vap->iv_ic;
+
+ if (ic->ic_caps & IEEE80211_C_WME) {
+- IEEE80211_LOCK(ic);
++ IEEE80211_BEACON_LOCK(ic);
+ ieee80211_wme_updateparams_locked(vap);
+- IEEE80211_UNLOCK(ic);
++ IEEE80211_BEACON_UNLOCK(ic);
+ }
+ }
+
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_scan_sta.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_scan_sta.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_scan_sta.c 2007-02-01 21:49:37.000000000 +0100
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_scan_sta.c 2007-05-13 18:17:56.601964232 +0200
+@@ -163,9 +163,11 @@
+ {
+ struct sta_table *st = ss->ss_priv;
+
+- spin_lock(&st->st_lock);
++ if (!irqs_disabled())
++ spin_lock_bh(&st->st_lock);
+ sta_flush_table(st);
+- spin_unlock(&st->st_lock);
++ if (!irqs_disabled())
++ spin_unlock_bh(&st->st_lock);
+ ss->ss_last = 0;
+ return 0;
+ }
+@@ -215,7 +217,8 @@
+ int hash;
+
+ hash = STA_HASH(macaddr);
+- spin_lock(&st->st_lock);
++ if (!irqs_disabled())
++ spin_lock_bh(&st->st_lock);
+ LIST_FOREACH(se, &st->st_hash[hash], se_hash)
+ if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr) &&
+ sp->ssid[1] == se->base.se_ssid[1] &&
+@@ -225,7 +228,7 @@
+ MALLOC(se, struct sta_entry *, sizeof(struct sta_entry),
+ M_80211_SCAN, M_NOWAIT | M_ZERO);
+ if (se == NULL) {
+- spin_unlock(&st->st_lock);
++ spin_unlock_bh(&st->st_lock);
+ return 0;
+ }
+ se->se_scangen = st->st_scangen-1;
+@@ -287,7 +290,8 @@
+ se->se_seen = 1;
+ se->se_notseen = 0;
+
+- spin_unlock(&st->st_lock);
++ if (!irqs_disabled())
++ spin_unlock_bh(&st->st_lock);
+
+ /*
+ * If looking for a quick choice and nothing's
+@@ -1063,7 +1067,8 @@
+ u_int gen;
+ int res = 0;
+
+- spin_lock(&st->st_scanlock);
++ if (!irqs_disabled())
++ spin_lock_bh(&st->st_scanlock);
+ gen = st->st_scangen++;
+ restart:
+ spin_lock(&st->st_lock);
+@@ -1086,7 +1091,8 @@
+ spin_unlock(&st->st_lock);
+
+ done:
+- spin_unlock(&st->st_scanlock);
++ if (!irqs_disabled())
++ spin_unlock_bh(&st->st_scanlock);
+
+ return res;
+ }
+@@ -1235,7 +1241,8 @@
+ bestchan = NULL;
+ bestrssi = -1;
+
+- spin_lock(&st->st_lock);
++ if (!irqs_disabled())
++ spin_lock_bh(&st->st_lock);
+ for (i = 0; i < ss->ss_last; i++) {
+ c = ss->ss_chans[i];
+ maxrssi = 0;
+@@ -1248,7 +1255,8 @@
+ if (bestchan == NULL || maxrssi < bestrssi)
+ bestchan = c;
+ }
+- spin_unlock(&st->st_lock);
++ if (!irqs_disabled())
++ spin_unlock_bh(&st->st_lock);
+
+ return bestchan;
+ }
--- /dev/null
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c
+--- madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c 2007-05-13 18:17:56.686951312 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c 2007-05-13 18:17:56.700949184 +0200
+@@ -3426,7 +3426,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 |
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_input.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_input.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_input.c 2007-05-13 18:17:56.688951008 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_input.c 2007-05-13 18:17:56.701949032 +0200
+@@ -343,11 +343,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_bss->ni_bssid) &&
+- !IEEE80211_ADDR_EQ(bssid, dev->broadcast)) {
++ !IEEE80211_ADDR_EQ(bssid, dev->broadcast) &&
++ (subtype != IEEE80211_FC0_SUBTYPE_BEACON)) {
+ /*
+ * allow MGT frames to vap->iv_xrvap.
+ * this will allow roaming between XR and normal vaps
+@@ -366,7 +367,8 @@
+ }
+ #else
+ if (!IEEE80211_ADDR_EQ(bssid, vap->iv_bss->ni_bssid) &&
+- !IEEE80211_ADDR_EQ(bssid, dev->broadcast)) {
++ !IEEE80211_ADDR_EQ(bssid, dev->broadcast) &&
++ (subtype != IEEE80211_FC0_SUBTYPE_BEACON)) {
+ /* not interested in */
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
+ bssid, NULL, "%s", "not to bss");
+@@ -2560,7 +2562,7 @@
+ u_int8_t *frm, *efrm;
+ u_int8_t *ssid, *rates, *xrates, *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;
+
+ wh = (struct ieee80211_frame *) skb->data;
+@@ -2582,11 +2584,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;
+ }
+@@ -2669,6 +2675,7 @@
+ break;
+ }
+ scan.erp = frm[2];
++ has_erp = 1;
+ break;
+ case IEEE80211_ELEMID_RSN:
+ scan.rsn = frm;
+@@ -2810,7 +2817,7 @@
+ vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) {
+ mod_timer(&vap->iv_swbmiss, jiffies + vap->iv_swbmiss_period);
+ }
+-
++
+ /*
+ * If scanning, pass the info to the scan module.
+ * Otherwise, check if it's the right time to do
+@@ -2832,6 +2839,20 @@
+ ieee80211_bg_scan(vap);
+ return;
+ }
++
++ /* 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.
+ */
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_node.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_node.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_node.c 2007-05-13 18:17:56.690950704 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_node.c 2007-05-13 18:17:56.702948880 +0200
+@@ -331,10 +331,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));
+ }
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_proto.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_proto.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_proto.c 2007-05-13 18:17:56.691950552 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_proto.c 2007-05-13 18:17:56.703948728 +0200
+@@ -586,6 +586,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
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_var.h madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_var.h
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_var.h 2007-05-13 18:17:56.579967576 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_var.h 2007-05-13 18:17:56.704948576 +0200
+@@ -581,6 +581,8 @@
+ void ieee80211_build_countryie(struct ieee80211com *);
+ int ieee80211_media_setup(struct ieee80211com *, struct ifmedia *, u_int32_t,
+ ifm_change_cb_t, ifm_stat_cb_t);
++void ieee80211_setpuregbasicrates(struct ieee80211_rateset *rs);
++
+
+ /* Key update synchronization methods. XXX should not be visible. */
+ static __inline void
--- /dev/null
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_wireless.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_wireless.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_wireless.c 2007-05-13 18:17:56.109039168 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_wireless.c 2007-05-13 18:17:56.795934744 +0200
+@@ -3359,7 +3359,7 @@
+ if (ieee80211_sta_join(vap, lookup.se))
+ while (!vap->iv_nsdone)
+ IEEE80211_RESCHEDULE();
+- if (vap->iv_nsparams.result)
++ if (!vap->iv_nsparams.result)
+ return 0;
+ }
+ }
--- /dev/null
+diff -urN madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c
+--- madwifi-ng-refcount-r2313-20070505.old/ath/if_ath.c 2007-05-13 18:17:56.785936264 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/ath/if_ath.c 2007-05-13 18:17:56.878922128 +0200
+@@ -5640,6 +5640,7 @@
+ u_int phyerr;
+ int processed = 0, early_stop = 0;
+ int rx_limit = dev->quota;
++ int mic_fail = 0;
+
+ /* Let the 802.11 layer know about the new noise floor */
+ ic->ic_channoise = sc->sc_channoise;
+@@ -5734,32 +5735,16 @@
+ }
+ if (ds->ds_rxstat.rs_status & HAL_RXERR_MIC) {
+ sc->sc_stats.ast_rx_badmic++;
+- /*
+- * Do minimal work required to hand off
+- * the 802.11 header for notification.
+- */
+- /* XXX frag's and QoS frames */
+- len = ds->ds_rxstat.rs_datalen;
+- if (len >= sizeof (struct ieee80211_frame)) {
+- bus_dma_sync_single(sc->sc_bdev,
+- bf->bf_skbaddr, len,
+- BUS_DMA_FROMDEVICE);
+-#if 0
+-/* XXX revalidate MIC, lookup ni to find VAP */
+- ieee80211_notify_michael_failure(ic,
+- (struct ieee80211_frame *) skb->data,
+- sc->sc_splitmic ?
+- ds->ds_rxstat.rs_keyix - 32 :
+- ds->ds_rxstat.rs_keyix
+- );
+-#endif
+- }
++ mic_fail = 1;
+ }
+ /*
+ * Reject error frames if we have no vaps that
+ * are operating in monitor mode.
+ */
+- if(sc->sc_nmonvaps == 0) goto rx_next;
++ if ((ds->ds_rxstat.rs_status & ~HAL_RXERR_MIC) &&
++ ((ds->ds_rxstat.rs_status &~ HAL_RXERR_DECRYPT) ||
++ (sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR)))
++ goto rx_next;
+ }
+ rx_accept:
+ /*
+@@ -5843,6 +5828,20 @@
+ ds->ds_rxstat.rs_rssi);
+ }
+
++ /* MIC failure. Drop the packet in any case */
++ if (mic_fail) {
++ ni = ieee80211_find_rxnode(ic,
++ (const struct ieee80211_frame_min *) skb->data);
++ if (ni != NULL) {
++ ieee80211_check_mic(ni, skb);
++ ieee80211_unref_node(&ni);
++ }
++ dev_kfree_skb_any(skb);
++ skb = NULL;
++ mic_fail = 0;
++ goto rx_next;
++ }
++
+ /*
+ * Locate the node for sender, track state, and then
+ * pass the (referenced) node up to the 802.11 layer
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_crypto_ccmp.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_crypto_ccmp.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_crypto_ccmp.c 2007-04-13 07:53:25.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_crypto_ccmp.c 2007-05-13 18:17:56.879921976 +0200
+@@ -78,7 +78,7 @@
+ static int ccmp_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t);
+ static int ccmp_decap(struct ieee80211_key *, struct sk_buff *, int);
+ static int ccmp_enmic(struct ieee80211_key *, struct sk_buff *, int);
+-static int ccmp_demic(struct ieee80211_key *, struct sk_buff *, int);
++static int ccmp_demic(struct ieee80211_key *, struct sk_buff *, int, int);
+
+ static const struct ieee80211_cipher ccmp = {
+ .ic_name = "AES-CCM",
+@@ -298,7 +298,7 @@
+ * Verify and strip MIC from the frame.
+ */
+ static int
+-ccmp_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen)
++ccmp_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen, int force)
+ {
+ return 1;
+ }
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_crypto.h madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_crypto.h
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_crypto.h 2007-04-25 22:29:55.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_crypto.h 2007-05-13 18:17:56.880921824 +0200
+@@ -145,7 +145,7 @@
+ int (*ic_encap)(struct ieee80211_key *, struct sk_buff *, u_int8_t);
+ int (*ic_decap)(struct ieee80211_key *, struct sk_buff *, int);
+ int (*ic_enmic)(struct ieee80211_key *, struct sk_buff *, int);
+- int (*ic_demic)(struct ieee80211_key *, struct sk_buff *, int);
++ int (*ic_demic)(struct ieee80211_key *, struct sk_buff *, int, int);
+ };
+ extern const struct ieee80211_cipher ieee80211_cipher_none;
+
+@@ -163,10 +163,10 @@
+ */
+ static __inline int
+ ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k,
+- struct sk_buff *skb, int hdrlen)
++ struct sk_buff *skb, int hdrlen, int force)
+ {
+ const struct ieee80211_cipher *cip = k->wk_cipher;
+- return (cip->ic_miclen > 0 ? cip->ic_demic(k, skb, hdrlen) : 1);
++ return (cip->ic_miclen > 0 ? cip->ic_demic(k, skb, hdrlen, force) : 1);
+ }
+
+ /*
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_crypto_none.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_crypto_none.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_crypto_none.c 2006-09-20 10:45:13.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_crypto_none.c 2007-05-13 18:17:56.880921824 +0200
+@@ -52,7 +52,7 @@
+ static int none_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t);
+ static int none_decap(struct ieee80211_key *, struct sk_buff *, int);
+ static int none_enmic(struct ieee80211_key *, struct sk_buff *, int);
+-static int none_demic(struct ieee80211_key *, struct sk_buff *, int);
++static int none_demic(struct ieee80211_key *, struct sk_buff *, int, int);
+
+ const struct ieee80211_cipher ieee80211_cipher_none = {
+ .ic_name = "NONE",
+@@ -137,7 +137,7 @@
+ }
+
+ static int
+-none_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen)
++none_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen, int force)
+ {
+ struct ieee80211vap *vap = k->wk_private;
+
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_crypto_tkip.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_crypto_tkip.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_crypto_tkip.c 2007-01-30 04:51:52.000000000 +0100
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_crypto_tkip.c 2007-05-13 18:17:56.880921824 +0200
+@@ -57,7 +57,7 @@
+ static int tkip_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t);
+ static int tkip_enmic(struct ieee80211_key *, struct sk_buff *, int);
+ static int tkip_decap(struct ieee80211_key *, struct sk_buff *, int);
+-static int tkip_demic(struct ieee80211_key *, struct sk_buff *, int);
++static int tkip_demic(struct ieee80211_key *, struct sk_buff *, int, int);
+
+ static const struct ieee80211_cipher tkip = {
+ .ic_name = "TKIP",
+@@ -339,7 +339,7 @@
+ * Verify and strip MIC from the frame.
+ */
+ static int
+-tkip_demic(struct ieee80211_key *k, struct sk_buff *skb0, int hdrlen)
++tkip_demic(struct ieee80211_key *k, struct sk_buff *skb0, int hdrlen, int force)
+ {
+ struct tkip_ctx *ctx = k->wk_private;
+ struct sk_buff *skb;
+@@ -355,7 +355,7 @@
+ }
+ wh = (struct ieee80211_frame *) skb0->data;
+ /* NB: skb left pointing at last in chain */
+- if (k->wk_flags & IEEE80211_KEY_SWMIC) {
++ if ((k->wk_flags & IEEE80211_KEY_SWMIC) || force) {
+ struct ieee80211vap *vap = ctx->tc_vap;
+ u8 mic[IEEE80211_WEP_MICLEN];
+ u8 mic0[IEEE80211_WEP_MICLEN];
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_crypto_wep.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_crypto_wep.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_crypto_wep.c 2006-09-20 10:45:13.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_crypto_wep.c 2007-05-13 18:17:56.881921672 +0200
+@@ -54,7 +54,7 @@
+ static int wep_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t);
+ static int wep_decap(struct ieee80211_key *, struct sk_buff *, int);
+ static int wep_enmic(struct ieee80211_key *, struct sk_buff *, int);
+-static int wep_demic(struct ieee80211_key *, struct sk_buff *, int);
++static int wep_demic(struct ieee80211_key *, struct sk_buff *, int, int);
+
+ static const struct ieee80211_cipher wep = {
+ .ic_name = "WEP",
+@@ -244,7 +244,7 @@
+ * Verify and strip MIC from the frame.
+ */
+ static int
+-wep_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen)
++wep_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen, int force)
+ {
+ return 1;
+ }
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_input.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_input.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_input.c 2007-05-13 18:17:56.786936112 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_input.c 2007-05-13 18:17:56.883921368 +0200
+@@ -654,7 +654,7 @@
+ * Next strip any MSDU crypto bits.
+ */
+ if (key != NULL &&
+- !ieee80211_crypto_demic(vap, key, skb, hdrspace)) {
++ !ieee80211_crypto_demic(vap, key, skb, hdrspace, 0)) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
+ ni->ni_macaddr, "data", "%s", "demic error");
+ IEEE80211_NODE_STAT(ni, rx_demicfail);
+@@ -3734,6 +3734,47 @@
+ }
+ #endif
+
++/*
++ * Process a frame w/ hw detected MIC failure.
++ * The frame will be dropped in any case.
++ */
++void
++ieee80211_check_mic(struct ieee80211_node *ni, struct sk_buff *skb)
++{
++ struct ieee80211vap *vap = ni->ni_vap;
++
++ struct ieee80211_frame *wh;
++ struct ieee80211_key *key;
++ int hdrspace;
++ struct ieee80211com *ic = vap->iv_ic;
++
++ if (skb->len < sizeof(struct ieee80211_frame_min)) {
++ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
++ ni->ni_macaddr, NULL,
++ "too short (1): len %u", skb->len);
++ vap->iv_stats.is_rx_tooshort++;
++ return;
++ }
++
++ wh = (struct ieee80211_frame *)skb->data;
++
++ hdrspace = ieee80211_hdrspace(ic, wh);
++ key = ieee80211_crypto_decap(ni, skb, hdrspace);
++ if (key == NULL) {
++ /* NB: stats+msgs handled in crypto_decap */
++ IEEE80211_NODE_STAT(ni, rx_wepfail);
++ return;
++ }
++
++ if (!ieee80211_crypto_demic(vap, key, skb, hdrspace, 1)) {
++ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
++ ni->ni_macaddr, "data", "%s", "demic error");
++ IEEE80211_NODE_STAT(ni, rx_demicfail);
++ }
++ return;
++}
++EXPORT_SYMBOL(ieee80211_check_mic);
++
+ #ifdef IEEE80211_DEBUG
+ /*
+ * Debugging support.
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_linux.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_linux.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_linux.c 2007-04-25 22:29:55.000000000 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_linux.c 2007-05-13 18:17:56.883921368 +0200
+@@ -309,8 +309,8 @@
+
+ /* TODO: needed parameters: count, keyid, key type, src address, TSC */
+ snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=%s)", tag,
+- keyix, IEEE80211_IS_MULTICAST(wh->i_addr1) ? "broad" : "uni",
+- ether_sprintf(wh->i_addr1));
++ keyix, IEEE80211_IS_MULTICAST(wh->i_addr2) ? "broad" : "uni",
++ ether_sprintf(wh->i_addr2));
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = strlen(buf);
+ wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_proto.h madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_proto.h
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_proto.h 2007-05-13 18:17:56.579967576 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_proto.h 2007-05-13 18:17:56.884921216 +0200
+@@ -91,6 +91,7 @@
+ void ieee80211_set11gbasicrates(struct ieee80211_rateset *, enum ieee80211_phymode);
+ enum ieee80211_phymode ieee80211_get11gbasicrates(struct ieee80211_rateset *);
+ void ieee80211_send_pspoll(struct ieee80211_node *);
++void ieee80211_check_mic(struct ieee80211_node *, struct sk_buff *);
+
+ /*
+ * Return the size of the 802.11 header for a management or data frame.
--- /dev/null
+diff -urN madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_beacon.c madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_beacon.c
+--- madwifi-ng-refcount-r2313-20070505.old/net80211/ieee80211_beacon.c 2007-05-13 18:17:56.687951160 +0200
++++ madwifi-ng-refcount-r2313-20070505.dev/net80211/ieee80211_beacon.c 2007-05-13 18:17:56.971907992 +0200
+@@ -512,7 +512,7 @@
+ vap->iv_flags &= ~IEEE80211_F_XRUPDATE;
+ }
+ #endif
+- if (ic->ic_flags_ext & IEEE80211_FEXT_ERPUPDATE) {
++ if ((ic->ic_flags_ext & IEEE80211_FEXT_ERPUPDATE) && (bo->bo_erp != NULL)) {
+ (void) ieee80211_add_erp(bo->bo_erp, ic);
+ ic->ic_flags_ext &= ~IEEE80211_FEXT_ERPUPDATE;
+ }